mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-25 14:33:52 +01:00
dist: remove old slip driver implementation
This commit is contained in:
parent
1a146f7934
commit
c3abfb3627
1719
dist/tools/linux-border_router/Doxyfile
vendored
1719
dist/tools/linux-border_router/Doxyfile
vendored
File diff suppressed because it is too large
Load Diff
24
dist/tools/linux-border_router/Makefile
vendored
24
dist/tools/linux-border_router/Makefile
vendored
@ -1,24 +0,0 @@
|
||||
CFLAGS = -lrt -pthread -Wall
|
||||
CC = gcc
|
||||
DOCTOOL = doxygen
|
||||
|
||||
TESTING = -D BORDER_TESTING
|
||||
|
||||
all: sixlowdriver doc
|
||||
|
||||
SRC = main.c sixlowdriver.c serial.c control_2xxx.c multiplex.c flowcontrol.c serialnumber.c
|
||||
|
||||
TARGETDIR = ../../bin/linux
|
||||
DOCDIR = ../../Documentation/linux
|
||||
|
||||
sixlowdriver: $(SRC)
|
||||
mkdir -p $(TARGETDIR) &> /dev/null
|
||||
$(CC) $(CFLAGS) -o $(TARGETDIR)/sixlowpan $(SRC)
|
||||
|
||||
sixlowtest: $(SRC) testing.c
|
||||
mkdir -p $(TARGETDIR) &> /dev/null
|
||||
$(CC) $(CFLAGS) $(TESTING) -o $(TARGETDIR)/sixlowpan $(SRC) testing.c
|
||||
|
||||
doc: $(SRC)
|
||||
mkdir -p $(DOCDIR) &> /dev/null
|
||||
$(DOCTOOL) > /dev/null
|
||||
39
dist/tools/linux-border_router/control_2xxx.c
vendored
39
dist/tools/linux-border_router/control_2xxx.c
vendored
@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin.
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
#include "control_2xxx.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "serial.h"
|
||||
|
||||
void hard_reset_to_bootloader(void)
|
||||
{
|
||||
printf("Reset CPU (into bootloader)\r\n");
|
||||
set_rts(1); /* RTS (ttl level) connects to P0.14 */
|
||||
set_dtr(1); /* DTR (ttl level) connects to RST */
|
||||
send_break_signal(); /* or break detect circuit to RST */
|
||||
usleep(75000);
|
||||
set_dtr(0); /* allow the CPU to run */
|
||||
set_baud(baud_rate);
|
||||
set_rts(1); /* set RTS again (as it has been reset by set_baudrate) */
|
||||
usleep(40000);
|
||||
}
|
||||
|
||||
void hard_reset_to_user_code(void)
|
||||
{
|
||||
printf("Reset CPU (into user code)\r\n");
|
||||
set_rts(0); /* RTS (ttl level) connects to P0.14 */
|
||||
set_dtr(1); /* DTR (ttl level) connects to RST */
|
||||
send_break_signal(); /* or break detect circuit to RST */
|
||||
usleep(75000);
|
||||
set_dtr(0); /* allow the CPU to run */
|
||||
usleep(40000);
|
||||
}
|
||||
16
dist/tools/linux-border_router/control_2xxx.h
vendored
16
dist/tools/linux-border_router/control_2xxx.h
vendored
@ -1,16 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin.
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/* token from pseudoterm */
|
||||
#ifndef CONTROL_2XXXX_H
|
||||
#define CONTROL_2XXXX_H
|
||||
|
||||
void hard_reset_to_bootloader(void);
|
||||
void hard_reset_to_user_code(void);
|
||||
|
||||
#endif // ..._H
|
||||
172
dist/tools/linux-border_router/flowcontrol.c
vendored
172
dist/tools/linux-border_router/flowcontrol.c
vendored
@ -1,172 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin.
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef BORDER_TESTING
|
||||
#include "testing.h"
|
||||
#endif
|
||||
|
||||
#include "flowcontrol.h"
|
||||
#include "multiplex.h"
|
||||
|
||||
flowcontrol_stat_t slwin_stat;
|
||||
uint8_t connection_established;
|
||||
|
||||
void *resend_thread_f(void *args)
|
||||
{
|
||||
uint8_t seq_num = *((uint8_t *)args);
|
||||
struct send_slot *slot = &(slwin_stat.send_win[seq_num % BORDER_SWS]);
|
||||
|
||||
while (1) {
|
||||
usleep(BORDER_SL_TIMEOUT);
|
||||
|
||||
if (seq_num == ((border_packet_t *)(slot->frame))->seq_num) {
|
||||
writepacket(slot->frame, slot->frame_len);
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void init_threeway_handshake(const struct in6_addr *addr)
|
||||
{
|
||||
border_syn_packet_t *syn = (border_syn_packet_t *)get_serial_out_buffer(0);
|
||||
syn->empty = 0;
|
||||
syn->type = BORDER_PACKET_CONF_TYPE;
|
||||
syn->next_seq_num = slwin_stat.last_frame + 1;
|
||||
syn->conftype = BORDER_CONF_SYN;
|
||||
syn->next_exp = slwin_stat.next_exp;
|
||||
memcpy(&(syn->addr), addr, 16);
|
||||
|
||||
do {
|
||||
writepacket((uint8_t *)syn, sizeof(border_syn_packet_t));
|
||||
usleep(BORDER_SL_TIMEOUT);
|
||||
}
|
||||
while (!connection_established);
|
||||
}
|
||||
|
||||
void signal_connection_established(void)
|
||||
{
|
||||
connection_established = 1;
|
||||
}
|
||||
|
||||
void flowcontrol_init(const struct in6_addr *addr)
|
||||
{
|
||||
int i;
|
||||
slwin_stat.last_frame = 0xFF;
|
||||
slwin_stat.last_ack = slwin_stat.last_frame;
|
||||
connection_established = 0;
|
||||
|
||||
sem_init(&slwin_stat.send_win_not_full, 0, BORDER_SWS);
|
||||
|
||||
for (i = 0; i < BORDER_SWS; i++) {
|
||||
slwin_stat.send_win[i].frame_len = 0;
|
||||
}
|
||||
|
||||
memset(&slwin_stat.send_win, 0, sizeof(struct send_slot) * BORDER_SWS);
|
||||
|
||||
slwin_stat.next_exp = 0;
|
||||
|
||||
for (i = 0; i < BORDER_RWS; i++) {
|
||||
slwin_stat.recv_win[i].received = 0;
|
||||
slwin_stat.recv_win[i].frame_len = 0;
|
||||
}
|
||||
|
||||
memset(&slwin_stat.recv_win, 0, sizeof(struct recv_slot) * BORDER_RWS);
|
||||
|
||||
init_threeway_handshake(addr);
|
||||
}
|
||||
|
||||
void flowcontrol_destroy(void)
|
||||
{
|
||||
sem_destroy(&slwin_stat.send_win_not_full);
|
||||
}
|
||||
|
||||
static int in_window(uint8_t seq_num, uint8_t min, uint8_t max)
|
||||
{
|
||||
uint8_t pos = seq_num - min;
|
||||
uint8_t maxpos = max - min + 1;
|
||||
return pos < maxpos;
|
||||
}
|
||||
|
||||
void send_ack(uint8_t seq_num)
|
||||
{
|
||||
border_packet_t *packet = (border_packet_t *)get_serial_out_buffer(0);
|
||||
packet->empty = 0;
|
||||
packet->type = BORDER_PACKET_ACK_TYPE;
|
||||
packet->seq_num = seq_num;
|
||||
writepacket((uint8_t *)packet, sizeof(border_packet_t));
|
||||
}
|
||||
|
||||
void flowcontrol_send_over_tty(border_packet_t *packet, int len)
|
||||
{
|
||||
struct send_slot *slot;
|
||||
uint8_t args[] = {packet->seq_num};
|
||||
|
||||
sem_wait(&(slwin_stat.send_win_not_full));
|
||||
packet->seq_num = ++slwin_stat.last_frame;
|
||||
slot = &(slwin_stat.send_win[packet->seq_num % BORDER_SWS]);
|
||||
memcpy(slot->frame, (uint8_t *)packet, len);
|
||||
slot->frame_len = len;
|
||||
pthread_create(&slot->resend_thread, NULL, resend_thread_f, (void *)args);
|
||||
#ifdef BORDER_TESTING
|
||||
testing_start(packet->seq_num);
|
||||
#endif
|
||||
writepacket((uint8_t *)packet, len);
|
||||
}
|
||||
|
||||
void flowcontrol_deliver_from_tty(const border_packet_t *packet, int len)
|
||||
{
|
||||
if (packet->type == BORDER_PACKET_ACK_TYPE) {
|
||||
if (in_window(packet->seq_num, slwin_stat.last_ack + 1, slwin_stat.last_frame)) {
|
||||
do {
|
||||
struct send_slot *slot;
|
||||
slot = &(slwin_stat.send_win[++slwin_stat.last_ack % BORDER_SWS]);
|
||||
#ifdef BORDER_TESTING
|
||||
testing_stop(slwin_stat.last_ack);
|
||||
#endif
|
||||
pthread_cancel(slot->resend_thread);
|
||||
memset(&slot->frame, 0, BUFFER_SIZE);
|
||||
slot->frame_len = 0;
|
||||
sem_post(&slwin_stat.send_win_not_full);
|
||||
}
|
||||
while (slwin_stat.last_ack != packet->seq_num);
|
||||
}
|
||||
}
|
||||
else {
|
||||
struct recv_slot *slot;
|
||||
|
||||
slot = &slwin_stat.recv_win[packet->seq_num % BORDER_RWS];
|
||||
|
||||
if (!in_window(packet->seq_num,
|
||||
slwin_stat.next_exp,
|
||||
slwin_stat.next_exp + BORDER_RWS - 1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(slot->frame, (uint8_t *)packet, len);
|
||||
slot->received = 1;
|
||||
|
||||
if (packet->seq_num == slwin_stat.next_exp) {
|
||||
while (slot->received) {
|
||||
demultiplex((border_packet_t *)slot->frame, slot->frame_len);
|
||||
memset(&slot->frame, 0, BUFFER_SIZE);
|
||||
slot->received = 0;
|
||||
slot = &slwin_stat.recv_win[++slwin_stat.next_exp % BORDER_RWS];
|
||||
}
|
||||
}
|
||||
|
||||
send_ack(slwin_stat.next_exp - 1);
|
||||
}
|
||||
}
|
||||
138
dist/tools/linux-border_router/flowcontrol.h
vendored
138
dist/tools/linux-border_router/flowcontrol.h
vendored
@ -1,138 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin.
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||
* @brief Public declarations for the flow control jobs via the
|
||||
* serial interface for the 6LoWPAN Border Router driver.
|
||||
*/
|
||||
|
||||
#ifndef FLOWCONTROL_H
|
||||
#define FLOWCONTROL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "multiplex.h"
|
||||
|
||||
/* packet types for flowcontrol */
|
||||
#define BORDER_PACKET_ACK_TYPE 1 ///< Packet type for acknowledgement packets (for flow control).
|
||||
|
||||
/* configuration types for flowcontrol */
|
||||
#define BORDER_CONF_SYN 0 ///< Configuration packet type for SYN-Packets.
|
||||
#define BORDER_CONF_SYNACK 1 ///< Configuration packet type for SYN/ACK-Packets.
|
||||
|
||||
#define BORDER_SWS 1 ///< Sending window size for flow control.
|
||||
#define BORDER_RWS 1 ///< Receiving window size for flow control.
|
||||
#define BORDER_SL_TIMEOUT 500000 ///< Timeout time (in µsec) for flow control.
|
||||
|
||||
/**
|
||||
* @brief State of the sliding window algorithm, used for flow control
|
||||
* @see "Computernetze -- Eine systemorientierte Einführung",
|
||||
* L.L. Peterson, B.S. Davie, dpunkt-lehrbuch, 2008
|
||||
*/
|
||||
typedef struct flowcontrol_stat_t {
|
||||
/* Sender state */
|
||||
uint8_t last_ack; ///< Sequence number of the last received acknowledgement.
|
||||
uint8_t last_frame; ///< Sequence number of the last send frame.
|
||||
/**
|
||||
* @brief Semaphore, that locks if sending window is full.
|
||||
*/
|
||||
sem_t send_win_not_full;
|
||||
/**
|
||||
* @brief a slot in the sending window
|
||||
*/
|
||||
struct send_slot {
|
||||
pthread_t resend_thread; ///< Thread that handles the resending of this slot's frame (if needed).
|
||||
uint8_t frame[BUFFER_SIZE]; ///< This slot's frame.
|
||||
size_t frame_len; ///< The length of this slot's frame.
|
||||
} send_win[BORDER_SWS]; ///< The sending window.
|
||||
|
||||
/* Receiver state */
|
||||
uint8_t next_exp; ///< The next expected sequence number to be received.
|
||||
/**
|
||||
* @brief a receiving in the sending window
|
||||
*/
|
||||
struct recv_slot {
|
||||
int8_t received; ///< 0 if this slot is empty, != 0 if this slot contains a received frame.
|
||||
uint8_t frame[BUFFER_SIZE]; ///< This slot's frame
|
||||
size_t frame_len; ///< The length of this slot's frame.
|
||||
} recv_win[BORDER_RWS]; ///< The receiving window.
|
||||
} flowcontrol_stat_t;
|
||||
|
||||
/**
|
||||
* @brief Describes a SYN packet for connection establishment of
|
||||
* the serial line.
|
||||
* @extends border_conf_header_t
|
||||
*/
|
||||
typedef struct __attribute__((packed)) border_syn_packet_t {
|
||||
uint8_t empty;
|
||||
uint8_t type;
|
||||
/**
|
||||
* @brief Next sequence number
|
||||
*
|
||||
* Communicates the next local sequence number to be send to the
|
||||
* MSB-A2 (for flow control).
|
||||
*
|
||||
* This replaces @ref border_conf_header_t::seq_num of normal
|
||||
* configuration packets.
|
||||
*/
|
||||
uint8_t next_seq_num;
|
||||
uint8_t conftype;
|
||||
/**
|
||||
* @brief Next expected sequence number
|
||||
*
|
||||
* Communicates to the MSB-A2 which sequence number the driver
|
||||
* expects next.
|
||||
*/
|
||||
uint8_t next_exp;
|
||||
struct in6_addr addr; ///< IPv6-Address of this border router.
|
||||
} border_syn_packet_t;
|
||||
|
||||
/**
|
||||
* @brief Sets the flow control algorithm to the initial state.
|
||||
* @param[in] addr The IP address that should be communicated to the
|
||||
* LoWPAN interface.
|
||||
*/
|
||||
void flowcontrol_init(const struct in6_addr *addr);
|
||||
|
||||
/**
|
||||
* @brief Destroys the state struct for the flow control algorithm.
|
||||
*/
|
||||
void flowcontrol_destroy(void);
|
||||
|
||||
/**
|
||||
* @brief Singals the flow control algorith, that an connection
|
||||
* was established (because a SYNACK packet was received).
|
||||
*/
|
||||
void signal_connection_established(void);
|
||||
|
||||
/**
|
||||
* @brief Sends a packet via the serial interface.
|
||||
* @param[in,out] packet The packet that is to be send via the
|
||||
* serial interface. The function sets the
|
||||
* sequence number of the packet for flow
|
||||
* control.
|
||||
* @param[in] len Length of the packet.
|
||||
*/
|
||||
void flowcontrol_send_over_tty(border_packet_t *packet, int len);
|
||||
|
||||
/**
|
||||
* @brief Delivers all actions that should be done by the sliding
|
||||
* window on receiving a packet.
|
||||
* @param[in] packet The packet the was received via the serial
|
||||
* interface.
|
||||
* @param[in] len Length of the packet.
|
||||
*/
|
||||
void flowcontrol_deliver_from_tty(const border_packet_t *packet, int len);
|
||||
|
||||
#endif /* FLOWCONTROL_H*/
|
||||
55
dist/tools/linux-border_router/main.c
vendored
55
dist/tools/linux-border_router/main.c
vendored
@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin.
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "sixlowdriver.h"
|
||||
|
||||
#ifdef BORDER_TESTING
|
||||
#include "testing.h"
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc < 4) {
|
||||
fprintf(stderr, "Usage: %s r_addr if_name tty_dev\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char addr[IPV6_ADDR_LEN];
|
||||
sprintf(addr, "abcd::1034:00FF:FE00:%s/64", argv[1]);
|
||||
char if_name[IF_NAME_LEN];
|
||||
strncpy(if_name, argv[2], IF_NAME_LEN);
|
||||
char tty_dev[DEV_LEN];
|
||||
strncpy(tty_dev, argv[3], DEV_LEN);
|
||||
|
||||
if (border_initialize(if_name, addr, tty_dev) == 0) {
|
||||
#ifdef BORDER_TESTING
|
||||
char ping_addr[IPV6_ADDR_LEN];
|
||||
float interval;
|
||||
|
||||
if (argc < 9) {
|
||||
fprintf(stderr, "Usage: %s r_addr if_name tty_dev ping_id result_dir skeleton_file ping_count interval\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sscanf(argv[8], "%20f", &interval);
|
||||
sprintf(ping_addr, "abcd::%s/64", argv[4]);
|
||||
|
||||
start_test(ping_addr, argv[5], argv[6], atoi(argv[7]), interval);
|
||||
#else
|
||||
|
||||
while (1);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
287
dist/tools/linux-border_router/multiplex.c
vendored
287
dist/tools/linux-border_router/multiplex.c
vendored
@ -1,287 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin.
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "flowcontrol.h"
|
||||
#include "multiplex.h"
|
||||
#include "serial.h"
|
||||
#include "sixlowdriver.h"
|
||||
|
||||
#define END 0xC0
|
||||
#define ESC 0xDB
|
||||
#define END_ESC 0xDC
|
||||
#define ESC_ESC 0xDD
|
||||
|
||||
uint8_t serial_out_buf[BUFFER_SIZE];
|
||||
uint8_t serial_in_buf[BUFFER_SIZE];
|
||||
|
||||
uint8_t *get_serial_out_buffer(int offset)
|
||||
{
|
||||
if (offset > BUFFER_SIZE) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &(serial_out_buf[offset]);
|
||||
}
|
||||
|
||||
uint8_t *get_serial_in_buffer(int offset)
|
||||
{
|
||||
if (offset > BUFFER_SIZE) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &(serial_in_buf[offset]);
|
||||
}
|
||||
|
||||
int init_multiplex(const char *tty_dev)
|
||||
{
|
||||
return open_serial_port(tty_dev);
|
||||
}
|
||||
|
||||
uint8_t serial_read_byte()
|
||||
{
|
||||
unsigned char c;
|
||||
|
||||
read_serial_port(&c, 1);
|
||||
|
||||
return (uint8_t)c;
|
||||
}
|
||||
|
||||
int readpacket(uint8_t *packet_buf, size_t size)
|
||||
{
|
||||
uint8_t *line_buf_ptr = packet_buf;
|
||||
uint8_t esc = 0;
|
||||
uint8_t translate = 1;
|
||||
|
||||
while ((line_buf_ptr - packet_buf) < size - 1) {
|
||||
uint8_t byte = serial_read_byte();
|
||||
|
||||
if (translate && byte == END) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (line_buf_ptr == packet_buf && byte != 0) {
|
||||
translate = 0;
|
||||
}
|
||||
|
||||
if (line_buf_ptr > packet_buf && !translate && byte == '\n') {
|
||||
*line_buf_ptr++ = '\0';
|
||||
return line_buf_ptr - packet_buf;
|
||||
}
|
||||
|
||||
if (translate) {
|
||||
if (esc) {
|
||||
esc = 0;
|
||||
|
||||
switch (byte) {
|
||||
case (END_ESC): {
|
||||
*line_buf_ptr++ = END;
|
||||
continue;
|
||||
}
|
||||
|
||||
case (ESC_ESC): {
|
||||
*line_buf_ptr++ = ESC;
|
||||
continue;
|
||||
}
|
||||
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (byte == ESC) {
|
||||
esc = 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
*line_buf_ptr++ = byte;
|
||||
}
|
||||
|
||||
return (line_buf_ptr - packet_buf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int writepacket(uint8_t *packet_buf, size_t size)
|
||||
{
|
||||
uint8_t packet_tmp[2 * BUFFER_SIZE];
|
||||
uint8_t *byte_ptr = packet_buf;
|
||||
uint8_t *tmp_ptr = packet_tmp;
|
||||
|
||||
if (2 * size + 1 > BUFFER_SIZE) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
while ((byte_ptr - packet_buf) < size) {
|
||||
switch (*byte_ptr) {
|
||||
case (END): {
|
||||
*byte_ptr = END_ESC;
|
||||
*tmp_ptr = ESC;
|
||||
tmp_ptr++;
|
||||
break;
|
||||
}
|
||||
|
||||
case (ESC): {
|
||||
*byte_ptr = ESC_ESC;
|
||||
*tmp_ptr = ESC;
|
||||
tmp_ptr++;
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*tmp_ptr = *byte_ptr;
|
||||
byte_ptr++;
|
||||
tmp_ptr++;
|
||||
}
|
||||
|
||||
*tmp_ptr++ = END;
|
||||
write_serial_port(packet_tmp, tmp_ptr - packet_tmp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void demultiplex(const border_packet_t *packet, int len)
|
||||
{
|
||||
switch (packet->type) {
|
||||
case (BORDER_PACKET_RAW_TYPE): {
|
||||
printf("\033[00;33m[via serial interface] %s\033[00m\n",
|
||||
((unsigned char *)packet) + sizeof(border_packet_t)
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case (BORDER_PACKET_L3_TYPE): {
|
||||
border_l3_header_t *l3_header_buf = (border_l3_header_t *)packet;
|
||||
|
||||
switch (l3_header_buf->ethertype) {
|
||||
case (ETHERTYPE_IPV6): {
|
||||
printf("INFO: IPv6-Packet %d received\n", l3_header_buf->seq_num);
|
||||
struct ip6_hdr *ip6_buf = (struct ip6_hdr *)(((unsigned char *)packet) + sizeof(border_l3_header_t));
|
||||
border_send_ipv6_over_tun(get_tun_fd(), ip6_buf);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
printf("INFO: Unknown ethertype %04x for packet %d\n", l3_header_buf->ethertype, l3_header_buf->seq_num);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case (BORDER_PACKET_CONF_TYPE): {
|
||||
border_conf_header_t *conf_header_buf = (border_conf_header_t *)packet;
|
||||
|
||||
switch (conf_header_buf->conftype) {
|
||||
case (BORDER_CONF_SYNACK): {
|
||||
printf("INFO: SYNACK-Packet %d received\n", conf_header_buf->seq_num);
|
||||
signal_connection_established();
|
||||
break;
|
||||
}
|
||||
|
||||
case (BORDER_CONF_CONTEXT): {
|
||||
printf("INFO: Context packet (%d) received, "
|
||||
"but nothing is implemented yet for this case.\n",
|
||||
conf_header_buf->seq_num);
|
||||
break;
|
||||
}
|
||||
|
||||
case (BORDER_CONF_IPADDR): {
|
||||
char str_addr[IPV6_ADDR_LEN];
|
||||
border_addr_packet_t *addr_packet = (border_addr_packet_t *)packet;
|
||||
|
||||
printf("INFO: Address packet (%d) received.\n",
|
||||
conf_header_buf->seq_num);
|
||||
inet_ntop(AF_INET6, &addr_packet->addr, str_addr, IPV6_ADDR_LEN);
|
||||
tun_add_addr(str_addr);
|
||||
}
|
||||
|
||||
default:
|
||||
printf("INFO: Unknown conftype %02x for packet %d\n",
|
||||
conf_header_buf->conftype,
|
||||
conf_header_buf->seq_num);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
printf("INFO: Unknown border packet type %02x for packet %d\n", packet->type, packet->seq_num);
|
||||
//print_packet_hex((unsigned char *)packet,len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void multiplex_send_context_over_tty(const border_context_t *context)
|
||||
{
|
||||
border_context_packet_t *con_packet = (border_context_packet_t *)get_serial_out_buffer(0);
|
||||
|
||||
con_packet->empty = 0;
|
||||
con_packet->type = BORDER_PACKET_CONF_TYPE;
|
||||
con_packet->conftype = BORDER_CONF_CONTEXT;
|
||||
memcpy(
|
||||
&con_packet->context,
|
||||
context,
|
||||
sizeof(border_context_t)
|
||||
);
|
||||
|
||||
flowcontrol_send_over_tty(
|
||||
(border_packet_t *) con_packet,
|
||||
sizeof(border_context_packet_t)
|
||||
);
|
||||
}
|
||||
|
||||
void multiplex_send_addr_over_tty(struct in6_addr *addr)
|
||||
{
|
||||
border_addr_packet_t *packet = (border_addr_packet_t *)get_serial_out_buffer(0);
|
||||
|
||||
packet->empty = 0;
|
||||
packet->type = BORDER_PACKET_CONF_TYPE;
|
||||
packet->conftype = BORDER_CONF_IPADDR;
|
||||
memcpy(
|
||||
&packet->addr,
|
||||
addr,
|
||||
sizeof(struct in6_addr)
|
||||
);
|
||||
|
||||
flowcontrol_send_over_tty(
|
||||
(border_packet_t *) packet,
|
||||
sizeof(border_addr_packet_t)
|
||||
);
|
||||
}
|
||||
|
||||
void multiplex_send_ipv6_over_tty(const struct ip6_hdr *packet)
|
||||
{
|
||||
border_l3_header_t *l3_hdr = (border_l3_header_t *)get_serial_out_buffer(0);
|
||||
size_t packet_size = sizeof(struct ip6_hdr) + packet->ip6_plen;
|
||||
|
||||
l3_hdr->empty = 0;
|
||||
l3_hdr->type = BORDER_PACKET_L3_TYPE;
|
||||
l3_hdr->ethertype = ETHERTYPE_IPV6;
|
||||
memcpy(
|
||||
get_serial_out_buffer(0) + sizeof(border_l3_header_t),
|
||||
packet,
|
||||
packet_size
|
||||
);
|
||||
|
||||
flowcontrol_send_over_tty(
|
||||
(border_packet_t *) l3_hdr,
|
||||
sizeof(border_l3_header_t) + packet_size
|
||||
);
|
||||
}
|
||||
202
dist/tools/linux-border_router/multiplex.h
vendored
202
dist/tools/linux-border_router/multiplex.h
vendored
@ -1,202 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin.
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||
* @brief Public declarations for the multiplexing jobs via the
|
||||
* serial interface for the 6LoWPAN Border Router driver.
|
||||
*/
|
||||
#ifndef MULTIPLEX_H
|
||||
#define MULTIPLEX_H
|
||||
|
||||
#include <netinet/ip6.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sixlowdriver.h"
|
||||
|
||||
#define MTU 1280 ///< MTU for IPv6 packets on serial interface.
|
||||
|
||||
/* packet types of tty-packets */
|
||||
#define BORDER_PACKET_RAW_TYPE 0 ///< Packet type for raw packets.
|
||||
#define BORDER_PACKET_CONF_TYPE 2 ///< Packet type for configuration packets.
|
||||
#define BORDER_PACKET_L3_TYPE 3 ///< Packet type for layer 3 packets.
|
||||
|
||||
/* configuration types */
|
||||
#define BORDER_CONF_CONTEXT 2 ///< Configuration packet type for context updates.
|
||||
#define BORDER_CONF_IPADDR 3 ///< Configuration packet type for IP address updates.
|
||||
|
||||
/* ethertypes for L3 packets */
|
||||
#define ETHERTYPE_IPV6 0x86DD ///< Ethertype for IPv6-Datagrams.
|
||||
|
||||
/**
|
||||
* @brief Describes packets for transmission via serial interface.
|
||||
*/
|
||||
typedef struct __attribute__((packed)) border_packet_t {
|
||||
/**
|
||||
* @brief Reserved byte.
|
||||
*
|
||||
* Must be always 0 to distinguish packets from MSB-A2
|
||||
* stdout/stdin/stderr.
|
||||
*/
|
||||
uint8_t empty;
|
||||
uint8_t type; ///< Type of the packet.
|
||||
uint8_t seq_num; ///< Sequence number of the packet (for flow control).
|
||||
} border_packet_t;
|
||||
|
||||
/**
|
||||
* @brief Describes a layer 3 packet header for transmission via
|
||||
* serial interface.
|
||||
* @extends border_packet_t
|
||||
*/
|
||||
typedef struct __attribute__((packed)) border_l3_header_t {
|
||||
uint8_t empty;
|
||||
uint8_t type;
|
||||
uint8_t seq_num;
|
||||
uint16_t ethertype; ///< Ethertype of the layer 3 packet.
|
||||
} border_l3_header_t;
|
||||
|
||||
/**
|
||||
* @brief Describes a configuration packet header for transmission via
|
||||
* serial interface.
|
||||
* @extends border_packet_t
|
||||
*/
|
||||
typedef struct __attribute__((packed)) border_conf_header_t {
|
||||
uint8_t empty;
|
||||
uint8_t type;
|
||||
uint8_t seq_num;
|
||||
uint8_t conftype; ///< Configuration packet type of this packet.
|
||||
} border_conf_header_t;
|
||||
|
||||
/**
|
||||
* @brief Describes an address configuration packet.
|
||||
* @extends border_conf_header_t
|
||||
*
|
||||
* This packet type enables the driver to add new IPv6 addresses to
|
||||
* the border router.
|
||||
*/
|
||||
typedef struct __attribute__((packed)) border_addr_packet_t {
|
||||
uint8_t empty;
|
||||
uint8_t type;
|
||||
uint8_t seq_num;
|
||||
uint8_t conftype;
|
||||
/**
|
||||
* @brief Version for this IP address (send with the ABRO for PIs,
|
||||
* s. draft-ietf-6lowpan-nd-17).
|
||||
*/
|
||||
uint16_t version;
|
||||
struct in6_addr addr; ///< New IPv6-Address to be added to this border router.
|
||||
} border_addr_packet_t;
|
||||
|
||||
/**
|
||||
* @brief Describes a context configuration packet.
|
||||
* @extends border_conf_header_t
|
||||
*
|
||||
* This packet type enables the driver to manipulate Context Informations
|
||||
* in the LoWPAN.
|
||||
*/
|
||||
typedef struct __attribute__((packed)) border_context_packet_t {
|
||||
uint8_t empty;
|
||||
uint8_t type;
|
||||
uint8_t seq_num;
|
||||
uint8_t conftype;
|
||||
border_context_t context; ///< Describes the context to be manipulated.
|
||||
} border_context_packet_t;
|
||||
|
||||
/**
|
||||
* @brief Size of all packet buffers in this driver.
|
||||
*
|
||||
* @ref border_l3_header_t was since packets of this type may be the
|
||||
* longest (with payload).
|
||||
*/
|
||||
#define BUFFER_SIZE sizeof (border_l3_header_t) + MTU
|
||||
|
||||
/**
|
||||
* @brief Initializes multiplexer
|
||||
* @param[in] tty_dev Filename of the serial interface over which the
|
||||
* multiplexer should multiplex.
|
||||
* @return 0 if successfull, -1 if not.
|
||||
*/
|
||||
int init_multiplex(const char *tty_dev);
|
||||
|
||||
/**
|
||||
* @brief Returns a pointer to a cell in the buffer for the output
|
||||
* data, that shall be send via the serial interface.
|
||||
* @param[in] offset The offset from the start of the buffer.
|
||||
* @return Pointer to a cell in the buffer for the output
|
||||
* data. The size of the buffer is then
|
||||
* \ref BUFFER_SIZE - <em>offset</em>.
|
||||
*/
|
||||
uint8_t *get_serial_out_buffer(int offset);
|
||||
|
||||
/**
|
||||
* @brief Returns a pointer to a cell in the buffer for the input
|
||||
* data, that was received via the serial interface.
|
||||
* @param[in] offset The offset from the start of the buffer.
|
||||
* @return Pointer to a cell in the buffer for the input
|
||||
* data. The size of the buffer is then
|
||||
* \ref BUFFER_SIZE - <em>offset</em>.
|
||||
*/
|
||||
uint8_t *get_serial_in_buffer(int offset);
|
||||
|
||||
/**
|
||||
* @brief Demultiplexes a packet, that was received via the serial
|
||||
* interface.
|
||||
* @param[in] packet Packet, that should be demultiplexed.
|
||||
* @param[in] len Length of the packet, that should be
|
||||
* demultiplexed.
|
||||
*/
|
||||
void demultiplex(const border_packet_t *packet, int len);
|
||||
|
||||
/**
|
||||
* @brief Sends an IPv6 datagram via the serial interface.
|
||||
* @param[in] packet The IPv6 datagram that is to be send via the
|
||||
* serial interface and starts with an IPv6 header.
|
||||
*
|
||||
* The function uses the payload length field of the IPv6 Header to
|
||||
* determine the length of the overall packet. The payload bytes
|
||||
* <em>must</em> follow the header in memory.
|
||||
*/
|
||||
void multiplex_send_ipv6_over_tty(const struct ip6_hdr *packet);
|
||||
|
||||
/**
|
||||
* @brief Sends context information via the serial interface.
|
||||
* @param[in] context The context information that is to be send via
|
||||
* the serial interface.
|
||||
*/
|
||||
void multiplex_send_context_over_tty(const border_context_t *context);
|
||||
|
||||
/**
|
||||
* @brief Sends new IPv6 address via the serial interface.
|
||||
* @param[in] addr The new address that is to be send via
|
||||
* the serial interface.
|
||||
*/
|
||||
void multiplex_send_addr_over_tty(struct in6_addr *addr);
|
||||
|
||||
/**
|
||||
* @brief Reads a packet up to a length of <em>size</em> bytes from
|
||||
* the serial interface and saves it to <em>packet_buf</em>.
|
||||
* @param[out] packet_buf The buffer the read packet should be written
|
||||
* into.
|
||||
* @param[in] size The maximum number of bytes to be read.
|
||||
* @return The number of bytes read.
|
||||
*/
|
||||
int readpacket(uint8_t *packet_buf, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Writes a packet up to a length of <em>size</em> bytes from
|
||||
* <em>packet_buf</em> to the serial interface.
|
||||
* @param[in] packet_buf The buffer from which the packet should be
|
||||
* written.
|
||||
* @param[in] size The maximum number of bytes to be written.
|
||||
* @return The number of bytes written.
|
||||
*/
|
||||
int writepacket(uint8_t *packet_buf, size_t size);
|
||||
|
||||
|
||||
#endif /* SIXLOWBORDER_H*/
|
||||
426
dist/tools/linux-border_router/serial.c
vendored
426
dist/tools/linux-border_router/serial.c
vendored
@ -1,426 +0,0 @@
|
||||
/*
|
||||
* LPC 2000 Loader, http://www.pjrc.com/arm/lpc2k_pgm
|
||||
* Copyright (c) 2004, PJRC.COM, LLC, <paul@pjrc.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* If this code fails to build, please provide at least the following
|
||||
* information when requesting (free) technical support.
|
||||
*
|
||||
* 1: Complete copy of all messages during the build.
|
||||
* 2: Output of "gtk-config --version"
|
||||
* 3: Output of "gtk-config --libs"
|
||||
* 4: Output of "gtk-config --cflags"
|
||||
* 5: Output of "uname -a"
|
||||
* 6: Version of GTK installed... eg, type: ls -l /lib/libgtk*
|
||||
* 7: Other info... which linux distribution, version, other software
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
#include <sys/ioctl.h>
|
||||
#ifdef LINUX
|
||||
#include <linux/serial.h>
|
||||
#endif
|
||||
|
||||
#include "serial.h"
|
||||
|
||||
int port_fd = -1;
|
||||
|
||||
static tcflag_t baud_name_to_flags(const char *baud_name);
|
||||
static void report_open_error(const char *filename, int err);
|
||||
|
||||
char *baud_rate = "115200";
|
||||
|
||||
int open_serial_port(const char *port_name)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (port_fd >= 0) {
|
||||
close(port_fd);
|
||||
}
|
||||
|
||||
port_fd = open(port_name, O_RDWR);
|
||||
|
||||
if (port_fd < 0) {
|
||||
report_open_error(port_name, errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = set_baud(baud_rate);
|
||||
|
||||
if (r == 0) {
|
||||
printf("Port \"%s\" opened at %s baud\r\n",
|
||||
port_name, baud_rate);
|
||||
}
|
||||
else {
|
||||
printf("Port \"%s\" opened, unable to set baud to %s\r\n",
|
||||
port_name, baud_rate);
|
||||
}
|
||||
|
||||
#ifdef LINUX
|
||||
{
|
||||
struct serial_struct kernel_serial_settings;
|
||||
/* attempt to set low latency mode, but don't worry if we can't */
|
||||
r = ioctl(port_fd, TIOCGSERIAL, &kernel_serial_settings);
|
||||
|
||||
if (r < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
kernel_serial_settings.flags |= ASYNC_LOW_LATENCY;
|
||||
ioctl(port_fd, TIOCSSERIAL, &kernel_serial_settings);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* if the port can't be opened, try to print as much info as
|
||||
* possible, so the problem can be resolved (usually permissions)
|
||||
*/
|
||||
static void report_open_error(const char *filename, int err)
|
||||
{
|
||||
struct stat info;
|
||||
uid_t my_uid;
|
||||
gid_t my_gid;
|
||||
char my_uname[64], my_gname[64], file_uname[64], file_gname[64];
|
||||
struct passwd *p;
|
||||
struct group *g;
|
||||
mode_t perm;
|
||||
int r;
|
||||
|
||||
printf("\r\n");
|
||||
printf("Unable to open \"%s\"\r\n", filename);
|
||||
|
||||
if (err == EACCES) {
|
||||
printf("You don't have permission to access %s\r\n", filename);
|
||||
}
|
||||
|
||||
r = stat(filename, &info);
|
||||
|
||||
if (r < 0) {
|
||||
if (errno == ENOENT) {
|
||||
printf("file %s does not exist\r\n", filename);
|
||||
}
|
||||
else if (errno == ELOOP) {
|
||||
printf("too many symbolic links\r\n");
|
||||
}
|
||||
else if (errno == EACCES) {
|
||||
printf("permission denied to get file status\r\n");
|
||||
}
|
||||
else {
|
||||
printf("Unable to get file status, err%d\r\n", errno);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
my_uid = getuid();
|
||||
my_gid = getgid();
|
||||
|
||||
p = getpwuid(my_uid);
|
||||
|
||||
if (p) {
|
||||
snprintf(my_uname, sizeof(my_uname),
|
||||
"\"%s\" (gid=%d)", p->pw_name, (int)my_uid);
|
||||
}
|
||||
else {
|
||||
snprintf(my_uname, sizeof(my_uname),
|
||||
"(gid=%d)", (int)my_uid);
|
||||
}
|
||||
|
||||
p = getpwuid(info.st_uid);
|
||||
|
||||
if (p) {
|
||||
snprintf(file_uname, sizeof(file_uname),
|
||||
"\"%s\" (uid=%d)", p->pw_name, (int)info.st_uid);
|
||||
}
|
||||
else {
|
||||
snprintf(file_uname, sizeof(file_uname),
|
||||
"(uid=%d)", (int)info.st_uid);
|
||||
}
|
||||
|
||||
g = getgrgid(my_gid);
|
||||
|
||||
if (g) {
|
||||
snprintf(my_gname, sizeof(my_gname),
|
||||
"\"%s\" (gid=%d)", g->gr_name, (int)my_gid);
|
||||
}
|
||||
else {
|
||||
snprintf(my_gname, sizeof(my_gname),
|
||||
"(gid=%d)", (int)my_gid);
|
||||
}
|
||||
|
||||
g = getgrgid(info.st_gid);
|
||||
|
||||
if (g) {
|
||||
snprintf(file_gname, sizeof(file_gname),
|
||||
"\"%s\" (uid=%d)", g->gr_name, (int)info.st_gid);
|
||||
}
|
||||
else {
|
||||
snprintf(file_gname, sizeof(file_gname),
|
||||
"(uid=%d)", (int)info.st_gid);
|
||||
}
|
||||
|
||||
/* printf("%s is owned by: user %s, group %s\r\n",
|
||||
filename, file_uname, file_gname); */
|
||||
|
||||
perm = info.st_mode;
|
||||
|
||||
if ((perm & S_IROTH) && (perm & S_IWOTH)) {
|
||||
printf("%s has read/write permission for everybody\r\n",
|
||||
filename);
|
||||
}
|
||||
else {
|
||||
printf("%s is not read/write for everybody, so\r\n", filename);
|
||||
printf(" you must match either user or group permission\r\n");
|
||||
int perm_ok = 0;
|
||||
|
||||
if ((perm & S_IRUSR) && (perm & S_IWUSR)) {
|
||||
printf("%s has read/write permission for user %s\r\n",
|
||||
filename, file_uname);
|
||||
perm_ok = 1;
|
||||
}
|
||||
|
||||
if ((perm & S_IRGRP) && (perm & S_IWGRP)) {
|
||||
printf("%s has read/write permission for group %s\r\n",
|
||||
filename, file_gname);
|
||||
perm_ok = 1;
|
||||
}
|
||||
|
||||
if (perm_ok == 0) {
|
||||
printf("%s does not read/write permission for user or group!\r\n",
|
||||
filename);
|
||||
}
|
||||
else {
|
||||
printf("Your access privs: user %s, group %s\r\n",
|
||||
my_uname, my_gname);
|
||||
}
|
||||
}
|
||||
|
||||
printf("\r\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
int write_serial_port(const void *buf, int num)
|
||||
{
|
||||
return(write(port_fd, buf, num));
|
||||
}
|
||||
|
||||
|
||||
void input_flush_serial_port(void)
|
||||
{
|
||||
tcflush(port_fd, TCIFLUSH);
|
||||
}
|
||||
|
||||
|
||||
int read_serial_port_nb(unsigned char *buf, int bufsize)
|
||||
{
|
||||
int num, flags;
|
||||
|
||||
flags = fcntl(port_fd, F_GETFL);
|
||||
fcntl(port_fd, F_SETFL, flags | O_NONBLOCK);
|
||||
num = read(port_fd, buf, bufsize);
|
||||
fcntl(port_fd, F_SETFL, flags);
|
||||
return num;
|
||||
}
|
||||
|
||||
int read_serial_port(unsigned char *buf, int bufsize)
|
||||
{
|
||||
int num;
|
||||
|
||||
num = read(port_fd, buf, bufsize);
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
|
||||
void send_break_signal(void)
|
||||
{
|
||||
tcsendbreak(port_fd, 0);
|
||||
}
|
||||
|
||||
|
||||
void close_serial_port(void)
|
||||
{
|
||||
if (port_fd >= 0) {
|
||||
close(port_fd);
|
||||
port_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
tcflag_t baud_name_to_flags(const char *baud_name)
|
||||
{
|
||||
if (strcmp(baud_name, "230400") == 0) {
|
||||
return B230400;
|
||||
}
|
||||
|
||||
if (strcmp(baud_name, "115200") == 0) {
|
||||
return B115200;
|
||||
}
|
||||
|
||||
if (strcmp(baud_name, "57600") == 0) {
|
||||
return B57600;
|
||||
}
|
||||
|
||||
if (strcmp(baud_name, "38400") == 0) {
|
||||
return B38400;
|
||||
}
|
||||
|
||||
if (strcmp(baud_name, "19200") == 0) {
|
||||
return B19200;
|
||||
}
|
||||
|
||||
if (strcmp(baud_name, "9600") == 0) {
|
||||
return B9600;
|
||||
}
|
||||
|
||||
if (strcmp(baud_name, "4800") == 0) {
|
||||
return B4800;
|
||||
}
|
||||
|
||||
if (strcmp(baud_name, "2400") == 0) {
|
||||
return B2400;
|
||||
}
|
||||
|
||||
if (strcmp(baud_name, "1200") == 0) {
|
||||
return B1200;
|
||||
}
|
||||
|
||||
if (strcmp(baud_name, "300") == 0) {
|
||||
return B300;
|
||||
}
|
||||
|
||||
return B0;
|
||||
}
|
||||
|
||||
|
||||
int set_baud(const char *baud_name)
|
||||
{
|
||||
struct termios port_setting;
|
||||
tcflag_t baud;
|
||||
int r;
|
||||
|
||||
if (port_fd < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
baud = baud_name_to_flags(baud_name);
|
||||
|
||||
if (baud == B0) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
r = tcgetattr(port_fd, &port_setting);
|
||||
|
||||
if (r != 0) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
port_setting.c_iflag = IGNBRK | IGNPAR;
|
||||
port_setting.c_cflag = baud | CS8 | CREAD | HUPCL | CLOCAL;
|
||||
port_setting.c_oflag = 0;
|
||||
port_setting.c_lflag = 0;
|
||||
r = tcsetattr(port_fd, TCSAFLUSH, &port_setting);
|
||||
|
||||
if (r != 0) {
|
||||
return -4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Normally this should never be used... except to pass the port
|
||||
// file descriptor to the GTK event monitoring loop. All other
|
||||
// use of the serial port is supposed to happen in the file.
|
||||
int serial_port_fd(void)
|
||||
{
|
||||
return port_fd;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void set_rts(int val)
|
||||
{
|
||||
int flags;
|
||||
int result;
|
||||
|
||||
result = ioctl(port_fd, TIOCMGET, &flags);
|
||||
|
||||
if (result == -1) {
|
||||
printf("Error %i while reading port io flags\n", errno);
|
||||
return;
|
||||
}
|
||||
|
||||
if (val) {
|
||||
flags |= TIOCM_RTS;
|
||||
}
|
||||
else {
|
||||
flags &= ~(TIOCM_RTS);
|
||||
}
|
||||
|
||||
result = ioctl(port_fd, TIOCMSET, &flags);
|
||||
|
||||
if (result == -1) {
|
||||
printf("Error %i while setting port io flags\n", errno);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void set_dtr(int val)
|
||||
{
|
||||
int flags;
|
||||
int result;
|
||||
|
||||
result = ioctl(port_fd, TIOCMGET, &flags);
|
||||
|
||||
if (result == -1) {
|
||||
printf("Error %i while reading port io flags\n", errno);
|
||||
return;
|
||||
}
|
||||
|
||||
if (val) {
|
||||
flags |= TIOCM_DTR;
|
||||
}
|
||||
else {
|
||||
flags &= ~(TIOCM_DTR);
|
||||
}
|
||||
|
||||
result = ioctl(port_fd, TIOCMSET, &flags);
|
||||
|
||||
if (result == -1) {
|
||||
printf("Error %i while setting port io flags\n", errno);
|
||||
}
|
||||
}
|
||||
28
dist/tools/linux-border_router/serial.h
vendored
28
dist/tools/linux-border_router/serial.h
vendored
@ -1,28 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin.
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/* token from pseudoterm */
|
||||
#ifndef SERIAL_H
|
||||
#define SERIAL_H
|
||||
|
||||
extern char *baud_rate;
|
||||
|
||||
int open_serial_port(const char *port_name);
|
||||
int write_serial_port(const void *buf, int num);
|
||||
void input_flush_serial_port(void);
|
||||
int read_serial_port_nb(unsigned char *buf, int bufsize);
|
||||
int read_serial_port(unsigned char *buf, int bufsize);
|
||||
void close_serial_port(void);
|
||||
void send_break_signal(void);
|
||||
int set_baud(const char *baud_name);
|
||||
int serial_port_fd(void);
|
||||
void set_rts(int val);
|
||||
void set_dtr(int val);
|
||||
void change_baud(const char *baud_name);
|
||||
|
||||
#endif // SERIAL_H
|
||||
90
dist/tools/linux-border_router/serialnumber.c
vendored
90
dist/tools/linux-border_router/serialnumber.c
vendored
@ -1,90 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin.
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
#include "serialnumber.h"
|
||||
|
||||
int serial_add8(uint8_t s, uint8_t n)
|
||||
{
|
||||
if (n > 127) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint16_t sum = s + n;
|
||||
return (uint8_t)(sum % 256);
|
||||
}
|
||||
|
||||
int serial_add16(uint16_t s, uint16_t n)
|
||||
{
|
||||
if (n > 32767) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t sum = s + n;
|
||||
return (uint16_t)(sum % 65536);
|
||||
}
|
||||
|
||||
int serial_add32(uint32_t s, uint32_t n)
|
||||
{
|
||||
if (n > 2147483647) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint64_t sum = s + n;
|
||||
return (uint32_t)(sum % 4294967296);
|
||||
}
|
||||
|
||||
serial_comp_res_t serial_comp8(uint8_t s1, uint8_t s2)
|
||||
{
|
||||
if (s1 == s2) {
|
||||
return EQUAL;
|
||||
}
|
||||
|
||||
if ((s1 < s2 && s1 - s2 < 128) || (s1 > s2 && s1 - s2 > 128)) {
|
||||
return LESS;
|
||||
}
|
||||
|
||||
if ((s1 < s2 && s1 - s2 > 128) || (s1 > s2 && s1 - s2 < 128)) {
|
||||
return GREATER;
|
||||
}
|
||||
|
||||
return UNDEF;
|
||||
}
|
||||
|
||||
serial_comp_res_t serial_comp16(uint16_t s1, uint16_t s2)
|
||||
{
|
||||
if (s1 == s2) {
|
||||
return EQUAL;
|
||||
}
|
||||
|
||||
if ((s1 < s2 && s1 - s2 < 32768) || (s1 > s2 && s1 - s2 > 32768)) {
|
||||
return LESS;
|
||||
}
|
||||
|
||||
if ((s1 < s2 && s1 - s2 > 32768) || (s1 > s2 && s1 - s2 < 32768)) {
|
||||
return GREATER;
|
||||
}
|
||||
|
||||
return UNDEF;
|
||||
}
|
||||
|
||||
serial_comp_res_t serial_comp32(uint32_t s1, uint32_t s2)
|
||||
{
|
||||
if (s1 == s2) {
|
||||
return EQUAL;
|
||||
}
|
||||
|
||||
if ((s1 < s2 && s1 - s2 < 2147483648) || (s1 > s2 && s1 - s2 > 2147483648)) {
|
||||
return LESS;
|
||||
}
|
||||
|
||||
if ((s1 < s2 && s1 - s2 > 2147483648) || (s1 > s2 && s1 - s2 < 2147483648)) {
|
||||
return GREATER;
|
||||
}
|
||||
|
||||
return UNDEF;
|
||||
}
|
||||
92
dist/tools/linux-border_router/serialnumber.h
vendored
92
dist/tools/linux-border_router/serialnumber.h
vendored
@ -1,92 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin.
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||
* @brief Serial number arithmetics after RFC 1982, section 3
|
||||
*/
|
||||
|
||||
#ifndef SERIALNUMBER_H
|
||||
#define SERIALNUMBER_H
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @brief Results for the serial number comparisson.
|
||||
*/
|
||||
typedef enum serial_comp_res_t {
|
||||
LESS, EQUAL, GREATER, UNDEF
|
||||
} serial_comp_res_t;
|
||||
|
||||
/**
|
||||
* @brief Addition for 8-bit unsigned integers in serial number
|
||||
* arithmetics (corresponding RFC 1982, section 3.1).
|
||||
* @param[in] s first summand in [0 .. 2^8 - 1].
|
||||
* @param[in] n second summand in [0 .. 2^7 - 1].
|
||||
* @return Sum corresponding RFC1982 section 3.1 if <em>n</em> in [0 .. 2^7 - 1] or
|
||||
* -1 if <em>n</em> not in [0 .. 2^7 - 1].
|
||||
**/
|
||||
int serial_add8(uint8_t s, uint8_t n);
|
||||
|
||||
/**
|
||||
* @brief Addition for 16-bit unsigned integers in serial number
|
||||
* arithmetics (corresponding RFC 1982, section 3.1).
|
||||
* @param[in] s first summand in [0 .. 2^16 - 1].
|
||||
* @param[in] n second summand in [0 .. 2^15 - 1].
|
||||
* @return Sum corresponding RFC 1982 section 3.1 if <em>n</em> in [0 .. 2^15 - 1] or
|
||||
* -1 if <em>n</em> not in [0 .. 2^15 - 1].
|
||||
**/
|
||||
int serial_add16(uint16_t s, uint16_t n);
|
||||
|
||||
/**
|
||||
* @brief Addition for 32-bit unsigned integers in serial number
|
||||
* arithmetics (corresponding RFC1982, section 3.1).
|
||||
* @param[in] s first summand in [0 .. 2^32 - 1].
|
||||
* @param[in] n second summand in [0 .. 2^31 - 1].
|
||||
* @return Sum corresponding RFC 1982 section 3.1 if <em>n</em> in [0 .. 2^31 - 1] or
|
||||
* -1 if <em>n</em> not in [0 .. 2^31 - 1].
|
||||
**/
|
||||
int serial_add32(uint32_t s, uint32_t n);
|
||||
|
||||
/**
|
||||
* @brief Comparison of 8-bit unsigned integers in serial number
|
||||
* arithmetics (corresponding RFC 1982, section 3.2).
|
||||
* @param[in] s1 first argument.
|
||||
* @param[in] s2 second argument.
|
||||
* @return <tt>LESS</tt> if <em>s1</em> < <em>s2</em>.
|
||||
* <tt>EQUAL</tt> if <em>s1</em> = <em>s2</em>.
|
||||
* <tt>GREATER</tt> if <em>s1</em> > <em>s2</em>.
|
||||
* else <tt>UNDEF</tt> (see RFC 1982, section 3.2).
|
||||
**/
|
||||
serial_comp_res_t serial_comp8(uint8_t s1, uint8_t s2);
|
||||
|
||||
/**
|
||||
* @brief Comparison of 16-bit unsigned integers in serial number
|
||||
* arithmetics (corresponding RFC 1982, section 3.2).
|
||||
* @param[in] s1 first argument.
|
||||
* @param[in] s2 second argument.
|
||||
* @return <tt>LESS</tt> if <em>s1</em> < <em>s2</em>.
|
||||
* <tt>EQUAL</tt> if <em>s1</em> = <em>s2</em>.
|
||||
* <tt>GREATER</tt> if <em>s1</em> > <em>s2</em>.
|
||||
* else <tt>UNDEF</tt> (see RFC 1982, section 3.2).
|
||||
**/
|
||||
serial_comp_res_t serial_comp16(uint16_t s1, uint16_t s2);
|
||||
|
||||
/**
|
||||
* @brief Comparison of 32-bit unsigned integers in serial number
|
||||
* arithmetics (corresponding RFC1982, section 3.2).
|
||||
* @param[in] s1 first argument.
|
||||
* @param[in] s2 second argument.
|
||||
* @return <tt>LESS</tt> if <em>s1</em> < <em>s2</em>.
|
||||
* <tt>EQUAL</tt> if <em>s1</em> = <em>s2</em>.
|
||||
* <tt>GREATER</tt> if <em>s1</em> > <em>s2</em>.
|
||||
* else <tt>UNDEF</tt> (see RFC 1982, section 3.2).
|
||||
**/
|
||||
serial_comp_res_t serial_comp32(uint32_t s1, uint32_t s2);
|
||||
|
||||
#endif /* SERIALNUMBER_H*/
|
||||
335
dist/tools/linux-border_router/sixlowdriver.c
vendored
335
dist/tools/linux-border_router/sixlowdriver.c
vendored
@ -1,335 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin.
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/ip6.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <linux/if_tun.h>
|
||||
|
||||
#include "sixlowdriver.h"
|
||||
#include "multiplex.h"
|
||||
#include "flowcontrol.h"
|
||||
#include "serialnumber.h"
|
||||
#include "control_2xxx.h"
|
||||
|
||||
#define TUNDEV "/dev/net/tun"
|
||||
#define MAXIMUM_CONTEXTS 16
|
||||
|
||||
char tun_if_name[IF_NAME_LEN];
|
||||
|
||||
uint8_t tun_out_buf[BUFFER_SIZE];
|
||||
uint8_t tun_in_buf[BUFFER_SIZE];
|
||||
|
||||
/* Cell i is defined as empty if context_cache[i].cid != i */
|
||||
border_context_t context_cache[MAXIMUM_CONTEXTS];
|
||||
|
||||
int tun_fd;
|
||||
pthread_t serial_reader, tun_reader;
|
||||
uint16_t abro_version = 0;
|
||||
|
||||
uint16_t get_abro_version()
|
||||
{
|
||||
return abro_version;
|
||||
}
|
||||
|
||||
uint16_t get_next_abro_version()
|
||||
{
|
||||
abro_version = serial_add16(abro_version, 1);
|
||||
return abro_version;
|
||||
}
|
||||
|
||||
int get_tun_fd(void)
|
||||
{
|
||||
return tun_fd;
|
||||
}
|
||||
|
||||
void *serial_reader_f(void *arg)
|
||||
{
|
||||
unsigned char buf[BUFFER_SIZE];
|
||||
border_packet_t *packet_buf;
|
||||
|
||||
while (1) {
|
||||
int n = readpacket(buf, BUFFER_SIZE);
|
||||
|
||||
if (n > 0) {
|
||||
if (buf[0] == 0) {
|
||||
packet_buf = (border_packet_t *)buf;
|
||||
flowcontrol_deliver_from_tty(packet_buf, n);
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("\033[00;33m[via serial interface] %s\033[00m\n", buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int tun_to_serial_packet(uint8_t *serial_packet, uint8_t *tun_packet, size_t packet_size)
|
||||
{
|
||||
struct tun_pi *tun_hdr = (struct tun_pi *)tun_packet;
|
||||
border_l3_header_t *l3_hdr = (border_l3_header_t *)serial_packet;
|
||||
|
||||
l3_hdr->empty = 0;
|
||||
l3_hdr->type = BORDER_PACKET_L3_TYPE;
|
||||
l3_hdr->ethertype = ntohs(tun_hdr->proto);
|
||||
|
||||
memcpy(
|
||||
serial_packet + sizeof(border_l3_header_t),
|
||||
tun_packet + sizeof(struct tun_pi),
|
||||
packet_size - sizeof(struct tun_pi)
|
||||
);
|
||||
return (sizeof(border_l3_header_t) + (packet_size - sizeof(struct tun_pi)));
|
||||
}
|
||||
|
||||
void *tun_reader_f(void *args)
|
||||
{
|
||||
unsigned char data[BUFFER_SIZE];
|
||||
|
||||
while (1) {
|
||||
size_t bytes = read(tun_fd, (void *)data, BUFFER_SIZE);
|
||||
|
||||
if (bytes > 0) {
|
||||
bytes = tun_to_serial_packet(tun_in_buf, (uint8_t *)data, bytes);
|
||||
flowcontrol_send_over_tty((border_packet_t *)tun_in_buf, bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void border_send_ipv6_over_tun(int fd, const struct ip6_hdr *packet)
|
||||
{
|
||||
uint8_t tun_packet[BUFFER_SIZE];
|
||||
int packet_size = packet->ip6_plen + sizeof(struct ip6_hdr);
|
||||
|
||||
struct tun_pi *tun_hdr = (struct tun_pi *)tun_packet;
|
||||
|
||||
tun_hdr->flags = 0;
|
||||
tun_hdr->proto = htons(ETHERTYPE_IPV6);
|
||||
|
||||
memcpy(tun_packet + sizeof(struct tun_pi), (uint8_t *)packet, packet_size);
|
||||
write(tun_fd, tun_packet, packet_size + sizeof(struct tun_pi));
|
||||
}
|
||||
|
||||
int tun_set_owner(int fd, const uid_t *uid, const gid_t *gid)
|
||||
{
|
||||
if (uid != NULL) {
|
||||
if (*uid != -1 && ioctl(fd, TUNSETOWNER, *uid)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (gid != NULL) {
|
||||
if (*gid != -1 && ioctl(fd, TUNSETGROUP, *gid)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tun_add_addr(const char *ip_addr)
|
||||
{
|
||||
char command[21 + IPV6_ADDR_LEN + IF_NAME_LEN];
|
||||
|
||||
printf("INFO: ip addr add %s dev %s\n", ip_addr, tun_if_name);
|
||||
sprintf(command, "ip addr add %s dev %s", ip_addr, tun_if_name);
|
||||
|
||||
if (system(command) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Source: http://backreference.org/2010/03/26/tuntap-interface-tutorial/
|
||||
*/
|
||||
int open_tun(char *if_name, int flags)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
int fd, err;
|
||||
|
||||
/* Arguments taken by the function:
|
||||
*
|
||||
* char *if_name: the name of an interface (or '\0'). MUST have enough
|
||||
* space to hold the interface name if '\0' is passed
|
||||
* int flags: interface flags (eg, IFF_TUN etc.)
|
||||
*/
|
||||
|
||||
/* open the clone device */
|
||||
if ((fd = open(TUNDEV, O_RDWR)) < 0) {
|
||||
return fd;
|
||||
}
|
||||
|
||||
/* preparation of the struct ifr, of type "struct ifreq" */
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
|
||||
ifr.ifr_flags = flags; /* IFF_TUN or IFF_TAP, plus maybe IFF_NO_PI */
|
||||
|
||||
if (*if_name) {
|
||||
/* if a device name was specified, put it in the structure; otherwise,
|
||||
* the kernel will try to allocate the "next" device of the
|
||||
* specified type */
|
||||
strncpy(ifr.ifr_name, if_name, IFNAMSIZ);
|
||||
}
|
||||
|
||||
/* try to create the device */
|
||||
if ((err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0) {
|
||||
close(fd);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* if the operation was successful, write back the name of the
|
||||
* interface to the variable "if_name", so the caller can know
|
||||
* it. Note that the caller MUST reserve space in *if_name (see calling
|
||||
* code below) */
|
||||
strcpy(if_name, ifr.ifr_name);
|
||||
|
||||
/* this is the special file descriptor that the caller will use to talk
|
||||
* with the virtual interface */
|
||||
return fd;
|
||||
}
|
||||
|
||||
int context_empty(uint8_t cid)
|
||||
{
|
||||
return context_cache[cid].cid != cid;
|
||||
}
|
||||
|
||||
int border_update_context(uint8_t cid, const struct in6_addr *prefix,
|
||||
uint8_t len, uint8_t comp,
|
||||
uint16_t lifetime)
|
||||
{
|
||||
if (cid >= MAXIMUM_CONTEXTS) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
len = (len <= 128) ? len : 128;
|
||||
|
||||
if (context_empty(cid)) {
|
||||
context_cache[cid].version = get_abro_version();
|
||||
}
|
||||
else {
|
||||
context_cache[cid].version = get_next_abro_version();
|
||||
}
|
||||
|
||||
context_cache[cid].cid = cid;
|
||||
memcpy(&(context_cache[cid].prefix), prefix, len);
|
||||
context_cache[cid].len = len;
|
||||
context_cache[cid].comp = comp;
|
||||
context_cache[cid].lifetime = lifetime;
|
||||
|
||||
multiplex_send_context_over_tty(&context_cache[cid]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int border_renew_existing_context(uint8_t cid)
|
||||
{
|
||||
if (cid >= MAXIMUM_CONTEXTS) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (context_empty(cid)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
multiplex_send_context_over_tty(&context_cache[cid]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void border_remove_context(uint8_t cid)
|
||||
{
|
||||
if (cid >= MAXIMUM_CONTEXTS) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (context_empty(cid)) {
|
||||
return;
|
||||
}
|
||||
|
||||
context_cache[cid].version = get_next_abro_version();
|
||||
context_cache[cid].lifetime = 0;
|
||||
|
||||
multiplex_send_context_over_tty(&context_cache[cid]);
|
||||
|
||||
context_cache[cid].cid = 0xFF;
|
||||
}
|
||||
|
||||
int border_add_addr(const char *ip_addr)
|
||||
{
|
||||
struct in6_addr parsed_addr;
|
||||
|
||||
if (inet_pton(AF_INET6, ip_addr, &parsed_addr) != 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
tun_add_addr(ip_addr);
|
||||
|
||||
multiplex_send_addr_over_tty(&parsed_addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int border_initialize(char *if_name, const char *ip_addr, const char *tty_dev)
|
||||
{
|
||||
int res, i;
|
||||
char command[21 + IPV6_ADDR_LEN + IF_NAME_LEN];
|
||||
char ip_addr_cpy[IPV6_ADDR_LEN + 1];
|
||||
struct in6_addr parsed_addr;
|
||||
|
||||
strncpy(ip_addr_cpy, ip_addr, IPV6_ADDR_LEN);
|
||||
ip_addr_cpy[IPV6_ADDR_LEN] = '\0';
|
||||
|
||||
strtok(ip_addr_cpy, "/");
|
||||
|
||||
if ((res = inet_pton(AF_INET6, ip_addr_cpy, &parsed_addr)) != 1) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if ((res = init_multiplex(tty_dev)) != 0) {
|
||||
return res;
|
||||
}
|
||||
|
||||
tun_fd = open_tun(if_name, IFF_TUN);
|
||||
|
||||
printf("INFO: ip link set %s up\n", if_name);
|
||||
sprintf(command, "ip link set %s up", if_name);
|
||||
|
||||
strncpy(tun_if_name, if_name, IF_NAME_LEN);
|
||||
|
||||
if ((res = system(command)) != 0) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if ((res = tun_add_addr(ip_addr)) != 0) {
|
||||
return res;
|
||||
}
|
||||
|
||||
// initialize context cache as empty.
|
||||
for (i = 0; i < MAXIMUM_CONTEXTS; i++) {
|
||||
context_cache[i].cid = 0xFF;
|
||||
}
|
||||
|
||||
pthread_create(&serial_reader, NULL, serial_reader_f, NULL);
|
||||
|
||||
hard_reset_to_user_code();
|
||||
flowcontrol_init(&parsed_addr);
|
||||
pthread_create(&tun_reader, NULL, tun_reader_f, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
177
dist/tools/linux-border_router/sixlowdriver.h
vendored
177
dist/tools/linux-border_router/sixlowdriver.h
vendored
@ -1,177 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin.
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||
* @brief Public declarations for the 6LoWPAN Border Router driver.
|
||||
*/
|
||||
|
||||
#ifndef SIXLOWDRIVER_H
|
||||
#define SIXLOWDRIVER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <netinet/ip6.h>
|
||||
|
||||
/**
|
||||
* @brief The maximum string length of an IPv6 address in text representation.
|
||||
*/
|
||||
#define IPV6_ADDR_LEN 40
|
||||
#define IF_NAME_LEN 10 ///< Maximum length of an interface name
|
||||
#define DEV_LEN 20 ///< Maximum length of a device filename
|
||||
|
||||
/**
|
||||
* @brief Defines the format of the context information.
|
||||
*/
|
||||
typedef struct __attribute__((packed)) border_context_t {
|
||||
uint16_t version; ///< Version of this context, send via the ABRO (s. draft-ietf-6lowpan-nd-17).
|
||||
uint8_t cid; ///< The CID of the Context (s. draft-ietf-6lowpan-nd-17).
|
||||
struct in6_addr prefix; ///< The prefix this context defines.
|
||||
uint8_t len; ///< The length of the prefix in bits.
|
||||
uint8_t comp; ///< Flag to determine if Context is allowed for compression (s. draft-ietf-6lowpan-nd-17).
|
||||
uint16_t lifetime; ///< Lifetime of this context (s. draft-ietf-6lowpan-nd-17).
|
||||
} border_context_t;
|
||||
|
||||
/**
|
||||
* @brief Initializes a TUN- or TAP-Interface.
|
||||
* @param[in,out] dev The name of the new interface. If the name
|
||||
* is not given, it is chosen by the kernel
|
||||
* and returned to the caller.
|
||||
* @param[in] flags Flags that signify the interface type
|
||||
* (<tt>IFF_TUN</tt> = TUN interface,
|
||||
* <tt>IFF_TAP</tt> = TAP interface,
|
||||
* @return The file descriptor to the new interface.
|
||||
* <tt>IFF_NO_PI</tt> = provide no packet information).
|
||||
* @see http://backreference.org/2010/03/26/tuntap-interface-tutorial/
|
||||
* @see http://www.kernel.org/pub/linux/kernel/people/marcelo/linux-2.4/Documentation/networking/tuntap.txt
|
||||
*
|
||||
* Initializes a TUN- or TAP-Interface by the name <em>dev</em>. Which kind
|
||||
* of interface is defined by <em>flags</em>. The function returns the file
|
||||
* descriptor to the interface, which can be accessed via the
|
||||
* POSIX.1-2001 functions <tt>read()</tt> and <tt>write()</tt>
|
||||
*/
|
||||
int open_tun(char *dev, int flags);
|
||||
|
||||
/**
|
||||
* @brief Returns the file descriptor to the TUN interface.
|
||||
* @return The file descriptor to the TUN interface initialized by
|
||||
* open_tun()
|
||||
*
|
||||
* open_tun() needs to be called before. Otherwise the result of this
|
||||
* function may not make sense.
|
||||
*/
|
||||
int get_tun_fd(void);
|
||||
|
||||
/**
|
||||
* @brief Sets the owner of a TUN- or TAP-Interface.
|
||||
* @param[in] fd The file descriptor to the interface to be changed.
|
||||
* @param[in] uid User ID of the new user to be assigned.
|
||||
* @param[in] gid Group ID of the new group to be assigned.
|
||||
* @return 0, if successful, -1 if not.
|
||||
*/
|
||||
int tun_set_owner(int fd, const uid_t *uid, const gid_t *gid);
|
||||
|
||||
/**
|
||||
* @brief Adds a new IPv6 address to the TUN interface.
|
||||
* @param[in] ip_addr The new address.
|
||||
* @return 0, if <em>ip_addr</em> is a valid IPv6 address, -1, if not.
|
||||
*/
|
||||
int tun_add_addr(const char *ip_addr);
|
||||
|
||||
/**
|
||||
* @brief Initializes the border router.
|
||||
* @param[in,out] if_name The name of the new TUN interface. If the
|
||||
* name is not given, it is chosen by the
|
||||
* kernel and returned to the caller.
|
||||
* @param[in] ip_addr The IPv6 Address, that is initially attached
|
||||
* to the LoWPAN Border Router.
|
||||
* @param[in] tty_dev Device file of the serial interface the
|
||||
* MSB-A2 is attached to.
|
||||
* @return 0 if successfull,
|
||||
* != 0 if an error occurs.
|
||||
*/
|
||||
int border_initialize(char *if_name, const char *ip_addr, const char *tty_dev);
|
||||
|
||||
/**
|
||||
* @brief Sends an IPv6 datagram via the TUN interface.
|
||||
* @param[in] fd The file descriptor of the TUN interface
|
||||
* @param[in] packet The IPv6 datagram that is to be send via the
|
||||
* TUN interface and starts with an IPv6 header.
|
||||
*
|
||||
* The function uses the payload length field of the IPv6 Header to
|
||||
* determine the length of the overall packet. The payload bytes
|
||||
* <em>must</em> follow the header in memory.
|
||||
*/
|
||||
void border_send_ipv6_over_tun(int fd, const struct ip6_hdr *packet);
|
||||
|
||||
/**
|
||||
* @brief Updates 6LoWPAN contex information.
|
||||
* @param[in] cid The context identifier, only values < 16
|
||||
* are allowed.
|
||||
* @param[in] prefix The prefix that shall be associated with the
|
||||
* <em>cid</em>.
|
||||
* @param[in] len The length of the <em>prefix</em> in bits.
|
||||
* @param[in] comp Flag to determine if Context is allowed for
|
||||
* compression (s. draft-ietf-6lowpan-nd-17).
|
||||
* @param[in] lifetime Lifetime of this context
|
||||
* (s. draft-ietf-6lowpan-nd-17).
|
||||
* @return If cid < 16 than it is 0, otherwise -1.
|
||||
*/
|
||||
int border_update_context(uint8_t cid, const struct in6_addr *prefix,
|
||||
uint8_t len, uint8_t comp,
|
||||
uint16_t lifetime);
|
||||
|
||||
/**
|
||||
* @brief Updates 6LoWPAN contex information, as it is stored in the
|
||||
* border router (e.g. to maintain a context which lifetime
|
||||
* is about to run out).
|
||||
* @param[in] cid The context identifier.
|
||||
* @return 0, if the context identifiet by cid is stored in the border
|
||||
* router, -1 if not.
|
||||
*
|
||||
* The information taken for this update ist the last, that was used
|
||||
* with \ref border_update_context().
|
||||
*/
|
||||
int border_renew_existing_context(uint8_t cid);
|
||||
|
||||
/**
|
||||
* @brief Removes 6LoWPAN context information.
|
||||
* @param[in] cid The context identifier.
|
||||
*
|
||||
* The information taken for this update ist the last, that was used
|
||||
* with \ref border_update_context().
|
||||
*/
|
||||
void border_remove_context(uint8_t cid);
|
||||
|
||||
/**
|
||||
* @brief Adds a new IPv6 address to the whole interface (TUN and
|
||||
* sensor node).
|
||||
* @param[in] ip_addr The new address.
|
||||
* @return 0, if <em>ip_addr</em> is a valid IPv6 address, -1, if not.
|
||||
*/
|
||||
int border_add_addr(const char *ip_addr);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Getter for the current version for ABROs send by this
|
||||
* router.
|
||||
* @return This border router's current version.
|
||||
*/
|
||||
uint16_t get_abro_version(void);
|
||||
|
||||
/**
|
||||
* @brief Increments and updates the version for ABROs send by this
|
||||
* router.
|
||||
* @return This border router's new ABRO version.
|
||||
*/
|
||||
uint16_t get_next_abro_version(void);
|
||||
|
||||
#endif /* SIXLOWDRIVER_H*/
|
||||
179
dist/tools/linux-border_router/testing.c
vendored
179
dist/tools/linux-border_router/testing.c
vendored
@ -1,179 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin.
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "testing.h"
|
||||
#include "flowcontrol.h"
|
||||
|
||||
struct timeval timers[256];
|
||||
struct test_stats *stats = NULL;
|
||||
int run_counter;
|
||||
|
||||
FILE *stats_file = NULL;
|
||||
|
||||
void init_file(const char *skeleton_file_name,
|
||||
int runs_per_test, float interval)
|
||||
{
|
||||
FILE *skeleton_file = NULL;
|
||||
char line[1024];
|
||||
|
||||
skeleton_file = fopen(skeleton_file_name, "r");
|
||||
|
||||
while (fgets(line, 1024, skeleton_file) != NULL) {
|
||||
if (strncmp(line, "# sending window size=%d\n", 1024) == 0) {
|
||||
fprintf(stats_file, line, BORDER_SWS);
|
||||
}
|
||||
else if (strncmp(line, "# count=%ld (-c)\n", 1024) == 0) {
|
||||
fprintf(stats_file, line, runs_per_test);
|
||||
}
|
||||
else if (strncmp(line, "# interval=%f (-i)\n", 1024) == 0) {
|
||||
fprintf(stats_file, line, interval);
|
||||
}
|
||||
else {
|
||||
fprintf(stats_file, "%s", line);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(skeleton_file);
|
||||
}
|
||||
|
||||
int testing_init(const char *stats_file_name,
|
||||
const char *skeleton_file_name,
|
||||
int runs_per_test, float interval)
|
||||
{
|
||||
if (stats_file != NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
stats = (struct test_stats *)calloc(runs_per_test, sizeof(struct test_stats));
|
||||
run_counter = 0;
|
||||
|
||||
stats_file = fopen(stats_file_name, "w");
|
||||
|
||||
if (stats_file == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
init_file(skeleton_file_name, runs_per_test, interval);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int testing_destroy()
|
||||
{
|
||||
int res, i;
|
||||
|
||||
for (i = 0; i < run_counter; i++) {
|
||||
fprintf(stats_file, "%7d\t%3d\t%7ld\n",
|
||||
i, stats[i].seq_num, stats[i].time_diff
|
||||
);
|
||||
}
|
||||
|
||||
free(stats);
|
||||
|
||||
stats = NULL;
|
||||
|
||||
res = fclose(stats_file);
|
||||
|
||||
stats_file = NULL;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void testing_start(uint8_t seq_num)
|
||||
{
|
||||
if (stats_file == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
gettimeofday(&(timers[seq_num]), NULL);
|
||||
}
|
||||
|
||||
void testing_stop(uint8_t seq_num)
|
||||
{
|
||||
if (stats_file == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct timeval start = timers[seq_num], end;
|
||||
|
||||
gettimeofday(&end, NULL);
|
||||
|
||||
stats[run_counter].seq_num = seq_num;
|
||||
|
||||
stats[run_counter].time_diff = (end.tv_sec - start.tv_sec) * 1000;
|
||||
|
||||
stats[run_counter].time_diff += (end.tv_usec - start.tv_usec) / 1000;
|
||||
|
||||
run_counter++;
|
||||
}
|
||||
|
||||
void generate_filename(
|
||||
char *filename,
|
||||
const char *results_dir_name,
|
||||
int runs_per_test,
|
||||
float interval)
|
||||
{
|
||||
time_t today;
|
||||
struct tm *tmp = NULL;
|
||||
char timestr[16];
|
||||
FILE *test = NULL;
|
||||
int count = 1;
|
||||
|
||||
today = time(NULL);
|
||||
tmp = localtime(&today);
|
||||
|
||||
if (tmp == NULL) {
|
||||
perror("localtime");
|
||||
return;
|
||||
}
|
||||
|
||||
strftime(timestr, 16, "%Y.%m.%d", tmp);
|
||||
|
||||
do {
|
||||
sprintf(filename,
|
||||
"%s/%s-Results-Ping6_%d_%d_%f-%d.txt",
|
||||
results_dir_name,
|
||||
timestr,
|
||||
BORDER_SWS,
|
||||
runs_per_test,
|
||||
interval,
|
||||
count++
|
||||
);
|
||||
}
|
||||
while ((test = fopen(filename, "r")) != NULL);
|
||||
|
||||
if (test != NULL) {
|
||||
fclose(test);
|
||||
}
|
||||
}
|
||||
|
||||
void start_test(const char *ping_addr,
|
||||
const char *results_dir_name, const char *skeleton_file,
|
||||
int runs_per_test, float interval)
|
||||
{
|
||||
printf("%d, %f\n", runs_per_test, interval);
|
||||
char command[50];
|
||||
char filename[50];
|
||||
generate_filename(filename, results_dir_name, runs_per_test, interval);
|
||||
|
||||
sprintf(command, "ping6 -v -f -c %d -i %f -W 1 abcd::d",
|
||||
runs_per_test,
|
||||
interval
|
||||
);
|
||||
|
||||
testing_init(filename, skeleton_file, runs_per_test, interval);
|
||||
puts(command);
|
||||
system(command);
|
||||
testing_destroy();
|
||||
}
|
||||
75
dist/tools/linux-border_router/testing.h
vendored
75
dist/tools/linux-border_router/testing.h
vendored
@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin.
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Test suite for the 6LoWPAN Border Router.
|
||||
*
|
||||
* The tests are managed in the following way:
|
||||
* Packets (ICMPv6 Echo Request) are send onto the sensor node
|
||||
* via the serial interface. The user can then decide what she
|
||||
* wants to measure by calling testing_start() to start the
|
||||
* measuring and testing_stop() to end it.
|
||||
*
|
||||
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||
*/
|
||||
|
||||
#ifndef TESTING_H
|
||||
#define TESTING_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @brief Defines the format to store test results.
|
||||
*/
|
||||
struct test_stats {
|
||||
uint8_t seq_num; ///< Sequence number of the send packet.
|
||||
/**
|
||||
* @brief Time difference between call of testing_start() and
|
||||
* testing_stop().
|
||||
*/
|
||||
long int time_diff;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Starts a test measuring.
|
||||
* @param[in] seq_num Sequence number of the measurement.
|
||||
*/
|
||||
void testing_start(uint8_t seq_num);
|
||||
|
||||
/**
|
||||
* @brief Stops a test measuring.
|
||||
* @param[in] seq_num Sequence number of the measurement.
|
||||
*/
|
||||
void testing_stop(uint8_t seq_num);
|
||||
|
||||
/**
|
||||
* @brief Starts the sending of the packets and initialises the
|
||||
* test environment
|
||||
* @param[in] ping_addr The address the packets should be
|
||||
* send to.
|
||||
* @param[in] results_dir_name Name of the results directory.
|
||||
* @param[in] skeleton_file Name of the skeleton file, where
|
||||
* the template for the results file
|
||||
* is. Lines of the formats
|
||||
* <tt>"# count=%ld (-c)\n"</tt> and
|
||||
* <tt>"# interval=%0.2f (-i)\n"</tt>
|
||||
* will be replaced with <tt>\%ld</tt>
|
||||
* set to <em>runs_per_test</em> and
|
||||
* <tt>\%0.2f</tt> set to
|
||||
* <em>interval</em>.
|
||||
* @param[in] runs_per_test How many packets shall be send in
|
||||
* this test.
|
||||
* @param[in] interval How many seconds shall lay between
|
||||
* the sending of each packet.
|
||||
*/
|
||||
void start_test(const char *ping_addr,
|
||||
const char *results_dir_name, const char *skeleton_file,
|
||||
int runs_per_test, float interval);
|
||||
|
||||
#endif /* TESTING_H*/
|
||||
Loading…
x
Reference in New Issue
Block a user