Contiki-Inga 3.x
uip-ds6.c
Go to the documentation of this file.
1 /**
2  * \addtogroup uip6
3  * @{
4  */
5 
6 /**
7  * \file
8  * IPv6 data structures handling functions.
9  * Comprises part of the Neighbor discovery (RFC 4861)
10  * and auto configuration (RFC 4862) state machines.
11  * \author Mathilde Durvy <mdurvy@cisco.com>
12  * \author Julien Abeille <jabeille@cisco.com>
13  */
14 /*
15  * Copyright (c) 2006, Swedish Institute of Computer Science.
16  * All rights reserved.
17  *
18  * Redistribution and use in source and binary forms, with or without
19  * modification, are permitted provided that the following conditions
20  * are met:
21  * 1. Redistributions of source code must retain the above copyright
22  * notice, this list of conditions and the following disclaimer.
23  * 2. Redistributions in binary form must reproduce the above copyright
24  * notice, this list of conditions and the following disclaimer in the
25  * documentation and/or other materials provided with the distribution.
26  * 3. Neither the name of the Institute nor the names of its contributors
27  * may be used to endorse or promote products derived from this software
28  * without specific prior written permission.
29  *
30  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
31  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
34  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40  * SUCH DAMAGE.
41  *
42  */
43 #include <string.h>
44 #include <stdlib.h>
45 #include <stddef.h>
46 #include "lib/random.h"
47 #include "net/ipv6/uip-nd6.h"
48 #include "net/ipv6/uip-ds6.h"
49 #include "net/ip/uip-packetqueue.h"
50 
51 #if UIP_CONF_IPV6
52 
53 #define DEBUG DEBUG_PRINT
54 #include "net/ip/uip-debug.h"
55 
56 struct etimer uip_ds6_timer_periodic; /** \brief Timer for maintenance of data structures */
57 
58 #if UIP_CONF_ROUTER
59 struct stimer uip_ds6_timer_ra; /** \brief RA timer, to schedule RA sending */
60 #if UIP_ND6_SEND_RA
61 static uint8_t racount; /** \brief number of RA already sent */
62 static uint16_t rand_time; /** \brief random time value for timers */
63 #endif
64 #else /* UIP_CONF_ROUTER */
65 struct etimer uip_ds6_timer_rs; /** \brief RS timer, to schedule RS sending */
66 static uint8_t rscount; /** \brief number of rs already sent */
67 #endif /* UIP_CONF_ROUTER */
68 
69 /** \name "DS6" Data structures */
70 /** @{ */
71 uip_ds6_netif_t uip_ds6_if; /** \brief The single interface */
72 uip_ds6_prefix_t uip_ds6_prefix_list[UIP_DS6_PREFIX_NB]; /** \brief Prefix list */
73 
74 /* Used by Cooja to enable extraction of addresses from memory.*/
76 uint8_t uip_ds6_netif_addr_list_offset;
77 
78 /** @} */
79 
80 /* "full" (as opposed to pointer) ip address used in this file, */
81 static uip_ipaddr_t loc_fipaddr;
82 
83 /* Pointers used in this file */
84 static uip_ds6_addr_t *locaddr;
85 static uip_ds6_maddr_t *locmaddr;
86 static uip_ds6_aaddr_t *locaaddr;
87 static uip_ds6_prefix_t *locprefix;
88 
89 /*---------------------------------------------------------------------------*/
90 void
92 {
93 
96 
97  PRINTF("Init of IPv6 data structures\n");
98  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",
99  NBR_TABLE_MAX_NEIGHBORS, UIP_DS6_DEFRT_NB, UIP_DS6_PREFIX_NB, UIP_DS6_ROUTE_NB,
100  UIP_DS6_ADDR_NB, UIP_DS6_MADDR_NB, UIP_DS6_AADDR_NB);
101  memset(uip_ds6_prefix_list, 0, sizeof(uip_ds6_prefix_list));
102  memset(&uip_ds6_if, 0, sizeof(uip_ds6_if));
103  printf("***uip_ds6_if: %d\n", sizeof(uip_ds6_if));
104  uip_ds6_addr_size = sizeof(struct uip_ds6_addr);
105  uip_ds6_netif_addr_list_offset = offsetof(struct uip_ds6_netif, addr_list);
106 
107  /* Set interface parameters */
108  uip_ds6_if.link_mtu = UIP_LINK_MTU;
109  uip_ds6_if.cur_hop_limit = UIP_TTL;
110  uip_ds6_if.base_reachable_time = UIP_ND6_REACHABLE_TIME;
111  uip_ds6_if.reachable_time = uip_ds6_compute_reachable_time();
112  uip_ds6_if.retrans_timer = UIP_ND6_RETRANS_TIMER;
113  uip_ds6_if.maxdadns = UIP_ND6_DEF_MAXDADNS;
114 
115  /* Create link local address, prefix, multicast addresses, anycast addresses */
116  uip_create_linklocal_prefix(&loc_fipaddr);
117 #if UIP_CONF_ROUTER
118  uip_ds6_prefix_add(&loc_fipaddr, UIP_DEFAULT_PREFIX_LEN, 0, 0, 0, 0);
119 #else /* UIP_CONF_ROUTER */
120  uip_ds6_prefix_add(&loc_fipaddr, UIP_DEFAULT_PREFIX_LEN, 0);
121 #endif /* UIP_CONF_ROUTER */
122  uip_ds6_set_addr_iid(&loc_fipaddr, &uip_lladdr);
123  uip_ds6_addr_add(&loc_fipaddr, 0, ADDR_AUTOCONF);
124 
126  uip_ds6_maddr_add(&loc_fipaddr);
127 #if UIP_CONF_ROUTER
129  uip_ds6_maddr_add(&loc_fipaddr);
130 #if UIP_ND6_SEND_RA
131  stimer_set(&uip_ds6_timer_ra, 2); /* wait to have a link local IP address */
132 #endif /* UIP_ND6_SEND_RA */
133 #else /* UIP_CONF_ROUTER */
135  random_rand() % (UIP_ND6_MAX_RTR_SOLICITATION_DELAY *
136  CLOCK_SECOND));
137 #endif /* UIP_CONF_ROUTER */
138  etimer_set(&uip_ds6_timer_periodic, UIP_DS6_PERIOD);
139 
140  return;
141 }
142 
143 
144 /*---------------------------------------------------------------------------*/
145 void
147 {
148 
149  /* Periodic processing on unicast addresses */
150  for(locaddr = uip_ds6_if.addr_list;
151  locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
152  if(locaddr->isused) {
153  if((!locaddr->isinfinite) && (stimer_expired(&locaddr->vlifetime))) {
154  uip_ds6_addr_rm(locaddr);
155 #if UIP_ND6_DEF_MAXDADNS > 0
156  } else if((locaddr->state == ADDR_TENTATIVE)
157  && (locaddr->dadnscount <= uip_ds6_if.maxdadns)
158  && (timer_expired(&locaddr->dadtimer))
159  && (uip_len == 0)) {
160  uip_ds6_dad(locaddr);
161 #endif /* UIP_ND6_DEF_MAXDADNS > 0 */
162  }
163  }
164  }
165 
166  /* Periodic processing on default routers */
168  /* for(locdefrt = uip_ds6_defrt_list;
169  locdefrt < uip_ds6_defrt_list + UIP_DS6_DEFRT_NB; locdefrt++) {
170  if((locdefrt->isused) && (!locdefrt->isinfinite) &&
171  (stimer_expired(&(locdefrt->lifetime)))) {
172  uip_ds6_defrt_rm(locdefrt);
173  }
174  }*/
175 
176 #if !UIP_CONF_ROUTER
177  /* Periodic processing on prefixes */
178  for(locprefix = uip_ds6_prefix_list;
179  locprefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB;
180  locprefix++) {
181  if(locprefix->isused && !locprefix->isinfinite
182  && stimer_expired(&(locprefix->vlifetime))) {
183  uip_ds6_prefix_rm(locprefix);
184  }
185  }
186 #endif /* !UIP_CONF_ROUTER */
187 
189 
190 #if UIP_CONF_ROUTER & UIP_ND6_SEND_RA
191  /* Periodic RA sending */
192  if(stimer_expired(&uip_ds6_timer_ra) && (uip_len == 0)) {
193  uip_ds6_send_ra_periodic();
194  }
195 #endif /* UIP_CONF_ROUTER & UIP_ND6_SEND_RA */
196  etimer_reset(&uip_ds6_timer_periodic);
197  return;
198 }
199 
200 /*---------------------------------------------------------------------------*/
201 uint8_t
203  uint16_t elementsize, uip_ipaddr_t *ipaddr,
204  uint8_t ipaddrlen, uip_ds6_element_t **out_element)
205 {
206  uip_ds6_element_t *element;
207 
208  *out_element = NULL;
209 
210  for(element = list;
211  element <
212  (uip_ds6_element_t *)((uint8_t *)list + (size * elementsize));
213  element = (uip_ds6_element_t *)((uint8_t *)element + elementsize)) {
214  if(element->isused) {
215  if(uip_ipaddr_prefixcmp(&element->ipaddr, ipaddr, ipaddrlen)) {
216  *out_element = element;
217  return FOUND;
218  }
219  } else {
220  *out_element = element;
221  }
222  }
223 
224  return *out_element != NULL ? FREESPACE : NOSPACE;
225 }
226 
227 /*---------------------------------------------------------------------------*/
228 #if UIP_CONF_ROUTER
229 /*---------------------------------------------------------------------------*/
231 uip_ds6_prefix_add(uip_ipaddr_t *ipaddr, uint8_t ipaddrlen,
232  uint8_t advertise, uint8_t flags, unsigned long vtime,
233  unsigned long ptime)
234 {
236  ((uip_ds6_element_t *)uip_ds6_prefix_list, UIP_DS6_PREFIX_NB,
237  sizeof(uip_ds6_prefix_t), ipaddr, ipaddrlen,
238  (uip_ds6_element_t **)&locprefix) == FREESPACE) {
239  locprefix->isused = 1;
240  uip_ipaddr_copy(&locprefix->ipaddr, ipaddr);
241  locprefix->length = ipaddrlen;
242  locprefix->advertise = advertise;
243  locprefix->l_a_reserved = flags;
244  locprefix->vlifetime = vtime;
245  locprefix->plifetime = ptime;
246  PRINTF("Adding prefix ");
247  PRINT6ADDR(&locprefix->ipaddr);
248  PRINTF(" length %u, flags %x, Valid lifetime %lx, Preffered lifetime %lx\n",
249  ipaddrlen, flags, vtime, ptime);
250  return locprefix;
251  } else {
252  PRINTF("No more space in Prefix list\n");
253  }
254  return NULL;
255 }
256 
257 
258 #else /* UIP_CONF_ROUTER */
260 uip_ds6_prefix_add(uip_ipaddr_t *ipaddr, uint8_t ipaddrlen,
261  unsigned long interval)
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  if(interval != 0) {
271  stimer_set(&(locprefix->vlifetime), interval);
272  locprefix->isinfinite = 0;
273  } else {
274  locprefix->isinfinite = 1;
275  }
276  PRINTF("Adding prefix ");
277  PRINT6ADDR(&locprefix->ipaddr);
278  PRINTF("length %u, vlifetime%lu\n", ipaddrlen, interval);
279  }
280  return NULL;
281 }
282 #endif /* UIP_CONF_ROUTER */
283 
284 /*---------------------------------------------------------------------------*/
285 void
286 uip_ds6_prefix_rm(uip_ds6_prefix_t *prefix)
287 {
288  if(prefix != NULL) {
289  prefix->isused = 0;
290  }
291  return;
292 }
293 /*---------------------------------------------------------------------------*/
295 uip_ds6_prefix_lookup(uip_ipaddr_t *ipaddr, uint8_t ipaddrlen)
296 {
297  if(uip_ds6_list_loop((uip_ds6_element_t *)uip_ds6_prefix_list,
298  UIP_DS6_PREFIX_NB, sizeof(uip_ds6_prefix_t),
299  ipaddr, ipaddrlen,
300  (uip_ds6_element_t **)&locprefix) == FOUND) {
301  return locprefix;
302  }
303  return NULL;
304 }
305 
306 /*---------------------------------------------------------------------------*/
307 uint8_t
308 uip_ds6_is_addr_onlink(uip_ipaddr_t *ipaddr)
309 {
310  for(locprefix = uip_ds6_prefix_list;
311  locprefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; locprefix++) {
312  if(locprefix->isused &&
313  uip_ipaddr_prefixcmp(&locprefix->ipaddr, ipaddr, locprefix->length)) {
314  return 1;
315  }
316  }
317  return 0;
318 }
319 
320 /*---------------------------------------------------------------------------*/
322 uip_ds6_addr_add(uip_ipaddr_t *ipaddr, unsigned long vlifetime, uint8_t type)
323 {
325  ((uip_ds6_element_t *)uip_ds6_if.addr_list, UIP_DS6_ADDR_NB,
326  sizeof(uip_ds6_addr_t), ipaddr, 128,
327  (uip_ds6_element_t **)&locaddr) == FREESPACE) {
328  locaddr->isused = 1;
329  uip_ipaddr_copy(&locaddr->ipaddr, ipaddr);
330  locaddr->type = type;
331  if(vlifetime == 0) {
332  locaddr->isinfinite = 1;
333  } else {
334  locaddr->isinfinite = 0;
335  stimer_set(&(locaddr->vlifetime), vlifetime);
336  }
337 #if UIP_ND6_DEF_MAXDADNS > 0
338  locaddr->state = ADDR_TENTATIVE;
339  timer_set(&locaddr->dadtimer,
340  random_rand() % (UIP_ND6_MAX_RTR_SOLICITATION_DELAY *
341  CLOCK_SECOND));
342  locaddr->dadnscount = 0;
343 #else /* UIP_ND6_DEF_MAXDADNS > 0 */
344  locaddr->state = ADDR_PREFERRED;
345 #endif /* UIP_ND6_DEF_MAXDADNS > 0 */
346  uip_create_solicited_node(ipaddr, &loc_fipaddr);
347  uip_ds6_maddr_add(&loc_fipaddr);
348  return locaddr;
349  }
350  return NULL;
351 }
352 
353 /*---------------------------------------------------------------------------*/
354 void
355 uip_ds6_addr_rm(uip_ds6_addr_t *addr)
356 {
357  if(addr != NULL) {
358  uip_create_solicited_node(&addr->ipaddr, &loc_fipaddr);
359  if((locmaddr = uip_ds6_maddr_lookup(&loc_fipaddr)) != NULL) {
360  uip_ds6_maddr_rm(locmaddr);
361  }
362  addr->isused = 0;
363  }
364  return;
365 }
366 
367 /*---------------------------------------------------------------------------*/
369 uip_ds6_addr_lookup(uip_ipaddr_t *ipaddr)
370 {
372  ((uip_ds6_element_t *)uip_ds6_if.addr_list, UIP_DS6_ADDR_NB,
373  sizeof(uip_ds6_addr_t), ipaddr, 128,
374  (uip_ds6_element_t **)&locaddr) == FOUND) {
375  return locaddr;
376  }
377  return NULL;
378 }
379 
380 /*---------------------------------------------------------------------------*/
381 /*
382  * get a link local address -
383  * state = -1 => any address is ok. Otherwise state = desired state of addr.
384  * (TENTATIVE, PREFERRED, DEPRECATED)
385  */
387 uip_ds6_get_link_local(int8_t state)
388 {
389  for(locaddr = uip_ds6_if.addr_list;
390  locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
391  if(locaddr->isused && (state == -1 || locaddr->state == state)
392  && (uip_is_addr_link_local(&locaddr->ipaddr))) {
393  return locaddr;
394  }
395  }
396  return NULL;
397 }
398 
399 /*---------------------------------------------------------------------------*/
400 /*
401  * get a global address -
402  * state = -1 => any address is ok. Otherwise state = desired state of addr.
403  * (TENTATIVE, PREFERRED, DEPRECATED)
404  */
406 uip_ds6_get_global(int8_t state)
407 {
408  for(locaddr = uip_ds6_if.addr_list;
409  locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
410  if(locaddr->isused && (state == -1 || locaddr->state == state)
411  && !(uip_is_addr_link_local(&locaddr->ipaddr))) {
412  return locaddr;
413  }
414  }
415  return NULL;
416 }
417 
418 /*---------------------------------------------------------------------------*/
420 uip_ds6_maddr_add(const uip_ipaddr_t *ipaddr)
421 {
423  ((uip_ds6_element_t *)uip_ds6_if.maddr_list, UIP_DS6_MADDR_NB,
424  sizeof(uip_ds6_maddr_t), (void*)ipaddr, 128,
425  (uip_ds6_element_t **)&locmaddr) == FREESPACE) {
426  locmaddr->isused = 1;
427  uip_ipaddr_copy(&locmaddr->ipaddr, ipaddr);
428  return locmaddr;
429  }
430  return NULL;
431 }
432 
433 /*---------------------------------------------------------------------------*/
434 void
435 uip_ds6_maddr_rm(uip_ds6_maddr_t *maddr)
436 {
437  if(maddr != NULL) {
438  maddr->isused = 0;
439  }
440  return;
441 }
442 
443 /*---------------------------------------------------------------------------*/
445 uip_ds6_maddr_lookup(const uip_ipaddr_t *ipaddr)
446 {
448  ((uip_ds6_element_t *)uip_ds6_if.maddr_list, UIP_DS6_MADDR_NB,
449  sizeof(uip_ds6_maddr_t), (void*)ipaddr, 128,
450  (uip_ds6_element_t **)&locmaddr) == FOUND) {
451  return locmaddr;
452  }
453  return NULL;
454 }
455 
456 
457 /*---------------------------------------------------------------------------*/
459 uip_ds6_aaddr_add(uip_ipaddr_t *ipaddr)
460 {
462  ((uip_ds6_element_t *)uip_ds6_if.aaddr_list, UIP_DS6_AADDR_NB,
463  sizeof(uip_ds6_aaddr_t), ipaddr, 128,
464  (uip_ds6_element_t **)&locaaddr) == FREESPACE) {
465  locaaddr->isused = 1;
466  uip_ipaddr_copy(&locaaddr->ipaddr, ipaddr);
467  return locaaddr;
468  }
469  return NULL;
470 }
471 
472 /*---------------------------------------------------------------------------*/
473 void
474 uip_ds6_aaddr_rm(uip_ds6_aaddr_t *aaddr)
475 {
476  if(aaddr != NULL) {
477  aaddr->isused = 0;
478  }
479  return;
480 }
481 
482 /*---------------------------------------------------------------------------*/
484 uip_ds6_aaddr_lookup(uip_ipaddr_t *ipaddr)
485 {
486  if(uip_ds6_list_loop((uip_ds6_element_t *)uip_ds6_if.aaddr_list,
487  UIP_DS6_AADDR_NB, sizeof(uip_ds6_aaddr_t), ipaddr, 128,
488  (uip_ds6_element_t **)&locaaddr) == FOUND) {
489  return locaaddr;
490  }
491  return NULL;
492 }
493 
494 /*---------------------------------------------------------------------------*/
495 void
496 uip_ds6_select_src(uip_ipaddr_t *src, uip_ipaddr_t *dst)
497 {
498  uint8_t best = 0; /* number of bit in common with best match */
499  uint8_t n = 0;
500  uip_ds6_addr_t *matchaddr = NULL;
501 
502  if(!uip_is_addr_link_local(dst) && !uip_is_addr_mcast(dst)) {
503  /* find longest match */
504  for(locaddr = uip_ds6_if.addr_list;
505  locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
506  /* Only preferred global (not link-local) addresses */
507  if(locaddr->isused && locaddr->state == ADDR_PREFERRED &&
508  !uip_is_addr_link_local(&locaddr->ipaddr)) {
509  n = get_match_length(dst, &locaddr->ipaddr);
510  if(n >= best) {
511  best = n;
512  matchaddr = locaddr;
513  }
514  }
515  }
516 #if UIP_IPV6_MULTICAST
517  } else if(uip_is_addr_mcast_routable(dst)) {
518  matchaddr = uip_ds6_get_global(ADDR_PREFERRED);
519 #endif
520  } else {
521  matchaddr = uip_ds6_get_link_local(ADDR_PREFERRED);
522  }
523 
524  /* use the :: (unspecified address) as source if no match found */
525  if(matchaddr == NULL) {
527  } else {
528  uip_ipaddr_copy(src, &matchaddr->ipaddr);
529  }
530 }
531 
532 /*---------------------------------------------------------------------------*/
533 void
534 uip_ds6_set_addr_iid(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr)
535 {
536  /* We consider only links with IEEE EUI-64 identifier or
537  * IEEE 48-bit MAC addresses */
538 #if (UIP_LLADDR_LEN == 8)
539  memcpy(ipaddr->u8 + 8, lladdr, UIP_LLADDR_LEN);
540  ipaddr->u8[8] ^= 0x02;
541 #elif (UIP_LLADDR_LEN == 6)
542  memcpy(ipaddr->u8 + 8, lladdr, 3);
543  ipaddr->u8[11] = 0xff;
544  ipaddr->u8[12] = 0xfe;
545  memcpy(ipaddr->u8 + 13, (uint8_t *)lladdr + 3, 3);
546  ipaddr->u8[8] ^= 0x02;
547 #else
548 #error uip-ds6.c cannot build interface address when UIP_LLADDR_LEN is not 6 or 8
549 #endif
550 }
551 
552 /*---------------------------------------------------------------------------*/
553 uint8_t
554 get_match_length(uip_ipaddr_t *src, uip_ipaddr_t *dst)
555 {
556  uint8_t j, k, x_or;
557  uint8_t len = 0;
558 
559  for(j = 0; j < 16; j++) {
560  if(src->u8[j] == dst->u8[j]) {
561  len += 8;
562  } else {
563  x_or = src->u8[j] ^ dst->u8[j];
564  for(k = 0; k < 8; k++) {
565  if((x_or & 0x80) == 0) {
566  len++;
567  x_or <<= 1;
568  } else {
569  break;
570  }
571  }
572  break;
573  }
574  }
575  return len;
576 }
577 
578 /*---------------------------------------------------------------------------*/
579 #if UIP_ND6_DEF_MAXDADNS > 0
580 void
581 uip_ds6_dad(uip_ds6_addr_t *addr)
582 {
583  /* send maxdadns NS for DAD */
584  if(addr->dadnscount < uip_ds6_if.maxdadns) {
585  uip_nd6_ns_output(NULL, NULL, &addr->ipaddr);
586  addr->dadnscount++;
587  timer_set(&addr->dadtimer,
588  uip_ds6_if.retrans_timer / 1000 * CLOCK_SECOND);
589  return;
590  }
591  /*
592  * If we arrive here it means DAD succeeded, otherwise the dad process
593  * would have been interrupted in ds6_dad_ns/na_input
594  */
595  PRINTF("DAD succeeded, ipaddr:");
596  PRINT6ADDR(&addr->ipaddr);
597  PRINTF("\n");
598 
599  addr->state = ADDR_PREFERRED;
600  return;
601 }
602 
603 /*---------------------------------------------------------------------------*/
604 /*
605  * Calling code must handle when this returns 0 (e.g. link local
606  * address can not be used).
607  */
608 int
609 uip_ds6_dad_failed(uip_ds6_addr_t *addr)
610 {
611  if(uip_is_addr_link_local(&addr->ipaddr)) {
612  PRINTF("Contiki shutdown, DAD for link local address failed\n");
613  return 0;
614  }
615  uip_ds6_addr_rm(addr);
616  return 1;
617 }
618 #endif /*UIP_ND6_DEF_MAXDADNS > 0 */
619 
620 /*---------------------------------------------------------------------------*/
621 #if UIP_CONF_ROUTER
622 #if UIP_ND6_SEND_RA
623 void
624 uip_ds6_send_ra_sollicited(void)
625 {
626  /* We have a pb here: RA timer max possible value is 1800s,
627  * hence we have to use stimers. However, when receiving a RS, we
628  * should delay the reply by a random value between 0 and 500ms timers.
629  * stimers are in seconds, hence we cannot do this. Therefore we just send
630  * the RA (setting the timer to 0 below). We keep the code logic for
631  * the days contiki will support appropriate timers */
632  rand_time = 0;
633  PRINTF("Solicited RA, random time %u\n", rand_time);
634 
635  if(stimer_remaining(&uip_ds6_timer_ra) > rand_time) {
636  if(stimer_elapsed(&uip_ds6_timer_ra) < UIP_ND6_MIN_DELAY_BETWEEN_RAS) {
637  /* Ensure that the RAs are rate limited */
638 /* stimer_set(&uip_ds6_timer_ra, rand_time +
639  UIP_ND6_MIN_DELAY_BETWEEN_RAS -
640  stimer_elapsed(&uip_ds6_timer_ra));
641  */ } else {
642  stimer_set(&uip_ds6_timer_ra, rand_time);
643  }
644  }
645 }
646 
647 /*---------------------------------------------------------------------------*/
648 void
649 uip_ds6_send_ra_periodic(void)
650 {
651  if(racount > 0) {
652  /* send previously scheduled RA */
653  uip_nd6_ra_output(NULL);
654  PRINTF("Sending periodic RA\n");
655  }
656 
657  rand_time = UIP_ND6_MIN_RA_INTERVAL + random_rand() %
658  (uint16_t) (UIP_ND6_MAX_RA_INTERVAL - UIP_ND6_MIN_RA_INTERVAL);
659  PRINTF("Random time 1 = %u\n", rand_time);
660 
661  if(racount < UIP_ND6_MAX_INITIAL_RAS) {
662  if(rand_time > UIP_ND6_MAX_INITIAL_RA_INTERVAL) {
663  rand_time = UIP_ND6_MAX_INITIAL_RA_INTERVAL;
664  PRINTF("Random time 2 = %u\n", rand_time);
665  }
666  racount++;
667  }
668  PRINTF("Random time 3 = %u\n", rand_time);
669  stimer_set(&uip_ds6_timer_ra, rand_time);
670 }
671 
672 #endif /* UIP_ND6_SEND_RA */
673 #else /* UIP_CONF_ROUTER */
674 /*---------------------------------------------------------------------------*/
675 void
677 {
678  if((uip_ds6_defrt_choose() == NULL)
679  && (rscount < UIP_ND6_MAX_RTR_SOLICITATIONS)) {
680  PRINTF("Sending RS %u\n", rscount);
682  rscount++;
684  UIP_ND6_RTR_SOLICITATION_INTERVAL * CLOCK_SECOND);
685  } else {
686  PRINTF("Router found ? (boolean): %u\n",
687  (uip_ds6_defrt_choose() != NULL));
689  }
690  return;
691 }
692 
693 #endif /* UIP_CONF_ROUTER */
694 /*---------------------------------------------------------------------------*/
695 uint32_t
697 {
698  return (uint32_t) (UIP_ND6_MIN_RANDOM_FACTOR
699  (uip_ds6_if.base_reachable_time)) +
700  ((uint16_t) (random_rand() << 8) +
701  (uint16_t) random_rand()) %
702  (uint32_t) (UIP_ND6_MAX_RANDOM_FACTOR(uip_ds6_if.base_reachable_time) -
703  UIP_ND6_MIN_RANDOM_FACTOR(uip_ds6_if.base_reachable_time));
704 }
705 /*---------------------------------------------------------------------------*/
706 /** @} */
707 #endif /* UIP_CONF_IPV6 */