integration of new uip6 code from Mathilde and Julien - adds routing and improved interface handling

This commit is contained in:
joxe 2010-03-15 16:41:24 +00:00
parent 7d5e3fbfde
commit fd3d6c44d0
15 changed files with 1558 additions and 2448 deletions

View file

@ -45,7 +45,7 @@ UPPERCASE = _ABCDEFGHIJKLMNOPQRSTUVWXYZ
TARGET_UPPERCASE := ${shell echo $(TARGET) | sed 'y!$(LOWERCASE)!$(UPPERCASE)!'} TARGET_UPPERCASE := ${shell echo $(TARGET) | sed 'y!$(LOWERCASE)!$(UPPERCASE)!'}
CFLAGS += -DCONTIKI_TARGET_$(TARGET_UPPERCASE) CFLAGS += -DCONTIKI_TARGET_$(TARGET_UPPERCASE)
include $(CONTIKI)/core/net/routing/Makefile.routing #include $(CONTIKI)/core/net/routing/Makefile.routing
include $(CONTIKI)/core/net/rime/Makefile.rime include $(CONTIKI)/core/net/rime/Makefile.rime
include $(CONTIKI)/core/net/mac/Makefile.mac include $(CONTIKI)/core/net/mac/Makefile.mac
SYSTEM = process.c procinit.c autostart.c elfloader.c profile.c \ SYSTEM = process.c procinit.c autostart.c elfloader.c profile.c \
@ -60,8 +60,8 @@ ifdef UIP_CONF_IPV6
CFLAGS += -DUIP_CONF_IPV6 CFLAGS += -DUIP_CONF_IPV6
UIP = uip6.c tcpip.c psock.c uip-udp-packet.c uip-split.c \ UIP = uip6.c tcpip.c psock.c uip-udp-packet.c uip-split.c \
resolv.c tcpdump.c uiplib.c resolv.c tcpdump.c uiplib.c
NET += $(UIP) uip-icmp6.c uip-nd6.c uip-nd6-io.c uip-netif.c \ NET += $(UIP) uip-icmp6.c uip-nd6.c \
sicslowpan.c neighbor-attr.c neighbor-info.c sicslowpan.c neighbor-attr.c neighbor-info.c uip-ds6.c
else # UIP_CONF_IPV6 else # UIP_CONF_IPV6
UIP = uip.c uiplib.c resolv.c tcpip.c psock.c hc.c uip-split.c uip-fw.c \ UIP = uip.c uiplib.c resolv.c tcpip.c psock.c hc.c uip-split.c uip-fw.c \
uip-fw-drv.c uip_arp.c tcpdump.c uip-neighbor.c uip-udp-packet.c \ uip-fw-drv.c uip_arp.c tcpdump.c uip-neighbor.c uip-udp-packet.c \

View file

@ -32,7 +32,7 @@
* *
* This file is part of the Contiki operating system. * This file is part of the Contiki operating system.
* *
* $Id: sicslowpan.c,v 1.27 2010/03/12 13:40:13 nvt-se Exp $ * $Id: sicslowpan.c,v 1.28 2010/03/15 16:41:24 joxe Exp $
*/ */
/** /**
* \file * \file
@ -62,7 +62,7 @@
#include "dev/watchdog.h" #include "dev/watchdog.h"
#include "net/tcpip.h" #include "net/tcpip.h"
#include "net/uip.h" #include "net/uip.h"
#include "net/uip-netif.h" #include "net/uip-ds6.h"
#include "net/rime.h" #include "net/rime.h"
#include "net/sicslowpan.h" #include "net/sicslowpan.h"
#include "net/neighbor-info.h" #include "net/neighbor-info.h"
@ -753,7 +753,7 @@ uncompress_hdr_hc06(u16_t ip_len) {
/* copy prefix from context */ /* copy prefix from context */
memcpy(&SICSLOWPAN_IP_BUF->srcipaddr, context->prefix, 8); memcpy(&SICSLOWPAN_IP_BUF->srcipaddr, context->prefix, 8);
/* infer IID from L2 address */ /* infer IID from L2 address */
uip_netif_addr_autoconf_set(&SICSLOWPAN_IP_BUF->srcipaddr, uip_ds6_set_addr_iid(&SICSLOWPAN_IP_BUF->srcipaddr,
(uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
break; break;
} }
@ -790,7 +790,7 @@ uncompress_hdr_hc06(u16_t ip_len) {
/* copy 12 NULL bytes then 8 last bytes from L2 */ /* copy 12 NULL bytes then 8 last bytes from L2 */
memset(&SICSLOWPAN_IP_BUF->srcipaddr.u8[2], 0, 6); memset(&SICSLOWPAN_IP_BUF->srcipaddr.u8[2], 0, 6);
/* infer IID from L2 address */ /* infer IID from L2 address */
uip_netif_addr_autoconf_set(&SICSLOWPAN_IP_BUF->srcipaddr, uip_ds6_set_addr_iid(&SICSLOWPAN_IP_BUF->srcipaddr,
(uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
break; break;
} }
@ -866,7 +866,7 @@ uncompress_hdr_hc06(u16_t ip_len) {
case SICSLOWPAN_IPHC_DAM_11: /* 0 bits */ case SICSLOWPAN_IPHC_DAM_11: /* 0 bits */
/* unicast address */ /* unicast address */
memcpy(&SICSLOWPAN_IP_BUF->destipaddr, context->prefix, 8); memcpy(&SICSLOWPAN_IP_BUF->destipaddr, context->prefix, 8);
uip_netif_addr_autoconf_set(&SICSLOWPAN_IP_BUF->destipaddr, uip_ds6_set_addr_iid(&SICSLOWPAN_IP_BUF->destipaddr,
(uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
break; break;
} }
@ -895,7 +895,7 @@ uncompress_hdr_hc06(u16_t ip_len) {
SICSLOWPAN_IP_BUF->destipaddr.u8[0] = 0xfe; SICSLOWPAN_IP_BUF->destipaddr.u8[0] = 0xfe;
SICSLOWPAN_IP_BUF->destipaddr.u8[1] = 0x80; SICSLOWPAN_IP_BUF->destipaddr.u8[1] = 0x80;
memset(&SICSLOWPAN_IP_BUF->destipaddr.u8[2], 0, 6); memset(&SICSLOWPAN_IP_BUF->destipaddr.u8[2], 0, 6);
uip_netif_addr_autoconf_set(&SICSLOWPAN_IP_BUF->destipaddr, uip_ds6_set_addr_iid(&SICSLOWPAN_IP_BUF->destipaddr,
(uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
break; break;
} }
@ -1145,10 +1145,10 @@ uncompress_hdr_hc1(u16_t ip_len) {
/* src and dest ip addresses */ /* src and dest ip addresses */
uip_ip6addr(&SICSLOWPAN_IP_BUF->srcipaddr, 0xfe80, 0, 0, 0, 0, 0, 0, 0); uip_ip6addr(&SICSLOWPAN_IP_BUF->srcipaddr, 0xfe80, 0, 0, 0, 0, 0, 0, 0);
uip_netif_addr_autoconf_set(&SICSLOWPAN_IP_BUF->srcipaddr, uip_sd6_set_addr_iid(&SICSLOWPAN_IP_BUF->srcipaddr,
(uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
uip_ip6addr(&SICSLOWPAN_IP_BUF->destipaddr, 0xfe80, 0, 0, 0, 0, 0, 0, 0); uip_ip6addr(&SICSLOWPAN_IP_BUF->destipaddr, 0xfe80, 0, 0, 0, 0, 0, 0, 0);
uip_netif_addr_autoconf_set(&SICSLOWPAN_IP_BUF->destipaddr, uip_sd6_set_addr_iid(&SICSLOWPAN_IP_BUF->destipaddr,
(uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
uncomp_hdr_len += UIP_IPH_LEN; uncomp_hdr_len += UIP_IPH_LEN;

View file

@ -29,7 +29,7 @@
* This file is part of the Contiki operating system. * This file is part of the Contiki operating system.
* *
* *
* $Id: tcpip.c,v 1.24 2010/02/09 12:58:53 adamdunkels Exp $ * $Id: tcpip.c,v 1.25 2010/03/15 16:41:24 joxe Exp $
*/ */
/** /**
* \file * \file
@ -47,7 +47,7 @@
#if UIP_CONF_IPV6 #if UIP_CONF_IPV6
#include "net/uip-nd6.h" #include "net/uip-nd6.h"
#include "net/uip-netif.h" #include "net/uip-ds6.h"
#endif #endif
#define DEBUG 0 #define DEBUG 0
@ -469,28 +469,23 @@ eventhandler(process_event_t ev, process_data_t data)
* check the different timers for neighbor discovery and * check the different timers for neighbor discovery and
* stateless autoconfiguration * stateless autoconfiguration
*/ */
if(data == &uip_nd6_timer_periodic && /*if(data == &uip_nd6_timer_periodic &&
etimer_expired(&uip_nd6_timer_periodic)) { etimer_expired(&uip_nd6_timer_periodic)) {
uip_nd6_periodic(); uip_nd6_periodic();
tcpip_ipv6_output(); tcpip_ipv6_output();
} }*/
#if !UIP_CONF_ROUTER
if(data == &uip_netif_timer_dad && if(data == &uip_ds6_timer_rs &&
etimer_expired(&uip_netif_timer_dad)){ etimer_expired(&uip_ds6_timer_rs)){
uip_netif_dad(); uip_ds6_send_rs();
tcpip_ipv6_output(); tcpip_ipv6_output();
} }
#endif /* !UIP_CONF_ROUTER */
if(data == &uip_netif_timer_rs && if(data == &uip_ds6_timer_periodic &&
etimer_expired(&uip_netif_timer_rs)){ etimer_expired(&uip_ds6_timer_periodic)){
uip_netif_send_rs(); uip_ds6_periodic();
tcpip_ipv6_output(); tcpip_ipv6_output();
} }
if(data == &uip_netif_timer_periodic &&
etimer_expired(&uip_netif_timer_periodic)){
uip_netif_periodic();
}
#endif /* UIP_CONF_IPV6 */ #endif /* UIP_CONF_IPV6 */
} }
break; break;
@ -547,8 +542,8 @@ tcpip_input(void)
void void
tcpip_ipv6_output(void) tcpip_ipv6_output(void)
{ {
struct uip_nd6_neighbor *nbc = NULL; uip_ds6_nbr_t *nbr = NULL;
struct uip_nd6_defrouter *dr = NULL; uip_ipaddr_t* nexthop;
if(uip_len == 0) if(uip_len == 0)
return; return;
@ -564,55 +559,33 @@ tcpip_ipv6_output(void)
return; return;
} }
if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) { if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) {
/*If destination is on link */ /* Next hop determination */
nbc = NULL; nbr = NULL;
if(uip_nd6_is_addr_onlink(&UIP_IP_BUF->destipaddr)){ if(uip_ds6_is_addr_onlink(&UIP_IP_BUF->destipaddr)){
nbc = uip_nd6_nbrcache_lookup(&UIP_IP_BUF->destipaddr); nexthop = &UIP_IP_BUF->destipaddr;
} else { } else {
#if UIP_CONF_ROUTER uip_ds6_route_t* locrt;
/*destination is not on link*/ locrt = uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr);
uip_ipaddr_t ipaddr; if(locrt == NULL) {
uip_ipaddr_t *next_hop; if((nexthop = uip_ds6_defrt_choose()) == NULL) {
PRINTF("tcpip_ipv6_output: Destination off-link but no route\n");
/* Try to find the next hop address in the local routing table. */
next_hop = uip_router != NULL ?
uip_router->lookup(&UIP_IP_BUF->destipaddr, &ipaddr) : NULL;
if(next_hop != NULL) {
/* Look for the next hop of the route in the neighbor cache.
Add a cache entry if we can't find it. */
nbc = uip_nd6_nbrcache_lookup(next_hop);
if(nbc == NULL) {
nbc = uip_nd6_nbrcache_add(next_hop, NULL, 1, NO_STATE);
}
} else {
#endif /* UIP_CONF_ROUTER */
/* No route found, check if a default router exists and use it then. */
dr = uip_nd6_choose_defrouter();
if(dr != NULL){
nbc = dr->nb;
} else {
/* shall we send a icmp error message destination unreachable ?*/
UIP_LOG("tcpip_ipv6_output: Destination off-link but no router");
uip_len = 0; uip_len = 0;
return; return;
} }
#if UIP_CONF_ROUTER
}
#endif /* UIP_CONF_ROUTER */
}
/* there are two cases where the entry logically does not exist:
* 1 it really does not exist. 2 it is in the NO_STATE state */
if (nbc == NULL || nbc->state == NO_STATE) {
if (nbc == NULL) {
/* create neighbor cache entry, original packet is replaced by NS*/
nbc = uip_nd6_nbrcache_add(&UIP_IP_BUF->destipaddr, NULL, 0, INCOMPLETE);
} else { } else {
nbc->state = INCOMPLETE; nexthop = &locrt->nexthop;
} }
}
/* end of next hop determination */
if((nbr = uip_ds6_nbr_lookup(nexthop)) == NULL) {
if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE)) == NULL) {
uip_len = 0;
return;
} else {
#if UIP_CONF_IPV6_QUEUE_PKT #if UIP_CONF_IPV6_QUEUE_PKT
/* copy outgoing pkt in the queuing buffer for later transmmit */ /* copy outgoing pkt in the queuing buffer for later transmmit */
memcpy(nbc->queue_buf, UIP_IP_BUF, uip_len); memcpy(nbr->queue_buf, UIP_IP_BUF, uip_len);
nbc->queue_buf_len = uip_len; nbr->queue_buf_len = uip_len;
#endif #endif
/* RFC4861, 7.2.2: /* RFC4861, 7.2.2:
* "If the source address of the packet prompting the solicitation is the * "If the source address of the packet prompting the solicitation is the
@ -620,23 +593,23 @@ tcpip_ipv6_output(void)
* address SHOULD be placed in the IP Source Address of the outgoing * address SHOULD be placed in the IP Source Address of the outgoing
* solicitation. Otherwise, any one of the addresses assigned to the * solicitation. Otherwise, any one of the addresses assigned to the
* interface should be used."*/ * interface should be used."*/
if(uip_netif_is_addr_my_unicast(&UIP_IP_BUF->srcipaddr)){ if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)){
uip_nd6_io_ns_output(&UIP_IP_BUF->srcipaddr, NULL, &nbc->ipaddr); uip_nd6_ns_output(&UIP_IP_BUF->srcipaddr, NULL, &nbr->ipaddr);
} else { } else {
uip_nd6_io_ns_output(NULL, NULL, &nbc->ipaddr); uip_nd6_ns_output(NULL, NULL, &nbr->ipaddr);
} }
stimer_set(&(nbc->last_send), stimer_set(&(nbr->sendns), uip_ds6_if.retrans_timer / 1000);
uip_netif_physical_if.retrans_timer / 1000); nbr->nscount = 1;
nbc->count_send = 1; }
} else { } else {
if (nbc->state == INCOMPLETE){ if (nbr->state == NBR_INCOMPLETE){
PRINTF("tcpip_ipv6_output: neighbor cache entry incomplete\n"); PRINTF("tcpip_ipv6_output: nbr cache entry incomplete\n");
#if UIP_CONF_IPV6_QUEUE_PKT #if UIP_CONF_IPV6_QUEUE_PKT
/* copy outgoing pkt in the queuing buffer for later transmmit and set /* copy outgoing pkt in the queuing buffer for later transmmit and set
the destination neighbor to nbc */ the destination nbr to nbr */
memcpy(nbc->queue_buf, UIP_IP_BUF, uip_len); memcpy(nbr->queue_buf, UIP_IP_BUF, uip_len);
nbc->queue_buf_len = uip_len; nbr->queue_buf_len = uip_len;
uip_len = 0; uip_len = 0;
#endif /*UIP_CONF_IPV6_QUEUE_PKT*/ #endif /*UIP_CONF_IPV6_QUEUE_PKT*/
return; return;
@ -644,17 +617,18 @@ tcpip_ipv6_output(void)
/* if running NUD (nbc->state == STALE, DELAY, or PROBE ) keep /* if running NUD (nbc->state == STALE, DELAY, or PROBE ) keep
sending in parallel see rfc 4861 Node behavior in section 7.7.3*/ sending in parallel see rfc 4861 Node behavior in section 7.7.3*/
if (nbc->state == STALE){ if (nbr->state == NBR_STALE){
nbc->state = DELAY; nbr->state = NBR_DELAY;
stimer_set(&(nbc->reachable), stimer_set(&(nbr->reachable),
UIP_ND6_DELAY_FIRST_PROBE_TIME); UIP_ND6_DELAY_FIRST_PROBE_TIME);
PRINTF("tcpip_ipv6_output: neighbor cache entry stale moving to delay\n"); nbr->nscount = 0;
PRINTF("tcpip_ipv6_output: nbr cache entry stale moving to delay\n");
} }
stimer_set(&(nbc->last_send), stimer_set(&(nbr->sendns),
uip_netif_physical_if.retrans_timer / 1000); uip_ds6_if.retrans_timer / 1000);
tcpip_output(&(nbc->lladdr)); tcpip_output(&(nbr->lladdr));
#if UIP_CONF_IPV6_QUEUE_PKT #if UIP_CONF_IPV6_QUEUE_PKT
@ -663,11 +637,11 @@ tcpip_ipv6_output(void)
* NA after sendiong a NS, you receive a NS with SLLAO: the entry moves * NA after sendiong a NS, you receive a NS with SLLAO: the entry moves
*to STALE, and you must both send a NA and the queued packet *to STALE, and you must both send a NA and the queued packet
*/ */
if(nbc->queue_buf_len != 0) { if(nbr->queue_buf_len != 0) {
uip_len = nbc->queue_buf_len; uip_len = nbr->queue_buf_len;
memcpy(UIP_IP_BUF, nbc->queue_buf, uip_len); memcpy(UIP_IP_BUF, nbr->queue_buf, uip_len);
nbc->queue_buf_len = 0; nbr->queue_buf_len = 0;
tcpip_output(&(nbc->lladdr)); tcpip_output(&(nbr->lladdr));
} }
#endif /*UIP_CONF_IPV6_QUEUE_PKT*/ #endif /*UIP_CONF_IPV6_QUEUE_PKT*/

View file

@ -60,6 +60,7 @@
struct etimer uip_ds6_timer_periodic; /** \brief Timer for maintenance of data structures */ struct etimer uip_ds6_timer_periodic; /** \brief Timer for maintenance of data structures */
#if UIP_CONF_ROUTER #if UIP_CONF_ROUTER
struct stimer uip_ds6_timer_ra; /** \brief RA timer, to schedule RA sending */ struct stimer uip_ds6_timer_ra; /** \brief RA timer, to schedule RA sending */
static uint8_t racount; /** \brief number of RA already sent */ static uint8_t racount; /** \brief number of RA already sent */
@ -71,50 +72,62 @@ static uint8_t rscount; /** \brief numbe
/** \name "DS6" Data structures */ /** \name "DS6" Data structures */
/** @{ */ /** @{ */
uip_ds6_netif uip_ds6_if; /** \brief The single interface */ uip_ds6_netif_t uip_ds6_if; /** \brief The single interface */
uip_ds6_nbr uip_ds6_nbr_cache[UIP_DS6_NBR_NB]; /** \brief Neighor cache */ uip_ds6_nbr_t uip_ds6_nbr_cache[UIP_DS6_NBR_NB]; /** \brief Neighor cache */
uip_ds6_defrt uip_ds6_defrt_list[UIP_DS6_DEFRT_NB]; /** \brief Default rt list */ uip_ds6_defrt_t uip_ds6_defrt_list[UIP_DS6_DEFRT_NB]; /** \brief Default rt list */
uip_ds6_prefix uip_ds6_prefix_list[UIP_DS6_PREFIX_NB]; /** \brief Prefix list */ uip_ds6_prefix_t uip_ds6_prefix_list[UIP_DS6_PREFIX_NB]; /** \brief Prefix list */
uip_ds6_route uip_ds6_routing_table[UIP_DS6_ROUTE_NB]; /** \brief Routing table */ uip_ds6_route_t uip_ds6_routing_table[UIP_DS6_ROUTE_NB]; /** \brief Routing table */
/** @} */ /** @} */
/* "full" (as opposed to pointer) ip address used in this file, */ /* "full" (as opposed to pointer) ip address used in this file, */
static uip_ipaddr_t loc_fipaddr; static uip_ipaddr_t loc_fipaddr;
/* Pointers used in this file */ /* Pointers used in this file */
static uip_ipaddr_t* locipaddr; static uip_ipaddr_t *locipaddr;
static uip_ds6_addr* locaddr; static uip_ds6_addr_t *locaddr;
static uip_ds6_maddr* locmaddr; static uip_ds6_maddr_t *locmaddr;
static uip_ds6_aaddr* locaaddr; static uip_ds6_aaddr_t *locaaddr;
static uip_ds6_prefix* locprefix; static uip_ds6_prefix_t *locprefix;
static uip_ds6_nbr* locnbr; static uip_ds6_nbr_t *locnbr;
static uip_ds6_defrt* locdefrt; static uip_ds6_defrt_t *locdefrt;
static uip_ds6_route* locroute; static uip_ds6_route_t *locroute;
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
uip_ds6_init(void) { uip_ds6_init(void)
{
PRINTF("Init of IPv6 data structures\n"); PRINTF("Init of IPv6 data structures\n");
PRINTF("%u neighbors\n%u default routers\n%u prefixes\n%u routes\n%u unicast addresses\n%u multicast addresses\n%u anycast addresses\n", UIP_DS6_NBR_NB, UIP_DS6_DEFRT_NB, UIP_DS6_PREFIX_NB, UIP_DS6_ROUTE_NB, UIP_DS6_ADDR_NB, UIP_DS6_MADDR_NB, UIP_DS6_AADDR_NB); PRINTF
for(locnbr = uip_ds6_nbr_cache; locnbr < uip_ds6_nbr_cache + UIP_DS6_NBR_NB; locnbr++) { ("%u neighbors\n%u default routers\n%u prefixes\n%u routes\n%u unicast addresses\n%u multicast addresses\n%u anycast addresses\n",
UIP_DS6_NBR_NB, UIP_DS6_DEFRT_NB, UIP_DS6_PREFIX_NB, UIP_DS6_ROUTE_NB,
UIP_DS6_ADDR_NB, UIP_DS6_MADDR_NB, UIP_DS6_AADDR_NB);
for(locnbr = uip_ds6_nbr_cache; locnbr < uip_ds6_nbr_cache + UIP_DS6_NBR_NB;
locnbr++) {
locnbr->isused = 0; locnbr->isused = 0;
} }
for(locdefrt = uip_ds6_defrt_list; locdefrt < uip_ds6_defrt_list + UIP_DS6_DEFRT_NB; locdefrt++) { for(locdefrt = uip_ds6_defrt_list;
locdefrt < uip_ds6_defrt_list + UIP_DS6_DEFRT_NB; locdefrt++) {
locdefrt->isused = 0; locdefrt->isused = 0;
} }
for(locprefix = uip_ds6_prefix_list; locprefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; locprefix++) { for(locprefix = uip_ds6_prefix_list;
locprefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; locprefix++) {
locprefix->isused = 0; locprefix->isused = 0;
} }
for(locaddr = uip_ds6_if.addr_list; locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) { for(locaddr = uip_ds6_if.addr_list;
locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
locaddr->isused = 0; locaddr->isused = 0;
} }
for(locmaddr = uip_ds6_if.maddr_list; locmaddr < uip_ds6_if.maddr_list + UIP_DS6_MADDR_NB; locmaddr++) { for(locmaddr = uip_ds6_if.maddr_list;
locmaddr < uip_ds6_if.maddr_list + UIP_DS6_MADDR_NB; locmaddr++) {
locmaddr->isused = 0; locmaddr->isused = 0;
} }
for(locaaddr = uip_ds6_if.aaddr_list; locaaddr < uip_ds6_if.aaddr_list + UIP_DS6_AADDR_NB; locaaddr++) { for(locaaddr = uip_ds6_if.aaddr_list;
locaaddr < uip_ds6_if.aaddr_list + UIP_DS6_AADDR_NB; locaaddr++) {
locaaddr->isused = 0; locaaddr->isused = 0;
} }
for(locroute = uip_ds6_routing_table; locroute < uip_ds6_routing_table + UIP_DS6_ROUTE_NB; locroute++) { for(locroute = uip_ds6_routing_table;
locroute < uip_ds6_routing_table + UIP_DS6_ROUTE_NB; locroute++) {
locroute->isused = 0; locroute->isused = 0;
} }
@ -145,7 +158,9 @@ uip_ds6_init(void) {
stimer_set(&uip_ds6_timer_ra, 2); /* wait to have a link local IP address */ stimer_set(&uip_ds6_timer_ra, 2); /* wait to have a link local IP address */
#endif /* UIP_ND6_SEND_RA */ #endif /* UIP_ND6_SEND_RA */
#else /* UIP_CONF_ROUTER */ #else /* UIP_CONF_ROUTER */
etimer_set(&uip_ds6_timer_rs, random_rand()%(UIP_ND6_MAX_RTR_SOLICITATION_DELAY * CLOCK_SECOND)); etimer_set(&uip_ds6_timer_rs,
random_rand() % (UIP_ND6_MAX_RTR_SOLICITATION_DELAY *
CLOCK_SECOND));
#endif /* UIP_CONF_ROUTER */ #endif /* UIP_CONF_ROUTER */
etimer_set(&uip_ds6_timer_periodic, UIP_DS6_PERIOD); etimer_set(&uip_ds6_timer_periodic, UIP_DS6_PERIOD);
@ -155,20 +170,25 @@ uip_ds6_init(void) {
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
uip_ds6_periodic(void) { uip_ds6_periodic(void)
{
/* Periodic processing on unicast addresses */ /* Periodic processing on unicast addresses */
for(locaddr = uip_ds6_if.addr_list; locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) { for(locaddr = uip_ds6_if.addr_list;
locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
if(locaddr->isused) { if(locaddr->isused) {
if((!locaddr->isinfinite) && (stimer_expired(&locaddr->vlifetime))) { if((!locaddr->isinfinite) && (stimer_expired(&locaddr->vlifetime))) {
uip_ds6_addr_rm(locaddr); uip_ds6_addr_rm(locaddr);
} else if ((locaddr->state == ADDR_TENTATIVE) && (locaddr->dadnscount <= uip_ds6_if.maxdadns) && (timer_expired(&locaddr->dadtimer))) { } else if((locaddr->state == ADDR_TENTATIVE)
&& (locaddr->dadnscount <= uip_ds6_if.maxdadns)
&& (timer_expired(&locaddr->dadtimer))) {
uip_ds6_dad(locaddr); uip_ds6_dad(locaddr);
} }
} }
} }
/* Periodic processing on default routers */ /* Periodic processing on default routers */
for(locdefrt = uip_ds6_defrt_list; locdefrt < uip_ds6_defrt_list + UIP_DS6_DEFRT_NB; locdefrt++) { for(locdefrt = uip_ds6_defrt_list;
locdefrt < uip_ds6_defrt_list + UIP_DS6_DEFRT_NB; locdefrt++) {
if((locdefrt->isused) && (stimer_expired(&(locdefrt->lifetime)))) { if((locdefrt->isused) && (stimer_expired(&(locdefrt->lifetime)))) {
uip_ds6_defrt_rm(locdefrt); uip_ds6_defrt_rm(locdefrt);
} }
@ -176,26 +196,26 @@ uip_ds6_periodic(void) {
#if !UIP_CONF_ROUTER #if !UIP_CONF_ROUTER
/* Periodic processing on prefixes */ /* Periodic processing on prefixes */
for(locprefix = uip_ds6_prefix_list; locprefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; locprefix++) { for(locprefix = uip_ds6_prefix_list;
if((locprefix->isused) && locprefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; locprefix++) {
(!locprefix->isinfinite) && if((locprefix->isused) && (!locprefix->isinfinite)
(stimer_expired(&(locprefix->vlifetime)))) { && (stimer_expired(&(locprefix->vlifetime)))) {
uip_ds6_prefix_rm(locprefix); uip_ds6_prefix_rm(locprefix);
} }
} }
#endif /* !UIP_CONF_ROUTER */ #endif /* !UIP_CONF_ROUTER */
/* Periodic processing on neighbors */ /* Periodic processing on neighbors */
for(locnbr = uip_ds6_nbr_cache; locnbr < uip_ds6_nbr_cache + UIP_DS6_NBR_NB; locnbr++) { for(locnbr = uip_ds6_nbr_cache; locnbr < uip_ds6_nbr_cache + UIP_DS6_NBR_NB;
locnbr++) {
if(locnbr->isused) { if(locnbr->isused) {
switch (locnbr->state) { switch (locnbr->state) {
case NBR_INCOMPLETE: case NBR_INCOMPLETE:
if(locnbr->nscount >= UIP_ND6_MAX_MULTICAST_SOLICIT) { if(locnbr->nscount >= UIP_ND6_MAX_MULTICAST_SOLICIT) {
uip_ds6_nbr_rm(locnbr); uip_ds6_nbr_rm(locnbr);
} } else if(stimer_expired(&(locnbr->sendns))) {
else if(stimer_expired(&(locnbr->sendns))) {
locnbr->nscount++; locnbr->nscount++;
PRINTF("NBR_INCOMPLETE: NS %u\n",locnbr->nscount); PRINTF("NBR_INCOMPLETE: NS %u\n", locnbr->nscount);
uip_nd6_ns_output(NULL, NULL, &locnbr->ipaddr); uip_nd6_ns_output(NULL, NULL, &locnbr->ipaddr);
stimer_set(&(locnbr->sendns), uip_ds6_if.retrans_timer / 1000); stimer_set(&(locnbr->sendns), uip_ds6_if.retrans_timer / 1000);
} }
@ -214,8 +234,7 @@ uip_ds6_periodic(void) {
locnbr->nscount = 1; locnbr->nscount = 1;
PRINTF("DELAY: moving to PROBE + NS %u\n", locnbr->nscount); PRINTF("DELAY: moving to PROBE + NS %u\n", locnbr->nscount);
uip_nd6_ns_output(NULL, &locnbr->ipaddr, &locnbr->ipaddr); uip_nd6_ns_output(NULL, &locnbr->ipaddr, &locnbr->ipaddr);
stimer_set(&(locnbr->sendns), stimer_set(&(locnbr->sendns), uip_ds6_if.retrans_timer / 1000);
uip_ds6_if.retrans_timer / 1000);
} }
break; break;
case NBR_PROBE: case NBR_PROBE:
@ -225,9 +244,9 @@ uip_ds6_periodic(void) {
uip_ds6_defrt_rm(locdefrt); uip_ds6_defrt_rm(locdefrt);
} }
uip_ds6_nbr_rm(locnbr); uip_ds6_nbr_rm(locnbr);
} else if(stimer_expired(&(locnbr->sendns))){ } else if(stimer_expired(&(locnbr->sendns))) {
locnbr->nscount++; locnbr->nscount++;
PRINTF("PROBE: NS %u\n",locnbr->nscount); PRINTF("PROBE: NS %u\n", locnbr->nscount);
uip_nd6_ns_output(NULL, &locnbr->ipaddr, &locnbr->ipaddr); uip_nd6_ns_output(NULL, &locnbr->ipaddr, &locnbr->ipaddr);
stimer_set(&(locnbr->sendns), uip_ds6_if.retrans_timer / 1000); stimer_set(&(locnbr->sendns), uip_ds6_if.retrans_timer / 1000);
} }
@ -249,11 +268,19 @@ uip_ds6_periodic(void) {
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
uint8_t uip_ds6_list_loop(uip_ds6_element* list, uint8_t size, uint16_t elementsize, uip_ipaddr_t* ipaddr, uint8_t ipaddrlen, uip_ds6_element** out_element) { uint8_t
uip_ds6_element *element; uip_ds6_list_loop(uip_ds6_element_t * list, uint8_t size,
uint16_t elementsize, uip_ipaddr_t * ipaddr,
uint8_t ipaddrlen, uip_ds6_element_t ** out_element)
{
uip_ds6_element_t *element;
*out_element = NULL; *out_element = NULL;
for(element = list; element < (uip_ds6_element*)((uint8_t*)list + (size * elementsize)); element = (uip_ds6_element*)((uint8_t*)element + elementsize)) { for(element = list;
element <
(uip_ds6_element_t *) ((uint8_t *) list + (size * elementsize));
element = (uip_ds6_element_t *) ((uint8_t *) element + elementsize)) {
if(element->isused) { if(element->isused) {
if(uip_ipaddr_prefixcmp(&(element->ipaddr), ipaddr, ipaddrlen)) { if(uip_ipaddr_prefixcmp(&(element->ipaddr), ipaddr, ipaddrlen)) {
*out_element = element; *out_element = element;
@ -272,12 +299,17 @@ uint8_t uip_ds6_list_loop(uip_ds6_element* list, uint8_t size, uint16_t elements
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
uip_ds6_nbr* uip_ds6_nbr_t *
uip_ds6_nbr_add(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr, uint8_t isrouter, uint8_t state) { uip_ds6_nbr_add(uip_ipaddr_t * ipaddr, uip_lladdr_t * lladdr,
if(uip_ds6_list_loop((uip_ds6_element*)uip_ds6_nbr_cache, UIP_DS6_NBR_NB, sizeof(uip_ds6_nbr),ipaddr, 128, (uip_ds6_element**)&locnbr) == FREESPACE) { uint8_t isrouter, uint8_t state)
{
if(uip_ds6_list_loop
((uip_ds6_element_t *) uip_ds6_nbr_cache, UIP_DS6_NBR_NB,
sizeof(uip_ds6_nbr_t), ipaddr, 128,
(uip_ds6_element_t **) & locnbr) == FREESPACE) {
locnbr->isused = 1; locnbr->isused = 1;
uip_ipaddr_copy(&(locnbr->ipaddr), ipaddr); uip_ipaddr_copy(&(locnbr->ipaddr), ipaddr);
if(lladdr != NULL){ if(lladdr != NULL) {
memcpy(&(locnbr->lladdr), lladdr, UIP_LLADDR_LEN); memcpy(&(locnbr->lladdr), lladdr, UIP_LLADDR_LEN);
} else { } else {
memset(&(locnbr->lladdr), 0, UIP_LLADDR_LEN); memset(&(locnbr->lladdr), 0, UIP_LLADDR_LEN);
@ -285,8 +317,8 @@ uip_ds6_nbr_add(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr, uint8_t isrouter, ui
locnbr->isrouter = isrouter; locnbr->isrouter = isrouter;
locnbr->state = state; locnbr->state = state;
/* timers are set separately, for now we put them in expired state */ /* timers are set separately, for now we put them in expired state */
stimer_set(&(locnbr->reachable),0); stimer_set(&(locnbr->reachable), 0);
stimer_set(&(locnbr->sendns),0); stimer_set(&(locnbr->sendns), 0);
locnbr->nscount = 0; locnbr->nscount = 0;
PRINTF("Adding neighbor with ip addr"); PRINTF("Adding neighbor with ip addr");
PRINT6ADDR(ipaddr); PRINT6ADDR(ipaddr);
@ -300,7 +332,8 @@ uip_ds6_nbr_add(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr, uint8_t isrouter, ui
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
uip_ds6_nbr_rm(uip_ds6_nbr* nbr) { uip_ds6_nbr_rm(uip_ds6_nbr_t * nbr)
{
if(nbr != NULL) { if(nbr != NULL) {
nbr->isused = 0; nbr->isused = 0;
} }
@ -308,18 +341,26 @@ uip_ds6_nbr_rm(uip_ds6_nbr* nbr) {
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
uip_ds6_nbr* uip_ds6_nbr_t *
uip_ds6_nbr_lookup(uip_ipaddr_t *ipaddr) { uip_ds6_nbr_lookup(uip_ipaddr_t * ipaddr)
if(uip_ds6_list_loop((uip_ds6_element*)uip_ds6_nbr_cache, UIP_DS6_NBR_NB, sizeof(uip_ds6_nbr) ,ipaddr, 128, (uip_ds6_element**)&locnbr) == FOUND) { {
if(uip_ds6_list_loop
((uip_ds6_element_t *) uip_ds6_nbr_cache, UIP_DS6_NBR_NB,
sizeof(uip_ds6_nbr_t), ipaddr, 128,
(uip_ds6_element_t **) & locnbr) == FOUND) {
return locnbr; return locnbr;
} }
return NULL; return NULL;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
uip_ds6_defrt* uip_ds6_defrt_t *
uip_ds6_defrt_add(uip_ipaddr_t *ipaddr, unsigned long interval) { uip_ds6_defrt_add(uip_ipaddr_t * ipaddr, unsigned long interval)
if(uip_ds6_list_loop((uip_ds6_element*)uip_ds6_defrt_list, UIP_DS6_DEFRT_NB, sizeof(uip_ds6_defrt),ipaddr, 128, (uip_ds6_element**)&locdefrt) == FREESPACE) { {
if(uip_ds6_list_loop
((uip_ds6_element_t *) uip_ds6_defrt_list, UIP_DS6_DEFRT_NB,
sizeof(uip_ds6_defrt_t), ipaddr, 128,
(uip_ds6_element_t **) & locdefrt) == FREESPACE) {
locdefrt->isused = 1; locdefrt->isused = 1;
uip_ipaddr_copy(&(locdefrt->ipaddr), ipaddr); uip_ipaddr_copy(&(locdefrt->ipaddr), ipaddr);
stimer_set(&(locdefrt->lifetime), interval); stimer_set(&(locdefrt->lifetime), interval);
@ -334,7 +375,8 @@ uip_ds6_defrt_add(uip_ipaddr_t *ipaddr, unsigned long interval) {
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
uip_ds6_defrt_rm(uip_ds6_defrt* defrt) { uip_ds6_defrt_rm(uip_ds6_defrt_t * defrt)
{
if(defrt != NULL) { if(defrt != NULL) {
defrt->isused = 0; defrt->isused = 0;
} }
@ -342,21 +384,27 @@ uip_ds6_defrt_rm(uip_ds6_defrt* defrt) {
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
uip_ds6_defrt* uip_ds6_defrt_t *
uip_ds6_defrt_lookup(uip_ipaddr_t *ipaddr) { uip_ds6_defrt_lookup(uip_ipaddr_t * ipaddr)
if(uip_ds6_list_loop((uip_ds6_element*)uip_ds6_defrt_list, UIP_DS6_DEFRT_NB, sizeof(uip_ds6_defrt),ipaddr, 128, (uip_ds6_element**)&locdefrt) == FOUND) { {
if(uip_ds6_list_loop
((uip_ds6_element_t *) uip_ds6_defrt_list, UIP_DS6_DEFRT_NB,
sizeof(uip_ds6_defrt_t), ipaddr, 128,
(uip_ds6_element_t **) & locdefrt) == FOUND) {
return locdefrt; return locdefrt;
} }
return NULL; return NULL;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
uip_ipaddr_t* uip_ipaddr_t *
uip_ds6_defrt_choose() { uip_ds6_defrt_choose()
uip_ds6_nbr *bestnbr; {
uip_ds6_nbr_t *bestnbr;
locipaddr = NULL; locipaddr = NULL;
for(locdefrt = uip_ds6_defrt_list; locdefrt < uip_ds6_defrt_list + UIP_DS6_DEFRT_NB; locdefrt++) { for(locdefrt = uip_ds6_defrt_list;
locdefrt < uip_ds6_defrt_list + UIP_DS6_DEFRT_NB; locdefrt++) {
if(locdefrt->isused) { if(locdefrt->isused) {
PRINTF("Defrt, IP address "); PRINTF("Defrt, IP address ");
PRINT6ADDR(&locdefrt->ipaddr); PRINT6ADDR(&locdefrt->ipaddr);
@ -380,9 +428,15 @@ uip_ds6_defrt_choose() {
#if UIP_CONF_ROUTER #if UIP_CONF_ROUTER
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
uip_ds6_prefix* uip_ds6_prefix_t *
uip_ds6_prefix_add(uip_ipaddr_t *ipaddr, uint8_t ipaddrlen, uint8_t advertise, uint8_t flags, unsigned long vtime, unsigned long ptime) { uip_ds6_prefix_add(uip_ipaddr_t * ipaddr, uint8_t ipaddrlen,
if(uip_ds6_list_loop((uip_ds6_element*)uip_ds6_prefix_list, UIP_DS6_PREFIX_NB, sizeof(uip_ds6_prefix), ipaddr, ipaddrlen, (uip_ds6_element**)&locprefix) == FREESPACE) { uint8_t advertise, uint8_t flags, unsigned long vtime,
unsigned long ptime)
{
if(uip_ds6_list_loop
((uip_ds6_element_t *) uip_ds6_prefix_list, UIP_DS6_PREFIX_NB,
sizeof(uip_ds6_prefix_t), ipaddr, ipaddrlen,
(uip_ds6_element_t **) & locprefix) == FREESPACE) {
locprefix->isused = 1; locprefix->isused = 1;
uip_ipaddr_copy(&(locprefix->ipaddr), ipaddr); uip_ipaddr_copy(&(locprefix->ipaddr), ipaddr);
locprefix->length = ipaddrlen; locprefix->length = ipaddrlen;
@ -392,7 +446,9 @@ uip_ds6_prefix_add(uip_ipaddr_t *ipaddr, uint8_t ipaddrlen, uint8_t advertise, u
locprefix->plifetime = ptime; locprefix->plifetime = ptime;
PRINTF("Adding prefix "); PRINTF("Adding prefix ");
PRINT6ADDR(&locprefix->ipaddr); PRINT6ADDR(&locprefix->ipaddr);
PRINTF("length %u, flags %x, Valid lifetime %lx, Preffered lifetime %lx\n", ipaddrlen, flags, vtime, ptime); PRINTF
("length %u, flags %x, Valid lifetime %lx, Preffered lifetime %lx\n",
ipaddrlen, flags, vtime, ptime);
return locprefix; return locprefix;
} else { } else {
PRINTF("No more space in Prefix list\n"); PRINTF("No more space in Prefix list\n");
@ -402,14 +458,19 @@ uip_ds6_prefix_add(uip_ipaddr_t *ipaddr, uint8_t ipaddrlen, uint8_t advertise, u
#else /* UIP_CONF_ROUTER */ #else /* UIP_CONF_ROUTER */
uip_ds6_prefix* uip_ds6_prefix_t *
uip_ds6_prefix_add(uip_ipaddr_t *ipaddr, uint8_t ipaddrlen, unsigned long interval){ uip_ds6_prefix_add(uip_ipaddr_t * ipaddr, uint8_t ipaddrlen,
if(uip_ds6_list_loop((uip_ds6_element*)uip_ds6_prefix_list, UIP_DS6_PREFIX_NB, sizeof(uip_ds6_prefix), ipaddr, ipaddrlen, (uip_ds6_element**)&locprefix) == FREESPACE) { unsigned long interval)
{
if(uip_ds6_list_loop
((uip_ds6_element_t *) uip_ds6_prefix_list, UIP_DS6_PREFIX_NB,
sizeof(uip_ds6_prefix_t), ipaddr, ipaddrlen,
(uip_ds6_element_t **) & locprefix) == FREESPACE) {
locprefix->isused = 1; locprefix->isused = 1;
uip_ipaddr_copy(&(locprefix->ipaddr), ipaddr); uip_ipaddr_copy(&(locprefix->ipaddr), ipaddr);
locprefix->length = ipaddrlen; locprefix->length = ipaddrlen;
if(interval != 0){ if(interval != 0) {
stimer_set(&(locprefix->vlifetime),interval); stimer_set(&(locprefix->vlifetime), interval);
locprefix->isinfinite = 0; locprefix->isinfinite = 0;
} else { } else {
locprefix->isinfinite = 1; locprefix->isinfinite = 1;
@ -425,7 +486,8 @@ uip_ds6_prefix_add(uip_ipaddr_t *ipaddr, uint8_t ipaddrlen, unsigned long interv
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
uip_ds6_prefix_rm( uip_ds6_prefix *prefix) { uip_ds6_prefix_rm(uip_ds6_prefix_t * prefix)
{
if(prefix != NULL) { if(prefix != NULL) {
prefix->isused = 0; prefix->isused = 0;
} }
@ -433,19 +495,28 @@ uip_ds6_prefix_rm( uip_ds6_prefix *prefix) {
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
uip_ds6_prefix* uip_ds6_prefix_t *
uip_ds6_prefix_lookup(uip_ipaddr_t *ipaddr, uint8_t ipaddrlen) { uip_ds6_prefix_lookup(uip_ipaddr_t * ipaddr, uint8_t ipaddrlen)
if(uip_ds6_list_loop((uip_ds6_element*)uip_ds6_prefix_list, UIP_DS6_PREFIX_NB, sizeof(uip_ds6_prefix), ipaddr, ipaddrlen, (uip_ds6_element**)&locprefix) == FOUND) { {
if(uip_ds6_list_loop
((uip_ds6_element_t *) uip_ds6_prefix_list, UIP_DS6_PREFIX_NB,
sizeof(uip_ds6_prefix_t), ipaddr, ipaddrlen,
(uip_ds6_element_t **) & locprefix) == FOUND) {
return locprefix; return locprefix;
} }
return NULL; return NULL;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
uint8_t uip_ds6_is_addr_onlink(uip_ipaddr_t *ipaddr) { uint8_t
for(locprefix = uip_ds6_prefix_list; locprefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; locprefix++) { uip_ds6_is_addr_onlink(uip_ipaddr_t * ipaddr)
if((locprefix->isused) && {
(uip_ipaddr_prefixcmp(&locprefix->ipaddr, ipaddr, locprefix->length)) ){ for(locprefix = uip_ds6_prefix_list;
locprefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; locprefix++) {
if((locprefix->isused)
&&
(uip_ipaddr_prefixcmp(&locprefix->ipaddr, ipaddr, locprefix->length)))
{
return 1; return 1;
} }
} }
@ -453,9 +524,13 @@ uint8_t uip_ds6_is_addr_onlink(uip_ipaddr_t *ipaddr) {
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
uip_ds6_addr* uip_ds6_addr_t *
uip_ds6_addr_add(uip_ipaddr_t *ipaddr, unsigned long vlifetime, uint8_t type) { uip_ds6_addr_add(uip_ipaddr_t * ipaddr, unsigned long vlifetime, uint8_t type)
if(uip_ds6_list_loop((uip_ds6_element*)uip_ds6_if.addr_list, UIP_DS6_ADDR_NB, sizeof(uip_ds6_addr),ipaddr, 128, (uip_ds6_element**)&locaddr) == FREESPACE) { {
if(uip_ds6_list_loop
((uip_ds6_element_t *) uip_ds6_if.addr_list, UIP_DS6_ADDR_NB,
sizeof(uip_ds6_addr_t), ipaddr, 128,
(uip_ds6_element_t **) & locaddr) == FREESPACE) {
locaddr->isused = 1; locaddr->isused = 1;
uip_ipaddr_copy(&locaddr->ipaddr, ipaddr); uip_ipaddr_copy(&locaddr->ipaddr, ipaddr);
locaddr->state = ADDR_TENTATIVE; locaddr->state = ADDR_TENTATIVE;
@ -466,7 +541,9 @@ uip_ds6_addr_add(uip_ipaddr_t *ipaddr, unsigned long vlifetime, uint8_t type) {
locaddr->isinfinite = 0; locaddr->isinfinite = 0;
stimer_set(&(locaddr->vlifetime), vlifetime); stimer_set(&(locaddr->vlifetime), vlifetime);
} }
timer_set(&locaddr->dadtimer, random_rand()%(UIP_ND6_MAX_RTR_SOLICITATION_DELAY * CLOCK_SECOND)); timer_set(&locaddr->dadtimer,
random_rand() % (UIP_ND6_MAX_RTR_SOLICITATION_DELAY *
CLOCK_SECOND));
locaddr->dadnscount = 0; locaddr->dadnscount = 0;
uip_create_solicited_node(ipaddr, &loc_fipaddr); uip_create_solicited_node(ipaddr, &loc_fipaddr);
uip_ds6_maddr_add(&loc_fipaddr); uip_ds6_maddr_add(&loc_fipaddr);
@ -477,7 +554,8 @@ uip_ds6_addr_add(uip_ipaddr_t *ipaddr, unsigned long vlifetime, uint8_t type) {
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
uip_ds6_addr_rm(uip_ds6_addr *addr) { uip_ds6_addr_rm(uip_ds6_addr_t * addr)
{
if(addr != NULL) { if(addr != NULL) {
uip_create_solicited_node(&addr->ipaddr, &loc_fipaddr); uip_create_solicited_node(&addr->ipaddr, &loc_fipaddr);
if((locmaddr = uip_ds6_maddr_lookup(&loc_fipaddr)) != NULL) { if((locmaddr = uip_ds6_maddr_lookup(&loc_fipaddr)) != NULL) {
@ -489,18 +567,26 @@ uip_ds6_addr_rm(uip_ds6_addr *addr) {
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
uip_ds6_addr* uip_ds6_addr_t *
uip_ds6_addr_lookup(uip_ipaddr_t* ipaddr) { uip_ds6_addr_lookup(uip_ipaddr_t * ipaddr)
if(uip_ds6_list_loop((uip_ds6_element*)uip_ds6_if.addr_list, UIP_DS6_ADDR_NB, sizeof(uip_ds6_addr),ipaddr, 128, (uip_ds6_element**)&locaddr) == FOUND) { {
if(uip_ds6_list_loop
((uip_ds6_element_t *) uip_ds6_if.addr_list, UIP_DS6_ADDR_NB,
sizeof(uip_ds6_addr_t), ipaddr, 128,
(uip_ds6_element_t **) & locaddr) == FOUND) {
return locaddr; return locaddr;
} }
return NULL; return NULL;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
uip_ds6_maddr* uip_ds6_maddr_t *
uip_ds6_maddr_add(uip_ipaddr_t *ipaddr) { uip_ds6_maddr_add(uip_ipaddr_t * ipaddr)
if(uip_ds6_list_loop((uip_ds6_element*)uip_ds6_if.maddr_list, UIP_DS6_MADDR_NB, sizeof(uip_ds6_maddr),ipaddr, 128, (uip_ds6_element**)&locmaddr) == FREESPACE) { {
if(uip_ds6_list_loop
((uip_ds6_element_t *) uip_ds6_if.maddr_list, UIP_DS6_MADDR_NB,
sizeof(uip_ds6_maddr_t), ipaddr, 128,
(uip_ds6_element_t **) & locmaddr) == FREESPACE) {
locmaddr->isused = 1; locmaddr->isused = 1;
uip_ipaddr_copy(&locmaddr->ipaddr, ipaddr); uip_ipaddr_copy(&locmaddr->ipaddr, ipaddr);
return locmaddr; return locmaddr;
@ -510,7 +596,8 @@ uip_ds6_maddr_add(uip_ipaddr_t *ipaddr) {
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
uip_ds6_maddr_rm(uip_ds6_maddr *maddr) { uip_ds6_maddr_rm(uip_ds6_maddr_t * maddr)
{
if(maddr != NULL) { if(maddr != NULL) {
maddr->isused = 0; maddr->isused = 0;
} }
@ -518,9 +605,13 @@ uip_ds6_maddr_rm(uip_ds6_maddr *maddr) {
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
uip_ds6_maddr* uip_ds6_maddr_t *
uip_ds6_maddr_lookup(uip_ipaddr_t* ipaddr) { uip_ds6_maddr_lookup(uip_ipaddr_t * ipaddr)
if(uip_ds6_list_loop((uip_ds6_element*)uip_ds6_if.maddr_list, UIP_DS6_MADDR_NB, sizeof(uip_ds6_maddr),ipaddr, 128, (uip_ds6_element**)&locmaddr) == FOUND) { {
if(uip_ds6_list_loop
((uip_ds6_element_t *) uip_ds6_if.maddr_list, UIP_DS6_MADDR_NB,
sizeof(uip_ds6_maddr_t), ipaddr, 128,
(uip_ds6_element_t **) & locmaddr) == FOUND) {
return locmaddr; return locmaddr;
} }
return NULL; return NULL;
@ -528,9 +619,13 @@ uip_ds6_maddr_lookup(uip_ipaddr_t* ipaddr) {
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
uip_ds6_aaddr* uip_ds6_aaddr_t *
uip_ds6_aaddr_add(uip_ipaddr_t *ipaddr) { uip_ds6_aaddr_add(uip_ipaddr_t * ipaddr)
if(uip_ds6_list_loop((uip_ds6_element*)uip_ds6_if.aaddr_list, UIP_DS6_AADDR_NB, sizeof(uip_ds6_aaddr),ipaddr, 128, (uip_ds6_element**)&locaaddr) == FREESPACE) { {
if(uip_ds6_list_loop
((uip_ds6_element_t *) uip_ds6_if.aaddr_list, UIP_DS6_AADDR_NB,
sizeof(uip_ds6_aaddr_t), ipaddr, 128,
(uip_ds6_element_t **) & locaaddr) == FREESPACE) {
locaaddr->isused = 1; locaaddr->isused = 1;
uip_ipaddr_copy(&locaaddr->ipaddr, ipaddr); uip_ipaddr_copy(&locaaddr->ipaddr, ipaddr);
return locaaddr; return locaaddr;
@ -540,7 +635,8 @@ uip_ds6_aaddr_add(uip_ipaddr_t *ipaddr) {
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
uip_ds6_aaddr_rm(uip_ds6_aaddr *aaddr) { uip_ds6_aaddr_rm(uip_ds6_aaddr_t * aaddr)
{
if(aaddr != NULL) { if(aaddr != NULL) {
aaddr->isused = 0; aaddr->isused = 0;
} }
@ -548,42 +644,75 @@ uip_ds6_aaddr_rm(uip_ds6_aaddr *aaddr) {
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
uip_ds6_aaddr* uip_ds6_aaddr_t *
uip_ds6_aaddr_lookup(uip_ipaddr_t* ipaddr) { uip_ds6_aaddr_lookup(uip_ipaddr_t * ipaddr)
if(uip_ds6_list_loop((uip_ds6_element*)uip_ds6_if.aaddr_list, UIP_DS6_AADDR_NB, sizeof(uip_ds6_aaddr),ipaddr, 128, (uip_ds6_element**)&locaaddr) == FOUND) { {
if(uip_ds6_list_loop
((uip_ds6_element_t *) uip_ds6_if.aaddr_list, UIP_DS6_AADDR_NB,
sizeof(uip_ds6_aaddr_t), ipaddr, 128,
(uip_ds6_element_t **) & locaaddr) == FOUND) {
return locaaddr; return locaaddr;
} }
return NULL; return NULL;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
uip_ipaddr_t* uip_ds6_route_t *
uip_ds6_route_lookup(uip_ipaddr_t *destipaddr) { uip_ds6_route_lookup(uip_ipaddr_t * destipaddr)
locipaddr = NULL; {
uip_ds6_route_t *locrt = NULL;
uint8_t longestmatch = 0; uint8_t longestmatch = 0;
for(locroute = uip_ds6_routing_table; locroute < uip_ds6_routing_table + UIP_DS6_ROUTE_NB; locroute++) { PRINTF("DS6: Looking up route for");
if((locroute->isused) && PRINT6ADDR(destipaddr);
(locroute->length >= longestmatch) && PRINTF("\n");
(uip_ipaddr_prefixcmp(destipaddr, &locroute->ipaddr, locroute->length))) {
for(locroute = uip_ds6_routing_table;
locroute < uip_ds6_routing_table + UIP_DS6_ROUTE_NB; locroute++) {
if((locroute->isused) && (locroute->length >= longestmatch)
&&
(uip_ipaddr_prefixcmp
(destipaddr, &locroute->ipaddr, locroute->length))) {
longestmatch = locroute->length; longestmatch = locroute->length;
locipaddr = &locroute->ipaddr; locrt = locroute;
} }
} }
return locipaddr; if(locrt != NULL) {
PRINTF("DS6: Found route:");
PRINT6ADDR(destipaddr);
PRINTF(" via ");
PRINT6ADDR(&locrt->nexthop);
PRINTF("\n");
} else {
PRINTF("DS6: No route found ...\n");
}
return locrt;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
uip_ds6_route* uip_ds6_route_t *
uip_ds6_route_add(uip_ipaddr_t *ipaddr, u8_t length, uip_ipaddr_t *nexthop, u8_t metric) { uip_ds6_route_add(uip_ipaddr_t * ipaddr, u8_t length, uip_ipaddr_t * nexthop,
u8_t metric)
{
if(uip_ds6_list_loop((uip_ds6_element*)uip_ds6_routing_table, UIP_DS6_ROUTE_NB, sizeof(uip_ds6_route), ipaddr, length, (uip_ds6_element**)&locroute) == FREESPACE) { if(uip_ds6_list_loop
((uip_ds6_element_t *) uip_ds6_routing_table, UIP_DS6_ROUTE_NB,
sizeof(uip_ds6_route_t), ipaddr, length,
(uip_ds6_element_t **) & locroute) == FREESPACE) {
locroute->isused = 1; locroute->isused = 1;
uip_ipaddr_copy(&(locroute->ipaddr), ipaddr); uip_ipaddr_copy(&(locroute->ipaddr), ipaddr);
locroute->length = length; locroute->length = length;
uip_ipaddr_copy(&(locroute->nexthop), nexthop); uip_ipaddr_copy(&(locroute->nexthop), nexthop);
locroute->metric = metric; locroute->metric = metric;
PRINTF("DS6: adding route:");
PRINT6ADDR(ipaddr);
PRINTF(" via ");
PRINT6ADDR(nexthop);
PRINTF("\n");
} }
return locroute; return locroute;
@ -591,25 +720,27 @@ uip_ds6_route_add(uip_ipaddr_t *ipaddr, u8_t length, uip_ipaddr_t *nexthop, u8_
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
uip_ds6_route_rm(uip_ds6_route* route) { uip_ds6_route_rm(uip_ds6_route_t * route)
{
route->isused = 0; route->isused = 0;
return; return;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
uip_ds6_select_src(uip_ipaddr_t *src, uip_ipaddr_t *dst) uip_ds6_select_src(uip_ipaddr_t * src, uip_ipaddr_t * dst)
{ {
uint8_t best = 0; /* number of bit in common with best match*/ uint8_t best = 0; /* number of bit in common with best match */
uint8_t n = 0; uint8_t n = 0;
uip_ds6_addr *matchaddr = uip_ds6_if.addr_list; uip_ds6_addr_t *matchaddr = uip_ds6_if.addr_list;
if(!uip_is_addr_link_local(dst) && !uip_is_addr_mcast(dst)) { if(!uip_is_addr_link_local(dst) && !uip_is_addr_mcast(dst)) {
// find longest match // find longest match
for(locaddr = uip_ds6_if.addr_list; locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) { for(locaddr = uip_ds6_if.addr_list;
if((locaddr->isused) && (locaddr->state == ADDR_PREFERRED)){ locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
if((locaddr->isused) && (locaddr->state == ADDR_PREFERRED)) {
n = get_match_length(dst, &(locaddr->ipaddr)); n = get_match_length(dst, &(locaddr->ipaddr));
if(n >= best){ if(n >= best) {
best = n; best = n;
matchaddr = locaddr; matchaddr = locaddr;
} }
@ -617,8 +748,10 @@ uip_ds6_select_src(uip_ipaddr_t *src, uip_ipaddr_t *dst)
} }
} else { } else {
// use link local // use link local
for(locaddr = uip_ds6_if.addr_list; locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) { for(locaddr = uip_ds6_if.addr_list;
if((locaddr->isused) && (locaddr->state == ADDR_PREFERRED) && (uip_is_addr_link_local(&locaddr->ipaddr))) { locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
if((locaddr->isused) && (locaddr->state == ADDR_PREFERRED)
&& (uip_is_addr_link_local(&locaddr->ipaddr))) {
matchaddr = locaddr; matchaddr = locaddr;
break; break;
} }
@ -630,7 +763,9 @@ uip_ds6_select_src(uip_ipaddr_t *src, uip_ipaddr_t *dst)
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void uip_ds6_set_addr_iid(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr) { void
uip_ds6_set_addr_iid(uip_ipaddr_t * ipaddr, uip_lladdr_t * lladdr)
{
/* We consider only links with IEEE EUI-64 identifier or /* We consider only links with IEEE EUI-64 identifier or
* IEEE 48-bit MAC addresses */ * IEEE 48-bit MAC addresses */
#if (UIP_LLADDR_LEN == 8) #if (UIP_LLADDR_LEN == 8)
@ -640,33 +775,30 @@ void uip_ds6_set_addr_iid(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr) {
memcpy(ipaddr->u8 + 8, lladdr, 3); memcpy(ipaddr->u8 + 8, lladdr, 3);
ipaddr->u8[11] = 0xff; ipaddr->u8[11] = 0xff;
ipaddr->u8[12] = 0xfe; ipaddr->u8[12] = 0xfe;
memcpy(ipaddr->u8 + 13, (uint8_t*)lladdr + 3, 3); memcpy(ipaddr->u8 + 13, (uint8_t *) lladdr + 3, 3);
ipaddr->u8[8] ^= 0x02; ipaddr->u8[8] ^= 0x02;
#else #else
PRINTF("CAN NOT BUIL INTERFACE IDENTIFIER"); #error uip-ds6.c cannot build interface address when UIP_LLADDR_LEN is not 6 or 8
PRINTF("THE STACK IS GOING TO SHUT DOWN");
PRINTF("THE HOST WILL BE UNREACHABLE");
exit(-1);
#endif #endif
return;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
uint8_t uint8_t
get_match_length(uip_ipaddr_t *src, uip_ipaddr_t *dst) { get_match_length(uip_ipaddr_t * src, uip_ipaddr_t * dst)
{
uint8_t j, k, x_or; uint8_t j, k, x_or;
uint8_t len = 0; uint8_t len = 0;
for(j = 0; j < 16; j ++) {
for(j = 0; j < 16; j++) {
if(src->u8[j] == dst->u8[j]) { if(src->u8[j] == dst->u8[j]) {
len += 8; len += 8;
} else { } else {
x_or = src->u8[j] ^ dst->u8[j]; x_or = src->u8[j] ^ dst->u8[j];
for(k = 0; k < 8; k ++) { for(k = 0; k < 8; k++) {
if((x_or & 0x80) == 0){ if((x_or & 0x80) == 0) {
len ++; len++;
x_or <<= 1; x_or <<= 1;
} } else {
else {
break; break;
} }
} }
@ -678,12 +810,14 @@ get_match_length(uip_ipaddr_t *src, uip_ipaddr_t *dst) {
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
uip_ds6_dad(uip_ds6_addr* addr) { uip_ds6_dad(uip_ds6_addr_t * addr)
{
/* send maxdadns NS for DAD */ /* send maxdadns NS for DAD */
if(addr->dadnscount < uip_ds6_if.maxdadns) { if(addr->dadnscount < uip_ds6_if.maxdadns) {
uip_nd6_ns_output(NULL, NULL, &addr->ipaddr); uip_nd6_ns_output(NULL, NULL, &addr->ipaddr);
addr->dadnscount++; addr->dadnscount++;
timer_set(&addr->dadtimer, uip_ds6_if.retrans_timer / 1000 * CLOCK_SECOND); timer_set(&addr->dadtimer,
uip_ds6_if.retrans_timer / 1000 * CLOCK_SECOND);
return; return;
} }
/* /*
@ -699,21 +833,27 @@ uip_ds6_dad(uip_ds6_addr* addr) {
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void /*
uip_ds6_dad_failed(uip_ds6_addr *addr) { * Calling code must handle when this returns 0 (e.g. link local
* address can not be used).
*/
int
uip_ds6_dad_failed(uip_ds6_addr_t * addr)
{
if(uip_is_addr_link_local(&addr->ipaddr)) { if(uip_is_addr_link_local(&addr->ipaddr)) {
PRINTF("Contiki shutdown, DAD for link local address failed\n"); PRINTF("Contiki shutdown, DAD for link local address failed\n");
exit(-1); return 0;
} }
uip_ds6_addr_rm(addr); uip_ds6_addr_rm(addr);
return; return 1;
} }
#if UIP_CONF_ROUTER #if UIP_CONF_ROUTER
#if UIP_ND6_SEND_RA #if UIP_ND6_SEND_RA
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
uip_ds6_send_ra_sollicited(void) { uip_ds6_send_ra_sollicited(void)
{
/* We have a pb here: RA timer max possible value is 1800s, /* We have a pb here: RA timer max possible value is 1800s,
* hence we have to use stimers. However, when receiving a RS, we * hence we have to use stimers. However, when receiving a RS, we
* should delay the reply by a random value between 0 and 500ms timers. * should delay the reply by a random value between 0 and 500ms timers.
@ -723,8 +863,8 @@ uip_ds6_send_ra_sollicited(void) {
rand_time = 0; rand_time = 0;
PRINTF("Solicited RA, random time %u\n", rand_time); PRINTF("Solicited RA, random time %u\n", rand_time);
if (stimer_remaining(&uip_ds6_timer_ra) > rand_time) { if(stimer_remaining(&uip_ds6_timer_ra) > rand_time) {
if (stimer_elapsed(&uip_ds6_timer_ra) < UIP_ND6_MIN_DELAY_BETWEEN_RAS) { if(stimer_elapsed(&uip_ds6_timer_ra) < UIP_ND6_MIN_DELAY_BETWEEN_RAS) {
/* Ensure that the RAs are rate limited */ /* Ensure that the RAs are rate limited */
/* stimer_set(&uip_ds6_timer_ra, rand_time + /* stimer_set(&uip_ds6_timer_ra, rand_time +
UIP_ND6_MIN_DELAY_BETWEEN_RAS - UIP_ND6_MIN_DELAY_BETWEEN_RAS -
@ -737,19 +877,20 @@ uip_ds6_send_ra_sollicited(void) {
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
uip_ds6_send_ra_periodic(void) { uip_ds6_send_ra_periodic(void)
if(racount > 0){ {
/* send previously scheduled RA*/ if(racount > 0) {
/* send previously scheduled RA */
uip_nd6_ra_output(NULL); uip_nd6_ra_output(NULL);
PRINTF("Sending periodic RA\n"); PRINTF("Sending periodic RA\n");
} }
rand_time = UIP_ND6_MIN_RA_INTERVAL + random_rand() % rand_time = UIP_ND6_MIN_RA_INTERVAL + random_rand() %
(uint16_t)(UIP_ND6_MAX_RA_INTERVAL - UIP_ND6_MIN_RA_INTERVAL); (uint16_t) (UIP_ND6_MAX_RA_INTERVAL - UIP_ND6_MIN_RA_INTERVAL);
PRINTF("Random time 1 = %u\n", rand_time); PRINTF("Random time 1 = %u\n", rand_time);
if(racount < UIP_ND6_MAX_INITIAL_RAS){ if(racount < UIP_ND6_MAX_INITIAL_RAS) {
if (rand_time > UIP_ND6_MAX_INITIAL_RA_INTERVAL){ if(rand_time > UIP_ND6_MAX_INITIAL_RA_INTERVAL) {
rand_time = UIP_ND6_MAX_INITIAL_RA_INTERVAL; rand_time = UIP_ND6_MAX_INITIAL_RA_INTERVAL;
PRINTF("Random time 2 = %u\n", rand_time); PRINTF("Random time 2 = %u\n", rand_time);
} }
@ -763,14 +904,18 @@ uip_ds6_send_ra_periodic(void) {
#else /* UIP_CONF_ROUTER */ #else /* UIP_CONF_ROUTER */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
uip_ds6_send_rs(void) { uip_ds6_send_rs(void)
if((uip_ds6_defrt_choose() == NULL) && (rscount < UIP_ND6_MAX_RTR_SOLICITATIONS)){ {
if((uip_ds6_defrt_choose() == NULL)
&& (rscount < UIP_ND6_MAX_RTR_SOLICITATIONS)) {
PRINTF("Sending RS %u\n", rscount); PRINTF("Sending RS %u\n", rscount);
uip_nd6_rs_output(); uip_nd6_rs_output();
rscount++; rscount++;
etimer_set(&uip_ds6_timer_rs, UIP_ND6_RTR_SOLICITATION_INTERVAL * CLOCK_SECOND); etimer_set(&uip_ds6_timer_rs,
UIP_ND6_RTR_SOLICITATION_INTERVAL * CLOCK_SECOND);
} else { } else {
PRINTF("Router found ? (boolean): %u\n", (uip_ds6_defrt_choose() != NULL)); PRINTF("Router found ? (boolean): %u\n",
(uip_ds6_defrt_choose() != NULL));
etimer_stop(&uip_ds6_timer_rs); etimer_stop(&uip_ds6_timer_rs);
} }
return; return;
@ -781,9 +926,11 @@ uip_ds6_send_rs(void) {
uint32_t uint32_t
uip_ds6_compute_reachable_time(void) uip_ds6_compute_reachable_time(void)
{ {
return (uint32_t)(UIP_ND6_MIN_RANDOM_FACTOR(uip_ds6_if.base_reachable_time)) + return (uint32_t) (UIP_ND6_MIN_RANDOM_FACTOR
((uint16_t)(random_rand() << 8) + (uint16_t)random_rand()) % (uip_ds6_if.base_reachable_time)) +
(uint32_t)(UIP_ND6_MAX_RANDOM_FACTOR(uip_ds6_if.base_reachable_time) - ((uint16_t) (random_rand() << 8) +
(uint16_t) random_rand()) %
(uint32_t) (UIP_ND6_MAX_RANDOM_FACTOR(uip_ds6_if.base_reachable_time) -
UIP_ND6_MIN_RANDOM_FACTOR(uip_ds6_if.base_reachable_time)); UIP_ND6_MIN_RANDOM_FACTOR(uip_ds6_if.base_reachable_time));
} }

View file

@ -165,15 +165,15 @@ typedef struct uip_ds6_nbr {
#if UIP_CONF_IPV6_QUEUE_PKT #if UIP_CONF_IPV6_QUEUE_PKT
uint8_t queue_buf[UIP_BUFSIZE - UIP_LLH_LEN]; uint8_t queue_buf[UIP_BUFSIZE - UIP_LLH_LEN];
uint8_t queue_buf_len; uint8_t queue_buf_len;
#endif /*UIP_CONF_QUEUE_PKT*/ #endif /*UIP_CONF_QUEUE_PKT */
} uip_ds6_nbr; } uip_ds6_nbr_t;
/** \brief An entry in the default router list */ /** \brief An entry in the default router list */
typedef struct uip_ds6_defrt { typedef struct uip_ds6_defrt {
uint8_t isused; uint8_t isused;
uip_ipaddr_t ipaddr; uip_ipaddr_t ipaddr;
struct stimer lifetime; struct stimer lifetime;
} uip_ds6_defrt; } uip_ds6_defrt_t;
/** \brief A prefix list entry */ /** \brief A prefix list entry */
#if UIP_CONF_ROUTER #if UIP_CONF_ROUTER
@ -185,7 +185,7 @@ typedef struct uip_ds6_prefix {
u32_t vlifetime; u32_t vlifetime;
u32_t plifetime; u32_t plifetime;
uint8_t l_a_reserved; /**< on-link and autonomous flags + 6 reserved bits */ uint8_t l_a_reserved; /**< on-link and autonomous flags + 6 reserved bits */
} uip_ds6_prefix ; } uip_ds6_prefix_t;
#else /* UIP_CONF_ROUTER */ #else /* UIP_CONF_ROUTER */
typedef struct uip_ds6_prefix { typedef struct uip_ds6_prefix {
uint8_t isused; uint8_t isused;
@ -193,8 +193,8 @@ typedef struct uip_ds6_prefix {
uint8_t length; uint8_t length;
struct stimer vlifetime; struct stimer vlifetime;
uint8_t isinfinite; uint8_t isinfinite;
} uip_ds6_prefix; } uip_ds6_prefix_t;
#endif /*UIP_CONF_ROUTER*/ #endif /*UIP_CONF_ROUTER */
/** * \brief Unicast address structure */ /** * \brief Unicast address structure */
typedef struct uip_ds6_addr { typedef struct uip_ds6_addr {
@ -206,19 +206,19 @@ typedef struct uip_ds6_addr {
struct stimer vlifetime; struct stimer vlifetime;
struct timer dadtimer; struct timer dadtimer;
uint8_t dadnscount; uint8_t dadnscount;
} uip_ds6_addr; } uip_ds6_addr_t;
/** \brief Anycast address */ /** \brief Anycast address */
typedef struct uip_ds6_aaddr { typedef struct uip_ds6_aaddr {
uint8_t isused; uint8_t isused;
uip_ipaddr_t ipaddr; uip_ipaddr_t ipaddr;
} uip_ds6_aaddr; } uip_ds6_aaddr_t;
/** \brief A multicast address */ /** \brief A multicast address */
typedef struct uip_ds6_maddr { typedef struct uip_ds6_maddr {
uint8_t isused; uint8_t isused;
uip_ipaddr_t ipaddr; uip_ipaddr_t ipaddr;
} uip_ds6_maddr; } uip_ds6_maddr_t;
/** \brief An entry in the routing table */ /** \brief An entry in the routing table */
typedef struct uip_ds6_route { typedef struct uip_ds6_route {
@ -227,7 +227,7 @@ typedef struct uip_ds6_route {
uint8_t length; uint8_t length;
uip_ipaddr_t nexthop; uip_ipaddr_t nexthop;
uint8_t metric; uint8_t metric;
} uip_ds6_route; } uip_ds6_route_t;
/** \brief Interface structure (contains all the interface variables) */ /** \brief Interface structure (contains all the interface variables) */
typedef struct uip_ds6_netif { typedef struct uip_ds6_netif {
@ -237,23 +237,24 @@ typedef struct uip_ds6_netif {
uint32_t reachable_time; /* in msec */ uint32_t reachable_time; /* in msec */
uint32_t retrans_timer; /* in msec */ uint32_t retrans_timer; /* in msec */
uint8_t maxdadns; uint8_t maxdadns;
uip_ds6_addr addr_list[UIP_DS6_ADDR_NB]; uip_ds6_addr_t addr_list[UIP_DS6_ADDR_NB];
uip_ds6_aaddr aaddr_list[UIP_DS6_AADDR_NB]; uip_ds6_aaddr_t aaddr_list[UIP_DS6_AADDR_NB];
uip_ds6_maddr maddr_list[UIP_DS6_MADDR_NB]; uip_ds6_maddr_t maddr_list[UIP_DS6_MADDR_NB];
} uip_ds6_netif; } uip_ds6_netif_t;
/** \brief Generic type for a DS6, to use a common loop though all DS */ /** \brief Generic type for a DS6, to use a common loop though all DS */
typedef struct uip_ds6_element { typedef struct uip_ds6_element {
uint8_t isused; uint8_t isused;
uip_ipaddr_t ipaddr; uip_ipaddr_t ipaddr;
} uip_ds6_element ; } uip_ds6_element_t;
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
extern uip_ds6_netif uip_ds6_if; extern uip_ds6_netif_t uip_ds6_if;
extern struct etimer uip_ds6_timer_periodic; extern struct etimer uip_ds6_timer_periodic;
#if UIP_CONF_ROUTER #if UIP_CONF_ROUTER
extern uip_ds6_prefix uip_ds6_prefix_list[UIP_DS6_PREFIX_NB]; extern uip_ds6_prefix_t uip_ds6_prefix_list[UIP_DS6_PREFIX_NB];
#else /* UIP_CONF_ROUTER */ #else /* UIP_CONF_ROUTER */
extern struct etimer uip_ds6_timer_rs; extern struct etimer uip_ds6_timer_rs;
#endif /* UIP_CONF_ROUTER */ #endif /* UIP_CONF_ROUTER */
@ -268,78 +269,97 @@ void uip_ds6_periodic(void);
/** \brief Generic loop routine on an abstract data structure, which generalizes /** \brief Generic loop routine on an abstract data structure, which generalizes
* all data structures used in DS6 */ * all data structures used in DS6 */
uint8_t uip_ds6_list_loop(uip_ds6_element* list, uint8_t size, uint16_t elementsize, uip_ipaddr_t* ipaddr, uint8_t ipaddrlen, uip_ds6_element** out_element); uint8_t uip_ds6_list_loop(uip_ds6_element_t * list, uint8_t size,
uint16_t elementsize, uip_ipaddr_t * ipaddr,
uint8_t ipaddrlen,
uip_ds6_element_t ** out_element);
/** \name Neighbor Cache basic routines */ /** \name Neighbor Cache basic routines */
/** @{ */ /** @{ */
uip_ds6_nbr* uip_ds6_nbr_add(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr, uint8_t isrouter, uint8_t state); uip_ds6_nbr_t *uip_ds6_nbr_add(uip_ipaddr_t * ipaddr, uip_lladdr_t * lladdr,
void uip_ds6_nbr_rm(uip_ds6_nbr* nbr); uint8_t isrouter, uint8_t state);
uip_ds6_nbr* uip_ds6_nbr_lookup(uip_ipaddr_t *ipaddr); void uip_ds6_nbr_rm(uip_ds6_nbr_t * nbr);
uip_ds6_nbr_t *uip_ds6_nbr_lookup(uip_ipaddr_t * ipaddr);
/** @} */ /** @} */
/** \name Default router list basic routines */ /** \name Default router list basic routines */
/** @{ */ /** @{ */
uip_ds6_defrt* uip_ds6_defrt_add(uip_ipaddr_t *ipaddr, unsigned long interval); uip_ds6_defrt_t *uip_ds6_defrt_add(uip_ipaddr_t * ipaddr,
void uip_ds6_defrt_rm(uip_ds6_defrt* defrt); unsigned long interval);
uip_ds6_defrt* uip_ds6_defrt_lookup(uip_ipaddr_t *ipaddr); void uip_ds6_defrt_rm(uip_ds6_defrt_t * defrt);
uip_ipaddr_t* uip_ds6_defrt_choose(void); uip_ds6_defrt_t *uip_ds6_defrt_lookup(uip_ipaddr_t * ipaddr);
uip_ipaddr_t *uip_ds6_defrt_choose(void);
/** @} */ /** @} */
/** \name Prefix list basic routines */ /** \name Prefix list basic routines */
/** @{ */ /** @{ */
#if UIP_CONF_ROUTER #if UIP_CONF_ROUTER
uip_ds6_prefix* uip_ds6_prefix_add(uip_ipaddr_t *ipaddr, uint8_t length, uint8_t advertise, uint8_t flags, unsigned long vtime, unsigned long ptime); uip_ds6_prefix_t *uip_ds6_prefix_add(uip_ipaddr_t * ipaddr, uint8_t length,
uint8_t advertise, uint8_t flags,
unsigned long vtime,
unsigned long ptime);
#else /* UIP_CONF_ROUTER */ #else /* UIP_CONF_ROUTER */
uip_ds6_prefix* uip_ds6_prefix_add(uip_ipaddr_t *ipaddr, uint8_t length, unsigned long interval); uip_ds6_prefix_t *uip_ds6_prefix_add(uip_ipaddr_t * ipaddr, uint8_t length,
unsigned long interval);
#endif /* UIP_CONF_ROUTER */ #endif /* UIP_CONF_ROUTER */
void uip_ds6_prefix_rm(uip_ds6_prefix* prefix); void uip_ds6_prefix_rm(uip_ds6_prefix_t * prefix);
uip_ds6_prefix* uip_ds6_prefix_lookup(uip_ipaddr_t *ipaddr, uint8_t ipaddrlen); uip_ds6_prefix_t *uip_ds6_prefix_lookup(uip_ipaddr_t * ipaddr,
uint8_t uip_ds6_is_addr_onlink(uip_ipaddr_t *ipaddr); uint8_t ipaddrlen);
uint8_t uip_ds6_is_addr_onlink(uip_ipaddr_t * ipaddr);
/** @} */ /** @} */
/** \name Unicast address list basic routines */ /** \name Unicast address list basic routines */
/** @{ */ /** @{ */
uip_ds6_addr* uip_ds6_addr_add(uip_ipaddr_t *ipaddr, unsigned long vlifetime, uint8_t type); uip_ds6_addr_t *uip_ds6_addr_add(uip_ipaddr_t * ipaddr,
void uip_ds6_addr_rm(uip_ds6_addr *addr); unsigned long vlifetime, uint8_t type);
uip_ds6_addr* uip_ds6_addr_lookup(uip_ipaddr_t* ipaddr); void uip_ds6_addr_rm(uip_ds6_addr_t * addr);
uip_ds6_addr_t *uip_ds6_addr_lookup(uip_ipaddr_t * ipaddr);
/** @} */ /** @} */
/** \name Multicast address list basic routines */ /** \name Multicast address list basic routines */
/** @{ */ /** @{ */
uip_ds6_maddr* uip_ds6_maddr_add(uip_ipaddr_t *ipaddr); uip_ds6_maddr_t *uip_ds6_maddr_add(uip_ipaddr_t * ipaddr);
void uip_ds6_maddr_rm(uip_ds6_maddr *maddr); void uip_ds6_maddr_rm(uip_ds6_maddr_t * maddr);
uip_ds6_maddr* uip_ds6_maddr_lookup(uip_ipaddr_t* ipaddr); uip_ds6_maddr_t *uip_ds6_maddr_lookup(uip_ipaddr_t * ipaddr);
/** @} */ /** @} */
/** \name Anycast address list basic routines */ /** \name Anycast address list basic routines */
/** @{ */ /** @{ */
uip_ds6_aaddr* uip_ds6_aaddr_add(uip_ipaddr_t *ipaddr); uip_ds6_aaddr_t *uip_ds6_aaddr_add(uip_ipaddr_t * ipaddr);
void uip_ds6_aaddr_rm(uip_ds6_aaddr *aaddr); void uip_ds6_aaddr_rm(uip_ds6_aaddr_t * aaddr);
uip_ds6_aaddr* uip_ds6_aaddr_lookup(uip_ipaddr_t* ipaddr); uip_ds6_aaddr_t *uip_ds6_aaddr_lookup(uip_ipaddr_t * ipaddr);
/** @} */ /** @} */
/** \name Routing Table basic routines */ /** \name Routing Table basic routines */
/** @{ */ /** @{ */
uip_ipaddr_t* uip_ds6_route_lookup(uip_ipaddr_t *destipaddr); uip_ds6_route_t *uip_ds6_route_lookup(uip_ipaddr_t * destipaddr);
uip_ds6_route* uip_ds6_route_add(uip_ipaddr_t *ipaddr, u8_t length, uip_ipaddr_t *next_hop, u8_t metric); uip_ds6_route_t *uip_ds6_route_add(uip_ipaddr_t * ipaddr, uint8_t length,
void uip_ds6_route_rm(uip_ds6_route* route); uip_ipaddr_t * next_hop, u8_t metric);
void uip_ds6_route_rm(uip_ds6_route_t * route);
/** @} */ /** @} */
/** \brief set the last 64 bits of an IP address based on the MAC address */ /** \brief set the last 64 bits of an IP address based on the MAC address */
void uip_ds6_set_addr_iid(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr); void uip_ds6_set_addr_iid(uip_ipaddr_t * ipaddr, uip_lladdr_t * lladdr);
/** \brief Get the number of matching bits of two addresses */ /** \brief Get the number of matching bits of two addresses */
uint8_t get_match_length(uip_ipaddr_t *src, uip_ipaddr_t *dst); uint8_t get_match_length(uip_ipaddr_t * src, uip_ipaddr_t * dst);
/** \brief Perform Duplicate Address Selection on one address */ /** \brief Perform Duplicate Address Selection on one address */
void uip_ds6_dad(uip_ds6_addr* ifaddr); void uip_ds6_dad(uip_ds6_addr_t * ifaddr);
/** \brief Callback when DAD failed */ /** \brief Callback when DAD failed */
void uip_ds6_dad_failed(uip_ds6_addr* ifaddr); int uip_ds6_dad_failed(uip_ds6_addr_t * ifaddr);
/** \brief Source address selection, see RFC 3484 */ /** \brief Source address selection, see RFC 3484 */
void uip_ds6_select_src(uip_ipaddr_t *src, uip_ipaddr_t *dst); void uip_ds6_select_src(uip_ipaddr_t * src, uip_ipaddr_t * dst);
#if UIP_CONF_ROUTER #if UIP_CONF_ROUTER
#if UIP_ND6_SEND_RA #if UIP_ND6_SEND_RA
@ -366,4 +386,3 @@ uint32_t uip_ds6_compute_reachable_time(void); /** \brief compute random reachab
/** @} */ /** @} */
#endif /* __UIP_DS6_H__ */ #endif /* __UIP_DS6_H__ */

View file

@ -43,7 +43,7 @@
*/ */
#include <string.h> #include <string.h>
#include "net/uip-netif.h" #include "net/uip-ds6.h"
#include "net/uip-icmp6.h" #include "net/uip-icmp6.h"
#define DEBUG 0 #define DEBUG 0
@ -79,11 +79,11 @@ uip_icmp6_echo_request_input(void)
PRINTF("\n"); PRINTF("\n");
/* IP header */ /* IP header */
UIP_IP_BUF->ttl = uip_netif_physical_if.cur_hop_limit; UIP_IP_BUF->ttl = uip_ds6_if.cur_hop_limit;
if(uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)){ if(uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)){
uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr); uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr);
uip_netif_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
} else { } else {
uip_ipaddr_copy(&tmp_ipaddr, &UIP_IP_BUF->srcipaddr); uip_ipaddr_copy(&tmp_ipaddr, &UIP_IP_BUF->srcipaddr);
uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
@ -127,6 +127,13 @@ uip_icmp6_echo_request_input(void)
void void
uip_icmp6_error_output(u8_t type, u8_t code, u32_t param) { uip_icmp6_error_output(u8_t type, u8_t code, u32_t param) {
uip_ext_len = 0; uip_ext_len = 0;
/* check if originating packet is not an ICMP error*/
if(UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type < 128){
uip_len = 0;
return;
}
/* remember data of original packet before shifting */ /* remember data of original packet before shifting */
uip_ipaddr_copy(&tmp_ipaddr, &UIP_IP_BUF->destipaddr); uip_ipaddr_copy(&tmp_ipaddr, &UIP_IP_BUF->destipaddr);
@ -142,7 +149,7 @@ uip_icmp6_error_output(u8_t type, u8_t code, u32_t param) {
UIP_IP_BUF->tcflow = 0; UIP_IP_BUF->tcflow = 0;
UIP_IP_BUF->flow = 0; UIP_IP_BUF->flow = 0;
UIP_IP_BUF->proto = UIP_PROTO_ICMP6; UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
UIP_IP_BUF->ttl = uip_netif_physical_if.cur_hop_limit; UIP_IP_BUF->ttl = uip_ds6_if.cur_hop_limit;
/* the source should not be unspecified nor multicast, the check for /* the source should not be unspecified nor multicast, the check for
multicast is done in uip_process */ multicast is done in uip_process */
@ -155,7 +162,7 @@ uip_icmp6_error_output(u8_t type, u8_t code, u32_t param) {
if(uip_is_addr_mcast(&tmp_ipaddr)){ if(uip_is_addr_mcast(&tmp_ipaddr)){
if(type == ICMP6_PARAM_PROB && code == ICMP6_PARAMPROB_OPTION){ if(type == ICMP6_PARAM_PROB && code == ICMP6_PARAMPROB_OPTION){
uip_netif_select_src(&UIP_IP_BUF->srcipaddr, &tmp_ipaddr); uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &tmp_ipaddr);
} else { } else {
uip_len = 0; uip_len = 0;
return; return;
@ -163,7 +170,7 @@ uip_icmp6_error_output(u8_t type, u8_t code, u32_t param) {
} else { } else {
#if UIP_CONF_ROUTER #if UIP_CONF_ROUTER
/* need to pick a source that corresponds to this node */ /* need to pick a source that corresponds to this node */
uip_netif_select_src(&UIP_IP_BUF->srcipaddr, &tmp_ipaddr); uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &tmp_ipaddr);
#else #else
uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &tmp_ipaddr); uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &tmp_ipaddr);
#endif #endif

View file

@ -63,6 +63,8 @@
#define ICMP6_NS 135 /**< Neighbor Solicitation */ #define ICMP6_NS 135 /**< Neighbor Solicitation */
#define ICMP6_NA 136 /**< Neighbor advertisement */ #define ICMP6_NA 136 /**< Neighbor advertisement */
#define ICMP6_REDIRECT 137 /**< Redirect */ #define ICMP6_REDIRECT 137 /**< Redirect */
#define ICMP6_RPL 155 /**< RPL */
/** @} */ /** @} */
@ -122,6 +124,11 @@ uip_icmp6_error_output(u8_t type, u8_t code, u32_t param);
/** @} */ /** @} */
#if UIP_CONF_IPV6_RPL
void
uip_rpl_input(void);
#endif /* UIP_CONF_IPV6_RPL */
#endif /*__ICMP6_H__*/ #endif /*__ICMP6_H__*/
/** @} */ /** @} */

View file

@ -1,917 +0,0 @@
/**
* \addtogroup uip6
* @{
*/
/**
* \file
* Neighbor discovery Input-Output (RFC 4861)
* \author Julien Abeille <jabeille@cisco.com>
* \author Mathilde Durvy <mdurvy@cisco.com>
*/
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Copyright (c) 2006, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <string.h>
#include "net/uip-icmp6.h"
#include "net/uip-nd6.h"
#include "net/uip-netif.h"
/*------------------------------------------------------------------*/
#define DEBUG 0
#if DEBUG
#include <stdio.h>
#define PRINTF(...) printf(__VA_ARGS__)
#define PRINT6ADDR(addr) PRINTF(" %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x ", ((u8_t *)addr)[0], ((u8_t *)addr)[1], ((u8_t *)addr)[2], ((u8_t *)addr)[3], ((u8_t *)addr)[4], ((u8_t *)addr)[5], ((u8_t *)addr)[6], ((u8_t *)addr)[7], ((u8_t *)addr)[8], ((u8_t *)addr)[9], ((u8_t *)addr)[10], ((u8_t *)addr)[11], ((u8_t *)addr)[12], ((u8_t *)addr)[13], ((u8_t *)addr)[14], ((u8_t *)addr)[15])
#define PRINTLLADDR(lladdr) PRINTF(" %02x:%02x:%02x:%02x:%02x:%02x ",lladdr->addr[0], lladdr->addr[1], lladdr->addr[2], lladdr->addr[3],lladdr->addr[4], lladdr->addr[5])
#else
#define PRINTF(...)
#define PRINT6ADDR(addr)
#define PRINTLLADDR(lladdr)
#endif
#if UIP_LOGGING
#include <stdio.h>
void uip_log(char *msg);
#define UIP_LOG(m) uip_log(m)
#else
#define UIP_LOG(m)
#endif /* UIP_LOGGING == 1 */
/*------------------------------------------------------------------*/
/** @{ */
/** \name Pointers to the header structures.
* All pointers except UIP_IP_BUF depend on uip_ext_len, which at
* packet reception, is the total length of the extension headers.
*
* The pointer to ND6 options header also depends on nd6_opt_offset,
* which we set in each function.
*
* Care should be taken when manipulating these buffers about the
* value of these length variables
*/
#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
/**< Pointer to IP header */
#define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[uip_l2_l3_hdr_len])
/**< Pointer to ICMP header*/
/**@{ Pointers to messages just after icmp header */
#define UIP_ND6_RS_BUF ((struct uip_nd6_rs *)&uip_buf[uip_l2_l3_icmp_hdr_len])
#define UIP_ND6_RA_BUF ((struct uip_nd6_ra *)&uip_buf[uip_l2_l3_icmp_hdr_len])
#define UIP_ND6_NS_BUF ((struct uip_nd6_ns *)&uip_buf[uip_l2_l3_icmp_hdr_len])
#define UIP_ND6_NA_BUF ((struct uip_nd6_na *)&uip_buf[uip_l2_l3_icmp_hdr_len])
#define UIP_ICMP6_ERROR_BUF ((struct uip_icmp6_error *)&uip_buf[uip_l2_l3_icmp_hdr_len])
/** @} */
/** Pointer to ND option */
#define UIP_ND6_OPT_HDR_BUF ((struct uip_nd6_opt_hdr *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset])
/** @} */
/** \brief Offset from the end of the icmpv6 header to the option in uip_buf*/
static u8_t nd6_opt_offset;
/** \brief Pointer to llao option in uip_buf */
static struct uip_nd6_opt_llao *nd6_opt_llao;
/** \brief Pointer to mtu option in uip_buf */
static struct uip_nd6_opt_mtu *nd6_opt_mtu;
/** \brief Pointer to prefix information option in uip_buf */
static struct uip_nd6_opt_prefix_info *nd6_opt_prefix_info[UIP_CONF_ND6_MAX_PREFIXES];
/** \brief Pointer to a neighbor cache entry*/
static struct uip_nd6_neighbor *neighbor;
/** \brief Pointer to a prefix list entry */
static struct uip_nd6_prefix *prefix;
/** \brief Pointer to a router list entry */
static struct uip_nd6_defrouter *router;
/** \brief Pointer to an interface address */
static struct uip_netif_addr *ifaddr;
/** \brief Index used in loops */
static u8_t i;
/*------------------------------------------------------------------*/
void
uip_nd6_io_ns_input(void)
{
u8_t flags;
PRINTF("Received NS from");
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
PRINTF("to");
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
PRINTF("with target address");
PRINT6ADDR((uip_ipaddr_t *)(&UIP_ND6_NS_BUF->tgtipaddr));
PRINTF("\n");
UIP_STAT(++uip_stat.nd6.recv);
#if UIP_CONF_IPV6_CHECKS
if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) ||
(uip_is_addr_mcast(&UIP_ND6_NS_BUF->tgtipaddr)) ||
(UIP_ICMP_BUF->icode != 0)) {
goto badpkt;
}
#endif /* UIP_CONF_IPV6_CHECKS */
/* Options reading: we handle only SLLAO for now */
nd6_opt_llao = NULL;
nd6_opt_offset = UIP_ND6_NS_LEN;
while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) {
#if UIP_CONF_IPV6_CHECKS
if(UIP_ND6_OPT_HDR_BUF->len == 0) {
goto badpkt;
}
#endif /* UIP_CONF_IPV6_CHECKS */
switch(UIP_ND6_OPT_HDR_BUF->type) {
case UIP_ND6_OPT_SLLAO:
nd6_opt_llao = (struct uip_nd6_opt_llao *)UIP_ND6_OPT_HDR_BUF;
break;
default:
UIP_LOG("ND option not supported in NS");
break;
}
nd6_opt_offset += (UIP_ND6_OPT_HDR_BUF->len << 3);
}
/* Options processing: only SLLAO */
if(nd6_opt_llao != NULL) {
#if UIP_CONF_IPV6_CHECKS
/* There must be NO option in a DAD NS */
if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
goto badpkt;
} else {
#endif /*UIP_CONF_IPV6_CHECKS*/
neighbor = uip_nd6_nbrcache_lookup(&UIP_IP_BUF->srcipaddr);
if(neighbor == NULL) {
/* we need to add the neighbor*/
uip_nd6_nbrcache_add(&UIP_IP_BUF->srcipaddr,
&nd6_opt_llao->addr, 0, STALE);
} else {
/* If LL address changed, set neighbor state to stale */
if(memcmp(&nd6_opt_llao->addr, &neighbor->lladdr, UIP_LLADDR_LEN) != 0) {
memcpy(&neighbor->lladdr, &nd6_opt_llao->addr, UIP_LLADDR_LEN);
neighbor->state = STALE;
} else {
/* If neighbor state is INCOMPLETE, set to STALE */
if(neighbor->state == INCOMPLETE) {
neighbor->state = STALE;
}
}
}
#if UIP_CONF_IPV6_CHECKS
}
#endif /*UIP_CONF_IPV6_CHECKS*/
}
/*
* Rest of NS processing: Depends on the purpose of the NS: NUD or DAD or
* Address Resolution
*/
/** \note we use ifaddr to remember the target address */
ifaddr = uip_netif_addr_lookup(&UIP_ND6_NS_BUF->tgtipaddr, 128, 0);
if(ifaddr != NULL) {
if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)){
/* DAD CASE */
#if UIP_CONF_IPV6_CHECKS
/* Dst address must be solicited node mcast address */
if(!uip_netif_is_addr_my_solicited(&UIP_IP_BUF->destipaddr)){
goto badpkt;
}
#endif /* UIP_CONF_IPV6_CHECKS */
/*
* If my address is not tentative, then send a NA to all nodes with
* TLLAO flags are: override = yes.
*/
if(ifaddr->state!=TENTATIVE) {
/*
* we need to send a NA, we set the src, dest, flags. tgt remains the
* same and the rest is done at "create_na"
*/
uip_create_linklocal_allnodes_mcast(&UIP_IP_BUF->destipaddr);
uip_netif_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
flags = UIP_ND6_NA_FLAG_OVERRIDE;
goto create_na;
} else {
/** \todo if I sent a NS before him, I win */
uip_netif_dad_failed(&UIP_ND6_NS_BUF->tgtipaddr);
goto discard;
}
}
#if UIP_CONF_IPV6_CHECKS
/* Duplicate check */
if(uip_netif_is_addr_my_unicast(&UIP_IP_BUF->srcipaddr)) {
/**
* \NOTE do we do something here? we both are using the same address.
* If we are doing dad, we could cancel it, though we should receive a
* NA in response of DAD NS we sent, hence DAD will fail anyway. If we
* were not doing DAD, it means there is a duplicate in the network!
*/
goto badpkt;
}
#endif /*UIP_CONF_IPV6_CHECKS*/
/* Address resolution case */
if(uip_netif_is_addr_my_solicited(&UIP_IP_BUF->destipaddr)){
/*
* we need to send a NA, we set the src, dest, flags. The rest is
* set at the "create_na" label.
*/
uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr);
uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &UIP_ND6_NS_BUF->tgtipaddr);
flags = UIP_ND6_NA_FLAG_SOLICITED | UIP_ND6_NA_FLAG_OVERRIDE;
goto create_na;
}
/*
* NUD CASE. at this point the packet must be for us! we check this,
* and at the same time if target == dest
*/
if(uip_netif_addr_lookup(&UIP_IP_BUF->destipaddr, 128, 0) == ifaddr){
/*
* we need to send a NA, we set the src, dest, flags. The rest is set
* at the "create_na" label.
*/
uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr);
uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &UIP_ND6_NS_BUF->tgtipaddr);
flags = UIP_ND6_NA_FLAG_SOLICITED | UIP_ND6_NA_FLAG_OVERRIDE;
goto create_na;
} else {
#if UIP_CONF_IPV6_CHECKS
goto badpkt;
#endif /* UIP_CONF_IPV6_CHECKS */
}
} else {
goto discard;
}
create_na:
/*
* Fill the part of the NA which is common to all NAs. If the NS contained
* extension headers, we must set the target address properly
*/
uip_ext_len = 0;
/* IP header */
UIP_IP_BUF->vtc = 0x60;
UIP_IP_BUF->tcflow = 0;
UIP_IP_BUF->flow = 0;
UIP_IP_BUF->len[0] = 0; /* length will not be more than 255 */
UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_NA_LEN + UIP_ND6_OPT_LLAO_LEN;
UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
UIP_IP_BUF->ttl = UIP_ND6_HOP_LIMIT;
/* ICMP header */
UIP_ICMP_BUF->type = ICMP6_NA;
UIP_ICMP_BUF->icode = 0;
/* NA static part */
UIP_ND6_NA_BUF->flagsreserved = flags;
memcpy(&UIP_ND6_NA_BUF->tgtipaddr, &ifaddr->ipaddr, sizeof(uip_ipaddr_t));
/* NA option: TLLAO. note that length field is in unit of 8 bytes */
uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NA_LEN + UIP_ND6_OPT_LLAO_LEN;
nd6_opt_llao = (struct uip_nd6_opt_llao *)&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_NA_LEN];
nd6_opt_llao->type = UIP_ND6_OPT_TLLAO;
nd6_opt_llao->len = UIP_ND6_OPT_LLAO_LEN >> 3;
memcpy(&(nd6_opt_llao->addr), &uip_lladdr, UIP_LLADDR_LEN);
/* padding if needed */
memset((void *)(&nd6_opt_llao->addr) + UIP_LLADDR_LEN, 0, UIP_ND6_OPT_LLAO_LEN - 2 - UIP_LLADDR_LEN);
/*ICMP checksum*/
UIP_ICMP_BUF->icmpchksum = 0;
UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
UIP_STAT(++uip_stat.nd6.sent);
PRINTF("Sending NA to");
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
PRINTF("from");
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
PRINTF("with target address");
PRINT6ADDR(&UIP_ND6_NA_BUF->tgtipaddr);
PRINTF("\n");
return;
#if UIP_CONF_IPV6_CHECKS
badpkt:
UIP_STAT(++uip_stat.nd6.drop);
UIP_LOG("NS received is bad");
#endif /* UIP_CONF_IPV6_CHECKS */
discard:
uip_len = 0;
return;
}
/*------------------------------------------------------------------*/
void
uip_nd6_io_ns_output(uip_ipaddr_t *src, uip_ipaddr_t *dest, uip_ipaddr_t *tgt)
{
/* IP header fields */
uip_ext_len = 0;
UIP_IP_BUF->vtc = 0x60;
UIP_IP_BUF->tcflow = 0;
UIP_IP_BUF->flow = 0;
UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
UIP_IP_BUF->ttl = UIP_ND6_HOP_LIMIT;
/*
* The caller must put a valid tgt address.
* For dest, if the caller is doing DAD or Address resolution, he sets
* dest to NULL and we forge dest as the sollicited node mcast address
* for tgt.
* If the caller is sending the NS for NUD, dest is unicast and the caller
* specifies it in the arguments
*/
if(dest == NULL) {
uip_create_solicited_node(tgt, &UIP_IP_BUF->destipaddr);
} else {
uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, dest);
}
UIP_ICMP_BUF->type = ICMP6_NS;
UIP_ICMP_BUF->icode = 0;
UIP_ND6_NS_BUF->reserved = 0;
/* Copy the tgt address */
uip_ipaddr_copy((uip_ipaddr_t *)&UIP_ND6_NS_BUF->tgtipaddr, tgt);
UIP_IP_BUF->len[0] = 0; /* length will not be more than 255 */
/*
* check if we add a SLLAO option: for DAD, MUST NOT, for NUD, MAY
* (here yes), for Address resolution , MUST
* i.e. if and only if tgt is our address (in this case it is DAD), we do
* not add it
*/
if(!(uip_netif_is_addr_my_unicast(tgt))) {
if(src != NULL) {
uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, src);
} else {
uip_netif_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
}
UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_NS_LEN + UIP_ND6_OPT_LLAO_LEN;
uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NS_LEN + UIP_ND6_OPT_LLAO_LEN;
nd6_opt_llao = (struct uip_nd6_opt_llao *)&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_NS_LEN];
nd6_opt_llao->type = UIP_ND6_OPT_SLLAO; /* type of the option */
/*
* length of the option: 2 bytes for type, length, plus the length of
* the L2 address. It must be in units of 8 bytes
*/
nd6_opt_llao->len = UIP_ND6_OPT_LLAO_LEN >> 3;
memcpy(&nd6_opt_llao->addr, &uip_lladdr, UIP_LLADDR_LEN);
/* padding if needed */
memset((void *)(&nd6_opt_llao->addr) + UIP_LLADDR_LEN, 0, UIP_ND6_OPT_LLAO_LEN - 2 - UIP_LLADDR_LEN);
}
else {
uip_create_unspecified(&UIP_IP_BUF->srcipaddr);
UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_NS_LEN;
uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NS_LEN;
}
UIP_ICMP_BUF->icmpchksum = 0;
UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
UIP_STAT(++uip_stat.nd6.sent);
PRINTF("Sending NS to");
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
PRINTF("from");
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
PRINTF("with target address");
PRINT6ADDR(tgt);
PRINTF("\n");
return;
}
/*------------------------------------------------------------------*/
void
uip_nd6_io_na_input(void)
{
/*
* booleans. the three last one are not 0 or 1 but 0 or 0x80, 0x40, 0x20
* but it works. Be careful though, do not use tests such as is_router == 1
*/
u8_t is_llchange = 0;
u8_t is_router = ((UIP_ND6_NA_BUF->flagsreserved & UIP_ND6_NA_FLAG_ROUTER));
u8_t is_solicited = ((UIP_ND6_NA_BUF->flagsreserved & UIP_ND6_NA_FLAG_SOLICITED));
u8_t is_override = ((UIP_ND6_NA_BUF->flagsreserved & UIP_ND6_NA_FLAG_OVERRIDE));
PRINTF("Received NA from");
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
PRINTF("to");
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
PRINTF("with target address");
PRINT6ADDR((uip_ipaddr_t *)(&UIP_ND6_NA_BUF->tgtipaddr));
PRINTF("\n");
UIP_STAT(++uip_stat.nd6.recv);
#if UIP_CONF_IPV6_CHECKS
/*
* Check hop limit / icmp code
* target address must not be multicast
* if the NA is solicited, dest must not be multicast
*/
if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) ||
(UIP_ICMP_BUF->icode != 0) ||
(uip_is_addr_mcast(&UIP_ND6_NA_BUF->tgtipaddr)) ||
(is_solicited && uip_is_addr_mcast(&UIP_IP_BUF->destipaddr))) {
goto badpkt;
}
#endif /*UIP_CONF_IPV6_CHECKS*/
/* Options reading: we can handle TLLAO, and must ignore othehrs */
nd6_opt_offset = UIP_ND6_NA_LEN;
nd6_opt_llao = NULL;
while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) {
#if UIP_CONF_IPV6_CHECKS
if(UIP_ND6_OPT_HDR_BUF->len == 0) {
goto badpkt;
}
#endif /*UIP_CONF_IPV6_CHECKS*/
switch(UIP_ND6_OPT_HDR_BUF->type) {
case UIP_ND6_OPT_TLLAO:
nd6_opt_llao = (struct uip_nd6_opt_llao *)UIP_ND6_OPT_HDR_BUF;
break;
default:
UIP_LOG("ND option not supported in NA");
break;
}
nd6_opt_offset += (UIP_ND6_OPT_HDR_BUF->len << 3);
}
ifaddr = uip_netif_addr_lookup(&UIP_ND6_NA_BUF->tgtipaddr, 128, 0);
/* Message processing, including TLLAO if any */
if(ifaddr != NULL) {
if(ifaddr->state == TENTATIVE) {
/*It means DAD failed*/
uip_netif_dad_failed(&UIP_ND6_NA_BUF->tgtipaddr);
}
goto discard;
} else {
neighbor = uip_nd6_nbrcache_lookup(&UIP_ND6_NA_BUF->tgtipaddr);
/* if the neighbor entry does not exist, silently discard */
if(neighbor == NULL) {
goto discard;
}
if(nd6_opt_llao != 0) {
is_llchange = memcmp((void *)&nd6_opt_llao->addr, (void *)(&neighbor->lladdr), UIP_LLADDR_LEN);
}
if(neighbor->state == INCOMPLETE){
if(nd6_opt_llao == 0) {
goto discard;
}
memcpy(&neighbor->lladdr, &nd6_opt_llao->addr, UIP_LLADDR_LEN);
if(is_solicited) {
neighbor->state = REACHABLE;
/* reachable time is stored in ms*/
stimer_set(&(neighbor->reachable),
uip_netif_physical_if.reachable_time / 1000);
} else {
neighbor->state = STALE;
}
neighbor->isrouter = is_router;
} else {
if(!is_override && is_llchange) {
if(neighbor->state == REACHABLE) {
neighbor->state = STALE;
}
goto discard;
} else {
if(is_override
|| (!is_override && nd6_opt_llao != 0 && !is_llchange)
|| nd6_opt_llao == 0) {
/* update LL address if any */
if(nd6_opt_llao != 0) {
memcpy(&neighbor->lladdr, &nd6_opt_llao->addr, UIP_LLADDR_LEN);
}
/*
* if the NA was solicited, change the state of the neighbor to
* reachabe. Otherwise and if the neighbor LL changed, set the
* state to STALE
*/
if(is_solicited) {
neighbor->state = REACHABLE;
/* reachable time is stored in ms*/
stimer_set(&(neighbor->reachable),
uip_netif_physical_if.reachable_time / 1000);
} else {
if(nd6_opt_llao != 0 && is_llchange) {
neighbor->state = STALE;
}
}
}
}
if(neighbor->isrouter && !is_router){
/* the neighbor stopped being a router, we remove it from the list */
router = uip_nd6_defrouter_lookup(neighbor);
if(router != NULL){
uip_nd6_defrouter_rm(router);
}
}
neighbor->isrouter = is_router;
}
}
#if UIP_CONF_IPV6_QUEUE_PKT
/* The neighbor is now reachable, check if we had buffered a pkt for it */
if(neighbor->queue_buf_len != 0) {
uip_len = neighbor->queue_buf_len;
memcpy(UIP_IP_BUF, neighbor->queue_buf, uip_len);
neighbor->queue_buf_len = 0;
return;
}
#endif /*UIP_CONF_IPV6_QUEUE_PKT*/
uip_len = 0;
return;
#if UIP_CONF_IPV6_CHECKS
badpkt:
UIP_STAT(++uip_stat.nd6.drop);
UIP_LOG("NA received is bad");
#endif /* UIP_CONF_IPV6_CHECKS */
discard:
uip_len = 0;
return;
}
/*---------------------------------------------------------------------------*/
void
uip_nd6_io_rs_output(void) {
UIP_IP_BUF->vtc = 0x60;
UIP_IP_BUF->tcflow = 0;
UIP_IP_BUF->flow = 0;
UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
UIP_IP_BUF->ttl = UIP_ND6_HOP_LIMIT;
uip_create_linklocal_allrouters_mcast(&UIP_IP_BUF->destipaddr);
uip_netif_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
UIP_ICMP_BUF->type = ICMP6_RS;
UIP_ICMP_BUF->icode = 0;
UIP_ND6_RS_BUF->reserved = 0;
UIP_IP_BUF->len[0] = 0; /* length will not be more than 255 */
/* we add the SLLAO option only if src is not unspecified */
if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_RS_LEN;
uip_len = uip_l3_icmp_hdr_len + UIP_ND6_RS_LEN;
} else {
uip_len = uip_l3_icmp_hdr_len + UIP_ND6_RS_LEN + UIP_ND6_OPT_LLAO_LEN;
UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_RS_LEN + UIP_ND6_OPT_LLAO_LEN;
nd6_opt_llao = (struct uip_nd6_opt_llao *)&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_RS_LEN];
nd6_opt_llao->type = UIP_ND6_OPT_SLLAO; /* type of the option */
nd6_opt_llao->len = UIP_ND6_OPT_LLAO_LEN >> 3;
/* length of the option in units of 8 bytes */
memcpy(&nd6_opt_llao->addr, &uip_lladdr, UIP_LLADDR_LEN);
/* padding if needed */
memset((void *)(&nd6_opt_llao->addr) + UIP_LLADDR_LEN, 0, UIP_ND6_OPT_LLAO_LEN - 2 - UIP_LLADDR_LEN);
}
UIP_ICMP_BUF->icmpchksum = 0;
UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
UIP_STAT(++uip_stat.nd6.sent);
PRINTF("Sendin RS to");
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
PRINTF("from");
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
PRINTF("\n");
return;
}
/*---------------------------------------------------------------------------*/
void
uip_nd6_io_ra_input(void) {
PRINTF("Received RA from");
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
PRINTF("to");
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
PRINTF("\n");
UIP_STAT(++uip_stat.nd6.recv);
#if UIP_CONF_IPV6_CHECKS
/* a few validity checks */
if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) ||
(!uip_is_addr_link_local(&UIP_IP_BUF->srcipaddr)) ||
(UIP_ICMP_BUF->icode != 0)) {
goto badpkt;
}
#endif /*UIP_CONF_IPV6_CHECKS*/
/*
* process the fields of the constant part
* As per RFC 4861, for reachable time and retrans timer, a value of 0 means
* unspecified by this router.
* If router lifetime is 0, the router SHOULD NOT be placed in default
* router list
*/
if(UIP_ND6_RA_BUF->cur_ttl != 0) {
uip_netif_physical_if.cur_hop_limit = UIP_ND6_RA_BUF->cur_ttl;
PRINTF("uip_netif_physical_if.cur_hop_limit %u\n", uip_netif_physical_if.cur_hop_limit);
}
/*
* As per RFC4861 section 6.3.4, if reachable time field is non zero
* and defers from the current base reachable time for the interface,
* set base reachable time to the new value and recompute the reachable time
* as a random value distributed between 0.5 and 1.5 x Base reachable time
*/
if(UIP_ND6_RA_BUF->reachable_time != 0) {
if(uip_netif_physical_if.base_reachable_time != ntohl(UIP_ND6_RA_BUF->reachable_time)) {
uip_netif_physical_if.base_reachable_time = ntohl(UIP_ND6_RA_BUF->reachable_time);
uip_netif_physical_if.reachable_time = uip_netif_compute_reachable_time();
}
}
if(UIP_ND6_RA_BUF->retrans_timer !=0) {
uip_netif_physical_if.retrans_timer = ntohl(UIP_ND6_RA_BUF->retrans_timer);
}
/*
* Note: in our implementation, an entry in the default router list contains
* does not contain the IP address of the router. The entry has a pointer
* to the corresponding neighbor cache entry, where the IP address is stored
*/
/* Options reading: possible options are MTU, SLLAO, prefix */
nd6_opt_llao = NULL;
nd6_opt_mtu = NULL;
for(i = 0; i < UIP_CONF_ND6_MAX_PREFIXES; i++) {
nd6_opt_prefix_info[i] = NULL;
}
nd6_opt_offset = UIP_ND6_RA_LEN;
while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) {
if(UIP_ND6_OPT_HDR_BUF->len == 0) {
goto badpkt;
}
switch(UIP_ND6_OPT_HDR_BUF->type) {
case UIP_ND6_OPT_SLLAO:
nd6_opt_llao = (struct uip_nd6_opt_llao *)UIP_ND6_OPT_HDR_BUF;
break;
case UIP_ND6_OPT_MTU:
nd6_opt_mtu = (struct uip_nd6_opt_mtu *)UIP_ND6_OPT_HDR_BUF;
break;
case UIP_ND6_OPT_PREFIX_INFO:
i = 0;
while((i < UIP_CONF_ND6_MAX_PREFIXES) && (nd6_opt_prefix_info[i] != NULL)) {
i++;
}
if(i < UIP_CONF_ND6_MAX_PREFIXES) {
nd6_opt_prefix_info[i] = (struct uip_nd6_opt_prefix_info *)UIP_ND6_OPT_HDR_BUF;
}
break;
default:
UIP_LOG("ND option not supported in RA");
break;
}
nd6_opt_offset += (UIP_ND6_OPT_HDR_BUF->len << 3);
}
/* Process the MTU option if any */
if(nd6_opt_mtu != NULL) {
/* just set the link MTU to the value specified. Note that this option */
PRINTF("Processing MTU option in RA\n");
uip_netif_physical_if.link_mtu = ntohl(nd6_opt_mtu->mtu);
}
/* Prefix information options processing */
i = 0;
while((i < UIP_CONF_ND6_MAX_PREFIXES - 1) && (nd6_opt_prefix_info[i] != NULL)) {
PRINTF("Processing PREFIX option in RA\n");
if((ntohl((nd6_opt_prefix_info[i])->validlt) >=
ntohl((nd6_opt_prefix_info[i])->preferredlt)) &&
(!uip_is_addr_link_local(&nd6_opt_prefix_info[i]->prefix))) {
/* on-link flag related processing*/
if(((nd6_opt_prefix_info[i])->flagsreserved1 & 0x80) == 0x80) {
prefix = uip_nd6_prefix_lookup(&(nd6_opt_prefix_info[i])->prefix);
if(prefix == NULL) {
if((nd6_opt_prefix_info[i])->validlt != 0){
if((nd6_opt_prefix_info[i])->validlt != UIP_ND6_INFINITE_LIFETIME){
prefix = uip_nd6_prefix_add(&(nd6_opt_prefix_info[i])->prefix,
(nd6_opt_prefix_info[i])->preflen,
ntohl((nd6_opt_prefix_info[i])->validlt));
} else {
prefix = uip_nd6_prefix_add(&(nd6_opt_prefix_info[i])->prefix,
(nd6_opt_prefix_info[i])->preflen,
0);
}
}
} else {
/* we update or remove an existing prefix */
switch((nd6_opt_prefix_info[i])->validlt) {
case 0:
uip_nd6_prefix_rm(prefix);
break;
case UIP_ND6_INFINITE_LIFETIME:
prefix->is_infinite = 1;
break;
default:
PRINTF("Updating timer of prefix");
PRINT6ADDR(prefix);
PRINTF("new value %lu\n", ntohl((nd6_opt_prefix_info[i])->validlt));
stimer_set(&prefix->vlifetime, ntohl((nd6_opt_prefix_info[i])->validlt));
/*in case the prefix lifetime was previously infinite */
prefix->is_infinite = 0;
break;
}
}
}
/* End of on-link flag related processing */
/* autonomous flag related processing*/
if((((nd6_opt_prefix_info[i])->flagsreserved1 & 0x40) == 0x40) &&
((nd6_opt_prefix_info[i])->validlt != 0)){
ifaddr = uip_netif_addr_lookup(&(nd6_opt_prefix_info[i])->prefix,
(nd6_opt_prefix_info[i])->preflen,
AUTOCONF);
if(ifaddr != NULL) {
if((nd6_opt_prefix_info[i])->validlt != UIP_ND6_INFINITE_LIFETIME) {
/* The processing below is defined in RFC4862 section 5.5.3 e */
if((ntohl((nd6_opt_prefix_info[i])->validlt) > 2 * 60 * 60) ||
(ntohl((nd6_opt_prefix_info[i])->validlt)> stimer_remaining(&ifaddr->vlifetime))) {
PRINTF("Updating timer of address");
PRINT6ADDR(&ifaddr->ipaddr);
PRINTF("new value %lu\n", ntohl((nd6_opt_prefix_info[i])->validlt));
stimer_set(&ifaddr->vlifetime, ntohl((nd6_opt_prefix_info[i])->validlt));
} else {
stimer_set(&ifaddr->vlifetime, 2 * 60 * 60);
PRINTF("Updating timer of address ");
PRINT6ADDR(&ifaddr->ipaddr);
PRINTF("new value %lu\n", (unsigned long)(2 * 60 * 60));
}
/*in case the address lifetime was previously infinite */
ifaddr->is_infinite = 0;
} else {
ifaddr->is_infinite = 1;
}
} else {
/* Autoconfigure an address*/
if((nd6_opt_prefix_info[i])->validlt != UIP_ND6_INFINITE_LIFETIME) {
/* Add an address with FINITE lifetime */
uip_netif_addr_add(&(nd6_opt_prefix_info[i])->prefix,
(nd6_opt_prefix_info[i])->preflen,
ntohl((nd6_opt_prefix_info[i])->validlt),
AUTOCONF);
} else {
/* Add an address with INFINITE lifetime */
uip_netif_addr_add(&(nd6_opt_prefix_info[i])->prefix,
(nd6_opt_prefix_info[i])->preflen,
0,
AUTOCONF);
}
}
}
/* End of autonomous flag related processing */
}
i++;
}
/* End of Prefix Information Option processing*/
/* SLLAO option processing */
neighbor = uip_nd6_nbrcache_lookup(&UIP_IP_BUF->srcipaddr);
if(nd6_opt_llao != NULL) {
PRINTF("Processing SLLAO option in RA\n");
if(neighbor == NULL) {
neighbor = uip_nd6_nbrcache_add(&UIP_IP_BUF->srcipaddr,
&nd6_opt_llao->addr, 1, STALE);
} else {
if(neighbor->state == INCOMPLETE) {
neighbor->state = STALE;
}
/* check if there was an address change. it applies to the case
* where if the router ND entry was in state NO_STATE */
if(memcmp(&nd6_opt_llao->addr, &neighbor->lladdr, UIP_LLADDR_LEN) != 0) {
memcpy(&neighbor->lladdr, &nd6_opt_llao->addr, UIP_LLADDR_LEN);
neighbor->state = STALE;
}
/*in case the neighbor was not a router before */
neighbor->isrouter = 1;
}
}
/*
* As per RFC4861, section 6.3.4, and considering that in our
* implementation, a router entry contains a pointer to an existing
* neighbor entry:
* if router lifetime != 0, if entry present in def router list
* (and therefore neighbor cache), update timer, and update neighbor entry
* if needed
* else add entry to both router list (and neighbor cache if absent)
* else delete entry in router list if it exists
*/
if(UIP_ND6_RA_BUF->router_lifetime != 0) {
/* Add router or update timer, we need a neighbor entry for this */
if(neighbor == NULL) {
neighbor = uip_nd6_nbrcache_add(&UIP_IP_BUF->srcipaddr, NULL, 1, NO_STATE);
} else {
/* in case the neighbor was not a router before */
neighbor->isrouter = 1;
}
if((router = uip_nd6_defrouter_lookup(neighbor)) == NULL) {
uip_nd6_defrouter_add(neighbor, (unsigned long)(ntohs(UIP_ND6_RA_BUF->router_lifetime)));
} else {
stimer_set(&(router->lifetime), (unsigned long)(ntohs(UIP_ND6_RA_BUF->router_lifetime)));
}
} else {
/* delete router entry*/
if(neighbor != NULL) {
router = uip_nd6_defrouter_lookup(neighbor);
if(router != NULL) {
uip_nd6_defrouter_rm(router);
}
}
}
#if UIP_CONF_IPV6_QUEUE_PKT
/*
* If the neighbor just became reachable (e.g. it was in INCOMPLETE state
* and we got a SLLAO), check if we had buffered a pkt for it
*/
if((neighbor != NULL) && (neighbor->queue_buf_len != 0)) {
uip_len = neighbor->queue_buf_len;
memcpy(UIP_IP_BUF, neighbor->queue_buf, uip_len);
neighbor->queue_buf_len = 0;
return;
}
#endif /*UIP_CONF_IPV6_QUEUE_PKT*/
uip_len = 0;
return;
badpkt:
UIP_STAT(++uip_stat.nd6.drop);
UIP_LOG("RA received is bad");
uip_len = 0;
return;
}
/** @} */

File diff suppressed because it is too large Load diff

View file

@ -477,7 +477,7 @@ void
* *
*/ */
void void
uip_nd6_io_ns_input(void); uip_nd6_ns_input(void);
/** /**
* \brief Send a neighbor solicitation, send a Neighbor Advertisement * \brief Send a neighbor solicitation, send a Neighbor Advertisement
@ -500,7 +500,7 @@ uip_nd6_io_ns_input(void);
* a SLLAO option, otherwise no. * a SLLAO option, otherwise no.
*/ */
void void
uip_nd6_io_ns_output(uip_ipaddr_t *src, uip_ipaddr_t *dest, uip_ipaddr_t *tgt); uip_nd6_ns_output(uip_ipaddr_t *src, uip_ipaddr_t *dest, uip_ipaddr_t *tgt);
/** /**
* \brief Process a Neighbor Advertisement * \brief Process a Neighbor Advertisement
@ -520,7 +520,7 @@ uip_nd6_io_ns_output(uip_ipaddr_t *src, uip_ipaddr_t *dest, uip_ipaddr_t *tgt);
* *
*/ */
void void
uip_nd6_io_na_input(void); uip_nd6_na_input(void);
#if UIP_CONF_ROUTER #if UIP_CONF_ROUTER
#if UIP_ND6_SEND_RA #if UIP_ND6_SEND_RA
@ -550,7 +550,7 @@ void uip_nd6_ra_output(uip_ipaddr_t *dest);
* possible option is SLLAO, MUST NOT be included if source = unspecified * possible option is SLLAO, MUST NOT be included if source = unspecified
* SHOULD be included otherwise * SHOULD be included otherwise
*/ */
void uip_nd6_io_rs_output(void); void uip_nd6_rs_output(void);
/** /**
* *
@ -563,7 +563,7 @@ void uip_nd6_io_rs_output(void);
* - If prefix option: start autoconf, add prefix to prefix list * - If prefix option: start autoconf, add prefix to prefix list
*/ */
void void
uip_nd6_io_ra_input(void); uip_nd6_ra_input(void);
/** @} */ /** @} */

View file

@ -1,424 +0,0 @@
/**
* \addtogroup uip6
* @{
*/
/**
* \file
* Network interface and stateless autoconfiguration (RFC 4862)
* \author Mathilde Durvy <mdurvy@cisco.com>
* \author Julien Abeille <jabeille@cisco.com>
*
*/
/*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
*/
#include "net/uip-nd6.h"
#include "net/uip-netif.h"
#include "lib/random.h"
#include <string.h>
#include <stdlib.h>
#define DEBUG 0
#if DEBUG
#include <stdio.h>
#define PRINTF(...) printf(__VA_ARGS__)
#define PRINT6ADDR(addr) PRINTF(" %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x ", ((u8_t *)addr)[0], ((u8_t *)addr)[1], ((u8_t *)addr)[2], ((u8_t *)addr)[3], ((u8_t *)addr)[4], ((u8_t *)addr)[5], ((u8_t *)addr)[6], ((u8_t *)addr)[7], ((u8_t *)addr)[8], ((u8_t *)addr)[9], ((u8_t *)addr)[10], ((u8_t *)addr)[11], ((u8_t *)addr)[12], ((u8_t *)addr)[13], ((u8_t *)addr)[14], ((u8_t *)addr)[15])
#define PRINTLLADDR(lladdr) PRINTF(" %02x:%02x:%02x:%02x:%02x:%02x ",lladdr->addr[0], lladdr->addr[1], lladdr->addr[2], lladdr->addr[3],lladdr->addr[4], lladdr->addr[5])
#else
#define PRINTF(...)
#define PRINT6ADDR(addr)
#define PRINTLLADDR(lladdr)
#endif
#if UIP_LOGGING
#include <stdio.h>
void uip_log(char *msg);
#define UIP_LOG(m) uip_log(m)
#else
#define UIP_LOG(m)
#endif /* UIP_LOGGING == 1 */
/*---------------------------------------------------------------------------*/
/** \brief The single physical interface */
struct uip_netif uip_netif_physical_if;
/** \brief DAD timer */
struct etimer uip_netif_timer_dad;
/** \brief The interface address on which dad is being performed */
static struct uip_netif_addr *dad_ifaddr;
/** \brief Number of ns already sent for DAD*/
static u8_t dad_ns;
/** \brief RS timer, to schedule RS sending */
struct etimer uip_netif_timer_rs;
/** \brief number of rs already sent */
static u8_t rs_count;
/** \brief index for loops */
static u8_t i;
/** \brief timer to check the address states */
struct etimer uip_netif_timer_periodic;
/** \brief remove an interface address, argument type is uip_netif_addr* */
#define uip_netif_addr_rm(addr) do { \
PRINTF("Removing address"); \
PRINT6ADDR(&addr->ipaddr); \
PRINTF("\n"); \
addr->state = NOT_USED; \
} while(0)
/*---------------------------------------------------------------------------*/
void
uip_netif_init(void)
{
/* INITIALIZE INTERFACE (default values for now) */
uip_netif_physical_if.link_mtu = UIP_LINK_MTU;
uip_netif_physical_if.cur_hop_limit = UIP_TTL;
uip_netif_physical_if.base_reachable_time = UIP_ND6_REACHABLE_TIME;
uip_netif_physical_if.reachable_time = uip_netif_compute_reachable_time();
uip_netif_physical_if.retrans_timer = UIP_ND6_RETRANS_TIMER;
uip_netif_physical_if.dup_addr_detect_transmit = 1;
/*
* STATELESS AUTOCONFIGURATION of the link local address. We set it to
* infinite (this will become really true once DAD succeeds)
*/
uip_ip6addr(&(uip_netif_physical_if.addresses[0].ipaddr),
0xfe80,0,0,0,0,0,0,0);
uip_netif_addr_autoconf_set(&(uip_netif_physical_if.addresses[0].ipaddr), &uip_lladdr);
uip_netif_physical_if.addresses[0].state = TENTATIVE;
uip_netif_physical_if.addresses[0].type = MANUAL;
uip_netif_physical_if.addresses[0].is_infinite = 1;
/* set all other addresses to NOT_USED initialy */
for(i = 1; i < UIP_CONF_NETIF_MAX_ADDRESSES; i ++) {
uip_netif_physical_if.addresses[i].state = NOT_USED;
}
uip_ip6addr_u8(&(uip_netif_physical_if.solicited_node_mcastaddr),
0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01, 0xff,
uip_lladdr.addr[UIP_LLADDR_LEN - 3],
uip_lladdr.addr[UIP_LLADDR_LEN - 2],
uip_lladdr.addr[UIP_LLADDR_LEN - 1]);
/* Start DAD */
uip_netif_sched_dad(&(uip_netif_physical_if.addresses[0]));
/* Find router (send rs to all-routers multicast group)) */
uip_netif_sched_send_rs();
/* Reset the timer */
etimer_set(&uip_netif_timer_periodic, CLOCK_SECOND);
}
/*---------------------------------------------------------------------------*/
void
uip_netif_periodic(void)
{
for(i = 1; i < UIP_CONF_NETIF_MAX_ADDRESSES; i++) {
if((uip_netif_physical_if.addresses[i].state != NOT_USED) &&
(uip_netif_physical_if.addresses[i].is_infinite != 1) &&
(stimer_expired(&uip_netif_physical_if.addresses[i].vlifetime))) {
uip_netif_addr_rm((&uip_netif_physical_if.addresses[i]));
}
}
etimer_reset(&uip_netif_timer_periodic);
return;
}
/*---------------------------------------------------------------------------*/
u32_t
uip_netif_compute_reachable_time(void)
{
return (u32_t)(UIP_ND6_MIN_RANDOM_FACTOR(uip_netif_physical_if.base_reachable_time)) +
((u16_t)(random_rand() << 8) + (u16_t)random_rand()) %
(u32_t)(UIP_ND6_MAX_RANDOM_FACTOR(uip_netif_physical_if.base_reachable_time) -
UIP_ND6_MIN_RANDOM_FACTOR(uip_netif_physical_if.base_reachable_time));
}
/*---------------------------------------------------------------------------*/
u8_t
uip_netif_is_addr_my_solicited(uip_ipaddr_t *ipaddr)
{
if(uip_ipaddr_cmp(ipaddr, &uip_netif_physical_if.solicited_node_mcastaddr)) {
return 1;
}
return 0;
}
/*---------------------------------------------------------------------------*/
struct uip_netif_addr *
uip_netif_addr_lookup(uip_ipaddr_t *ipaddr, u8_t length, uip_netif_type type)
{
for(i = 0; i < UIP_CONF_NETIF_MAX_ADDRESSES; i ++) {
if((uip_netif_physical_if.addresses[i].state != NOT_USED) &&
(uip_netif_physical_if.addresses[i].type == type || type == 0) &&
(uip_ipaddr_prefixcmp(&(uip_netif_physical_if.addresses[i].ipaddr), ipaddr, length))) {
return &uip_netif_physical_if.addresses[i];
}
}
return NULL;
}
/*---------------------------------------------------------------------------*/
void
uip_netif_addr_add(uip_ipaddr_t *ipaddr, u8_t length, unsigned long vlifetime, uip_netif_type type) {
/* check prefix has the right length if we are doing autoconf */
if((type == AUTOCONF) && (length != UIP_DEFAULT_PREFIX_LEN)) {
UIP_LOG("Error: UNSUPPORTED PREFIX LENGTH");
return;
}
/* check if addr does not already exist and find a free entry */
for(i = 0; i < UIP_CONF_NETIF_MAX_ADDRESSES; ++i) {
if(uip_netif_physical_if.addresses[i].state == NOT_USED){
/*
* Copying address
* If we are doing autoconf, ipaddr is a prefix, we copy the 128 bits
* of it, then overwrite the last 64 bits with the interface ID at
* next if statement.
* Otherwise ipaddr is an address, we just copy it
*/
uip_ipaddr_copy(&uip_netif_physical_if.addresses[i].ipaddr, ipaddr);
if(type == AUTOCONF) {
/* construct address from prefix and layer2 id */
uip_netif_addr_autoconf_set(&uip_netif_physical_if.addresses[i].ipaddr, &uip_lladdr);
}
/* setting state, type */
uip_netif_physical_if.addresses[i].state = TENTATIVE;
uip_netif_physical_if.addresses[i].type = type;
/* setting lifetime timer if lieftime is not infinite */
if(vlifetime != 0) {
stimer_set(&(uip_netif_physical_if.addresses[i].vlifetime), vlifetime);
uip_netif_physical_if.addresses[i].is_infinite = 0;
} else {
uip_netif_physical_if.addresses[i].is_infinite = 1;
}
PRINTF("Created new address");
PRINT6ADDR(&uip_netif_physical_if.addresses[i].ipaddr);
PRINTF("for interface\n");
/* schedule DAD */
uip_netif_sched_dad(&uip_netif_physical_if.addresses[i]);
return;
}
}
/* If we did not find space, log */
UIP_LOG("ADDRESS LIST FULL");
return;
}
/*---------------------------------------------------------------------------*/
void
uip_netif_addr_autoconf_set(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr)
{
/* We consider only links with IEEE EUI-64 identifier or
IEEE 48-bit MAC addresses */
#if (UIP_LLADDR_LEN == 8)
memcpy(ipaddr->u8 + 8, lladdr, UIP_LLADDR_LEN);
ipaddr->u8[8] ^= 0x02;
#elif (UIP_LLADDR_LEN == 6)
memcpy(ipaddr->u8 + 8, lladdr, 3);
ipaddr->u8[11] = 0xff;
ipaddr->u8[12] = 0xfe;
memcpy(ipaddr->u8 + 13, (u8_t*)lladdr + 3, 3);
ipaddr->u8[8] ^= 0x02;
#else
#error uip-netif.c cannot build interface address when UIP_LLADDR_LEN is not 6 or 8
#endif
}
/*---------------------------------------------------------------------------*/
u8_t
get_match_length(uip_ipaddr_t *src, uip_ipaddr_t *dst)
{
u8_t j, k, x_or;
u8_t len = 0;
for(j = 0; j < 16; j ++) {
if(src->u8[j] == dst->u8[j]) {
len += 8;
} else {
x_or = src->u8[j] ^ dst->u8[j];
for(k = 0; k < 8; k ++) {
if((x_or & 0x80) == 0){
len ++;
x_or <<= 1;
}
else {
break;
}
}
break;
}
}
return len;
}
/*---------------------------------------------------------------------------*/
void
uip_netif_select_src(uip_ipaddr_t *src, uip_ipaddr_t *dst)
{
u8_t best = 0; /* number of bit in common with best match*/
u8_t n = 0;
u8_t index = 0;
if(!uip_is_addr_link_local(dst) && !uip_is_addr_mcast(dst)) {
for(i = 1; i < UIP_CONF_NETIF_MAX_ADDRESSES; ++i) {
if(uip_netif_physical_if.addresses[i].state == PREFERRED){
n = get_match_length(dst, &(uip_netif_physical_if.addresses[i].ipaddr));
if(n >= best){
best = n;
index = i;
}
}
}
}
uip_ipaddr_copy(src, &(uip_netif_physical_if.addresses[index].ipaddr));
return;
}
/*---------------------------------------------------------------------------*/
void
uip_netif_sched_dad(struct uip_netif_addr *ifaddr)
{
if(ifaddr->state != TENTATIVE){
UIP_LOG("DAD called with non tentative address");
return;
}
/*
* check dad is not running
*/
if(dad_ifaddr != NULL){
UIP_LOG("DAD already running");
return;
}
/*
* Set the interface address that is going through DAD
*/
dad_ifaddr = ifaddr;
PRINTF("Scheduling DAD for ipaddr:");
PRINT6ADDR(&dad_ifaddr->ipaddr);
PRINTF("\n");
etimer_set(&uip_netif_timer_dad, random_rand()%(UIP_ND6_MAX_RTR_SOLICITATION_DELAY * CLOCK_SECOND));
}
/*---------------------------------------------------------------------------*/
void
uip_netif_dad(void)
{
/*
* check if dad is running
*/
if(dad_ifaddr == NULL){
PRINTF("uip_netif_dad: DAD not running\n");
return;
}
/*
* send dup_addr_detect_transmit NS for DAD
*/
if(dad_ns < uip_netif_physical_if.dup_addr_detect_transmit) {
uip_nd6_io_ns_output(NULL, NULL, &dad_ifaddr->ipaddr);
dad_ns++;
etimer_set(&uip_netif_timer_dad, uip_netif_physical_if.retrans_timer / 1000 * CLOCK_SECOND);
return;
}
/*
* If we arrive here it means DAD succeeded, otherwise the dad process
* would have been interrupted in nd6_dad_ns/na_input
*/
PRINTF("DAD succeeded for ipaddr:");
PRINT6ADDR(&(dad_ifaddr->ipaddr));
PRINTF("\n");
etimer_stop(&uip_netif_timer_dad);
dad_ifaddr->state = PREFERRED;
dad_ifaddr = NULL;
dad_ns = 0;
/*
* check if we need to run DAD on another address
* This is necessary because if you receive a RA,
* you might want to run DAD for several addresses
* Considering that we have structures to do DAD
* for one address only, we start DAD for the subsequent
* addresses here
*/
PRINTF("END of DAD\n");
for(i = 0; i < UIP_CONF_NETIF_MAX_ADDRESSES; i ++){
if(uip_netif_physical_if.addresses[i].state != NOT_USED){
PRINTF("address %u : ",i);
PRINT6ADDR(&(uip_netif_physical_if.addresses[i].ipaddr));
PRINTF("\n");
}
if(uip_netif_physical_if.addresses[i].state == TENTATIVE){
uip_netif_sched_dad(&uip_netif_physical_if.addresses[i]);
return;
}
}
}
/*---------------------------------------------------------------------------*/
void
uip_netif_dad_failed(uip_ipaddr_t *ipaddr)
{
UIP_LOG("DAD FAILED");
UIP_LOG("THE STACK IS GOING TO SHUT DOWN");
UIP_LOG("THE HOST WILL BE UNREACHABLE");
if(uip_ipaddr_cmp(&dad_ifaddr->ipaddr, ipaddr)){
etimer_stop(&uip_netif_timer_dad);
dad_ifaddr->state = NOT_USED;
dad_ifaddr = NULL;
dad_ns = 0;
}
}
/*---------------------------------------------------------------------------*/
void
uip_netif_sched_send_rs(void)
{
/* before a host sends an initial solicitation, it SHOULD delay the
transmission for a random amount of time between 0 and
UIP_ND6_MAX_RTR_SOLICITATION_DELAY. */
if(rs_count == 0){
etimer_set(&uip_netif_timer_rs, random_rand()%(UIP_ND6_MAX_RTR_SOLICITATION_DELAY * CLOCK_SECOND));
PRINTF("Scheduling RS\n");
}
}
/*---------------------------------------------------------------------------*/
void
uip_netif_send_rs(void)
{
if((uip_nd6_choose_defrouter() == NULL) && (rs_count < UIP_ND6_MAX_RTR_SOLICITATIONS)){
PRINTF("Sending RS %u\n", rs_count);
uip_nd6_io_rs_output();
rs_count++;
etimer_set(&uip_netif_timer_rs, UIP_ND6_RTR_SOLICITATION_INTERVAL * CLOCK_SECOND);
} else {
PRINTF("Router found ? (boolean): %u\n", (uip_nd6_choose_defrouter() != NULL));
etimer_stop(&uip_netif_timer_rs);
rs_count = 0;
}
}
/** @} */

View file

@ -1,207 +0,0 @@
/**
* \addtogroup uip6
* @{
*/
/**
* \file
* Network interface and stateless autoconfiguration (RFC 4862)
* \author Mathilde Durvy <mdurvy@cisco.com>
* \author Julien Abeille <jabeille@cisco.com>
*
*/
/*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
*/
#ifndef __UIP_NETIF_H__
#define __UIP_NETIF_H__
#include "net/uip-nd6.h"
#ifndef UIP_CONF_NETIF_MAX_ADDRESSES
#define UIP_CONF_NETIF_MAX_ADDRESSES 2
#endif /*UIP_CONF_NETIF_MAX_ADDRESSES*/
/**
* \brief Possible states for the address of an interface (RFC 4862 autoconf +
* NOT_USED + INFINITE)
*/
typedef enum {
NOT_USED = -1,
TENTATIVE = 0,
PREFERRED = 1,
DEPRECATED = 2, /* not needed if we don't use pliffetime in prefix struct */
} uip_netif_state;
/**
* \brief How the address was acquired: Autoconf, DHCP or manually
*
*/
typedef enum {
AUTOCONF = 1,
DHCP = 2,
MANUAL = 3
} uip_netif_type;
/**
* \brief An address structure for an interface
*
* Contains an ip address assigned to the interface, and its state.
*/
struct uip_netif_addr {
uip_ipaddr_t ipaddr;
uip_netif_state state;
struct stimer vlifetime;
u8_t is_infinite;
uip_netif_type type;
};
/** \brief Interface structure (contains all the interface variables) */
struct uip_netif {
u32_t link_mtu;
u8_t cur_hop_limit;
u32_t base_reachable_time; /* in msec */
u32_t reachable_time; /* in msec */
u32_t retrans_timer; /* in msec */
u8_t dup_addr_detect_transmit;
/** Note: the link-local address is at position 0 */
struct uip_netif_addr addresses[UIP_CONF_NETIF_MAX_ADDRESSES];
uip_ipaddr_t solicited_node_mcastaddr;
};
/*---------------------------------------------------------------------------*/
extern struct uip_netif uip_netif_physical_if;
extern struct etimer uip_netif_timer_dad;
extern struct etimer uip_netif_timer_rs;
extern struct etimer uip_netif_timer_periodic;
/*---------------------------------------------------------------------------*/
/** \brief Initialize the network interfac and run stateless autoconf */
void uip_netif_init(void);
/**
* \brief periodically check the state of the addresses.
*/
void uip_netif_periodic(void);
/**
* \brief recompute random reachable timer
* \return the new value for timer
*/
u32_t uip_netif_compute_reachable_time(void);
/**
* \brief Check if an unicast address is attached to my interface
* \param ipaddr an IP address to be checked
* \return 1 if address is attached to my interface (otherwise false)
*/
#define uip_netif_is_addr_my_unicast(a) (uip_netif_addr_lookup(a, 128, 0) != NULL)
/**
* \brief Check if this is my solicited-node multicast address
* \param ipaddr an IP address to be checked
* \return 1 if the address is my solicited-node (otherwise false)
*/
u8_t uip_netif_is_addr_my_solicited(uip_ipaddr_t *ipaddr);
/**
* \brief Autoconfigure and add an address corresponding to a specific prefix
* \param ipaddr the prefix if we are doing autoconf, the address for DHCP and manual
* \param length the prefix length if autoconf, 0 for DHCP and manual
* \param vlifetime valid lifetime of the address, 0 if the address has INFINITE lifetime,
* non 0 otherwise
* \param type AUTOCONF or MANUAL or DHCP
*/
void uip_netif_addr_add(uip_ipaddr_t *ipaddr, u8_t length, unsigned long vlifetime, uip_netif_type type);
/**
* \brief Set the 8 last bytes of the IP address
* based on the L2 identifier using autoconf
* \param *ipaddr the IP address to be completed with layer 2 info
* \param *lladdr the L2 address
*/
void uip_netif_addr_autoconf_set(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr);
/**
* \brief Lookup an address
* \param ipaddr the prefix if we are looking for an autoconf address, the address otherwise
* \param length the prefix length if we are looking for autoconf address, 128 otherwise
* \param type AUTOCONF or MANUAL or DHCP or 0
*
*
* If we are looking for an AUTOCONFIGURED address, ipaddr is a prefix
* length is its length, type is AUTOCONF.
* Otherwise ipaddr is a full address, length must be 128, type is MANUAL
* or DHCP.
* Note: if we do not care about the type, type MUST be 0
*/
struct uip_netif_addr *
uip_netif_addr_lookup(uip_ipaddr_t *ipaddr, u8_t length, uip_netif_type type);
/**
* \brief Select the appropriate source address for a packet
* \param ipaddr the selected address (returned value)
* \param ipaddr the destination of the packet
*/
void uip_netif_select_src(uip_ipaddr_t *src, uip_ipaddr_t *dst);
/**
* \brief Schedule DAD for a given address
* \param ifaddr the address for which schedule DAD
*/
void uip_netif_sched_dad(struct uip_netif_addr *ifaddr);
/**
* \brief Perform DAD (i.e. Duplicate Address Detection)
*/
void uip_netif_dad(void);
/**
* \brief DAD failed, should never happen!
* \param ipaddr the address for which DAD failed
*/
void uip_netif_dad_failed(uip_ipaddr_t *ipaddr);
/**
* \brief Schedule the sending of RS
*/
void uip_netif_sched_send_rs(void);
/**
* \brief Send up to MAX_RTR_SOLICITATION_DELAY RS separated by a delay of
* RTR_SOLICITATION_INTERVAL
*/
void uip_netif_send_rs(void);
#endif
/** @} */

View file

@ -47,7 +47,7 @@
* *
* This file is part of the uIP TCP/IP stack. * This file is part of the uIP TCP/IP stack.
* *
* $Id: uip.h,v 1.26 2010/03/12 16:19:19 joxe Exp $ * $Id: uip.h,v 1.27 2010/03/15 16:41:24 joxe Exp $
* *
*/ */
@ -82,38 +82,39 @@ typedef uip_ip4addr_t uip_ipaddr_t;
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** \brief 16 bit 802.15.4 address */ /** \brief 16 bit 802.15.4 address */
struct uip_802154_shortaddr { typedef struct uip_802154_shortaddr {
u8_t addr[2]; u8_t addr[2];
}; } uip_802154_shortaddr;
/** \brief 64 bit 802.15.4 address */ /** \brief 64 bit 802.15.4 address */
struct uip_802154_longaddr { typedef struct uip_802154_longaddr {
u8_t addr[8]; u8_t addr[8];
}; } uip_802154_longaddr;
/** \brief 802.11 address */ /** \brief 802.11 address */
struct uip_80211_addr { typedef struct uip_80211_addr {
u8_t addr[6]; u8_t addr[6];
}; } uip_80211_addr;
/** \brief 802.3 address */ /** \brief 802.3 address */
struct uip_eth_addr { typedef struct uip_eth_addr {
u8_t addr[6]; u8_t addr[6];
}; } uip_eth_addr;
#if UIP_CONF_LL_802154 #if UIP_CONF_LL_802154
/** \brief 802.15.4 address */ /** \brief 802.15.4 address */
typedef struct uip_802154_longaddr uip_lladdr_t; typedef uip_802154_longaddr uip_lladdr_t;
#define UIP_802154_SHORTADDR_LEN 2 #define UIP_802154_SHORTADDR_LEN 2
#define UIP_802154_LONGADDR_LEN 8 #define UIP_802154_LONGADDR_LEN 8
#define UIP_LLADDR_LEN UIP_802154_LONGADDR_LEN #define UIP_LLADDR_LEN UIP_802154_LONGADDR_LEN
#else /*UIP_CONF_LL_802154*/ #else /*UIP_CONF_LL_802154*/
#if UIP_CONF_LL_80211 #if UIP_CONF_LL_80211
/** \brief 802.11 address */ /** \brief 802.11 address */
typedef struct uip_80211_addr uip_lladdr_t; typedef uip_80211_addr uip_lladdr_t;
#define UIP_LLADDR_LEN 6 #define UIP_LLADDR_LEN 6
#else /*UIP_CONF_LL_80211*/ #else /*UIP_CONF_LL_80211*/
/** \brief Ethernet address */ /** \brief Ethernet address */
typedef struct uip_eth_addr uip_lladdr_t; typedef uip_eth_addr uip_lladdr_t;
#define UIP_LLADDR_LEN 6 #define UIP_LLADDR_LEN 6
#endif /*UIP_CONF_LL_80211*/ #endif /*UIP_CONF_LL_80211*/
#endif /*UIP_CONF_LL_802154*/ #endif /*UIP_CONF_LL_802154*/
@ -1716,22 +1717,22 @@ struct uip_ip_hdr {
* used in IPSec and defined in RFC4302,4303,4305,4385 * used in IPSec and defined in RFC4302,4303,4305,4385
*/ */
/* common header part */ /* common header part */
struct uip_ext_hdr { typedef struct uip_ext_hdr {
u8_t next; u8_t next;
u8_t len; u8_t len;
}; } uip_ext_hdr;
/* Hop by Hop option header */ /* Hop by Hop option header */
struct uip_hbho_hdr { typedef struct uip_hbho_hdr {
u8_t next; u8_t next;
u8_t len; u8_t len;
}; } uip_hbho_hdr;
/* destination option header */ /* destination option header */
struct uip_desto_hdr { typedef struct uip_desto_hdr {
u8_t next; u8_t next;
u8_t len; u8_t len;
}; } uip_desto_hdr;
/* We do not define structures for PAD1 and PADN options */ /* We do not define structures for PAD1 and PADN options */
@ -1743,35 +1744,35 @@ struct uip_desto_hdr {
* RFC3775 (MIPv6) here we do not implement MIPv6, so we just need to * RFC3775 (MIPv6) here we do not implement MIPv6, so we just need to
* parse the 4 first bytes * parse the 4 first bytes
*/ */
struct uip_routing_hdr { typedef struct uip_routing_hdr {
u8_t next; u8_t next;
u8_t len; u8_t len;
u8_t routing_type; u8_t routing_type;
u8_t seg_left; u8_t seg_left;
}; } uip_routing_hdr;
/* fragmentation header */ /* fragmentation header */
struct uip_frag_hdr { typedef struct uip_frag_hdr {
u8_t next; u8_t next;
u8_t res; u8_t res;
u16_t offsetresmore; u16_t offsetresmore;
u32_t id; u32_t id;
}; } uip_frag_hdr;
/* /*
* an option within the destination or hop by hop option headers * an option within the destination or hop by hop option headers
* it contains type an length, which is true for all options but PAD1 * it contains type an length, which is true for all options but PAD1
*/ */
struct uip_ext_hdr_opt { typedef struct uip_ext_hdr_opt {
u8_t type; u8_t type;
u8_t len; u8_t len;
}; } uip_ext_hdr_opt;
/* PADN option */ /* PADN option */
struct uip_ext_hdr_opt_padn { typedef struct uip_ext_hdr_opt_padn {
u8_t opt_type; u8_t opt_type;
u8_t opt_len; u8_t opt_len;
}; } uip_ext_hdr_opt_padn;
/* TCP header */ /* TCP header */
struct uip_tcp_hdr { struct uip_tcp_hdr {
@ -1923,6 +1924,22 @@ CCIF extern uip_lladdr_t uip_lladdr;
#ifdef UIP_CONF_IPV6 #ifdef UIP_CONF_IPV6
/** Length of the link local prefix */
#define UIP_LLPREF_LEN 10
/**
* \brief Is IPv6 address a the unspecified address
* a is of type uip_ipaddr_t
*/
#define uip_is_addr_loopback(a) \
((((a)->u16[0]) == 0) && \
(((a)->u16[1]) == 0) && \
(((a)->u16[2]) == 0) && \
(((a)->u16[3]) == 0) && \
(((a)->u16[4]) == 0) && \
(((a)->u16[5]) == 0) && \
(((a)->u16[6]) == 0) && \
(((a)->u16[7]) == 1))
/** /**
* \brief Is IPv6 address a the unspecified address * \brief Is IPv6 address a the unspecified address
* a is of type uip_ipaddr_t * a is of type uip_ipaddr_t
@ -1985,11 +2002,12 @@ CCIF extern uip_lladdr_t uip_lladdr;
#define uip_is_addr_solicited_node(a) \ #define uip_is_addr_solicited_node(a) \
((((a)->u8[0]) == 0xFF) && \ ((((a)->u8[0]) == 0xFF) && \
(((a)->u8[1]) == 0x02) && \ (((a)->u8[1]) == 0x02) && \
(((a)->u16[1]) == 0) && \ (((a)->u16[1]) == 0x00) && \
(((a)->u16[2]) == 0) && \ (((a)->u16[2]) == 0x00) && \
(((a)->u16[3]) == 0) && \ (((a)->u16[3]) == 0x00) && \
(((a)->u16[4]) == 0) && \ (((a)->u16[4]) == 0x00) && \
(((a)->u16[5]) == 1) && \ (((a)->u8[10]) == 0x00) && \
(((a)->u8[11]) == 0x01) && \
(((a)->u8[12]) == 0xFF)) (((a)->u8[12]) == 0xFF))
/** /**

View file

@ -41,7 +41,7 @@
* *
* This file is part of the uIP TCP/IP stack. * This file is part of the uIP TCP/IP stack.
* *
* $Id: uip6.c,v 1.14 2010/03/09 15:50:15 joxe Exp $ * $Id: uip6.c,v 1.15 2010/03/15 16:41:24 joxe Exp $
* *
*/ */
@ -75,7 +75,7 @@
#include "net/uipopt.h" #include "net/uipopt.h"
#include "net/uip-icmp6.h" #include "net/uip-icmp6.h"
#include "net/uip-nd6.h" #include "net/uip-nd6.h"
#include "net/uip-netif.h" #include "net/uip-ds6.h"
#include <string.h> #include <string.h>
@ -405,8 +405,7 @@ void
uip_init(void) uip_init(void)
{ {
uip_netif_init(); uip_ds6_init();
uip_nd6_init();
#if UIP_TCP #if UIP_TCP
for(c = 0; c < UIP_LISTENPORTS; ++c) { for(c = 0; c < UIP_LISTENPORTS; ++c) {
@ -428,19 +427,6 @@ uip_init(void)
#endif /* UIP_UDP */ #endif /* UIP_UDP */
} }
/*---------------------------------------------------------------------------*/
#if UIP_CONF_ROUTER
void
uip_router_register(const struct uip_router *router) {
if(uip_router != NULL) {
uip_router->deactivate();
}
uip_router = router;
if(uip_router != NULL) {
router->activate();
}
}
#endif /*UIP_CONF_ROUTER*/
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#if UIP_TCP && UIP_ACTIVE_OPEN #if UIP_TCP && UIP_ACTIVE_OPEN
struct uip_conn * struct uip_conn *
@ -550,7 +536,7 @@ uip_udp_new(const uip_ipaddr_t *ripaddr, u16_t rport)
} else { } else {
uip_ipaddr_copy(&conn->ripaddr, ripaddr); uip_ipaddr_copy(&conn->ripaddr, ripaddr);
} }
conn->ttl = uip_netif_physical_if.cur_hop_limit; conn->ttl = uip_ds6_if.cur_hop_limit;
return conn; return conn;
} }
@ -1091,36 +1077,54 @@ uip_process(u8_t flag)
} }
#if UIP_CONF_ROUTER #if UIP_CONF_ROUTER
if(!uip_netif_is_addr_my_unicast(&UIP_IP_BUF->destipaddr) && /* TBD Some Parameter problem messages */
!uip_netif_is_addr_my_solicited(&UIP_IP_BUF->destipaddr)) { if(!uip_ds6_is_my_addr(&UIP_IP_BUF->destipaddr) &&
!uip_ds6_is_my_maddr(&UIP_IP_BUF->destipaddr)) {
if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr) && if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr) &&
!uip_is_addr_link_local(&UIP_IP_BUF->destipaddr)) { !uip_is_addr_link_local(&UIP_IP_BUF->destipaddr) &&
!uip_is_addr_link_local(&UIP_IP_BUF->srcipaddr) &&
!uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr) &&
!uip_is_addr_loopback(&UIP_IP_BUF->destipaddr)) {
/* Check MTU */
if(uip_len > UIP_LINK_MTU) {
uip_icmp6_error_output(ICMP6_PACKET_TOO_BIG, 0, UIP_LINK_MTU);
UIP_STAT(++uip_stat.ip.drop);
goto send;
}
/* Check Hop Limit */
if(UIP_IP_BUF->ttl <= 1) {
uip_icmp6_error_output(ICMP6_TIME_EXCEEDED,
ICMP6_TIME_EXCEED_TRANSIT, 0);
UIP_STAT(++uip_stat.ip.drop);
goto send;
}
UIP_IP_BUF->ttl = UIP_IP_BUF->ttl - 1;
PRINTF("Forwarding packet to "); PRINTF("Forwarding packet to ");
PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINT6ADDR(&UIP_IP_BUF->destipaddr);
PRINTF("\n"); PRINTF("\n");
if(UIP_IP_BUF->ttl <= 1) {
PRINTF("Dropping packet: hop limit reached\n");
UIP_STAT(++uip_stat.ip.drop);
uip_icmp6_error_output(ICMP6_TIME_EXCEEDED,
ICMP6_TIME_EXCEED_TRANSIT, 0);
} else {
/* Decrement the TTL (time-to-live) value in the IP header */
UIP_IP_BUF->ttl = UIP_IP_BUF->ttl - 1;
UIP_STAT(++uip_stat.ip.forwarded); UIP_STAT(++uip_stat.ip.forwarded);
}
goto send; goto send;
} else if(!uip_is_addr_linklocal_allnodes_mcast(&UIP_IP_BUF->destipaddr) && } else {
!uip_is_addr_linklocal_allrouters_mcast(&UIP_IP_BUF->destipaddr)) { if((uip_is_addr_link_local(&UIP_IP_BUF->srcipaddr)) &&
PRINTF("Dropping packet, not for me\n"); (!uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) &&
(!uip_is_addr_loopback(&UIP_IP_BUF->destipaddr)) &&
(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) &&
(!uip_ds6_is_addr_onlink((&UIP_IP_BUF->destipaddr)))) {
PRINTF("LL source address with off link destination, dropping\n");
uip_icmp6_error_output(ICMP6_DST_UNREACH,
ICMP6_DST_UNREACH_NOTNEIGHBOR, 0);
goto send;
}
PRINTF("Dropping packet, not for me and link local or multicast\n");
UIP_STAT(++uip_stat.ip.drop); UIP_STAT(++uip_stat.ip.drop);
goto drop; goto drop;
} }
} }
#else #else /* UIP_CONF_ROUTER */
if(!uip_netif_is_addr_my_unicast(&UIP_IP_BUF->destipaddr) && if(!uip_ds6_is_my_addr(&UIP_IP_BUF->destipaddr) &&
!uip_netif_is_addr_my_solicited(&UIP_IP_BUF->destipaddr) && !uip_ds6_is_my_maddr(&UIP_IP_BUF->destipaddr)) {
!uip_is_addr_linklocal_allnodes_mcast(&UIP_IP_BUF->destipaddr)){
PRINTF("Dropping packet, not for me\n"); PRINTF("Dropping packet, not for me\n");
UIP_STAT(++uip_stat.ip.drop); UIP_STAT(++uip_stat.ip.drop);
goto drop; goto drop;
@ -1292,7 +1296,7 @@ uip_process(u8_t flag)
/* /*
* Here we process incoming ICMPv6 packets * Here we process incoming ICMPv6 packets
* For echo request, we send echo reply * For echo request, we send echo reply
* For ND pkts, we call the appropriate function in uip-nd6-io.c * For ND pkts, we call the appropriate function in uip-nd6.c
* We do not treat Error messages for now * We do not treat Error messages for now
* If no pkt is to be sent as an answer to the incoming one, we * If no pkt is to be sent as an answer to the incoming one, we
* "goto drop". Else we just break; then at the after the "switch" * "goto drop". Else we just break; then at the after the "switch"
@ -1304,18 +1308,32 @@ uip_process(u8_t flag)
switch(UIP_ICMP_BUF->type) { switch(UIP_ICMP_BUF->type) {
case ICMP6_NS: case ICMP6_NS:
uip_nd6_io_ns_input(); uip_nd6_ns_input();
break; break;
case ICMP6_NA: case ICMP6_NA:
uip_nd6_io_na_input(); uip_nd6_na_input();
break; break;
case ICMP6_RS: case ICMP6_RS:
#if UIP_CONF_ROUTER && UIP_ND6_SEND_RA
uip_nd6_rs_input();
#else /* UIP_CONF_ROUTER && UIP_ND6_SEND_RA */
UIP_STAT(++uip_stat.icmp.drop); UIP_STAT(++uip_stat.icmp.drop);
uip_len = 0; uip_len = 0;
#endif /* UIP_CONF_ROUTER && UIP_ND6_SEND_RA */
break; break;
case ICMP6_RA: case ICMP6_RA:
uip_nd6_io_ra_input(); #if UIP_CONF_ROUTER
UIP_STAT(++uip_stat.icmp.drop);
uip_len = 0;
#else /* UIP_CONF_ROUTER */
uip_nd6_ra_input();
#endif /* UIP_CONF_ROUTER */
break; break;
#if UIP_CONF_IPV6_RPL
case ICMP6_RPL:
uip_rpl_input();
break;
#endif /* UIP_CONF_IPV6_RPL */
case ICMP6_ECHO_REQUEST: case ICMP6_ECHO_REQUEST:
uip_icmp6_echo_request_input(); uip_icmp6_echo_request_input();
break; break;
@ -1426,7 +1444,7 @@ uip_process(u8_t flag)
UIP_TCP_BUF->destport = uip_udp_conn->rport; UIP_TCP_BUF->destport = uip_udp_conn->rport;
uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &uip_udp_conn->ripaddr); uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &uip_udp_conn->ripaddr);
uip_netif_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPTCPH_LEN]; uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPTCPH_LEN];
@ -1542,7 +1560,7 @@ uip_process(u8_t flag)
/* Swap IP addresses. */ /* Swap IP addresses. */
uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr); uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr);
uip_netif_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
/* And send out the RST packet! */ /* And send out the RST packet! */
goto tcp_send_noconn; goto tcp_send_noconn;
@ -2113,7 +2131,7 @@ uip_process(u8_t flag)
uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &uip_connr->ripaddr); uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &uip_connr->ripaddr);
uip_netif_select_src(&UIP_IP_BUF->srcipaddr,&UIP_IP_BUF->destipaddr); uip_ds6_select_src(&UIP_IP_BUF->srcipaddr,&UIP_IP_BUF->destipaddr);
PRINTF("Sending TCP packet to"); PRINTF("Sending TCP packet to");
PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINT6ADDR(&UIP_IP_BUF->destipaddr);
PRINTF("from"); PRINTF("from");
@ -2130,7 +2148,7 @@ uip_process(u8_t flag)
} }
tcp_send_noconn: tcp_send_noconn:
UIP_IP_BUF->ttl = uip_netif_physical_if.cur_hop_limit; UIP_IP_BUF->ttl = uip_ds6_if.cur_hop_limit;
UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);

View file

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* @(#)$Id: contiki-sky-main.c,v 1.74 2010/03/01 14:46:57 nifi Exp $ * @(#)$Id: contiki-sky-main.c,v 1.75 2010/03/15 16:43:04 joxe Exp $
*/ */
#include <signal.h> #include <signal.h>
@ -40,7 +40,6 @@
#include "dev/cc2420.h" #include "dev/cc2420.h"
#include "dev/ds2411.h" #include "dev/ds2411.h"
#include "dev/leds.h" #include "dev/leds.h"
#include "dev/light.h"
#include "dev/serial-line.h" #include "dev/serial-line.h"
#include "dev/sht11.h" #include "dev/sht11.h"
#include "dev/slip.h" #include "dev/slip.h"
@ -53,7 +52,7 @@
#if WITH_UIP6 #if WITH_UIP6
#include "net/sicslowpan.h" #include "net/sicslowpan.h"
#include "net/uip-netif.h" #include "net/uip-ds6.h"
#include "net/mac/sicslowmac.h" #include "net/mac/sicslowmac.h"
#endif /* WITH_UIP6 */ #endif /* WITH_UIP6 */
@ -301,24 +300,28 @@ main(int argc, char **argv)
printf("Tentative link-local IPv6 address "); printf("Tentative link-local IPv6 address ");
{ {
int i; int i, a;
for(a = 0; a < UIP_DS6_ADDR_NB; a++) {
if (uip_ds6_if.addr_list[a].isused) {
for(i = 0; i < 7; ++i) { for(i = 0; i < 7; ++i) {
printf("%02x%02x:", printf("%02x%02x:",
uip_netif_physical_if.addresses[0].ipaddr.u8[i * 2], uip_ds6_if.addr_list[a].ipaddr.u8[i * 2],
uip_netif_physical_if.addresses[0].ipaddr.u8[i * 2 + 1]); uip_ds6_if.addr_list[a].ipaddr.u8[i * 2 + 1]);
} }
printf("%02x%02x\n", printf("%02x%02x\n",
uip_netif_physical_if.addresses[0].ipaddr.u8[14], uip_ds6_if.addr_list[a].ipaddr.u8[14],
uip_netif_physical_if.addresses[0].ipaddr.u8[15]); uip_ds6_if.addr_list[a].ipaddr.u8[15]);
}
}
} }
if(1) { if(1) {
uip_ipaddr_t ipaddr; uip_ipaddr_t ipaddr;
int i; int i;
uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0);
uip_netif_addr_autoconf_set(&ipaddr, &uip_lladdr); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr);
uip_netif_addr_add(&ipaddr, 16, 0, TENTATIVE); uip_ds6_addr_add(&ipaddr, 0, ADDR_TENTATIVE);
printf("Tentative IPv6 address "); printf("Tentative global IPv6 address ");
for(i = 0; i < 7; ++i) { for(i = 0; i < 7; ++i) {
printf("%02x%02x:", printf("%02x%02x:",
ipaddr.u8[i * 2], ipaddr.u8[i * 2 + 1]); ipaddr.u8[i * 2], ipaddr.u8[i * 2 + 1]);
@ -329,7 +332,8 @@ main(int argc, char **argv)
#if UIP_CONF_ROUTER #if UIP_CONF_ROUTER
uip_router_register(&UIP_ROUTER_MODULE); //uip_router_register(&UIP_ROUTER_MODULE);
UIP_ROUTER_MODULE.activate();
#endif /* UIP_CONF_ROUTER */ #endif /* UIP_CONF_ROUTER */
#else /* WITH_UIP6 */ #else /* WITH_UIP6 */