1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-01-18 12:52:44 +01:00

Merge branch 'sixlowpan'

Conflicts:
	cpu/arm_common/hwtimer_cpu.c
	sys/include/vtimer.h
	sys/vtimer.c
This commit is contained in:
Oliver Hahm 2012-01-11 17:02:43 +01:00
commit 59a46e0e88
72 changed files with 11251 additions and 10 deletions

View File

@ -29,6 +29,7 @@
# OS specifics
#
if $(NT) {
SLASH = \\ ;
POSIXSHELL = sh ;
NULLDEV = NUL ;
CAT = type ;

View File

@ -37,7 +37,11 @@ int mutex_init(struct mutex_t* mutex) {
int mutex_trylock(struct mutex_t* mutex) {
DEBUG("%s: trylocking to get mutex. val: %u\n", active_thread->name, mutex->val);
return atomic_set_return(&mutex->val, 1 ) == 0;
return (atomic_set_return(&mutex->val, thread_pid ) == 0);
}
int prio() {
return active_thread->priority;
}
int mutex_lock(struct mutex_t* mutex) {

View File

@ -0,0 +1,5 @@
SubDir TOP projects sixborder ;
Module sixborder : main.c : auto_init uart0 posix_io cc110x_ng 6lowpan vtimer rtc destiny ;
UseModule sixborder ;

13
projects/sixborder/main.c Normal file
View File

@ -0,0 +1,13 @@
#include <stdio.h>
#include <string.h>
#include <transceiver.h>
#include <vtimer.h>
#include "sys/net/sixlowpan/sixlowip.h"
#include "sys/net/sixlowpan/sixlowborder.h"
#include "sys/net/sixlowpan/sixlowerror.h"
int main(void)
{
border_initialize(TRANSCEIVER_CC1100, NULL);
}

View File

@ -0,0 +1,13 @@
#!/usr/bin/expect
set timeout 5
spawn pseudoterm $env(PORT)
expect {
"Hello World!" {}
timeout { exit 1 }
}
puts "\nTest successful!\n"

View File

@ -0,0 +1,11 @@
#
# FireKernel example project Jamfile
#
# Copyright (C) 2008, 2009 Kaspar Schleiser <kaspar@schleiser.de>
#
SubDir TOP projects sixlowpan ;
Module sixlowpan : main.c : ps shell_commands config shell posix_io uart0 cc110x_ng 6lowpan vtimer auto_init rtc ;
UseModule sixlowpan ;

174
projects/sixlowpan/main.c Normal file
View File

@ -0,0 +1,174 @@
/*
* Copyright (C) 2008, 2009, 2010 Kaspar Schleiser <kaspar@schleiser.de>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <posix_io.h>
#include <shell.h>
#include <board_uart0.h>
#include <vtimer.h>
#include <ltc4150.h>
#include <thread.h>
#include <cc110x_ng.h>
#include <transceiver.h>
#include <time.h>
#include <rtc.h>
#include "sys/net/sixlowpan/sixlowmac.h"
#include "sys/net/sixlowpan/sixlowip.h"
#include "sys/net/sixlowpan/sixlowborder.h"
#include "sys/net/sixlowpan/sixlowpan.h"
#include "sys/net/sixlowpan/sixlowerror.h"
void init(char *str){
char command;
uint16_t r_addr;
ipv6_addr_t std_addr;
int res = sscanf(str, "init %c %hu", &command, &r_addr);
if(res < 1){
printf("Usage: init {h | r | a | e} radio_address\n");
printf("\th\tinitialize as host\n");
printf("\tr\tinitialize as router\n");
printf("\ta\tinitialize as ad-hoc router\n");
printf("\tb\tinitialize as border router\n\n");
printf("\tradio_address must be an 8 bit integer\n");
}
ipv6_init_address(&std_addr,0xABCD,0,0,0,0x1034,0x00FF,0xFE00,r_addr);
switch (command) {
case 'h':
printf("INFO: Initialize as host on radio address %hu\n", r_addr);
if (r_addr > 255) {
printf("ERROR: radio_address not an 8 bit integer\n");
return;
}
sixlowpan_init(TRANSCEIVER_CC1100,r_addr,0);
break;
case 'r':
printf("INFO: Initialize as router on radio address %hu\n", r_addr);
if (r_addr > 255) {
printf("ERROR: radio_address not an 8 bit integer\n");
return;
}
sixlowpan_init(TRANSCEIVER_CC1100, r_addr,0);
ipv6_init_iface_as_router();
break;
case 'a':
printf("INFO: Initialize as adhoc router on radio address %hu\n", r_addr);
if (r_addr > 255) {
printf("ERROR: radio_address not an 8 bit integer\n");
return;
}
sixlowpan_adhoc_init(TRANSCEIVER_CC1100, &std_addr, r_addr);
break;
case 'b':
printf("INFO: Initialize as border router on radio address %hu\n", r_addr);
if (r_addr > 255) {
printf("ERROR: radio_address not an 8 bit integer\n");
return;
}
res = border_initialize(TRANSCEIVER_CC1100, &std_addr);
switch (res) {
case (SUCCESS): printf("INFO: Border router initialized.\n"); break;
case (SIXLOWERROR_ADDRESS): printf("ERROR: Illegal IP address: ");
ipv6_print_addr(&std_addr); break;
default: printf("ERROR: Unknown error (%d).\n", res); break;
}
break;
default:
printf("ERROR: Unknown command '%c'\n", command);
break;
}
}
void bootstrapping(char *str){
sixlowpan_bootstrapping();
}
void send_packet(char *str){
uint8_t test[2];
test[0] = 30;
test[1] = 98;
ipv6_addr_t ipaddr;
ipv6_init_address(&ipaddr, 0xabcd, 0x0, 0x0, 0x0, 0x3612, 0x00ff, 0xfe00, 0x0005);
ipv6_print_addr(&ipaddr);
for(int j=0;j<100;j++){
test[0] = j;
for(int i=0;i<1000;i++){
sixlowpan_send(&ipaddr, test, 2, 0);
}
//lib6lowpan_bootstrapping(&addr8);
}
}
void set_radio_chann(char *str){
uint16_t chann;
int res = sscanf(str, "set_chann %hu", &chann);
if(res < 1){
printf("Usage: set_chann [channel]\n");
}
cc110x_set_channel(chann);
}
void get_r_address(char *str){
printf("radio: %hu\n", cc110x_get_address());
}
void ip(char *str){
ipv6_iface_print_addrs();
}
void context(char *str){
uint8_t i;
lowpan_context_t *context;
for(i = 0; i < LOWPAN_CONTEXT_MAX; i++){
context = lowpan_context_num_lookup(i);
if (context != NULL) {
printf("%2d\tLifetime: %5u\tLength: %3d\t",context->num,context->lifetime,context->length);
ipv6_print_addr(&(context->prefix));
}
}
}
const shell_command_t shell_commands[] = {
{"send", "", send_packet},
{"init", "", init},
{"addr", "", get_r_address},
{"set_chann", "", set_radio_chann},
{"boot", "", bootstrapping},
{"ip", "", ip},
{"context", "", context},
{NULL, NULL, NULL}
};
int main(void) {
printf("6LoWPAN\n");
vtimer_init();
posix_open(uart0_handler_pid, 0);
//struct tm now;
//rtc_get_localtime(&now);
//srand((unsigned int)now.tm_sec);
//uint8_t random = rand() % 256;
//printf("address: %d\n", random);
shell_t shell;
shell_init(&shell, shell_commands, uart0_readc, uart0_putc);
shell_run(&shell);
return 0;
}

View File

@ -0,0 +1,13 @@
#!/usr/bin/expect
set timeout 5
spawn board/msba2/tools/bin/pseudoterm $env(PORT)
expect {
"Hello World!" {}
timeout { exit 1 }
}
puts "\nTest successful!\n"

View File

@ -39,7 +39,10 @@ int main(void)
thread_print_all();
printf("Waking up sleeper.\n");
thread_wakeup(pid);
<<<<<<< HEAD
=======
thread_print_all();
>>>>>>> master
thread_yield();
}
}

15
projects/tlayer/Jamfile Normal file
View File

@ -0,0 +1,15 @@
SubDir TOP projects tlayer ;
Module tlayer : main.c : ps shell_commands config ;
UseModule auto_init ;
UseModule tlayer ;
UseModule cc110x_ng ;
UseModule destiny ;
UseModule uart0 ;
UseModule posix_io ;
UseModule shell ;
UseModule ps ;
UseModule 6lowpan ;
UseModule vtimer ;
UseModule rtc ;

452
projects/tlayer/main.c Normal file
View File

@ -0,0 +1,452 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <posix_io.h>
#include <shell.h>
#include <board_uart0.h>
#include <vtimer.h>
#include <ltc4150.h>
#include <thread.h>
#include <cc110x_ng.h>
#include <transceiver.h>
#include <time.h>
#include <rtc.h>
#include "sys/net/sixlowpan/sixlowmac.h"
#include "sys/net/sixlowpan/sixlowip.h"
#include "sys/net/sixlowpan/sixlowborder.h"
#include "sys/net/sixlowpan/sixlowpan.h"
#include "sys/net/sixlowpan/sixlowerror.h"
#include "sys/net/destiny/udp.h"
#include "sys/net/destiny/tcp.h"
#include "sys/net/destiny/socket.h"
#include "sys/net/destiny/in.h"
#include "sys/net/destiny/destiny.h"
#include "sys/net/net_help/net_help.h"
uint8_t udp_server_thread_pid;
char udp_server_stack_buffer[UDP_STACK_SIZE];
uint8_t tcp_server_thread_pid;
char tcp_server_stack_buffer[TCP_STACK_SIZE];
uint8_t tcp_cht_pid;
char tcp_cht_stack_buffer[TCP_STACK_SIZE];
typedef struct tcp_msg_t
{
int node_number;
char tcp_string_msg[50];
}tcp_message_t;
tcp_message_t current_message;
void init_tl (char *str)
{
init_transport_layer();
}
void tcp_ch(void)
{
uint32_t state = 0;
msg_t recv_msg;
sockaddr6_t stSockAddr;
msg_receive(&recv_msg);
int SocketFD = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
if (-1 == SocketFD)
{
printf("cannot create socket");
}
memset(&stSockAddr, 0, sizeof(stSockAddr));
stSockAddr.sin6_family = AF_INET6;
stSockAddr.sin6_port = HTONS(1100);
ipv6_init_address(&stSockAddr.sin6_addr, 0xabcd, 0x0, 0x0, 0x0, 0x3612, 0x00ff, 0xfe00, current_message.node_number);
ipv6_print_addr(&stSockAddr.sin6_addr);
if (-1 == connect(SocketFD, &stSockAddr, sizeof(stSockAddr), tcp_cht_pid))
{
printf("connect failed");
close(SocketFD);
}
msg_receive(&recv_msg);
state = recv_msg.content.value;
while (state == 1)
{
printf("Trying to send data!\n");
if (send(SocketFD, (void*) current_message.tcp_string_msg, strlen(current_message.tcp_string_msg)+1, 0) < 0)
{
printf("Could not send %s!\n", current_message.tcp_string_msg);
}
msg_receive(&recv_msg);
state = recv_msg.content.value;
}
close(SocketFD);
// while (1)
// {
// thread_sleep();
// }
}
void init_udp_server(void)
{
sockaddr6_t sa;
char buffer_main[256];
ssize_t recsize;
uint32_t fromlen;
int sock = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
memset(&sa, 0, sizeof sa);
sa.sin6_family = AF_INET;
sa.sin6_port = HTONS(7654);
fromlen = sizeof(sa);
if (-1 == bind(sock, &sa, sizeof(sa), udp_server_thread_pid))
{
printf("Error bind failed!\n");
close(sock);
}
for (;;)
{
recsize = recvfrom(sock, (void *)buffer_main, 256, 0, &sa, &fromlen);
if (recsize < 0)
{
printf("ERROR: recsize < 0!\n");
}
printf("recsize: %i\n ", recsize);
printf("datagram: %s\n", buffer_main);
}
}
void init_tcp_server(void)
{
sockaddr6_t stSockAddr;
int read_bytes = -1;
char buff_msg[MAX_TCP_BUFFER];
int SocketFD = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
if(-1 == SocketFD)
{
perror("can not create socket");
exit(EXIT_FAILURE);
}
memset(&stSockAddr, 0, sizeof(stSockAddr));
stSockAddr.sin6_family = AF_INET6;
stSockAddr.sin6_port = HTONS(1100);
// TODO: HARDCODED! Use one of the IPv6 methods after initializing the node to get the correct ipv6 address!
ipv6_init_address(&stSockAddr.sin6_addr, 0xabcd, 0x0, 0x0, 0x0, 0x3612, 0x00ff, 0xfe00, get_radio_address());
ipv6_print_addr(&stSockAddr.sin6_addr);
if(-1 == bind(SocketFD, &stSockAddr, sizeof(stSockAddr), tcp_server_thread_pid))
{
perror("error bind failed");
close(SocketFD);
exit(EXIT_FAILURE);
}
print_internal_socket(getSocket(SocketFD));
if(-1 == listen(SocketFD, 10))
{
perror("error listen failed");
close(SocketFD);
exit(EXIT_FAILURE);
}
for(;;)
{
// Decide whether a new thread should be used to handle the new connection or the same (other queued
// connections would not be handled!)
read_bytes = -1;
printf("INFO: WAITING FOR INC CONNECTIONS!\n");
int ConnectFD = accept(SocketFD, NULL, 0, tcp_server_thread_pid);
if(0 > ConnectFD)
{
perror("error accept failed");
close(SocketFD);
exit(EXIT_FAILURE);
}
while (read_bytes != 0)
{
read_bytes = recv(ConnectFD, buff_msg, MAX_TCP_BUFFER, 0);
printf("--- Message: %s ---\n", buff_msg);
}
printf("INFO: CLOSING SOCKET!\n");
close(ConnectFD);
}
}
void init_udp_server_thread(char *str)
{
udp_server_thread_pid = thread_create(udp_server_stack_buffer, UDP_STACK_SIZE, PRIORITY_MAIN, CREATE_STACKTEST, init_udp_server, "init_udp_server");
printf("UDP SERVER THREAD PID: %i\n", udp_server_thread_pid);
}
void init_tcp_server_thread(char *str)
{
tcp_server_thread_pid = thread_create(tcp_server_stack_buffer, TCP_STACK_SIZE, PRIORITY_MAIN, CREATE_STACKTEST, init_tcp_server, "init_tcp_server");
printf("TCP SERVER THREAD PID: %i\n", tcp_server_thread_pid);
}
// Init TCP connection handler thread
void init_tcp_cht(char *str)
{
tcp_cht_pid = thread_create( tcp_cht_stack_buffer,
TCP_STACK_SIZE,
PRIORITY_MAIN,
CREATE_STACKTEST,
tcp_ch,
"init_connection_handler");
printf("TCP CONNECTION HANDLER THREAD PID: %i\n", tcp_cht_pid);
}
void send_tcp_msg(char *str)
{
msg_t send_msg;
sscanf(str, "send_tcp %s", current_message.tcp_string_msg);
printf("Message: %s, strcmp: %i\n", current_message.tcp_string_msg, strcmp(current_message.tcp_string_msg, "close"));
if (strcmp(current_message.tcp_string_msg, "close") == 0)
{
send_msg.content.value = 0;
msg_send(&send_msg, tcp_cht_pid, 0);
}
else
{
send_msg.content.value = 1;
msg_send(&send_msg, tcp_cht_pid, 0);
}
}
void connect_tcp(char *str)
{
msg_t send_msg;
sscanf(str, "connect_tcp %i", &current_message.node_number);
send_msg.content.value = 1;
msg_send(&send_msg, tcp_cht_pid, 0);
}
void disconnect_tcp(char *str)
{
msg_t send_msg;
send_msg.content.value = 0;
msg_send(&send_msg, tcp_cht_pid, 0);
}
void init(char *str){
char command;
uint16_t r_addr;
ipv6_addr_t std_addr;
int res = sscanf(str, "init %c %hu", &command, &r_addr);
if(res < 1){
printf("Usage: init {h | r | a | e} radio_address\n");
printf("\th\tinitialize as host\n");
printf("\tr\tinitialize as router\n");
printf("\ta\tinitialize as ad-hoc router\n");
printf("\tb\tinitialize as border router\n\n");
printf("\tradio_address must be an 8 bit integer\n");
}
ipv6_init_address(&std_addr,0xABCD,0,0,0,0x1034,0x00FF,0xFE00,r_addr);
switch (command) {
case 'h':
printf("INFO: Initialize as host on radio address %hu\n", r_addr);
if (r_addr > 255) {
printf("ERROR: radio_address not an 8 bit integer\n");
return;
}
sixlowpan_init(TRANSCEIVER_CC1100,r_addr,0);
break;
case 'r':
printf("INFO: Initialize as router on radio address %hu\n", r_addr);
if (r_addr > 255) {
printf("ERROR: radio_address not an 8 bit integer\n");
return;
}
sixlowpan_init(TRANSCEIVER_CC1100, r_addr,0);
ipv6_init_iface_as_router();
break;
case 'a':
printf("INFO: Initialize as adhoc router on radio address %hu\n", r_addr);
if (r_addr > 255) {
printf("ERROR: radio_address not an 8 bit integer\n");
return;
}
sixlowpan_adhoc_init(TRANSCEIVER_CC1100, &std_addr, r_addr);
break;
case 'b':
printf("INFO: Initialize as border router on radio address %hu\n", r_addr);
if (r_addr > 255) {
printf("ERROR: radio_address not an 8 bit integer\n");
return;
}
res = border_initialize(TRANSCEIVER_CC1100, &std_addr);
switch (res) {
case (SUCCESS): printf("INFO: Border router initialized.\n"); break;
case (SIXLOWERROR_ADDRESS): printf("ERROR: Illegal IP address: ");
ipv6_print_addr(&std_addr); break;
default: printf("ERROR: Unknown error (%d).\n", res); break;
}
break;
default:
printf("ERROR: Unknown command '%c'\n", command);
break;
}
}
void bootstrapping(char *str){
sixlowpan_bootstrapping();
}
void send_packet(char *str){
uint8_t send_buffer[UDP_STACK_SIZE];
uint8_t text[20];
sscanf(str, "send %s", text);
ipv6_hdr_t *test_ipv6_header = ((ipv6_hdr_t*)(&send_buffer));
udp_hdr_t *test_udp_header = ((udp_hdr_t*)(&send_buffer[IPV6_HDR_LEN]));
uint8_t *payload = &send_buffer[IPV6_HDR_LEN+UDP_HDR_LEN];
ipv6_addr_t ipaddr;
ipv6_init_address(&ipaddr, 0xabcd, 0x0, 0x0, 0x0, 0x3612, 0x00ff, 0xfe00, 0x0005);
ipv6_print_addr(&ipaddr);
memcpy(&(test_ipv6_header->destaddr), &ipaddr, 16);
ipv6_get_saddr(&(test_ipv6_header->srcaddr), &(test_ipv6_header->destaddr));
test_ipv6_header->version_trafficclass = IPV6_VER;
test_ipv6_header->trafficclass_flowlabel = 0;
test_ipv6_header->flowlabel = 0;
test_ipv6_header->nextheader = IPPROTO_UDP;
test_ipv6_header->hoplimit = MULTIHOP_HOPLIMIT;
test_ipv6_header->length = sizeof(test_udp_header);
test_udp_header->src_port = 9821;
test_udp_header->dst_port = 7654;
test_udp_header->checksum = 0;
memcpy(payload, text, strlen((char*)text)+1);
test_udp_header->length = 8 + strlen((char*)text)+1;
test_udp_header->checksum = ~udp_csum(test_ipv6_header, test_udp_header);
sixlowpan_send(&ipaddr, (uint8_t*)(test_udp_header), test_udp_header->length, IPPROTO_UDP);
}
void send_udp(char *str)
{
int sock;
sockaddr6_t sa;
ipv6_addr_t ipaddr;
int bytes_sent;
int address;
uint8_t text[20];
sscanf(str, "send_udp %s %i", text, &address);
sock = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
if (-1 == sock)
{
printf("Error Creating Socket!");
exit(EXIT_FAILURE);
}
memset(&sa, 0, sizeof sa);
ipv6_init_address(&ipaddr, 0xabcd, 0x0, 0x0, 0x0, 0x3612, 0x00ff, 0xfe00, (uint16_t)address);
ipv6_print_addr(&ipaddr);
sa.sin6_family = AF_INET;
memcpy(&sa.sin6_addr, &ipaddr, 16);
sa.sin6_port = HTONS(7654);
bytes_sent = sendto(sock, (char*)text, strlen((char*)text)+1, 0, &sa, sizeof sa);
if (bytes_sent < 0)
{
printf("Error sending packet!\n");
}
close(sock);
}
void set_radio_chann(char *str){
uint16_t chann;
int res = sscanf(str, "set_chann %hu", &chann);
if(res < 1){
printf("Usage: set_chann [channel]\n");
}
cc110x_set_channel(chann);
}
void get_r_address(char *str){
printf("radio: %hu\n", cc110x_get_address());
}
void ip(char *str){
ipv6_iface_print_addrs();
}
void context(char *str){
uint8_t i;
lowpan_context_t *context;
for(i = 0; i < LOWPAN_CONTEXT_MAX; i++){
context = lowpan_context_num_lookup(i);
if (context != NULL) {
printf("%2d\tLifetime: %5u\tLength: %3d\t",context->num,context->lifetime,context->length);
ipv6_print_addr(&(context->prefix));
}
}
}
void shows(char *str)
{
print_sockets();
}
void showReas(char *str)
{
printReasBuffers();
}
const shell_command_t shell_commands[] = {
{"init", "", init},
{"addr", "", get_r_address},
{"set_chann", "", set_radio_chann},
{"boot", "", bootstrapping},
{"ip", "", ip},
{"shows", "Show Sockets", shows},
{"show_reas", "Show reassembly Buffers", showReas},
{"context", "", context},
{"init_tl", "", init_tl},
{"init_udp_server_thread", "", init_udp_server_thread},
{"init_tcp_server_thread", "", init_tcp_server_thread},
{"init_tcp_cht", "", init_tcp_cht},
{"connect_tcp", "", connect_tcp},
{"send_tcp", "", send_tcp_msg},
{"send_udp", "", send_udp},
{NULL, NULL, NULL}
};
int main(void) {
printf("6LoWPAN Transport Layers\n");
posix_open(uart0_handler_pid, 0);
init_tl(NULL);
shell_t shell;
shell_init(&shell, shell_commands, uart0_readc, uart0_putc);
shell_run(&shell);
return 0;
}

View File

@ -0,0 +1,13 @@
#!/usr/bin/expect
set timeout 5
spawn board/msba2/tools/bin/pseudoterm $env(PORT)
expect {
"Hello World!" {}
timeout { exit 1 }
}
puts "\nTest successful!\n"

View File

@ -43,3 +43,6 @@ Module transceiver : transceiver.c ;
SubInclude TOP sys net ;
SubInclude TOP sys lib ;
SubInclude TOP sys shell ;
SubInclude TOP sys net sixlowpan ;
SubInclude TOP sys net destiny ;
SubInclude TOP sys net net_help ;

View File

@ -21,7 +21,7 @@ timex_t timex_set(uint32_t seconds, uint32_t microseconds);
*
* @return -1 when a is smaller, 0 if equal, 1 if a is bigger
*/
timex_t timex_sub(const timex_t a, const timex_t b);
int timex_cmp(const timex_t a, const timex_t b);
/**
* @brief Corrects timex_t structure so that microseconds < 1000000

View File

@ -10,6 +10,8 @@
#define TRANSCEIVER_STACK_SIZE (512)
#endif
#define PAYLOAD_SIZE (58)
/* The maximum of threads to register */
#define TRANSCEIVER_MAX_REGISTERED (4)

View File

@ -29,3 +29,4 @@ SubDir TOP sys net ;
Module protocol_multiplex : protocol-multiplex.c ;
# SubInclude TOP net ;

5
sys/net/destiny/Jamfile Normal file
View File

@ -0,0 +1,5 @@
SubDir TOP sys net destiny ;
# HDRS += $(TOP)/sys/net/destiny/ ;
Module destiny : destiny.c udp.c tcp.c socket.c : vtimer 6lowpan net_help ;

28
sys/net/destiny/destiny.c Normal file
View File

@ -0,0 +1,28 @@
/*
* destiny.c
*
* Created on: 03.09.2011
* Author: Oliver
*/
#include <thread.h>
#include <stdio.h>
#include <string.h>
#include "udp.h"
#include "tcp.h"
#include "socket.h"
void init_transport_layer(void)
{
printf("Initiating Transport Layer packages.\n");
// SOCKETS
memset(sockets, 0, MAX_SOCKETS*sizeof(socket_internal_t));
// UDP
int udp_thread_pid = thread_create(udp_stack_buffer, UDP_STACK_SIZE, PRIORITY_MAIN, CREATE_STACKTEST, udp_packet_handler, "udp_packet_handler");
set_udp_packet_handler_pid(udp_thread_pid);
// TCP
int tcp_thread_pid = thread_create(tcp_stack_buffer, TCP_STACK_SIZE, PRIORITY_MAIN, CREATE_STACKTEST, tcp_packet_handler, "tcp_packet_handler");
set_tcp_packet_handler_pid(tcp_thread_pid);
}

13
sys/net/destiny/destiny.h Normal file
View File

@ -0,0 +1,13 @@
/*
* destiny.h
*
* Created on: 03.09.2011
* Author: Oliver
*/
#ifndef DESTINY_H_
#define DESTINY_H_
void init_transport_layer(void);
#endif /* DESTINY_H_ */

133
sys/net/destiny/in.h Normal file
View File

@ -0,0 +1,133 @@
/*
* in.h
*
* Created on: 16.09.2011
* Author: Oliver
*/
#ifndef IN_H_
#define IN_H_
/*
* Constants and structures defined by the internet system,
* Per RFC 790, September 1981, and numerous additions.
*/
/*
* Protocols (RFC 1700)
*/
#define IPPROTO_IP 0 /* dummy for IP */
#define IPPROTO_HOPOPTS 0 /* IP6 hop-by-hop options */
#define IPPROTO_ICMP 1 /* control message protocol */
#define IPPROTO_IGMP 2 /* group mgmt protocol */
#define IPPROTO_GGP 3 /* gateway^2 (deprecated) */
#define IPPROTO_IPV4 4 /* IPv4 encapsulation */
#define IPPROTO_IPIP IPPROTO_IPV4 /* for compatibility */
#define IPPROTO_TCP 6 /* tcp */
#define IPPROTO_ST 7 /* Stream protocol II */
#define IPPROTO_EGP 8 /* exterior gateway protocol */
#define IPPROTO_PIGP 9 /* private interior gateway */
#define IPPROTO_RCCMON 10 /* BBN RCC Monitoring */
#define IPPROTO_NVPII 11 /* network voice protocol*/
#define IPPROTO_PUP 12 /* pup */
#define IPPROTO_ARGUS 13 /* Argus */
#define IPPROTO_EMCON 14 /* EMCON */
#define IPPROTO_XNET 15 /* Cross Net Debugger */
#define IPPROTO_CHAOS 16 /* Chaos*/
#define IPPROTO_UDP 17 /* user datagram protocol */
#define IPPROTO_MUX 18 /* Multiplexing */
#define IPPROTO_MEAS 19 /* DCN Measurement Subsystems */
#define IPPROTO_HMP 20 /* Host Monitoring */
#define IPPROTO_PRM 21 /* Packet Radio Measurement */
#define IPPROTO_IDP 22 /* xns idp */
#define IPPROTO_TRUNK1 23 /* Trunk-1 */
#define IPPROTO_TRUNK2 24 /* Trunk-2 */
#define IPPROTO_LEAF1 25 /* Leaf-1 */
#define IPPROTO_LEAF2 26 /* Leaf-2 */
#define IPPROTO_RDP 27 /* Reliable Data */
#define IPPROTO_IRTP 28 /* Reliable Transaction */
#define IPPROTO_TP 29 /* tp-4 w/ class negotiation */
#define IPPROTO_BLT 30 /* Bulk Data Transfer */
#define IPPROTO_NSP 31 /* Network Services */
#define IPPROTO_INP 32 /* Merit Internodal */
#define IPPROTO_SEP 33 /* Sequential Exchange */
#define IPPROTO_3PC 34 /* Third Party Connect */
#define IPPROTO_IDPR 35 /* InterDomain Policy Routing */
#define IPPROTO_XTP 36 /* XTP */
#define IPPROTO_DDP 37 /* Datagram Delivery */
#define IPPROTO_CMTP 38 /* Control Message Transport */
#define IPPROTO_TPXX 39 /* TP++ Transport */
#define IPPROTO_IL 40 /* IL transport protocol */
#define IPPROTO_IPV6 41 /* IP6 header */
#define IPPROTO_SDRP 42 /* Source Demand Routing */
#define IPPROTO_ROUTING 43 /* IP6 routing header */
#define IPPROTO_FRAGMENT 44 /* IP6 fragmentation header */
#define IPPROTO_IDRP 45 /* InterDomain Routing*/
#define IPPROTO_RSVP 46 /* resource reservation */
#define IPPROTO_GRE 47 /* General Routing Encap. */
#define IPPROTO_MHRP 48 /* Mobile Host Routing */
#define IPPROTO_BHA 49 /* BHA */
#define IPPROTO_ESP 50 /* IP6 Encap Sec. Payload */
#define IPPROTO_AH 51 /* IP6 Auth Header */
#define IPPROTO_INLSP 52 /* Integ. Net Layer Security */
#define IPPROTO_SWIPE 53 /* IP with encryption */
#define IPPROTO_NHRP 54 /* Next Hop Resolution */
/* 55-57: Unassigned */
#define IPPROTO_ICMPV6 58 /* ICMP6 */
#define IPPROTO_NONE 59 /* IP6 no next header */
#define IPPROTO_DSTOPTS 60 /* IP6 destination option */
#define IPPROTO_AHIP 61 /* any host internal protocol */
#define IPPROTO_CFTP 62 /* CFTP */
#define IPPROTO_HELLO 63 /* "hello" routing protocol */
#define IPPROTO_SATEXPAK 64 /* SATNET/Backroom EXPAK */
#define IPPROTO_KRYPTOLAN 65 /* Kryptolan */
#define IPPROTO_RVD 66 /* Remote Virtual Disk */
#define IPPROTO_IPPC 67 /* Pluribus Packet Core */
#define IPPROTO_ADFS 68 /* Any distributed FS */
#define IPPROTO_SATMON 69 /* Satnet Monitoring */
#define IPPROTO_VISA 70 /* VISA Protocol */
#define IPPROTO_IPCV 71 /* Packet Core Utility */
#define IPPROTO_CPNX 72 /* Comp. Prot. Net. Executive */
#define IPPROTO_CPHB 73 /* Comp. Prot. HeartBeat */
#define IPPROTO_WSN 74 /* Wang Span Network */
#define IPPROTO_PVP 75 /* Packet Video Protocol */
#define IPPROTO_BRSATMON 76 /* BackRoom SATNET Monitoring */
#define IPPROTO_ND 77 /* Sun net disk proto (temp.) */
#define IPPROTO_WBMON 78 /* WIDEBAND Monitoring */
#define IPPROTO_WBEXPAK 79 /* WIDEBAND EXPAK */
#define IPPROTO_EON 80 /* ISO cnlp */
#define IPPROTO_VMTP 81 /* VMTP */
#define IPPROTO_SVMTP 82 /* Secure VMTP */
#define IPPROTO_VINES 83 /* Banyon VINES */
#define IPPROTO_TTP 84 /* TTP */
#define IPPROTO_IGP 85 /* NSFNET-IGP */
#define IPPROTO_DGP 86 /* dissimilar gateway prot. */
#define IPPROTO_TCF 87 /* TCF */
#define IPPROTO_IGRP 88 /* Cisco/GXS IGRP */
#define IPPROTO_OSPFIGP 89 /* OSPFIGP */
#define IPPROTO_SRPC 90 /* Strite RPC protocol */
#define IPPROTO_LARP 91 /* Locus Address Resoloution */
#define IPPROTO_MTP 92 /* Multicast Transport */
#define IPPROTO_AX25 93 /* AX.25 Frames */
#define IPPROTO_IPEIP 94 /* IP encapsulated in IP */
#define IPPROTO_MICP 95 /* Mobile Int.ing control */
#define IPPROTO_SCCSP 96 /* Semaphore Comm. security */
#define IPPROTO_ETHERIP 97 /* Ethernet IP encapsulation */
#define IPPROTO_ENCAP 98 /* encapsulation header */
#define IPPROTO_APES 99 /* any private encr. scheme */
#define IPPROTO_GMTP 100 /* GMTP*/
#define IPPROTO_IPCOMP 108 /* payload compression (IPComp) */
/* 101-254: Partly Unassigned */
#define IPPROTO_PIM 103 /* Protocol Independent Mcast */
#define IPPROTO_PGM 113 /* PGM */
/* 255: Reserved */
/* BSD Private, local use, namespace incursion */
#define IPPROTO_DIVERT 254 /* divert pseudo-protocol */
#define IPPROTO_RAW 255 /* raw IP packet */
#define IPPROTO_MAX 256
/* last return value of *_input(), meaning "all job for this pkt is done". */
#define IPPROTO_DONE 257
#define IN_LOOPBACKNET 127 /* official! */
#endif /* IN_H_ */

897
sys/net/destiny/socket.c Normal file
View File

@ -0,0 +1,897 @@
/*
* socket.c
*
* Created on: 16.09.2011
* Author: Oliver
*/
#include <thread.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "udp.h"
#include "tcp.h"
#include "socket.h"
#include "sys/net/net_help/net_help.h"
#include "sys/net/net_help/msg_help.h"
void print_tcp_flags (tcp_hdr_t *tcp_header)
{
printf("FLAGS: ");
switch(tcp_header->reserved_flags)
{
case TCP_ACK:
{
printf("ACK ");
break;
}
case TCP_RST:
{
printf("RST ");
break;
}
case TCP_SYN:
{
printf("SYN ");
break;
}
case TCP_FIN:
{
printf("FIN ");
break;
}
case TCP_URG_PSH:
{
printf("URG PSH ");
break;
}
case TCP_SYN_ACK:
{
printf("SYN ACK ");
break;
}
case TCP_FIN_ACK:
{
printf("FIN ACK ");
break;
}
}
printf("\n\n");
}
void print_tcp_status(int in_or_out, ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header)
{
printf("--- %s TCP packet: ---\n", (in_or_out == INC_PACKET ? "Incoming" : "Outgoing"));
printf("IPv6 Source:");
ipv6_print_addr(&ipv6_header->srcaddr);
printf("IPv6 Dest:");
ipv6_print_addr(&ipv6_header->destaddr);
printf("TCP Length: %i\n", ipv6_header->length-TCP_HDR_LEN);
printf("Source Port: %i, Dest. Port: %i\n", tcp_header->src_port, tcp_header->dst_port);
printf("ACK: %li, SEQ: %li, Window: %i\n", tcp_header->ack_nr, tcp_header->seq_nr, tcp_header->window);
print_tcp_flags(tcp_header);
}
void print_socket(socket_t *current_socket)
{
printf("Domain: %i, Type: %i, Protocol: %i \n",
current_socket->domain,
current_socket->type,
current_socket->protocol);
// printf("Local address: \tPort: %i, \tFamily: %i\n",
// NTOHS(current_socket->local_address.sin6_port),
// current_socket->local_address.sin6_family);
ipv6_print_addr(&current_socket->local_address.sin6_addr);
// printf("Foreign address: \tPort: %i, \tFamily: %i\n",
// NTOHS(current_socket->foreign_address.sin6_port),
// current_socket->foreign_address.sin6_family);
ipv6_print_addr(&current_socket->foreign_address.sin6_addr);
// printf("Local TCP status: ACK: %li, SEQ: %li, STATE: %i\n",
// current_socket->local_tcp_status.ack_nr,
// current_socket->local_tcp_status.seq_nr,
// current_socket->local_tcp_status.state);
// printf("Foreign TCP status: ACK: %li, SEQ: %li, STATE: %i\n",
// current_socket->foreign_tcp_status.ack_nr,
// current_socket->foreign_tcp_status.seq_nr,
// current_socket->foreign_tcp_status.state);
}
void print_internal_socket(socket_internal_t *current_socket_internal)
{
socket_t *current_socket = &current_socket_internal->in_socket;
printf("\n--------------------------\n");
printf("ID: %i, PID: %i\n", current_socket_internal->socket_id, current_socket_internal->pid);
print_socket(current_socket);
printf("\n--------------------------\n");
}
socket_internal_t *getSocket(uint8_t s)
{
if (exists_socket(s))
{
return &(sockets[s-1]);
}
else
{
return NULL;
}
}
void print_sockets(void)
{
int i;
printf("\n--- Socket list: ---\n");
for (i = 1; i < MAX_SOCKETS+1; i++)
{
if(getSocket(i) != NULL)
{
print_internal_socket(getSocket(i));
}
}
}
bool exists_socket(uint8_t socket)
{
if (sockets[socket-1].socket_id == 0)
{
return false;
}
else
{
return true;
}
}
void close_socket(socket_t *current_socket)
{
memset(current_socket, 0, sizeof(current_socket));
}
bool isUDPSocket(uint8_t s)
{
if ( (exists_socket(s)) &&
(getSocket(s)->in_socket.domain == PF_INET6) &&
(getSocket(s)->in_socket.type == SOCK_DGRAM) &&
((getSocket(s)->in_socket.protocol == IPPROTO_UDP) ||
(getSocket(s)->in_socket.protocol == 0)))
return true;
else
return false;
}
bool isTCPSocket(uint8_t s)
{
if ( (exists_socket(s)) &&
(getSocket(s)->in_socket.domain == PF_INET6) &&
(getSocket(s)->in_socket.type == SOCK_STREAM) &&
((getSocket(s)->in_socket.protocol == IPPROTO_TCP) ||
(getSocket(s)->in_socket.protocol == 0)))
return true;
else
return false;
}
int bind_udp_socket(int s, sockaddr6_t *name, int namelen, uint8_t pid)
{
int i;
if (!exists_socket(s))
{
return -1;
}
for (i = 1; i < MAX_SOCKETS+1; i++)
{
if (isUDPSocket(i) && (getSocket(i)->in_socket.local_address.sin6_port == name->sin6_port))
{
return -1;
}
}
memcpy(&getSocket(s)->in_socket.local_address, name, namelen);
getSocket(s)->pid = pid;
return 1;
}
int bind_tcp_socket(int s, sockaddr6_t *name, int namelen, uint8_t pid)
{
int i;
if (!exists_socket(s))
{
return -1;
}
for (i = 1; i < MAX_SOCKETS+1; i++)
{
if (isTCPSocket(i) && (getSocket(i)->in_socket.local_address.sin6_port == name->sin6_port))
{
return -1;
}
}
memcpy(&getSocket(s)->in_socket.local_address, name, namelen);
getSocket(s)->pid = pid;
return 1;
}
int socket(int domain, int type, int protocol)
{
int i = 1;
while (getSocket(i) != NULL)
{
i++;
}
if (i > MAX_SOCKETS+1)
{
return -1;
}
else
{
socket_t *current_socket = &sockets[i-1].in_socket;
sockets[i-1].socket_id = i;
current_socket->domain = domain;
current_socket->type = type;
current_socket->protocol = protocol;
current_socket->local_tcp_status.state = CLOSED;
current_socket->foreign_tcp_status.state = UNKNOWN;
return sockets[i-1].socket_id;
}
}
socket_internal_t *get_udp_socket(ipv6_hdr_t *ipv6_header, udp_hdr_t *udp_header)
{
uint8_t i = 1;
while (i < MAX_SOCKETS+1)
{
if ( isUDPSocket(i) &&
(getSocket(i)->in_socket.local_address.sin6_port == udp_header->dst_port))
{
return getSocket(i);
}
i++;
}
return NULL;
}
socket_internal_t *get_tcp_socket(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header)
{
uint8_t i = 1;
socket_internal_t *current_socket = NULL;
socket_internal_t *listening_socket = NULL;
uint8_t compare[16];
memset(compare, 0, 16);
while (i < MAX_SOCKETS+1)
{
current_socket = getSocket(i);
// Check for matching 4 touple
if( isTCPSocket(i) &&
(ipv6_get_addr_match(&current_socket->in_socket.local_address.sin6_addr, &ipv6_header->destaddr) == 128) &&
(current_socket->in_socket.local_address.sin6_port == tcp_header->dst_port) &&
(ipv6_get_addr_match(&current_socket->in_socket.foreign_address.sin6_addr, &ipv6_header->srcaddr) == 128) &&
(current_socket->in_socket.foreign_address.sin6_port == tcp_header->src_port))
{
return current_socket;
}
// TODO: Figure out a better strategy of using *.LOCAL_ADRESS than using the last Byte
else if ( isTCPSocket(i) &&
((current_socket->in_socket.local_tcp_status.state == LISTEN) || (current_socket->in_socket.local_tcp_status.state == SYN_RCVD)) &&
(current_socket->in_socket.local_address.sin6_addr.uint8[15] == ipv6_header->destaddr.uint8[15]) &&
(current_socket->in_socket.local_address.sin6_port == tcp_header->dst_port) &&
(current_socket->in_socket.foreign_address.sin6_addr.uint8[15] == 0x00) &&
(current_socket->in_socket.foreign_address.sin6_port == 0))
{
listening_socket = current_socket;
}
i++;
}
// Return either NULL if nothing was matched or the listening 2 touple socket
return listening_socket;
}
uint16_t get_free_source_port(uint8_t protocol)
{
int i;
uint16_t biggest_port = EPHEMERAL_PORTS-1;
// Remember biggest ephemeral port number used so far and add 1
for (i = 0; i < MAX_SOCKETS; i++)
{
if ((sockets[i].in_socket.protocol == protocol) && (sockets[i].in_socket.local_address.sin6_port > biggest_port))
{
biggest_port = sockets[i].in_socket.local_address.sin6_port;
}
}
return biggest_port + 1;
}
void set_tcp_status(tcp_socket_status_t *tcp_socket_status, uint32_t ack_nr, uint8_t mss, uint32_t seq_nr, uint8_t state, uint16_t window)
{
tcp_socket_status->ack_nr = ack_nr;
tcp_socket_status->mss = mss;
tcp_socket_status->seq_nr = seq_nr;
tcp_socket_status->state = state;
tcp_socket_status->window = window;
}
void set_socket_address(sockaddr6_t *sockaddr, uint8_t sin6_family, uint16_t sin6_port, uint32_t sin6_flowinfo, ipv6_addr_t *sin6_addr)
{
sockaddr->sin6_family = sin6_family;
sockaddr->sin6_port = sin6_port;
sockaddr->sin6_flowinfo = sin6_flowinfo;
memcpy(&sockaddr->sin6_addr, sin6_addr, 16);
}
void set_tcp_packet(tcp_hdr_t *tcp_hdr, uint16_t src_port, uint16_t dst_port, uint32_t seq_nr, uint32_t ack_nr,
uint8_t dataOffset_reserved, uint8_t reserved_flags, uint16_t window, uint16_t checksum, uint16_t urg_pointer)
{
tcp_hdr->ack_nr = ack_nr;
tcp_hdr->checksum = checksum;
tcp_hdr->dataOffset_reserved = dataOffset_reserved;
tcp_hdr->dst_port = dst_port;
tcp_hdr->reserved_flags = reserved_flags;
tcp_hdr->seq_nr = seq_nr;
tcp_hdr->src_port = src_port;
tcp_hdr->urg_pointer = urg_pointer;
tcp_hdr->window = window;
}
// Check for consistent ACK and SEQ number
int check_tcp_consistency(socket_t *current_tcp_socket, tcp_hdr_t *tcp_header)
{
if (IS_TCP_ACK(tcp_header->reserved_flags))
{
if(tcp_header->ack_nr > (current_tcp_socket->local_tcp_status.seq_nr+1))
{
// ACK of not yet sent byte, discard
return ACK_NO_TOO_BIG;
}
else if (tcp_header->ack_nr < (current_tcp_socket->local_tcp_status.seq_nr+1))
{
// ACK of previous segments, maybe dropped?
return ACK_NO_TOO_SMALL;
}
}
if ((current_tcp_socket->foreign_tcp_status.seq_nr > 0) && (tcp_header->seq_nr <= current_tcp_socket->foreign_tcp_status.seq_nr))
{
// segment repetition, maybe ACK got lost?
return SEQ_NO_SAME;
}
return PACKET_OK;
}
int send_tcp(sockaddr6_t *addr, socket_t *current_tcp_socket, tcp_hdr_t *current_tcp_packet, ipv6_hdr_t *temp_ipv6_header, uint8_t flags, uint8_t payload_length)
{
if (addr != NULL)
{
// Local address information
ipv6_addr_t src_addr;
ipv6_get_saddr(&src_addr, &addr->sin6_addr);
set_socket_address(&current_tcp_socket->local_address, PF_INET6, HTONS(get_free_source_port(IPPROTO_TCP)), 0, &src_addr);
// Foreign address information
set_socket_address(&current_tcp_socket->foreign_address, addr->sin6_family, addr->sin6_port, addr->sin6_flowinfo, &addr->sin6_addr);
}
set_tcp_packet(current_tcp_packet, current_tcp_socket->local_address.sin6_port, current_tcp_socket->foreign_address.sin6_port,
current_tcp_socket->local_tcp_status.seq_nr, current_tcp_socket->local_tcp_status.ack_nr, 0, flags, current_tcp_socket->local_tcp_status.window, 0, 0);
// Fill IPv6 Header
memcpy(&(temp_ipv6_header->destaddr), &current_tcp_socket->foreign_address.sin6_addr, 16);
memcpy(&(temp_ipv6_header->srcaddr), &current_tcp_socket->local_address.sin6_addr, 16);
temp_ipv6_header->length = TCP_HDR_LEN + payload_length;
current_tcp_packet->checksum = ~tcp_csum(temp_ipv6_header, current_tcp_packet);
// send TCP SYN packet
sixlowpan_send(&current_tcp_socket->foreign_address.sin6_addr, (uint8_t*)(current_tcp_packet), TCP_HDR_LEN+payload_length, IPPROTO_TCP);
return 1;
}
int connect(int socket, sockaddr6_t *addr, uint32_t addrlen, uint8_t tcp_client_thread)
{
// Variables
socket_internal_t *current_int_tcp_socket;
socket_t *current_tcp_socket;
msg_t msg_from_server, msg_reply_fin;
uint8_t send_buffer[BUFFER_SIZE];
ipv6_hdr_t *temp_ipv6_header = ((ipv6_hdr_t*)(&send_buffer));
tcp_hdr_t *current_tcp_packet = ((tcp_hdr_t*)(&send_buffer[IPV6_HDR_LEN]));
// Check if socket exists
current_int_tcp_socket = getSocket(socket);
if (current_int_tcp_socket == NULL)
{
return -1;
}
current_tcp_socket = &current_int_tcp_socket->in_socket;
// Set client thread process ID
getSocket(socket)->pid = tcp_client_thread;
// TODO: random number should be generated like common BSD socket implementation with a periodic timer increasing it
// TODO: Add TCP MSS option field
// Fill lcoal TCP socket information
srand(addr->sin6_port);
set_tcp_status(&current_tcp_socket->local_tcp_status, 0, STATIC_MSS, rand(), SYN_SENT, STATIC_WINDOW);
// Fill foreign TCP socket information
set_tcp_status(&current_tcp_socket->foreign_tcp_status, 0, 0, 0, UNKNOWN, 0);
// Send packet
send_tcp(addr, current_tcp_socket, current_tcp_packet, temp_ipv6_header, TCP_SYN, 0);
// wait for SYN ACK
net_msg_receive(&msg_from_server, FID_SOCKET_CONNECT);
// Read packet content
tcp_hdr_t *tcp_header = ((tcp_hdr_t*)(msg_from_server.content.ptr));
// Check for consistency
if (check_tcp_consistency(current_tcp_socket, tcp_header) == -1)
{
printf("TCP packets not consistent!\n");
}
// Got SYN ACK from Server
// Refresh foreign TCP socket information
set_tcp_status(&current_tcp_socket->foreign_tcp_status, tcp_header->ack_nr, STATIC_MSS, tcp_header->seq_nr, ESTABLISHED, tcp_header->window);
// Refresh local TCP socket information
set_tcp_status(&current_tcp_socket->local_tcp_status, tcp_header->seq_nr + 1, STATIC_MSS, tcp_header->ack_nr, ESTABLISHED, STATIC_WINDOW);
// Send packet
send_tcp(NULL, current_tcp_socket, current_tcp_packet, temp_ipv6_header, TCP_ACK, 0);
net_msg_reply(&msg_from_server, &msg_reply_fin, FID_TCP_SYN_ACK);
return 0;
}
int32_t send(int s, void *msg, uint64_t len, int flags)
{
// Variables
int32_t sent_bytes = 0;
socket_internal_t *current_int_tcp_socket;
socket_t *current_tcp_socket;
uint8_t send_buffer[BUFFER_SIZE];
ipv6_hdr_t *temp_ipv6_header = ((ipv6_hdr_t*)(&send_buffer));
tcp_hdr_t *current_tcp_packet = ((tcp_hdr_t*)(&send_buffer[IPV6_HDR_LEN]));
// Check if socket exists and is TCP socket
if (!isTCPSocket(s))
{
return -1;
}
current_int_tcp_socket = getSocket(s);
current_tcp_socket = &current_int_tcp_socket->in_socket;
// Check for ESTABLISHED STATE
if (current_tcp_socket->local_tcp_status.state != ESTABLISHED)
{
return -1;
}
// Refresh local TCP socket information
current_tcp_socket->local_tcp_status.seq_nr = current_tcp_socket->local_tcp_status.seq_nr + len;
// Add packet data
if (len > current_tcp_socket->foreign_tcp_status.window)
{
memcpy(&send_buffer[IPV6_HDR_LEN+TCP_HDR_LEN], msg, current_tcp_socket->foreign_tcp_status.window);
sent_bytes = current_tcp_socket->foreign_tcp_status.window;
}
else
{
memcpy(&send_buffer[IPV6_HDR_LEN+TCP_HDR_LEN], msg, len);
sent_bytes = len;
}
send_tcp(NULL, current_tcp_socket, current_tcp_packet, temp_ipv6_header, 0, sent_bytes);
return sent_bytes;
}
uint8_t read_from_socket(socket_internal_t *current_int_tcp_socket, void *buf, int len)
{
if (len > current_int_tcp_socket->tcp_input_buffer_end)
{
uint8_t read_bytes = current_int_tcp_socket->tcp_input_buffer_end;
memcpy(buf, current_int_tcp_socket->tcp_input_buffer, current_int_tcp_socket->tcp_input_buffer_end);
current_int_tcp_socket->tcp_input_buffer_end = 0;
current_int_tcp_socket->in_socket.local_tcp_status.window += read_bytes;
return read_bytes;
}
else
{
memcpy(buf, current_int_tcp_socket->tcp_input_buffer, len);
memmove(current_int_tcp_socket->tcp_input_buffer, (current_int_tcp_socket->tcp_input_buffer+len), current_int_tcp_socket->tcp_input_buffer_end-len);
current_int_tcp_socket->tcp_input_buffer_end = current_int_tcp_socket->tcp_input_buffer_end-len;
current_int_tcp_socket->in_socket.local_tcp_status.window += len;
return len;
}
}
int32_t recv(int s, void *buf, uint64_t len, int flags)
{
// Variables
msg_t m_recv;
socket_internal_t *current_int_tcp_socket;
socket_t *current_tcp_socket;
// Check if socket exists
if (!isTCPSocket(s))
{
printf("INFO: NO TCP SOCKET!\n");
return 0;
}
current_int_tcp_socket = getSocket(s);
current_tcp_socket = &current_int_tcp_socket->in_socket;
if (current_int_tcp_socket->tcp_input_buffer_end > 0)
{
return read_from_socket(current_int_tcp_socket, buf, len);
}
net_msg_receive(&m_recv, FID_SOCKET_RECV);
if (current_int_tcp_socket->tcp_input_buffer_end > 0)
{
return read_from_socket(current_int_tcp_socket, buf, len);
}
// Received FIN
if (m_recv.content.value == CLOSE_CONN)
{
// Sent FIN_ACK, wait for ACK
net_msg_receive(&m_recv, FID_SOCKET_RECV);
// Received ACK, return with closed socket!
return 0;
}
return -1;
}
int32_t recvfrom(int s, void *buf, uint64_t len, int flags, sockaddr6_t *from, uint32_t *fromlen)
{
if (isUDPSocket(s))
{
msg_t m_recv, m_send;
ipv6_hdr_t *ipv6_header;
udp_hdr_t *udp_header;
uint8_t *payload;
net_msg_receive(&m_recv, FID_SOCKET_RECV_FROM);
ipv6_header = ((ipv6_hdr_t*)m_recv.content.ptr);
udp_header = ((udp_hdr_t*)(m_recv.content.ptr + IPV6_HDR_LEN));
payload = (uint8_t*)(m_recv.content.ptr + IPV6_HDR_LEN+UDP_HDR_LEN);
memset(buf, 0, len);
memcpy(buf, payload, udp_header->length);
memcpy(&from->sin6_addr, &ipv6_header->srcaddr, 16);
from->sin6_family = AF_INET6;
from->sin6_flowinfo = 0;
from->sin6_port = udp_header->src_port;
memcpy(fromlen, (void*)(sizeof(sockaddr6_t)), sizeof(fromlen));
net_msg_reply(&m_recv, &m_send, FID_UDP_PH);
return udp_header->length;
}
else if (isTCPSocket(s))
{
return recv(s, buf, len, flags);
}
else
{
printf("Socket Type not supported!\n");
return -1;
}
}
int32_t sendto(int s, void *msg, uint64_t len, int flags, sockaddr6_t *to, uint32_t tolen)
{
if (isUDPSocket(s) && (getSocket(s)->in_socket.foreign_address.sin6_port == 0))
{
uint8_t send_buffer[BUFFER_SIZE];
ipv6_hdr_t *temp_ipv6_header = ((ipv6_hdr_t*)(&send_buffer));
udp_hdr_t *current_udp_packet = ((udp_hdr_t*)(&send_buffer[IPV6_HDR_LEN]));
uint8_t *payload = &send_buffer[IPV6_HDR_LEN+UDP_HDR_LEN];
ipv6_print_addr(&to->sin6_addr);
memcpy(&(temp_ipv6_header->destaddr), &to->sin6_addr, 16);
ipv6_get_saddr(&(temp_ipv6_header->srcaddr), &(temp_ipv6_header->destaddr));
current_udp_packet->src_port = get_free_source_port(IPPROTO_UDP);
current_udp_packet->dst_port = to->sin6_port;
current_udp_packet->checksum = 0;
memcpy(payload, msg, len);
current_udp_packet->length = UDP_HDR_LEN + len;
temp_ipv6_header->length = UDP_HDR_LEN + len;
current_udp_packet->checksum = ~udp_csum(temp_ipv6_header, current_udp_packet);
sixlowpan_send(&to->sin6_addr, (uint8_t*)(current_udp_packet), current_udp_packet->length, IPPROTO_UDP);
return current_udp_packet->length;
}
else
{
return -1;
}
}
int close(int s)
{
socket_internal_t *current_socket = getSocket(s);
if (current_socket != NULL)
{
// Variables
msg_t m_recv;
socket_t *current_tcp_socket;
uint8_t send_buffer[BUFFER_SIZE];
ipv6_hdr_t *temp_ipv6_header = ((ipv6_hdr_t*)(&send_buffer));
tcp_hdr_t *current_tcp_packet = ((tcp_hdr_t*)(&send_buffer[IPV6_HDR_LEN]));
// Check if socket exists and is TCP socket
if (!isTCPSocket(s))
{
return -1;
}
current_tcp_socket = &current_socket->in_socket;
// Check for ESTABLISHED STATE
if (current_tcp_socket->local_tcp_status.state != ESTABLISHED)
{
return -1;
}
// Refresh local TCP socket information
current_tcp_socket->local_tcp_status.seq_nr++;
current_tcp_socket->local_tcp_status.state = FIN_WAIT_1;
send_tcp(NULL, current_tcp_socket, current_tcp_packet, temp_ipv6_header, TCP_FIN, 0);
net_msg_receive(&m_recv, FID_SOCKET_CLOSE);
return 1;
}
else
{
return -1;
}
}
int bind(int s, sockaddr6_t *name, int namelen, uint8_t pid)
{
if (exists_socket(s))
{
socket_t *current_socket = &getSocket(s)->in_socket;
switch (current_socket->domain)
{
case (PF_INET):
{
// Not provided
return -1;
break;
}
case (PF_INET6):
{
switch (current_socket->type)
{
// TCP
case (SOCK_STREAM):
{
if ((current_socket->protocol == 0) || (current_socket->protocol == IPPROTO_TCP))
{
return bind_tcp_socket(s, name, namelen, pid);
break;
}
else
{
return -1;
break;
}
break;
}
// UDP
case (SOCK_DGRAM):
{
if ((current_socket->protocol == 0) || (current_socket->protocol == IPPROTO_UDP))
{
return bind_udp_socket(s, name, namelen, pid);
break;
}
else
{
return -1;
break;
}
break;
}
case (SOCK_SEQPACKET):
{
// not provided
return -1;
break;
}
case (SOCK_RAW):
{
// not provided
return -1;
break;
}
default:
{
return -1;
break;
}
}
break;
}
case (PF_UNIX):
{
// Not provided
return -1;
break;
}
}
}
else
{
printf("SOCKET DOES NOT EXIST!\n");
return -1;
}
return -1;
}
int listen(int s, int backlog)
{
if (isTCPSocket(s) && getSocket(s)->in_socket.local_tcp_status.state == CLOSED)
{
socket_internal_t *current_socket = getSocket(s);
current_socket->in_socket.local_tcp_status.state = LISTEN;
memset(current_socket->queued_sockets, 0, MAX_QUEUED_SOCKETS*sizeof(socket_t));
return 0;
}
else
{
return -1;
}
}
socket_t *getWaitingConnectionSocket(int socket)
{
int i;
for (i = 0; i < MAX_QUEUED_SOCKETS; i++)
{
if (getSocket(socket)->queued_sockets[i].local_tcp_status.state == SYN_RCVD)
{
return &getSocket(socket)->queued_sockets[i];
}
}
return NULL;
}
int handle_new_tcp_connection(socket_t *current_queued_socket, socket_internal_t *server_socket, uint8_t pid)
{
// Got new connection request (SYN), get new socket number and establish connection (send SYN ACK)
int new_socket;
msg_t msg_recv_client_ack, msg_send_client_ack;
socket_internal_t *current_new_socket;
uint8_t send_buffer[BUFFER_SIZE], consistency;
ipv6_hdr_t *temp_ipv6_header = ((ipv6_hdr_t*)(&send_buffer));
tcp_hdr_t *syn_ack_packet = ((tcp_hdr_t*)(&send_buffer[IPV6_HDR_LEN]));
// Set status of internal socket to SYN_RCVD until connection with second socket is established!
server_socket->in_socket.local_tcp_status.state = SYN_RCVD;
// Fill SYN ACK TCP packet, still use queued socket for port number until connection is completely established!
// Otherwise the program doesnt return to this function and instead trys to call the new registered thread
// which isnt prepared to complete the threeway handshake process!
set_tcp_packet(syn_ack_packet, server_socket->in_socket.local_address.sin6_port, current_queued_socket->foreign_address.sin6_port,
current_queued_socket->local_tcp_status.seq_nr, current_queued_socket->local_tcp_status.ack_nr, 0, TCP_SYN_ACK,
current_queued_socket->local_tcp_status.window, 0, 0);
// Specify IPV6 target address and choose outgoing interface source address
memcpy(&(temp_ipv6_header->destaddr), &current_queued_socket->foreign_address.sin6_addr, 16);
ipv6_get_saddr(&(temp_ipv6_header->srcaddr), &(temp_ipv6_header->destaddr));
temp_ipv6_header->length = TCP_HDR_LEN;
syn_ack_packet->checksum = ~tcp_csum(temp_ipv6_header, syn_ack_packet);
sixlowpan_send(&current_queued_socket->foreign_address.sin6_addr, (uint8_t*)(syn_ack_packet), TCP_HDR_LEN, IPPROTO_TCP);
// wait for ACK from Client
net_msg_receive(&msg_recv_client_ack, FID_SOCKET_HANDLE_NEW_TCP_CON);
tcp_hdr_t *tcp_header;
tcp_header = ((tcp_hdr_t*)(msg_recv_client_ack.content.ptr));
// Check for consistency
consistency = check_tcp_consistency(current_queued_socket, tcp_header);
if (consistency != PACKET_OK)
{
printf("TCP packets not consistent, Error Code: %i!\n", consistency);
printf("TCP ACK NR: %li, Local TCP Status SEQ: %li, TCP SEQ NR: %li, FOREIGN TCP STATUS SEQ: %li\n", tcp_header->ack_nr, current_queued_socket->local_tcp_status.seq_nr+1,
tcp_header->seq_nr, current_queued_socket->foreign_tcp_status.seq_nr);
}
// Got ack, connection established, refresh local and foreign tcp socket status
set_tcp_status(&current_queued_socket->foreign_tcp_status, tcp_header->ack_nr, STATIC_MSS, tcp_header->seq_nr, ESTABLISHED, tcp_header->window);
set_tcp_status(&current_queued_socket->local_tcp_status, tcp_header->seq_nr+1, STATIC_MSS, tcp_header->ack_nr, ESTABLISHED, STATIC_WINDOW);
// Set status of internal socket back to LISTEN
server_socket->in_socket.local_tcp_status.state = LISTEN;
// send a reply to the TCP handler after processing every information from the TCP ACK packet
net_msg_reply(&msg_recv_client_ack, &msg_send_client_ack, FID_TCP_ACK);
new_socket = socket(current_queued_socket->domain, current_queued_socket->type, current_queued_socket->protocol);
current_new_socket = getSocket(new_socket);
current_new_socket->pid = pid;
memcpy(&current_new_socket->in_socket, current_queued_socket, sizeof(socket_t));
close_socket(current_queued_socket);
print_sockets();
return new_socket;
}
int accept(int s, sockaddr6_t *addr, uint32_t addrlen, uint8_t pid)
{
socket_internal_t *server_socket = getSocket(s);
if (isTCPSocket(s) && (server_socket->in_socket.local_tcp_status.state == LISTEN))
{
socket_t *current_queued_socket = getWaitingConnectionSocket(s);
if (current_queued_socket != NULL)
{
return handle_new_tcp_connection(current_queued_socket, server_socket, pid);
}
else
{
// No waiting connections, waiting for message from TCP Layer
msg_t msg_recv_client_syn;
msg_receive(&msg_recv_client_syn);
current_queued_socket = getWaitingConnectionSocket(s);
return handle_new_tcp_connection(current_queued_socket, server_socket, pid);
}
}
else
{
return -1;
}
}
socket_t *new_tcp_queued_socket(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, socket_internal_t *socket)
{
int i, free_slot = -1;
for (i = 0; i < MAX_QUEUED_SOCKETS; i++)
{
if (socket->queued_sockets[i].type == 0)
{
// Found a free slot, remember for usage later
free_slot = i;
}
else if (socket->queued_sockets[i].foreign_address.sin6_port == tcp_header->src_port)
{
// Already registered as waiting connection
return NULL;
}
}
socket_t *current_queued_socket = &socket->queued_sockets[free_slot];
current_queued_socket->domain = PF_INET6;
current_queued_socket->type = SOCK_STREAM;
current_queued_socket->protocol = IPPROTO_TCP;
// Foreign address
set_socket_address(&current_queued_socket->foreign_address, AF_INET6, tcp_header->src_port, ipv6_header->flowlabel, &ipv6_header->srcaddr);
// Local address
set_socket_address(&current_queued_socket->local_address, AF_INET6, tcp_header->dst_port, 0, &ipv6_header->destaddr);
// Foreign TCP information
set_tcp_status(&current_queued_socket->foreign_tcp_status, tcp_header->ack_nr, STATIC_MSS, tcp_header->seq_nr, SYN_SENT, tcp_header->window);
// Local TCP information
srand(tcp_header->src_port);
set_tcp_status(&current_queued_socket->local_tcp_status, tcp_header->seq_nr+1, STATIC_MSS, rand(), SYN_RCVD, STATIC_WINDOW);
return current_queued_socket;
}

179
sys/net/destiny/socket.h Normal file
View File

@ -0,0 +1,179 @@
/*
* socket.h
*
* Created on: 16.09.2011
* Author: Oliver
*/
#ifndef SOCKET_H_
#define SOCKET_H_
#include <stdint.h>
#include "tcp.h"
#include "udp.h"
#include "in.h"
#include "sys/net/sixlowpan/sixlowip.h"
/*
* Types
*/
#define SOCK_STREAM 1 /* stream socket */
#define SOCK_DGRAM 2 /* datagram socket */
#define SOCK_RAW 3 /* raw-protocol interface */
#define SOCK_RDM 4 /* reliably-delivered message */
#define SOCK_SEQPACKET 5 /* sequenced packet stream */
/*
* Address families.
*/
#define AF_UNSPEC 0 /* unspecified */
#define AF_LOCAL 1 /* local to host (pipes, portals) */
#define AF_UNIX AF_LOCAL /* backward compatibility */
#define AF_INET 2 /* internetwork: UDP, TCP, etc. */
#define AF_IMPLINK 3 /* arpanet imp addresses */
#define AF_PUP 4 /* pup protocols: e.g. BSP */
#define AF_CHAOS 5 /* mit CHAOS protocols */
#define AF_NS 6 /* XEROX NS protocols */
#define AF_ISO 7 /* ISO protocols */
#define AF_OSI AF_ISO
#define AF_ECMA 8 /* European computer manufacturers */
#define AF_DATAKIT 9 /* datakit protocols */
#define AF_CCITT 10 /* CCITT protocols, X.25 etc */
#define AF_SNA 11 /* IBM SNA */
#define AF_DECnet 12 /* DECnet */
#define AF_DLI 13 /* DEC Direct data link interface */
#define AF_LAT 14 /* LAT */
#define AF_HYLINK 15 /* NSC Hyperchannel */
#define AF_APPLETALK 16 /* Apple Talk */
#define AF_ROUTE 17 /* Internal Routing Protocol */
#define AF_LINK 18 /* Link layer interface */
#define pseudo_AF_XTP 19 /* eXpress Transfer Protocol (no AF) */
#define AF_COIP 20 /* connection-oriented IP, aka ST II */
#define AF_CNT 21 /* Computer Network Technology */
#define pseudo_AF_RTIP 22 /* Help Identify RTIP packets */
#define AF_IPX 23 /* Novell Internet Protocol */
#define AF_SIP 24 /* Simple Internet Protocol */
#define pseudo_AF_PIP 25 /* Help Identify PIP packets */
#define AF_ISDN 26 /* Integrated Services Digital Network*/
#define AF_E164 AF_ISDN /* CCITT E.164 recommendation */
#define pseudo_AF_KEY 27 /* Internal key-management function */
#define AF_INET6 28 /* IPv6 */
#define AF_NATM 29 /* native ATM access */
#define AF_ATM 30 /* ATM */
#define pseudo_AF_HDRCMPLT 31 /* Used by BPF to not rewrite headers
* in interface output routine
*/
#define AF_NETGRAPH 32 /* Netgraph sockets */
#define AF_MAX 33
/*
* Protocol families, same as address families for now.
*/
#define PF_UNSPEC AF_UNSPEC
#define PF_LOCAL AF_LOCAL
#define PF_UNIX PF_LOCAL /* backward compatibility */
#define PF_INET AF_INET
#define PF_IMPLINK AF_IMPLINK
#define PF_PUP AF_PUP
#define PF_CHAOS AF_CHAOS
#define PF_NS AF_NS
#define PF_ISO AF_ISO
#define PF_OSI AF_ISO
#define PF_ECMA AF_ECMA
#define PF_DATAKIT AF_DATAKIT
#define PF_CCITT AF_CCITT
#define PF_SNA AF_SNA
#define PF_DECnet AF_DECnet
#define PF_DLI AF_DLI
#define PF_LAT AF_LAT
#define PF_HYLINK AF_HYLINK
#define PF_APPLETALK AF_APPLETALK
#define PF_ROUTE AF_ROUTE
#define PF_LINK AF_LINK
#define PF_XTP pseudo_AF_XTP /* really just proto family, no AF */
#define PF_COIP AF_COIP
#define PF_CNT AF_CNT
#define PF_SIP AF_SIP
#define PF_IPX AF_IPX /* same format as AF_NS */
#define PF_RTIP pseudo_AF_RTIP /* same format as AF_INET */
#define PF_PIP pseudo_AF_PIP
#define PF_ISDN AF_ISDN
#define PF_KEY pseudo_AF_KEY
#define PF_INET6 AF_INET6
#define PF_NATM AF_NATM
#define PF_ATM AF_ATM
#define PF_NETGRAPH AF_NETGRAPH
#define PF_MAX AF_MAX
#define MAX_SOCKETS 5
#define MAX_QUEUED_SOCKETS 2
#define EPHEMERAL_PORTS 49152
#define STATIC_MSS 32
#define STATIC_WINDOW 1 * STATIC_MSS
#define MAX_TCP_BUFFER 1 * STATIC_WINDOW
#define INC_PACKET 0
#define OUT_PACKET 1
typedef struct __attribute__ ((packed)) socka6
{
uint8_t sin6_family; /* AF_INET6 */
uint16_t sin6_port; /* transport layer port # */
uint32_t sin6_flowinfo; /* IPv6 flow information */
ipv6_addr_t sin6_addr; /* IPv6 address */
} sockaddr6_t;
typedef struct __attribute__ ((packed)) sock_t
{
uint8_t domain;
uint8_t type;
uint8_t protocol;
tcp_socket_status_t local_tcp_status;
tcp_socket_status_t foreign_tcp_status;
sockaddr6_t local_address;
sockaddr6_t foreign_address;
} socket_t;
typedef struct __attribute__ ((packed)) socket_in_t
{
uint8_t socket_id;
uint8_t pid;
// TODO: Maybe use ring buffer instead of copying array values each time
uint8_t tcp_input_buffer_end;
uint8_t tcp_input_buffer[MAX_TCP_BUFFER];
socket_t in_socket;
socket_t queued_sockets[MAX_QUEUED_SOCKETS];
} socket_internal_t;
socket_internal_t sockets[MAX_SOCKETS];
int socket(int domain, int type, int protocol);
int connect(int socket, sockaddr6_t *addr, uint32_t addrlen, uint8_t tcp_client_thread);
socket_t *getWaitingConnectionSocket(int socket);
int32_t recvfrom( int s, void *buf, uint64_t len, int flags, sockaddr6_t *from, uint32_t *fromlen );
int32_t sendto( int s, void *msg, uint64_t len, int flags, sockaddr6_t *to, uint32_t tolen);
int32_t send(int s, void *msg, uint64_t len, int flags);
int32_t recv(int s, void *buf, uint64_t len, int flags);
int close(int s);
int bind(int s, sockaddr6_t *name, int namelen, uint8_t pid);
int listen(int s, int backlog);
int accept(int s, sockaddr6_t *addr, uint32_t addrlen, uint8_t pid);
void socket_init(void);
socket_internal_t *get_udp_socket(ipv6_hdr_t *ipv6_header, udp_hdr_t *udp_header);
socket_internal_t *get_tcp_socket(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header);
socket_internal_t *getSocket(uint8_t s);
void print_sockets(void);
void print_internal_socket(socket_internal_t *current_socket_internal);
void print_socket(socket_t *current_socket);
bool exists_socket(uint8_t socket);
socket_t *new_tcp_queued_socket(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, socket_internal_t *socket);
void print_tcp_status(int in_or_out, ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header);
void set_tcp_status(tcp_socket_status_t *tcp_socket_status, uint32_t ack_nr, uint8_t mss, uint32_t seq_nr, uint8_t state, uint16_t window);
void set_socket_address(sockaddr6_t *sockaddr, uint8_t sin6_family, uint16_t sin6_port, uint32_t sin6_flowinfo, ipv6_addr_t *sin6_addr);
void set_tcp_packet(tcp_hdr_t *tcp_hdr, uint16_t src_port, uint16_t dst_port, uint32_t seq_nr, uint32_t ack_nr,
uint8_t dataOffset_reserved, uint8_t reserved_flags, uint16_t window, uint16_t checksum, uint16_t urg_pointer);
int check_tcp_consistency(socket_t *current_tcp_socket, tcp_hdr_t *tcp_header);
int send_tcp(sockaddr6_t *addr, socket_t *current_tcp_socket, tcp_hdr_t *current_tcp_packet, ipv6_hdr_t *temp_ipv6_header, uint8_t flags, uint8_t payload_length);
#endif /* SOCKET_H_ */

320
sys/net/destiny/tcp.c Normal file
View File

@ -0,0 +1,320 @@
/*
* tcp.c
*
* Created on: 29.09.2011
* Author: Oliver
*/
#include <stdio.h>
#include <thread.h>
#include <string.h>
#include "tcp.h"
#include "in.h"
#include "socket.h"
#include "sys/net/net_help/net_help.h"
#include "sys/net/net_help/msg_help.h"
void printTCPHeader(tcp_hdr_t *tcp_header)
{
printf("\nBEGIN: TCP HEADER\n");
printf("ack_nr: %lu\n", tcp_header->ack_nr);
printf("checksum: %i\n", tcp_header->checksum);
printf("dataOffset_reserved: %i\n", tcp_header->dataOffset_reserved);
printf("dst_port: %i\n", tcp_header->dst_port);
printf("reserved_flags: %i\n", tcp_header->reserved_flags);
printf("seq_nr: %lu\n", tcp_header->seq_nr);
printf("src_port: %i\n", tcp_header->src_port);
printf("urg_pointer: %i\n", tcp_header->urg_pointer);
printf("window: %i\n", tcp_header->window);
printf("END: TCP HEADER\n");
}
void printArrayRange_tcp(uint8_t *udp_header, uint16_t len)
{
int i = 0;
printf("-------------MEMORY-------------\n");
for (i = 0; i < len; i++)
{
printf("%#x ", *(udp_header+i));
}
printf("-------------MEMORY-------------\n");
}
uint16_t tcp_csum(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header)
{
uint16_t sum;
uint16_t len = ipv6_header->length;
sum = len + IPPROTO_TCP;
sum = csum(sum, (uint8_t *)&ipv6_header->srcaddr, 2 * sizeof(ipv6_addr_t));
sum = csum(sum, (uint8_t *)tcp_header, len);
return (sum == 0) ? 0xffff : HTONS(sum);
}
uint8_t handle_payload(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, socket_internal_t *tcp_socket, uint8_t *payload)
{
msg_t m_send_tcp;
uint8_t tcp_payload_len = ipv6_header->length-TCP_HDR_LEN;
uint8_t acknowledged_bytes = 0;
if (tcp_payload_len > tcp_socket->in_socket.local_tcp_status.window)
{
memcpy(tcp_socket->tcp_input_buffer, payload, tcp_socket->in_socket.local_tcp_status.window);
acknowledged_bytes = tcp_socket->in_socket.local_tcp_status.window;
tcp_socket->in_socket.local_tcp_status.window = 0;
tcp_socket->tcp_input_buffer_end = tcp_socket->tcp_input_buffer_end + tcp_socket->in_socket.local_tcp_status.window;
}
else
{
memcpy(tcp_socket->tcp_input_buffer, payload, tcp_payload_len);
tcp_socket->in_socket.local_tcp_status.window = tcp_socket->in_socket.local_tcp_status.window - tcp_payload_len;
acknowledged_bytes = tcp_payload_len;
tcp_socket->tcp_input_buffer_end = tcp_socket->tcp_input_buffer_end + tcp_payload_len;
}
net_msg_send(&m_send_tcp, tcp_socket->pid, 1, FID_SOCKET_RECV);
return acknowledged_bytes;
}
void handle_tcp_ack_packet(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, socket_internal_t *tcp_socket)
{
msg_t m_recv_tcp, m_send_tcp;
if (tcp_socket->in_socket.local_tcp_status.state == LAST_ACK)
{
net_msg_send(&m_send_tcp, tcp_socket->pid, 0, FID_SOCKET_RECV);
memset(tcp_socket, 0, sizeof(socket_internal_t));
return;
}
// TODO: Find better way of handling queued sockets ACK packets
else if (getWaitingConnectionSocket(tcp_socket->socket_id) != NULL)
{
m_send_tcp.content.ptr = (char*)tcp_header;
net_msg_send_recv(&m_send_tcp, &m_recv_tcp, tcp_socket->pid, FID_SOCKET_HANDLE_NEW_TCP_CON, FID_TCP_ACK);
return;
}
else if (tcp_socket->in_socket.local_tcp_status.state == ESTABLISHED)
{
printf("Got regular ack for established connections payload.\n");
return;
}
printf("NO WAY OF HANDLING THIS ACK!\n");
}
void handle_tcp_rst_packet(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, socket_internal_t *tcp_socket)
{
}
void handle_tcp_syn_packet(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, socket_internal_t *tcp_socket)
{
msg_t m_send_tcp;
if (tcp_socket->in_socket.local_tcp_status.state == LISTEN)
{
socket_t *new_socket = new_tcp_queued_socket(ipv6_header, tcp_header, tcp_socket);
if (new_socket != NULL)
{
// notify socket function accept(..) that a new connection request has arrived
// No need to wait for an answer because the server accept() function isnt reading from anything other than the queued sockets
msg_send(&m_send_tcp, tcp_socket->pid, 0);
}
else
{
printf("Dropped TCP SYN Message because an error occured while requesting a new queued socket!\n");
}
}
else
{
printf("Dropped TCP SYN Message because socket was not in state LISTEN!");
}
}
void handle_tcp_syn_ack_packet(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, socket_internal_t *tcp_socket)
{
msg_t m_recv_tcp, m_send_tcp;
if (tcp_socket->in_socket.local_tcp_status.state == SYN_SENT)
{
m_send_tcp.content.ptr = (char*) tcp_header;
net_msg_send_recv(&m_send_tcp, &m_recv_tcp, tcp_socket->pid, FID_SOCKET_CONNECT, FID_TCP_SYN_ACK);
}
else
{
printf("Socket not in state SYN_SENT, dropping SYN-ACK-packet!");
}
}
void handle_tcp_fin_packet(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, socket_internal_t *tcp_socket)
{
msg_t m_send;
socket_t *current_tcp_socket = &tcp_socket->in_socket;
uint8_t send_buffer[BUFFER_SIZE];
ipv6_hdr_t *temp_ipv6_header = ((ipv6_hdr_t*)(&send_buffer));
tcp_hdr_t *current_tcp_packet = ((tcp_hdr_t*)(&send_buffer[IPV6_HDR_LEN]));
set_tcp_status(&current_tcp_socket->local_tcp_status,
tcp_header->seq_nr+1,
STATIC_MSS,
current_tcp_socket->local_tcp_status.seq_nr+1,
LAST_ACK,
current_tcp_socket->local_tcp_status.window);
set_tcp_status(&current_tcp_socket->foreign_tcp_status,
tcp_header->ack_nr,
STATIC_MSS,
tcp_header->seq_nr,
FIN_WAIT_1,
current_tcp_socket->foreign_tcp_status.window);
send_tcp(NULL, current_tcp_socket, current_tcp_packet, temp_ipv6_header, TCP_FIN_ACK, 0);
m_send.content.value = CLOSE_CONN;
net_msg_send(&m_send, tcp_socket->pid, 0, FID_SOCKET_RECV);
}
void handle_tcp_fin_ack_packet(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, socket_internal_t *tcp_socket)
{
msg_t m_send;
socket_t *current_tcp_socket = &tcp_socket->in_socket;
uint8_t send_buffer[BUFFER_SIZE];
ipv6_hdr_t *temp_ipv6_header = ((ipv6_hdr_t*)(&send_buffer));
tcp_hdr_t *current_tcp_packet = ((tcp_hdr_t*)(&send_buffer[IPV6_HDR_LEN]));
set_tcp_status(&current_tcp_socket->local_tcp_status,
tcp_header->seq_nr+1,
STATIC_MSS,
current_tcp_socket->local_tcp_status.seq_nr,
CLOSED,
current_tcp_socket->local_tcp_status.window);
set_tcp_status(&current_tcp_socket->foreign_tcp_status,
tcp_header->ack_nr,
STATIC_MSS,
tcp_header->seq_nr,
LAST_ACK,
current_tcp_socket->foreign_tcp_status.window);
send_tcp(NULL, current_tcp_socket, current_tcp_packet, temp_ipv6_header, TCP_ACK, 0);
memset(tcp_socket, 0, sizeof(socket_internal_t));
net_msg_send(&m_send, tcp_socket->pid, 0, FID_SOCKET_CLOSE);
}
void handle_tcp_no_flags_packet(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header, socket_internal_t *tcp_socket, uint8_t *payload)
{
uint8_t tcp_payload_len = ipv6_header->length-TCP_HDR_LEN, read_bytes = 0;
socket_t *current_tcp_socket = &tcp_socket->in_socket;
uint8_t send_buffer[BUFFER_SIZE];
ipv6_hdr_t *temp_ipv6_header = ((ipv6_hdr_t*)(&send_buffer));
tcp_hdr_t *current_tcp_packet = ((tcp_hdr_t*)(&send_buffer[IPV6_HDR_LEN]));
if (tcp_payload_len > 0)
{
read_bytes = handle_payload(ipv6_header, tcp_header, tcp_socket, payload);
// Refresh TCP status values
set_tcp_status(&tcp_socket->in_socket.foreign_tcp_status,
tcp_header->ack_nr,
STATIC_MSS,
tcp_header->seq_nr,
ESTABLISHED,
tcp_header->window);
set_tcp_status(&tcp_socket->in_socket.local_tcp_status,
tcp_header->seq_nr - tcp_payload_len + read_bytes + 1,
STATIC_MSS,
tcp_socket->in_socket.local_tcp_status.seq_nr,
ESTABLISHED,
tcp_socket->in_socket.local_tcp_status.window);
// Fill IPv6 Header
memcpy(&(temp_ipv6_header->destaddr), &current_tcp_socket->foreign_address.sin6_addr, 16);
memcpy(&(temp_ipv6_header->srcaddr), &current_tcp_socket->local_address.sin6_addr, 16);
temp_ipv6_header->length = TCP_HDR_LEN;
// Fill TCP ACK packet
set_tcp_packet(current_tcp_packet, current_tcp_socket->local_address.sin6_port, current_tcp_socket->foreign_address.sin6_port,
current_tcp_socket->local_tcp_status.seq_nr, current_tcp_socket->local_tcp_status.ack_nr, 0, TCP_ACK, current_tcp_socket->local_tcp_status.window,
0, 0);
current_tcp_packet->checksum = ~tcp_csum(temp_ipv6_header, current_tcp_packet);
sixlowpan_send(&current_tcp_socket->foreign_address.sin6_addr, (uint8_t*)(current_tcp_packet), TCP_HDR_LEN, IPPROTO_TCP);
}
}
void tcp_packet_handler (void)
{
msg_t m_recv_ip, m_send_ip;
ipv6_hdr_t *ipv6_header;
tcp_hdr_t *tcp_header;
uint8_t *payload;
socket_internal_t *tcp_socket = NULL;
uint16_t chksum;
while (1)
{
net_msg_receive(&m_recv_ip, FID_TCP_PH);
ipv6_header = ((ipv6_hdr_t*)m_recv_ip.content.ptr);
tcp_header = ((tcp_hdr_t*)(m_recv_ip.content.ptr + IPV6_HDR_LEN));
payload = (uint8_t*)(m_recv_ip.content.ptr + IPV6_HDR_LEN + TCP_HDR_LEN);
chksum = tcp_csum(ipv6_header, tcp_header);
printf("Checksum is %x!\n", chksum);
print_tcp_status(INC_PACKET, ipv6_header, tcp_header);
tcp_socket = get_tcp_socket(ipv6_header, tcp_header);
if ((chksum == 0xffff) && (tcp_socket != NULL))
{
// Remove reserved bits from tcp flags field
uint8_t tcp_flags = tcp_header->reserved_flags & REMOVE_RESERVED;
// TODO: URG Flag and PSH flag are currently being ignored
switch (tcp_flags)
{
case TCP_ACK:
{
// only ACK Bit set
handle_tcp_ack_packet(ipv6_header, tcp_header, tcp_socket);
break;
}
case TCP_RST:
{
printf("RST Bit set!\n");
// only RST Bit set
handle_tcp_rst_packet(ipv6_header, tcp_header, tcp_socket);
break;
}
case TCP_SYN:
{
// only SYN Bit set, look for matching, listening socket and request new queued socket
printf("SYN Bit set!\n");
handle_tcp_syn_packet(ipv6_header, tcp_header, tcp_socket);
break;
}
case TCP_SYN_ACK:
{
// only SYN and ACK Bit set, complete three way handshake when socket in state SYN_SENT
handle_tcp_syn_ack_packet(ipv6_header, tcp_header, tcp_socket);
break;
}
case TCP_FIN:
{
printf("FIN Bit set!\n");
// only FIN Bit set
handle_tcp_fin_packet(ipv6_header, tcp_header, tcp_socket);
break;
}
case TCP_FIN_ACK:
{
printf("FIN ACK Bit set!\n");
// only FIN and ACK Bit set
handle_tcp_fin_ack_packet(ipv6_header, tcp_header, tcp_socket);
break;
}
default:
{
printf("DEFAULT!\n");
handle_tcp_no_flags_packet(ipv6_header, tcp_header, tcp_socket, payload);
}
}
}
else
{
printf("Wrong checksum (%x) or no corresponding socket found!\n", chksum);
}
net_msg_reply(&m_recv_ip, &m_send_ip, FID_SIXLOWIP_TCP);
}
}

102
sys/net/destiny/tcp.h Normal file
View File

@ -0,0 +1,102 @@
/*
* tcp.h
*
* Created on: 29.09.2011
* Author: Oliver
*/
#ifndef TCP_H_
#define TCP_H_
#define TCP_HDR_LEN 20
enum tcp_flags
{
TCP_ACK = 0x08,
TCP_URG_PSH = 0x14,
TCP_RST = 0x20,
TCP_SYN = 0x40,
TCP_SYN_ACK = 0x48,
TCP_FIN = 0x80,
TCP_FIN_ACK = 0x88
};
enum tcp_states
{
CLOSED = 0,
LISTEN = 1,
SYN_SENT = 2,
SYN_RCVD = 3,
ESTABLISHED = 4,
FIN_WAIT_1 = 5,
FIN_WAIT_2 = 6,
CLOSE_WAIT = 7,
CLOSING = 8,
LAST_ACK = 9,
TIME_WAIT = 10,
UNKNOWN = 11
};
enum tcp_codes
{
UNDEFINED = 0,
PACKET_OK = 1,
CLOSE_CONN = 2,
SEQ_NO_SAME = 3,
ACK_NO_TOO_SMALL = 4,
ACK_NO_TOO_BIG = 5
};
#define REMOVE_RESERVED 0xFC
#define IS_TCP_ACK(a) ((a & TCP_ACK) > 0) // Test for ACK flag only, iognore URG und PSH flag
#define IS_TCP_RST(a) ((a & TCP_RST) > 0)
#define IS_TCP_SYN(a) ((a & TCP_SYN) > 0)
#define IS_TCP_SYN_ACK(a) ((a & TCP_SYN_ACK) > 0)
#define IS_TCP_FIN(a) ((a & TCP_FIN) > 0)
#define IS_TCP_FIN_ACK(a) ((a & TCP_FIN_ACK) > 0)
#define SET_TCP_ACK(a) a = ((a & 0x00) | TCP_ACK)
#define SET_TCP_RST(a) a = ((a & 0x00) | TCP_RST)
#define SET_TCP_SYN(a) a = ((a & 0x00) | TCP_SYN)
#define SET_TCP_SYN_ACK(a) a = ((a & 0x00) | TCP_SYN_ACK)
#define SET_TCP_FIN(a) a = ((a & 0x00) | TCP_FIN)
#define SET_TCP_FIN_ACK(a) a = ((a & 0x00) | TCP_FIN_ACK)
// TODO: Probably stack size too high
#define TCP_STACK_SIZE 4096
#include "sys/net/sixlowpan/sixlowip.h"
typedef struct __attribute__ ((packed)) tcp_so_sta_t
{
uint32_t ack_nr;
uint8_t mss;
uint32_t seq_nr;
uint8_t state;
uint16_t window;
} tcp_socket_status_t;
typedef struct __attribute__ ((packed)) tcp_h_t
{
uint16_t src_port;
uint16_t dst_port;
uint32_t seq_nr;
uint32_t ack_nr;
uint8_t dataOffset_reserved;
uint8_t reserved_flags;
uint16_t window;
uint16_t checksum;
uint16_t urg_pointer;
} tcp_hdr_t;
// uint8_t buffer_tcp[BUFFER_SIZE];
char tcp_stack_buffer[TCP_STACK_SIZE];
void tcp_packet_handler (void);
uint16_t tcp_csum(ipv6_hdr_t *ipv6_header, tcp_hdr_t *tcp_header);
void printTCPHeader(tcp_hdr_t *tcp_header);
void printArrayRange_tcp(uint8_t *udp_header, uint16_t len);
#endif /* TCP_H_ */

65
sys/net/destiny/udp.c Normal file
View File

@ -0,0 +1,65 @@
#include <stdio.h>
#include <thread.h>
#include <string.h>
#include "udp.h"
#include "msg.h"
#include "sys/net/sixlowpan/sixlowip.h"
#include "sys/net/sixlowpan/sixlowpan.h"
#include "socket.h"
#include "in.h"
#include "sys/net/net_help/net_help.h"
#include "sys/net/net_help/msg_help.h"
uint16_t udp_csum(ipv6_hdr_t *ipv6_header, udp_hdr_t *udp_header)
{
uint16_t sum;
uint16_t len = udp_header->length;
sum = len + IPPROTO_UDP;
sum = csum(sum, (uint8_t *)&ipv6_header->srcaddr, 2 * sizeof(ipv6_addr_t));
sum = csum(sum, (uint8_t*)udp_header, len);
return (sum == 0) ? 0xffff : HTONS(sum);
}
void udp_packet_handler(void)
{
msg_t m_recv_ip, m_send_ip, m_recv_udp, m_send_udp;
ipv6_hdr_t *ipv6_header;
udp_hdr_t *udp_header;
uint8_t *payload;
socket_internal_t *udp_socket = NULL;
uint16_t chksum;
while (1)
{
net_msg_receive(&m_recv_ip, FID_UDP_PH);
ipv6_header = ((ipv6_hdr_t*)m_recv_ip.content.ptr);
udp_header = ((udp_hdr_t*)(m_recv_ip.content.ptr + IPV6_HDR_LEN));
payload = (uint8_t*)(m_recv_ip.content.ptr + IPV6_HDR_LEN + UDP_HDR_LEN);
chksum = udp_csum(ipv6_header, udp_header);
if (chksum == 0xffff)
{
udp_socket = get_udp_socket(ipv6_header, udp_header);
if (udp_socket != NULL)
{
m_send_udp.content.ptr = (char*)ipv6_header;
net_msg_send_recv(&m_send_udp, &m_recv_udp, udp_socket->pid, FID_SOCKET_RECV_FROM, FID_UDP_PH);
}
else
{
printf("Dropped UDP Message because no process ID was found for delivery!\n");
}
}
else
{
printf("Wrong checksum (%x)!\n", chksum);
}
net_msg_reply(&m_recv_ip, &m_send_ip, FID_SIXLOWIP_UDP);
}
}

32
sys/net/destiny/udp.h Normal file
View File

@ -0,0 +1,32 @@
/*
* udp.h
*
* Created on: 05.09.2011
* Author: Oliver
*/
#ifndef UDP_H_
#define UDP_H_
#define UDP_HDR_LEN 8
// TODO: Probably stack size too high
#define UDP_STACK_SIZE 4096
#include "sys/net/sixlowpan/sixlowip.h"
typedef struct __attribute__ ((packed)) udp_h_t{
uint16_t src_port;
uint16_t dst_port;
uint16_t length;
uint16_t checksum;
} udp_hdr_t;
// uint8_t buffer_udp[BUFFER_SIZE];
char udp_stack_buffer[UDP_STACK_SIZE];
uint16_t udp_csum(ipv6_hdr_t *ipv6_header, udp_hdr_t *udp_header);
void udp_packet_handler(void);
#endif /* UDP_H_ */

7
sys/net/net_help/Jamfile Normal file
View File

@ -0,0 +1,7 @@
SubDir TOP sys net net_help ;
# HDRS += $(TOP)/sys/net/net_help/ ;
Module net_help : net_help.c msg_help.c ;

View File

@ -0,0 +1,45 @@
/*
* msg_help.c
*
* Created on: 24.11.2011
* Author: Oliver
*/
#include <thread.h>
#include <stdio.h>
#include "msg_help.h"
int net_msg_receive(msg_t *m, uint16_t function_id)
{
int ret_val;
ret_val = msg_receive(m);
while (m->type != function_id)
{
ret_val = msg_receive(m);
}
return ret_val;
}
int net_msg_reply(msg_t *m, msg_t *reply, uint16_t function_id)
{
reply->type = function_id;
return msg_reply(m, reply);
}
int net_msg_send(msg_t *m, unsigned int pid, bool block, uint16_t function_id)
{
m->type = function_id;
return msg_send(m, pid, block);
}
int net_msg_send_recv(msg_t *m, msg_t *reply, unsigned int pid, uint16_t function_id_m, uint16_t function_id_reply)
{
int ret_val;
m->type = function_id_m;
ret_val = msg_send_receive(m, reply, pid);
while(reply->type != function_id_reply)
{
ret_val = msg_receive(reply);
}
return ret_val;
}

View File

@ -0,0 +1,31 @@
/*
* msg_help.h
*
* Created on: 24.11.2011
* Author: Oliver
*/
#ifndef MSG_HELP_H_
#define MSG_HELP_H_
// Function IDs
#define FID_SIXLOWIP_TCP 0
#define FID_SIXLOWIP_UDP 1
#define FID_TCP_PH 2
#define FID_UDP_PH 3
#define FID_H_PAYLOAD 4
#define FID_SOCKET_RECV 5
#define FID_SOCKET_RECV_FROM 6
#define FID_TCP_SYN_ACK 7
#define FID_SOCKET_CONNECT 8
#define FID_SOCKET_HANDLE_NEW_TCP_CON 9
#define FID_TCP_ACK 10
#define FID_SOCKET_CLOSE 11
int net_msg_receive(msg_t *m, uint16_t function_id);
int net_msg_reply(msg_t *m, msg_t *reply, uint16_t function_id);
int net_msg_send(msg_t *m, unsigned int pid, bool block, uint16_t function_id);
/* Target Function ID: function_id_m, Source Function ID: function_id_reply */
int net_msg_send_recv(msg_t *m, msg_t *reply, unsigned int pid, uint16_t function_id_m, uint16_t function_id_reply);
#endif /* MSG_HELP_H_ */

View File

@ -0,0 +1,48 @@
/*
* common.c
*
* Created on: 05.10.2011
* Author: Oliver
*/
#include <stdio.h>
#include <thread.h>
#include <string.h>
#include "net_help.h"
uint16_t csum(uint16_t sum, uint8_t *buf, uint16_t len)
{
int count;
uint16_t carry;
count = len >> 1;
if(count)
{
if(count)
{
carry = 0;
do
{
uint16_t t = (*buf << 8) + *(buf+1);
count--;
buf += 2;
sum += carry;
sum += t;
carry = (t > sum);
} while(count);
sum += carry;
}
}
if(len & 1)
{
uint16_t u = (*buf << 8);
sum += (*buf << 8);
if(sum < u)
{
sum++;
}
}
return sum;
}

View File

@ -0,0 +1,24 @@
/*
* common.h
*
* Created on: 05.10.2011
* Author: Oliver
*/
#ifndef COMMON_H_
#define COMMON_H_
#include <string.h>
#define HTONS(a) ((((uint16_t) (a) >> 8) & 0xff) | ((((uint16_t) (a)) & 0xff) << 8))
#define HTONL(a) ((((uint32_t) (a) & 0xff000000) >> 24) | \
(((uint32_t) (a) & 0x00ff0000) >> 8) | \
(((uint32_t) (a) & 0x0000ff00) << 8) | \
(((uint32_t) (a) & 0x000000ff) << 24))
#define NTOHS HTONS
#define NTOHL HTONL
#define CMP_IPV6_ADDR(a, b) (memcmp(a, b, 16))
uint16_t csum(uint16_t sum, uint8_t *buf, uint16_t len);
#endif /* COMMON_H_ */

View File

@ -0,0 +1,5 @@
SubDir TOP sys net sixlowpan ;
# HDRS += $(TOP)/sys/net/sixlowpan/ ;
Module 6lowpan : sixlowpan.c sixlowip.c sixlowmac.c sixlownd.c sixlowborder.c ieee802154_frame.c serialnumber.c semaphore.c bordermultiplex.c flowcontrol.c : vtimer transceiver net_help ;

View File

@ -0,0 +1,173 @@
#include <stdio.h>
#include <string.h>
#include <board_uart0.h>
#include "flowcontrol.h"
#include "sixlowpan.h"
#include "sixlownd.h"
#include "sixlowborder.h"
#include "sixlowerror.h"
#include "bordermultiplex.h"
#define END 0xC0
#define ESC 0xDB
#define END_ESC 0xDC
#define ESC_ESC 0xDD
void demultiplex(border_packet_t *packet, int len) {
switch (packet->type) {
case (BORDER_PACKET_RAW_TYPE):{
fputs(((char *)packet) + sizeof (border_packet_t), stdin);
break;
}
case (BORDER_PACKET_L3_TYPE):{
border_l3_header_t *l3_header_buf = (border_l3_header_t *)packet;
switch (l3_header_buf->ethertype) {
case (BORDER_ETHERTYPE_IPV6):{
struct ipv6_hdr_t *ipv6_buf = (struct ipv6_hdr_t *)(((unsigned char *)packet) + sizeof (border_l3_header_t));
border_send_ipv6_over_lowpan(ipv6_buf, 1, 1);
break;
}
default:
printf("ERROR: Unknown ethertype 0x%04x\n", l3_header_buf->ethertype);
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_CONTEXT):{
border_context_packet_t *context = (border_context_packet_t *)packet;
ipv6_addr_t target_addr;
ipv6_set_all_nds_mcast_addr(&target_addr);
mutex_lock(&lowpan_context_mutex);
lowpan_context_update(
context->context.cid,
&context->context.prefix,
context->context.length,
context->context.comp,
context->context.lifetime
);
mutex_unlock(&lowpan_context_mutex,0);
abr_add_context(context->context.version, &abr_addr, context->context.cid);
// Send router advertisement
break;
}
case (BORDER_CONF_IPADDR):{
//border_addr_packet_t *addr_packet = (border_addr_packet_t *)packet;
// add address
break;
}
default:
printf("ERROR: Unknown conftype %02x\n", conf_header_buf->conftype);
break;
}
break;
}
default:
printf("ERROR: Unknown border packet type %02x\n", packet->type);
break;
}
}
void multiplex_send_ipv6_over_uart(struct ipv6_hdr_t *packet) {
border_l3_header_t *serial_buf;
serial_buf = (border_l3_header_t *)get_serial_out_buffer(0);
serial_buf->empty = 0;
serial_buf->type = BORDER_PACKET_L3_TYPE;
serial_buf->ethertype = BORDER_ETHERTYPE_IPV6;
memcpy(get_serial_in_buffer(0)+sizeof (border_l3_header_t), packet, IPV6_HDR_LEN + packet->length);
flowcontrol_send_over_uart((border_packet_t *) serial_buf, sizeof (border_l3_header_t));
}
void multiplex_send_addr_over_uart(ipv6_addr_t *addr) {
border_addr_packet_t *serial_buf;
serial_buf = (border_addr_packet_t *)get_serial_in_buffer(0);
serial_buf->empty = 0;
serial_buf->type = BORDER_PACKET_CONF_TYPE;
serial_buf->conftype = BORDER_CONF_IPADDR;
memcpy(&serial_buf->addr, addr, sizeof(ipv6_addr_t));
flowcontrol_send_over_uart((border_packet_t *) serial_buf, sizeof (border_addr_packet_t));
}
int readpacket(uint8_t *packet_buf, size_t size) {
uint8_t *line_buf_ptr = packet_buf;
uint8_t byte = END+1;
uint8_t esc = 0;
while (1) {
byte = uart0_readc();
if (byte == END) {
break;
}
if ( (line_buf_ptr - packet_buf) >= size-1) {
return -SIXLOWERROR_ARRAYFULL;
}
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 - 1);
}
int writepacket(uint8_t *packet_buf, size_t size) {
uint8_t *byte_ptr = packet_buf;
while ((byte_ptr - packet_buf) < size) {
if ((byte_ptr - packet_buf) > BORDER_BUFFER_SIZE) {
return -1;
}
switch (*byte_ptr) {
case(END):{
*byte_ptr = END_ESC;
uart0_putc(ESC);
break;
}
case(ESC):{
*byte_ptr = ESC_ESC;
uart0_putc(ESC);
break;
}
default:{
break;
}
}
uart0_putc(*byte_ptr);
byte_ptr++;
}
uart0_putc(END);
return (byte_ptr - packet_buf);
}

View File

@ -0,0 +1,74 @@
#ifndef BORDERMULTIPLEX_H
#define BORDERMULTIPLEX_H
#include <stdint.h>
#include <stdlib.h>
#include "sixlowip.h"
/* packet types of uart-packets */
#define BORDER_PACKET_RAW_TYPE 0
#define BORDER_PACKET_CONF_TYPE 2
#define BORDER_PACKET_L3_TYPE 3
/* configuration types */
#define BORDER_CONF_CONTEXT 2
#define BORDER_CONF_IPADDR 3
/* ethertypes for L3 packets */
#define BORDER_ETHERTYPE_IPV6 0x86DD
typedef struct __attribute__ ((packed)) border_packet_t {
uint8_t empty;
uint8_t type;
uint8_t seq_num;
} border_packet_t;
typedef struct __attribute__ ((packed)) border_l3_header_t {
uint8_t empty;
uint8_t type;
uint8_t seq_num;
uint16_t ethertype;
} border_l3_header_t;
typedef struct __attribute__ ((packed)) border_conf_header_t {
uint8_t empty;
uint8_t type;
uint8_t seq_num;
uint8_t conftype;
} border_conf_header_t;
typedef struct __attribute__ ((packed)) border_addr_packet_t {
uint8_t empty;
uint8_t type;
uint8_t seq_num;
uint8_t conftype;
uint16_t version;
ipv6_addr_t addr;
} border_addr_packet_t;
typedef struct __attribute__ ((packed)) border_context_packet_t {
uint8_t empty;
uint8_t type;
uint8_t seq_num;
uint8_t conftype;
struct border_context_t {
uint16_t version;
uint8_t cid;
ipv6_addr_t prefix;
uint8_t length;
uint8_t comp;
uint16_t lifetime;
} context;
} border_context_packet_t;
#define BORDER_BUFFER_SIZE (sizeof (border_l3_header_t) + MTU)
void demultiplex(border_packet_t *packet, int len);
void multiplex_send_ipv6_over_uart(struct ipv6_hdr_t *packet);
void multiplex_send_addr_over_uart(ipv6_addr_t *addr);
int readpacket(uint8_t *packet_buf, size_t size);
int writepacket(uint8_t *packet_buf, size_t size);
#endif /* BORDERMULTIPLEX_H*/

View File

@ -0,0 +1,168 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "vtimer.h"
#include "thread.h"
#include "semaphore.h"
#include "bordermultiplex.h"
#include "flowcontrol.h"
static int set_timeout(vtimer_t *timeout, long useconds, void *args);
static void sending_slot(void);
char sending_slot_stack[SENDING_SLOT_STACK_SIZE];
unsigned int sending_slot_pid;
flowcontrol_stat_t slwin_stat;
sem_t connection_established;
int16_t synack_seqnum = -1;
ipv6_addr_t init_threeway_handshake() {
border_syn_packet_t *syn;
msg_t m;
m.content.ptr = NULL;
msg_send(&m,border_get_serial_reader(),1);
msg_receive(&m);
syn = (border_syn_packet_t *)m.content.ptr;
border_conf_header_t *synack = (border_conf_header_t *)get_serial_out_buffer(0);
ipv6_addr_t addr;
memcpy(&addr, &(syn->addr), sizeof (ipv6_addr_t));
slwin_stat.next_exp = syn->next_seq_num;
slwin_stat.last_frame = syn->next_exp - 1;
slwin_stat.last_ack = slwin_stat.last_frame;
synack->empty = 0;
synack->type = BORDER_PACKET_CONF_TYPE;
synack->conftype = BORDER_CONF_SYNACK;
sending_slot_pid = thread_create(sending_slot_stack, SENDING_SLOT_STACK_SIZE, PRIORITY_MAIN-1, CREATE_SLEEPING, sending_slot, "sending slot");
flowcontrol_send_over_uart((border_packet_t *)synack, sizeof (border_conf_header_t));
synack_seqnum = synack->seq_num;
return addr;
}
ipv6_addr_t flowcontrol_init() {
int i;
sem_init(&slwin_stat.send_win_not_full,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);
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);
return init_threeway_handshake();
}
static void sending_slot(void) {
msg_t m;
uint8_t seq_num;
struct send_slot *slot;
border_packet_t *tmp;
while(1) {
msg_receive(&m);
seq_num = *((uint8_t *)m.content.ptr);
slot = &(slwin_stat.send_win[seq_num % BORDER_SWS]);
tmp = (border_packet_t*) slot->frame;
if (seq_num == tmp->seq_num) {
writepacket(slot->frame,slot->frame_len);
if (set_timeout(&slot->timeout, BORDER_SL_TIMEOUT, (void*) m.content.ptr) != 0) {
printf("ERROR: Error invoking timeout timer\n");
}
}
}
}
static int set_timeout(vtimer_t *timeout, long useconds, void *args) {
timex_t interval;
interval.seconds = useconds / 1000000;
interval.microseconds = (useconds % 1000000) * 1000;
return vtimer_set_msg(timeout, interval, sending_slot_pid, args);
}
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 flowcontrol_send_over_uart(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;
if (set_timeout(&slot->timeout, BORDER_SL_TIMEOUT, (void *)args) != 0) {
printf("ERROR: Error invoking timeout timer\n");
return;
}
writepacket((uint8_t *)packet, len);
}
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_deliver_from_uart(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)) {
if (synack_seqnum == packet->seq_num) {
synack_seqnum = -1;
sem_signal(&connection_established);
}
do {
struct send_slot *slot;
slot = &(slwin_stat.send_win[++slwin_stat.last_ack % BORDER_SWS]);
vtimer_remove(&slot->timeout);
memset(&slot->frame,0,BORDER_BUFFER_SIZE);
sem_signal(&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,BORDER_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

@ -0,0 +1,58 @@
#ifndef FLOWCONTROL_H
#define FLOWCONTROL_H
#include <stdint.h>
#include <vtimer.h>
#include "semaphore.h"
#include "sixlowip.h"
#include "sixlowborder.h"
#include "bordermultiplex.h"
/* packet types for flowcontrol */
#define BORDER_PACKET_ACK_TYPE 1
/* configuration types for flowcontrol */
#define BORDER_CONF_SYN 0
#define BORDER_CONF_SYNACK 1
#define BORDER_SWS 1
#define BORDER_RWS 1
#define BORDER_SL_TIMEOUT 500 // microseconds, maybe smaller
#define SENDING_SLOT_STACK_SIZE (256)
typedef struct flowcontrol_stat_t {
/* Sender state */
uint8_t last_ack;
uint8_t last_frame;
sem_t send_win_not_full;
struct send_slot {
vtimer_t timeout;
uint8_t frame[BORDER_BUFFER_SIZE];
size_t frame_len;
} send_win[BORDER_SWS];
/* Receiver state */
uint8_t next_exp;
struct recv_slot {
int8_t received;
uint8_t frame[BORDER_BUFFER_SIZE];
size_t frame_len;
} recv_win[BORDER_RWS];
} flowcontrol_stat_t;
typedef struct __attribute__ ((packed)) border_syn_packet_t {
uint8_t empty;
uint8_t type;
uint8_t next_seq_num;
uint8_t conftype;
uint8_t next_exp;
ipv6_addr_t addr;
} border_syn_packet_t;
ipv6_addr_t flowcontrol_init();
void flowcontrol_send_over_uart(border_packet_t *packet, int len);
void flowcontrol_deliver_from_uart(border_packet_t *packet, int len);
#endif /* FLOWCONTROL_H*/

View File

@ -0,0 +1,224 @@
#include "ieee802154_frame.h"
//uint8_t mac_buf[IEEE_802154_HDR_LEN + IEEE_802154_PAYLOAD_LEN];
uint8_t ieee802154_hdr_ptr;
uint8_t ieee802154_payload_ptr;
uint16_t ieee802154_payload_len;
uint8_t init_802154_frame(ieee802154_frame_t *frame, uint8_t *buf){
/* Frame Control Field - 802.15.4 - 2006 - 7.2.1.1 */
uint8_t index = 0;
buf[index] = ((frame->fcf.frame_type << 5) |
(frame->fcf.sec_enb << 4) |
(frame->fcf.frame_pend << 3) |
(frame->fcf.ack_req << 2) |
(frame->fcf.panid_comp << 1));
index++;
buf[index] = ((frame->fcf.dest_addr_m << 4) |
(frame->fcf.frame_ver << 2) |
(frame->fcf.src_addr_m));
index++;
/* Sequence Number - 802.15.4 - 2006 - 7.2.1.2 */
buf[index] = frame->seq_nr;
index++;
/* Destination PAN Identifier - 802.15.4 - 2006 - 7.2.1.3 */
if(frame->fcf.dest_addr_m == 0x02 || frame->fcf.dest_addr_m == 0x03){
buf[index] = ((frame->dest_pan_id >> 8) & 0xff);
buf[index+1] = (frame->dest_pan_id & 0xff);
}
index += 2;
/* Destination Address - 802.15.4 - 2006 - 7.2.1.4 */
if(frame->fcf.dest_addr_m == 0x02){
buf[index] = frame->dest_addr[0];
buf[index+1] = frame->dest_addr[1];
index += 2;
} else if(frame->fcf.dest_addr_m == 0x03){
buf[index] = frame->dest_addr[0];
buf[index+1] = frame->dest_addr[1];
buf[index+2] = frame->dest_addr[2];
buf[index+3] = frame->dest_addr[3];
buf[index+4] = frame->dest_addr[4];
buf[index+5] = frame->dest_addr[5];
buf[index+6] = frame->dest_addr[6];
buf[index+7] = frame->dest_addr[7];
index += 8;
}
/* Source PAN Identifier - 802.15.4 - 2006 - 7.2.1.5 */
if(!(frame->fcf.panid_comp & 0x01)){
if(frame->fcf.src_addr_m == 0x02 || frame->fcf.src_addr_m == 0x03){
buf[index] = ((frame->src_pan_id >> 8) & 0xff);
buf[index+1] = (frame->src_pan_id & 0xff);
index += 2;
}
}
/* Source Address field - 802.15.4 - 2006 - 7.2.1.6 */
if(frame->fcf.src_addr_m == 0x02){
buf[index] = frame->src_addr[0];
buf[index+1] = frame->src_addr[1];
index += 2;
} else if(frame->fcf.src_addr_m == 0x03){
buf[index] = frame->src_addr[0];
buf[index+1] = frame->src_addr[1];
buf[index+2] = frame->src_addr[2];
buf[index+3] = frame->src_addr[3];
buf[index+4] = frame->src_addr[4];
buf[index+5] = frame->src_addr[5];
buf[index+6] = frame->src_addr[6];
buf[index+7] = frame->src_addr[7];
index += 8;
}
return index;
}
/** 2 1 2 VAR 2 VAR
* -------------------------------------------
* | FCF | DSN | DPID | DAD | SPID | SAD |
* -------------------------------------------
*/
uint8_t get_802154_hdr_len(ieee802154_frame_t *frame){
uint8_t len = 0;
if(frame->fcf.dest_addr_m == 0x02){
len += 2;
} else if(frame->fcf.dest_addr_m == 0x03){
len += 8;
}
if(frame->fcf.src_addr_m == 0x02){
len += 2;
} else if(frame->fcf.src_addr_m == 0x03){
len += 8;
}
if((frame->fcf.dest_addr_m == 0x02) || (frame->fcf.dest_addr_m == 0x03)){
len += 2;
}
if((frame->fcf.src_addr_m == 0x02) || (frame->fcf.src_addr_m == 0x03)){
len += 2;
}
/* if src pan id == dest pan id set compression bit */
if(frame->src_pan_id == frame->dest_pan_id){
frame->fcf.panid_comp = 1;
len -= 2;
}
/* (DPID + DAD + SPID + SAD) + (FCF + DSN) */
return (len + 3);
}
uint8_t read_802154_frame(uint8_t *buf, ieee802154_frame_t *frame, uint8_t len){
uint8_t index = 0;
uint8_t hdrlen;
frame->fcf.frame_type = (buf[index] >> 5) & 0x07;
frame->fcf.sec_enb = (buf[index] >> 4) & 0x01;
frame->fcf.frame_pend = (buf[index] >> 3) & 0x01;
frame->fcf.ack_req = (buf[index] >> 2) & 0x01;
frame->fcf.panid_comp = (buf[index] >> 1) & 0x01;
index++;
frame->fcf.dest_addr_m = (buf[index] >> 4) & 0x03;
frame->fcf.frame_ver = (buf[index] >> 2) & 0x03;
frame->fcf.src_addr_m = buf[index] & 0x03;
//print_802154_fcf_frame(frame);
index++;
frame->seq_nr = buf[index];
index++;
frame->dest_pan_id = (((uint16_t)buf[index]) << 8) | buf[index+1];
index += 2;
switch(frame->fcf.dest_addr_m){
case(0):{
printf("fcf.dest_addr_m: pan identifier/address fields empty\n");
break;
}
case(2):{
frame->dest_addr[0] = buf[index];
frame->dest_addr[1] = buf[index+1];
index += 2;
break;
}
case(3):{
frame->dest_addr[0] = buf[index];
frame->dest_addr[1] = buf[index+1];
frame->dest_addr[2] = buf[index+2];
frame->dest_addr[3] = buf[index+3];
frame->dest_addr[4] = buf[index+4];
frame->dest_addr[5] = buf[index+5];
frame->dest_addr[6] = buf[index+6];
frame->dest_addr[7] = buf[index+7];
index += 8;
break;
}
}
if(!(frame->fcf.panid_comp == 1)){
frame->src_pan_id = (((uint16_t)buf[index]) << 8) | buf[index+1];
index += 2;
}
switch(frame->fcf.src_addr_m){
case(0):{
printf("fcf.src_addr_m: pan identifier/address fields empty\n");
break;
}
case(2):{
frame->src_addr[0] = buf[index];
frame->src_addr[1] = buf[index+1];
index += 2;
break;
}
case(3):{
frame->src_addr[0] = buf[index];
frame->src_addr[1] = buf[index+1];
frame->src_addr[2] = buf[index+2];
frame->src_addr[3] = buf[index+3];
frame->src_addr[4] = buf[index+4];
frame->src_addr[5] = buf[index+5];
frame->src_addr[6] = buf[index+6];
frame->src_addr[7] = buf[index+7];
index += 8;
break;
}
}
frame->payload = (buf + index);
hdrlen = index;
frame->payload_len = (len - hdrlen);
return hdrlen;
}
void print_802154_fcf_frame(ieee802154_frame_t *frame){
printf("frame type: %02x\n"
"security enabled: %02x\n"
"frame pending: %02x\n"
"ack requested: %02x\n"
"pan id compression: %02x\n"
"destination address mode: %02x\n"
"frame version: %02x\n"
"source address mode: %02x\n",
frame->fcf.frame_type,
frame->fcf.sec_enb,
frame->fcf.frame_pend,
frame->fcf.ack_req,
frame->fcf.panid_comp,
frame->fcf.dest_addr_m,
frame->fcf.frame_ver,
frame->fcf.src_addr_m);
}

View File

@ -0,0 +1,50 @@
#ifndef IEEE802154_FRAME
#define IEEE802154_FRAME
#include <stdio.h>
#include <stdint.h>
/* maximum 802.15.4 header length */
#define IEEE_802154_MAX_HDR_LEN 23
/* mininmum */
#define IEEE_802154_PAYLOAD_LEN 21
#define IEEE_802154_BEACON_FRAME 0
#define IEEE_802154_DATA_FRAME 1
#define IEEE_802154_ACK_FRAME 2
#define IEEE_802154_MAC_CMD_FRAME 3
#define IEEE_802154_SHORT_ADDR_M 2
#define IEEE_802154_LONG_ADDR_M 3
#define IEEE_802154_PAN_ID 0x1234
typedef struct __attribute__ ((packed)) {
uint8_t frame_type;
uint8_t sec_enb;
uint8_t frame_pend;
uint8_t ack_req;
uint8_t panid_comp;
uint8_t dest_addr_m;
uint8_t frame_ver;
uint8_t src_addr_m;
} ieee802154_fcf_frame_t;
typedef struct __attribute__ ((packed)) {
ieee802154_fcf_frame_t fcf;
uint8_t seq_nr;
uint16_t dest_pan_id;
uint8_t dest_addr[8];
uint16_t src_pan_id;
uint8_t src_addr[8];
uint8_t *payload;
uint8_t payload_len;
} ieee802154_frame_t;
uint8_t init_802154_frame(ieee802154_frame_t *frame, uint8_t *buf);
uint8_t get_802154_hdr_len(ieee802154_frame_t *frame);
uint8_t get_802154_pkt_len(void);
uint8_t read_802154_frame(uint8_t *buf, ieee802154_frame_t *frame, uint8_t len);
void print_802154_fcf_frame(ieee802154_frame_t *frame);
#endif /* IEEE802154_FRAME */

View File

@ -0,0 +1,31 @@
#include <mutex.h>
#include "semaphore.h"
void sem_init(sem_t *sem, int8_t value) {
sem->value = value;
mutex_init(&sem->mutex);
sem->locked = 0;
}
int sem_wait(sem_t *sem) {
int res;
if(--(sem->value) <= 0 && !sem->locked) {
sem->locked = !(sem->locked);
res = mutex_lock(&(sem->mutex));
if (res < 0) {
return res;
}
}
return 0;
}
int sem_signal(sem_t *sem) {
if (++(sem->value) > 0 && sem->locked) {
sem->locked = !(sem->locked);
mutex_unlock(&(sem->mutex),0);
}
return 0;
}

View File

@ -0,0 +1,17 @@
#ifndef SEMAPHORE_H
#define SEMAPHORE_H
#include <stdint.h>
#include <mutex.h>
typedef struct sem_t {
int8_t value;
int8_t locked;
mutex_t mutex;
} sem_t;
void sem_init(sem_t *sem, int8_t value);
int sem_wait(sem_t *sem);
int sem_signal(sem_t *sem);
#endif /* SEMAPHORE_H*/

View File

@ -0,0 +1,58 @@
#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

@ -0,0 +1,82 @@
/*
* Header file for serial number arithmetics [RFC1982]
*/
#ifndef SERIALNUMBER_H
#define SERIALNUMBER_H
#include <stdint.h>
typedef enum serial_comp_res_t {
LESS = 0,
EQUAL = 1,
GREATER = 2,
UNDEF = 3,
} serial_comp_res_t;
/**
* @brief Addition for 8-bit unsigned integers in serial number
* arithmetics (corresponding RFC1982 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 n in [0 .. 2^7 - 1] or
* -1 if n 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 RFC1982 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 RFC1982 section 3.1 if n in [0 .. 2^15 - 1] or
* -1 if n 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 RFC1982 section 3.1 if n in [0 .. 2^31 - 1] or
* -1 if n 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 RFC1982 section 3.2).
* @param[in] s1 first argument.
* @param[in] s2 second argument.
* @return LESS if s1 < s2.
* EQUAL if s1 = s2.
* GREATER if s1 > s2.
* else UNDEF (see RFC1982 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 RFC1982 section 3.2).
* @param[in] s1 first argument.
* @param[in] s2 second argument.
* @return LESS if s1 < s2.
* EQUAL if s1 = s2.
* GREATER if s1 > s2.
* else UNDEF (see RFC1982 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 LESS if s1 < s2.
* EQUAL if s1 = s2.
* GREATER if s1 > s2.
* else UNDEF (see RFC1982 section 3.2).
**/
serial_comp_res_t serial_comp32(uint32_t s1, uint32_t s2);
#endif /* SERIALNUMBER_H*/

View File

@ -0,0 +1,167 @@
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <mutex.h>
#include <thread.h>
#include <msg.h>
#include <posix_io.h>
#include <board_uart0.h>
#include "bordermultiplex.h"
#include "ieee802154_frame.h"
#include "flowcontrol.h"
#include "sixlowborder.h"
#include "sixlowip.h"
#include "sixlownd.h"
#include "serialnumber.h"
#include "sixlowerror.h"
#include "sys/net/net_help/net_help.h"
#define READER_STACK_SIZE 512
ipv6_addr_t abr_addr;
char serial_reader_stack[READER_STACK_SIZE];
uint16_t serial_reader_pid;
uint8_t serial_out_buf[BORDER_BUFFER_SIZE];
uint8_t serial_in_buf[BORDER_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]);
}
uint16_t border_get_serial_reader() {
return serial_reader_pid;
}
void serial_reader_f(void) {
int main_pid = 0;
int bytes;
msg_t m;
border_packet_t *uart_buf;
posix_open(uart0_handler_pid, 0);
msg_receive(&m);
main_pid = m.sender_pid;
while(1) {
posix_open(uart0_handler_pid, 0);
bytes = readpacket(get_serial_in_buffer(0), BORDER_BUFFER_SIZE);
if (bytes < 0) {
switch (bytes) {
case (-SIXLOWERROR_ARRAYFULL):{
printf("ERROR: Array was full\n");
break;
}
default:{
printf("ERROR: unknown\n");
break;
}
}
continue;
}
uart_buf = (border_packet_t*)get_serial_in_buffer(0);
if (uart_buf->empty == 0) {
if (uart_buf->type == BORDER_PACKET_CONF_TYPE) {
border_conf_header_t *conf_packet = (border_conf_header_t*)uart_buf;
if (conf_packet->conftype == BORDER_CONF_SYN) {
m.content.ptr = (char *)conf_packet;
msg_send(&m, main_pid, 1);
continue;
}
}
flowcontrol_deliver_from_uart(uart_buf, bytes);
}
}
}
uint8_t border_initialize(transceiver_type_t trans,ipv6_addr_t *border_router_addr) {
ipv6_addr_t addr;
serial_reader_pid = thread_create(
serial_reader_stack, READER_STACK_SIZE,
PRIORITY_MAIN-1, CREATE_STACKTEST,
serial_reader_f, "serial_reader");
if (border_router_addr == NULL) {
border_router_addr = &addr;
addr = flowcontrol_init();
}
/* only allow addresses generated accoding to
* RFC 4944 (Section 6) & RFC 2464 (Section 4) from short address
* -- for now
*/
if ( border_router_addr->uint16[4] != HTONS(IEEE_802154_PAN_ID ^ 0x0200) ||
border_router_addr->uint16[5] != HTONS(0x00FF) ||
border_router_addr->uint16[6] != HTONS(0xFE00)
) {
return SIXLOWERROR_ADDRESS;
}
// radio-address is 8-bit so this must be tested extra
if (border_router_addr->uint8[14] != 0) {
return SIXLOWERROR_ADDRESS;
}
memcpy(&(abr_addr.uint8[0]),&(border_router_addr->uint8[0]),16);
sixlowpan_init(trans,border_router_addr->uint8[15],1);
ipv6_init_iface_as_router();
return SUCCESS;
}
void border_send_ipv6_over_lowpan(struct ipv6_hdr_t *packet, uint8_t aro_flag, uint8_t sixco_flag) {
uint16_t offset = IPV6_HDR_LEN+HTONS(packet->length);
packet->flowlabel = HTONS(packet->flowlabel);
packet->length = HTONS(packet->length);
memset(buffer, 0, BUFFER_SIZE);
memcpy(buffer+LL_HDR_LEN, packet, offset);
lowpan_init((ieee_802154_long_t*)&(packet->destaddr.uint16[4]), (uint8_t*)packet);
}
void border_process_lowpan(void) {
msg_t m;
struct ipv6_hdr_t *ipv6_buf;
while(1) {
msg_receive(&m);
ipv6_buf = (struct ipv6_hdr_t *)m.content.ptr;
if (ipv6_buf->nextheader == PROTO_NUM_ICMPV6) {
struct icmpv6_hdr_t *icmp_buf = (struct icmpv6_hdr_t *)(((uint8_t *)ipv6_buf) + IPV6_HDR_LEN);
if (icmp_buf->type == ICMP_REDIRECT) {
continue;
}
if (icmpv6_demultiplex(icmp_buf) == 0) {
continue;
}
// Here, other ICMPv6 message types for ND may follow.
}
// TODO: Bei ICMPv6-Paketen entsprechende LoWPAN-Optionen verarbeiten und entfernen
multiplex_send_ipv6_over_uart(ipv6_buf);
}
}

View File

@ -0,0 +1,24 @@
/* 6LoWPAN Border Router header file */
#ifndef SIXLOWBORDER_H
#define SIXLOWBORDER_H
#include <stdint.h>
#include <mutex.h>
#include <transceiver.h>
#include "sixlowip.h"
#include "semaphore.h"
extern ipv6_addr_t abr_addr;
uint16_t border_get_serial_reader();
uint8_t *get_serial_out_buffer(int offset);
uint8_t *get_serial_in_buffer(int offset);
uint8_t border_initialize(transceiver_type_t trans,ipv6_addr_t *border_router_addr);
void border_send_ipv6_over_lowpan(struct ipv6_hdr_t *packet, uint8_t aro_flag, uint8_t sixco_flag);
void border_process_lowpan(void);
#endif /* SIXLOWBORDER_H*/

View File

@ -0,0 +1,16 @@
#ifndef SIXLOWERROR_H
#define SIXLOWERROR_H
#define SUCCESS 0
#define SIXLOWERROR_ARRAYFULL 132 // array is full
#define SIXLOWERROR_NULLPTR 133 // null pointer error
#define SIXLOWERROR_VALUE 134 // illegal value
#define SIXLOWERROR_ADDRESS 135 // illegal address
#define SIXLOWERROR_DISPATCH 136 // lowpan dispatch unknown
#define SIXLOWERROR_FSTFRAG 137 // first lowpan fragment not received
#define SIXLOWERROR_INVFRAG 138 // invalid fragment received
#define SIXLOWERROR_SCI 139 // source context not found
#define SIXLOWERROR_DCI 140 // destination context not found
#define SIXLOWERROR_CSUM 141 // wrong checksum
#endif /* SIXLOWERROR_H*/

View File

@ -0,0 +1,463 @@
#include <stdio.h>
#include <string.h>
#include <vtimer.h>
#include <mutex.h>
#include "msg.h"
#include "sixlowip.h"
#include "sixlowmac.h"
#include "sixlownd.h"
#include "sixlowpan.h"
#include "sys/net/destiny/in.h"
#include "sys/net/destiny/socket.h"
#include "sys/net/net_help/net_help.h"
#include "sys/net/net_help/msg_help.h"
uint8_t buffer[BUFFER_SIZE];
msg_t msg_queue[IP_PKT_RECV_BUF_SIZE];
struct ipv6_hdr_t* ipv6_buf;
struct icmpv6_hdr_t* icmp_buf;
uint8_t ipv6_ext_hdr_len;
uint8_t *nextheader;
iface_t iface;
uint8_t iface_addr_list_count = 0;
int udp_packet_handler_pid = 0;
int tcp_packet_handler_pid = 0;
//uint8_t *udp_packet_buffer;
//uint8_t *tcp_packet_buffer;
//mutex_t buf_mutex;
struct ipv6_hdr_t* get_ipv6_buf(void){
return ((struct ipv6_hdr_t*)&(buffer[LL_HDR_LEN]));
}
struct icmpv6_hdr_t* get_icmpv6_buf(uint8_t ext_len){
return ((struct icmpv6_hdr_t*)&(buffer[LLHDR_IPV6HDR_LEN + ext_len]));
}
uint8_t * get_payload_buf(uint8_t ext_len){
return &(buffer[LLHDR_IPV6HDR_LEN + ext_len]);
}
void sixlowpan_bootstrapping(void){
init_rtr_sol(OPT_SLLAO);
}
void sixlowpan_send(ipv6_addr_t *addr, uint8_t *payload, uint16_t p_len, uint8_t next_header){
ipv6_buf = get_ipv6_buf();
icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len);
packet_length = 0;
ipv6_buf->version_trafficclass = IPV6_VER;
ipv6_buf->trafficclass_flowlabel = 0;
ipv6_buf->flowlabel = 0;
ipv6_buf->nextheader = next_header;
ipv6_buf->hoplimit = MULTIHOP_HOPLIMIT;
ipv6_buf->length = p_len;
memcpy(&(ipv6_buf->destaddr), addr, 16);
ipv6_get_saddr(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr));
uint8_t *p_ptr = get_payload_buf(ipv6_ext_hdr_len);
memcpy(p_ptr,payload,p_len);
packet_length = IPV6_HDR_LEN + p_len;
#ifdef MODULE_DESTINY
if (next_header == IPPROTO_TCP) {
print_tcp_status(OUT_PACKET, ipv6_buf, (tcp_hdr_t *)(payload));
}
#endif
lowpan_init((ieee_802154_long_t*)&(ipv6_buf->destaddr.uint16[4]),(uint8_t*)ipv6_buf);
}
int icmpv6_demultiplex(const struct icmpv6_hdr_t *hdr) {
switch(hdr->type) {
case(ICMP_RTR_SOL):{
printf("INFO: packet type: icmp router solicitation\n");
/* processing router solicitation */
recv_rtr_sol();
/* init solicited router advertisment*/
break;
}
case(ICMP_RTR_ADV):{
printf("INFO: packet type: icmp router advertisment\n");
/* processing router advertisment */
recv_rtr_adv();
/* init neighbor solicitation */
break;
}
case(ICMP_NBR_SOL):{
printf("INFO: packet type: icmp neighbor solicitation\n");
recv_nbr_sol();
break;
}
case(ICMP_NBR_ADV):{
printf("INFO: packet type: icmp neighbor advertisment\n");
recv_nbr_adv();
break;
}
default:
return -1;
}
return 0;
}
void ipv6_process(void){
msg_t m_recv, m_send;
msg_init_queue(msg_queue, IP_PKT_RECV_BUF_SIZE);
while(1){
msg_receive(&m_recv);
//ipv6_buf = get_ipv6_buf();
ipv6_buf = (struct ipv6_hdr_t*) m_recv.content.ptr;
/* identifiy packet */
nextheader = &ipv6_buf->nextheader;
switch(*nextheader) {
case(PROTO_NUM_ICMPV6):{
/* checksum test*/
if(icmpv6_csum(PROTO_NUM_ICMPV6) != 0xffff){
printf("ERROR: wrong checksum\n");
}
icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len);
icmpv6_demultiplex(icmp_buf);
break;
}
case(IPPROTO_TCP):
{
// printf("INFO: TCP Packet received.\n");
if (tcp_packet_handler_pid != 0)
{
m_send.content.ptr = (char*) ipv6_buf;
net_msg_send_recv(&m_send, &m_recv, tcp_packet_handler_pid, FID_TCP_PH, FID_SIXLOWIP_TCP);
}
else
{
printf("INFO: No TCP handler registered.\n");
}
break;
}
case(IPPROTO_UDP):
{
printf("INFO: UDP Packet received.\n");
if (udp_packet_handler_pid != 0)
{
m_send.content.ptr = (char*) ipv6_buf;
net_msg_send_recv(&m_send, &m_recv, udp_packet_handler_pid, FID_UDP_PH, FID_SIXLOWIP_UDP);
}
else
{
printf("INFO: No UDP handler registered.\n");
}
break;
}
case(PROTO_NUM_NONE):
{
printf("INFO: Packet with no Header following the IPv6 Header received.\n");
break;
}
default:
break;
}
}
}
void ipv6_iface_add_addr(ipv6_addr_t *addr, uint8_t state, uint32_t val_ltime, uint32_t pref_ltime, uint8_t type){
if(ipv6_addr_unspec_match(addr) == 128){
printf("ERROR: unspecified address (::) can't be assigned to interface.\n");
return;
}
if(ipv6_iface_addr_match(addr) != 0) {
return;
}
if(iface_addr_list_count < IFACE_ADDR_LIST_LEN){
memcpy(&(iface.addr_list[iface_addr_list_count].addr.uint8[0]), &(addr->uint8[0]), 16);
iface.addr_list[iface_addr_list_count].state = state;
timex_t valtime = {val_ltime, 0};
timex_t preftime = {pref_ltime, 0};
timex_t now = vtimer_now();
iface.addr_list[iface_addr_list_count].val_ltime = timex_add(now, valtime);
iface.addr_list[iface_addr_list_count].pref_ltime = timex_add(now, preftime);
iface.addr_list[iface_addr_list_count].type = type;
iface_addr_list_count++;
// Register to Solicited-Node multicast address according to RFC 4291
if (type == ADDR_TYPE_ANYCAST || type == ADDR_TYPE_LINK_LOCAL ||
type == ADDR_TYPE_GLOBAL || type == ADDR_TYPE_UNICAST) {
ipv6_addr_t sol_node_mcast_addr;
ipv6_set_sol_node_mcast_addr(addr, &sol_node_mcast_addr);
if (ipv6_iface_addr_match(&sol_node_mcast_addr) == NULL) {
ipv6_iface_add_addr(&sol_node_mcast_addr, state, val_ltime, pref_ltime, ADDR_TYPE_SOL_NODE_MCAST);
}
}
}
}
addr_list_t * ipv6_iface_addr_match(ipv6_addr_t *addr){
int i;
for(i = 0; i < iface_addr_list_count; i++){
if(memcmp(&(iface.addr_list[i].addr.uint8[0]),
&(addr->uint8[0]),16) == 0){
return &(iface.addr_list[i]);
}
}
return NULL;
}
addr_list_t * ipv6_iface_addr_prefix_eq(ipv6_addr_t *addr){
int i;
for(i = 0; i < iface_addr_list_count; i++){
if(memcmp(&(iface.addr_list[i].addr.uint8[0]),
&(addr->uint8[0]), 8) == 0){
return &(iface.addr_list[i]);
}
}
return NULL;
}
void ipv6_iface_print_addrs(void){
for(int i = 0; i < iface_addr_list_count; i++){
ipv6_print_addr(&(iface.addr_list[i].addr));
}
}
void ipv6_init_addr_prefix(ipv6_addr_t *inout, ipv6_addr_t *prefix){
inout->uint16[0] = prefix->uint16[0];
inout->uint16[1] = prefix->uint16[1];
inout->uint16[2] = prefix->uint16[2];
inout->uint16[3] = prefix->uint16[3];
memcpy(&(inout->uint8[8]),&(iface.laddr.uint8[0]), 8);
}
void ipv6_set_prefix(ipv6_addr_t *inout, ipv6_addr_t *prefix){
inout->uint16[0] = prefix->uint16[0];
inout->uint16[1] = prefix->uint16[1];
inout->uint16[2] = prefix->uint16[2];
inout->uint16[3] = prefix->uint16[3];
inout->uint16[4] = 0;
inout->uint16[5] = 0;
inout->uint16[6] = 0;
inout->uint16[7] = 0;
}
void ipv6_set_all_rtrs_mcast_addr(ipv6_addr_t *ipaddr){
ipaddr->uint16[0] = HTONS(0xff02);
ipaddr->uint16[1] = 0;
ipaddr->uint16[2] = 0;
ipaddr->uint16[3] = 0;
ipaddr->uint16[4] = 0;
ipaddr->uint16[5] = 0;
ipaddr->uint16[6] = 0;
ipaddr->uint16[7] = HTONS(0x0002);
}
void ipv6_set_all_nds_mcast_addr(ipv6_addr_t *ipaddr){
ipaddr->uint16[0] = HTONS(0xff02);
ipaddr->uint16[1] = 0;
ipaddr->uint16[2] = 0;
ipaddr->uint16[3] = 0;
ipaddr->uint16[4] = 0;
ipaddr->uint16[5] = 0;
ipaddr->uint16[6] = 0;
ipaddr->uint16[7] = HTONS(0x0001);
}
void ipv6_set_loaddr(ipv6_addr_t *ipaddr){
ipaddr->uint16[0] = 0;
ipaddr->uint16[1] = 0;
ipaddr->uint16[2] = 0;
ipaddr->uint16[3] = 0;
ipaddr->uint16[4] = 0;
ipaddr->uint16[5] = 0;
ipaddr->uint16[6] = 0;
ipaddr->uint16[7] = HTONS(0x0001);
}
void ipv6_get_saddr(ipv6_addr_t *src, ipv6_addr_t *dst){
/* try to find best match if dest is not mcast or link local */
int8_t itmp = -1;
uint8_t tmp = 0;
uint8_t bmatch = 0;
if(!(ipv6_prefix_ll_match(dst)) && !(ipv6_prefix_mcast_match(dst))){
for(int i = 0; i < IFACE_ADDR_LIST_LEN; i++){
if(iface.addr_list[i].state == ADDR_STATE_PREFERRED){
if(!(ipv6_prefix_ll_match(&(iface.addr_list[i].addr)))){
tmp = ipv6_get_addr_match(dst, &(iface.addr_list[i].addr));
if(tmp >= bmatch){
bmatch = tmp;
itmp = i;
}
}
}
}
} else {
for(int j=0; j < IFACE_ADDR_LIST_LEN; j++){
if((iface.addr_list[j].state == ADDR_STATE_PREFERRED) &&
ipv6_prefix_ll_match(&(iface.addr_list[j].addr))){
itmp = j;
}
}
}
if(itmp == -1){
memset(src, 0, 16);
} else {
memcpy(src, &(iface.addr_list[itmp].addr), 16);
}
}
uint8_t ipv6_get_addr_match(ipv6_addr_t *src, ipv6_addr_t *dst){
uint8_t val = 0, xor;
for(int i = 0; i < 16; i++){
/* if bytes are equal add 8 */
if(src->uint8[i] == dst->uint8[i]){
val += 8;
} else {
xor = src->uint8[i] ^ dst->uint8[i];
/* while bits from byte equal add 1 */
for(int j = 0; j < 8; j++){
if((xor & 0x80) == 0){
val++;
xor = xor << 1;
} else {
break;
}
}
}
}
return val;
}
void ipv6_set_ll_prefix(ipv6_addr_t *ipaddr){
ipaddr->uint16[0] = HTONS(0xfe80);
ipaddr->uint16[1] = 0;
ipaddr->uint16[2] = 0;
ipaddr->uint16[3] = 0;
}
void ipv6_init_address(ipv6_addr_t *addr, uint16_t addr0, uint16_t addr1,
uint16_t addr2, uint16_t addr3, uint16_t addr4,
uint16_t addr5, uint16_t addr6, uint16_t addr7){
addr->uint16[0] = HTONS(addr0);
addr->uint16[1] = HTONS(addr1);
addr->uint16[2] = HTONS(addr2);
addr->uint16[3] = HTONS(addr3);
addr->uint16[4] = HTONS(addr4);
addr->uint16[5] = HTONS(addr5);
addr->uint16[6] = HTONS(addr6);
addr->uint16[7] = HTONS(addr7);
}
uint8_t ipv6_prefix_ll_match(ipv6_addr_t *addr){
if(addr->uint8[0] == 0xfe && addr->uint8[1] == 0x80){
return 1;
}
return 0;
}
uint8_t ipv6_prefix_mcast_match(ipv6_addr_t *addr){
if(addr->uint8[0] == 0xff && addr->uint8[1] == 0x02){
return 1;
}
return 0;
}
uint8_t ipv6_addr_unspec_match(ipv6_addr_t *addr){
if((addr->uint16[0] == 0) && (addr->uint16[1] == 0) &&
(addr->uint16[2] == 0) && (addr->uint16[3] == 0) &&
(addr->uint16[4] == 0) && (addr->uint16[5] == 0) &&
(addr->uint16[6] == 0) && (addr->uint16[7] == 0)){
return 1;
}
return 0;
}
uint8_t ipv6_addr_sol_node_mcast_match(ipv6_addr_t *addr){
/* note: cool if-condition*/
if((addr->uint8[0] == 0xFF) && (addr->uint8[1] == 0x02) &&
(addr->uint16[1] == 0x00) && (addr->uint16[2] == 0x00) &&
(addr->uint16[3] == 0x00) && (addr->uint16[4] == 0x00) &&
(addr->uint8[10] == 0x00) && (addr->uint8[11] == 0x01) &&
(addr->uint8[12] == 0xFF)){
return 1;
}
return 0;
}
void ipv6_set_sol_node_mcast_addr(ipv6_addr_t *addr_in, ipv6_addr_t *addr_out){
/* copy only the last 24-bit of the ip-address that is beeing resolved */
addr_out->uint16[0] = HTONS(0xff02);
addr_out->uint16[1] = 0;
addr_out->uint16[2] = 0;
addr_out->uint16[3] = 0;
addr_out->uint16[4] = 0;
addr_out->uint16[5] = HTONS(0x0001);
addr_out->uint8[12] = 0xff;
addr_out->uint8[13] = addr_in->uint8[13];
addr_out->uint16[7] = addr_in->uint16[7];
}
void ipv6_print_addr(ipv6_addr_t *ipaddr){
printf("%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
((uint8_t *)ipaddr)[0], ((uint8_t *)ipaddr)[1], ((uint8_t *)ipaddr)[2],
((uint8_t *)ipaddr)[3], ((uint8_t *)ipaddr)[4], ((uint8_t *)ipaddr)[5],
((uint8_t *)ipaddr)[6], ((uint8_t *)ipaddr)[7], ((uint8_t *)ipaddr)[8],
((uint8_t *)ipaddr)[9], ((uint8_t *)ipaddr)[10], ((uint8_t *)ipaddr)[11],
((uint8_t *)ipaddr)[12], ((uint8_t *)ipaddr)[13], ((uint8_t *)ipaddr)[14],
((uint8_t *)ipaddr)[15]);
}
uint8_t ipv6_next_hdr_unknown(uint8_t next_hdr) {
return next_hdr == PROTO_NUM_ICMPV6 ||
next_hdr == PROTO_NUM_NONE;
}
uint32_t get_remaining_time(timex_t *t){
timex_t now = vtimer_now();
return (timex_sub(*t, now).seconds);
}
void set_remaining_time(timex_t *t, uint32_t time){
timex_t tmp = {time, 0};
*t = timex_add(vtimer_now(), tmp);
}
void ipv6_init_iface_as_router(void) {
ipv6_addr_t addr;
ipv6_set_all_rtrs_mcast_addr(&addr);
ipv6_iface_add_addr(&addr,ADDR_STATE_PREFERRED,0,0,ADDR_TYPE_MULTICAST);
}
uint8_t ipv6_is_router(void) {
ipv6_addr_t addr;
ipv6_set_all_rtrs_mcast_addr(&addr);
if (ipv6_iface_addr_match(&addr) != NULL) {
return 1;
}
return 0;
}
void set_tcp_packet_handler_pid(int pid) {
tcp_packet_handler_pid = pid;
}
void set_udp_packet_handler_pid(int pid) {
udp_packet_handler_pid = pid;
}

View File

@ -0,0 +1,166 @@
/* 6LoWPAN IP header file */
#ifndef SIXLOWIP_H
#define SIXLOWIP_H
#include <stdint.h>
#include <timex.h>
#include <mutex.h>
/* set maximum transmission unit */
#define MTU 256
/* IPv6 field values */
#define IPV6_VER 0x60
#define PROTO_NUM_ICMPV6 58
#define PROTO_NUM_NONE 59
#define ND_HOPLIMIT 0xFF
#define SIXLOWPAN_IPV6_LL_ADDR_LEN 8
/* size of global buffer */
#define BUFFER_SIZE (LL_HDR_LEN + MTU)
#define MULTIHOP_HOPLIMIT 64
#define IP_PKT_RECV_BUF_SIZE 64
#define DEBUGLINE printf("%s:%d\n",__FILE__,__LINE__)
/* extern variables */
extern uint8_t ipv6_ext_hdr_len;
extern uint8_t opt_hdr_len;
extern uint16_t packet_length;
extern uint8_t packet_dispatch;
extern uint8_t iface_addr_list_count;
extern mutex_t buf_mutex;
extern double start;
/* base header lengths */
#define LL_HDR_LEN 0x4
#define ICMPV6_HDR_LEN 0x4
#define IPV6_HDR_LEN 0x28
#define LLHDR_IPV6HDR_LEN (LL_HDR_LEN + IPV6_HDR_LEN)
#define LLHDR_ICMPV6HDR_LEN (LL_HDR_LEN + IPV6_HDR_LEN + ICMPV6_HDR_LEN)
#define IPV6HDR_ICMPV6HDR_LEN (IPV6_HDR_LEN + ipv6_ext_hdr_len + ICMPV6_HDR_LEN)
#define IFACE_ADDR_LIST_LEN 10 // maybe to much
/* rfc 4862 section 2. address states */
#define ADDR_STATE_TENTATIVE 0
#define ADDR_STATE_PREFERRED 1
#define ADDR_STATE_DEPRECATED 2
/* addresses with this state are always permitted */
#define ADDR_STATE_ANY 4
/* how the address is configured */
#define ADDR_CONFIGURED_AUTO 1
#define ADDR_CONFIGURED_MANUAL 2
/* address types */
#define ADDR_TYPE_NONE 0
#define ADDR_TYPE_UNICAST 1
#define ADDR_TYPE_MULTICAST 2
#define ADDR_TYPE_ANYCAST 3
#define ADDR_TYPE_SOL_NODE_MCAST 4
#define ADDR_TYPE_LOOPBACK 5
#define ADDR_TYPE_LINK_LOCAL 6
#define ADDR_TYPE_GLOBAL 7
/* dispatch types */
#define DISPATCH_TYPE_IPV6 0x41
#define DISPATCH_TYPE_LOWPAN_HC1 0x42
/* compression types */
#define COMPRESSION_TYPE_NONE
/* buffer */
extern uint8_t buffer[BUFFER_SIZE];
/* ipv6 extension header length */
typedef union __attribute__ ((packed)) ipv6_addr_t{
uint8_t uint8[16];
uint16_t uint16[8];
uint32_t uint32[4];
} ipv6_addr_t;
struct __attribute__ ((packed)) icmpv6_hdr_t{
uint8_t type;
uint8_t code;
uint16_t checksum;
};
typedef struct __attribute__ ((packed)) ipv6_hdr_t{
uint8_t version_trafficclass;
uint8_t trafficclass_flowlabel;
uint16_t flowlabel;
uint16_t length;
uint8_t nextheader;
uint8_t hoplimit;
ipv6_addr_t srcaddr;
ipv6_addr_t destaddr;
} ipv6_hdr_t;
/* link layer addressing */
typedef union __attribute__ ((packed)) ieee_802154_long_t {
uint8_t uint8[8];
uint16_t uint16[4];
} ieee_802154_long_t;
typedef union __attribute__ ((packed)) ieee_802154_short_t {
uint8_t uint8[2];
uint16_t uint16[1];
} ieee_802154_short_t;
typedef struct __attribute__ ((packed)) addr_list_t {
uint8_t state;
timex_t val_ltime;
timex_t pref_ltime;
uint8_t type;
ipv6_addr_t addr;
} addr_list_t;
typedef struct __attribute__ ((packed)) iface_t {
ieee_802154_short_t saddr;
ieee_802154_long_t laddr;
addr_list_t addr_list[IFACE_ADDR_LIST_LEN];
uint8_t adv_cur_hop_limit;
uint32_t adv_reachable_time;
uint32_t adv_retrans_timer;
} iface_t;
extern iface_t iface;
/* function prototypes */
struct icmpv6_hdr_t* get_icmpv6_buf(uint8_t ext_len);
struct ipv6_hdr_t* get_ipv6_buf(void);
uint8_t * get_payload_buf(uint8_t ext_len);
int icmpv6_demultiplex(const struct icmpv6_hdr_t *hdr);
void ipv6_init_iface_as_router(void);
uint8_t ipv6_is_router(void);
void ipv6_set_ll_prefix(ipv6_addr_t *ipaddr);
void ipv6_set_all_rtrs_mcast_addr(ipv6_addr_t *ipaddr);
void ipv6_set_all_nds_mcast_addr(ipv6_addr_t *ipaddr);
void ipv6_set_loaddr(ipv6_addr_t *ipaddr);
void ipv6_set_sol_node_mcast_addr(ipv6_addr_t *addr_in, ipv6_addr_t *addr_out);
void sixlowpan_bootstrapping(void);
void sixlowpan_send(ipv6_addr_t *addr, uint8_t *payload, uint16_t p_len, uint8_t next_header);
void ipv6_print_addr(ipv6_addr_t *ipaddr);
void ipv6_process(void);
void ipv6_get_saddr(ipv6_addr_t *src, ipv6_addr_t *dst);
uint8_t ipv6_get_addr_match(ipv6_addr_t *src, ipv6_addr_t *dst);
uint8_t ipv6_prefix_mcast_match(ipv6_addr_t *addr);
uint8_t ipv6_prefix_ll_match(ipv6_addr_t *addr);
void ipv6_iface_add_addr(ipv6_addr_t* addr, uint8_t state, uint32_t val_ltime,
uint32_t pref_ltime, uint8_t type);
addr_list_t * ipv6_iface_addr_prefix_eq(ipv6_addr_t *addr);
addr_list_t * ipv6_iface_addr_match(ipv6_addr_t *addr);
void ipv6_iface_print_addrs(void);
void ipv6_init_addr_prefix(ipv6_addr_t *inout, ipv6_addr_t *prefix);
void ipv6_init_address(ipv6_addr_t *addr, uint16_t addr0, uint16_t addr1,
uint16_t addr2, uint16_t addr3, uint16_t addr4,
uint16_t addr5, uint16_t addr6, uint16_t addr7);
uint32_t get_remaining_time(timex_t *t);
void set_remaining_time(timex_t *t, uint32_t time);
void ipv6_set_prefix(ipv6_addr_t *inout, ipv6_addr_t *prefix);
uint8_t ipv6_addr_unspec_match(ipv6_addr_t *addr);
uint8_t ipv6_addr_sol_node_mcast_match(ipv6_addr_t *addr);
uint8_t ipv6_next_hdr_unrec(uint8_t next_hdr);
void set_tcp_packet_handler_pid(int pid);
void set_udp_packet_handler_pid(int pid);
#endif /* SIXLOWIP_H*/

View File

@ -0,0 +1,204 @@
/* 6LoWPAN MAC - layer 2 implementations */
#include <stdlib.h>
#include <string.h>
#include "sixlowmac.h"
#include "sixlowip.h"
#include "sixlownd.h"
#include "sixlowpan.h"
#include <ltc4150.h>
#include <hwtimer.h>
#include "thread.h"
#include "msg.h"
#include "radio/radio.h"
#include "transceiver.h"
#include "vtimer.h"
#include "ieee802154_frame.h"
#include "sys/net/net_help/net_help.h"
char radio_stack_buffer[RADIO_STACK_SIZE];
msg_t msg_q[RADIO_RCV_BUF_SIZE];
uint8_t snd_buffer[RADIO_SND_BUF_SIZE][PAYLOAD_SIZE];
uint8_t r_src_addr;
uint8_t buf[PAYLOAD_SIZE];
uint16_t packet_length;
static uint8_t macdsn;
//static uint8_t macbsn;
mutex_t buf_mutex;
static radio_packet_t p;
static msg_t mesg;
int transceiver_type;
static transceiver_command_t tcmd;
uint8_t get_radio_address(void){
int16_t address;
tcmd.transceivers = transceiver_type;
tcmd.data = &address;
mesg.content.ptr = (char*)&tcmd;
mesg.type = GET_ADDRESS;
msg_send_receive(&mesg,&mesg,transceiver_pid);
return (uint8_t)address;
}
void set_radio_address(uint8_t addr){
int16_t address = (int16_t)addr;
tcmd.transceivers = transceiver_type;
tcmd.data = &address;
mesg.content.ptr = (char*)&tcmd;
mesg.type = SET_ADDRESS;
msg_send_receive(&mesg, &mesg, transceiver_pid);
}
void set_radio_channel(uint8_t channel){
int16_t chan = (int16_t)channel;
tcmd.transceivers = transceiver_type;
tcmd.data = &chan;
mesg.content.ptr = (char*)&tcmd;
mesg.type = SET_CHANNEL;
msg_send_receive(&mesg,&mesg,transceiver_pid);
}
void switch_to_rx(void){
mesg.type = SWITCH_RX;
mesg.content.ptr = (char*) &tcmd;
tcmd.transceivers = TRANSCEIVER_CC1100;
msg_send(&mesg, transceiver_pid, 1);
}
void init_802154_short_addr(ieee_802154_short_t *saddr){
saddr->uint8[0] = 0;
saddr->uint8[1] = get_radio_address();
}
ieee_802154_long_t* mac_get_eui(ipv6_addr_t *ipaddr){
return ((ieee_802154_long_t *) &(ipaddr->uint8[8]));
}
void init_802154_long_addr(ieee_802154_long_t *laddr){
// 16bit Pan-ID:16-zero-bits:16-bit-short-addr = 48bit
laddr->uint16[0] = IEEE_802154_PAN_ID;
/* RFC 4944 Section 6 / RFC 2464 Section 4 */
laddr->uint8[0] ^= 0x02;
laddr->uint8[2] = 0;
laddr->uint8[3] = 0xFF;
laddr->uint8[4] = 0xFE;
laddr->uint8[5] = 0;
laddr->uint8[6] = 0;
laddr->uint8[7] = get_radio_address();
}
void recv_ieee802154_frame(void){
msg_t m;
radio_packet_t *p;
uint8_t hdrlen, length;
ieee802154_frame_t frame;
msg_init_queue(msg_q, RADIO_RCV_BUF_SIZE);
while (1) {
msg_receive(&m);
if (m.type == PKT_PENDING) {
p = (radio_packet_t*) m.content.ptr;
hdrlen = read_802154_frame(p->data, &frame, p->length);
length = p->length - hdrlen;
/* deliver packet to network(6lowpan)-layer */
lowpan_read(frame.payload, length, (ieee_802154_long_t*)&frame.src_addr,
(ieee_802154_long_t*)&frame.dest_addr);
p->processing--;
}
else if (m.type == ENOBUFFER) {
puts("Transceiver buffer full");
}
else {
puts("Unknown packet received");
}
}
}
void set_ieee802154_fcf_values(ieee802154_frame_t *frame, uint8_t dest_mode,
uint8_t src_mode){
frame->fcf.frame_type = IEEE_802154_DATA_FRAME;
frame->fcf.sec_enb = 0;
frame->fcf.frame_pend = 0;
frame->fcf.ack_req = 0;
frame->fcf.panid_comp = 0;
frame->fcf.frame_ver = 0;
frame->fcf.src_addr_m = src_mode;
frame->fcf.dest_addr_m = dest_mode;
}
void set_ieee802154_frame_values(ieee802154_frame_t *frame){
// TODO: addresse aus ip paket auslesen und in frame einfuegen
frame->dest_pan_id = IEEE_802154_PAN_ID;
frame->src_pan_id = IEEE_802154_PAN_ID;
frame->seq_nr = macdsn;
macdsn++;
}
void send_ieee802154_frame(ieee_802154_long_t *addr, uint8_t *payload,
uint8_t length, uint8_t mcast){
uint16_t daddr;
r_src_addr = get_radio_address();
mesg.type = SND_PKT;
mesg.content.ptr = (char*) &tcmd;
tcmd.transceivers = transceiver_type;
tcmd.data = &p;
ieee802154_frame_t frame;
memset(&frame, 0, sizeof(frame));
set_ieee802154_fcf_values(&frame, IEEE_802154_LONG_ADDR_M,
IEEE_802154_LONG_ADDR_M);
set_ieee802154_frame_values(&frame);
memcpy(&(frame.dest_addr[0]), &(addr->uint8[0]), 8);
memcpy(&(frame.src_addr[0]), &(iface.laddr.uint8[0]), 8);
daddr = HTONS(addr->uint16[3]);
frame.payload = payload;
frame.payload_len = length;
uint8_t hdrlen = get_802154_hdr_len(&frame);
memset(&buf,0,PAYLOAD_SIZE);
init_802154_frame(&frame,(uint8_t*)&buf);
memcpy(&buf[hdrlen],frame.payload,frame.payload_len);
/* mutex unlock */
mutex_unlock(&buf_mutex, 0);
p.length = hdrlen + frame.payload_len;
if(mcast == 0){
p.dst = daddr;
} else {
p.dst = 0;
}
p.data = buf;
msg_send(&mesg, transceiver_pid, 1);
hwtimer_wait(5000);
}
void sixlowmac_init(transceiver_type_t type){
int recv_pid = thread_create(radio_stack_buffer, RADIO_STACK_SIZE,
PRIORITY_MAIN-2, CREATE_STACKTEST, recv_ieee802154_frame , "radio");
hwtimer_init();
transceiver_type = type;
transceiver_init(transceiver_type);
transceiver_start();
transceiver_register(type, recv_pid);
macdsn = rand() % 256;
}

View File

@ -0,0 +1,26 @@
/* 6LoWPAN MAC header file */
#ifndef SIXLOWMAC_H
#define SIXLOWMAC_H
#include <stdio.h>
#include <stdint.h>
#include "sixlowip.h"
#include "radio/radio.h"
#include <transceiver.h>
#define RADIO_STACK_SIZE 3072
#define RADIO_RCV_BUF_SIZE 64
#define RADIO_SND_BUF_SIZE 100
#define RADIO_SENDING_DELAY 1000
uint8_t get_radio_address(void);
void set_radio_address(uint8_t addr);
void send_ieee802154_frame(ieee_802154_long_t *addr, uint8_t *payload,
uint8_t length, uint8_t mcast);
void init_802154_long_addr(ieee_802154_long_t *laddr);
void init_802154_short_addr(ieee_802154_short_t *saddr);
void sixlowmac_init(transceiver_type_t type);
ieee_802154_long_t* mac_get_eui(ipv6_addr_t *ipaddr);
#endif /* SIXLOWMAC_H*/

1196
sys/net/sixlowpan/sixlownd.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,257 @@
/* 6LoWPAN ND header file */
#ifndef SIXLOWND_H
#define SIXLOWND_H
#include <stdint.h>
#include "vtimer.h"
#include "sixlowpan.h"
#include "sixlowip.h"
/* parameter problem [rfc4443] */
#define PARA_PROB_LEN 8
#define PARA_PROB_CODE_ERR 0 /* Erroneous header field encountered */
#define PARA_PROB_NXT_HDR_UNREC 1 /* Unrecognized Next Header type encountered */
#define PARA_PROB_IPV6_OPT_UNREC 2 /* Unrecognized IPv6 option encountered */
/* router solicitation */
#define RTR_SOL_LEN 4
#define RTR_SOL_INTERVAL 4
#define RTR_SOL_MAX 3
/* router advertisment */
#define RTR_ADV_M_FLAG 0
#define RTR_ADV_O_FLAG 0
#define RTR_ADV_MAX 3
#define RTR_ADV_MAX_INTERVAL 600
#define RTR_ADV_LEN 12
/* neighbour solicitation */
#define NBR_SOL_LEN 20
/* neighbour advertisement */
#define NBR_ADV_LEN 20
#define NBR_ADV_FLAG_R 0x80
#define NBR_ADV_FLAG_S 0x40
#define NBR_ADV_FLAG_O 0x20
/* icmp message types rfc4443 */
#define ICMP_PARA_PROB 4
/* icmp message types rfc4861 4.*/
#define ICMP_RTR_ADV 134
#define ICMP_RTR_SOL 133
#define ICMP_NBR_ADV 136
#define ICMP_NBR_SOL 135
#define ICMP_REDIRECT 137 // will be filtered out by the border router
/* stllao option rfc4861 4.6.1 */
#define OPT_STLLAO_MIN_LEN 8
#define OPT_STLLAO_MAX_LEN 16
#define OPT_SLLAO_TYPE 1
#define OPT_TLLAO_TYPE 2
/* prefix info option rfc 4.6.2 */
#define OPT_PI_LIST_LEN 5 //TODO: initalwert suchen
#define OPT_PI_TYPE 3
#define OPT_PI_LEN 4
#define OPT_PI_HDR_LEN 32
#define OPT_PI_FLAG_A 0x40
#define OPT_PI_FLAG_L 0x80
#define OPT_PI_VLIFETIME_INFINITE 0xffffffff
/* mtu option rfc4861 4.6.4 */
#define OPT_MTU_TYPE 5
#define OPT_MTU_LEN 1
#define OPT_MTU_HDR_LEN 8
/* aro - address registration option draft-ietf-6lowpan-nd-14 4.2 */
#define OPT_ARO_TYPE 31 // TBD1
#define OPT_ARO_LEN 2
#define OPT_ARO_HDR_LEN 16
#define OPT_ARO_LTIME 300 // geeigneten wert finden
#define OPT_ARO_STATE_SUCCESS 0
#define OPT_ARO_STATE_DUP_ADDR 1
#define OPT_ARO_STATE_NBR_CACHE_FULL 2
/* 6lowpan context option */
#define OPT_6CO_TYPE 32
#define OPT_6CO_MIN_LEN 2
#define OPT_6CO_MAX_LEN 3
#define OPT_6CO_HDR_LEN 8
#define OPT_6CO_LTIME 5 // geeigneten Wert finden
#define OPT_6CO_FLAG_C 0x10
#define OPT_6CO_FLAG_CID 0x0F
#define OPT_6CO_FLAG_C_VALUE_SET 1
#define OPT_6CO_FLAG_C_VALUE_UNSET 0
/* authoritative border router option */
#define OPT_ABRO_TYPE 33
#define OPT_ABRO_LEN 3
#define OPT_ABRO_HDR_LEN 24
/* authoritive border router cache size */
#define ABR_CACHE_SIZE 2
/* neighbor cache size */
#define NBR_CACHE_SIZE 8
#define NBR_CACHE_TYPE_GC 1
#define NBR_CACHE_TYPE_REG 2
#define NBR_CACHE_TYPE_TEN 3
#define NBR_CACHE_LTIME_TEN 20
/* neighbor status values */
#define NBR_STATUS_INCOMPLETE 0
#define NBR_STATUS_REACHABLE 1
#define NBR_STATUS_STALE 2
#define NBR_STATUS_DELAY 3
#define NBR_STATUS_PROBE 4
/* default router list size */
#define DEF_RTR_LST_SIZE 3 // geeigneten wert finden
extern unsigned int nd_nbr_cache_rem_pid;
enum option_types_t {
OPT_SLLAO = 1,
OPT_TLLAO,
OPT_PI,
OPT_MTU,
OPT_ARO,
OPT_6CO,
OPT_ABRO,
OPT_DAR,
OPT_DAC,
};
typedef struct __attribute__ ((packed)) opt_buf_t {
uint8_t type;
uint8_t length;
} opt_buf_t;
typedef struct __attribute__ ((packed)) opt_stllao_t {
uint8_t type;
uint8_t length;
} opt_stllao_t;
typedef struct __attribute__ ((packed)) opt_mtu_t {
uint8_t type;
uint8_t length;
uint16_t reserved;
uint32_t mtu;
} opt_mtu_t;
typedef struct __attribute__ ((packed)) opt_pi_t {
uint8_t type;
uint8_t length;
uint8_t prefix_length;
uint8_t l_a_reserved1;
uint32_t val_ltime;
uint32_t pref_ltime;
uint32_t reserved2;
ipv6_addr_t addr;
} opt_pi_t;
typedef struct __attribute__ ((packed)) opt_aro_t {
uint8_t type;
uint8_t length;
uint8_t status;
uint8_t reserved1;
uint16_t reserved2;
uint16_t reg_ltime;
ieee_802154_long_t eui64;
} opt_aro_t;
typedef struct __attribute__ ((packed)) opt_6co_hdr_t {
uint8_t type;
uint8_t length;
uint8_t c_length;
uint8_t c_flags;
uint16_t reserved;
uint16_t val_ltime;
} opt_6co_hdr_t;
typedef struct __attribute__ ((packed)) opt_abro_t {
uint8_t type;
uint8_t length;
uint16_t version;
uint32_t reserved;
ipv6_addr_t addr;
} opt_abro_t;
typedef struct __attribute__ ((packed)) plist_t {
uint8_t inuse;
uint8_t adv;
ipv6_addr_t addr;
uint8_t length;
uint8_t l_a_reserved1;
uint32_t val_ltime;
uint32_t pref_ltime;
uint8_t infinite;
} plist_t;
struct __attribute__ ((packed)) rtr_adv_t {
uint8_t hoplimit;
uint8_t autoconfig_flags;
uint16_t router_lifetime;
uint32_t reachable_time;
uint32_t retrans_timer;
};
struct __attribute__ ((packed)) nbr_sol_t {
uint32_t reserved;
ipv6_addr_t tgtaddr;
};
struct __attribute__ ((packed)) nbr_adv_t {
uint8_t rso;
uint8_t reserved[3];
ipv6_addr_t tgtaddr;
};
struct __attribute__ ((packed)) para_prob_t {
uint8_t pointer;
};
/* authoritive border router cache - draft-draft-ietf-6lowpan-nd-17 */
typedef struct __attribute__((packed)) abr_cache_t {
uint16_t version;
ipv6_addr_t abr_addr;
uint8_t cids[LOWPAN_CONTEXT_MAX];
} abr_cache_t;
/* neighbor cache - rfc4861 5.1. */
typedef struct __attribute__ ((packed)) nbr_cache_t {
uint8_t type;
uint8_t state;
uint8_t isrouter;
ipv6_addr_t addr;
ieee_802154_long_t laddr;
ieee_802154_short_t saddr;
timex_t ltime;
} nbr_cache_t;
/* default router list - rfc4861 5.1. */
typedef struct __attribute__ ((packed)) def_rtr_lst_t {
ipv6_addr_t addr;
timex_t inval_time;
} def_rtr_lst_t;
void init_rtr_sol(uint8_t sllao);
void recv_rtr_sol(void);
void recv_rtr_adv(void);
void init_rtr_adv(ipv6_addr_t *addr, uint8_t sllao, uint8_t mtu, uint8_t pi,
uint8_t sixco, uint8_t abro);
uint8_t plist_search(ipv6_addr_t *addr);
uint8_t plist_cmp(ipv6_addr_t *addr1, ipv6_addr_t *addr2);
int8_t plist_add(ipv6_addr_t *addr, uint8_t size, uint32_t val_ltime,
uint32_t pref_ltime, uint8_t adv_opt, uint8_t l_a_reserved1);
void set_llao(opt_stllao_t *sllao, uint8_t type, uint8_t length);
abr_cache_t *abr_get_version(uint16_t version, ipv6_addr_t *abr_addr);
abr_cache_t *abr_add_context( uint16_t version, ipv6_addr_t *abr_addr,
uint8_t cid);
void abr_remove_context(uint8_t cid);
nbr_cache_t * nbr_cache_search(ipv6_addr_t *ipaddr);
uint8_t nbr_cache_add(ipv6_addr_t *ipaddr, ieee_802154_long_t *laddr,
uint8_t isrouter, uint8_t state, uint8_t type,
uint16_t ltime, ieee_802154_short_t *saddr);
void nbr_cache_auto_rem(void);
void nbr_cache_rem(ipv6_addr_t *addr);
uint16_t icmpv6_csum(uint8_t proto);
def_rtr_lst_t * def_rtr_lst_search(ipv6_addr_t *ipaddr);
void def_rtr_lst_add(ipv6_addr_t *ipaddr, uint32_t rtr_ltime);
void def_rtr_lst_rem(def_rtr_lst_t *entry);
void init_para_prob(ipv6_addr_t *src, ipv6_addr_t *dest, uint8_t code, uint32_t pointer, uint8_t *packet, uint8_t packet_len);
void init_nbr_sol(ipv6_addr_t *src, ipv6_addr_t *dest, ipv6_addr_t *targ,
uint8_t slloa, uint8_t aro);
void init_nbr_adv(ipv6_addr_t *src, ipv6_addr_t *dst, ipv6_addr_t *tgt,
uint8_t rso, uint8_t sllao, uint8_t aro, uint8_t aro_state);
void recv_nbr_adv(void);
void recv_nbr_sol(void);
#endif /* SIXLOWND_H*/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,83 @@
#ifndef SIXLOWPAN_H
#define SIXLOWPAN_H
#define IP_PROCESS_STACKSIZE 3072
#define NC_STACKSIZE 512
#define CON_STACKSIZE 512
/* fragment size in bytes*/
#define FRAG_PART_ONE_HDR_LEN 4
#define FRAG_PART_N_HDR_LEN 5
#define LOWPAN_IPHC_DISPATCH 0x60
#define LOWPAN_IPHC_FL_C 0x10
#define LOWPAN_IPHC_TC_C 0x08
#define LOWPAN_IPHC_CID 0x80
#define LOWPAN_IPHC_SAC 0x40
#define LOWPAN_IPHC_SAM 0x30
#define LOWPAN_IPHC_DAC 0x04
#define LOWPAN_IPHC_DAM 0x03
#define LOWPAN_IPHC_M 0x08
#define LOWPAN_IPHC_NH 0x04
#define LOWPAN_IPV6_DISPATCH 0x41
#define LOWPAN_CONTEXT_MAX 16
#define LOWPAN_REAS_BUF_TIMEOUT 60
#include "transceiver.h"
#include "sixlowip.h"
#include <vtimer.h>
#include <mutex.h>
#include <time.h>
extern mutex_t lowpan_context_mutex;
typedef struct lowpan_context_t {
uint8_t num;
ipv6_addr_t prefix;
uint8_t length;
uint8_t comp;
uint16_t lifetime;
} lowpan_context_t;
typedef struct lowpan_interval_list_t {
uint8_t start;
uint8_t end;
struct lowpan_interval_list_t *next;
} lowpan_interval_list_t;
typedef struct lowpan_reas_buf_t {
ieee_802154_long_t s_laddr; // Source Address
ieee_802154_long_t d_laddr; // Destination Address
uint16_t ident_no; // Identification Number
time_t timestamp; // Timestamp of last packet fragment
uint8_t packet_size; // Size of reassembled packet with possible IPHC header
uint8_t current_packet_size; // Additive size of currently already received fragments
uint8_t *packet; // Pointer to allocated memory for reassembled packet + 6LoWPAN Dispatch Byte
lowpan_interval_list_t *interval_list_head; // Pointer to list of intervals of received packet fragments (if any)
struct lowpan_reas_buf_t *next; // Pointer to next reassembly buffer (if any)
} lowpan_reas_buf_t;
extern lowpan_reas_buf_t *head;
void sixlowpan_init(transceiver_type_t trans, uint8_t r_addr, int as_border);
void sixlowpan_adhoc_init(transceiver_type_t trans, ipv6_addr_t *prefix, uint8_t r_addr);
void lowpan_init(ieee_802154_long_t *addr, uint8_t *data);
void lowpan_read(uint8_t *data, uint8_t length, ieee_802154_long_t *s_laddr,
ieee_802154_long_t *d_laddr);
void lowpan_iphc_encoding(ieee_802154_long_t *dest);
void lowpan_iphc_decoding(uint8_t *data, uint8_t length,
ieee_802154_long_t *s_laddr,
ieee_802154_long_t *d_laddr);
uint8_t lowpan_context_len();
lowpan_context_t * lowpan_context_update(
uint8_t num, const ipv6_addr_t *prefix,
uint8_t length, uint8_t comp,
uint16_t lifetime);
lowpan_context_t * lowpan_context_get();
lowpan_context_t * lowpan_context_lookup(ipv6_addr_t *addr);
lowpan_context_t * lowpan_context_num_lookup(uint8_t num);
void lowpan_ipv6_set_dispatch(uint8_t *data);
void init_reas_bufs(lowpan_reas_buf_t *buf);
void printReasBuffers(void);
#endif

View File

@ -8,8 +8,6 @@
#include <transceiver.h>
#include <radio/types.h>
#define PAYLOAD_SIZE (0)
/* supported transceivers */
#ifdef MODULE_CC110X_NG
#include <cc110x_ng.h>
@ -64,6 +62,11 @@ static void switch_to_rx(transceiver_type_t t);
/* Transceiver init */
void transceiver_init(transceiver_type_t t) {
uint8_t i;
/* Initializing transceiver buffer and data buffer */
memset(transceiver_buffer, 0, TRANSCEIVER_BUFFER_SIZE);
memset(data_buffer, 0, TRANSCEIVER_BUFFER_SIZE * PAYLOAD_SIZE);
for (i = 0; i < TRANSCEIVER_MAX_REGISTERED; i++) {
reg[i].transceivers = TRANSCEIVER_NONE;
reg[i].pid = 0;
@ -124,7 +127,6 @@ void run(void) {
msg_receive(&m);
/* only makes sense for messages for upper layers */
cmd = (transceiver_command_t*) m.content.ptr;
DEBUG("Transceiver: Message received\n");
switch (m.type) {
case RCV_PKT_CC1020:
@ -279,7 +281,6 @@ static uint8_t send_packet(transceiver_type_t t, void *pkt) {
cc110x_pkt.address = p.dst;
cc110x_pkt.flags = 0;
memcpy(cc110x_pkt.data, p.data, p.length);
res = cc110x_send(&cc110x_pkt);
break;
default:

View File

@ -12,6 +12,7 @@
//#define ENABLE_DEBUG
#include <debug.h>
#define VTIMER_THRESHOLD 20U
#define VTIMER_BACKOFF 10U
@ -65,6 +66,7 @@ static int update_shortterm() {
}
hwtimer_id = hwtimer_set_absolute(next, vtimer_callback, NULL);
DEBUG("update_shortterm: Set hwtimer to %lu (now=%lu)\n", hwtimer_next_absolute + longterm_tick_start, hwtimer_now());
return 0;
}
@ -158,23 +160,25 @@ static int vtimer_set(vtimer_t *timer) {
}
int state = disableIRQ();
if (timer->absolute.seconds != seconds ) {
if (timer->absolute.seconds != seconds){
/* we're long-term */
DEBUG("vtimer_set(): setting long_term\n");
result = set_longterm(timer);
} else {
}
else {
DEBUG("vtimer_set(): setting short_term\n");
if (set_shortterm(timer)) {
/* delay update of next shortterm timer if we
* are called from within vtimer_callback.
*/
* are called from within vtimer_callback. */
if (!in_callback) {
result = update_shortterm();
}
}
}
restoreIRQ(state);
return result;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,24 @@
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

@ -0,0 +1,31 @@
#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

@ -0,0 +1,9 @@
/* 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

@ -0,0 +1,145 @@
#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

@ -0,0 +1,131 @@
/**
* @file flowcontrol.h
* @author Freie Universität Berlin, Computer Systems & Telemetics
* @author Martin 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

@ -0,0 +1,41 @@
#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], "%f", &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

@ -0,0 +1,254 @@
#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 byte = END+1;
uint8_t esc = 0;
uint8_t translate = 1;
while ((line_buf_ptr - packet_buf) < size-1) {
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

@ -0,0 +1,195 @@
/**
* @file multiplex.h
* @author Freie Universität Berlin, Computer Systems & Telemetics
* @author Martin 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

@ -0,0 +1,350 @@
/*
* 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; either 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, perm_ok=0;
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);
}
//printf("Attemping to find more information about %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");
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 | IXANY | IXON;
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

@ -0,0 +1,20 @@
/* 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

@ -0,0 +1,58 @@
#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

@ -0,0 +1,85 @@
/**
* @file serialnumber.h
* @author Freie Universität Berlin, Computer Systems & Telemetics
* @author Martin 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

@ -0,0 +1,309 @@
#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];
size_t bytes;
while (1) {
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];
struct in6_addr parsed_addr;
strncpy(ip_addr_cpy,ip_addr,IPV6_ADDR_LEN);
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

@ -0,0 +1,170 @@
/**
* @file sixlowdriver.h
* @author Freie Universität Berlin, Computer Systems & Telemetics
* @author Martin 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();
/**
* @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();
#endif /* SIXLOWDRIVER_H*/

View File

@ -0,0 +1,150 @@
#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);
}
}
}
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

@ -0,0 +1,68 @@
/**
* @file testing.h
* @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 Freie Universität Berlin, Computer Systems & Telemetics
* @author Martin 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*/