Contiki-NG
Loading...
Searching...
No Matches
uip-ds6.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2006, Swedish Institute of Computer Science.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the Institute nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 */
30
31/**
32 * \addtogroup uip
33 * @{
34 */
35
36/**
37 * \file
38 * IPv6 data structure manipulation.
39 * Comprises part of the Neighbor discovery (RFC 4861)
40 * and auto configuration (RFC 4862) state machines.
41 * \author Mathilde Durvy <mdurvy@cisco.com>
42 * \author Julien Abeille <jabeille@cisco.com>
43 */
44
45#include <string.h>
46#include <stddef.h>
47#include "lib/random.h"
48#include "net/ipv6/uip-nd6.h"
50#include "net/ipv6/uip-ds6.h"
52#include "net/ipv6/uip-packetqueue.h"
53
54/* Log configuration */
55#include "sys/log.h"
56#define LOG_MODULE "IPv6 DS"
57#define LOG_LEVEL LOG_LEVEL_IPV6
58
59struct etimer uip_ds6_timer_periodic; /**< Timer for maintenance of data structures */
60
61#if UIP_CONF_ROUTER
62struct stimer uip_ds6_timer_ra; /**< RA timer, to schedule RA sending */
63#if UIP_ND6_SEND_RA
64static uint8_t racount; /**< number of RA already sent */
65static uint16_t rand_time; /**< random time value for timers */
66#endif
67#else /* UIP_CONF_ROUTER */
68struct etimer uip_ds6_timer_rs; /**< RS timer, to schedule RS sending */
69static uint8_t rscount; /**< number of rs already sent */
70#endif /* UIP_CONF_ROUTER */
71
72/** \name "DS6" Data structures */
73/** @{ */
74uip_ds6_netif_t uip_ds6_if; /**< The single interface */
75uip_ds6_prefix_t uip_ds6_prefix_list[UIP_DS6_PREFIX_NB]; /**< Prefix list */
76
77/* Used by Cooja to enable extraction of addresses from memory.*/
78uint8_t uip_ds6_addr_size;
79uint8_t uip_ds6_netif_addr_list_offset;
80
81/** @} */
82
83/* "full" (as opposed to pointer) ip address used in this file, */
84static uip_ipaddr_t loc_fipaddr;
85
86/* Pointers used in this file */
87static uip_ds6_addr_t *locaddr;
88static uip_ds6_maddr_t *locmaddr;
89#if UIP_DS6_AADDR_NB
90static uip_ds6_aaddr_t *locaaddr;
91#endif /* UIP_DS6_AADDR_NB */
92static uip_ds6_prefix_t *locprefix;
93#if (UIP_LLADDR_LEN == 2)
94static const uint8_t iid_prefix[] = { 0x00, 0x00 , 0x00 , 0xff , 0xfe , 0x00 };
95#endif /* (UIP_LLADDR_LEN == 2) */
96
97/* The default prefix */
98static uip_ip6addr_t default_prefix = {
99 .u16 = { 0, 0, 0, 0, 0, 0, 0, 0 }
100};
101/*---------------------------------------------------------------------------*/
102const uip_ip6addr_t *
104{
105 return &default_prefix;
106}
107/*---------------------------------------------------------------------------*/
108void
109uip_ds6_set_default_prefix(const uip_ip6addr_t *prefix)
110{
111 uip_ip6addr_copy(&default_prefix, prefix);
112}
113/*---------------------------------------------------------------------------*/
114void
116{
117 if(uip_is_addr_unspecified(&default_prefix)) {
118 uip_ip6addr(&default_prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0);
119 }
120
121 uip_ds6_neighbors_init();
122 uip_ds6_route_init();
123
124 LOG_INFO("Init: %u neighbors\n", NBR_TABLE_MAX_NEIGHBORS);
125 LOG_INFO("%u default routers\n", UIP_DS6_DEFRT_NB);
126 LOG_INFO("%u prefixes\n", UIP_DS6_PREFIX_NB);
127 LOG_INFO("%u routes\n", UIP_DS6_ROUTE_NB);
128 LOG_INFO("%u unicast addresses\n", UIP_DS6_ADDR_NB);
129 LOG_INFO("%u multicast addresses\n", UIP_DS6_MADDR_NB);
130 LOG_INFO("%u anycast addresses\n", UIP_DS6_AADDR_NB);
131
132 memset(uip_ds6_prefix_list, 0, sizeof(uip_ds6_prefix_list));
133 memset(&uip_ds6_if, 0, sizeof(uip_ds6_if));
134 uip_ds6_addr_size = sizeof(struct uip_ds6_addr);
135 uip_ds6_netif_addr_list_offset = offsetof(struct uip_ds6_netif, addr_list);
136
137 /* Set interface parameters */
138 uip_ds6_if.link_mtu = UIP_LINK_MTU;
139 uip_ds6_if.cur_hop_limit = UIP_TTL;
140 uip_ds6_if.base_reachable_time = UIP_ND6_REACHABLE_TIME;
142 uip_ds6_if.retrans_timer = UIP_ND6_RETRANS_TIMER;
144
145 /* Create link local address, prefix, multicast addresses, anycast addresses */
146 uip_create_linklocal_prefix(&loc_fipaddr);
147#if UIP_CONF_ROUTER
148 uip_ds6_prefix_add(&loc_fipaddr, UIP_DEFAULT_PREFIX_LEN, 0, 0, 0, 0);
149#else /* UIP_CONF_ROUTER */
150 uip_ds6_prefix_add(&loc_fipaddr, UIP_DEFAULT_PREFIX_LEN, 0);
151#endif /* UIP_CONF_ROUTER */
152 uip_ds6_set_addr_iid(&loc_fipaddr, &uip_lladdr);
153 uip_ds6_addr_add(&loc_fipaddr, 0, ADDR_AUTOCONF);
154
156 uip_ds6_maddr_add(&loc_fipaddr);
157#if UIP_CONF_ROUTER
159 uip_ds6_maddr_add(&loc_fipaddr);
160#if UIP_ND6_SEND_RA
161 stimer_set(&uip_ds6_timer_ra, 2); /* wait to have a link local IP address */
162#endif /* UIP_ND6_SEND_RA */
163#else /* UIP_CONF_ROUTER */
165 random_rand() % (UIP_ND6_MAX_RTR_SOLICITATION_DELAY *
166 CLOCK_SECOND));
167#endif /* UIP_CONF_ROUTER */
169
170 return;
171}
172
173
174/*---------------------------------------------------------------------------*/
175void
177{
178
179 /* Periodic processing on unicast addresses */
180 for(locaddr = uip_ds6_if.addr_list;
181 locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
182 if(locaddr->isused) {
183 if((!locaddr->isinfinite) && (stimer_expired(&locaddr->vlifetime))) {
184 uip_ds6_addr_rm(locaddr);
185#if UIP_ND6_DEF_MAXDADNS > 0
186 } else if((locaddr->state == ADDR_TENTATIVE)
187 && (locaddr->dadnscount <= uip_ds6_if.maxdadns)
188 && (timer_expired(&locaddr->dadtimer))
189 && (uip_len == 0)) {
190 uip_ds6_dad(locaddr);
191#endif /* UIP_ND6_DEF_MAXDADNS > 0 */
192 }
193 }
194 }
195
196 /* Periodic processing on default routers */
197 uip_ds6_defrt_periodic();
198#if !UIP_CONF_ROUTER
199 /* Periodic processing on prefixes */
200 for(locprefix = uip_ds6_prefix_list;
201 locprefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB;
202 locprefix++) {
203 if(locprefix->isused && !locprefix->isinfinite
204 && stimer_expired(&(locprefix->vlifetime))) {
205 uip_ds6_prefix_rm(locprefix);
206 }
207 }
208#endif /* !UIP_CONF_ROUTER */
209
210#if UIP_ND6_SEND_NS
212#endif /* UIP_ND6_SEND_NS */
213
214#if UIP_CONF_ROUTER && UIP_ND6_SEND_RA
215 /* Periodic RA sending */
216 if(stimer_expired(&uip_ds6_timer_ra) && (uip_len == 0)) {
217 uip_ds6_send_ra_periodic();
218 }
219#endif /* UIP_CONF_ROUTER && UIP_ND6_SEND_RA */
221 return;
222}
223
224/*---------------------------------------------------------------------------*/
225uint8_t
227 uint16_t elementsize, uip_ipaddr_t *ipaddr,
228 uint8_t ipaddrlen, uip_ds6_element_t **out_element)
229{
230 uip_ds6_element_t *element;
231
232 if(list == NULL || ipaddr == NULL || out_element == NULL) {
233 return NOSPACE;
234 }
235
236 *out_element = NULL;
237
238 for(element = list;
239 element <
240 (uip_ds6_element_t *)((uint8_t *)list + (size * elementsize));
241 element = (uip_ds6_element_t *)((uint8_t *)element + elementsize)) {
242 if(element->isused) {
243 if(uip_ipaddr_prefixcmp(&element->ipaddr, ipaddr, ipaddrlen)) {
244 *out_element = element;
245 return FOUND;
246 }
247 } else {
248 *out_element = element;
249 }
250 }
251
252 return *out_element != NULL ? FREESPACE : NOSPACE;
253}
254
255/*---------------------------------------------------------------------------*/
256#if UIP_CONF_ROUTER
257/*---------------------------------------------------------------------------*/
259uip_ds6_prefix_add(uip_ipaddr_t *ipaddr, uint8_t ipaddrlen,
260 uint8_t advertise, uint8_t flags, unsigned long vtime,
261 unsigned long ptime)
262{
264 ((uip_ds6_element_t *)uip_ds6_prefix_list, UIP_DS6_PREFIX_NB,
265 sizeof(uip_ds6_prefix_t), ipaddr, ipaddrlen,
266 (uip_ds6_element_t **)&locprefix) == FREESPACE) {
267 locprefix->isused = 1;
268 uip_ipaddr_copy(&locprefix->ipaddr, ipaddr);
269 locprefix->length = ipaddrlen;
270 locprefix->advertise = advertise;
271 locprefix->l_a_reserved = flags;
272 locprefix->vlifetime = vtime;
273 locprefix->plifetime = ptime;
274 LOG_INFO("Adding prefix ");
275 LOG_INFO_6ADDR(&locprefix->ipaddr);
276 LOG_INFO_(" len %u, flags %x, valid/preferred lifetime %lx/%lx\n",
277 ipaddrlen, flags, vtime, ptime);
278 return locprefix;
279 } else {
280 LOG_INFO("No more space in Prefix list\n");
281 }
282 return NULL;
283}
284
285
286#else /* UIP_CONF_ROUTER */
288uip_ds6_prefix_add(uip_ipaddr_t *ipaddr, uint8_t ipaddrlen,
289 unsigned long interval)
290{
292 ((uip_ds6_element_t *)uip_ds6_prefix_list, UIP_DS6_PREFIX_NB,
293 sizeof(uip_ds6_prefix_t), ipaddr, ipaddrlen,
294 (uip_ds6_element_t **)&locprefix) == FREESPACE) {
295 locprefix->isused = 1;
296 uip_ipaddr_copy(&locprefix->ipaddr, ipaddr);
297 locprefix->length = ipaddrlen;
298 if(interval != 0) {
299 stimer_set(&(locprefix->vlifetime), interval);
300 locprefix->isinfinite = 0;
301 } else {
302 locprefix->isinfinite = 1;
303 }
304 LOG_INFO("Adding prefix ");
305 LOG_INFO_6ADDR(&locprefix->ipaddr);
306 LOG_INFO_(" len %u, valid lifetime %lu\n", ipaddrlen, interval);
307 return locprefix;
308 }
309 return NULL;
310}
311#endif /* UIP_CONF_ROUTER */
312
313/*---------------------------------------------------------------------------*/
314void
315uip_ds6_prefix_rm(uip_ds6_prefix_t *prefix)
316{
317 if(prefix != NULL) {
318 prefix->isused = 0;
319 }
320 return;
321}
322/*---------------------------------------------------------------------------*/
324uip_ds6_prefix_lookup(uip_ipaddr_t *ipaddr, uint8_t ipaddrlen)
325{
327 UIP_DS6_PREFIX_NB, sizeof(uip_ds6_prefix_t),
328 ipaddr, ipaddrlen,
329 (uip_ds6_element_t **)&locprefix) == FOUND) {
330 return locprefix;
331 }
332 return NULL;
333}
334
335/*---------------------------------------------------------------------------*/
336uint8_t
337uip_ds6_is_addr_onlink(uip_ipaddr_t *ipaddr)
338{
339 for(locprefix = uip_ds6_prefix_list;
340 locprefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; locprefix++) {
341 if(locprefix->isused &&
342 uip_ipaddr_prefixcmp(&locprefix->ipaddr, ipaddr, locprefix->length)) {
343 return 1;
344 }
345 }
346 return 0;
347}
348
349/*---------------------------------------------------------------------------*/
351uip_ds6_addr_add(uip_ipaddr_t *ipaddr, unsigned long vlifetime, uint8_t type)
352{
354 ((uip_ds6_element_t *)uip_ds6_if.addr_list, UIP_DS6_ADDR_NB,
355 sizeof(uip_ds6_addr_t), ipaddr, 128,
356 (uip_ds6_element_t **)&locaddr) == FREESPACE) {
357 locaddr->isused = 1;
358 uip_ipaddr_copy(&locaddr->ipaddr, ipaddr);
359 locaddr->type = type;
360 if(vlifetime == 0) {
361 locaddr->isinfinite = 1;
362 } else {
363 locaddr->isinfinite = 0;
364 stimer_set(&(locaddr->vlifetime), vlifetime);
365 }
366#if UIP_ND6_DEF_MAXDADNS > 0
367 locaddr->state = ADDR_TENTATIVE;
368 timer_set(&locaddr->dadtimer,
369 random_rand() % (UIP_ND6_MAX_RTR_SOLICITATION_DELAY *
370 CLOCK_SECOND));
371 locaddr->dadnscount = 0;
372#else /* UIP_ND6_DEF_MAXDADNS > 0 */
373 locaddr->state = ADDR_PREFERRED;
374#endif /* UIP_ND6_DEF_MAXDADNS > 0 */
375 uip_create_solicited_node(ipaddr, &loc_fipaddr);
376 uip_ds6_maddr_add(&loc_fipaddr);
377 return locaddr;
378 }
379 return NULL;
380}
381
382/*---------------------------------------------------------------------------*/
383void
384uip_ds6_addr_rm(uip_ds6_addr_t *addr)
385{
386 if(addr != NULL) {
387 uip_create_solicited_node(&addr->ipaddr, &loc_fipaddr);
388 if((locmaddr = uip_ds6_maddr_lookup(&loc_fipaddr)) != NULL) {
389 uip_ds6_maddr_rm(locmaddr);
390 }
391 addr->isused = 0;
392 }
393 return;
394}
395
396/*---------------------------------------------------------------------------*/
398uip_ds6_addr_lookup(uip_ipaddr_t *ipaddr)
399{
401 ((uip_ds6_element_t *)uip_ds6_if.addr_list, UIP_DS6_ADDR_NB,
402 sizeof(uip_ds6_addr_t), ipaddr, 128,
403 (uip_ds6_element_t **)&locaddr) == FOUND) {
404 return locaddr;
405 }
406 return NULL;
407}
408
409/*---------------------------------------------------------------------------*/
410/*
411 * get a link local address -
412 * state = -1 => any address is ok. Otherwise state = desired state of addr.
413 * (TENTATIVE, PREFERRED, DEPRECATED)
414 */
416uip_ds6_get_link_local(int8_t state)
417{
418 for(locaddr = uip_ds6_if.addr_list;
419 locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
420 if(locaddr->isused && (state == -1 || locaddr->state == state)
421 && (uip_is_addr_linklocal(&locaddr->ipaddr))) {
422 return locaddr;
423 }
424 }
425 return NULL;
426}
427
428/*---------------------------------------------------------------------------*/
429/*
430 * get a global address -
431 * state = -1 => any address is ok. Otherwise state = desired state of addr.
432 * (TENTATIVE, PREFERRED, DEPRECATED)
433 */
435uip_ds6_get_global(int8_t state)
436{
437 for(locaddr = uip_ds6_if.addr_list;
438 locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
439 if(locaddr->isused && (state == -1 || locaddr->state == state)
440 && !(uip_is_addr_linklocal(&locaddr->ipaddr))) {
441 return locaddr;
442 }
443 }
444 return NULL;
445}
446
447/*---------------------------------------------------------------------------*/
449uip_ds6_maddr_add(const uip_ipaddr_t *ipaddr)
450{
452 ((uip_ds6_element_t *)uip_ds6_if.maddr_list, UIP_DS6_MADDR_NB,
453 sizeof(uip_ds6_maddr_t), (void*)ipaddr, 128,
454 (uip_ds6_element_t **)&locmaddr) == FREESPACE) {
455 locmaddr->isused = 1;
456 uip_ipaddr_copy(&locmaddr->ipaddr, ipaddr);
457 return locmaddr;
458 }
459 return NULL;
460}
461
462/*---------------------------------------------------------------------------*/
463void
464uip_ds6_maddr_rm(uip_ds6_maddr_t *maddr)
465{
466 if(maddr != NULL) {
467 maddr->isused = 0;
468 }
469 return;
470}
471
472/*---------------------------------------------------------------------------*/
474uip_ds6_maddr_lookup(const uip_ipaddr_t *ipaddr)
475{
477 ((uip_ds6_element_t *)uip_ds6_if.maddr_list, UIP_DS6_MADDR_NB,
478 sizeof(uip_ds6_maddr_t), (void*)ipaddr, 128,
479 (uip_ds6_element_t **)&locmaddr) == FOUND) {
480 return locmaddr;
481 }
482 return NULL;
483}
484
485
486/*---------------------------------------------------------------------------*/
488uip_ds6_aaddr_add(uip_ipaddr_t *ipaddr)
489{
490#if UIP_DS6_AADDR_NB
492 ((uip_ds6_element_t *)uip_ds6_if.aaddr_list, UIP_DS6_AADDR_NB,
493 sizeof(uip_ds6_aaddr_t), ipaddr, 128,
494 (uip_ds6_element_t **)&locaaddr) == FREESPACE) {
495 locaaddr->isused = 1;
496 uip_ipaddr_copy(&locaaddr->ipaddr, ipaddr);
497 return locaaddr;
498 }
499#endif /* UIP_DS6_AADDR_NB */
500 return NULL;
501}
502
503/*---------------------------------------------------------------------------*/
504void
505uip_ds6_aaddr_rm(uip_ds6_aaddr_t *aaddr)
506{
507 if(aaddr != NULL) {
508 aaddr->isused = 0;
509 }
510 return;
511}
512
513/*---------------------------------------------------------------------------*/
515uip_ds6_aaddr_lookup(uip_ipaddr_t *ipaddr)
516{
517#if UIP_DS6_AADDR_NB
519 UIP_DS6_AADDR_NB, sizeof(uip_ds6_aaddr_t), ipaddr, 128,
520 (uip_ds6_element_t **)&locaaddr) == FOUND) {
521 return locaaddr;
522 }
523#endif /* UIP_DS6_AADDR_NB */
524 return NULL;
525}
526
527/*---------------------------------------------------------------------------*/
528void
529uip_ds6_select_src(uip_ipaddr_t *src, uip_ipaddr_t *dst)
530{
531 uint8_t best = 0; /* number of bit in common with best match */
532 uint8_t n = 0;
533 uip_ds6_addr_t *matchaddr = NULL;
534
535 if(!uip_is_addr_linklocal(dst) && !uip_is_addr_mcast(dst)) {
536 /* find longest match */
537 for(locaddr = uip_ds6_if.addr_list;
538 locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
539 /* Only preferred global (not link-local) addresses */
540 if(locaddr->isused && locaddr->state == ADDR_PREFERRED &&
541 !uip_is_addr_linklocal(&locaddr->ipaddr)) {
542 n = get_match_length(dst, &locaddr->ipaddr);
543 if(n >= best) {
544 best = n;
545 matchaddr = locaddr;
546 }
547 }
548 }
549#if UIP_IPV6_MULTICAST
550 } else if(uip_is_addr_mcast_routable(dst)) {
551 matchaddr = uip_ds6_get_global(ADDR_PREFERRED);
552#endif
553 } else {
554 matchaddr = uip_ds6_get_link_local(ADDR_PREFERRED);
555 }
556
557 /* use the :: (unspecified address) as source if no match found */
558 if(matchaddr == NULL) {
560 } else {
561 uip_ipaddr_copy(src, &matchaddr->ipaddr);
562 }
563}
564
565/*---------------------------------------------------------------------------*/
566void
567uip_ds6_set_addr_iid(uip_ipaddr_t *ipaddr, const uip_lladdr_t *lladdr)
568{
569#if (UIP_LLADDR_LEN == 8)
570 memcpy(ipaddr->u8 + 8, lladdr, UIP_LLADDR_LEN);
571 ipaddr->u8[8] ^= 0x02;
572#elif (UIP_LLADDR_LEN == 6)
573 memcpy(ipaddr->u8 + 8, lladdr, 3);
574 ipaddr->u8[11] = 0xff;
575 ipaddr->u8[12] = 0xfe;
576 memcpy(ipaddr->u8 + 13, (uint8_t *)lladdr + 3, 3);
577 ipaddr->u8[8] ^= 0x02;
578#elif (UIP_LLADDR_LEN == 2)
579 /* derive IID as per RFC 6282 */
580 memcpy(ipaddr->u8 + 8, iid_prefix, 6);
581 memcpy(ipaddr->u8 + 8 + 6, lladdr, UIP_LLADDR_LEN);
582#else
583#error uip-ds6.c cannot build interface address when UIP_LLADDR_LEN is not 6, 8, or 2
584#endif
585}
586/*---------------------------------------------------------------------------*/
587void
588uip_ds6_set_lladdr_from_iid(uip_lladdr_t *lladdr, const uip_ipaddr_t *ipaddr)
589{
590#if (UIP_LLADDR_LEN == 8)
591 memcpy(lladdr, ipaddr->u8 + 8, UIP_LLADDR_LEN);
592 lladdr->addr[0] ^= 0x02;
593#elif (UIP_LLADDR_LEN == 2)
594 memcpy(lladdr, ipaddr->u8 + 8 + 6, UIP_LLADDR_LEN);
595#else
596#error uip-ds6.c cannot build lladdr address when UIP_LLADDR_LEN is not 8 or 2
597#endif
598}
599
600/*---------------------------------------------------------------------------*/
601uint8_t
602get_match_length(uip_ipaddr_t *src, uip_ipaddr_t *dst)
603{
604 uint8_t j, k, x_or;
605 uint8_t len = 0;
606
607 for(j = 0; j < 16; j++) {
608 if(src->u8[j] == dst->u8[j]) {
609 len += 8;
610 } else {
611 x_or = src->u8[j] ^ dst->u8[j];
612 for(k = 0; k < 8; k++) {
613 if((x_or & 0x80) == 0) {
614 len++;
615 x_or <<= 1;
616 } else {
617 break;
618 }
619 }
620 break;
621 }
622 }
623 return len;
624}
625
626/*---------------------------------------------------------------------------*/
627#if UIP_ND6_DEF_MAXDADNS > 0
628void
630{
631 /* send maxdadns NS for DAD */
632 if(addr->dadnscount < uip_ds6_if.maxdadns) {
633 uip_nd6_ns_output(NULL, NULL, &addr->ipaddr);
634 addr->dadnscount++;
635 timer_set(&addr->dadtimer,
636 uip_ds6_if.retrans_timer / 1000 * CLOCK_SECOND);
637 return;
638 }
639 /*
640 * If we arrive here it means DAD succeeded, otherwise the dad process
641 * would have been interrupted in ds6_dad_ns/na_input
642 */
643 LOG_INFO("DAD succeeded, ipaddr: ");
644 LOG_INFO_6ADDR(&addr->ipaddr);
645 LOG_INFO_("\n");
646
647 addr->state = ADDR_PREFERRED;
648 return;
649}
650
651/*---------------------------------------------------------------------------*/
652/*
653 * Calling code must handle when this returns 0 (e.g. link local
654 * address can not be used).
655 */
656int
658{
659 if(uip_is_addr_linklocal(&addr->ipaddr)) {
660 LOG_ERR("Contiki shutdown, DAD for link local address failed\n");
661 return 0;
662 }
663 uip_ds6_addr_rm(addr);
664 return 1;
665}
666#endif /*UIP_ND6_DEF_MAXDADNS > 0 */
667
668/*---------------------------------------------------------------------------*/
669#if UIP_CONF_ROUTER
670#if UIP_ND6_SEND_RA
671void
672uip_ds6_send_ra_sollicited(void)
673{
674 /* We have a pb here: RA timer max possible value is 1800s,
675 * hence we have to use stimers. However, when receiving a RS, we
676 * should delay the reply by a random value between 0 and 500ms timers.
677 * stimers are in seconds, hence we cannot do this. Therefore we just send
678 * the RA (setting the timer to 0 below). We keep the code logic for
679 * the days contiki will support appropriate timers */
680 rand_time = 0;
681 LOG_INFO("Solicited RA, random time %u\n", rand_time);
682
683 if(stimer_remaining(&uip_ds6_timer_ra) > rand_time) {
684 if(stimer_elapsed(&uip_ds6_timer_ra) < UIP_ND6_MIN_DELAY_BETWEEN_RAS) {
685 /* Ensure that the RAs are rate limited */
686/* stimer_set(&uip_ds6_timer_ra, rand_time +
687 UIP_ND6_MIN_DELAY_BETWEEN_RAS -
688 stimer_elapsed(&uip_ds6_timer_ra));
689 */ } else {
690 stimer_set(&uip_ds6_timer_ra, rand_time);
691 }
692 }
693}
694
695/*---------------------------------------------------------------------------*/
696void
697uip_ds6_send_ra_periodic(void)
698{
699 if(racount > 0) {
700 /* send previously scheduled RA */
701 uip_nd6_ra_output(NULL);
702 LOG_INFO("Sending periodic RA\n");
703 }
704
705 rand_time = UIP_ND6_MIN_RA_INTERVAL + random_rand() %
706 (uint16_t) (UIP_ND6_MAX_RA_INTERVAL - UIP_ND6_MIN_RA_INTERVAL);
707 LOG_DBG("Random time 1 = %u\n", rand_time);
708
709 if(racount < UIP_ND6_MAX_INITIAL_RAS) {
710 if(rand_time > UIP_ND6_MAX_INITIAL_RA_INTERVAL) {
711 rand_time = UIP_ND6_MAX_INITIAL_RA_INTERVAL;
712 LOG_DBG("Random time 2 = %u\n", rand_time);
713 }
714 racount++;
715 }
716 LOG_DBG("Random time 3 = %u\n", rand_time);
717 stimer_set(&uip_ds6_timer_ra, rand_time);
718}
719
720#endif /* UIP_ND6_SEND_RA */
721#else /* UIP_CONF_ROUTER */
722/*---------------------------------------------------------------------------*/
723void
725{
726 if((uip_ds6_defrt_choose() == NULL)
728 LOG_INFO("Sending RS %u\n", rscount);
730 rscount++;
733 } else {
734 LOG_INFO("Router found ? (boolean): %u\n",
735 (uip_ds6_defrt_choose() != NULL));
737 }
738 return;
739}
740
741#endif /* UIP_CONF_ROUTER */
742/*---------------------------------------------------------------------------*/
743uint32_t
745{
746 return (uint32_t) (UIP_ND6_MIN_RANDOM_FACTOR
747 (uip_ds6_if.base_reachable_time)) +
748 ((uint16_t) (random_rand() << 8) +
749 (uint16_t) random_rand()) %
750 (uint32_t) (UIP_ND6_MAX_RANDOM_FACTOR(uip_ds6_if.base_reachable_time) -
751 UIP_ND6_MIN_RANDOM_FACTOR(uip_ds6_if.base_reachable_time));
752}
753/*---------------------------------------------------------------------------*/
754
755/** @}*/
static volatile at86rf215_flags_t flags
The radio driver uses the following flags to keep track of the current state of the radio and IRQ eve...
Definition at86rf215.c:144
#define CLOCK_SECOND
A second, measured in system clock time.
Definition clock.h:105
void etimer_reset(struct etimer *et)
Reset an event timer with the same interval as was previously set.
Definition etimer.c:192
void etimer_stop(struct etimer *et)
Stop a pending event timer.
Definition etimer.c:237
void etimer_set(struct etimer *et, clock_time_t interval)
Set an event timer.
Definition etimer.c:177
static void stimer_set(struct stimer *t, unsigned long interval)
Set a timer.
Definition stimer.h:100
static unsigned long stimer_remaining(struct stimer *t)
The time until the timer expires.
Definition stimer.h:121
unsigned long stimer_elapsed(struct stimer *t)
The time elapsed since the timer started.
Definition stimer.c:125
bool stimer_expired(struct stimer *t)
Check if a timer has expired.
Definition stimer.c:109
void timer_set(struct timer *t, clock_time_t interval)
Set a timer.
Definition timer.c:64
bool timer_expired(struct timer *t)
Check if a timer has expired.
Definition timer.c:123
void uip_nd6_ns_output(const uip_ipaddr_t *src, const uip_ipaddr_t *dest, uip_ipaddr_t *tgt)
Send a neighbor solicitation, send a Neighbor Advertisement.
#define uip_create_linklocal_allrouters_mcast(a)
set IP address a to the link local all-routers multicast address
Definition uip.h:1777
#define uip_create_unspecified(a)
set IP address a to unspecified
Definition uip.h:1771
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)
Generic loop routine on an abstract data structure, which generalizes all data structures used in DS6...
Definition uip-ds6.c:226
uint8_t get_match_length(uip_ipaddr_t *src, uip_ipaddr_t *dst)
Get the number of matching bits of two addresses.
Definition uip-ds6.c:602
#define UIP_ND6_MAX_RTR_SOLICITATION_DELAY
Maximum router solicitation delay.
Definition uip-nd6.h:64
void uip_ds6_periodic(void)
Periodic processing of data structures.
Definition uip-ds6.c:176
const uip_ip6addr_t * uip_ds6_default_prefix()
Retrieve the Default IPv6 prefix.
Definition uip-ds6.c:103
uip_lladdr_t uip_lladdr
Host L2 address.
Definition uip6.c:107
#define uip_is_addr_mcast_routable(a)
is address a routable multicast address.
Definition uip.h:1888
void uip_ds6_dad(uip_ds6_addr_t *addr)
Perform Duplicate Address Selection on one address.
Definition uip-ds6.c:629
#define uip_is_addr_unspecified(a)
Is IPv6 address a the unspecified address a is of type uip_ipaddr_t.
Definition uip.h:1725
void uip_ds6_init(void)
Initialize data structures.
Definition uip-ds6.c:115
void uip_ds6_send_rs(void)
Send periodic RS to find router.
Definition uip-ds6.c:724
#define UIP_LLADDR_LEN
802.15.4 address
Definition uip.h:145
#define UIP_DS6_PERIOD
General DS6 definitions.
Definition uip-ds6.h:169
struct etimer uip_ds6_timer_periodic
Timer for maintenance of data structures.
Definition uip-ds6.c:59
void uip_nd6_rs_output(void)
Neighbor Solicitation Processing.
Definition uip-nd6.c:800
#define UIP_ND6_RTR_SOLICITATION_INTERVAL
Router solicitation interval.
Definition uip-nd6.h:70
#define uip_is_addr_mcast(a)
is address a multicast address, see RFC 4291 a is of type uip_ipaddr_t*
Definition uip.h:1860
#define UIP_ND6_DEF_MAXDADNS
Do not try DAD when using EUI-64 as allowed by draft-ietf-6lowpan-nd-15 section 8....
Definition uip-nd6.h:144
uip_ds6_addr_t * uip_ds6_addr_add(uip_ipaddr_t *ipaddr, unsigned long vlifetime, uint8_t type)
Add a unicast address to the interface.
Definition uip-ds6.c:351
void uip_ds6_neighbor_periodic(void)
The housekeeping function called periodically.
void uip_ds6_set_default_prefix(const uip_ip6addr_t *prefix)
Set the Default IPv6 prefix.
Definition uip-ds6.c:109
int uip_ds6_dad_failed(uip_ds6_addr_t *addr)
Callback when DAD failed.
Definition uip-ds6.c:657
static uint8_t rscount
number of rs already sent
Definition uip-ds6.c:69
#define uip_create_solicited_node(a, b)
put in b the solicited node address corresponding to address a both a and b are of type uip_ipaddr_t*
Definition uip.h:1804
struct etimer uip_ds6_timer_rs
RS timer, to schedule RS sending.
Definition uip-ds6.c:68
#define uip_is_addr_linklocal(a)
is addr (a) a link local unicast address, see RFC 4291 i.e.
Definition uip.h:1766
void uip_ds6_select_src(uip_ipaddr_t *src, uip_ipaddr_t *dst)
Source address selection, see RFC 3484.
Definition uip-ds6.c:529
void uip_ds6_set_addr_iid(uip_ipaddr_t *ipaddr, const uip_lladdr_t *lladdr)
set the last 64 bits of an IP address based on the MAC address
Definition uip-ds6.c:567
void uip_ds6_set_lladdr_from_iid(uip_lladdr_t *lladdr, const uip_ipaddr_t *ipaddr)
Build a link-layer address from an IPv6 address based on its UUID64.
Definition uip-ds6.c:588
uip_ds6_prefix_t uip_ds6_prefix_list[UIP_DS6_PREFIX_NB]
Prefix list.
Definition uip-ds6.c:75
#define UIP_ND6_MAX_RTR_SOLICITATIONS
Maximum router solicitations.
Definition uip-nd6.h:76
#define ADDR_TENTATIVE
Possible states for the an address (RFC 4862)
Definition uip-ds6.h:156
uip_ds6_netif_t uip_ds6_if
The single interface.
Definition uip-ds6.c:74
#define uip_create_linklocal_allnodes_mcast(a)
set IP address a to the link local all-nodes multicast address
Definition uip.h:1774
uint32_t uip_ds6_compute_reachable_time(void)
Compute the reachable time based on base reachable time, see RFC 4861.
Definition uip-ds6.c:744
#define uip_ip6addr(addr, addr0, addr1, addr2, addr3, addr4, addr5, addr6, addr7)
Construct an IPv6 address from eight 16-bit words.
Definition uip.h:912
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
Definition uip.h:969
uint16_t uip_len
The length of the packet in the uip_buf buffer.
Definition uip6.c:159
#define UIP_TTL
The IP TTL (time to live) of IP packets sent by uIP.
Definition uipopt.h:125
#define UIP_LINK_MTU
The maximum transmission unit at the IP layer.
Definition uipopt.h:145
Header file for the logging system.
Header file for generating non-cryptographic random numbers.
A timer.
Definition etimer.h:79
A timer.
Definition stimer.h:83
Anycast address
Definition uip-ds6.h:219
Unicast address structure.
Definition uip-ds6.h:205
Generic type for a DS6, to use a common loop though all DS.
Definition uip-ds6.h:250
A multicast address.
Definition uip-ds6.h:225
Interface structure (contains all the interface variables)
Definition uip-ds6.h:231
A prefix list entry.
Definition uip-ds6.h:195
IPv6 Neighbor cache (link-layer/IPv6 address mapping)
Header file for IPv6-related data structures.
This header file contains configuration directives for uIPv6 multicast support.
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
Definition uip-nd6.c:116
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Definition uip-nd6.c:107
Header file for IPv6 Neighbor discovery (RFC 4861)