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  * \file
33  * IPv6 data structures handling functions.
34  * Comprises part of the Neighbor discovery (RFC 4861)
35  * and auto configuration (RFC 4862) state machines.
36  * \author Mathilde Durvy <mdurvy@cisco.com>
37  * \author Julien Abeille <jabeille@cisco.com>
38  */
39 
40 /**
41  * \addtogroup uip6
42  * @{
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 #if UIP_CONF_IPV6
54 
55 #define DEBUG DEBUG_NONE
56 #include "net/ip/uip-debug.h"
57 
58 struct etimer uip_ds6_timer_periodic; /** \brief Timer for maintenance of data structures */
59 
60 #if UIP_CONF_ROUTER
61 struct stimer uip_ds6_timer_ra; /** \brief RA timer, to schedule RA sending */
62 #if UIP_ND6_SEND_RA
63 static uint8_t racount; /** \brief number of RA already sent */
64 static uint16_t rand_time; /** \brief random time value for timers */
65 #endif
66 #else /* UIP_CONF_ROUTER */
67 struct etimer uip_ds6_timer_rs; /** \brief RS timer, to schedule RS sending */
68 static uint8_t rscount; /** \brief number of rs already sent */
69 #endif /* UIP_CONF_ROUTER */
70 
71 /** \name "DS6" Data structures */
72 /** @{ */
73 uip_ds6_netif_t uip_ds6_if; /** \brief The single interface */
74 uip_ds6_prefix_t uip_ds6_prefix_list[UIP_DS6_PREFIX_NB]; /** \brief Prefix list */
75 
76 /* Used by Cooja to enable extraction of addresses from memory.*/
78 uint8_t uip_ds6_netif_addr_list_offset;
79 
80 /** @} */
81 
82 /* "full" (as opposed to pointer) ip address used in this file, */
83 static uip_ipaddr_t loc_fipaddr;
84 
85 /* Pointers used in this file */
86 static uip_ds6_addr_t *locaddr;
87 static uip_ds6_maddr_t *locmaddr;
88 static uip_ds6_aaddr_t *locaaddr;
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 */
136  random_rand() % (UIP_ND6_MAX_RTR_SOLICITATION_DELAY *
137  CLOCK_SECOND));
138 #endif /* UIP_CONF_ROUTER */
139  etimer_set(&uip_ds6_timer_periodic, UIP_DS6_PERIOD);
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  uip_ds6_neighbor_periodic();
190 
191 #if UIP_CONF_ROUTER & UIP_ND6_SEND_RA
192  /* Periodic RA sending */
193  if(stimer_expired(&uip_ds6_timer_ra) && (uip_len == 0)) {
194  uip_ds6_send_ra_periodic();
195  }
196 #endif /* UIP_CONF_ROUTER & UIP_ND6_SEND_RA */
197  etimer_reset(&uip_ds6_timer_periodic);
198  return;
199 }
200 
201 /*---------------------------------------------------------------------------*/
202 uint8_t
204  uint16_t elementsize, uip_ipaddr_t *ipaddr,
205  uint8_t ipaddrlen, uip_ds6_element_t **out_element)
206 {
207  uip_ds6_element_t *element;
208 
209  *out_element = NULL;
210 
211  for(element = list;
212  element <
213  (uip_ds6_element_t *)((uint8_t *)list + (size * elementsize));
214  element = (uip_ds6_element_t *)((uint8_t *)element + elementsize)) {
215  if(element->isused) {
216  if(uip_ipaddr_prefixcmp(&element->ipaddr, ipaddr, ipaddrlen)) {
217  *out_element = element;
218  return FOUND;
219  }
220  } else {
221  *out_element = element;
222  }
223  }
224 
225  return *out_element != NULL ? FREESPACE : NOSPACE;
226 }
227 
228 /*---------------------------------------------------------------------------*/
229 #if UIP_CONF_ROUTER
230 /*---------------------------------------------------------------------------*/
232 uip_ds6_prefix_add(uip_ipaddr_t *ipaddr, uint8_t ipaddrlen,
233  uint8_t advertise, uint8_t flags, unsigned long vtime,
234  unsigned long ptime)
235 {
237  ((uip_ds6_element_t *)uip_ds6_prefix_list, UIP_DS6_PREFIX_NB,
238  sizeof(uip_ds6_prefix_t), ipaddr, ipaddrlen,
239  (uip_ds6_element_t **)&locprefix) == FREESPACE) {
240  locprefix->isused = 1;
241  uip_ipaddr_copy(&locprefix->ipaddr, ipaddr);
242  locprefix->length = ipaddrlen;
243  locprefix->advertise = advertise;
244  locprefix->l_a_reserved = flags;
245  locprefix->vlifetime = vtime;
246  locprefix->plifetime = ptime;
247  PRINTF("Adding prefix ");
248  PRINT6ADDR(&locprefix->ipaddr);
249  PRINTF("length %u, flags %x, Valid lifetime %lx, Preffered lifetime %lx\n",
250  ipaddrlen, flags, vtime, ptime);
251  return locprefix;
252  } else {
253  PRINTF("No more space in Prefix list\n");
254  }
255  return NULL;
256 }
257 
258 
259 #else /* UIP_CONF_ROUTER */
261 uip_ds6_prefix_add(uip_ipaddr_t *ipaddr, uint8_t ipaddrlen,
262  unsigned long interval)
263 {
265  ((uip_ds6_element_t *)uip_ds6_prefix_list, UIP_DS6_PREFIX_NB,
266  sizeof(uip_ds6_prefix_t), ipaddr, ipaddrlen,
267  (uip_ds6_element_t **)&locprefix) == FREESPACE) {
268  locprefix->isused = 1;
269  uip_ipaddr_copy(&locprefix->ipaddr, ipaddr);
270  locprefix->length = ipaddrlen;
271  if(interval != 0) {
272  stimer_set(&(locprefix->vlifetime), interval);
273  locprefix->isinfinite = 0;
274  } else {
275  locprefix->isinfinite = 1;
276  }
277  PRINTF("Adding prefix ");
278  PRINT6ADDR(&locprefix->ipaddr);
279  PRINTF("length %u, vlifetime%lu\n", ipaddrlen, interval);
280  }
281  return NULL;
282 }
283 #endif /* UIP_CONF_ROUTER */
284 
285 /*---------------------------------------------------------------------------*/
286 void
287 uip_ds6_prefix_rm(uip_ds6_prefix_t *prefix)
288 {
289  if(prefix != NULL) {
290  prefix->isused = 0;
291  }
292  return;
293 }
294 /*---------------------------------------------------------------------------*/
296 uip_ds6_prefix_lookup(uip_ipaddr_t *ipaddr, uint8_t ipaddrlen)
297 {
298  if(uip_ds6_list_loop((uip_ds6_element_t *)uip_ds6_prefix_list,
299  UIP_DS6_PREFIX_NB, sizeof(uip_ds6_prefix_t),
300  ipaddr, ipaddrlen,
301  (uip_ds6_element_t **)&locprefix) == FOUND) {
302  return locprefix;
303  }
304  return NULL;
305 }
306 
307 /*---------------------------------------------------------------------------*/
308 uint8_t
309 uip_ds6_is_addr_onlink(uip_ipaddr_t *ipaddr)
310 {
311  for(locprefix = uip_ds6_prefix_list;
312  locprefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; locprefix++) {
313  if(locprefix->isused &&
314  uip_ipaddr_prefixcmp(&locprefix->ipaddr, ipaddr, locprefix->length)) {
315  return 1;
316  }
317  }
318  return 0;
319 }
320 
321 /*---------------------------------------------------------------------------*/
323 uip_ds6_addr_add(uip_ipaddr_t *ipaddr, unsigned long vlifetime, uint8_t type)
324 {
326  ((uip_ds6_element_t *)uip_ds6_if.addr_list, UIP_DS6_ADDR_NB,
327  sizeof(uip_ds6_addr_t), ipaddr, 128,
328  (uip_ds6_element_t **)&locaddr) == FREESPACE) {
329  locaddr->isused = 1;
330  uip_ipaddr_copy(&locaddr->ipaddr, ipaddr);
331  locaddr->type = type;
332  if(vlifetime == 0) {
333  locaddr->isinfinite = 1;
334  } else {
335  locaddr->isinfinite = 0;
336  stimer_set(&(locaddr->vlifetime), vlifetime);
337  }
338 #if UIP_ND6_DEF_MAXDADNS > 0
339  locaddr->state = ADDR_TENTATIVE;
340  timer_set(&locaddr->dadtimer,
341  random_rand() % (UIP_ND6_MAX_RTR_SOLICITATION_DELAY *
342  CLOCK_SECOND));
343  locaddr->dadnscount = 0;
344 #else /* UIP_ND6_DEF_MAXDADNS > 0 */
345  locaddr->state = ADDR_PREFERRED;
346 #endif /* UIP_ND6_DEF_MAXDADNS > 0 */
347  uip_create_solicited_node(ipaddr, &loc_fipaddr);
348  uip_ds6_maddr_add(&loc_fipaddr);
349  return locaddr;
350  }
351  return NULL;
352 }
353 
354 /*---------------------------------------------------------------------------*/
355 void
356 uip_ds6_addr_rm(uip_ds6_addr_t *addr)
357 {
358  if(addr != NULL) {
359  uip_create_solicited_node(&addr->ipaddr, &loc_fipaddr);
360  if((locmaddr = uip_ds6_maddr_lookup(&loc_fipaddr)) != NULL) {
361  uip_ds6_maddr_rm(locmaddr);
362  }
363  addr->isused = 0;
364  }
365  return;
366 }
367 
368 /*---------------------------------------------------------------------------*/
370 uip_ds6_addr_lookup(uip_ipaddr_t *ipaddr)
371 {
373  ((uip_ds6_element_t *)uip_ds6_if.addr_list, UIP_DS6_ADDR_NB,
374  sizeof(uip_ds6_addr_t), ipaddr, 128,
375  (uip_ds6_element_t **)&locaddr) == FOUND) {
376  return locaddr;
377  }
378  return NULL;
379 }
380 
381 /*---------------------------------------------------------------------------*/
382 /*
383  * get a link local address -
384  * state = -1 => any address is ok. Otherwise state = desired state of addr.
385  * (TENTATIVE, PREFERRED, DEPRECATED)
386  */
388 uip_ds6_get_link_local(int8_t state)
389 {
390  for(locaddr = uip_ds6_if.addr_list;
391  locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
392  if(locaddr->isused && (state == -1 || locaddr->state == state)
393  && (uip_is_addr_link_local(&locaddr->ipaddr))) {
394  return locaddr;
395  }
396  }
397  return NULL;
398 }
399 
400 /*---------------------------------------------------------------------------*/
401 /*
402  * get a global address -
403  * state = -1 => any address is ok. Otherwise state = desired state of addr.
404  * (TENTATIVE, PREFERRED, DEPRECATED)
405  */
407 uip_ds6_get_global(int8_t state)
408 {
409  for(locaddr = uip_ds6_if.addr_list;
410  locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
411  if(locaddr->isused && (state == -1 || locaddr->state == state)
412  && !(uip_is_addr_link_local(&locaddr->ipaddr))) {
413  return locaddr;
414  }
415  }
416  return NULL;
417 }
418 
419 /*---------------------------------------------------------------------------*/
421 uip_ds6_maddr_add(const uip_ipaddr_t *ipaddr)
422 {
424  ((uip_ds6_element_t *)uip_ds6_if.maddr_list, UIP_DS6_MADDR_NB,
425  sizeof(uip_ds6_maddr_t), (void*)ipaddr, 128,
426  (uip_ds6_element_t **)&locmaddr) == FREESPACE) {
427  locmaddr->isused = 1;
428  uip_ipaddr_copy(&locmaddr->ipaddr, ipaddr);
429  return locmaddr;
430  }
431  return NULL;
432 }
433 
434 /*---------------------------------------------------------------------------*/
435 void
436 uip_ds6_maddr_rm(uip_ds6_maddr_t *maddr)
437 {
438  if(maddr != NULL) {
439  maddr->isused = 0;
440  }
441  return;
442 }
443 
444 /*---------------------------------------------------------------------------*/
446 uip_ds6_maddr_lookup(const uip_ipaddr_t *ipaddr)
447 {
449  ((uip_ds6_element_t *)uip_ds6_if.maddr_list, UIP_DS6_MADDR_NB,
450  sizeof(uip_ds6_maddr_t), (void*)ipaddr, 128,
451  (uip_ds6_element_t **)&locmaddr) == FOUND) {
452  return locmaddr;
453  }
454  return NULL;
455 }
456 
457 
458 /*---------------------------------------------------------------------------*/
460 uip_ds6_aaddr_add(uip_ipaddr_t *ipaddr)
461 {
463  ((uip_ds6_element_t *)uip_ds6_if.aaddr_list, UIP_DS6_AADDR_NB,
464  sizeof(uip_ds6_aaddr_t), ipaddr, 128,
465  (uip_ds6_element_t **)&locaaddr) == FREESPACE) {
466  locaaddr->isused = 1;
467  uip_ipaddr_copy(&locaaddr->ipaddr, ipaddr);
468  return locaaddr;
469  }
470  return NULL;
471 }
472 
473 /*---------------------------------------------------------------------------*/
474 void
475 uip_ds6_aaddr_rm(uip_ds6_aaddr_t *aaddr)
476 {
477  if(aaddr != NULL) {
478  aaddr->isused = 0;
479  }
480  return;
481 }
482 
483 /*---------------------------------------------------------------------------*/
485 uip_ds6_aaddr_lookup(uip_ipaddr_t *ipaddr)
486 {
487  if(uip_ds6_list_loop((uip_ds6_element_t *)uip_ds6_if.aaddr_list,
488  UIP_DS6_AADDR_NB, sizeof(uip_ds6_aaddr_t), ipaddr, 128,
489  (uip_ds6_element_t **)&locaaddr) == FOUND) {
490  return locaaddr;
491  }
492  return NULL;
493 }
494 
495 /*---------------------------------------------------------------------------*/
496 void
497 uip_ds6_select_src(uip_ipaddr_t *src, uip_ipaddr_t *dst)
498 {
499  uint8_t best = 0; /* number of bit in common with best match */
500  uint8_t n = 0;
501  uip_ds6_addr_t *matchaddr = NULL;
502 
503  if(!uip_is_addr_link_local(dst) && !uip_is_addr_mcast(dst)) {
504  /* find longest match */
505  for(locaddr = uip_ds6_if.addr_list;
506  locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
507  /* Only preferred global (not link-local) addresses */
508  if(locaddr->isused && locaddr->state == ADDR_PREFERRED &&
509  !uip_is_addr_link_local(&locaddr->ipaddr)) {
510  n = get_match_length(dst, &locaddr->ipaddr);
511  if(n >= best) {
512  best = n;
513  matchaddr = locaddr;
514  }
515  }
516  }
517 #if UIP_IPV6_MULTICAST
518  } else if(uip_is_addr_mcast_routable(dst)) {
519  matchaddr = uip_ds6_get_global(ADDR_PREFERRED);
520 #endif
521  } else {
522  matchaddr = uip_ds6_get_link_local(ADDR_PREFERRED);
523  }
524 
525  /* use the :: (unspecified address) as source if no match found */
526  if(matchaddr == NULL) {
528  } else {
529  uip_ipaddr_copy(src, &matchaddr->ipaddr);
530  }
531 }
532 
533 /*---------------------------------------------------------------------------*/
534 void
535 uip_ds6_set_addr_iid(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr)
536 {
537  /* We consider only links with IEEE EUI-64 identifier or
538  * IEEE 48-bit MAC addresses */
539 #if (UIP_LLADDR_LEN == 8)
540  memcpy(ipaddr->u8 + 8, lladdr, UIP_LLADDR_LEN);
541  ipaddr->u8[8] ^= 0x02;
542 #elif (UIP_LLADDR_LEN == 6)
543  memcpy(ipaddr->u8 + 8, lladdr, 3);
544  ipaddr->u8[11] = 0xff;
545  ipaddr->u8[12] = 0xfe;
546  memcpy(ipaddr->u8 + 13, (uint8_t *)lladdr + 3, 3);
547  ipaddr->u8[8] ^= 0x02;
548 #else
549 #error uip-ds6.c cannot build interface address when UIP_LLADDR_LEN is not 6 or 8
550 #endif
551 }
552 
553 /*---------------------------------------------------------------------------*/
554 uint8_t
555 get_match_length(uip_ipaddr_t *src, uip_ipaddr_t *dst)
556 {
557  uint8_t j, k, x_or;
558  uint8_t len = 0;
559 
560  for(j = 0; j < 16; j++) {
561  if(src->u8[j] == dst->u8[j]) {
562  len += 8;
563  } else {
564  x_or = src->u8[j] ^ dst->u8[j];
565  for(k = 0; k < 8; k++) {
566  if((x_or & 0x80) == 0) {
567  len++;
568  x_or <<= 1;
569  } else {
570  break;
571  }
572  }
573  break;
574  }
575  }
576  return len;
577 }
578 
579 /*---------------------------------------------------------------------------*/
580 #if UIP_ND6_DEF_MAXDADNS > 0
581 void
582 uip_ds6_dad(uip_ds6_addr_t *addr)
583 {
584  /* send maxdadns NS for DAD */
585  if(addr->dadnscount < uip_ds6_if.maxdadns) {
586  uip_nd6_ns_output(NULL, NULL, &addr->ipaddr);
587  addr->dadnscount++;
588  timer_set(&addr->dadtimer,
589  uip_ds6_if.retrans_timer / 1000 * CLOCK_SECOND);
590  return;
591  }
592  /*
593  * If we arrive here it means DAD succeeded, otherwise the dad process
594  * would have been interrupted in ds6_dad_ns/na_input
595  */
596  PRINTF("DAD succeeded, ipaddr:");
597  PRINT6ADDR(&addr->ipaddr);
598  PRINTF("\n");
599 
600  addr->state = ADDR_PREFERRED;
601  return;
602 }
603 
604 /*---------------------------------------------------------------------------*/
605 /*
606  * Calling code must handle when this returns 0 (e.g. link local
607  * address can not be used).
608  */
609 int
610 uip_ds6_dad_failed(uip_ds6_addr_t *addr)
611 {
612  if(uip_is_addr_link_local(&addr->ipaddr)) {
613  PRINTF("Contiki shutdown, DAD for link local address failed\n");
614  return 0;
615  }
616  uip_ds6_addr_rm(addr);
617  return 1;
618 }
619 #endif /*UIP_ND6_DEF_MAXDADNS > 0 */
620 
621 /*---------------------------------------------------------------------------*/
622 #if UIP_CONF_ROUTER
623 #if UIP_ND6_SEND_RA
624 void
625 uip_ds6_send_ra_sollicited(void)
626 {
627  /* We have a pb here: RA timer max possible value is 1800s,
628  * hence we have to use stimers. However, when receiving a RS, we
629  * should delay the reply by a random value between 0 and 500ms timers.
630  * stimers are in seconds, hence we cannot do this. Therefore we just send
631  * the RA (setting the timer to 0 below). We keep the code logic for
632  * the days contiki will support appropriate timers */
633  rand_time = 0;
634  PRINTF("Solicited RA, random time %u\n", rand_time);
635 
636  if(stimer_remaining(&uip_ds6_timer_ra) > rand_time) {
637  if(stimer_elapsed(&uip_ds6_timer_ra) < UIP_ND6_MIN_DELAY_BETWEEN_RAS) {
638  /* Ensure that the RAs are rate limited */
639 /* stimer_set(&uip_ds6_timer_ra, rand_time +
640  UIP_ND6_MIN_DELAY_BETWEEN_RAS -
641  stimer_elapsed(&uip_ds6_timer_ra));
642  */ } else {
643  stimer_set(&uip_ds6_timer_ra, rand_time);
644  }
645  }
646 }
647 
648 /*---------------------------------------------------------------------------*/
649 void
650 uip_ds6_send_ra_periodic(void)
651 {
652  if(racount > 0) {
653  /* send previously scheduled RA */
654  uip_nd6_ra_output(NULL);
655  PRINTF("Sending periodic RA\n");
656  }
657 
658  rand_time = UIP_ND6_MIN_RA_INTERVAL + random_rand() %
659  (uint16_t) (UIP_ND6_MAX_RA_INTERVAL - UIP_ND6_MIN_RA_INTERVAL);
660  PRINTF("Random time 1 = %u\n", rand_time);
661 
662  if(racount < UIP_ND6_MAX_INITIAL_RAS) {
663  if(rand_time > UIP_ND6_MAX_INITIAL_RA_INTERVAL) {
664  rand_time = UIP_ND6_MAX_INITIAL_RA_INTERVAL;
665  PRINTF("Random time 2 = %u\n", rand_time);
666  }
667  racount++;
668  }
669  PRINTF("Random time 3 = %u\n", rand_time);
670  stimer_set(&uip_ds6_timer_ra, rand_time);
671 }
672 
673 #endif /* UIP_ND6_SEND_RA */
674 #else /* UIP_CONF_ROUTER */
675 /*---------------------------------------------------------------------------*/
676 void
678 {
679  if((uip_ds6_defrt_choose() == NULL)
680  && (rscount < UIP_ND6_MAX_RTR_SOLICITATIONS)) {
681  PRINTF("Sending RS %u\n", rscount);
683  rscount++;
685  UIP_ND6_RTR_SOLICITATION_INTERVAL * CLOCK_SECOND);
686  } else {
687  PRINTF("Router found ? (boolean): %u\n",
688  (uip_ds6_defrt_choose() != NULL));
690  }
691  return;
692 }
693 
694 #endif /* UIP_CONF_ROUTER */
695 /*---------------------------------------------------------------------------*/
696 uint32_t
698 {
699  return (uint32_t) (UIP_ND6_MIN_RANDOM_FACTOR
700  (uip_ds6_if.base_reachable_time)) +
701  ((uint16_t) (random_rand() << 8) +
702  (uint16_t) random_rand()) %
703  (uint32_t) (UIP_ND6_MAX_RANDOM_FACTOR(uip_ds6_if.base_reachable_time) -
704  UIP_ND6_MIN_RANDOM_FACTOR(uip_ds6_if.base_reachable_time));
705 }
706 /*---------------------------------------------------------------------------*/
707 #endif /* UIP_CONF_IPV6 */
708 
709 /** @}*/
#define uip_create_unspecified(a)
set IP address a to unspecified
Definition: uip.h:2007
#define UIP_LINK_MTU
The maximum transmission unit at the IP Layer.
Definition: uipopt.h:283
uip_len
The length of the packet in the uip_buf buffer.
Definition: tcp_loader.c:75
#define uip_is_addr_mcast(a)
is address a multicast address, see RFC 3513 a is of type uip_ipaddr_t*
Definition: uip.h:2095
Neighbor discovery (RFC 4861)
int stimer_expired(struct stimer *t)
Check if a timer has expired.
Definition: stimer.c:124
#define uip_is_addr_link_local(a)
is addr (a) a link local unicast address, see RFC3513 i.e.
Definition: uip.h:2058
CCIF uip_lladdr_t uip_lladdr
Host L2 address.
Definition: uip6.c:115
#define UIP_DS6_PERIOD
General DS6 definitions.
Definition: uip-ds6.h:136
Unicast address structure.
Definition: uip-ds6.h:172
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:203
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:535
void uip_nd6_rs_output(void)
Send a Router Solicitation.
Definition: uip-nd6.c:740
Network interface and stateless autoconfiguration (RFC 4862)
void timer_set(struct timer *t, clock_time_t interval)
Set a timer.
Definition: timer.c:64
struct etimer uip_ds6_timer_rs
Timer for maintenance of data structures.
Definition: uip-ds6.c:67
#define uip_is_addr_mcast_routable(a)
is address a routable multicast address.
Definition: uip.h:2123
void uip_ds6_periodic(void)
Periodic processing of data structures.
Definition: uip-ds6.c:147
#define NULL
The null pointer.
#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:2040
A multicast address.
Definition: uip-ds6.h:192
#define uip_create_linklocal_allrouters_mcast(a)
set IP address a to the link local all-routers multicast address
Definition: uip.h:2013
A prefix list entry.
Definition: uip-ds6.h:162
void stimer_set(struct stimer *t, unsigned long interval)
Set a timer.
Definition: stimer.c:67
uip_ds6_prefix_t uip_ds6_prefix_list[UIP_DS6_PREFIX_NB]
The single interface.
Definition: uip-ds6.c:74
#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:97
Generic type for a DS6, to use a common loop though all DS.
Definition: uip-ds6.h:225
uint8_t uip_ds6_addr_size
Prefix list.
Definition: uip-ds6.c:77
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
Definition: uip.h:1026
802.3 address
Definition: uip.h:135
#define uip_create_linklocal_allnodes_mcast(a)
set IP address a to the link local all-nodes multicast address
Definition: uip.h:2010
void uip_ds6_select_src(uip_ipaddr_t *src, uip_ipaddr_t *dst)
Source address selection, see RFC 3484.
Definition: uip-ds6.c:497
A timer.
Definition: stimer.h:81
void etimer_reset(struct etimer *et)
Reset an event timer with the same interval as was previously set.
Definition: etimer.c:184
void uip_ds6_send_rs(void)
Send periodic RS to find router.
Definition: uip-ds6.c:677
#define ADDR_TENTATIVE
Possible states for the an address (RFC 4862)
Definition: uip-ds6.h:123
void etimer_stop(struct etimer *et)
Stop a pending event timer.
Definition: etimer.c:235
Interface structure (contains all the interface variables)
Definition: uip-ds6.h:212
void etimer_set(struct etimer *et, clock_time_t interval)
Set an event timer.
Definition: etimer.c:177
#define UIP_TTL
The IP TTL (time to live) of IP packets sent by uIP.
Definition: uipopt.h:245
A set of debugging macros.
void uip_ds6_init(void)
Initialize data structures.
Definition: uip-ds6.c:93
int timer_expired(struct timer *t)
Check if a timer has expired.
Definition: timer.c:121
uint32_t uip_ds6_compute_reachable_time(void)
Compute the reachable time based on base reachable time, see RFC 4861.
Definition: uip-ds6.c:697
A timer.
Definition: etimer.h:76
Anycast address.
Definition: uip-ds6.h:186
unsigned short random_rand(void)
Generate the next state and return the upper part of it.
Definition: random.c:47
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:328
unsigned long stimer_elapsed(struct stimer *t)
The time elapsed since the timer started.
Definition: stimer.c:156
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:555
#define CLOCK_SECOND
A second, measured in system clock time.
Definition: clock.h:82
unsigned long stimer_remaining(struct stimer *t)
The time until the timer expires.
Definition: stimer.c:140