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