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