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