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