Contiki-NG
uip-nd6.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
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 project 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 PROJECT 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 PROJECT 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  * Copyright (c) 2006, Swedish Institute of Computer Science.
31  * All rights reserved.
32  *
33  * Redistribution and use in source and binary forms, with or without
34  * modification, are permitted provided that the following conditions
35  * are met:
36  * 1. Redistributions of source code must retain the above copyright
37  * notice, this list of conditions and the following disclaimer.
38  * 2. Redistributions in binary form must reproduce the above copyright
39  * notice, this list of conditions and the following disclaimer in the
40  * documentation and/or other materials provided with the distribution.
41  * 3. Neither the name of the Institute nor the names of its contributors
42  * may be used to endorse or promote products derived from this software
43  * without specific prior written permission.
44  *
45  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
46  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
49  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55  * SUCH DAMAGE.
56  *
57  */
58 
59 /**
60  * \addtogroup uip
61  * @{
62  */
63 
64 /**
65  * \file
66  * Neighbor discovery (RFC 4861)
67  * \author Mathilde Durvy <mdurvy@cisco.com>
68  * \author Julien Abeille <jabeille@cisco.com>
69  */
70 
71 #include <string.h>
72 #include <inttypes.h>
73 #include "net/ipv6/uip-icmp6.h"
74 #include "net/ipv6/uip-nd6.h"
75 #include "net/ipv6/uip-ds6.h"
77 #include "lib/random.h"
78 
79 /* Log configuration */
80 #include "sys/log.h"
81 #define LOG_MODULE "IPv6 NDP"
82 #define LOG_LEVEL LOG_LEVEL_IPV6
83 
84 /*------------------------------------------------------------------*/
85 /** @{ */
86 /** \name Pointers to the header structures.
87  */
88 
89 /**@{ Pointers to messages just after icmp header */
90 #define UIP_ND6_RS_BUF ((uip_nd6_rs *)UIP_ICMP_PAYLOAD)
91 #define UIP_ND6_RA_BUF ((uip_nd6_ra *)UIP_ICMP_PAYLOAD)
92 #define UIP_ND6_NS_BUF ((uip_nd6_ns *)UIP_ICMP_PAYLOAD)
93 #define UIP_ND6_NA_BUF ((uip_nd6_na *)UIP_ICMP_PAYLOAD)
94 /** @} */
95 /** Pointer to ND option */
96 #define ND6_OPT(opt) ((unsigned char *)(UIP_ICMP_PAYLOAD + (opt)))
97 #define ND6_OPT_HDR_BUF(opt) ((uip_nd6_opt_hdr *)ND6_OPT(opt))
98 #define ND6_OPT_PREFIX_BUF(opt) ((uip_nd6_opt_prefix_info *)ND6_OPT(opt))
99 #define ND6_OPT_MTU_BUF(opt) ((uip_nd6_opt_mtu *)ND6_OPT(opt))
100 #define ND6_OPT_RDNSS_BUF(opt) ((uip_nd6_opt_dns *)ND6_OPT(opt))
101 /** @} */
102 
103 #if UIP_ND6_SEND_NS || UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER
104 static uint16_t nd6_opt_offset; /** Offset from the end of the icmpv6 header to the option in uip_buf*/
105 static uint8_t *nd6_opt_llao; /** Pointer to llao option in uip_buf */
106 static uip_ds6_nbr_t *nbr; /** Pointer to a nbr cache entry*/
107 static uip_ds6_addr_t *addr; /** Pointer to an interface address */
108 #endif /* UIP_ND6_SEND_NS || UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER */
109 
110 #if UIP_ND6_SEND_NS || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER
111 static uip_ds6_defrt_t *defrt; /** Pointer to a router list entry */
112 #endif /* UIP_ND6_SEND_NS || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER */
113 
114 #if !UIP_CONF_ROUTER // TBD see if we move it to ra_input
115 static uip_nd6_opt_prefix_info *nd6_opt_prefix_info; /** Pointer to prefix information option in uip_buf */
116 static uip_ipaddr_t ipaddr;
117 #endif
118 #if (!UIP_CONF_ROUTER || UIP_ND6_SEND_RA)
119 static uip_ds6_prefix_t *prefix; /** Pointer to a prefix list entry */
120 #endif
121 
122 #if UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER
123 /*------------------------------------------------------------------*/
124 /* Copy link-layer address from LLAO option to a word-aligned uip_lladdr_t */
125 static int
127 {
128  if(dest != NULL && nd6_opt_llao != NULL) {
129  memcpy(dest, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], UIP_LLADDR_LEN);
130  return 1;
131  }
132  return 0;
133 }
134 #endif /* UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER */
135 /*------------------------------------------------------------------*/
136 #if UIP_ND6_SEND_NA /* UIP_ND6_SEND_NA */
137 /* create a llao */
138 static void
139 create_llao(uint8_t *llao, uint8_t type)
140 {
141  llao[UIP_ND6_OPT_TYPE_OFFSET] = type;
142  llao[UIP_ND6_OPT_LEN_OFFSET] = UIP_ND6_OPT_LLAO_LEN >> 3;
143  memcpy(&llao[UIP_ND6_OPT_DATA_OFFSET], &uip_lladdr, UIP_LLADDR_LEN);
144  /* padding on some */
145  memset(&llao[UIP_ND6_OPT_DATA_OFFSET + UIP_LLADDR_LEN], 0,
147 }
148 #endif /* UIP_ND6_SEND_NA */
149 /*------------------------------------------------------------------*/
150  /**
151  * Neighbor Solicitation Processing
152  *
153  * The NS can be received in 3 cases (procedures):
154  * - sender is performing DAD (ip src = unspecified, no SLLAO option)
155  * - sender is performing NUD (ip dst = unicast)
156  * - sender is performing address resolution (ip dest = solicited node mcast
157  * address)
158  *
159  * We do:
160  * - if the tgt belongs to me, reply, otherwise ignore
161  * - if i was performing DAD for the same address, two cases:
162  * -- I already sent a NS, hence I win
163  * -- I did not send a NS yet, hence I lose
164  *
165  * If we need to send a NA in response (i.e. the NS was done for NUD, or
166  * address resolution, or DAD and there is a conflict), we do it in this
167  * function: set src, dst, tgt address in the three cases, then for all cases
168  * set the rest, including SLLAO
169  *
170  */
171 #if UIP_ND6_SEND_NA
172 static void
173 ns_input(void)
174 {
175  uint8_t flags = 0;
176 
177  LOG_INFO("Received NS from ");
178  LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr);
179  LOG_INFO_(" to ");
180  LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
181  LOG_INFO_(" with target address ");
182  LOG_INFO_6ADDR((uip_ipaddr_t *) (&UIP_ND6_NS_BUF->tgtipaddr));
183  LOG_INFO_("\n");
184  UIP_STAT(++uip_stat.nd6.recv);
185 
186 #if UIP_CONF_IPV6_CHECKS
187  if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) ||
188  (uip_is_addr_mcast(&UIP_ND6_NS_BUF->tgtipaddr)) ||
189  (UIP_ICMP_BUF->icode != 0)) {
190  LOG_ERR("NS received is bad\n");
191  goto discard;
192  }
193 #endif /* UIP_CONF_IPV6_CHECKS */
194 
195  /* Options processing */
196  nd6_opt_llao = NULL;
197  nd6_opt_offset = UIP_ND6_NS_LEN;
198  while(uip_l3_icmp_hdr_len + nd6_opt_offset + UIP_ND6_OPT_HDR_LEN < uip_len) {
199 #if UIP_CONF_IPV6_CHECKS
200  if(ND6_OPT_HDR_BUF(nd6_opt_offset)->len == 0) {
201  LOG_ERR("NS received is bad\n");
202  goto discard;
203  }
204 #endif /* UIP_CONF_IPV6_CHECKS */
205  switch (ND6_OPT_HDR_BUF(nd6_opt_offset)->type) {
206  case UIP_ND6_OPT_SLLAO:
207  if(uip_l3_icmp_hdr_len + nd6_opt_offset +
208  UIP_ND6_OPT_DATA_OFFSET + UIP_LLADDR_LEN > uip_len) {
209  LOG_ERR("Insufficient data for NS SLLAO option\n");
210  goto discard;
211  }
212  nd6_opt_llao = &uip_buf[uip_l3_icmp_hdr_len + nd6_opt_offset];
213 #if UIP_CONF_IPV6_CHECKS
214  /* There must be NO option in a DAD NS */
215  if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
216  LOG_ERR("NS received is bad\n");
217  goto discard;
218  } else {
219 #endif /*UIP_CONF_IPV6_CHECKS */
220  uip_lladdr_t lladdr_aligned;
221  extract_lladdr_from_llao_aligned(&lladdr_aligned);
222  nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr);
223  if(nbr == NULL) {
224  uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned,
225  0, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL);
226  } else {
227  const uip_lladdr_t *lladdr = uip_ds6_nbr_get_ll(nbr);
228  if(lladdr == NULL) {
229  goto discard;
230  }
231  if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
232  lladdr, UIP_LLADDR_LEN) != 0) {
233  if(uip_ds6_nbr_update_ll(&nbr,
234  (const uip_lladdr_t *)&lladdr_aligned)
235  < 0) {
236  /* failed to update the lladdr */
237  goto discard;
238  }
239  nbr->state = NBR_STALE;
240  } else {
241  if(nbr->state == NBR_INCOMPLETE) {
242  nbr->state = NBR_STALE;
243  }
244  }
245  }
246 #if UIP_CONF_IPV6_CHECKS
247  }
248 #endif /*UIP_CONF_IPV6_CHECKS */
249  break;
250  default:
251  LOG_WARN("ND option not supported in NS");
252  break;
253  }
254  nd6_opt_offset += (ND6_OPT_HDR_BUF(nd6_opt_offset)->len << 3);
255  }
256 
257  addr = uip_ds6_addr_lookup(&UIP_ND6_NS_BUF->tgtipaddr);
258  if(addr != NULL) {
259  if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
260  /* DAD CASE */
261 #if UIP_ND6_DEF_MAXDADNS > 0
262 #if UIP_CONF_IPV6_CHECKS
263  if(!uip_is_addr_solicited_node(&UIP_IP_BUF->destipaddr)) {
264  LOG_ERR("NS received is bad\n");
265  goto discard;
266  }
267 #endif /* UIP_CONF_IPV6_CHECKS */
268  if(addr->state != ADDR_TENTATIVE) {
270  uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
271  flags = UIP_ND6_NA_FLAG_OVERRIDE;
272  goto create_na;
273  } else {
274  /** \todo if I sent a NS before him, I win */
275  uip_ds6_dad_failed(addr);
276  goto discard;
277  }
278 #else /* UIP_ND6_DEF_MAXDADNS > 0 */
279  goto discard; /* DAD CASE */
280 #endif /* UIP_ND6_DEF_MAXDADNS > 0 */
281  }
282 #if UIP_CONF_IPV6_CHECKS
283  if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)) {
284  /**
285  * \NOTE do we do something here? we both are using the same address.
286  * If we are doing dad, we could cancel it, though we should receive a
287  * NA in response of DAD NS we sent, hence DAD will fail anyway. If we
288  * were not doing DAD, it means there is a duplicate in the network!
289  */
290  LOG_ERR("NS received is bad\n");
291  goto discard;
292  }
293 #endif /*UIP_CONF_IPV6_CHECKS */
294 
295  /* Address resolution case */
296  if(uip_is_addr_solicited_node(&UIP_IP_BUF->destipaddr)) {
297  uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr);
298  uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &UIP_ND6_NS_BUF->tgtipaddr);
299  flags = UIP_ND6_NA_FLAG_SOLICITED | UIP_ND6_NA_FLAG_OVERRIDE;
300  goto create_na;
301  }
302 
303  /* NUD CASE */
304  if(uip_ds6_addr_lookup(&UIP_IP_BUF->destipaddr) == addr) {
305  uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr);
306  uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &UIP_ND6_NS_BUF->tgtipaddr);
307  flags = UIP_ND6_NA_FLAG_SOLICITED | UIP_ND6_NA_FLAG_OVERRIDE;
308  goto create_na;
309  } else {
310 #if UIP_CONF_IPV6_CHECKS
311  LOG_ERR("NS received is bad\n");
312  goto discard;
313 #endif /* UIP_CONF_IPV6_CHECKS */
314  }
315  } else {
316  goto discard;
317  }
318 
319 
320 create_na:
321  /* If the node is a router it should set R flag in NAs */
322 #if UIP_CONF_ROUTER
323  flags = flags | UIP_ND6_NA_FLAG_ROUTER;
324 #endif
325  uipbuf_clear();
326  UIP_IP_BUF->vtc = 0x60;
327  UIP_IP_BUF->tcflow = 0;
328  UIP_IP_BUF->flow = 0;
329  uipbuf_set_len_field(UIP_IP_BUF, UIP_ICMPH_LEN + UIP_ND6_NA_LEN + UIP_ND6_OPT_LLAO_LEN);
330  UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
332 
333  UIP_ICMP_BUF->type = ICMP6_NA;
334  UIP_ICMP_BUF->icode = 0;
335 
336  UIP_ND6_NA_BUF->flagsreserved = flags;
337  memcpy(&UIP_ND6_NA_BUF->tgtipaddr, &addr->ipaddr, sizeof(uip_ipaddr_t));
338 
339  create_llao(&uip_buf[uip_l3_icmp_hdr_len + UIP_ND6_NA_LEN],
340  UIP_ND6_OPT_TLLAO);
341 
342  UIP_ICMP_BUF->icmpchksum = 0;
343  UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
344 
345  uipbuf_set_len(UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NA_LEN + UIP_ND6_OPT_LLAO_LEN);
346 
347  UIP_STAT(++uip_stat.nd6.sent);
348  LOG_INFO("Sending NA to ");
349  LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
350  LOG_INFO_(" from ");
351  LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr);
352  LOG_INFO_(" with target address ");
353  LOG_INFO_6ADDR(&UIP_ND6_NA_BUF->tgtipaddr);
354  LOG_INFO_("\n");
355  return;
356 
357 discard:
358  uipbuf_clear();
359  return;
360 }
361 #endif /* UIP_ND6_SEND_NA */
362 
363 
364 /*------------------------------------------------------------------*/
365 #if UIP_ND6_SEND_NS
366 void
367 uip_nd6_ns_output(const uip_ipaddr_t * src, const uip_ipaddr_t * dest,
368  uip_ipaddr_t * tgt)
369 {
370  uipbuf_clear();
371  UIP_IP_BUF->vtc = 0x60;
372  UIP_IP_BUF->tcflow = 0;
373  UIP_IP_BUF->flow = 0;
374  UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
376 
377  if(dest == NULL) {
378  uip_create_solicited_node(tgt, &UIP_IP_BUF->destipaddr);
379  } else {
380  uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, dest);
381  }
382  UIP_ICMP_BUF->type = ICMP6_NS;
383  UIP_ICMP_BUF->icode = 0;
384  UIP_ND6_NS_BUF->reserved = 0;
385  uip_ipaddr_copy((uip_ipaddr_t *) &UIP_ND6_NS_BUF->tgtipaddr, tgt);
386  /*
387  * check if we add a SLLAO option: for DAD, MUST NOT, for NUD, MAY
388  * (here yes), for Address resolution , MUST
389  */
390  if(!(uip_ds6_is_my_addr(tgt))) {
391  if(src != NULL) {
392  uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, src);
393  } else {
394  uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
395  }
396  if (uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
397  LOG_ERR("Dropping NS due to no suitable source address\n");
398  uipbuf_clear();
399  return;
400  }
401  uipbuf_set_len_field(UIP_IP_BUF, UIP_ICMPH_LEN + UIP_ND6_NS_LEN + UIP_ND6_OPT_LLAO_LEN);
402 
403  create_llao(&uip_buf[uip_l3_icmp_hdr_len + UIP_ND6_NS_LEN],
404  UIP_ND6_OPT_SLLAO);
405 
406  uip_len =
407  UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NS_LEN + UIP_ND6_OPT_LLAO_LEN;
408  } else {
409  uip_create_unspecified(&UIP_IP_BUF->srcipaddr);
410  UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_NS_LEN;
411  uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NS_LEN;
412  }
413 
414  UIP_ICMP_BUF->icmpchksum = 0;
415  UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
416 
417  UIP_STAT(++uip_stat.nd6.sent);
418  LOG_INFO("Sending NS to ");
419  LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
420  LOG_INFO_(" from ");
421  LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr);
422  LOG_INFO_(" with target address ");
423  LOG_INFO_6ADDR(tgt);
424  LOG_INFO_("\n");
425  return;
426 }
427 #endif /* UIP_ND6_SEND_NS */
428 
429 #if UIP_ND6_SEND_NS
430 /*------------------------------------------------------------------*/
431 /**
432  * Neighbor Advertisement Processing
433  *
434  * we might have to send a pkt that had been buffered while address
435  * resolution was performed (if we support buffering, see UIP_CONF_QUEUE_PKT)
436  *
437  * As per RFC 4861, on link layer that have addresses, TLLAO options MUST be
438  * included when responding to multicast solicitations, SHOULD be included in
439  * response to unicast (here we assume it is for now)
440  *
441  * NA can be received after sending NS for DAD, Address resolution or NUD. Can
442  * be unsolicited as well.
443  * It can trigger update of the state of the neighbor in the neighbor cache,
444  * router in the router list.
445  * If the NS was for DAD, it means DAD failed
446  *
447  */
448 static void
449 na_input(void)
450 {
451  uint8_t is_llchange;
452  uint8_t is_router;
453  uint8_t is_solicited;
454  uint8_t is_override;
455  uip_lladdr_t lladdr_aligned;
456 
457  LOG_INFO("Received NA from ");
458  LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr);
459  LOG_INFO_(" to ");
460  LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
461  LOG_INFO_(" with target address ");
462  LOG_INFO_6ADDR((uip_ipaddr_t *) (&UIP_ND6_NA_BUF->tgtipaddr));
463  LOG_INFO_("\n");
464  UIP_STAT(++uip_stat.nd6.recv);
465 
466  /*
467  * booleans. the three last one are not 0 or 1 but 0 or 0x80, 0x40, 0x20
468  * but it works. Be careful though, do not use tests such as is_router == 1
469  */
470  is_llchange = 0;
471  is_router = ((UIP_ND6_NA_BUF->flagsreserved & UIP_ND6_NA_FLAG_ROUTER));
472  is_solicited =
473  ((UIP_ND6_NA_BUF->flagsreserved & UIP_ND6_NA_FLAG_SOLICITED));
474  is_override =
475  ((UIP_ND6_NA_BUF->flagsreserved & UIP_ND6_NA_FLAG_OVERRIDE));
476 
477 #if UIP_CONF_IPV6_CHECKS
478  if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) ||
479  (UIP_ICMP_BUF->icode != 0) ||
480  (uip_is_addr_mcast(&UIP_ND6_NA_BUF->tgtipaddr)) ||
481  (is_solicited && uip_is_addr_mcast(&UIP_IP_BUF->destipaddr))) {
482  LOG_ERR("NA received is bad\n");
483  goto discard;
484  }
485 #endif /*UIP_CONF_IPV6_CHECKS */
486 
487  /* Options processing: we handle TLLAO, and must ignore others */
488  nd6_opt_offset = UIP_ND6_NA_LEN;
489  nd6_opt_llao = NULL;
490  while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) {
491 #if UIP_CONF_IPV6_CHECKS
492  if(ND6_OPT_HDR_BUF(nd6_opt_offset)->len == 0) {
493  LOG_ERR("NA received is bad\n");
494  goto discard;
495  }
496 #endif /*UIP_CONF_IPV6_CHECKS */
497  switch (ND6_OPT_HDR_BUF(nd6_opt_offset)->type) {
498  case UIP_ND6_OPT_TLLAO:
499  nd6_opt_llao = (uint8_t *)ND6_OPT_HDR_BUF(nd6_opt_offset);
500  break;
501  default:
502  LOG_WARN("ND option not supported in NA\n");
503  break;
504  }
505  nd6_opt_offset += (ND6_OPT_HDR_BUF(nd6_opt_offset)->len << 3);
506  }
507  addr = uip_ds6_addr_lookup(&UIP_ND6_NA_BUF->tgtipaddr);
508  /* Message processing, including TLLAO if any */
509  if(addr != NULL) {
510 #if UIP_ND6_DEF_MAXDADNS > 0
511  if(addr->state == ADDR_TENTATIVE) {
512  uip_ds6_dad_failed(addr);
513  }
514 #endif /*UIP_ND6_DEF_MAXDADNS > 0 */
515  LOG_ERR("NA received is bad\n");
516  goto discard;
517  } else {
518  const uip_lladdr_t *lladdr;
519  nbr = uip_ds6_nbr_lookup(&UIP_ND6_NA_BUF->tgtipaddr);
520  if(nbr == NULL) {
521  goto discard;
522  }
523  lladdr = uip_ds6_nbr_get_ll(nbr);
524  if(lladdr == NULL) {
525  goto discard;
526  }
527  if(nd6_opt_llao != NULL) {
528  is_llchange =
529  memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], lladdr,
530  UIP_LLADDR_LEN) == 0 ? 0 : 1;
531  }
532  if(nbr->state == NBR_INCOMPLETE) {
533  if(nd6_opt_llao == NULL || !extract_lladdr_from_llao_aligned(&lladdr_aligned)) {
534  goto discard;
535  }
536  if(uip_ds6_nbr_update_ll(&nbr,
537  (const uip_lladdr_t *)&lladdr_aligned) < 0) {
538  /* failed to update the lladdr */
539  goto discard;
540  }
541 
542  /* Note: No need to refresh the state of the nbr here.
543  * It has already been refreshed upon receiving the unicast IPv6 ND packet.
544  * See: uip_ds6_nbr_refresh_reachable_state()
545  */
546  if(!is_solicited) {
547  nbr->state = NBR_STALE;
548  }
549  nbr->isrouter = is_router;
550  } else { /* NBR is not INCOMPLETE */
551  if(!is_override && is_llchange) {
552  if(nbr->state == NBR_REACHABLE) {
553  nbr->state = NBR_STALE;
554  }
555  goto discard;
556  } else {
557  /**
558  * If this is an cache override, or same lladdr, or no llao -
559  * do updates of nbr states.
560  */
561  if(is_override || !is_llchange || nd6_opt_llao == NULL) {
562  if(nd6_opt_llao != NULL && is_llchange) {
563  if(!extract_lladdr_from_llao_aligned(&lladdr_aligned) ||
565  (const uip_lladdr_t *)&lladdr_aligned)
566  < 0) {
567  /* failed to update the lladdr */
568  goto discard;
569  }
570  }
571  /* Note: No need to refresh the state of the nbr here.
572  * It has already been refreshed upon receiving the unicast IPv6 ND packet.
573  * See: uip_ds6_nbr_refresh_reachable_state()
574  */
575  }
576  }
577  if(nbr->isrouter && !is_router) {
578  defrt = uip_ds6_defrt_lookup(&UIP_IP_BUF->srcipaddr);
579  if(defrt != NULL) {
580  uip_ds6_defrt_rm(defrt);
581  }
582  }
583  nbr->isrouter = is_router;
584  }
585  }
586 #if UIP_CONF_IPV6_QUEUE_PKT
587  /* The nbr is now reachable, check if we had buffered a pkt for it */
588  /*if(nbr->queue_buf_len != 0) {
589  uip_len = nbr->queue_buf_len;
590  memcpy(UIP_IP_BUF, nbr->queue_buf, uip_len);
591  nbr->queue_buf_len = 0;
592  return;
593  }*/
594  if(uip_packetqueue_buflen(&nbr->packethandle) != 0) {
595  uip_len = uip_packetqueue_buflen(&nbr->packethandle);
596  memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len);
597  uip_packetqueue_free(&nbr->packethandle);
598  return;
599  }
600 
601 #endif /*UIP_CONF_IPV6_QUEUE_PKT */
602 
603 discard:
604  uipbuf_clear();
605  return;
606 }
607 #endif /* UIP_ND6_SEND_NS */
608 
609 #if UIP_CONF_ROUTER
610 #if UIP_ND6_SEND_RA
611 /*---------------------------------------------------------------------------*/
612 static void
613 rs_input(void)
614 {
615 
616  LOG_INFO("Received RS from ");
617  LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr);
618  LOG_INFO_(" to ");
619  LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
620  LOG_INFO_("\n");
621  UIP_STAT(++uip_stat.nd6.recv);
622 
623 
624 #if UIP_CONF_IPV6_CHECKS
625  /*
626  * Check hop limit / icmp code
627  * target address must not be multicast
628  * if the NA is solicited, dest must not be multicast
629  */
630  if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) || (UIP_ICMP_BUF->icode != 0)) {
631  LOG_ERR("RS received is bad\n");
632  goto discard;
633  }
634 #endif /*UIP_CONF_IPV6_CHECKS */
635 
636  /* Only valid option is Source Link-Layer Address option any thing
637  else is discarded */
638  nd6_opt_offset = UIP_ND6_RS_LEN;
639  nd6_opt_llao = NULL;
640 
641  while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) {
642 #if UIP_CONF_IPV6_CHECKS
643  if(ND6_OPT_HDR_BUF(nd6_opt_offset)->len == 0) {
644  LOG_ERR("RS received is bad\n");
645  goto discard;
646  }
647 #endif /*UIP_CONF_IPV6_CHECKS */
648  switch (ND6_OPT_HDR_BUF(nd6_opt_offset)->type) {
649  case UIP_ND6_OPT_SLLAO:
650  nd6_opt_llao = (uint8_t *)ND6_OPT_HDR_BUF(nd6_opt_offset);
651  break;
652  default:
653  LOG_WARN("ND option not supported in RS\n");
654  break;
655  }
656  nd6_opt_offset += (ND6_OPT_HDR_BUF(nd6_opt_offset)->len << 3);
657  }
658  /* Options processing: only SLLAO */
659  if(nd6_opt_llao != NULL) {
660 #if UIP_CONF_IPV6_CHECKS
661  if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
662  LOG_ERR("RS received is bad\n");
663  goto discard;
664  } else {
665 #endif /*UIP_CONF_IPV6_CHECKS */
666  uip_lladdr_t lladdr_aligned;
667  extract_lladdr_from_llao_aligned(&lladdr_aligned);
668  if((nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr)) == NULL) {
669  /* we need to add the neighbor */
670  uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned,
671  0, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL);
672  } else {
673  /* If LL address changed, set neighbor state to stale */
674  const uip_lladdr_t *lladdr = uip_ds6_nbr_get_ll(nbr);
675  if(lladdr == NULL) {
676  goto discard;
677  }
678  if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
679  lladdr, UIP_LLADDR_LEN) != 0) {
680  uip_ds6_nbr_t nbr_data;
681  nbr_data = *nbr;
682  uip_ds6_nbr_rm(nbr);
683  nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned,
684  0, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL);
685  nbr->reachable = nbr_data.reachable;
686  nbr->sendns = nbr_data.sendns;
687  nbr->nscount = nbr_data.nscount;
688  }
689  nbr->isrouter = 0;
690  }
691 #if UIP_CONF_IPV6_CHECKS
692  }
693 #endif /*UIP_CONF_IPV6_CHECKS */
694  }
695 
696  /* Schedule a sollicited RA */
697  uip_ds6_send_ra_sollicited();
698 
699 discard:
700  uipbuf_clear();
701  return;
702 }
703 
704 /*---------------------------------------------------------------------------*/
705 void
706 uip_nd6_ra_output(const uip_ipaddr_t * dest)
707 {
708 
709  UIP_IP_BUF->vtc = 0x60;
710  UIP_IP_BUF->tcflow = 0;
711  UIP_IP_BUF->flow = 0;
712  UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
714 
715  if(dest == NULL) {
717  } else {
718  /* For sollicited RA */
719  uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, dest);
720  }
721  uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
722 
723  UIP_ICMP_BUF->type = ICMP6_RA;
724  UIP_ICMP_BUF->icode = 0;
725 
726  UIP_ND6_RA_BUF->cur_ttl = uip_ds6_if.cur_hop_limit;
727 
728  UIP_ND6_RA_BUF->flags_reserved =
729  (UIP_ND6_M_FLAG << 7) | (UIP_ND6_O_FLAG << 6);
730 
731  UIP_ND6_RA_BUF->router_lifetime = uip_htons(UIP_ND6_ROUTER_LIFETIME);
732  //UIP_ND6_RA_BUF->reachable_time = uip_htonl(uip_ds6_if.reachable_time);
733  //UIP_ND6_RA_BUF->retrans_timer = uip_htonl(uip_ds6_if.retrans_timer);
734  UIP_ND6_RA_BUF->reachable_time = 0;
735  UIP_ND6_RA_BUF->retrans_timer = 0;
736 
737  uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_RA_LEN;
738  nd6_opt_offset = UIP_ND6_RA_LEN;
739 
740 
741  /* Prefix list */
742  for(prefix = uip_ds6_prefix_list;
743  prefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; prefix++) {
744  if((prefix->isused) && (prefix->advertise)) {
745  ND6_OPT_PREFIX_BUF(nd6_opt_offset)->type = UIP_ND6_OPT_PREFIX_INFO;
746  ND6_OPT_PREFIX_BUF(nd6_opt_offset)->len = UIP_ND6_OPT_PREFIX_INFO_LEN / 8;
747  ND6_OPT_PREFIX_BUF(nd6_opt_offset)->preflen = prefix->length;
748  ND6_OPT_PREFIX_BUF(nd6_opt_offset)->flagsreserved1 = prefix->l_a_reserved;
749  ND6_OPT_PREFIX_BUF(nd6_opt_offset)->validlt = uip_htonl(prefix->vlifetime);
750  ND6_OPT_PREFIX_BUF(nd6_opt_offset)->preferredlt = uip_htonl(prefix->plifetime);
751  ND6_OPT_PREFIX_BUF(nd6_opt_offset)->reserved2 = 0;
752  uip_ipaddr_copy(&(ND6_OPT_PREFIX_BUF(nd6_opt_offset)->prefix), &(prefix->ipaddr));
753  nd6_opt_offset += UIP_ND6_OPT_PREFIX_INFO_LEN;
754  uip_len += UIP_ND6_OPT_PREFIX_INFO_LEN;
755  }
756  }
757 
758  /* Source link-layer option */
759  create_llao((uint8_t *)ND6_OPT_HDR_BUF(nd6_opt_offset), UIP_ND6_OPT_SLLAO);
760 
762  nd6_opt_offset += UIP_ND6_OPT_LLAO_LEN;
763 
764  /* MTU */
765  ND6_OPT_MTU_BUF(nd6_opt_offset)->type = UIP_ND6_OPT_MTU;
766  ND6_OPT_MTU_BUF(nd6_opt_offset)->len = UIP_ND6_OPT_MTU_LEN >> 3;
767  ND6_OPT_MTU_BUF(nd6_opt_offset)->reserved = 0;
768  //ND6_OPT_MTU_BUF(nd6_opt_offset)->mtu = uip_htonl(uip_ds6_if.link_mtu);
769  ND6_OPT_MTU_BUF(nd6_opt_offset)->mtu = uip_htonl(1500);
770 
771  uip_len += UIP_ND6_OPT_MTU_LEN;
772  nd6_opt_offset += UIP_ND6_OPT_MTU_LEN;
773 
774 #if UIP_ND6_RA_RDNSS
775  if(uip_nameserver_count() > 0) {
776  uint8_t i = 0;
777  uip_ipaddr_t *ip = &ND6_OPT_RDNSS_BUF(nd6_opt_offset)->ip;
778  uip_ipaddr_t *dns = NULL;
779  ND6_OPT_RDNSS_BUF(nd6_opt_offset)->type = UIP_ND6_OPT_RDNSS;
780  ND6_OPT_RDNSS_BUF(nd6_opt_offset)->reserved = 0;
781  ND6_OPT_RDNSS_BUF(nd6_opt_offset)->lifetime = uip_nameserver_next_expiration();
782  if(ND6_OPT_RDNSS_BUF(nd6_opt_offset)->lifetime != UIP_NAMESERVER_INFINITE_LIFETIME) {
783  ND6_OPT_RDNSS_BUF(nd6_opt_offset)->lifetime -= clock_seconds();
784  }
785  while((dns = uip_nameserver_get(i)) != NULL) {
786  uip_ipaddr_copy(ip++, dns);
787  i++;
788  }
789  ND6_OPT_RDNSS_BUF(nd6_opt_offset)->len = UIP_ND6_OPT_RDNSS_LEN + (i << 1);
790  LOG_INFO("%d nameservers reported\n", i);
791  uip_len += ND6_OPT_RDNSS_BUF(nd6_opt_offset)->len << 3;
792  nd6_opt_offset += ND6_OPT_RDNSS_BUF(nd6_opt_offset)->len << 3;
793  }
794 #endif /* UIP_ND6_RA_RDNSS */
795 
796  uipbuf_set_len_field(UIP_IP_BUF, uip_len - UIP_IPH_LEN);
797 
798  /*ICMP checksum */
799  UIP_ICMP_BUF->icmpchksum = 0;
800  UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
801 
802  UIP_STAT(++uip_stat.nd6.sent);
803  LOG_INFO("Sending RA to ");
804  LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
805  LOG_INFO_(" from ");
806  LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr);
807  LOG_INFO_("\n");
808  return;
809 }
810 #endif /* UIP_ND6_SEND_RA */
811 #endif /* UIP_CONF_ROUTER */
812 
813 #if !UIP_CONF_ROUTER
814 /*---------------------------------------------------------------------------*/
815 void
817 {
818  UIP_IP_BUF->vtc = 0x60;
819  UIP_IP_BUF->tcflow = 0;
820  UIP_IP_BUF->flow = 0;
821  UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
824  uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
825  UIP_ICMP_BUF->type = ICMP6_RS;
826  UIP_ICMP_BUF->icode = 0;
827 
828  if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
829  UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_RS_LEN;
830  uip_len = uip_l3_icmp_hdr_len + UIP_ND6_RS_LEN;
831  } else {
832  uip_len = uip_l3_icmp_hdr_len + UIP_ND6_RS_LEN + UIP_ND6_OPT_LLAO_LEN;
833  uipbuf_set_len_field(UIP_IP_BUF, UIP_ICMPH_LEN + UIP_ND6_RS_LEN + UIP_ND6_OPT_LLAO_LEN);
834 
835  create_llao(&uip_buf[uip_l3_icmp_hdr_len + UIP_ND6_RS_LEN],
836  UIP_ND6_OPT_SLLAO);
837  }
838 
839  UIP_ICMP_BUF->icmpchksum = 0;
840  UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
841 
842  UIP_STAT(++uip_stat.nd6.sent);
843  LOG_INFO("Sending RS to ");
844  LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
845  LOG_INFO_(" from ");
846  LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr);
847  LOG_INFO_("\n");
848  return;
849 }
850 /*---------------------------------------------------------------------------*/
851 /**
852  * Process a Router Advertisement
853  *
854  * - Possible actions when receiving a RA: add router to router list,
855  * recalculate reachable time, update link hop limit, update retrans timer.
856  * - If MTU option: update MTU.
857  * - If SLLAO option: update entry in neighbor cache
858  * - If prefix option: start autoconf, add prefix to prefix list
859  */
860 void
861 ra_input(void)
862 {
863  uip_lladdr_t lladdr_aligned;
864 
865  LOG_INFO("Received RA from ");
866  LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr);
867  LOG_INFO_(" to ");
868  LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
869  LOG_INFO_("\n");
870  UIP_STAT(++uip_stat.nd6.recv);
871 
872 #if UIP_CONF_IPV6_CHECKS
873  if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) ||
874  (!uip_is_addr_linklocal(&UIP_IP_BUF->srcipaddr)) ||
875  (UIP_ICMP_BUF->icode != 0)) {
876  LOG_ERR("RA received is bad");
877  goto discard;
878  }
879 #endif /*UIP_CONF_IPV6_CHECKS */
880 
881  if(UIP_ND6_RA_BUF->cur_ttl != 0) {
882  uip_ds6_if.cur_hop_limit = UIP_ND6_RA_BUF->cur_ttl;
883  LOG_INFO("uip_ds6_if.cur_hop_limit %u\n", uip_ds6_if.cur_hop_limit);
884  }
885 
886  if(UIP_ND6_RA_BUF->reachable_time != 0) {
887  if(uip_ds6_if.base_reachable_time !=
888  uip_ntohl(UIP_ND6_RA_BUF->reachable_time)) {
889  uip_ds6_if.base_reachable_time = uip_ntohl(UIP_ND6_RA_BUF->reachable_time);
890  uip_ds6_if.reachable_time = uip_ds6_compute_reachable_time();
891  }
892  }
893  if(UIP_ND6_RA_BUF->retrans_timer != 0) {
894  uip_ds6_if.retrans_timer = uip_ntohl(UIP_ND6_RA_BUF->retrans_timer);
895  }
896 
897  /* Options processing */
898  nd6_opt_offset = UIP_ND6_RA_LEN;
899  while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) {
900  if(ND6_OPT_HDR_BUF(nd6_opt_offset)->len == 0) {
901  LOG_ERR("RA received is bad");
902  goto discard;
903  }
904  switch (ND6_OPT_HDR_BUF(nd6_opt_offset)->type) {
905  case UIP_ND6_OPT_SLLAO:
906  LOG_DBG("Processing SLLAO option in RA\n");
907  nd6_opt_llao = (uint8_t *) ND6_OPT_HDR_BUF(nd6_opt_offset);
908  nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr);
909  if(!extract_lladdr_from_llao_aligned(&lladdr_aligned)) {
910  /* failed to extract llao - discard packet */
911  goto discard;
912  }
913  if(nbr == NULL) {
914  nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned,
915  1, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL);
916  } else {
917  const uip_lladdr_t *lladdr = uip_ds6_nbr_get_ll(nbr);
918  if(lladdr == NULL) {
919  goto discard;
920  }
921  if(nbr->state == NBR_INCOMPLETE) {
922  nbr->state = NBR_STALE;
923  }
924  if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
925  lladdr, UIP_LLADDR_LEN) != 0) {
926  /* change of link layer address */
927  if(uip_ds6_nbr_update_ll(&nbr,
928  (const uip_lladdr_t *)&lladdr_aligned) < 0) {
929  /* failed to update the lladdr */
930  goto discard;
931  }
932  nbr->state = NBR_STALE;
933  }
934  nbr->isrouter = 1;
935  }
936  break;
937  case UIP_ND6_OPT_MTU:
938  LOG_DBG("Processing MTU option in RA\n");
939  uip_ds6_if.link_mtu =
940  uip_ntohl(((uip_nd6_opt_mtu *) ND6_OPT_HDR_BUF(nd6_opt_offset))->mtu);
941  break;
942  case UIP_ND6_OPT_PREFIX_INFO:
943  LOG_DBG("Processing PREFIX option in RA\n");
944  nd6_opt_prefix_info = (uip_nd6_opt_prefix_info *) ND6_OPT_HDR_BUF(nd6_opt_offset);
945  if((uip_ntohl(nd6_opt_prefix_info->validlt) >=
946  uip_ntohl(nd6_opt_prefix_info->preferredlt))
947  && (!uip_is_addr_linklocal(&nd6_opt_prefix_info->prefix))) {
948  /* on-link flag related processing */
949  if(nd6_opt_prefix_info->flagsreserved1 & UIP_ND6_RA_FLAG_ONLINK) {
950  prefix =
951  uip_ds6_prefix_lookup(&nd6_opt_prefix_info->prefix,
952  nd6_opt_prefix_info->preflen);
953  if(prefix == NULL) {
954  if(nd6_opt_prefix_info->validlt != 0) {
955  if(nd6_opt_prefix_info->validlt != UIP_ND6_INFINITE_LIFETIME) {
956  prefix = uip_ds6_prefix_add(&nd6_opt_prefix_info->prefix,
957  nd6_opt_prefix_info->preflen,
958  uip_ntohl(nd6_opt_prefix_info->
959  validlt));
960  } else {
961  prefix = uip_ds6_prefix_add(&nd6_opt_prefix_info->prefix,
962  nd6_opt_prefix_info->preflen, 0);
963  }
964  }
965  } else {
966  switch (nd6_opt_prefix_info->validlt) {
967  case 0:
968  uip_ds6_prefix_rm(prefix);
969  break;
971  prefix->isinfinite = 1;
972  break;
973  default:
974  LOG_DBG("Updating timer of prefix ");
975  LOG_DBG_6ADDR(&prefix->ipaddr);
976  LOG_DBG_(" new value %"PRIu32"\n", uip_ntohl(nd6_opt_prefix_info->validlt));
977  stimer_set(&prefix->vlifetime,
978  uip_ntohl(nd6_opt_prefix_info->validlt));
979  prefix->isinfinite = 0;
980  break;
981  }
982  }
983  }
984  /* End of on-link flag related processing */
985  /* autonomous flag related processing */
986  if((nd6_opt_prefix_info->flagsreserved1 & UIP_ND6_RA_FLAG_AUTONOMOUS)
987  && (nd6_opt_prefix_info->validlt != 0)
988  && (nd6_opt_prefix_info->preflen == UIP_DEFAULT_PREFIX_LEN)) {
989 
990  uip_ipaddr_copy(&ipaddr, &nd6_opt_prefix_info->prefix);
992  addr = uip_ds6_addr_lookup(&ipaddr);
993  if((addr != NULL) && (addr->type == ADDR_AUTOCONF)) {
994  if(nd6_opt_prefix_info->validlt != UIP_ND6_INFINITE_LIFETIME) {
995  /* The processing below is defined in RFC4862 section 5.5.3 e */
996  if((uip_ntohl(nd6_opt_prefix_info->validlt) > 2 * 60 * 60) ||
997  (uip_ntohl(nd6_opt_prefix_info->validlt) >
998  stimer_remaining(&addr->vlifetime))) {
999  LOG_DBG("Updating timer of address ");
1000  LOG_DBG_6ADDR(&addr->ipaddr);
1001  LOG_DBG_(" new value %lu\n",
1002  (unsigned long)uip_ntohl(nd6_opt_prefix_info->validlt));
1003  stimer_set(&addr->vlifetime,
1004  uip_ntohl(nd6_opt_prefix_info->validlt));
1005  } else {
1006  stimer_set(&addr->vlifetime, 2 * 60 * 60);
1007  LOG_DBG("Updating timer of address ");
1008  LOG_DBG_6ADDR(&addr->ipaddr);
1009  LOG_DBG_(" new value %lu\n", (unsigned long)(2 * 60 * 60));
1010  }
1011  addr->isinfinite = 0;
1012  } else {
1013  addr->isinfinite = 1;
1014  }
1015  } else {
1016  if(uip_ntohl(nd6_opt_prefix_info->validlt) ==
1018  uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF);
1019  } else {
1020  uip_ds6_addr_add(&ipaddr, uip_ntohl(nd6_opt_prefix_info->validlt),
1021  ADDR_AUTOCONF);
1022  }
1023  }
1024  }
1025  /* End of autonomous flag related processing */
1026  }
1027  break;
1028 #if UIP_ND6_RA_RDNSS
1029  case UIP_ND6_OPT_RDNSS:
1030  LOG_DBG("Processing RDNSS option\n");
1031  uint8_t naddr = (ND6_OPT_RDNSS_BUF(nd6_opt_offset)->len - 1) / 2;
1032  uip_ipaddr_t *ip = (uip_ipaddr_t *)(&ND6_OPT_RDNSS_BUF(nd6_opt_offset)->ip);
1033  LOG_DBG("got %d nameservers\n", naddr);
1034  while(naddr-- > 0) {
1035  LOG_DBG("nameserver: ");
1036  LOG_DBG_6ADDR(ip);
1037  LOG_DBG_(" lifetime: %"PRIx32"\n", uip_ntohl(ND6_OPT_RDNSS_BUF(nd6_opt_offset)->lifetime));
1038  uip_nameserver_update(ip, uip_ntohl(ND6_OPT_RDNSS_BUF(nd6_opt_offset)->lifetime));
1039  ip++;
1040  }
1041  break;
1042 #endif /* UIP_ND6_RA_RDNSS */
1043  default:
1044  LOG_ERR("ND option not supported in RA\n");
1045  break;
1046  }
1047  nd6_opt_offset += (ND6_OPT_HDR_BUF(nd6_opt_offset)->len << 3);
1048  }
1049 
1050  defrt = uip_ds6_defrt_lookup(&UIP_IP_BUF->srcipaddr);
1051  if(UIP_ND6_RA_BUF->router_lifetime != 0) {
1052  if(nbr != NULL) {
1053  nbr->isrouter = 1;
1054  }
1055  if(defrt == NULL) {
1056  uip_ds6_defrt_add(&UIP_IP_BUF->srcipaddr,
1057  (unsigned
1058  long)(uip_ntohs(UIP_ND6_RA_BUF->router_lifetime)));
1059  } else {
1060  stimer_set(&(defrt->lifetime),
1061  (unsigned long)(uip_ntohs(UIP_ND6_RA_BUF->router_lifetime)));
1062  }
1063  } else {
1064  if(defrt != NULL) {
1065  uip_ds6_defrt_rm(defrt);
1066  }
1067  }
1068 
1069 #if UIP_CONF_IPV6_QUEUE_PKT
1070  /* If the nbr just became reachable (e.g. it was in NBR_INCOMPLETE state
1071  * and we got a SLLAO), check if we had buffered a pkt for it */
1072  /* if((nbr != NULL) && (nbr->queue_buf_len != 0)) {
1073  uip_len = nbr->queue_buf_len;
1074  memcpy(UIP_IP_BUF, nbr->queue_buf, uip_len);
1075  nbr->queue_buf_len = 0;
1076  return;
1077  }*/
1078  if(nbr != NULL && uip_packetqueue_buflen(&nbr->packethandle) != 0) {
1079  uip_len = uip_packetqueue_buflen(&nbr->packethandle);
1080  memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len);
1081  uip_packetqueue_free(&nbr->packethandle);
1082  return;
1083  }
1084 
1085 #endif /*UIP_CONF_IPV6_QUEUE_PKT */
1086 
1087 discard:
1088  uipbuf_clear();
1089  return;
1090 }
1091 #endif /* !UIP_CONF_ROUTER */
1092 /*------------------------------------------------------------------*/
1093 /* ICMPv6 input handlers */
1094 #if UIP_ND6_SEND_NA
1095 UIP_ICMP6_HANDLER(ns_input_handler, ICMP6_NS, UIP_ICMP6_HANDLER_CODE_ANY,
1096  ns_input);
1097 #endif
1098 #if UIP_ND6_SEND_NS
1099 UIP_ICMP6_HANDLER(na_input_handler, ICMP6_NA, UIP_ICMP6_HANDLER_CODE_ANY,
1100  na_input);
1101 #endif
1102 
1103 #if UIP_CONF_ROUTER && UIP_ND6_SEND_RA
1104 UIP_ICMP6_HANDLER(rs_input_handler, ICMP6_RS, UIP_ICMP6_HANDLER_CODE_ANY,
1105  rs_input);
1106 #endif
1107 
1108 #if !UIP_CONF_ROUTER
1109 UIP_ICMP6_HANDLER(ra_input_handler, ICMP6_RA, UIP_ICMP6_HANDLER_CODE_ANY,
1110  ra_input);
1111 #endif
1112 /*---------------------------------------------------------------------------*/
1113 void
1115 {
1116 #if UIP_ND6_SEND_NA
1117  /* Only handle NSs if we are prepared to send out NAs */
1118  uip_icmp6_register_input_handler(&ns_input_handler);
1119 #endif
1120 
1121 #if UIP_ND6_SEND_NS
1122  /*
1123  * Only handle NAs if we are prepared to send out NSs. */
1124  uip_icmp6_register_input_handler(&na_input_handler);
1125 #endif
1126 
1127 #if UIP_CONF_ROUTER && UIP_ND6_SEND_RA
1128  /* Only accept RS if we are a router and happy to send out RAs */
1129  uip_icmp6_register_input_handler(&rs_input_handler);
1130 #endif
1131 
1132 #if !UIP_CONF_ROUTER
1133  /* Only process RAs if we are not a router */
1134  uip_icmp6_register_input_handler(&ra_input_handler);
1135 #endif
1136 }
1137 /*---------------------------------------------------------------------------*/
1138  /** @} */
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
Definition: uip-nd6.c:116
#define UIP_IP_BUF
Direct access to IPv6 header.
Definition: uip.h:71
An entry in the default router list.
uip_lladdr_t uip_lladdr
Host L2 address.
Definition: uip6.c:107
Header file for ICMPv6 message and error handing (RFC 4443)
ND option MTU.
Definition: uip-nd6.h:342
#define UIP_ND6_OPT_LLAO_LEN
length of a ND6 LLAO option for default L2 type (e.g.
Definition: uip-nd6.h:243
static uip_ds6_nbr_t * nbr
Pointer to llao option in uip_buf.
Definition: uip-nd6.c:106
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 ra_input(void)
Process a Router Advertisement.
Definition: uip-nd6.c:861
#define UIP_ICMP_BUF
Direct access to ICMP, UDP, and TCP headers and payload, with implicit ext header offset (global uip_...
Definition: uip.h:77
uint32_t uip_nameserver_next_expiration(void)
Get next expiration time.
#define UIP_NAMESERVER_INFINITE_LIFETIME
Infinite Lifetime indicator.
void uip_nd6_init()
Initialise the uIP ND core.
Definition: uip-nd6.c:1114
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
static int extract_lladdr_from_llao_aligned(uip_lladdr_t *dest)
Pointer to a prefix list entry.
Definition: uip-nd6.c:126
unsigned long clock_seconds(void)
Get the current value of the platform seconds.
Definition: clock.c:130
uip_ds6_prefix_t uip_ds6_prefix_list[UIP_DS6_PREFIX_NB]
Prefix list.
Definition: uip-ds6.c:76
uint16_t uip_htons(uint16_t val)
Convert a 16-bit quantity from host byte order to network byte order.
Definition: uip6.c:2347
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 ICMP6_RA
Router Advertisement.
Definition: uip-icmp6.h:61
#define UIP_LLADDR_LEN
802.15.4 address
Definition: uip.h:145
void uip_nd6_ns_output(const uip_ipaddr_t *src, const uip_ipaddr_t *dest, uip_ipaddr_t *tgt)
Send a neighbor solicitation, send a Neighbor Advertisement.
void stimer_set(struct stimer *t, unsigned long interval)
Set a timer.
Definition: stimer.c:67
void uip_nameserver_update(const uip_ipaddr_t *nameserver, uint32_t lifetime)
Initialize the module variables.
static uint8_t * nd6_opt_llao
Offset from the end of the icmpv6 header to the option in uip_buf.
Definition: uip-nd6.c:105
#define uip_create_linklocal_allnodes_mcast(a)
set IP address a to the link local all-nodes multicast address
Definition: uip.h:1809
uip_ds6_nbr_t * uip_ds6_nbr_lookup(const uip_ipaddr_t *ipaddr)
Get the neighbor cache associated with a specified IPv6 address.
Definition: uip-ds6-nbr.c:467
#define UIP_ND6_INFINITE_LIFETIME
INFINITE lifetime.
Definition: uip-nd6.h:57
uIP Name Server interface
#define uip_is_addr_unspecified(a)
Is IPv6 address a the unspecified address a is of type uip_ipaddr_t.
Definition: uip.h:1760
#define uip_buf
Macro to access uip_aligned_buf as an array of bytes.
Definition: uip.h:465
Unicast address structure.
Definition: uip-ds6.h:205
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
Definition: uip.h:969
#define uip_is_addr_solicited_node(a)
is addr (a) a solicited node multicast address, see RFC 4291 a is of type uip_ipaddr_t* ...
Definition: uip.h:1824
#define ICMP6_NS
Neighbor Solicitation.
Definition: uip-icmp6.h:62
#define UIP_STAT(s)
The uIP TCP/IP statistics.
Definition: uip.h:1351
#define uip_create_linklocal_allrouters_mcast(a)
set IP address a to the link local all-routers multicast address
Definition: uip.h:1812
#define ADDR_TENTATIVE
Possible states for the an address (RFC 4862)
Definition: uip-ds6.h:156
ND option prefix information.
Definition: uip-nd6.h:330
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
#define NBR_INCOMPLETE
Possible states for the nbr cache entries.
Definition: uip-ds6-nbr.h:64
#define uip_is_addr_mcast(a)
is address a multicast address, see RFC 4291 a is of type uip_ipaddr_t*
Definition: uip.h:1885
static uip_nd6_opt_prefix_info * nd6_opt_prefix_info
Pointer to a router list entry.
Definition: uip-nd6.c:115
#define ICMP6_RS
Router Solicitation.
Definition: uip-icmp6.h:60
#define uip_create_unspecified(a)
set IP address a to unspecified
Definition: uip.h:1806
#define ICMP6_NA
Neighbor advertisement.
Definition: uip-icmp6.h:63
uip_ds6_nbr_t * uip_ds6_nbr_add(const uip_ipaddr_t *ipaddr, const uip_lladdr_t *lladdr, uint8_t isrouter, uint8_t state, nbr_table_reason_t reason, void *data)
Add a neighbor cache for a specified IPv6 address, which is associated with a specified link-layer ad...
Definition: uip-ds6-nbr.c:122
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:195
uint16_t uip_icmp6chksum(void)
Calculate the ICMP checksum of the packet in uip_buf.
Definition: uip6.c:363
#define UIP_ND6_HOP_LIMIT
HOP LIMIT to be used when sending ND messages (255)
Definition: uip-nd6.h:55
int uip_ds6_nbr_update_ll(uip_ds6_nbr_t **nbr_pp, const uip_lladdr_t *new_ll_addr)
Update the link-layer address associated with an IPv6 address.
Definition: uip-ds6-nbr.c:317
int uip_ds6_nbr_rm(uip_ds6_nbr_t *nbr)
Remove a neighbor cache.
Definition: uip-ds6-nbr.c:294
void uip_icmp6_register_input_handler(uip_icmp6_input_handler_t *handler)
Register a handler which can handle a specific ICMPv6 message type.
Definition: uip-icmp6.c:102
const uip_lladdr_t * uip_ds6_nbr_get_ll(const uip_ds6_nbr_t *nbr)
Get the link-layer address associated with a specified nbr cache.
Definition: uip-ds6-nbr.c:392
#define uip_is_addr_linklocal(a)
is addr (a) a link local unicast address, see RFC 4291 i.e.
Definition: uip.h:1801
static uip_ds6_defrt_t * defrt
Pointer to an interface address.
Definition: uip-nd6.c:111
Header file for the logging system
uint16_t uip_nameserver_count(void)
Get the number of recorded name servers.
void uip_nd6_rs_output(void)
Neighbor Solicitation Processing.
Definition: uip-nd6.c:816
uip_ipaddr_t * uip_nameserver_get(uint8_t num)
Get a Nameserver ip address given in RA.
#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:1839
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
The default nbr_table entry (when UIP_DS6_NBR_MULTI_IPV6_ADDRS is disabled), that implements nbr cach...
Definition: uip-ds6-nbr.h:105