diff --git a/sys/net/sixlowpan/sixlowip.c b/sys/net/sixlowpan/sixlowip.c index 5f1392fc58..e07273e6db 100644 --- a/sys/net/sixlowpan/sixlowip.c +++ b/sys/net/sixlowpan/sixlowip.c @@ -1,11 +1,11 @@ +#include +#include +#include #include "msg.h" #include "sixlowip.h" #include "sixlowmac.h" #include "sixlownd.h" #include "sixlowpan.h" -#include -#include "drivers/cc110x/cc1100.h" -#include "radio/radio.h" msg msg_queue[IP_PKT_RECV_BUF_SIZE]; struct ipv6_hdr_t* ipv6_buf; @@ -26,15 +26,20 @@ struct icmpv6_hdr_t* get_icmpv6_buf(uint8_t ext_len){ void bootstrapping(uint8_t *addr){ #ifdef SIXLOWPAN_NODE /* create link-local address based on eui-64 */ - ipv6_buf = get_ipv6_buf(); + //ipv6_buf = get_ipv6_buf(); //RADIO.set_address(5); //create_link_local_prefix(&ipv6_buf->srcaddr); //init_802154_long_addr((uint8_t*)&(ipv6_buf->srcaddr.uint8[8])); //set_eui64(&ipv6_buf->srcaddr); // print6addr(&ipv6_buf->srcaddr); /* send router solicitation */ - init_rtr_sol(); + + init_rtr_sol(OPT_SLLAO); + //init_rtr_adv(NULL, 0, 0, 0, 0, 0); + //init_rtr_adv(&ipv6_buf->srcaddr, 0, 0, OPT_PI, 0, 0); + + ipv6_buf = get_ipv6_buf(); output(addr,(uint8_t*)ipv6_buf); //send_rtr_adv(&ipv6_buf->destaddr); #endif @@ -48,10 +53,9 @@ void ip_process(void){ ipv6_buf = get_ipv6_buf(); ipv6_buf = (struct ipv6_hdr_t*) m.content.ptr; - + printf("INFO: packet received, source: "); print6addr(&ipv6_buf->srcaddr); - /* identifiy packet */ nextheader = &ipv6_buf->nextheader; @@ -65,7 +69,26 @@ void ip_process(void){ switch(icmp_buf->type) { case(ICMP_RTR_SOL):{ printf("INFO: packet type: icmp router solicitation\n"); - recv_rtr_sol(); + /* processing router solicitation */ + recv_rtr_sol(); + /* init solicited router advertisment*/ + init_rtr_adv(&ipv6_buf->srcaddr, 0, 0, OPT_PI, 0, 0); + /* send solicited router advertisment */ + uint8_t addr = 0; + output(&addr,(uint8_t*)ipv6_buf); + + break; + } + case(ICMP_RTR_ADV):{ + printf("INFO: packet type: icmp router advertisment\n"); + /* processing router advertisment */ + recv_rtr_adv(); + /* init neighbor solicitation */ + //init_nbr_sol(); + break; + } + case(ICMP_NBR_SOL):{ + printf("INFO: packet type: icmp neighbor solicitation\n"); } default: break; @@ -78,10 +101,69 @@ void ip_process(void){ } } +void iface_addr_list_add(ipv6_addr_t *addr, uint8_t state, uint32_t val_ltime, + uint32_t pref_ltime, uint8_t type){ + 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; + iface.addr_list[iface_addr_list_count].val_ltime.absolute.seconds = val_ltime; + timex_t vtime, ptime; + vtime.seconds = val_ltime; + ptime.seconds = pref_ltime; + vtimer_set_wakeup(&(iface.addr_list[iface_addr_list_count].val_ltime),vtime,NULL); + //iface.addr_list[iface_addr_list_count].pref_ltime.absolute.seconds = pref_ltime; + vtimer_set_wakeup(&(iface.addr_list[iface_addr_list_count].pref_ltime), ptime, NULL); + iface.addr_list[iface_addr_list_count].type = type; + iface_addr_list_count++; + } +} + +addr_list_t * iface_addr_list_search(ipv6_addr_t *addr){ + int i; + for(i = 0; i < IFACE_ADDR_LIST_LEN; i++){ + if(memcmp(&(iface.addr_list[i].addr.uint8[0]), + &(addr->uint8[0]),16) == 0){ + return &(iface.addr_list[i]); + } + } +} + +addr_list_t * iface_addr_list_prefix_equals(ipv6_addr_t *addr){ + int i; + for(i = 0; i < IFACE_ADDR_LIST_LEN; i++){ + if(memcmp(&(iface.addr_list[i].addr.uint8[0]), + &(addr->uint8[0]), 8) == 0){ + return &(iface.addr_list[i]); + } + } + return NULL; +} + +void setup_addr_with_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); +} + ieee_802154_long_t* get_eui(ipv6_addr_t *ipaddr){ return ((ieee_802154_long_t *) &(ipaddr->uint8[8])); } +void create_prefix(ipv6_addr_t *inout, uint16_t prefix){ + inout->uint16[0] = prefix; + inout->uint16[1] = 0; + inout->uint16[2] = 0; + inout->uint16[3] = 0; + inout->uint16[4] = 0; + inout->uint16[5] = 0; + inout->uint16[6] = 0; + inout->uint16[7] = 0; +} + void create_all_routers_mcast_addr(ipv6_addr_t *ipaddr){ ipaddr->uint16[0] = HTONS(0xff02); ipaddr->uint16[1] = 0; @@ -104,10 +186,57 @@ void create_all_nodes_mcast_addr(ipv6_addr_t *ipaddr){ ipaddr->uint16[7] = HTONS(0x0001); } -void get_src_ipaddr(ipv6_addr_t *ipaddr){ +void iface_find_src_ipaddr(ipv6_addr_t *ipaddr, uint8_t state, + uint8_t dest_addr_type){ int i; - for(i=0;i<16;i++){ - ipaddr->uint8[i] = iface.ipaddr.uint8[i]; + int found = 0; + + switch(dest_addr_type) { + case(ADDR_TYPE_MULTICAST):{ + printf("a\n"); + for(i = 0; i < IFACE_ADDR_LIST_LEN; i++){ + if(prefix_link_local_check(&(iface.addr_list[i].addr))){ + printf("b\n"); + if(iface.addr_list[i].state == state){ + printf("c\n"); + memcpy(&(ipaddr->uint8[0]), + &(iface.addr_list[i].addr.uint8[0]),16); + found = 1; + } + } + } + break; + } + case(ADDR_TYPE_LINK_LOCAL):{ + for(i = 0; i < IFACE_ADDR_LIST_LEN; i++){ + if(prefix_link_local_check(&(iface.addr_list[i].addr))){ + if(iface.addr_list[i].state == state){ + memcpy(&(ipaddr->uint8[0]), + &(iface.addr_list[i].addr.uint8[0]),16); + found = 1; + } + } + } + break; + } + case(ADDR_TYPE_GLOBAL):{ + for(i = 0; i < IFACE_ADDR_LIST_LEN; i++){ + if(!(prefix_link_local_check(&(iface.addr_list[i].addr)))){ + if(iface.addr_list[i].state == state){ + memcpy(&(ipaddr->uint8[0]), + &(iface.addr_list[i].addr.uint8[0]),16); + found = 1; + } + } + } + break; + } + default: + break; + } + + if(found == 0){ + memset(ipaddr, 0, 16); } } @@ -118,6 +247,26 @@ void create_link_local_prefix(ipv6_addr_t *ipaddr){ ipaddr->uint16[3] = 0; } +uint8_t prefix_link_local_check(ipv6_addr_t *addr){ + if(addr->uint8[0] == 0xfe && addr->uint8[1] == 0x80){ + return 1; + } + return 0; +} + +void create_solicited_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 print6addr(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], @@ -127,3 +276,16 @@ void print6addr(ipv6_addr_t *ipaddr){ ((uint8_t *)ipaddr)[12], ((uint8_t *)ipaddr)[13], ((uint8_t *)ipaddr)[14], ((uint8_t *)ipaddr)[15]); } + +uint32_t get_remaining_time(vtimer_t *t){ + timex_t time; + time = vtimer_remaining(t); + + uint32_t seconds = time.nanoseconds / 1000000; + + return seconds; +} + +void set_remaining_time(vtimer_t *t, uint32_t time){ + t->absolute.nanoseconds = time * 1000000; +} diff --git a/sys/net/sixlowpan/sixlowip.h b/sys/net/sixlowpan/sixlowip.h index 77d40a87e2..de4c105bc0 100644 --- a/sys/net/sixlowpan/sixlowip.h +++ b/sys/net/sixlowpan/sixlowip.h @@ -4,6 +4,7 @@ #define SIXLOWIP_H #include +#include /* set maximum transmission unit */ #define MTU 1280 @@ -18,9 +19,6 @@ #define MSBA2_OUI 0x005BA2 // 24bit OUI #define R8BIT 0xA2 // random 8bit #define OUI 0x005BA2 -/* radio driver */ -#define RADIO_CONF radio_cc1100 -#define RADIO RADIO_CONF #define MULTIHOP_HOPLIMIT 64 @@ -30,6 +28,8 @@ 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; /* base header lengths */ #define LL_HDR_LEN 0x4 @@ -39,6 +39,30 @@ extern uint16_t packet_length; #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 5 // 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_LINK_LOCAL 5 +#define ADDR_TYPE_GLOBAL 6 +/* dispatch types */ +#define DISPATCH_TYPE_IPV6 0x41 +#define DISPATCH_TYPE_LOWPAN_HC1 0x42 +/* compression types */ +#define COMPRESSION_TYPE_NONE + /* buffer */ uint8_t buffer[BUFFER_SIZE]; @@ -79,10 +103,21 @@ typedef union __attribute__ ((packed)) ieee_802154_short_t { uint16_t uint16[1]; } ieee_802154_short_t; +typedef struct __attribute__ ((packed)) addr_list_t { + uint8_t state; + vtimer_t val_ltime; + vtimer_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; - ipv6_addr_t ipaddr; + 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; @@ -106,5 +141,14 @@ ieee_802154_long_t* get_eui(ipv6_addr_t *ipaddr); void bootstrapping(uint8_t *addr); void print6addr(ipv6_addr_t *ipaddr); void ip_process(void); - +void iface_find_src_ipaddr(ipv6_addr_t *ipaddr, uint8_t state, + uint8_t dest_addr_type); +uint8_t prefix_link_local_check(ipv6_addr_t *addr); +void iface_addr_list_add(ipv6_addr_t* addr, uint8_t state, uint32_t val_ltime, + uint32_t pref_ltime, uint8_t type); +addr_list_t * iface_addr_list_prefix_equals(ipv6_addr_t *addr); +void setup_addr_with_prefix(ipv6_addr_t *inout, ipv6_addr_t *prefix); +uint32_t get_remaining_time(vtimer_t *t); +void set_remaining_time(vtimer_t *t, uint32_t time); +void create_prefix(ipv6_addr_t *inout, uint16_t prefix); #endif /* SIXLOWIP_H*/ diff --git a/sys/net/sixlowpan/sixlowmac.c b/sys/net/sixlowpan/sixlowmac.c index 3959f8ccc5..1b71c0973c 100644 --- a/sys/net/sixlowpan/sixlowmac.c +++ b/sys/net/sixlowpan/sixlowmac.c @@ -10,6 +10,7 @@ #include "msg.h" #include "radio/radio.h" #include "transceiver.h" +#include "vtimer.h" #include "ieee802154_frame.h" char radio_stack_buffer[RADIO_STACK_SIZE]; @@ -46,6 +47,13 @@ void set_radio_channel(uint8_t 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(); @@ -72,7 +80,7 @@ void recv_ieee802154_frame(void){ ieee802154_frame_t frame; msg_init_queue(msg_q, RADIO_RCV_BUF_SIZE); - + while (1) { msg_receive(&m); if (m.type == PKT_PENDING) { @@ -80,12 +88,11 @@ void recv_ieee802154_frame(void){ hdrlen = read_802154_frame(p->data, &frame, p->length); length = p->length - hdrlen; - + /* deliver packet to network(6lowpan)-layer */ input(frame.payload, length); - + p->processing--; - // printf("\n"); } else if (m.type == ENOBUFFER) { puts("Transceiver buffer full"); @@ -117,9 +124,6 @@ void set_ieee802154_frame_values(ieee802154_frame_t *frame){ } void send_ieee802154_frame(uint8_t *addr, uint8_t *payload, uint8_t length){ - - set_radio_channel(13); - mesg.type = SND_PKT; mesg.content.ptr = (char*) &tcmd; @@ -139,8 +143,6 @@ void send_ieee802154_frame(uint8_t *addr, uint8_t *payload, uint8_t length){ frame.src_addr[0] = 0; frame.src_addr[1] = 5; - - /* check if destination address is NULL => broadcast */ if(addr[0] == 0 && addr[1] == 0){ frame.dest_addr[0] = 0xff; @@ -162,15 +164,14 @@ void send_ieee802154_frame(uint8_t *addr, uint8_t *payload, uint8_t length){ p.dst = *addr; // TODO: geeignete ring-bufferung nötig p.data = buf; - //p.data = snd_buffer[i % RADIO_SND_BUF_SIZE]; msg_send(&mesg, transceiver_pid, 1); - //swtimer_usleep(RADIO_SENDING_DELAY); + //switch_to_rx(); } void sixlowmac_init(transceiver_type_t type){ int recv_pid = thread_create(radio_stack_buffer, RADIO_STACK_SIZE, - PRIORITY_MAIN-1, CREATE_STACKTEST, recv_ieee802154_frame , "radio"); + PRIORITY_MAIN-2, CREATE_STACKTEST, recv_ieee802154_frame , "radio"); transceiver_type = type; transceiver_init(transceiver_type); transceiver_start(); diff --git a/sys/net/sixlowpan/sixlownd.c b/sys/net/sixlowpan/sixlownd.c index 85d8222b69..59f2e75554 100644 --- a/sys/net/sixlowpan/sixlownd.c +++ b/sys/net/sixlowpan/sixlownd.c @@ -3,13 +3,48 @@ #include "sixlowmac.h" #include #include +#include +#include -uint8_t rtr_sol_count = 0; +/* extern variables */ uint8_t opt_hdr_len = 0; uint8_t ipv6_ext_hdr_len = 0; uint16_t packet_length; + +/* counter */ +uint8_t nbr_count = 0; +uint8_t def_rtr_count = 0; +uint8_t rtr_sol_count = 0; +uint8_t prefix_count = 0; + +/* global interface*/ iface_t iface; +/* datastructures */ +nbr_cache_t nbr_cache[NBR_CACHE_SIZE]; +def_rtr_lst_t def_rtr_lst[DEF_RTR_LST_SIZE]; +plist_t plist[OPT_PI_LIST_LEN]; + +/* pointer */ +static uint8_t *llao; +addr_list_t *addr_list_ptr; + +static struct ipv6_hdr_t *ipv6_buf; +static struct icmpv6_hdr_t *icmp_buf; +static struct rtr_adv_t *rtr_adv_buf; +static struct nbr_sol_t *nbr_sol_buf; +static struct opt_buf_t *opt_buf; +static struct opt_stllao_t *opt_stllao_buf; +static struct opt_mtu_t *opt_mtu_buf; +static struct opt_pi_t *opt_pi_buf; +static struct opt_aro_t *opt_aro_buf; + +nbr_cache_t *nbr_entry; +def_rtr_lst_t *def_rtr_entry; + +/* elements */ +ipv6_addr_t tmpaddr; + static struct rtr_adv_t* get_rtr_adv_buf(uint8_t ext_len){ return ((struct rtr_adv_t*)&(buffer[LLHDR_ICMPV6HDR_LEN + ext_len])); } @@ -18,6 +53,11 @@ static struct nbr_sol_t* get_nbr_sol_buf(uint8_t ext_len){ return ((struct nbr_sol_t*)&(buffer[LLHDR_ICMPV6HDR_LEN + ext_len])); } +static struct opt_buf_t* get_opt_buf(uint8_t ext_len, uint8_t opt_len){ + return ((struct opt_buf_t*)&(buffer[LLHDR_ICMPV6HDR_LEN + + ext_len + opt_len])); +} + static struct opt_stllao_t* get_opt_stllao_buf(uint8_t ext_len, uint8_t opt_len){ return ((struct opt_stllao_t*)&(buffer[LLHDR_ICMPV6HDR_LEN + ext_len + opt_len])); @@ -38,29 +78,11 @@ static struct opt_aro_t* get_opt_aro_buf(uint8_t ext_len, uint8_t opt_len){ ext_len + opt_len])); } -/* data stuctures */ -// TODO: prefix list size initialwert herausfinden -pfx_elem_t plist[OPT_PI_LIST_LEN]; - -/* pointer */ -static pfx_elem_t *pelem; -static uint8_t *llao; - -static struct ipv6_hdr_t *ipv6_buf; -static struct icmpv6_hdr_t *icmp_buf; -static struct rtr_adv_t *rtr_adv_buf; -static struct nbr_sol_t *nbr_sol_buf; -static struct opt_stllao_t *opt_stllao_buf; -static struct opt_mtu_t *opt_mtu_buf; -static struct opt_pi_t *opt_pi_buf; -static struct opt_aro_t *opt_aro_buf; - - /* send router solicitation message - RFC4861 section 4.1 */ -void init_rtr_sol(void){ +void init_rtr_sol(uint8_t sllao){ ipv6_buf = get_ipv6_buf(); icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len); - if(rtr_sol_count < RTR_SOL_MAX){ + //if(rtr_sol_count < RTR_SOL_MAX){ packet_length = 0; icmp_buf->type = ICMP_RTR_SOL; icmp_buf->code = 0; @@ -71,40 +93,69 @@ void init_rtr_sol(void){ ipv6_buf->hoplimit = ND_HOPLIMIT; create_all_routers_mcast_addr(&ipv6_buf->destaddr); - get_src_ipaddr(&ipv6_buf->srcaddr); + iface_find_src_ipaddr(&ipv6_buf->srcaddr, ADDR_STATE_PREFERRED, + ADDR_TYPE_MULTICAST); + opt_hdr_len = RTR_SOL_LEN; ipv6_buf->length = ICMPV6_HDR_LEN + RTR_SOL_LEN + OPT_STLLAO_LEN; - opt_stllao_buf = get_opt_stllao_buf(ipv6_ext_hdr_len, opt_hdr_len); - set_llao((uint8_t*)opt_stllao_buf, OPT_SLLAO_TYPE, 2); - - packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + ipv6_ext_hdr_len + - RTR_SOL_LEN + OPT_STLLAO_LEN; - + if(sllao == OPT_SLLAO){ + opt_stllao_buf = get_opt_stllao_buf(ipv6_ext_hdr_len, opt_hdr_len); + set_llao(opt_stllao_buf, OPT_SLLAO_TYPE, 2); + packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + ipv6_ext_hdr_len + + RTR_SOL_LEN + OPT_STLLAO_LEN; + } else { + packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + ipv6_ext_hdr_len + + RTR_SOL_LEN; + } icmp_buf->checksum = 0; icmp_buf->checksum = ~icmpv6_csum(ICMPV6_NXT_HDR); - rtr_sol_count++; + // rtr_sol_count++; // sleep 4 sec //swtimer_usleep(RTR_SOL_INTERVAL * 1000000); - } + //} } void recv_rtr_sol(void){ opt_hdr_len = RTR_SOL_LEN; - /* get link layer address option from buf */ - if(opt_stllao_buf->type == OPT_STLLAO_LEN){ + ipv6_buf = get_ipv6_buf(); + + /* check if source option is set*/ + if(opt_stllao_buf->type == OPT_SLLAO_TYPE){ + opt_stllao_buf = get_opt_stllao_buf(ipv6_ext_hdr_len, opt_hdr_len); llao = (uint8_t*)opt_stllao_buf; + opt_hdr_len += (opt_stllao_buf->length) << 3; } if(llao != NULL){ - // TODO: Neighbor lookup + nbr_entry = nbr_cache_search(&ipv6_buf->srcaddr); + if(nbr_entry != NULL){ + /* found neighbor in cache, update values and check long addr */ + if(memcmp(&llao[2],&nbr_entry->laddr,8) == 0){ + nbr_entry->isrouter = 0; + } else { + /* new long addr found, update */ + memcpy(&nbr_entry->laddr,&llao[2],8); + nbr_entry->state = NBR_STATUS_STALE; + nbr_entry->isrouter = 0; + } + } else { + /* nothing found, add neigbor into cache*/ + nbr_cache_add(&ipv6_buf->srcaddr,(ieee_802154_long_t*)&llao[2], + 0, NBR_STATUS_STALE); + } } - //send_rtr_adv(); + /* init solicited router advertisment*/ +// init_rtr_adv(&ipv6_buf->srcaddr, 0, 0, 0, 0, 0); + /* send solicited router advertisment */ +// uint8_t addr = 0; +// output(&addr,(uint8_t*)ipv6_buf); } -void init_rtr_adv(ipv6_addr_t *addr){ +void init_rtr_adv(ipv6_addr_t *addr, uint8_t sllao, uint8_t mtu, uint8_t pi, + uint8_t sixco, uint8_t abro){ ipv6_buf = get_ipv6_buf(); icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len); @@ -113,8 +164,13 @@ void init_rtr_adv(ipv6_addr_t *addr){ ipv6_buf->flowlabel = 0; ipv6_buf->nextheader = ICMPV6_NXT_HDR; ipv6_buf->hoplimit = ND_HOPLIMIT; - /* not solicited */ - create_all_nodes_mcast_addr(&ipv6_buf->destaddr); + + if(addr == NULL){ + /* not solicited */ + create_all_nodes_mcast_addr(&ipv6_buf->destaddr); + } else { + memcpy(&ipv6_buf->destaddr, addr, 16); + } icmp_buf->type = ICMP_RTR_ADV; icmp_buf->code = 0; @@ -125,45 +181,50 @@ void init_rtr_adv(ipv6_addr_t *addr){ rtr_adv_buf->hoplimit = MULTIHOP_HOPLIMIT; /* set M and O flag, last 6 bits are zero */ rtr_adv_buf->autoconfig_flags = (RTR_ADV_M_FLAG << 7) | (RTR_ADV_O_FLAG << 6); - rtr_adv_buf->router_lifetime = RTR_ADV_MAX_INTERVAL * RTR_ADV_MAX; + rtr_adv_buf->router_lifetime = HTONS(RTR_ADV_MAX_INTERVAL * RTR_ADV_MAX); rtr_adv_buf->reachable_time = 0; rtr_adv_buf->retrans_timer = 0; opt_hdr_len = RTR_ADV_LEN; - /* set link layer address option */ - opt_stllao_buf = get_opt_stllao_buf(ipv6_ext_hdr_len, opt_hdr_len); - set_llao((uint8_t *)opt_stllao_buf,OPT_STLLAO_LEN, 2); - opt_hdr_len += OPT_STLLAO_LEN; + packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + RTR_ADV_LEN; - /* set MTU options */ - opt_mtu_buf = get_opt_mtu_buf(ipv6_ext_hdr_len, opt_hdr_len); - opt_mtu_buf->type = OPT_MTU_TYPE; - opt_mtu_buf->length = OPT_MTU_LEN; - opt_mtu_buf->reserved = 0; - /* 1500 octets mtu */ - opt_mtu_buf->mtu = HTONL(1500); - opt_hdr_len += OPT_MTU_HDR_LEN; - - /* set packet length */ - packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + - RTR_ADV_LEN + OPT_STLLAO_LEN + OPT_MTU_HDR_LEN; + if(sllao == OPT_SLLAO){ + /* set link layer address option */ + opt_stllao_buf = get_opt_stllao_buf(ipv6_ext_hdr_len, opt_hdr_len); + set_llao(opt_stllao_buf,OPT_STLLAO_LEN, 2); + opt_hdr_len += OPT_STLLAO_LEN; + packet_length += OPT_STLLAO_LEN; + } + + if(mtu == OPT_MTU){ + /* set MTU options */ + opt_mtu_buf = get_opt_mtu_buf(ipv6_ext_hdr_len, opt_hdr_len); + opt_mtu_buf->type = OPT_MTU_TYPE; + opt_mtu_buf->length = OPT_MTU_LEN; + opt_mtu_buf->reserved = 0; + opt_mtu_buf->mtu = HTONL(1500); + opt_hdr_len += OPT_MTU_HDR_LEN; + packet_length += OPT_MTU_HDR_LEN; + } /* set payload length field */ - /* set prefix option */ - opt_pi_buf = get_opt_pi_buf(ipv6_ext_hdr_len, opt_hdr_len); - for(int i=0;iaddr = plist[i].addr; + if(pi == OPT_PI){ + /* set prefix option */ + for(int i=0;iaddr.uint8[0]), &(plist[i].addr.uint8[0]), 16); opt_pi_buf->type = OPT_PI_TYPE; opt_pi_buf->length = OPT_PI_LEN; opt_pi_buf->prefix_length = plist[i].length; opt_pi_buf->l_a_reserved1 = plist[i].l_a_reserved1; - opt_pi_buf->val_ltime = HTONL(pelem->val_ltime); - opt_pi_buf->pref_ltime = HTONL(pelem->val_ltime); + opt_pi_buf->val_ltime = HTONL(plist[i].val_ltime); + opt_pi_buf->pref_ltime = HTONL(plist[i].val_ltime); opt_pi_buf->reserved2 = 0; packet_length += OPT_PI_HDR_LEN; opt_hdr_len += OPT_PI_HDR_LEN; } + } } ipv6_buf->length = packet_length - IPV6_HDR_LEN; @@ -174,8 +235,110 @@ void init_rtr_adv(ipv6_addr_t *addr){ //printf("%x\n",icmp_buf->checksum); } -void init_nbr_sol(ipv6_addr_t *src, ipv6_addr_t *dest, ipv6_addr_t *targ){ - ipv6_ext_hdr_len = 0; +void recv_rtr_adv(void){ + ipv6_buf = get_ipv6_buf(); + opt_hdr_len = RTR_ADV_LEN; + rtr_adv_buf = get_rtr_adv_buf(ipv6_ext_hdr_len); + + /* update interface reachable time and retrans timer */ + if(rtr_adv_buf->reachable_time != 0){ + iface.adv_reachable_time = HTONL(rtr_adv_buf->reachable_time); + } + + if(rtr_adv_buf->retrans_timer != 0){ + iface.adv_retrans_timer = HTONL(rtr_adv_buf->retrans_timer); + } + + def_rtr_entry = def_rtr_lst_search(&ipv6_buf->srcaddr); + + if(rtr_adv_buf->router_lifetime != 0){ + if(def_rtr_entry != NULL){ + def_rtr_entry->inval_timer.absolute.seconds = + HTONL(rtr_adv_buf->router_lifetime); + vtimer_set(&(def_rtr_entry->inval_timer)); + } else { + def_rtr_lst_add(&(ipv6_buf->srcaddr), HTONL(rtr_adv_buf->router_lifetime)); + } + } else { + /* remove router from default router list */ + if(def_rtr_entry != NULL){ + def_rtr_lst_rem(def_rtr_entry); + } + } + + /* read options */ + while(packet_length > IPV6HDR_ICMPV6HDR_LEN + opt_hdr_len){ + opt_buf = get_opt_buf(ipv6_ext_hdr_len, opt_hdr_len); + timex_t tmp; + + switch(opt_buf->type){ + case(OPT_SLLAO_TYPE):{ + break; + } + case(OPT_MTU_TYPE):{ + break; + } + /* rfc 4862 section 5.5.3 */ + case(OPT_PI_TYPE):{ + opt_pi_buf = get_opt_pi_buf(ipv6_ext_hdr_len, opt_hdr_len); + /* crazy condition, read 5.5.3a-b-c for further information */ + if((!(opt_pi_buf->l_a_reserved1 & OPT_PI_FLAG_A)) || + (prefix_link_local_check(&opt_pi_buf->addr)) || + (opt_pi_buf->pref_ltime > opt_pi_buf->val_ltime)){ + break; + } else{ + addr_list_ptr = iface_addr_list_prefix_equals(&opt_pi_buf->addr); + if(addr_list_ptr == NULL){ + /* 5.5.3d */ + if(opt_pi_buf->val_ltime != 0){ + setup_addr_with_prefix(&tmpaddr, &opt_pi_buf->addr); + /* add into address list */ + iface_addr_list_add(&tmpaddr,ADDR_STATE_TENTATIVE, + opt_pi_buf->val_ltime, + opt_pi_buf->pref_ltime, + ADDR_CONFIGURED_AUTO); + } + } else { + /* 5.5.3e */ + set_remaining_time(&(addr_list_ptr->pref_ltime), opt_pi_buf->pref_ltime); + //addr_list_ptr->pref_ltime.absolute.seconds = opt_pi_buf->pref_ltime; + //vtimer_set(&addr_list_ptr->pref_ltime); + + /* 7200 = 2hours in seconds */ + if(HTONL(opt_pi_buf->val_ltime) > 7200 || + HTONL(opt_pi_buf->val_ltime) > + //addr_list_ptr->val_ltime.absolute.seconds){ + get_remaining_time(&(addr_list_ptr->val_ltime))){ + set_remaining_time(&(addr_list_ptr->val_ltime),HTONL(opt_pi_buf->val_ltime)); + addr_list_ptr->val_ltime.absolute.seconds = HTONL(opt_pi_buf->val_ltime); + vtimer_set(&addr_list_ptr->val_ltime); + } else { + /* reset valid lifetime to 2 hours */ + //set_remaining_time(addr_list_ptr->val_ltime, 7200); + //addr_list_ptr->val_ltime.absolute.seconds = 7200; + tmp.seconds = 7200; + vtimer_set_wakeup(&(addr_list_ptr->val_ltime), tmp, NULL); + } + } + } + break; + } + case(OPT_6CO_TYPE):{ + break; + } + case(OPT_ABRO_TYPE):{ + break; + } + default: + break; + } + /* multiplied with 8 because options length is in units of 8 bytes */ + opt_hdr_len += (opt_buf->length * 8); + } +} + +void init_nbr_sol(ipv6_addr_t *src, ipv6_addr_t *dest, ipv6_addr_t *targ, + uint8_t sllao, uint8_t aro){ ipv6_buf = get_ipv6_buf(); ipv6_buf->version_trafficclass = IPV6_VER; ipv6_buf->trafficclass_flowlabel = 0; @@ -184,88 +347,60 @@ void init_nbr_sol(ipv6_addr_t *src, ipv6_addr_t *dest, ipv6_addr_t *targ){ ipv6_buf->hoplimit = ND_HOPLIMIT; if(src == NULL){ - // TODO: src auswaehlen + } else{ - ipv6_buf->srcaddr = *src; + memcpy(&(ipv6_buf->srcaddr), src, 16); } if(dest == NULL){ - // TODO: solicited knoten erstellen + create_solicited_node_mcast_addr(targ, &(ipv6_buf->destaddr)); } else{ - ipv6_buf->destaddr = *dest; + memcpy(&(ipv6_buf->destaddr.uint8[0]), &(dest->uint8[0]), 16); } - + + ipv6_ext_hdr_len = 0; icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len); icmp_buf->type = ICMP_NBR_SOL; icmp_buf->code = 0; nbr_sol_buf = get_nbr_sol_buf(ipv6_ext_hdr_len); - nbr_sol_buf->reserved = 0; - nbr_sol_buf->tgtaddr = *targ; + nbr_sol_buf->reserved = 0; + memcpy(&(nbr_sol_buf->tgtaddr), targ, 16); opt_hdr_len = NBR_SOL_LEN; - /* set sllao option */ - opt_stllao_buf = get_opt_stllao_buf(ipv6_ext_hdr_len, opt_hdr_len); - set_llao((uint8_t*)opt_stllao_buf, OPT_SLLAO_TYPE, 1); - opt_hdr_len += OPT_STLLAO_LEN; + packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + NBR_SOL_LEN; + + if(sllao == OPT_SLLAO){ + /* set sllao option */ + opt_stllao_buf = get_opt_stllao_buf(ipv6_ext_hdr_len, opt_hdr_len); + set_llao(opt_stllao_buf, OPT_SLLAO_TYPE, 1); + opt_hdr_len += OPT_STLLAO_LEN; + + packet_length += OPT_STLLAO_LEN; + } - /* set aro option */ - opt_aro_buf = get_opt_aro_buf(ipv6_ext_hdr_len, opt_hdr_len); - opt_aro_buf->type = OPT_ARO_TYPE; - opt_aro_buf->length = OPT_ARO_LEN; - opt_aro_buf->status = 0; - opt_aro_buf->reserved1 = 0; - opt_aro_buf->reserved2 = 0; - opt_aro_buf->eui64 = *get_eui(src); - opt_hdr_len += OPT_ARO_HDR_LEN; + if(aro == OPT_ARO){ + /* set aro option */ + opt_aro_buf = get_opt_aro_buf(ipv6_ext_hdr_len, opt_hdr_len); + opt_aro_buf->type = OPT_ARO_TYPE; + opt_aro_buf->length = OPT_ARO_LEN; + opt_aro_buf->status = 0; + opt_aro_buf->reserved1 = 0; + opt_aro_buf->reserved2 = 0; + memcpy(&(opt_aro_buf->eui64), get_eui(src),8); + opt_hdr_len += OPT_ARO_HDR_LEN; - packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + NBR_SOL_LEN + - OPT_STLLAO_LEN + OPT_ARO_HDR_LEN; + packet_length += OPT_ARO_HDR_LEN; + } + ipv6_buf->length = packet_length - IPV6_HDR_LEN; } -void pfx_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){ - if(pfx_chk_list(addr,size) == 1){ - pelem->inuse = 1; - pelem->length = size; - pelem->adv = adv_opt; - pelem->l_a_reserved1 = l_a_reserved1; - pelem->val_ltime = val_ltime; - pelem->pref_ltime = pref_ltime; - pelem->addr = *addr; - } -} - -uint8_t pfx_chk_list(ipv6_addr_t *addr, uint8_t size){ - pelem = NULL; - for(int i=0 ; i < size ; i++){ - if(plist[i].inuse){ - if(pfx_cmp(&plist[i].addr, addr)){ - *pelem = plist[i]; - return 0; - } - } else { - *pelem = plist[i]; - } - } - if(pelem){ - return 1; - } - return 2; -} - -uint8_t pfx_cmp(ipv6_addr_t *addr1, ipv6_addr_t *addr2){ - if(memcmp(addr1, addr2, 8) == 0){ - return 1; - } - return 0; -} - /* link-layer address option - RFC4861 section 4.6.1/ RFC4944 8. */ -void set_llao(uint8_t *llao, uint8_t type, uint8_t length){ - llao[0] = type; - llao[1] = length; +void set_llao(opt_stllao_t *sllao, uint8_t type, uint8_t length){ + sllao->type = type; + sllao->length = length; + uint8_t *llao = (uint8_t*)sllao; // get link layer address switch(length) { case(1):{ @@ -276,21 +411,17 @@ void set_llao(uint8_t *llao, uint8_t type, uint8_t length){ case(2):{ memcpy(&llao[2], &(iface.laddr), 8); memset(&llao[10], 0, 6); + break; } default:{ printf("ERROR: llao not set\n"); break; } } - //ieee_802154_long_t *mac = get_eui(&ipv6_buf->srcaddr); - //get_ieee_802154_long_t_from_ipaddr(&ipv6_buf->srcaddr,&mac); - - //memcpy(&llao[2], mac, SIXLOWPAN_IPV6_LL_ADDR_LEN); - // padding (all zeros) - 48bit - //memset(&llao[2 + SIXLOWPAN_IPV6_LL_ADDR_LEN], 0, - // OPT_STLLAO_LEN - SIXLOWPAN_IPV6_LL_ADDR_LEN - 2); } +//------------------------------------------------------------------------------ +// checksum calculation uint16_t csum(uint16_t sum, uint8_t *buf, uint16_t len){ int count; @@ -322,16 +453,111 @@ uint16_t csum(uint16_t sum, uint8_t *buf, uint16_t len){ return sum; } - uint16_t icmpv6_csum(uint8_t proto){ ipv6_buf = get_ipv6_buf(); uint16_t sum; uint16_t len = ipv6_buf->length; sum = len + proto; + sum = csum(sum, (uint8_t *)&ipv6_buf->srcaddr, 2 * sizeof(ipv6_addr_t)); sum = csum(sum,(uint8_t*)get_icmpv6_buf(0),len); return (sum == 0) ? 0xffff : HTONS(sum); } +//------------------------------------------------------------------------------ +// neighbor cache functions + +nbr_cache_t * nbr_cache_search(ipv6_addr_t *ipaddr){ + int i; + for(i = 0; i < NBR_CACHE_SIZE; i++){ + if(memcmp(&(nbr_cache[i].addr.uint8[0]), &(ipaddr->uint8[0]), 16) == 0){ + return &nbr_cache[i]; + } + } + return NULL; +} + +void nbr_cache_add(ipv6_addr_t *ipaddr, ieee_802154_long_t *laddr, + uint8_t isrouter, uint8_t state){ + if(nbr_count == NBR_CACHE_SIZE){ + printf("ERROR: neighbor cache full\n"); + } else { + memcpy(&(nbr_cache[nbr_count].addr), ipaddr, 16); + memcpy(&(nbr_cache[nbr_count].laddr), laddr, 8); + nbr_cache[nbr_count].isrouter = isrouter; + nbr_cache[nbr_count].state = state; + + nbr_count++; + } +} + +//------------------------------------------------------------------------------ +// default router list functions + +def_rtr_lst_t * def_rtr_lst_search(ipv6_addr_t *ipaddr){ + int i; + for(i = 0; i < DEF_RTR_LST_SIZE; i++){ + if(memcmp(&def_rtr_lst[i].addr.uint8[0], + &(ipaddr->uint8[0]), 16) == 0){ + return &def_rtr_lst[i]; + } + } + return NULL; +} + +void def_rtr_lst_add(ipv6_addr_t *ipaddr, uint32_t rtr_ltime){ + if(def_rtr_count == DEF_RTR_LST_SIZE){ + DEBUG("ERROR: default router list full\n"); + } else { + memcpy(&(def_rtr_lst[def_rtr_count].addr), ipaddr, 16); + def_rtr_lst[def_rtr_count].inval_timer.absolute.seconds = rtr_ltime; + vtimer_set(&(def_rtr_lst[def_rtr_count].inval_timer)); + + def_rtr_count++; + } +} + +void def_rtr_lst_rem(def_rtr_lst_t *entry){ + int i; + for(i = 0; i < DEF_RTR_LST_SIZE; i++){ + if(&def_rtr_lst[i] == entry){ + /* search the to deleted item, then memmove the last item to its + * position, and decrement array count */ + memmove(entry, &def_rtr_lst[def_rtr_count], sizeof(def_rtr_lst_t)); + memset(&def_rtr_lst[def_rtr_count], 0, sizeof(def_rtr_lst_t)); + def_rtr_count--; + } + } +} + +//------------------------------------------------------------------------------ +// prefix list functions + +void 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){ + if(prefix_count == OPT_PI_LIST_LEN){ + printf("ERROR: prefix list full\n"); + } else { + plist[prefix_count].inuse = 1; + plist[prefix_count].length = size; + plist[prefix_count].adv = adv_opt; + plist[prefix_count].l_a_reserved1 = l_a_reserved1; + plist[prefix_count].val_ltime = val_ltime; + plist[prefix_count].pref_ltime = pref_ltime; + memcpy(&(plist[prefix_count].addr.uint8[0]), &(addr->uint8[0]), 16); + + prefix_count++; + } +} + +uint8_t plist_search(ipv6_addr_t *addr){ + int i; + for(i = 0; i < OPT_PI_LIST_LEN; i++){ + if(memcmp(&(plist[i].addr.uint8[0]), &addr->uint8[0], 16) == 0){ + return &plist[i]; + } + } + return NULL; +} diff --git a/sys/net/sixlowpan/sixlownd.h b/sys/net/sixlowpan/sixlownd.h index c27e1bf40c..55a30883a0 100644 --- a/sys/net/sixlowpan/sixlownd.h +++ b/sys/net/sixlowpan/sixlownd.h @@ -1,4 +1,5 @@ #include +#include "vtimer.h" /* router solicitation */ #define RTR_SOL_LEN 4 @@ -28,6 +29,9 @@ #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 @@ -37,10 +41,41 @@ #define OPT_ARO_LEN 2 #define OPT_ARO_HDR_LEN 16 #define OPT_ARO_LTIME 300 // geeigneten wert finden +/* 6lowpan context option */ +#define OPT_6CO_TYPE 32 +/* authoritative border router option */ +#define OPT_ABRO_TYPE 33 +/* neighbor cache size */ +#define NBR_CACHE_SIZE 8 +/* 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 + +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; + uint8_t type; + uint8_t length; } opt_stllao_t; typedef struct __attribute__ ((packed)) opt_mtu_t { @@ -71,7 +106,7 @@ typedef struct __attribute__ ((packed)) opt_aro_t { ieee_802154_long_t eui64; } opt_aro_t; -typedef struct __attribute__ ((packed)) pfx_elem_t { +typedef struct __attribute__ ((packed)) plist_t { uint8_t inuse; uint8_t adv; ipv6_addr_t addr; @@ -79,7 +114,8 @@ typedef struct __attribute__ ((packed)) pfx_elem_t { uint8_t l_a_reserved1; uint32_t val_ltime; uint32_t pref_ltime; -} pfx_elem_t; + uint8_t infinite; +} plist_t; struct __attribute__ ((packed)) rtr_adv_t { uint8_t hoplimit; @@ -95,14 +131,38 @@ struct __attribute__ ((packed)) nbr_sol_t { }; -void init_rtr_sol(void); -void recv_rtr_sol(void); -void init_rtr_adv(ipv6_addr_t *addr); -uint8_t pfx_chk_list(ipv6_addr_t *addr, uint8_t size); -uint8_t pfx_cmp(ipv6_addr_t *addr1, ipv6_addr_t *addr2); -void pfx_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(uint8_t *llao, uint8_t type, uint8_t length); +/* neighbor cache - rfc4861 5.1. */ +typedef struct __attribute__ ((packed)) nbr_cache_t { + uint8_t state; + uint8_t isrouter; + ipv6_addr_t addr; + ieee_802154_long_t laddr; +} nbr_cache_t; +/* default router list - rfc4861 5.1. */ +typedef struct __attribute__ ((packed)) def_rtr_lst_t { + ipv6_addr_t addr; + vtimer_t inval_timer; +} def_rtr_lst_t; + +void init_rtr_sol(uint8_t sllao); +void recv_rtr_sol(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); +void 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); +nbr_cache_t * nbr_cache_search(ipv6_addr_t *ipaddr); +void nbr_cache_add(ipv6_addr_t *ipaddr, ieee_802154_long_t *laddr, + uint8_t isrouter, uint8_t state); uint16_t icmpv6_csum(uint8_t proto); uint16_t csum(uint16_t sum, uint8_t *buf, uint16_t len); +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_nbr_sol(ipv6_addr_t *src, ipv6_addr_t *dest, ipv6_addr_t *targ, + uint8_t slloa, uint8_t aro); +void 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); diff --git a/sys/net/sixlowpan/sixlowpan.c b/sys/net/sixlowpan/sixlowpan.c index d61becabb4..ad9cfabe67 100644 --- a/sys/net/sixlowpan/sixlowpan.c +++ b/sys/net/sixlowpan/sixlowpan.c @@ -1,14 +1,19 @@ #include #include #include +#include #include "thread.h" #include "msg.h" #include "sixlowmac.h" #include "sixlowpan.h" +#include "sixlowip.h" +#include "sixlownd.h" #include "transceiver.h" #include "ieee802154_frame.h" +uint8_t iface_addr_list_count = 0; uint16_t packet_length; +uint8_t packet_dispatch; uint16_t tag; uint8_t packet_size = 0; uint8_t header_size = 0; @@ -17,36 +22,54 @@ uint8_t max_frag_initial = 0; uint8_t position; uint8_t max_frag; +struct ipv6_hdr_t *ipv6_buf; + uint8_t frag_size; uint8_t *reas_buf; uint8_t byte_offset; uint8_t first_frag = 0; -static struct ipv6_hdr_t *ipv6_buf; unsigned int ip_process_pid; iface_t iface; +ipv6_addr_t loaddr; char ip_process_buf[IP_PROCESS_STACKSIZE]; /* deliver packet to mac*/ void output(uint8_t *addr, uint8_t *data){ + /* TODO: compression and set global dispatch byte */ + packet_dispatch = 0x41; + + /* check/set dispatch byte */ + switch(packet_dispatch){ + case(DISPATCH_TYPE_IPV6):{ + memmove(data + 1, data, packet_length); + data[0] = packet_dispatch; + packet_length++; + break; + } + case(DISPATCH_TYPE_LOWPAN_HC1):{ + break; + } + default: + printf("ERROR: wrong dispatch byte\n"); + } + packet_size = (uint8_t)packet_length; /* check if packet needs to be fragmented */ if(packet_size + header_size > PAYLOAD_SIZE - IEEE_802154_MAX_HDR_LEN){ printf("INFO: packet is to large, fragmentation started. size:" " %hu byte\n", packet_length); - uint8_t *ptr = data; uint8_t fragbuf[packet_size + header_size]; uint8_t remaining; uint8_t i = 2; /* first fragment */ - max_frame = PAYLOAD_SIZE - IEEE_802154_MAX_HDR_LEN; max_frag_initial = ((max_frame - 4 - header_size) / 8) * 8; - memcpy(fragbuf + 4, ptr, max_frag_initial); + memcpy(fragbuf + 4, data, max_frag_initial); fragbuf[0] = (((0xc0 << 8) | packet_length) >> 8) & 0xff; fragbuf[1] = ((0xc0 << 8) | packet_length) & 0xff; @@ -59,11 +82,11 @@ void output(uint8_t *addr, uint8_t *data){ position = max_frag_initial; max_frag = ((max_frame - 5) / 8) * 8; - ptr += position; + data += position; while(packet_size - position > max_frame - 5){ memset(&fragbuf,0,packet_size + header_size); - memcpy(fragbuf + 5, ptr, max_frag); + memcpy(fragbuf + 5, data, max_frag); fragbuf[0] = (((0xe0 << 8) | packet_length) >> 8) & 0xff; fragbuf[1] = ((0xe0 << 8) | packet_length) & 0xff; @@ -73,14 +96,16 @@ void output(uint8_t *addr, uint8_t *data){ send_ieee802154_frame(addr,(uint8_t*)&fragbuf, max_frag + 5); printf(" frag %d size: %d byte\n",i , max_frag); - ptr += position; + data += max_frag; position += max_frag; + i++; } remaining = packet_size - position; + memset(&fragbuf,0,packet_size + header_size); - memcpy(fragbuf + 5, ptr, remaining); + memcpy(fragbuf + 5, data, remaining); fragbuf[0] = (((0xe0 << 8) | packet_length) >> 8) & 0xff; fragbuf[1] = ((0xe0 << 8) | packet_length) & 0xff; @@ -150,13 +175,26 @@ void input(uint8_t *data, uint8_t length){ frag_size = length - hdr_length; byte_offset = datagram_offset * 8; if((frag_size % 8) != 0){ - printf("ERROR: received invalid fragment\n"); - return; + if((byte_offset + frag_size) != datagram_size){ + printf("ERROR: received invalid fragment\n"); + return; + } } memcpy(reas_buf + byte_offset, data + hdr_length, byte_offset); if((byte_offset + frag_size) == datagram_size){ - m.content.ptr = (char*)reas_buf; - msg_send(&m,ip_process_pid, 1); + //m.content.ptr = (char*)reas_buf; + switch(reas_buf[0]) { + case(DISPATCH_TYPE_IPV6):{ + ipv6_buf = get_ipv6_buf(); + memcpy(ipv6_buf, reas_buf + 1, datagram_size - 1); + m.content.ptr = (char*) ipv6_buf; + packet_length = datagram_size - 1; + msg_send(&m,ip_process_pid, 1); + break; + } + default: + printf("ERROR: packet with unknown dispatch received\n"); + } free(reas_buf); } break; @@ -171,16 +209,25 @@ void input(uint8_t *data, uint8_t length){ void sixlowpan_init(transceiver_type_t trans){ /* init mac-layer and radio transceiver */ + vtimer_init(); sixlowmac_init(trans); /* init interface addresses */ memset(&iface,0,sizeof(iface_t)); init_802154_short_addr(&(iface.saddr)); init_802154_long_addr(&(iface.laddr)); - create_link_local_prefix(&(iface.ipaddr)); - memcpy(&(iface.ipaddr.uint8[8]), &iface.laddr, 8); + //create_link_local_prefix(&(iface.ipaddr)); + //memcpy(&(iface.ipaddr.uint8[8]), &iface.laddr, 8); + create_link_local_prefix(&loaddr); + ipv6_addr_t prefix; + create_prefix(&prefix, HTONS(0xabcd)); + plist_add(&prefix, 64, OPT_PI_VLIFETIME_INFINITE,0,1,0); + memcpy(&(loaddr.uint8[8]), &(iface.laddr.uint8[0]), 8); + iface_addr_list_add(&loaddr, ADDR_STATE_PREFERRED, 0, 0, + ADDR_CONFIGURED_AUTO); + ip_process_pid = thread_create(ip_process_buf, IP_PROCESS_STACKSIZE, PRIORITY_MAIN-1, CREATE_STACKTEST, ip_process, "ip_process"); -// send_ieee802154_frame(); + //send_ieee802154_frame(); }