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 "net/ipv6/uip-icmp6.h"
73 #include "net/ipv6/uip-nd6.h"
74 #include "net/ipv6/uip-ds6.h"
76 #include "lib/random.h"
77 
78 /* Log configuration */
79 #include "sys/log.h"
80 #define LOG_MODULE "IPv6 NDP"
81 #define LOG_LEVEL LOG_LEVEL_IPV6
82 
83 /*------------------------------------------------------------------*/
84 /** @{ */
85 /** \name Pointers to the header structures.
86  * All pointers except UIP_IP_BUF depend on uip_ext_len, which at
87  * packet reception, is the total length of the extension headers.
88  *
89  * The pointer to ND6 options header also depends on nd6_opt_offset,
90  * which we set in each function.
91  *
92  * Care should be taken when manipulating these buffers about the
93  * value of these length variables
94  */
95 
96 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) /**< Pointer to IP header */
97 #define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[uip_l2_l3_hdr_len]) /**< Pointer to ICMP header*/
98 /**@{ Pointers to messages just after icmp header */
99 #define UIP_ND6_RS_BUF ((uip_nd6_rs *)&uip_buf[uip_l2_l3_icmp_hdr_len])
100 #define UIP_ND6_RA_BUF ((uip_nd6_ra *)&uip_buf[uip_l2_l3_icmp_hdr_len])
101 #define UIP_ND6_NS_BUF ((uip_nd6_ns *)&uip_buf[uip_l2_l3_icmp_hdr_len])
102 #define UIP_ND6_NA_BUF ((uip_nd6_na *)&uip_buf[uip_l2_l3_icmp_hdr_len])
103 /** @} */
104 /** Pointer to ND option */
105 #define UIP_ND6_OPT_HDR_BUF ((uip_nd6_opt_hdr *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset])
106 #define UIP_ND6_OPT_PREFIX_BUF ((uip_nd6_opt_prefix_info *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset])
107 #define UIP_ND6_OPT_MTU_BUF ((uip_nd6_opt_mtu *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset])
108 #define UIP_ND6_OPT_RDNSS_BUF ((uip_nd6_opt_dns *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset])
109 /** @} */
110 
111 #if UIP_ND6_SEND_NS || UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER
112 static uint8_t nd6_opt_offset; /** Offset from the end of the icmpv6 header to the option in uip_buf*/
113 static uint8_t *nd6_opt_llao; /** Pointer to llao option in uip_buf */
114 static uip_ds6_nbr_t *nbr; /** Pointer to a nbr cache entry*/
115 static uip_ds6_addr_t *addr; /** Pointer to an interface address */
116 #endif /* UIP_ND6_SEND_NS || UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER */
117 
118 #if UIP_ND6_SEND_NS || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER
119 static uip_ds6_defrt_t *defrt; /** Pointer to a router list entry */
120 #endif /* UIP_ND6_SEND_NS || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER */
121 
122 #if !UIP_CONF_ROUTER // TBD see if we move it to ra_input
123 static uip_nd6_opt_prefix_info *nd6_opt_prefix_info; /** Pointer to prefix information option in uip_buf */
124 static uip_ipaddr_t ipaddr;
125 #endif
126 #if (!UIP_CONF_ROUTER || UIP_ND6_SEND_RA)
127 static uip_ds6_prefix_t *prefix; /** Pointer to a prefix list entry */
128 #endif
129 
130 #if UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER
131 /*------------------------------------------------------------------*/
132 /* Copy link-layer address from LLAO option to a word-aligned uip_lladdr_t */
133 static int
134 extract_lladdr_from_llao_aligned(uip_lladdr_t *dest) {
135  if(dest != NULL && nd6_opt_llao != NULL) {
136  memcpy(dest, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], UIP_LLADDR_LEN);
137  return 1;
138  }
139  return 0;
140 }
141 #endif /* UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER */
142 /*------------------------------------------------------------------*/
143 #if UIP_ND6_SEND_NA /* UIP_ND6_SEND_NA */
144 /* create a llao */
145 static void
146 create_llao(uint8_t *llao, uint8_t type) {
147  llao[UIP_ND6_OPT_TYPE_OFFSET] = type;
148  llao[UIP_ND6_OPT_LEN_OFFSET] = UIP_ND6_OPT_LLAO_LEN >> 3;
149  memcpy(&llao[UIP_ND6_OPT_DATA_OFFSET], &uip_lladdr, UIP_LLADDR_LEN);
150  /* padding on some */
151  memset(&llao[UIP_ND6_OPT_DATA_OFFSET + UIP_LLADDR_LEN], 0,
153 }
154 #endif /* UIP_ND6_SEND_NA */
155 /*------------------------------------------------------------------*/
156  /**
157  * Neighbor Solicitation Processing
158  *
159  * The NS can be received in 3 cases (procedures):
160  * - sender is performing DAD (ip src = unspecified, no SLLAO option)
161  * - sender is performing NUD (ip dst = unicast)
162  * - sender is performing address resolution (ip dest = solicited node mcast
163  * address)
164  *
165  * We do:
166  * - if the tgt belongs to me, reply, otherwise ignore
167  * - if i was performing DAD for the same address, two cases:
168  * -- I already sent a NS, hence I win
169  * -- I did not send a NS yet, hence I lose
170  *
171  * If we need to send a NA in response (i.e. the NS was done for NUD, or
172  * address resolution, or DAD and there is a conflict), we do it in this
173  * function: set src, dst, tgt address in the three cases, then for all cases
174  * set the rest, including SLLAO
175  *
176  */
177 #if UIP_ND6_SEND_NA
178 static void
179 ns_input(void)
180 {
181  uint8_t flags;
182  LOG_INFO("Received NS from ");
183  LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr);
184  LOG_INFO_(" to ");
185  LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
186  LOG_INFO_(" with target address ");
187  LOG_INFO_6ADDR((uip_ipaddr_t *) (&UIP_ND6_NS_BUF->tgtipaddr));
188  LOG_INFO_("\n");
189  UIP_STAT(++uip_stat.nd6.recv);
190 
191 #if UIP_CONF_IPV6_CHECKS
192  if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) ||
193  (uip_is_addr_mcast(&UIP_ND6_NS_BUF->tgtipaddr)) ||
194  (UIP_ICMP_BUF->icode != 0)) {
195  LOG_ERR("NS received is bad\n");
196  goto discard;
197  }
198 #endif /* UIP_CONF_IPV6_CHECKS */
199 
200  /* Options processing */
201  nd6_opt_llao = NULL;
202  nd6_opt_offset = UIP_ND6_NS_LEN;
203  while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) {
204 #if UIP_CONF_IPV6_CHECKS
205  if(UIP_ND6_OPT_HDR_BUF->len == 0) {
206  LOG_ERR("NS received is bad\n");
207  goto discard;
208  }
209 #endif /* UIP_CONF_IPV6_CHECKS */
210  switch (UIP_ND6_OPT_HDR_BUF->type) {
211  case UIP_ND6_OPT_SLLAO:
212  nd6_opt_llao = &uip_buf[uip_l2_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 += (UIP_ND6_OPT_HDR_BUF->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  uip_ext_len = 0;
326  UIP_IP_BUF->vtc = 0x60;
327  UIP_IP_BUF->tcflow = 0;
328  UIP_IP_BUF->flow = 0;
329  UIP_IP_BUF->len[0] = 0; /* length will not be more than 255 */
330  UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_NA_LEN + UIP_ND6_OPT_LLAO_LEN;
331  UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
333 
334  UIP_ICMP_BUF->type = ICMP6_NA;
335  UIP_ICMP_BUF->icode = 0;
336 
337  UIP_ND6_NA_BUF->flagsreserved = flags;
338  memcpy(&UIP_ND6_NA_BUF->tgtipaddr, &addr->ipaddr, sizeof(uip_ipaddr_t));
339 
340  create_llao(&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_NA_LEN],
341  UIP_ND6_OPT_TLLAO);
342 
343  UIP_ICMP_BUF->icmpchksum = 0;
344  UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
345 
346  uip_len =
347  UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NA_LEN + UIP_ND6_OPT_LLAO_LEN;
348 
349  UIP_STAT(++uip_stat.nd6.sent);
350  LOG_INFO("Sending NA to ");
351  LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
352  LOG_INFO_(" from ");
353  LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr);
354  LOG_INFO_(" with target address ");
355  LOG_INFO_6ADDR(&UIP_ND6_NA_BUF->tgtipaddr);
356  LOG_INFO_("\n");
357  return;
358 
359 discard:
360  uip_clear_buf();
361  return;
362 }
363 #endif /* UIP_ND6_SEND_NA */
364 
365 
366 /*------------------------------------------------------------------*/
367 #if UIP_ND6_SEND_NS
368 void
369 uip_nd6_ns_output(uip_ipaddr_t * src, uip_ipaddr_t * dest, uip_ipaddr_t * tgt)
370 {
371  uip_ext_len = 0;
372  UIP_IP_BUF->vtc = 0x60;
373  UIP_IP_BUF->tcflow = 0;
374  UIP_IP_BUF->flow = 0;
375  UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
377 
378  if(dest == NULL) {
379  uip_create_solicited_node(tgt, &UIP_IP_BUF->destipaddr);
380  } else {
381  uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, dest);
382  }
383  UIP_ICMP_BUF->type = ICMP6_NS;
384  UIP_ICMP_BUF->icode = 0;
385  UIP_ND6_NS_BUF->reserved = 0;
386  uip_ipaddr_copy((uip_ipaddr_t *) &UIP_ND6_NS_BUF->tgtipaddr, tgt);
387  UIP_IP_BUF->len[0] = 0; /* length will not be more than 255 */
388  /*
389  * check if we add a SLLAO option: for DAD, MUST NOT, for NUD, MAY
390  * (here yes), for Address resolution , MUST
391  */
392  if(!(uip_ds6_is_my_addr(tgt))) {
393  if(src != NULL) {
394  uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, src);
395  } else {
396  uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
397  }
398  if (uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
399  LOG_ERR("Dropping NS due to no suitable source address\n");
400  uip_clear_buf();
401  return;
402  }
403  UIP_IP_BUF->len[1] =
404  UIP_ICMPH_LEN + UIP_ND6_NS_LEN + UIP_ND6_OPT_LLAO_LEN;
405 
406  create_llao(&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_NS_LEN],
407  UIP_ND6_OPT_SLLAO);
408 
409  uip_len =
410  UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NS_LEN + UIP_ND6_OPT_LLAO_LEN;
411  } else {
412  uip_create_unspecified(&UIP_IP_BUF->srcipaddr);
413  UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_NS_LEN;
414  uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NS_LEN;
415  }
416 
417  UIP_ICMP_BUF->icmpchksum = 0;
418  UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
419 
420  UIP_STAT(++uip_stat.nd6.sent);
421  LOG_INFO("Sending NS to ");
422  LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
423  LOG_INFO_(" from ");
424  LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr);
425  LOG_INFO_(" with target address ");
426  LOG_INFO_6ADDR(tgt);
427  LOG_INFO_("\n");
428  return;
429 }
430 #endif /* UIP_ND6_SEND_NS */
431 
432 #if UIP_ND6_SEND_NS
433 /*------------------------------------------------------------------*/
434 /**
435  * Neighbor Advertisement Processing
436  *
437  * we might have to send a pkt that had been buffered while address
438  * resolution was performed (if we support buffering, see UIP_CONF_QUEUE_PKT)
439  *
440  * As per RFC 4861, on link layer that have addresses, TLLAO options MUST be
441  * included when responding to multicast solicitations, SHOULD be included in
442  * response to unicast (here we assume it is for now)
443  *
444  * NA can be received after sending NS for DAD, Address resolution or NUD. Can
445  * be unsolicited as well.
446  * It can trigger update of the state of the neighbor in the neighbor cache,
447  * router in the router list.
448  * If the NS was for DAD, it means DAD failed
449  *
450  */
451 static void
452 na_input(void)
453 {
454  uint8_t is_llchange;
455  uint8_t is_router;
456  uint8_t is_solicited;
457  uint8_t is_override;
458  uip_lladdr_t lladdr_aligned;
459 
460  LOG_INFO("Received NA from ");
461  LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr);
462  LOG_INFO_(" to ");
463  LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
464  LOG_INFO_(" with target address ");
465  LOG_INFO_6ADDR((uip_ipaddr_t *) (&UIP_ND6_NA_BUF->tgtipaddr));
466  LOG_INFO_("\n");
467  UIP_STAT(++uip_stat.nd6.recv);
468 
469  /*
470  * booleans. the three last one are not 0 or 1 but 0 or 0x80, 0x40, 0x20
471  * but it works. Be careful though, do not use tests such as is_router == 1
472  */
473  is_llchange = 0;
474  is_router = ((UIP_ND6_NA_BUF->flagsreserved & UIP_ND6_NA_FLAG_ROUTER));
475  is_solicited =
476  ((UIP_ND6_NA_BUF->flagsreserved & UIP_ND6_NA_FLAG_SOLICITED));
477  is_override =
478  ((UIP_ND6_NA_BUF->flagsreserved & UIP_ND6_NA_FLAG_OVERRIDE));
479 
480 #if UIP_CONF_IPV6_CHECKS
481  if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) ||
482  (UIP_ICMP_BUF->icode != 0) ||
483  (uip_is_addr_mcast(&UIP_ND6_NA_BUF->tgtipaddr)) ||
484  (is_solicited && uip_is_addr_mcast(&UIP_IP_BUF->destipaddr))) {
485  LOG_ERR("NA received is bad\n");
486  goto discard;
487  }
488 #endif /*UIP_CONF_IPV6_CHECKS */
489 
490  /* Options processing: we handle TLLAO, and must ignore others */
491  nd6_opt_offset = UIP_ND6_NA_LEN;
492  nd6_opt_llao = NULL;
493  while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) {
494 #if UIP_CONF_IPV6_CHECKS
495  if(UIP_ND6_OPT_HDR_BUF->len == 0) {
496  LOG_ERR("NA received is bad\n");
497  goto discard;
498  }
499 #endif /*UIP_CONF_IPV6_CHECKS */
500  switch (UIP_ND6_OPT_HDR_BUF->type) {
501  case UIP_ND6_OPT_TLLAO:
502  nd6_opt_llao = (uint8_t *)UIP_ND6_OPT_HDR_BUF;
503  break;
504  default:
505  LOG_WARN("ND option not supported in NA\n");
506  break;
507  }
508  nd6_opt_offset += (UIP_ND6_OPT_HDR_BUF->len << 3);
509  }
510  addr = uip_ds6_addr_lookup(&UIP_ND6_NA_BUF->tgtipaddr);
511  /* Message processing, including TLLAO if any */
512  if(addr != NULL) {
513 #if UIP_ND6_DEF_MAXDADNS > 0
514  if(addr->state == ADDR_TENTATIVE) {
515  uip_ds6_dad_failed(addr);
516  }
517 #endif /*UIP_ND6_DEF_MAXDADNS > 0 */
518  LOG_ERR("NA received is bad\n");
519  goto discard;
520  } else {
521  const uip_lladdr_t *lladdr;
522  nbr = uip_ds6_nbr_lookup(&UIP_ND6_NA_BUF->tgtipaddr);
523  if(nbr == NULL) {
524  goto discard;
525  }
526  lladdr = uip_ds6_nbr_get_ll(nbr);
527  if(lladdr == NULL) {
528  goto discard;
529  }
530  if(nd6_opt_llao != NULL) {
531  is_llchange =
532  memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], lladdr,
533  UIP_LLADDR_LEN) == 0 ? 0 : 1;
534  }
535  if(nbr->state == NBR_INCOMPLETE) {
536  if(nd6_opt_llao == NULL || !extract_lladdr_from_llao_aligned(&lladdr_aligned)) {
537  goto discard;
538  }
539  if(uip_ds6_nbr_update_ll(&nbr,
540  (const uip_lladdr_t *)&lladdr_aligned) < 0) {
541  /* failed to update the lladdr */
542  goto discard;
543  }
544 
545  /* Note: No need to refresh the state of the nbr here.
546  * It has already been refreshed upon receiving the unicast IPv6 ND packet.
547  * See: uip_ds6_nbr_refresh_reachable_state()
548  */
549  if(!is_solicited) {
550  nbr->state = NBR_STALE;
551  }
552  nbr->isrouter = is_router;
553  } else { /* NBR is not INCOMPLETE */
554  if(!is_override && is_llchange) {
555  if(nbr->state == NBR_REACHABLE) {
556  nbr->state = NBR_STALE;
557  }
558  goto discard;
559  } else {
560  /**
561  * If this is an cache override, or same lladdr, or no llao -
562  * do updates of nbr states.
563  */
564  if(is_override || !is_llchange || nd6_opt_llao == NULL) {
565  if(nd6_opt_llao != NULL && is_llchange) {
566  if(!extract_lladdr_from_llao_aligned(&lladdr_aligned) ||
567  uip_ds6_nbr_update_ll(&nbr,
568  (const uip_lladdr_t *)&lladdr_aligned)
569  < 0) {
570  /* failed to update the lladdr */
571  goto discard;
572  }
573  }
574  /* Note: No need to refresh the state of the nbr here.
575  * It has already been refreshed upon receiving the unicast IPv6 ND packet.
576  * See: uip_ds6_nbr_refresh_reachable_state()
577  */
578  }
579  }
580  if(nbr->isrouter && !is_router) {
581  defrt = uip_ds6_defrt_lookup(&UIP_IP_BUF->srcipaddr);
582  if(defrt != NULL) {
583  uip_ds6_defrt_rm(defrt);
584  }
585  }
586  nbr->isrouter = is_router;
587  }
588  }
589 #if UIP_CONF_IPV6_QUEUE_PKT
590  /* The nbr is now reachable, check if we had buffered a pkt for it */
591  /*if(nbr->queue_buf_len != 0) {
592  uip_len = nbr->queue_buf_len;
593  memcpy(UIP_IP_BUF, nbr->queue_buf, uip_len);
594  nbr->queue_buf_len = 0;
595  return;
596  }*/
597  if(uip_packetqueue_buflen(&nbr->packethandle) != 0) {
598  uip_len = uip_packetqueue_buflen(&nbr->packethandle);
599  memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len);
600  uip_packetqueue_free(&nbr->packethandle);
601  return;
602  }
603 
604 #endif /*UIP_CONF_IPV6_QUEUE_PKT */
605 
606 discard:
607  uip_clear_buf();
608  return;
609 }
610 #endif /* UIP_ND6_SEND_NS */
611 
612 #if UIP_CONF_ROUTER
613 #if UIP_ND6_SEND_RA
614 /*---------------------------------------------------------------------------*/
615 static void
616 rs_input(void)
617 {
618 
619  LOG_INFO("Received RS from ");
620  LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr);
621  LOG_INFO_(" to ");
622  LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
623  LOG_INFO_("\n");
624  UIP_STAT(++uip_stat.nd6.recv);
625 
626 
627 #if UIP_CONF_IPV6_CHECKS
628  /*
629  * Check hop limit / icmp code
630  * target address must not be multicast
631  * if the NA is solicited, dest must not be multicast
632  */
633  if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) || (UIP_ICMP_BUF->icode != 0)) {
634  LOG_ERR("RS received is bad\n");
635  goto discard;
636  }
637 #endif /*UIP_CONF_IPV6_CHECKS */
638 
639  /* Only valid option is Source Link-Layer Address option any thing
640  else is discarded */
641  nd6_opt_offset = UIP_ND6_RS_LEN;
642  nd6_opt_llao = NULL;
643 
644  while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) {
645 #if UIP_CONF_IPV6_CHECKS
646  if(UIP_ND6_OPT_HDR_BUF->len == 0) {
647  LOG_ERR("RS received is bad\n");
648  goto discard;
649  }
650 #endif /*UIP_CONF_IPV6_CHECKS */
651  switch (UIP_ND6_OPT_HDR_BUF->type) {
652  case UIP_ND6_OPT_SLLAO:
653  nd6_opt_llao = (uint8_t *)UIP_ND6_OPT_HDR_BUF;
654  break;
655  default:
656  LOG_WARN("ND option not supported in RS\n");
657  break;
658  }
659  nd6_opt_offset += (UIP_ND6_OPT_HDR_BUF->len << 3);
660  }
661  /* Options processing: only SLLAO */
662  if(nd6_opt_llao != NULL) {
663 #if UIP_CONF_IPV6_CHECKS
664  if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
665  LOG_ERR("RS received is bad\n");
666  goto discard;
667  } else {
668 #endif /*UIP_CONF_IPV6_CHECKS */
669  uip_lladdr_t lladdr_aligned;
670  extract_lladdr_from_llao_aligned(&lladdr_aligned);
671  if((nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr)) == NULL) {
672  /* we need to add the neighbor */
673  uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned,
674  0, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL);
675  } else {
676  /* If LL address changed, set neighbor state to stale */
677  const uip_lladdr_t *lladdr = uip_ds6_nbr_get_ll(nbr);
678  if(lladdr == NULL) {
679  goto discard;
680  }
681  if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
682  lladdr, UIP_LLADDR_LEN) != 0) {
683  uip_ds6_nbr_t nbr_data;
684  nbr_data = *nbr;
685  uip_ds6_nbr_rm(nbr);
686  nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned,
687  0, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL);
688  nbr->reachable = nbr_data.reachable;
689  nbr->sendns = nbr_data.sendns;
690  nbr->nscount = nbr_data.nscount;
691  }
692  nbr->isrouter = 0;
693  }
694 #if UIP_CONF_IPV6_CHECKS
695  }
696 #endif /*UIP_CONF_IPV6_CHECKS */
697  }
698 
699  /* Schedule a sollicited RA */
700  uip_ds6_send_ra_sollicited();
701 
702 discard:
703  uip_clear_buf();
704  return;
705 }
706 
707 /*---------------------------------------------------------------------------*/
708 void
709 uip_nd6_ra_output(uip_ipaddr_t * dest)
710 {
711 
712  UIP_IP_BUF->vtc = 0x60;
713  UIP_IP_BUF->tcflow = 0;
714  UIP_IP_BUF->flow = 0;
715  UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
717 
718  if(dest == NULL) {
720  } else {
721  /* For sollicited RA */
722  uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, dest);
723  }
724  uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
725 
726  UIP_ICMP_BUF->type = ICMP6_RA;
727  UIP_ICMP_BUF->icode = 0;
728 
729  UIP_ND6_RA_BUF->cur_ttl = uip_ds6_if.cur_hop_limit;
730 
731  UIP_ND6_RA_BUF->flags_reserved =
732  (UIP_ND6_M_FLAG << 7) | (UIP_ND6_O_FLAG << 6);
733 
734  UIP_ND6_RA_BUF->router_lifetime = uip_htons(UIP_ND6_ROUTER_LIFETIME);
735  //UIP_ND6_RA_BUF->reachable_time = uip_htonl(uip_ds6_if.reachable_time);
736  //UIP_ND6_RA_BUF->retrans_timer = uip_htonl(uip_ds6_if.retrans_timer);
737  UIP_ND6_RA_BUF->reachable_time = 0;
738  UIP_ND6_RA_BUF->retrans_timer = 0;
739 
740  uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_RA_LEN;
741  nd6_opt_offset = UIP_ND6_RA_LEN;
742 
743 
744  /* Prefix list */
745  for(prefix = uip_ds6_prefix_list;
746  prefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; prefix++) {
747  if((prefix->isused) && (prefix->advertise)) {
748  UIP_ND6_OPT_PREFIX_BUF->type = UIP_ND6_OPT_PREFIX_INFO;
749  UIP_ND6_OPT_PREFIX_BUF->len = UIP_ND6_OPT_PREFIX_INFO_LEN / 8;
750  UIP_ND6_OPT_PREFIX_BUF->preflen = prefix->length;
751  UIP_ND6_OPT_PREFIX_BUF->flagsreserved1 = prefix->l_a_reserved;
752  UIP_ND6_OPT_PREFIX_BUF->validlt = uip_htonl(prefix->vlifetime);
753  UIP_ND6_OPT_PREFIX_BUF->preferredlt = uip_htonl(prefix->plifetime);
754  UIP_ND6_OPT_PREFIX_BUF->reserved2 = 0;
755  uip_ipaddr_copy(&(UIP_ND6_OPT_PREFIX_BUF->prefix), &(prefix->ipaddr));
756  nd6_opt_offset += UIP_ND6_OPT_PREFIX_INFO_LEN;
757  uip_len += UIP_ND6_OPT_PREFIX_INFO_LEN;
758  }
759  }
760 
761  /* Source link-layer option */
762  create_llao((uint8_t *)UIP_ND6_OPT_HDR_BUF, UIP_ND6_OPT_SLLAO);
763 
765  nd6_opt_offset += UIP_ND6_OPT_LLAO_LEN;
766 
767  /* MTU */
768  UIP_ND6_OPT_MTU_BUF->type = UIP_ND6_OPT_MTU;
769  UIP_ND6_OPT_MTU_BUF->len = UIP_ND6_OPT_MTU_LEN >> 3;
770  UIP_ND6_OPT_MTU_BUF->reserved = 0;
771  //UIP_ND6_OPT_MTU_BUF->mtu = uip_htonl(uip_ds6_if.link_mtu);
772  UIP_ND6_OPT_MTU_BUF->mtu = uip_htonl(1500);
773 
774  uip_len += UIP_ND6_OPT_MTU_LEN;
775  nd6_opt_offset += UIP_ND6_OPT_MTU_LEN;
776 
777 #if UIP_ND6_RA_RDNSS
778  if(uip_nameserver_count() > 0) {
779  uint8_t i = 0;
780  uip_ipaddr_t *ip = &UIP_ND6_OPT_RDNSS_BUF->ip;
781  uip_ipaddr_t *dns = NULL;
782  UIP_ND6_OPT_RDNSS_BUF->type = UIP_ND6_OPT_RDNSS;
783  UIP_ND6_OPT_RDNSS_BUF->reserved = 0;
784  UIP_ND6_OPT_RDNSS_BUF->lifetime = uip_nameserver_next_expiration();
785  if(UIP_ND6_OPT_RDNSS_BUF->lifetime != UIP_NAMESERVER_INFINITE_LIFETIME) {
786  UIP_ND6_OPT_RDNSS_BUF->lifetime -= clock_seconds();
787  }
788  while((dns = uip_nameserver_get(i)) != NULL) {
789  uip_ipaddr_copy(ip++, dns);
790  i++;
791  }
792  UIP_ND6_OPT_RDNSS_BUF->len = UIP_ND6_OPT_RDNSS_LEN + (i << 1);
793  LOG_INFO("%d nameservers reported\n", i);
794  uip_len += UIP_ND6_OPT_RDNSS_BUF->len << 3;
795  nd6_opt_offset += UIP_ND6_OPT_RDNSS_BUF->len << 3;
796  }
797 #endif /* UIP_ND6_RA_RDNSS */
798 
799  UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
800  UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
801 
802  /*ICMP checksum */
803  UIP_ICMP_BUF->icmpchksum = 0;
804  UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
805 
806  UIP_STAT(++uip_stat.nd6.sent);
807  LOG_INFO("Sending RA to ");
808  LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
809  LOG_INFO_(" from ");
810  LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr);
811  LOG_INFO_("\n");
812  return;
813 }
814 #endif /* UIP_ND6_SEND_RA */
815 #endif /* UIP_CONF_ROUTER */
816 
817 #if !UIP_CONF_ROUTER
818 /*---------------------------------------------------------------------------*/
819 void
821 {
822  UIP_IP_BUF->vtc = 0x60;
823  UIP_IP_BUF->tcflow = 0;
824  UIP_IP_BUF->flow = 0;
825  UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
828  uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
829  UIP_ICMP_BUF->type = ICMP6_RS;
830  UIP_ICMP_BUF->icode = 0;
831  UIP_IP_BUF->len[0] = 0; /* length will not be more than 255 */
832 
833  if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
834  UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_RS_LEN;
835  uip_len = uip_l3_icmp_hdr_len + UIP_ND6_RS_LEN;
836  } else {
837  uip_len = uip_l3_icmp_hdr_len + UIP_ND6_RS_LEN + UIP_ND6_OPT_LLAO_LEN;
838  UIP_IP_BUF->len[1] =
839  UIP_ICMPH_LEN + UIP_ND6_RS_LEN + UIP_ND6_OPT_LLAO_LEN;
840 
841  create_llao(&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_RS_LEN],
842  UIP_ND6_OPT_SLLAO);
843  }
844 
845  UIP_ICMP_BUF->icmpchksum = 0;
846  UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
847 
848  UIP_STAT(++uip_stat.nd6.sent);
849  LOG_INFO("Sending RS to ");
850  LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
851  LOG_INFO_(" from ");
852  LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr);
853  LOG_INFO_("\n");
854  return;
855 }
856 /*---------------------------------------------------------------------------*/
857 /**
858  * Process a Router Advertisement
859  *
860  * - Possible actions when receiving a RA: add router to router list,
861  * recalculate reachable time, update link hop limit, update retrans timer.
862  * - If MTU option: update MTU.
863  * - If SLLAO option: update entry in neighbor cache
864  * - If prefix option: start autoconf, add prefix to prefix list
865  */
866 void
867 ra_input(void)
868 {
869  uip_lladdr_t lladdr_aligned;
870 
871  LOG_INFO("Received RA from ");
872  LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr);
873  LOG_INFO_(" to ");
874  LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
875  LOG_INFO_("\n");
876  UIP_STAT(++uip_stat.nd6.recv);
877 
878 #if UIP_CONF_IPV6_CHECKS
879  if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) ||
880  (!uip_is_addr_linklocal(&UIP_IP_BUF->srcipaddr)) ||
881  (UIP_ICMP_BUF->icode != 0)) {
882  LOG_ERR("RA received is bad");
883  goto discard;
884  }
885 #endif /*UIP_CONF_IPV6_CHECKS */
886 
887  if(UIP_ND6_RA_BUF->cur_ttl != 0) {
888  uip_ds6_if.cur_hop_limit = UIP_ND6_RA_BUF->cur_ttl;
889  LOG_INFO("uip_ds6_if.cur_hop_limit %u\n", uip_ds6_if.cur_hop_limit);
890  }
891 
892  if(UIP_ND6_RA_BUF->reachable_time != 0) {
893  if(uip_ds6_if.base_reachable_time !=
894  uip_ntohl(UIP_ND6_RA_BUF->reachable_time)) {
895  uip_ds6_if.base_reachable_time = uip_ntohl(UIP_ND6_RA_BUF->reachable_time);
896  uip_ds6_if.reachable_time = uip_ds6_compute_reachable_time();
897  }
898  }
899  if(UIP_ND6_RA_BUF->retrans_timer != 0) {
900  uip_ds6_if.retrans_timer = uip_ntohl(UIP_ND6_RA_BUF->retrans_timer);
901  }
902 
903  /* Options processing */
904  nd6_opt_offset = UIP_ND6_RA_LEN;
905  while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) {
906  if(UIP_ND6_OPT_HDR_BUF->len == 0) {
907  LOG_ERR("RA received is bad");
908  goto discard;
909  }
910  switch (UIP_ND6_OPT_HDR_BUF->type) {
911  case UIP_ND6_OPT_SLLAO:
912  LOG_DBG("Processing SLLAO option in RA\n");
913  nd6_opt_llao = (uint8_t *) UIP_ND6_OPT_HDR_BUF;
914  nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr);
915  if(!extract_lladdr_from_llao_aligned(&lladdr_aligned)) {
916  /* failed to extract llao - discard packet */
917  goto discard;
918  }
919  if(nbr == NULL) {
920  nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned,
921  1, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL);
922  } else {
923  const uip_lladdr_t *lladdr = uip_ds6_nbr_get_ll(nbr);
924  if(lladdr == NULL) {
925  goto discard;
926  }
927  if(nbr->state == NBR_INCOMPLETE) {
928  nbr->state = NBR_STALE;
929  }
930  if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
931  lladdr, UIP_LLADDR_LEN) != 0) {
932  /* change of link layer address */
933  if(uip_ds6_nbr_update_ll(&nbr,
934  (const uip_lladdr_t *)&lladdr_aligned) < 0) {
935  /* failed to update the lladdr */
936  goto discard;
937  }
938  nbr->state = NBR_STALE;
939  }
940  nbr->isrouter = 1;
941  }
942  break;
943  case UIP_ND6_OPT_MTU:
944  LOG_DBG("Processing MTU option in RA\n");
945  uip_ds6_if.link_mtu =
946  uip_ntohl(((uip_nd6_opt_mtu *) UIP_ND6_OPT_HDR_BUF)->mtu);
947  break;
948  case UIP_ND6_OPT_PREFIX_INFO:
949  LOG_DBG("Processing PREFIX option in RA\n");
950  nd6_opt_prefix_info = (uip_nd6_opt_prefix_info *) UIP_ND6_OPT_HDR_BUF;
951  if((uip_ntohl(nd6_opt_prefix_info->validlt) >=
952  uip_ntohl(nd6_opt_prefix_info->preferredlt))
953  && (!uip_is_addr_linklocal(&nd6_opt_prefix_info->prefix))) {
954  /* on-link flag related processing */
955  if(nd6_opt_prefix_info->flagsreserved1 & UIP_ND6_RA_FLAG_ONLINK) {
956  prefix =
957  uip_ds6_prefix_lookup(&nd6_opt_prefix_info->prefix,
958  nd6_opt_prefix_info->preflen);
959  if(prefix == NULL) {
960  if(nd6_opt_prefix_info->validlt != 0) {
961  if(nd6_opt_prefix_info->validlt != UIP_ND6_INFINITE_LIFETIME) {
962  prefix = uip_ds6_prefix_add(&nd6_opt_prefix_info->prefix,
963  nd6_opt_prefix_info->preflen,
964  uip_ntohl(nd6_opt_prefix_info->
965  validlt));
966  } else {
967  prefix = uip_ds6_prefix_add(&nd6_opt_prefix_info->prefix,
968  nd6_opt_prefix_info->preflen, 0);
969  }
970  }
971  } else {
972  switch (nd6_opt_prefix_info->validlt) {
973  case 0:
974  uip_ds6_prefix_rm(prefix);
975  break;
977  prefix->isinfinite = 1;
978  break;
979  default:
980  LOG_DBG("Updating timer of prefix ");
981  LOG_DBG_6ADDR(&prefix->ipaddr);
982  LOG_DBG_(" new value %"PRIu32"\n", uip_ntohl(nd6_opt_prefix_info->validlt));
983  stimer_set(&prefix->vlifetime,
984  uip_ntohl(nd6_opt_prefix_info->validlt));
985  prefix->isinfinite = 0;
986  break;
987  }
988  }
989  }
990  /* End of on-link flag related processing */
991  /* autonomous flag related processing */
992  if((nd6_opt_prefix_info->flagsreserved1 & UIP_ND6_RA_FLAG_AUTONOMOUS)
993  && (nd6_opt_prefix_info->validlt != 0)
994  && (nd6_opt_prefix_info->preflen == UIP_DEFAULT_PREFIX_LEN)) {
995 
996  uip_ipaddr_copy(&ipaddr, &nd6_opt_prefix_info->prefix);
998  addr = uip_ds6_addr_lookup(&ipaddr);
999  if((addr != NULL) && (addr->type == ADDR_AUTOCONF)) {
1000  if(nd6_opt_prefix_info->validlt != UIP_ND6_INFINITE_LIFETIME) {
1001  /* The processing below is defined in RFC4862 section 5.5.3 e */
1002  if((uip_ntohl(nd6_opt_prefix_info->validlt) > 2 * 60 * 60) ||
1003  (uip_ntohl(nd6_opt_prefix_info->validlt) >
1004  stimer_remaining(&addr->vlifetime))) {
1005  LOG_DBG("Updating timer of address ");
1006  LOG_DBG_6ADDR(&addr->ipaddr);
1007  LOG_DBG_(" new value %lu\n",
1008  (unsigned long)uip_ntohl(nd6_opt_prefix_info->validlt));
1009  stimer_set(&addr->vlifetime,
1010  uip_ntohl(nd6_opt_prefix_info->validlt));
1011  } else {
1012  stimer_set(&addr->vlifetime, 2 * 60 * 60);
1013  LOG_DBG("Updating timer of address ");
1014  LOG_DBG_6ADDR(&addr->ipaddr);
1015  LOG_DBG_(" new value %lu\n", (unsigned long)(2 * 60 * 60));
1016  }
1017  addr->isinfinite = 0;
1018  } else {
1019  addr->isinfinite = 1;
1020  }
1021  } else {
1022  if(uip_ntohl(nd6_opt_prefix_info->validlt) ==
1024  uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF);
1025  } else {
1026  uip_ds6_addr_add(&ipaddr, uip_ntohl(nd6_opt_prefix_info->validlt),
1027  ADDR_AUTOCONF);
1028  }
1029  }
1030  }
1031  /* End of autonomous flag related processing */
1032  }
1033  break;
1034 #if UIP_ND6_RA_RDNSS
1035  case UIP_ND6_OPT_RDNSS:
1036  LOG_DBG("Processing RDNSS option\n");
1037  uint8_t naddr = (UIP_ND6_OPT_RDNSS_BUF->len - 1) / 2;
1038  uip_ipaddr_t *ip = (uip_ipaddr_t *)(&UIP_ND6_OPT_RDNSS_BUF->ip);
1039  LOG_DBG("got %d nameservers\n", naddr);
1040  while(naddr-- > 0) {
1041  LOG_DBG("nameserver: ");
1042  LOG_DBG_6ADDR(ip);
1043  LOG_DBG_(" lifetime: %"PRIx32"\n", uip_ntohl(UIP_ND6_OPT_RDNSS_BUF->lifetime));
1044  uip_nameserver_update(ip, uip_ntohl(UIP_ND6_OPT_RDNSS_BUF->lifetime));
1045  ip++;
1046  }
1047  break;
1048 #endif /* UIP_ND6_RA_RDNSS */
1049  default:
1050  LOG_ERR("ND option not supported in RA\n");
1051  break;
1052  }
1053  nd6_opt_offset += (UIP_ND6_OPT_HDR_BUF->len << 3);
1054  }
1055 
1056  defrt = uip_ds6_defrt_lookup(&UIP_IP_BUF->srcipaddr);
1057  if(UIP_ND6_RA_BUF->router_lifetime != 0) {
1058  if(nbr != NULL) {
1059  nbr->isrouter = 1;
1060  }
1061  if(defrt == NULL) {
1062  uip_ds6_defrt_add(&UIP_IP_BUF->srcipaddr,
1063  (unsigned
1064  long)(uip_ntohs(UIP_ND6_RA_BUF->router_lifetime)));
1065  } else {
1066  stimer_set(&(defrt->lifetime),
1067  (unsigned long)(uip_ntohs(UIP_ND6_RA_BUF->router_lifetime)));
1068  }
1069  } else {
1070  if(defrt != NULL) {
1071  uip_ds6_defrt_rm(defrt);
1072  }
1073  }
1074 
1075 #if UIP_CONF_IPV6_QUEUE_PKT
1076  /* If the nbr just became reachable (e.g. it was in NBR_INCOMPLETE state
1077  * and we got a SLLAO), check if we had buffered a pkt for it */
1078  /* if((nbr != NULL) && (nbr->queue_buf_len != 0)) {
1079  uip_len = nbr->queue_buf_len;
1080  memcpy(UIP_IP_BUF, nbr->queue_buf, uip_len);
1081  nbr->queue_buf_len = 0;
1082  return;
1083  }*/
1084  if(nbr != NULL && uip_packetqueue_buflen(&nbr->packethandle) != 0) {
1085  uip_len = uip_packetqueue_buflen(&nbr->packethandle);
1086  memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len);
1087  uip_packetqueue_free(&nbr->packethandle);
1088  return;
1089  }
1090 
1091 #endif /*UIP_CONF_IPV6_QUEUE_PKT */
1092 
1093 discard:
1094  uip_clear_buf();
1095  return;
1096 }
1097 #endif /* !UIP_CONF_ROUTER */
1098 /*------------------------------------------------------------------*/
1099 /* ICMPv6 input handlers */
1100 #if UIP_ND6_SEND_NA
1101 UIP_ICMP6_HANDLER(ns_input_handler, ICMP6_NS, UIP_ICMP6_HANDLER_CODE_ANY,
1102  ns_input);
1103 #endif
1104 #if UIP_ND6_SEND_NS
1105 UIP_ICMP6_HANDLER(na_input_handler, ICMP6_NA, UIP_ICMP6_HANDLER_CODE_ANY,
1106  na_input);
1107 #endif
1108 
1109 #if UIP_CONF_ROUTER && UIP_ND6_SEND_RA
1110 UIP_ICMP6_HANDLER(rs_input_handler, ICMP6_RS, UIP_ICMP6_HANDLER_CODE_ANY,
1111  rs_input);
1112 #endif
1113 
1114 #if !UIP_CONF_ROUTER
1115 UIP_ICMP6_HANDLER(ra_input_handler, ICMP6_RA, UIP_ICMP6_HANDLER_CODE_ANY,
1116  ra_input);
1117 #endif
1118 /*---------------------------------------------------------------------------*/
1119 void
1121 {
1122 #if UIP_ND6_SEND_NA
1123  /* Only handle NSs if we are prepared to send out NAs */
1124  uip_icmp6_register_input_handler(&ns_input_handler);
1125 #endif
1126 
1127 #if UIP_ND6_SEND_NS
1128  /*
1129  * Only handle NAs if we are prepared to send out NSs. */
1130  uip_icmp6_register_input_handler(&na_input_handler);
1131 #endif
1132 
1133 #if UIP_CONF_ROUTER && UIP_ND6_SEND_RA
1134  /* Only accept RS if we are a router and happy to send out RAs */
1135  uip_icmp6_register_input_handler(&rs_input_handler);
1136 #endif
1137 
1138 #if !UIP_CONF_ROUTER
1139  /* Only process RAs if we are not a router */
1140  uip_icmp6_register_input_handler(&ra_input_handler);
1141 #endif
1142 }
1143 /*---------------------------------------------------------------------------*/
1144  /** @} */
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
Definition: uip-nd6.c:124
#define UIP_IP_BUF
Pointer to IP header.
Definition: uip-nd6.c:96
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:114
unsigned long stimer_remaining(struct stimer *t)
The time until the timer expires.
Definition: stimer.c:140
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:115
void ra_input(void)
Process a Router Advertisement.
Definition: uip-nd6.c:867
#define UIP_ICMP_BUF
Pointer to ICMP header.
Definition: uip-nd6.c:97
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:1120
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
static int extract_lladdr_from_llao_aligned(uip_lladdr_t *dest)
Pointer to a prefix list entry.
Definition: uip-nd6.c:134
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:2324
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 ICMP6_RA
Router Advertisement.
Definition: uip-icmp6.h:61
#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.
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:113
#define uip_create_linklocal_allnodes_mcast(a)
set IP address a to the link local all-nodes multicast address
Definition: uip.h:2031
#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:1982
#define uip_buf
Macro to access uip_aligned_buf as an array of bytes.
Definition: uip.h:513
Unicast address structure.
Definition: uip-ds6.h:204
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
Definition: uip.h:1018
#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:2046
#define ICMP6_NS
Neighbor Solicitation.
Definition: uip-icmp6.h:62
#define UIP_STAT(s)
The uIP TCP/IP statistics.
Definition: uip.h:1439
#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
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:341
#define NBR_INCOMPLETE
Possible states for the nbr cache entries.
Definition: uip-ds6-nbr.h:60
#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
static uip_nd6_opt_prefix_info * nd6_opt_prefix_info
Pointer to a router list entry.
Definition: uip-nd6.c:123
#define ICMP6_RS
Router Solicitation.
Definition: uip-icmp6.h:60
#define uip_create_unspecified(a)
set IP address a to unspecified
Definition: uip.h:2028
#define ICMP6_NA
Neighbor advertisement.
Definition: uip-icmp6.h:63
uint8_t uip_ext_len
The length of the extension headers.
Definition: uip6.c:132
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)
Neighbor Cache basic routines.
Definition: uip-ds6-nbr.c:74
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
uint16_t uip_icmp6chksum(void)
Calculate the ICMP checksum of the packet in uip_buf.
Definition: uip6.c:384
#define UIP_ND6_OPT_HDR_BUF
Pointer to ND option.
Definition: uip-nd6.c:105
#define UIP_ND6_HOP_LIMIT
HOP LIMIT to be used when sending ND messages (255)
Definition: uip-nd6.h:55
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:106
#define uip_is_addr_linklocal(a)
is addr (a) a link local unicast address, see RFC 4291 i.e.
Definition: uip.h:2023
static uip_ds6_defrt_t * defrt
Pointer to an interface address.
Definition: uip-nd6.c:119
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:820
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: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
An entry in the nbr cache.
Definition: uip-ds6-nbr.h:69