Contiki 3.x
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 uip6
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 <stdlib.h>
47 #include <stddef.h>
48 #include "lib/random.h"
49 #include "net/ipv6/uip-nd6.h"
50 #include "net/ipv6/uip-ds6.h"
51 #include "net/ip/uip-packetqueue.h"
52 
53 #define DEBUG DEBUG_NONE
54 #include "net/ip/uip-debug.h"
55 
56 struct etimer uip_ds6_timer_periodic; /**< Timer for maintenance of data structures */
57 
58 #if UIP_CONF_ROUTER
59 struct stimer uip_ds6_timer_ra; /**< RA timer, to schedule RA sending */
60 #if UIP_ND6_SEND_RA
61 static uint8_t racount; /**< number of RA already sent */
62 static uint16_t rand_time; /**< random time value for timers */
63 #endif
64 #else /* UIP_CONF_ROUTER */
65 struct etimer uip_ds6_timer_rs; /**< RS timer, to schedule RS sending */
66 static uint8_t rscount; /**< 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; /**< The single interface */
72 uip_ds6_prefix_t uip_ds6_prefix_list[UIP_DS6_PREFIX_NB]; /**< Prefix list */
73 
74 /* Used by Cooja to enable extraction of addresses from memory.*/
75 uint8_t uip_ds6_addr_size;
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 #if UIP_DS6_AADDR_NB
87 static uip_ds6_aaddr_t *locaaddr;
88 #endif /* UIP_DS6_AADDR_NB */
89 static uip_ds6_prefix_t *locprefix;
90 
91 /*---------------------------------------------------------------------------*/
92 void
94 {
95 
96  uip_ds6_neighbors_init();
97  uip_ds6_route_init();
98 
99  PRINTF("Init of IPv6 data structures\n");
100  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",
101  NBR_TABLE_MAX_NEIGHBORS, UIP_DS6_DEFRT_NB, UIP_DS6_PREFIX_NB, UIP_DS6_ROUTE_NB,
102  UIP_DS6_ADDR_NB, UIP_DS6_MADDR_NB, UIP_DS6_AADDR_NB);
103  memset(uip_ds6_prefix_list, 0, sizeof(uip_ds6_prefix_list));
104  memset(&uip_ds6_if, 0, sizeof(uip_ds6_if));
105  uip_ds6_addr_size = sizeof(struct uip_ds6_addr);
106  uip_ds6_netif_addr_list_offset = offsetof(struct uip_ds6_netif, addr_list);
107 
108  /* Set interface parameters */
109  uip_ds6_if.link_mtu = UIP_LINK_MTU;
110  uip_ds6_if.cur_hop_limit = UIP_TTL;
111  uip_ds6_if.base_reachable_time = UIP_ND6_REACHABLE_TIME;
112  uip_ds6_if.reachable_time = uip_ds6_compute_reachable_time();
113  uip_ds6_if.retrans_timer = UIP_ND6_RETRANS_TIMER;
114  uip_ds6_if.maxdadns = UIP_ND6_DEF_MAXDADNS;
115 
116  /* Create link local address, prefix, multicast addresses, anycast addresses */
117  uip_create_linklocal_prefix(&loc_fipaddr);
118 #if UIP_CONF_ROUTER
119  uip_ds6_prefix_add(&loc_fipaddr, UIP_DEFAULT_PREFIX_LEN, 0, 0, 0, 0);
120 #else /* UIP_CONF_ROUTER */
121  uip_ds6_prefix_add(&loc_fipaddr, UIP_DEFAULT_PREFIX_LEN, 0);
122 #endif /* UIP_CONF_ROUTER */
123  uip_ds6_set_addr_iid(&loc_fipaddr, &uip_lladdr);
124  uip_ds6_addr_add(&loc_fipaddr, 0, ADDR_AUTOCONF);
125 
127  uip_ds6_maddr_add(&loc_fipaddr);
128 #if UIP_CONF_ROUTER
130  uip_ds6_maddr_add(&loc_fipaddr);
131 #if UIP_ND6_SEND_RA
132  stimer_set(&uip_ds6_timer_ra, 2); /* wait to have a link local IP address */
133 #endif /* UIP_ND6_SEND_RA */
134 #else /* UIP_CONF_ROUTER */
137  CLOCK_SECOND));
138 #endif /* UIP_CONF_ROUTER */
140 
141  return;
142 }
143 
144 
145 /*---------------------------------------------------------------------------*/
146 void
148 {
149 
150  /* Periodic processing on unicast addresses */
151  for(locaddr = uip_ds6_if.addr_list;
152  locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
153  if(locaddr->isused) {
154  if((!locaddr->isinfinite) && (stimer_expired(&locaddr->vlifetime))) {
155  uip_ds6_addr_rm(locaddr);
156 #if UIP_ND6_DEF_MAXDADNS > 0
157  } else if((locaddr->state == ADDR_TENTATIVE)
158  && (locaddr->dadnscount <= uip_ds6_if.maxdadns)
159  && (timer_expired(&locaddr->dadtimer))
160  && (uip_len == 0)) {
161  uip_ds6_dad(locaddr);
162 #endif /* UIP_ND6_DEF_MAXDADNS > 0 */
163  }
164  }
165  }
166 
167  /* Periodic processing on default routers */
168  uip_ds6_defrt_periodic();
169  /* for(locdefrt = uip_ds6_defrt_list;
170  locdefrt < uip_ds6_defrt_list + UIP_DS6_DEFRT_NB; locdefrt++) {
171  if((locdefrt->isused) && (!locdefrt->isinfinite) &&
172  (stimer_expired(&(locdefrt->lifetime)))) {
173  uip_ds6_defrt_rm(locdefrt);
174  }
175  }*/
176 
177 #if !UIP_CONF_ROUTER
178  /* Periodic processing on prefixes */
179  for(locprefix = uip_ds6_prefix_list;
180  locprefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB;
181  locprefix++) {
182  if(locprefix->isused && !locprefix->isinfinite
183  && stimer_expired(&(locprefix->vlifetime))) {
184  uip_ds6_prefix_rm(locprefix);
185  }
186  }
187 #endif /* !UIP_CONF_ROUTER */
188 
189 #if UIP_ND6_SEND_NA
190  uip_ds6_neighbor_periodic();
191 #endif /* UIP_ND6_SEND_RA */
192 
193 #if UIP_CONF_ROUTER && UIP_ND6_SEND_RA
194  /* Periodic RA sending */
195  if(stimer_expired(&uip_ds6_timer_ra) && (uip_len == 0)) {
196  uip_ds6_send_ra_periodic();
197  }
198 #endif /* UIP_CONF_ROUTER && UIP_ND6_SEND_RA */
200  return;
201 }
202 
203 /*---------------------------------------------------------------------------*/
204 uint8_t
206  uint16_t elementsize, uip_ipaddr_t *ipaddr,
207  uint8_t ipaddrlen, uip_ds6_element_t **out_element)
208 {
209  uip_ds6_element_t *element;
210 
211  *out_element = NULL;
212 
213  for(element = list;
214  element <
215  (uip_ds6_element_t *)((uint8_t *)list + (size * elementsize));
216  element = (uip_ds6_element_t *)((uint8_t *)element + elementsize)) {
217  if(element->isused) {
218  if(uip_ipaddr_prefixcmp(&element->ipaddr, ipaddr, ipaddrlen)) {
219  *out_element = element;
220  return FOUND;
221  }
222  } else {
223  *out_element = element;
224  }
225  }
226 
227  return *out_element != NULL ? FREESPACE : NOSPACE;
228 }
229 
230 /*---------------------------------------------------------------------------*/
231 #if UIP_CONF_ROUTER
232 /*---------------------------------------------------------------------------*/
234 uip_ds6_prefix_add(uip_ipaddr_t *ipaddr, uint8_t ipaddrlen,
235  uint8_t advertise, uint8_t flags, unsigned long vtime,
236  unsigned long ptime)
237 {
239  ((uip_ds6_element_t *)uip_ds6_prefix_list, UIP_DS6_PREFIX_NB,
240  sizeof(uip_ds6_prefix_t), ipaddr, ipaddrlen,
241  (uip_ds6_element_t **)&locprefix) == FREESPACE) {
242  locprefix->isused = 1;
243  uip_ipaddr_copy(&locprefix->ipaddr, ipaddr);
244  locprefix->length = ipaddrlen;
245  locprefix->advertise = advertise;
246  locprefix->l_a_reserved = flags;
247  locprefix->vlifetime = vtime;
248  locprefix->plifetime = ptime;
249  PRINTF("Adding prefix ");
250  PRINT6ADDR(&locprefix->ipaddr);
251  PRINTF("length %u, flags %x, Valid lifetime %lx, Preffered lifetime %lx\n",
252  ipaddrlen, flags, vtime, ptime);
253  return locprefix;
254  } else {
255  PRINTF("No more space in Prefix list\n");
256  }
257  return NULL;
258 }
259 
260 
261 #else /* UIP_CONF_ROUTER */
263 uip_ds6_prefix_add(uip_ipaddr_t *ipaddr, uint8_t ipaddrlen,
264  unsigned long interval)
265 {
267  ((uip_ds6_element_t *)uip_ds6_prefix_list, UIP_DS6_PREFIX_NB,
268  sizeof(uip_ds6_prefix_t), ipaddr, ipaddrlen,
269  (uip_ds6_element_t **)&locprefix) == FREESPACE) {
270  locprefix->isused = 1;
271  uip_ipaddr_copy(&locprefix->ipaddr, ipaddr);
272  locprefix->length = ipaddrlen;
273  if(interval != 0) {
274  stimer_set(&(locprefix->vlifetime), interval);
275  locprefix->isinfinite = 0;
276  } else {
277  locprefix->isinfinite = 1;
278  }
279  PRINTF("Adding prefix ");
280  PRINT6ADDR(&locprefix->ipaddr);
281  PRINTF("length %u, vlifetime %lu\n", ipaddrlen, interval);
282  return locprefix;
283  }
284  return NULL;
285 }
286 #endif /* UIP_CONF_ROUTER */
287 
288 /*---------------------------------------------------------------------------*/
289 void
290 uip_ds6_prefix_rm(uip_ds6_prefix_t *prefix)
291 {
292  if(prefix != NULL) {
293  prefix->isused = 0;
294  }
295  return;
296 }
297 /*---------------------------------------------------------------------------*/
299 uip_ds6_prefix_lookup(uip_ipaddr_t *ipaddr, uint8_t ipaddrlen)
300 {
301  if(uip_ds6_list_loop((uip_ds6_element_t *)uip_ds6_prefix_list,
302  UIP_DS6_PREFIX_NB, sizeof(uip_ds6_prefix_t),
303  ipaddr, ipaddrlen,
304  (uip_ds6_element_t **)&locprefix) == FOUND) {
305  return locprefix;
306  }
307  return NULL;
308 }
309 
310 /*---------------------------------------------------------------------------*/
311 uint8_t
312 uip_ds6_is_addr_onlink(uip_ipaddr_t *ipaddr)
313 {
314  for(locprefix = uip_ds6_prefix_list;
315  locprefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; locprefix++) {
316  if(locprefix->isused &&
317  uip_ipaddr_prefixcmp(&locprefix->ipaddr, ipaddr, locprefix->length)) {
318  return 1;
319  }
320  }
321  return 0;
322 }
323 
324 /*---------------------------------------------------------------------------*/
326 uip_ds6_addr_add(uip_ipaddr_t *ipaddr, unsigned long vlifetime, uint8_t type)
327 {
329  ((uip_ds6_element_t *)uip_ds6_if.addr_list, UIP_DS6_ADDR_NB,
330  sizeof(uip_ds6_addr_t), ipaddr, 128,
331  (uip_ds6_element_t **)&locaddr) == FREESPACE) {
332  locaddr->isused = 1;
333  uip_ipaddr_copy(&locaddr->ipaddr, ipaddr);
334  locaddr->type = type;
335  if(vlifetime == 0) {
336  locaddr->isinfinite = 1;
337  } else {
338  locaddr->isinfinite = 0;
339  stimer_set(&(locaddr->vlifetime), vlifetime);
340  }
341 #if UIP_ND6_DEF_MAXDADNS > 0
342  locaddr->state = ADDR_TENTATIVE;
343  timer_set(&locaddr->dadtimer,
345  CLOCK_SECOND));
346  locaddr->dadnscount = 0;
347 #else /* UIP_ND6_DEF_MAXDADNS > 0 */
348  locaddr->state = ADDR_PREFERRED;
349 #endif /* UIP_ND6_DEF_MAXDADNS > 0 */
350  uip_create_solicited_node(ipaddr, &loc_fipaddr);
351  uip_ds6_maddr_add(&loc_fipaddr);
352  return locaddr;
353  }
354  return NULL;
355 }
356 
357 /*---------------------------------------------------------------------------*/
358 void
359 uip_ds6_addr_rm(uip_ds6_addr_t *addr)
360 {
361  if(addr != NULL) {
362  uip_create_solicited_node(&addr->ipaddr, &loc_fipaddr);
363  if((locmaddr = uip_ds6_maddr_lookup(&loc_fipaddr)) != NULL) {
364  uip_ds6_maddr_rm(locmaddr);
365  }
366  addr->isused = 0;
367  }
368  return;
369 }
370 
371 /*---------------------------------------------------------------------------*/
373 uip_ds6_addr_lookup(uip_ipaddr_t *ipaddr)
374 {
376  ((uip_ds6_element_t *)uip_ds6_if.addr_list, UIP_DS6_ADDR_NB,
377  sizeof(uip_ds6_addr_t), ipaddr, 128,
378  (uip_ds6_element_t **)&locaddr) == FOUND) {
379  return locaddr;
380  }
381  return NULL;
382 }
383 
384 /*---------------------------------------------------------------------------*/
385 /*
386  * get a link local address -
387  * state = -1 => any address is ok. Otherwise state = desired state of addr.
388  * (TENTATIVE, PREFERRED, DEPRECATED)
389  */
391 uip_ds6_get_link_local(int8_t state)
392 {
393  for(locaddr = uip_ds6_if.addr_list;
394  locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
395  if(locaddr->isused && (state == -1 || locaddr->state == state)
396  && (uip_is_addr_linklocal(&locaddr->ipaddr))) {
397  return locaddr;
398  }
399  }
400  return NULL;
401 }
402 
403 /*---------------------------------------------------------------------------*/
404 /*
405  * get a global address -
406  * state = -1 => any address is ok. Otherwise state = desired state of addr.
407  * (TENTATIVE, PREFERRED, DEPRECATED)
408  */
410 uip_ds6_get_global(int8_t state)
411 {
412  for(locaddr = uip_ds6_if.addr_list;
413  locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
414  if(locaddr->isused && (state == -1 || locaddr->state == state)
415  && !(uip_is_addr_linklocal(&locaddr->ipaddr))) {
416  return locaddr;
417  }
418  }
419  return NULL;
420 }
421 
422 /*---------------------------------------------------------------------------*/
424 uip_ds6_maddr_add(const uip_ipaddr_t *ipaddr)
425 {
427  ((uip_ds6_element_t *)uip_ds6_if.maddr_list, UIP_DS6_MADDR_NB,
428  sizeof(uip_ds6_maddr_t), (void*)ipaddr, 128,
429  (uip_ds6_element_t **)&locmaddr) == FREESPACE) {
430  locmaddr->isused = 1;
431  uip_ipaddr_copy(&locmaddr->ipaddr, ipaddr);
432  return locmaddr;
433  }
434  return NULL;
435 }
436 
437 /*---------------------------------------------------------------------------*/
438 void
439 uip_ds6_maddr_rm(uip_ds6_maddr_t *maddr)
440 {
441  if(maddr != NULL) {
442  maddr->isused = 0;
443  }
444  return;
445 }
446 
447 /*---------------------------------------------------------------------------*/
449 uip_ds6_maddr_lookup(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) == FOUND) {
455  return locmaddr;
456  }
457  return NULL;
458 }
459 
460 
461 /*---------------------------------------------------------------------------*/
463 uip_ds6_aaddr_add(uip_ipaddr_t *ipaddr)
464 {
465 #if UIP_DS6_AADDR_NB
467  ((uip_ds6_element_t *)uip_ds6_if.aaddr_list, UIP_DS6_AADDR_NB,
468  sizeof(uip_ds6_aaddr_t), ipaddr, 128,
469  (uip_ds6_element_t **)&locaaddr) == FREESPACE) {
470  locaaddr->isused = 1;
471  uip_ipaddr_copy(&locaaddr->ipaddr, ipaddr);
472  return locaaddr;
473  }
474 #endif /* UIP_DS6_AADDR_NB */
475  return NULL;
476 }
477 
478 /*---------------------------------------------------------------------------*/
479 void
480 uip_ds6_aaddr_rm(uip_ds6_aaddr_t *aaddr)
481 {
482  if(aaddr != NULL) {
483  aaddr->isused = 0;
484  }
485  return;
486 }
487 
488 /*---------------------------------------------------------------------------*/
490 uip_ds6_aaddr_lookup(uip_ipaddr_t *ipaddr)
491 {
492 #if UIP_DS6_AADDR_NB
493  if(uip_ds6_list_loop((uip_ds6_element_t *)uip_ds6_if.aaddr_list,
494  UIP_DS6_AADDR_NB, sizeof(uip_ds6_aaddr_t), ipaddr, 128,
495  (uip_ds6_element_t **)&locaaddr) == FOUND) {
496  return locaaddr;
497  }
498 #endif /* UIP_DS6_AADDR_NB */
499  return NULL;
500 }
501 
502 /*---------------------------------------------------------------------------*/
503 void
504 uip_ds6_select_src(uip_ipaddr_t *src, uip_ipaddr_t *dst)
505 {
506  uint8_t best = 0; /* number of bit in common with best match */
507  uint8_t n = 0;
508  uip_ds6_addr_t *matchaddr = NULL;
509 
510  if(!uip_is_addr_linklocal(dst) && !uip_is_addr_mcast(dst)) {
511  /* find longest match */
512  for(locaddr = uip_ds6_if.addr_list;
513  locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
514  /* Only preferred global (not link-local) addresses */
515  if(locaddr->isused && locaddr->state == ADDR_PREFERRED &&
516  !uip_is_addr_linklocal(&locaddr->ipaddr)) {
517  n = get_match_length(dst, &locaddr->ipaddr);
518  if(n >= best) {
519  best = n;
520  matchaddr = locaddr;
521  }
522  }
523  }
524 #if UIP_IPV6_MULTICAST
525  } else if(uip_is_addr_mcast_routable(dst)) {
526  matchaddr = uip_ds6_get_global(ADDR_PREFERRED);
527 #endif
528  } else {
529  matchaddr = uip_ds6_get_link_local(ADDR_PREFERRED);
530  }
531 
532  /* use the :: (unspecified address) as source if no match found */
533  if(matchaddr == NULL) {
535  } else {
536  uip_ipaddr_copy(src, &matchaddr->ipaddr);
537  }
538 }
539 
540 /*---------------------------------------------------------------------------*/
541 void
542 uip_ds6_set_addr_iid(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr)
543 {
544  /* We consider only links with IEEE EUI-64 identifier or
545  * IEEE 48-bit MAC addresses */
546 #if (UIP_LLADDR_LEN == 8)
547  memcpy(ipaddr->u8 + 8, lladdr, UIP_LLADDR_LEN);
548  ipaddr->u8[8] ^= 0x02;
549 #elif (UIP_LLADDR_LEN == 6)
550  memcpy(ipaddr->u8 + 8, lladdr, 3);
551  ipaddr->u8[11] = 0xff;
552  ipaddr->u8[12] = 0xfe;
553  memcpy(ipaddr->u8 + 13, (uint8_t *)lladdr + 3, 3);
554  ipaddr->u8[8] ^= 0x02;
555 #else
556 #error uip-ds6.c cannot build interface address when UIP_LLADDR_LEN is not 6 or 8
557 #endif
558 }
559 
560 /*---------------------------------------------------------------------------*/
561 uint8_t
562 get_match_length(uip_ipaddr_t *src, uip_ipaddr_t *dst)
563 {
564  uint8_t j, k, x_or;
565  uint8_t len = 0;
566 
567  for(j = 0; j < 16; j++) {
568  if(src->u8[j] == dst->u8[j]) {
569  len += 8;
570  } else {
571  x_or = src->u8[j] ^ dst->u8[j];
572  for(k = 0; k < 8; k++) {
573  if((x_or & 0x80) == 0) {
574  len++;
575  x_or <<= 1;
576  } else {
577  break;
578  }
579  }
580  break;
581  }
582  }
583  return len;
584 }
585 
586 /*---------------------------------------------------------------------------*/
587 #if UIP_ND6_DEF_MAXDADNS > 0
588 void
590 {
591  /* send maxdadns NS for DAD */
592  if(addr->dadnscount < uip_ds6_if.maxdadns) {
593  uip_nd6_ns_output(NULL, NULL, &addr->ipaddr);
594  addr->dadnscount++;
595  timer_set(&addr->dadtimer,
596  uip_ds6_if.retrans_timer / 1000 * CLOCK_SECOND);
597  return;
598  }
599  /*
600  * If we arrive here it means DAD succeeded, otherwise the dad process
601  * would have been interrupted in ds6_dad_ns/na_input
602  */
603  PRINTF("DAD succeeded, ipaddr: ");
604  PRINT6ADDR(&addr->ipaddr);
605  PRINTF("\n");
606 
607  addr->state = ADDR_PREFERRED;
608  return;
609 }
610 
611 /*---------------------------------------------------------------------------*/
612 /*
613  * Calling code must handle when this returns 0 (e.g. link local
614  * address can not be used).
615  */
616 int
618 {
619  if(uip_is_addr_linklocal(&addr->ipaddr)) {
620  PRINTF("Contiki shutdown, DAD for link local address failed\n");
621  return 0;
622  }
623  uip_ds6_addr_rm(addr);
624  return 1;
625 }
626 #endif /*UIP_ND6_DEF_MAXDADNS > 0 */
627 
628 /*---------------------------------------------------------------------------*/
629 #if UIP_CONF_ROUTER
630 #if UIP_ND6_SEND_RA
631 void
632 uip_ds6_send_ra_sollicited(void)
633 {
634  /* We have a pb here: RA timer max possible value is 1800s,
635  * hence we have to use stimers. However, when receiving a RS, we
636  * should delay the reply by a random value between 0 and 500ms timers.
637  * stimers are in seconds, hence we cannot do this. Therefore we just send
638  * the RA (setting the timer to 0 below). We keep the code logic for
639  * the days contiki will support appropriate timers */
640  rand_time = 0;
641  PRINTF("Solicited RA, random time %u\n", rand_time);
642 
643  if(stimer_remaining(&uip_ds6_timer_ra) > rand_time) {
644  if(stimer_elapsed(&uip_ds6_timer_ra) < UIP_ND6_MIN_DELAY_BETWEEN_RAS) {
645  /* Ensure that the RAs are rate limited */
646 /* stimer_set(&uip_ds6_timer_ra, rand_time +
647  UIP_ND6_MIN_DELAY_BETWEEN_RAS -
648  stimer_elapsed(&uip_ds6_timer_ra));
649  */ } else {
650  stimer_set(&uip_ds6_timer_ra, rand_time);
651  }
652  }
653 }
654 
655 /*---------------------------------------------------------------------------*/
656 void
657 uip_ds6_send_ra_periodic(void)
658 {
659  if(racount > 0) {
660  /* send previously scheduled RA */
661  uip_nd6_ra_output(NULL);
662  PRINTF("Sending periodic RA\n");
663  }
664 
665  rand_time = UIP_ND6_MIN_RA_INTERVAL + random_rand() %
666  (uint16_t) (UIP_ND6_MAX_RA_INTERVAL - UIP_ND6_MIN_RA_INTERVAL);
667  PRINTF("Random time 1 = %u\n", rand_time);
668 
669  if(racount < UIP_ND6_MAX_INITIAL_RAS) {
670  if(rand_time > UIP_ND6_MAX_INITIAL_RA_INTERVAL) {
671  rand_time = UIP_ND6_MAX_INITIAL_RA_INTERVAL;
672  PRINTF("Random time 2 = %u\n", rand_time);
673  }
674  racount++;
675  }
676  PRINTF("Random time 3 = %u\n", rand_time);
677  stimer_set(&uip_ds6_timer_ra, rand_time);
678 }
679 
680 #endif /* UIP_ND6_SEND_RA */
681 #else /* UIP_CONF_ROUTER */
682 /*---------------------------------------------------------------------------*/
683 void
685 {
686  if((uip_ds6_defrt_choose() == NULL)
688  PRINTF("Sending RS %u\n", rscount);
690  rscount++;
693  } else {
694  PRINTF("Router found ? (boolean): %u\n",
695  (uip_ds6_defrt_choose() != NULL));
697  }
698  return;
699 }
700 
701 #endif /* UIP_CONF_ROUTER */
702 /*---------------------------------------------------------------------------*/
703 uint32_t
705 {
706  return (uint32_t) (UIP_ND6_MIN_RANDOM_FACTOR
707  (uip_ds6_if.base_reachable_time)) +
708  ((uint16_t) (random_rand() << 8) +
709  (uint16_t) random_rand()) %
710  (uint32_t) (UIP_ND6_MAX_RANDOM_FACTOR(uip_ds6_if.base_reachable_time) -
711  UIP_ND6_MIN_RANDOM_FACTOR(uip_ds6_if.base_reachable_time));
712 }
713 /*---------------------------------------------------------------------------*/
714 
715 /** @}*/
Header file for IPv6 Neighbor discovery (RFC 4861)
uip_len
The length of the packet in the uip_buf buffer.
Definition: tcp_loader.c:75
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
Definition: uip-nd6.c:129
unsigned long stimer_elapsed(struct stimer *t)
The time elapsed since the timer started.
Definition: stimer.c:156
#define UIP_TTL
The IP TTL (time to live) of IP packets sent by uIP.
Definition: uipopt.h:245
static uip_ds6_addr_t * addr
Pointer to a router list entry.
Definition: uip-nd6.c:124
Header file for IPv6-related data structures.
A prefix list entry.
Definition: uip-ds6.h:192
void uip_nd6_rs_output(void)
Send a Router Solicitation.
Definition: uip-nd6.c:801
void uip_ds6_send_rs(void)
Send periodic RS to find router.
Definition: uip-ds6.c:684
uip_ds6_prefix_t uip_ds6_prefix_list[UIP_DS6_PREFIX_NB]
Prefix list.
Definition: uip-ds6.c:72
#define uip_create_unspecified(a)
set IP address a to unspecified
Definition: uip.h:2024
void timer_set(struct timer *t, clock_time_t interval)
Set a timer.
Definition: timer.c:64
int stimer_expired(struct stimer *t)
Check if a timer has expired.
Definition: stimer.c:124
void etimer_set(struct etimer *et, clock_time_t interval)
Set an event timer.
Definition: etimer.c:177
A timer.
Definition: etimer.h:76
#define UIP_LLADDR_LEN
Link layer address length.
Definition: uip.h:151
int uip_ds6_dad_failed(uip_ds6_addr_t *addr)
Callback when DAD failed.
Definition: uip-ds6.c:617
#define UIP_ND6_MAX_RTR_SOLICITATION_DELAY
Maximum router solicitation delay.
Definition: uip-nd6.h:63
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
Definition: uip.h:1027
#define uip_is_addr_mcast_routable(a)
is address a routable multicast address.
Definition: uip.h:2131
#define uip_is_addr_mcast(a)
is address a multicast address, see RFC 3513 a is of type uip_ipaddr_t*
Definition: uip.h:2103
void etimer_stop(struct etimer *et)
Stop a pending event timer.
Definition: etimer.c:243
#define uip_create_linklocal_allnodes_mcast(a)
set IP address a to the link local all-nodes multicast address
Definition: uip.h:2027
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:205
struct etimer uip_ds6_timer_periodic
Timer for maintenance of data structures.
Definition: uip-ds6.c:56
void uip_ds6_select_src(uip_ipaddr_t *src, uip_ipaddr_t *dst)
Source address selection, see RFC 3484.
Definition: uip-ds6.c:504
#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:2057
Unicast address structure.
Definition: uip-ds6.h:202
#define UIP_ND6_RTR_SOLICITATION_INTERVAL
Router solicitation interval.
Definition: uip-nd6.h:65
uint32_t uip_ds6_compute_reachable_time(void)
Compute the reachable time based on base reachable time, see RFC 4861.
Definition: uip-ds6.c:704
Interface structure (contains all the interface variables)
Definition: uip-ds6.h:242
#define uip_create_linklocal_allrouters_mcast(a)
set IP address a to the link local all-routers multicast address
Definition: uip.h:2030
static uint8_t rscount
number of rs already sent
Definition: uip-ds6.c:66
#define NULL
The null pointer.
struct etimer uip_ds6_timer_rs
RS timer, to schedule RS sending.
Definition: uip-ds6.c:65
802.3 address
Definition: uip.h:129
unsigned long stimer_remaining(struct stimer *t)
The time until the timer expires.
Definition: stimer.c:140
void stimer_set(struct stimer *t, unsigned long interval)
Set a timer.
Definition: stimer.c:67
unsigned short random_rand(void)
Generates a new random number using the cc2538 RNG.
Definition: random.c:47
void uip_ds6_periodic(void)
Periodic processing of data structures.
Definition: uip-ds6.c:147
#define UIP_ND6_MAX_RTR_SOLICITATIONS
Maximum router solicitations.
Definition: uip-nd6.h:67
#define ADDR_TENTATIVE
Possible states for the an address (RFC 4862)
Definition: uip-ds6.h:153
#define CLOCK_SECOND
A second, measured in system clock time.
Definition: clock.h:82
A multicast address.
Definition: uip-ds6.h:222
A timer.
Definition: stimer.h:81
void uip_ds6_dad(uip_ds6_addr_t *addr)
Perform Duplicate Address Selection on one address.
Definition: uip-ds6.c:589
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:326
void uip_nd6_ns_output(uip_ipaddr_t *src, uip_ipaddr_t *dest, uip_ipaddr_t *tgt)
Send a neighbor solicitation, send a Neighbor Advertisement.
Definition: uip-nd6.c:352
A set of debugging macros for the IP stack
CCIF uip_lladdr_t uip_lladdr
Host L2 address.
Definition: uip.c:118
void uip_ds6_init(void)
Initialize data structures.
Definition: uip-ds6.c:93
#define UIP_DS6_PERIOD
General DS6 definitions.
Definition: uip-ds6.h:166
#define uip_is_addr_linklocal(a)
is addr (a) a link local unicast address, see RFC3513 i.e.
Definition: uip.h:2019
uip_ds6_netif_t uip_ds6_if
The single interface.
Definition: uip-ds6.c:71
Anycast address.
Definition: uip-ds6.h:216
Generic type for a DS6, to use a common loop though all DS.
Definition: uip-ds6.h:261
#define UIP_LINK_MTU
The maximum transmission unit at the IP Layer.
Definition: uipopt.h:283
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:562
void uip_ds6_set_addr_iid(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr)
set the last 64 bits of an IP address based on the MAC address
Definition: uip-ds6.c:542
void etimer_reset(struct etimer *et)
Reset an event timer with the same interval as was previously set.
Definition: etimer.c:192
int timer_expired(struct timer *t)
Check if a timer has expired.
Definition: timer.c:122
#define UIP_ND6_DEF_MAXDADNS
Do not try DAD when using EUI-64 as allowed by draft-ietf-6lowpan-nd-15 section 8.2.
Definition: uip-nd6.h:112