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