2011-06-22 21:09:06 +02:00
|
|
|
#include <stdint.h>
|
2011-07-05 04:24:13 +02:00
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
2011-06-24 01:48:41 +02:00
|
|
|
#include <mutex.h>
|
2011-07-12 15:00:21 +02:00
|
|
|
#include <thread.h>
|
|
|
|
#include <msg.h>
|
2011-07-05 04:24:13 +02:00
|
|
|
|
|
|
|
#include <posix_io.h>
|
|
|
|
#include <board_uart0.h>
|
2011-06-22 21:09:06 +02:00
|
|
|
#include "ieee802154_frame.h"
|
2011-07-25 16:33:24 +02:00
|
|
|
#include "flowcontrol.h"
|
2011-07-25 15:06:40 +02:00
|
|
|
#include "sixlowborder.h"
|
2011-06-22 21:09:06 +02:00
|
|
|
#include "sixlowip.h"
|
2011-07-05 04:24:13 +02:00
|
|
|
#include "sixlownd.h"
|
2011-06-22 21:09:06 +02:00
|
|
|
#include "serialnumber.h"
|
|
|
|
#include "sixlowerror.h"
|
|
|
|
|
2011-07-05 04:24:13 +02:00
|
|
|
#define DC3 0x0D
|
|
|
|
#define END 0xC0
|
|
|
|
#define ESC 0xDB
|
|
|
|
#define END_ESC 0xDC
|
|
|
|
#define ESC_ESC 0xDD
|
|
|
|
#define DC3_ESC 0xDE
|
|
|
|
|
2011-07-12 15:00:21 +02:00
|
|
|
#define READER_STACK_SIZE 512
|
|
|
|
|
2011-07-23 22:17:52 +02:00
|
|
|
char serial_reader_stack[READER_STACK_SIZE];
|
|
|
|
uint16_t serial_reader_pid;
|
2011-07-12 15:00:21 +02:00
|
|
|
|
2011-07-25 16:14:15 +02:00
|
|
|
uint8_t serial_out_buf[BORDER_BUFFER_SIZE];
|
|
|
|
uint8_t serial_in_buf[BORDER_BUFFER_SIZE];
|
2011-06-22 21:09:06 +02:00
|
|
|
|
2011-07-23 22:17:52 +02:00
|
|
|
void serial_reader_f(void);
|
2011-07-12 15:00:21 +02:00
|
|
|
|
2011-07-23 22:17:52 +02:00
|
|
|
uint8_t border_initialize(transceiver_type_t trans,ipv6_addr_t *border_router_addr) {
|
2011-07-12 15:00:21 +02:00
|
|
|
ipv6_addr_t addr;
|
|
|
|
|
2011-07-23 22:17:52 +02:00
|
|
|
serial_reader_pid = thread_create(
|
|
|
|
serial_reader_stack, READER_STACK_SIZE,
|
2011-07-12 15:00:21 +02:00
|
|
|
PRIORITY_MAIN-1, CREATE_STACKTEST,
|
2011-07-23 22:17:52 +02:00
|
|
|
serial_reader_f, "serial_reader");
|
2011-07-12 15:00:21 +02:00
|
|
|
|
2011-07-23 22:17:52 +02:00
|
|
|
if (border_router_addr == NULL) {
|
|
|
|
border_router_addr = &addr;
|
2011-07-12 15:00:21 +02:00
|
|
|
|
2011-07-25 16:33:24 +02:00
|
|
|
addr = flowcontrol_init();
|
2011-07-12 15:00:21 +02:00
|
|
|
}
|
|
|
|
|
2011-06-22 21:09:06 +02:00
|
|
|
/* only allow addresses generated accoding to
|
|
|
|
* RFC 4944 (Section 6) & RFC 2464 (Section 4) from short address
|
|
|
|
* -- for now
|
|
|
|
*/
|
2011-07-23 22:17:52 +02:00
|
|
|
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)
|
2011-06-22 21:09:06 +02:00
|
|
|
) {
|
|
|
|
return SIXLOWERROR_ADDRESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
// radio-address is 8-bit so this must be tested extra
|
2011-07-23 22:17:52 +02:00
|
|
|
if (border_router_addr->uint8[14] != 0) {
|
2011-06-22 21:09:06 +02:00
|
|
|
return SIXLOWERROR_ADDRESS;
|
|
|
|
}
|
|
|
|
|
2011-07-23 22:17:52 +02:00
|
|
|
sixlowpan_init(trans,border_router_addr->uint8[15],1);
|
2011-06-22 21:09:06 +02:00
|
|
|
|
|
|
|
ipv6_init_iface_as_router();
|
|
|
|
|
2011-07-11 18:26:12 +02:00
|
|
|
|
2011-06-22 21:09:06 +02:00
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
2011-07-25 16:14:15 +02:00
|
|
|
uint16_t border_get_serial_reader() {
|
|
|
|
return serial_reader_pid;
|
|
|
|
}
|
|
|
|
|
|
|
|
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]);
|
|
|
|
}
|
|
|
|
|
2011-07-05 04:24:13 +02:00
|
|
|
int readpacket(uint8_t *packet_buf, int size) {
|
|
|
|
uint8_t *line_buf_ptr = packet_buf;
|
2011-07-09 19:04:03 +02:00
|
|
|
uint8_t byte = END+1;
|
2011-07-05 04:24:13 +02:00
|
|
|
uint8_t esc = 0;
|
|
|
|
|
|
|
|
while (byte != END) {
|
|
|
|
byte = uart0_readc();
|
|
|
|
|
|
|
|
if ( (line_buf_ptr - packet_buf) >= size-1) {
|
|
|
|
return -SIXLOWERROR_ARRAYFULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (byte == DC3) continue;
|
|
|
|
|
|
|
|
if (esc) {
|
|
|
|
switch (byte) {
|
|
|
|
case(END_ESC):{
|
|
|
|
byte = END;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case(ESC_ESC):{
|
|
|
|
byte = ESC;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case(DC3_ESC):{
|
|
|
|
byte = DC3;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
esc = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (byte == ESC) {
|
|
|
|
esc = 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
*line_buf_ptr++ = byte;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (line_buf_ptr - packet_buf - 1);
|
|
|
|
}
|
|
|
|
|
2011-07-09 19:14:13 +02:00
|
|
|
int writepacket(uint8_t *packet_buf, size_t size) {
|
|
|
|
uint8_t *byte_ptr = packet_buf;
|
|
|
|
|
|
|
|
while ((byte_ptr - packet_buf) < size) {
|
2011-07-23 22:17:52 +02:00
|
|
|
if ((byte_ptr - packet_buf) > BORDER_BUFFER_SIZE) {
|
2011-07-09 19:14:13 +02:00
|
|
|
return -1;
|
|
|
|
}
|
2011-07-12 15:00:21 +02:00
|
|
|
printf("%02x ",*byte_ptr);
|
2011-07-09 19:14:13 +02:00
|
|
|
switch (*byte_ptr) {
|
|
|
|
case(DC3):{
|
|
|
|
*byte_ptr = DC3_ESC;
|
2011-07-24 23:29:42 +02:00
|
|
|
uart0_putc(ESC);
|
|
|
|
break;
|
2011-07-09 19:14:13 +02:00
|
|
|
}
|
|
|
|
case(END):{
|
|
|
|
*byte_ptr = END_ESC;
|
2011-07-24 23:29:42 +02:00
|
|
|
uart0_putc(ESC);
|
|
|
|
break;
|
2011-07-09 19:14:13 +02:00
|
|
|
}
|
|
|
|
case(ESC):{
|
|
|
|
*byte_ptr = ESC_ESC;
|
2011-07-24 23:29:42 +02:00
|
|
|
uart0_putc(ESC);
|
|
|
|
break;
|
2011-07-09 19:14:13 +02:00
|
|
|
}
|
|
|
|
default:{
|
2011-07-24 23:29:42 +02:00
|
|
|
break;
|
2011-07-09 19:14:13 +02:00
|
|
|
}
|
|
|
|
}
|
2011-07-24 23:29:42 +02:00
|
|
|
uart0_putc(*byte_ptr);
|
2011-07-09 19:14:13 +02:00
|
|
|
byte_ptr++;
|
|
|
|
}
|
|
|
|
|
2011-07-12 15:00:21 +02:00
|
|
|
printf("\n");
|
2011-07-09 19:14:13 +02:00
|
|
|
uart0_putc(END);
|
|
|
|
|
|
|
|
return (byte_ptr - packet_buf);
|
|
|
|
}
|
|
|
|
|
2011-07-23 22:17:52 +02:00
|
|
|
void serial_reader_f(void) {
|
2011-07-12 15:00:21 +02:00
|
|
|
int main_pid = 0;
|
2011-07-11 18:26:12 +02:00
|
|
|
int bytes;
|
2011-07-12 15:00:21 +02:00
|
|
|
msg_t m;
|
2011-07-23 22:17:52 +02:00
|
|
|
border_packet_t *uart_buf;
|
2011-07-12 15:00:21 +02:00
|
|
|
|
|
|
|
posix_open(uart0_handler_pid, 0);
|
|
|
|
|
|
|
|
msg_receive(&m);
|
|
|
|
main_pid = m.sender_pid;
|
|
|
|
|
2011-07-05 04:24:13 +02:00
|
|
|
while(1) {
|
2011-07-12 15:00:21 +02:00
|
|
|
posix_open(uart0_handler_pid, 0);
|
2011-07-25 16:14:15 +02:00
|
|
|
bytes = readpacket(get_serial_in_buffer(0), BORDER_BUFFER_SIZE);
|
2011-07-11 18:26:12 +02:00
|
|
|
if (bytes < 0) {
|
|
|
|
switch (bytes) {
|
2011-07-05 04:24:13 +02:00
|
|
|
case (-SIXLOWERROR_ARRAYFULL):{
|
2011-07-11 18:26:12 +02:00
|
|
|
printf("ERROR: Array was full\n");
|
2011-07-05 04:24:13 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:{
|
|
|
|
printf("ERROR: unknown\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
2011-07-11 18:26:12 +02:00
|
|
|
|
2011-07-25 16:14:15 +02:00
|
|
|
uart_buf = (border_packet_t*)get_serial_in_buffer(0);
|
2011-07-05 04:24:13 +02:00
|
|
|
if (uart_buf->reserved == 0) {
|
2011-07-23 22:17:52 +02:00
|
|
|
if (uart_buf->type == BORDER_PACKET_CONF_TYPE) {
|
2011-07-25 16:14:15 +02:00
|
|
|
border_conf_header_t *conf_packet = (border_conf_header_t*)uart_buf;
|
2011-07-23 22:17:52 +02:00
|
|
|
if (conf_packet->conftype == BORDER_CONF_SYN) {
|
2011-07-12 15:00:21 +02:00
|
|
|
m.content.ptr = (char *)conf_packet;
|
|
|
|
msg_send(&m, main_pid, 1);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2011-07-23 22:17:52 +02:00
|
|
|
flowcontrol_deliver_from_uart(uart_buf, bytes);
|
2011-07-11 18:26:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-23 22:17:52 +02:00
|
|
|
void demultiplex(border_packet_t *packet, int len) {
|
2011-07-11 18:26:12 +02:00
|
|
|
switch (packet->type) {
|
2011-07-23 22:17:52 +02:00
|
|
|
case (BORDER_PACKET_RAW_TYPE):{
|
|
|
|
fputs(((char *)packet) + sizeof (border_packet_t), stdin);
|
2011-07-11 18:26:12 +02:00
|
|
|
break;
|
|
|
|
}
|
2011-07-23 22:17:52 +02:00
|
|
|
case (BORDER_PACKET_L3_TYPE):{
|
|
|
|
border_l3_header_t *l3_header_buf = (border_l3_header_t *)packet;
|
2011-07-11 18:26:12 +02:00
|
|
|
switch (l3_header_buf->ethertype) {
|
2011-07-23 22:17:52 +02:00
|
|
|
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);
|
2011-07-05 04:24:13 +02:00
|
|
|
break;
|
|
|
|
}
|
2011-07-11 18:26:12 +02:00
|
|
|
default:
|
2011-07-24 21:27:07 +02:00
|
|
|
printf("ERROR: Unknown ethertype %02x\n", l3_header_buf->ethertype);
|
2011-07-05 04:24:13 +02:00
|
|
|
break;
|
2011-07-11 18:26:12 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2011-07-23 22:17:52 +02:00
|
|
|
case (BORDER_PACKET_CONF_TYPE):{
|
|
|
|
border_conf_header_t *conf_header_buf = (border_conf_header_t *)packet;
|
2011-07-11 18:26:12 +02:00
|
|
|
switch (conf_header_buf->conftype) {
|
2011-07-24 17:29:50 +02:00
|
|
|
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);
|
2011-07-25 15:36:22 +02:00
|
|
|
mutex_lock(&lowpan_context_mutex);
|
2011-07-24 17:29:50 +02:00
|
|
|
lowpan_context_update(
|
|
|
|
context->context.cid,
|
|
|
|
&context->context.prefix,
|
|
|
|
context->context.length,
|
|
|
|
context->context.comp,
|
|
|
|
context->context.lifetime
|
|
|
|
);
|
2011-07-25 15:36:22 +02:00
|
|
|
// abr stuff
|
|
|
|
mutex_unlock(&lowpan_context_mutex,0);
|
2011-07-24 17:29:50 +02:00
|
|
|
// Send router advertisement
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case (BORDER_CONF_IPADDR):{
|
2011-07-24 23:06:48 +02:00
|
|
|
//border_addr_packet_t *addr_packet = (border_addr_packet_t *)packet;
|
2011-07-24 17:29:50 +02:00
|
|
|
// add address
|
2011-07-24 23:06:48 +02:00
|
|
|
break;
|
2011-07-24 17:29:50 +02:00
|
|
|
}
|
2011-07-11 18:26:12 +02:00
|
|
|
default:
|
2011-07-24 23:06:48 +02:00
|
|
|
printf("ERROR: Unknown conftype %02x\n", conf_header_buf->conftype);
|
2011-07-05 04:24:13 +02:00
|
|
|
break;
|
|
|
|
}
|
2011-07-11 18:26:12 +02:00
|
|
|
break;
|
2011-07-05 04:24:13 +02:00
|
|
|
}
|
2011-07-11 18:26:12 +02:00
|
|
|
default:
|
2011-07-24 23:06:48 +02:00
|
|
|
printf("ERROR: Unknown border packet type %02x\n", packet->type);
|
2011-07-11 18:26:12 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-23 22:17:52 +02:00
|
|
|
void multiplex_send_ipv6_over_uart(struct ipv6_hdr_t *packet) {
|
|
|
|
border_l3_header_t *serial_buf;
|
2011-07-09 19:14:13 +02:00
|
|
|
|
2011-07-25 16:14:15 +02:00
|
|
|
serial_buf = (border_l3_header_t *)get_serial_out_buffer(0);
|
2011-07-09 19:14:13 +02:00
|
|
|
serial_buf->reserved = 0;
|
2011-07-23 22:17:52 +02:00
|
|
|
serial_buf->type = BORDER_PACKET_L3_TYPE;
|
|
|
|
serial_buf->ethertype = BORDER_ETHERTYPE_IPV6;
|
2011-07-25 16:14:15 +02:00
|
|
|
memcpy(get_serial_in_buffer(0)+sizeof (border_l3_header_t), packet, IPV6_HDR_LEN + packet->length);
|
2011-07-24 18:06:28 +02:00
|
|
|
|
2011-07-24 18:13:10 +02:00
|
|
|
flowcontrol_send_over_uart(
|
2011-07-24 18:06:28 +02:00
|
|
|
(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;
|
|
|
|
|
2011-07-25 16:14:15 +02:00
|
|
|
serial_buf = (border_addr_packet_t *)get_serial_in_buffer(0);
|
2011-07-24 18:06:28 +02:00
|
|
|
serial_buf->reserved = 0;
|
|
|
|
serial_buf->type = BORDER_PACKET_CONF_TYPE;
|
|
|
|
serial_buf->conftype = BORDER_CONF_IPADDR;
|
|
|
|
memcpy(
|
|
|
|
&serial_buf->addr,
|
|
|
|
addr,
|
|
|
|
sizeof (ipv6_addr_t)
|
|
|
|
);
|
|
|
|
|
2011-07-24 18:13:10 +02:00
|
|
|
flowcontrol_send_over_uart(
|
2011-07-24 18:06:28 +02:00
|
|
|
(border_packet_t *) serial_buf,
|
|
|
|
sizeof (border_addr_packet_t)
|
|
|
|
);
|
2011-07-09 19:14:13 +02:00
|
|
|
}
|
|
|
|
|
2011-07-23 22:17:52 +02:00
|
|
|
void border_send_ipv6_over_lowpan(struct ipv6_hdr_t *packet, uint8_t aro_flag, uint8_t sixco_flag) {
|
2011-07-09 19:06:28 +02:00
|
|
|
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);
|
|
|
|
|
2011-07-24 21:25:47 +02:00
|
|
|
if (packet->nextheader == PROTO_NUM_ICMPV6) {
|
|
|
|
struct icmpv6_hdr_t *icmp_buf = (struct icmpv6_hdr_t *)(packet + IPV6_HDR_LEN);
|
|
|
|
if (icmp_buf->type == ICMP_REDIRECT) {
|
|
|
|
return;
|
2011-07-09 19:06:28 +02:00
|
|
|
}
|
2011-07-24 21:25:47 +02:00
|
|
|
// Here, other ICMPv6 message types for ND may follow.
|
|
|
|
}
|
2011-07-09 19:06:28 +02:00
|
|
|
|
|
|
|
lowpan_init((ieee_802154_long_t*)&(packet->destaddr.uint16[4]), (uint8_t*)packet);
|
|
|
|
}
|
|
|
|
|
2011-07-23 22:17:52 +02:00
|
|
|
void border_process_lowpan(void) {
|
2011-07-10 22:49:41 +02:00
|
|
|
msg_t m;
|
2011-07-09 19:19:31 +02:00
|
|
|
struct ipv6_hdr_t *ipv6_buf;
|
|
|
|
|
|
|
|
while(1) {
|
|
|
|
msg_receive(&m);
|
|
|
|
ipv6_buf = (struct ipv6_hdr_t *)m.content.ptr;
|
|
|
|
// TODO: Bei ICMPv6-Paketen entsprechende LoWPAN-Optionen verarbeiten und entfernen
|
2011-07-23 22:17:52 +02:00
|
|
|
multiplex_send_ipv6_over_uart(ipv6_buf);
|
2011-07-09 19:19:31 +02:00
|
|
|
}
|
|
|
|
}
|