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 /*---------------------------------------------------------------------------*/
99 void
101 {
102 
103  uip_ds6_neighbors_init();
104  uip_ds6_route_init();
105 
106  LOG_INFO("Init: %u neighbors\n", NBR_TABLE_MAX_NEIGHBORS);
107  LOG_INFO("%u default routers\n", UIP_DS6_DEFRT_NB);
108  LOG_INFO("%u prefixes\n", UIP_DS6_PREFIX_NB);
109  LOG_INFO("%u routes\n", UIP_DS6_ROUTE_NB);
110  LOG_INFO("%u unicast addresses\n", UIP_DS6_ADDR_NB);
111  LOG_INFO("%u multicast addresses\n", UIP_DS6_MADDR_NB);
112  LOG_INFO("%u anycast addresses\n", UIP_DS6_AADDR_NB);
113 
114  memset(uip_ds6_prefix_list, 0, sizeof(uip_ds6_prefix_list));
115  memset(&uip_ds6_if, 0, sizeof(uip_ds6_if));
116  uip_ds6_addr_size = sizeof(struct uip_ds6_addr);
117  uip_ds6_netif_addr_list_offset = offsetof(struct uip_ds6_netif, addr_list);
118 
119  /* Set interface parameters */
120  uip_ds6_if.link_mtu = UIP_LINK_MTU;
121  uip_ds6_if.cur_hop_limit = UIP_TTL;
122  uip_ds6_if.base_reachable_time = UIP_ND6_REACHABLE_TIME;
123  uip_ds6_if.reachable_time = uip_ds6_compute_reachable_time();
124  uip_ds6_if.retrans_timer = UIP_ND6_RETRANS_TIMER;
125  uip_ds6_if.maxdadns = UIP_ND6_DEF_MAXDADNS;
126 
127  /* Create link local address, prefix, multicast addresses, anycast addresses */
128  uip_create_linklocal_prefix(&loc_fipaddr);
129 #if UIP_CONF_ROUTER
130  uip_ds6_prefix_add(&loc_fipaddr, UIP_DEFAULT_PREFIX_LEN, 0, 0, 0, 0);
131 #else /* UIP_CONF_ROUTER */
132  uip_ds6_prefix_add(&loc_fipaddr, UIP_DEFAULT_PREFIX_LEN, 0);
133 #endif /* UIP_CONF_ROUTER */
134  uip_ds6_set_addr_iid(&loc_fipaddr, &uip_lladdr);
135  uip_ds6_addr_add(&loc_fipaddr, 0, ADDR_AUTOCONF);
136 
138  uip_ds6_maddr_add(&loc_fipaddr);
139 #if UIP_CONF_ROUTER
141  uip_ds6_maddr_add(&loc_fipaddr);
142 #if UIP_ND6_SEND_RA
143  stimer_set(&uip_ds6_timer_ra, 2); /* wait to have a link local IP address */
144 #endif /* UIP_ND6_SEND_RA */
145 #else /* UIP_CONF_ROUTER */
148  CLOCK_SECOND));
149 #endif /* UIP_CONF_ROUTER */
151 
152  return;
153 }
154 
155 
156 /*---------------------------------------------------------------------------*/
157 void
159 {
160 
161  /* Periodic processing on unicast addresses */
162  for(locaddr = uip_ds6_if.addr_list;
163  locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
164  if(locaddr->isused) {
165  if((!locaddr->isinfinite) && (stimer_expired(&locaddr->vlifetime))) {
166  uip_ds6_addr_rm(locaddr);
167 #if UIP_ND6_DEF_MAXDADNS > 0
168  } else if((locaddr->state == ADDR_TENTATIVE)
169  && (locaddr->dadnscount <= uip_ds6_if.maxdadns)
170  && (timer_expired(&locaddr->dadtimer))
171  && (uip_len == 0)) {
172  uip_ds6_dad(locaddr);
173 #endif /* UIP_ND6_DEF_MAXDADNS > 0 */
174  }
175  }
176  }
177 
178  /* Periodic processing on default routers */
179  uip_ds6_defrt_periodic();
180  /* for(locdefrt = uip_ds6_defrt_list;
181  locdefrt < uip_ds6_defrt_list + UIP_DS6_DEFRT_NB; locdefrt++) {
182  if((locdefrt->isused) && (!locdefrt->isinfinite) &&
183  (stimer_expired(&(locdefrt->lifetime)))) {
184  uip_ds6_defrt_rm(locdefrt);
185  }
186  }*/
187 
188 #if !UIP_CONF_ROUTER
189  /* Periodic processing on prefixes */
190  for(locprefix = uip_ds6_prefix_list;
191  locprefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB;
192  locprefix++) {
193  if(locprefix->isused && !locprefix->isinfinite
194  && stimer_expired(&(locprefix->vlifetime))) {
195  uip_ds6_prefix_rm(locprefix);
196  }
197  }
198 #endif /* !UIP_CONF_ROUTER */
199 
200 #if UIP_ND6_SEND_NS
201  uip_ds6_neighbor_periodic();
202 #endif /* UIP_ND6_SEND_NS */
203 
204 #if UIP_CONF_ROUTER && UIP_ND6_SEND_RA
205  /* Periodic RA sending */
206  if(stimer_expired(&uip_ds6_timer_ra) && (uip_len == 0)) {
207  uip_ds6_send_ra_periodic();
208  }
209 #endif /* UIP_CONF_ROUTER && UIP_ND6_SEND_RA */
211  return;
212 }
213 
214 /*---------------------------------------------------------------------------*/
215 uint8_t
217  uint16_t elementsize, uip_ipaddr_t *ipaddr,
218  uint8_t ipaddrlen, uip_ds6_element_t **out_element)
219 {
220  uip_ds6_element_t *element;
221 
222  if(list == NULL || ipaddr == NULL || out_element == NULL) {
223  return NOSPACE;
224  }
225 
226  *out_element = NULL;
227 
228  for(element = list;
229  element <
230  (uip_ds6_element_t *)((uint8_t *)list + (size * elementsize));
231  element = (uip_ds6_element_t *)((uint8_t *)element + elementsize)) {
232  if(element->isused) {
233  if(uip_ipaddr_prefixcmp(&element->ipaddr, ipaddr, ipaddrlen)) {
234  *out_element = element;
235  return FOUND;
236  }
237  } else {
238  *out_element = element;
239  }
240  }
241 
242  return *out_element != NULL ? FREESPACE : NOSPACE;
243 }
244 
245 /*---------------------------------------------------------------------------*/
246 #if UIP_CONF_ROUTER
247 /*---------------------------------------------------------------------------*/
249 uip_ds6_prefix_add(uip_ipaddr_t *ipaddr, uint8_t ipaddrlen,
250  uint8_t advertise, uint8_t flags, unsigned long vtime,
251  unsigned long ptime)
252 {
254  ((uip_ds6_element_t *)uip_ds6_prefix_list, UIP_DS6_PREFIX_NB,
255  sizeof(uip_ds6_prefix_t), ipaddr, ipaddrlen,
256  (uip_ds6_element_t **)&locprefix) == FREESPACE) {
257  locprefix->isused = 1;
258  uip_ipaddr_copy(&locprefix->ipaddr, ipaddr);
259  locprefix->length = ipaddrlen;
260  locprefix->advertise = advertise;
261  locprefix->l_a_reserved = flags;
262  locprefix->vlifetime = vtime;
263  locprefix->plifetime = ptime;
264  LOG_INFO("Adding prefix ");
265  LOG_INFO_6ADDR(&locprefix->ipaddr);
266  LOG_INFO_("length %u, flags %x, Valid lifetime %lx, Preffered lifetime %lx\n",
267  ipaddrlen, flags, vtime, ptime);
268  return locprefix;
269  } else {
270  LOG_INFO("No more space in Prefix list\n");
271  }
272  return NULL;
273 }
274 
275 
276 #else /* UIP_CONF_ROUTER */
278 uip_ds6_prefix_add(uip_ipaddr_t *ipaddr, uint8_t ipaddrlen,
279  unsigned long interval)
280 {
282  ((uip_ds6_element_t *)uip_ds6_prefix_list, UIP_DS6_PREFIX_NB,
283  sizeof(uip_ds6_prefix_t), ipaddr, ipaddrlen,
284  (uip_ds6_element_t **)&locprefix) == FREESPACE) {
285  locprefix->isused = 1;
286  uip_ipaddr_copy(&locprefix->ipaddr, ipaddr);
287  locprefix->length = ipaddrlen;
288  if(interval != 0) {
289  stimer_set(&(locprefix->vlifetime), interval);
290  locprefix->isinfinite = 0;
291  } else {
292  locprefix->isinfinite = 1;
293  }
294  LOG_INFO("Adding prefix ");
295  LOG_INFO_6ADDR(&locprefix->ipaddr);
296  LOG_INFO_("length %u, vlifetime %lu\n", ipaddrlen, interval);
297  return locprefix;
298  }
299  return NULL;
300 }
301 #endif /* UIP_CONF_ROUTER */
302 
303 /*---------------------------------------------------------------------------*/
304 void
305 uip_ds6_prefix_rm(uip_ds6_prefix_t *prefix)
306 {
307  if(prefix != NULL) {
308  prefix->isused = 0;
309  }
310  return;
311 }
312 /*---------------------------------------------------------------------------*/
314 uip_ds6_prefix_lookup(uip_ipaddr_t *ipaddr, uint8_t ipaddrlen)
315 {
316  if(uip_ds6_list_loop((uip_ds6_element_t *)uip_ds6_prefix_list,
317  UIP_DS6_PREFIX_NB, sizeof(uip_ds6_prefix_t),
318  ipaddr, ipaddrlen,
319  (uip_ds6_element_t **)&locprefix) == FOUND) {
320  return locprefix;
321  }
322  return NULL;
323 }
324 
325 /*---------------------------------------------------------------------------*/
326 uint8_t
327 uip_ds6_is_addr_onlink(uip_ipaddr_t *ipaddr)
328 {
329  for(locprefix = uip_ds6_prefix_list;
330  locprefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; locprefix++) {
331  if(locprefix->isused &&
332  uip_ipaddr_prefixcmp(&locprefix->ipaddr, ipaddr, locprefix->length)) {
333  return 1;
334  }
335  }
336  return 0;
337 }
338 
339 /*---------------------------------------------------------------------------*/
341 uip_ds6_addr_add(uip_ipaddr_t *ipaddr, unsigned long vlifetime, uint8_t type)
342 {
344  ((uip_ds6_element_t *)uip_ds6_if.addr_list, UIP_DS6_ADDR_NB,
345  sizeof(uip_ds6_addr_t), ipaddr, 128,
346  (uip_ds6_element_t **)&locaddr) == FREESPACE) {
347  locaddr->isused = 1;
348  uip_ipaddr_copy(&locaddr->ipaddr, ipaddr);
349  locaddr->type = type;
350  if(vlifetime == 0) {
351  locaddr->isinfinite = 1;
352  } else {
353  locaddr->isinfinite = 0;
354  stimer_set(&(locaddr->vlifetime), vlifetime);
355  }
356 #if UIP_ND6_DEF_MAXDADNS > 0
357  locaddr->state = ADDR_TENTATIVE;
358  timer_set(&locaddr->dadtimer,
360  CLOCK_SECOND));
361  locaddr->dadnscount = 0;
362 #else /* UIP_ND6_DEF_MAXDADNS > 0 */
363  locaddr->state = ADDR_PREFERRED;
364 #endif /* UIP_ND6_DEF_MAXDADNS > 0 */
365  uip_create_solicited_node(ipaddr, &loc_fipaddr);
366  uip_ds6_maddr_add(&loc_fipaddr);
367  return locaddr;
368  }
369  return NULL;
370 }
371 
372 /*---------------------------------------------------------------------------*/
373 void
374 uip_ds6_addr_rm(uip_ds6_addr_t *addr)
375 {
376  if(addr != NULL) {
377  uip_create_solicited_node(&addr->ipaddr, &loc_fipaddr);
378  if((locmaddr = uip_ds6_maddr_lookup(&loc_fipaddr)) != NULL) {
379  uip_ds6_maddr_rm(locmaddr);
380  }
381  addr->isused = 0;
382  }
383  return;
384 }
385 
386 /*---------------------------------------------------------------------------*/
388 uip_ds6_addr_lookup(uip_ipaddr_t *ipaddr)
389 {
391  ((uip_ds6_element_t *)uip_ds6_if.addr_list, UIP_DS6_ADDR_NB,
392  sizeof(uip_ds6_addr_t), ipaddr, 128,
393  (uip_ds6_element_t **)&locaddr) == FOUND) {
394  return locaddr;
395  }
396  return NULL;
397 }
398 
399 /*---------------------------------------------------------------------------*/
400 /*
401  * get a link local address -
402  * state = -1 => any address is ok. Otherwise state = desired state of addr.
403  * (TENTATIVE, PREFERRED, DEPRECATED)
404  */
406 uip_ds6_get_link_local(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_linklocal(&locaddr->ipaddr))) {
412  return locaddr;
413  }
414  }
415  return NULL;
416 }
417 
418 /*---------------------------------------------------------------------------*/
419 /*
420  * get a global address -
421  * state = -1 => any address is ok. Otherwise state = desired state of addr.
422  * (TENTATIVE, PREFERRED, DEPRECATED)
423  */
425 uip_ds6_get_global(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 /*---------------------------------------------------------------------------*/
439 uip_ds6_maddr_add(const uip_ipaddr_t *ipaddr)
440 {
442  ((uip_ds6_element_t *)uip_ds6_if.maddr_list, UIP_DS6_MADDR_NB,
443  sizeof(uip_ds6_maddr_t), (void*)ipaddr, 128,
444  (uip_ds6_element_t **)&locmaddr) == FREESPACE) {
445  locmaddr->isused = 1;
446  uip_ipaddr_copy(&locmaddr->ipaddr, ipaddr);
447  return locmaddr;
448  }
449  return NULL;
450 }
451 
452 /*---------------------------------------------------------------------------*/
453 void
454 uip_ds6_maddr_rm(uip_ds6_maddr_t *maddr)
455 {
456  if(maddr != NULL) {
457  maddr->isused = 0;
458  }
459  return;
460 }
461 
462 /*---------------------------------------------------------------------------*/
464 uip_ds6_maddr_lookup(const uip_ipaddr_t *ipaddr)
465 {
467  ((uip_ds6_element_t *)uip_ds6_if.maddr_list, UIP_DS6_MADDR_NB,
468  sizeof(uip_ds6_maddr_t), (void*)ipaddr, 128,
469  (uip_ds6_element_t **)&locmaddr) == FOUND) {
470  return locmaddr;
471  }
472  return NULL;
473 }
474 
475 
476 /*---------------------------------------------------------------------------*/
478 uip_ds6_aaddr_add(uip_ipaddr_t *ipaddr)
479 {
480 #if UIP_DS6_AADDR_NB
482  ((uip_ds6_element_t *)uip_ds6_if.aaddr_list, UIP_DS6_AADDR_NB,
483  sizeof(uip_ds6_aaddr_t), ipaddr, 128,
484  (uip_ds6_element_t **)&locaaddr) == FREESPACE) {
485  locaaddr->isused = 1;
486  uip_ipaddr_copy(&locaaddr->ipaddr, ipaddr);
487  return locaaddr;
488  }
489 #endif /* UIP_DS6_AADDR_NB */
490  return NULL;
491 }
492 
493 /*---------------------------------------------------------------------------*/
494 void
495 uip_ds6_aaddr_rm(uip_ds6_aaddr_t *aaddr)
496 {
497  if(aaddr != NULL) {
498  aaddr->isused = 0;
499  }
500  return;
501 }
502 
503 /*---------------------------------------------------------------------------*/
505 uip_ds6_aaddr_lookup(uip_ipaddr_t *ipaddr)
506 {
507 #if UIP_DS6_AADDR_NB
508  if(uip_ds6_list_loop((uip_ds6_element_t *)uip_ds6_if.aaddr_list,
509  UIP_DS6_AADDR_NB, sizeof(uip_ds6_aaddr_t), ipaddr, 128,
510  (uip_ds6_element_t **)&locaaddr) == FOUND) {
511  return locaaddr;
512  }
513 #endif /* UIP_DS6_AADDR_NB */
514  return NULL;
515 }
516 
517 /*---------------------------------------------------------------------------*/
518 void
519 uip_ds6_select_src(uip_ipaddr_t *src, uip_ipaddr_t *dst)
520 {
521  uint8_t best = 0; /* number of bit in common with best match */
522  uint8_t n = 0;
523  uip_ds6_addr_t *matchaddr = NULL;
524 
525  if(!uip_is_addr_linklocal(dst) && !uip_is_addr_mcast(dst)) {
526  /* find longest match */
527  for(locaddr = uip_ds6_if.addr_list;
528  locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
529  /* Only preferred global (not link-local) addresses */
530  if(locaddr->isused && locaddr->state == ADDR_PREFERRED &&
531  !uip_is_addr_linklocal(&locaddr->ipaddr)) {
532  n = get_match_length(dst, &locaddr->ipaddr);
533  if(n >= best) {
534  best = n;
535  matchaddr = locaddr;
536  }
537  }
538  }
539 #if UIP_IPV6_MULTICAST
540  } else if(uip_is_addr_mcast_routable(dst)) {
541  matchaddr = uip_ds6_get_global(ADDR_PREFERRED);
542 #endif
543  } else {
544  matchaddr = uip_ds6_get_link_local(ADDR_PREFERRED);
545  }
546 
547  /* use the :: (unspecified address) as source if no match found */
548  if(matchaddr == NULL) {
550  } else {
551  uip_ipaddr_copy(src, &matchaddr->ipaddr);
552  }
553 }
554 
555 /*---------------------------------------------------------------------------*/
556 void
557 uip_ds6_set_addr_iid(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr)
558 {
559 #if (UIP_LLADDR_LEN == 8)
560  memcpy(ipaddr->u8 + 8, lladdr, UIP_LLADDR_LEN);
561  ipaddr->u8[8] ^= 0x02;
562 #elif (UIP_LLADDR_LEN == 6)
563  memcpy(ipaddr->u8 + 8, lladdr, 3);
564  ipaddr->u8[11] = 0xff;
565  ipaddr->u8[12] = 0xfe;
566  memcpy(ipaddr->u8 + 13, (uint8_t *)lladdr + 3, 3);
567  ipaddr->u8[8] ^= 0x02;
568 #elif (UIP_LLADDR_LEN == 2)
569  /* derive IID as per RFC 6282 */
570  memcpy(ipaddr->u8 + 8, iid_prefix, 6);
571  memcpy(ipaddr->u8 + 8 + 6, lladdr, UIP_LLADDR_LEN);
572 #else
573 #error uip-ds6.c cannot build interface address when UIP_LLADDR_LEN is not 6, 8, or 2
574 #endif
575 }
576 /*---------------------------------------------------------------------------*/
577 void
578 uip_ds6_set_lladdr_from_iid(uip_lladdr_t *lladdr, const uip_ipaddr_t *ipaddr)
579 {
580 #if (UIP_LLADDR_LEN == 8)
581  memcpy(lladdr, ipaddr->u8 + 8, UIP_LLADDR_LEN);
582  lladdr->addr[0] ^= 0x02;
583 #elif (UIP_LLADDR_LEN == 2)
584  memcpy(lladdr, ipaddr->u8 + 6, UIP_LLADDR_LEN);
585 #else
586 #error uip-ds6.c cannot build lladdr address when UIP_LLADDR_LEN is not 8 or 2
587 #endif
588 }
589 
590 /*---------------------------------------------------------------------------*/
591 uint8_t
592 get_match_length(uip_ipaddr_t *src, uip_ipaddr_t *dst)
593 {
594  uint8_t j, k, x_or;
595  uint8_t len = 0;
596 
597  for(j = 0; j < 16; j++) {
598  if(src->u8[j] == dst->u8[j]) {
599  len += 8;
600  } else {
601  x_or = src->u8[j] ^ dst->u8[j];
602  for(k = 0; k < 8; k++) {
603  if((x_or & 0x80) == 0) {
604  len++;
605  x_or <<= 1;
606  } else {
607  break;
608  }
609  }
610  break;
611  }
612  }
613  return len;
614 }
615 
616 /*---------------------------------------------------------------------------*/
617 #if UIP_ND6_DEF_MAXDADNS > 0
618 void
620 {
621  /* send maxdadns NS for DAD */
622  if(addr->dadnscount < uip_ds6_if.maxdadns) {
623  uip_nd6_ns_output(NULL, NULL, &addr->ipaddr);
624  addr->dadnscount++;
625  timer_set(&addr->dadtimer,
626  uip_ds6_if.retrans_timer / 1000 * CLOCK_SECOND);
627  return;
628  }
629  /*
630  * If we arrive here it means DAD succeeded, otherwise the dad process
631  * would have been interrupted in ds6_dad_ns/na_input
632  */
633  LOG_INFO("DAD succeeded, ipaddr: ");
634  LOG_INFO_6ADDR(&addr->ipaddr);
635  LOG_INFO_("\n");
636 
637  addr->state = ADDR_PREFERRED;
638  return;
639 }
640 
641 /*---------------------------------------------------------------------------*/
642 /*
643  * Calling code must handle when this returns 0 (e.g. link local
644  * address can not be used).
645  */
646 int
648 {
649  if(uip_is_addr_linklocal(&addr->ipaddr)) {
650  LOG_ERR("Contiki shutdown, DAD for link local address failed\n");
651  return 0;
652  }
653  uip_ds6_addr_rm(addr);
654  return 1;
655 }
656 #endif /*UIP_ND6_DEF_MAXDADNS > 0 */
657 
658 /*---------------------------------------------------------------------------*/
659 #if UIP_CONF_ROUTER
660 #if UIP_ND6_SEND_RA
661 void
662 uip_ds6_send_ra_sollicited(void)
663 {
664  /* We have a pb here: RA timer max possible value is 1800s,
665  * hence we have to use stimers. However, when receiving a RS, we
666  * should delay the reply by a random value between 0 and 500ms timers.
667  * stimers are in seconds, hence we cannot do this. Therefore we just send
668  * the RA (setting the timer to 0 below). We keep the code logic for
669  * the days contiki will support appropriate timers */
670  rand_time = 0;
671  LOG_INFO("Solicited RA, random time %u\n", rand_time);
672 
673  if(stimer_remaining(&uip_ds6_timer_ra) > rand_time) {
674  if(stimer_elapsed(&uip_ds6_timer_ra) < UIP_ND6_MIN_DELAY_BETWEEN_RAS) {
675  /* Ensure that the RAs are rate limited */
676 /* stimer_set(&uip_ds6_timer_ra, rand_time +
677  UIP_ND6_MIN_DELAY_BETWEEN_RAS -
678  stimer_elapsed(&uip_ds6_timer_ra));
679  */ } else {
680  stimer_set(&uip_ds6_timer_ra, rand_time);
681  }
682  }
683 }
684 
685 /*---------------------------------------------------------------------------*/
686 void
687 uip_ds6_send_ra_periodic(void)
688 {
689  if(racount > 0) {
690  /* send previously scheduled RA */
691  uip_nd6_ra_output(NULL);
692  LOG_INFO("Sending periodic RA\n");
693  }
694 
695  rand_time = UIP_ND6_MIN_RA_INTERVAL + random_rand() %
696  (uint16_t) (UIP_ND6_MAX_RA_INTERVAL - UIP_ND6_MIN_RA_INTERVAL);
697  LOG_DBG("Random time 1 = %u\n", rand_time);
698 
699  if(racount < UIP_ND6_MAX_INITIAL_RAS) {
700  if(rand_time > UIP_ND6_MAX_INITIAL_RA_INTERVAL) {
701  rand_time = UIP_ND6_MAX_INITIAL_RA_INTERVAL;
702  LOG_DBG("Random time 2 = %u\n", rand_time);
703  }
704  racount++;
705  }
706  LOG_DBG("Random time 3 = %u\n", rand_time);
707  stimer_set(&uip_ds6_timer_ra, rand_time);
708 }
709 
710 #endif /* UIP_ND6_SEND_RA */
711 #else /* UIP_CONF_ROUTER */
712 /*---------------------------------------------------------------------------*/
713 void
715 {
716  if((uip_ds6_defrt_choose() == NULL)
718  LOG_INFO("Sending RS %u\n", rscount);
720  rscount++;
723  } else {
724  LOG_INFO("Router found ? (boolean): %u\n",
725  (uip_ds6_defrt_choose() != NULL));
727  }
728  return;
729 }
730 
731 #endif /* UIP_CONF_ROUTER */
732 /*---------------------------------------------------------------------------*/
733 uint32_t
735 {
736  return (uint32_t) (UIP_ND6_MIN_RANDOM_FACTOR
737  (uip_ds6_if.base_reachable_time)) +
738  ((uint16_t) (random_rand() << 8) +
739  (uint16_t) random_rand()) %
740  (uint32_t) (UIP_ND6_MAX_RANDOM_FACTOR(uip_ds6_if.base_reachable_time) -
741  UIP_ND6_MIN_RANDOM_FACTOR(uip_ds6_if.base_reachable_time));
742 }
743 /*---------------------------------------------------------------------------*/
744 
745 /** @}*/
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
Definition: uip-nd6.c:125
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:2135
void uip_ds6_send_rs(void)
Send periodic RS to find router.
Definition: uip-ds6.c:714
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:179
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Definition: uip-nd6.c:116
void uip_ds6_init(void)
Initialize data structures.
Definition: uip-ds6.c:100
#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:578
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:592
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:557
void uip_ds6_dad(uip_ds6_addr_t *addr)
Perform Duplicate Address Selection on one address.
Definition: uip-ds6.c:619
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:249
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:647
#define UIP_LLADDR_LEN
802.15.4 address
Definition: uip.h:148
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 stimer_set(struct stimer *t, unsigned long interval)
Set a timer.
Definition: stimer.c:67
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:2031
A timer.
Definition: stimer.h:81
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:1018
#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:2034
#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:341
A timer.
Definition: etimer.h:75
#define uip_is_addr_mcast(a)
is address a multicast address, see RFC 4291 a is of type uip_ipaddr_t*
Definition: uip.h:2107
void uip_ds6_periodic(void)
Periodic processing of data structures.
Definition: uip-ds6.c:158
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:2028
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:216
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:2023
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:211
void uip_nd6_rs_output(void)
Neighbor Solicitation Processing.
Definition: uip-nd6.c:821
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:2061
void uip_ds6_select_src(uip_ipaddr_t *src, uip_ipaddr_t *dst)
Source address selection, see RFC 3484.
Definition: uip-ds6.c:519
uint32_t uip_ds6_compute_reachable_time(void)
Compute the reachable time based on base reachable time, see RFC 4861.
Definition: uip-ds6.c:734