1
0
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:
Martine Lenders 2015-03-23 17:22:01 +01:00 committed by Martine Lenders
parent 1a146f7934
commit c3abfb3627
17 changed files with 0 additions and 4054 deletions

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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*/

View File

@ -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;
}

View File

@ -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
);
}

View File

@ -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*/

View File

@ -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);
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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*/

View File

@ -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;
}

View File

@ -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*/

View File

@ -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();
}

View File

@ -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*/