Contiki-Inga 3.x
uip-nd6.c
1 /**
2  * \addtogroup uip6
3  * @{
4  */
5 
6 /**
7  * \file Neighbor discovery (RFC 4861)
8  *
9  * \author Mathilde Durvy <mdurvy@cisco.com>
10  * \author Julien Abeille <jabeille@cisco.com>
11  */
12 
13 /*
14  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
15  * All rights reserved.
16  *
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions
19  * are met:
20  * 1. Redistributions of source code must retain the above copyright
21  * notice, this list of conditions and the following disclaimer.
22  * 2. Redistributions in binary form must reproduce the above copyright
23  * notice, this list of conditions and the following disclaimer in the
24  * documentation and/or other materials provided with the distribution.
25  * 3. Neither the name of the project nor the names of its contributors
26  * may be used to endorse or promote products derived from this software
27  * without specific prior written permission.
28  *
29  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
30  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32  * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
33  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39  * SUCH DAMAGE.
40  */
41 /*
42  * Copyright (c) 2006, Swedish Institute of Computer Science.
43  * All rights reserved.
44  *
45  * Redistribution and use in source and binary forms, with or without
46  * modification, are permitted provided that the following conditions
47  * are met:
48  * 1. Redistributions of source code must retain the above copyright
49  * notice, this list of conditions and the following disclaimer.
50  * 2. Redistributions in binary form must reproduce the above copyright
51  * notice, this list of conditions and the following disclaimer in the
52  * documentation and/or other materials provided with the distribution.
53  * 3. Neither the name of the Institute nor the names of its contributors
54  * may be used to endorse or promote products derived from this software
55  * without specific prior written permission.
56  *
57  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
58  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
59  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
60  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
61  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
62  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
63  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
64  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
65  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
66  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
67  * SUCH DAMAGE.
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 DEBUG_NONE
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 
131 /*------------------------------------------------------------------*/
132 /* create a llao */
133 static void
134 create_llao(uint8_t *llao, uint8_t type) {
135  llao[UIP_ND6_OPT_TYPE_OFFSET] = type;
136  llao[UIP_ND6_OPT_LEN_OFFSET] = UIP_ND6_OPT_LLAO_LEN >> 3;
137  memcpy(&llao[UIP_ND6_OPT_DATA_OFFSET], &uip_lladdr, UIP_LLADDR_LEN);
138  /* padding on some */
139  memset(&llao[UIP_ND6_OPT_DATA_OFFSET + UIP_LLADDR_LEN], 0,
140  UIP_ND6_OPT_LLAO_LEN - 2 - UIP_LLADDR_LEN);
141 }
142 
143 /*------------------------------------------------------------------*/
144 
145 
146 void
148 {
149  uint8_t flags;
150  PRINTF("Received NS from ");
151  PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
152  PRINTF(" to ");
153  PRINT6ADDR(&UIP_IP_BUF->destipaddr);
154  PRINTF(" with target address ");
155  PRINT6ADDR((uip_ipaddr_t *) (&UIP_ND6_NS_BUF->tgtipaddr));
156  PRINTF("\n");
157  UIP_STAT(++uip_stat.nd6.recv);
158 
159 #if UIP_CONF_IPV6_CHECKS
160  if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) ||
161  (uip_is_addr_mcast(&UIP_ND6_NS_BUF->tgtipaddr)) ||
162  (UIP_ICMP_BUF->icode != 0)) {
163  PRINTF("NS received is bad\n");
164  goto discard;
165  }
166 #endif /* UIP_CONF_IPV6_CHECKS */
167 
168  /* Options processing */
169  nd6_opt_llao = NULL;
170  nd6_opt_offset = UIP_ND6_NS_LEN;
171  while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) {
172 #if UIP_CONF_IPV6_CHECKS
173  if(UIP_ND6_OPT_HDR_BUF->len == 0) {
174  PRINTF("NS received is bad\n");
175  goto discard;
176  }
177 #endif /* UIP_CONF_IPV6_CHECKS */
178  switch (UIP_ND6_OPT_HDR_BUF->type) {
179  case UIP_ND6_OPT_SLLAO:
180  nd6_opt_llao = &uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset];
181 #if UIP_CONF_IPV6_CHECKS
182  /* There must be NO option in a DAD NS */
183  if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
184  PRINTF("NS received is bad\n");
185  goto discard;
186  } else {
187 #endif /*UIP_CONF_IPV6_CHECKS */
188  nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr);
189  if(nbr == NULL) {
190  uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr,
191  (uip_lladdr_t *)&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
192  0, NBR_STALE);
193  } else {
194  uip_lladdr_t *lladdr = (uip_lladdr_t *)uip_ds6_nbr_get_ll(nbr);
195  if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
196  lladdr, UIP_LLADDR_LEN) != 0) {
197  memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
198  UIP_LLADDR_LEN);
199  nbr->state = NBR_STALE;
200  } else {
201  if(nbr->state == NBR_INCOMPLETE) {
202  nbr->state = NBR_STALE;
203  }
204  }
205  }
206 #if UIP_CONF_IPV6_CHECKS
207  }
208 #endif /*UIP_CONF_IPV6_CHECKS */
209  break;
210  default:
211  PRINTF("ND option not supported in NS");
212  break;
213  }
214  nd6_opt_offset += (UIP_ND6_OPT_HDR_BUF->len << 3);
215  }
216 
217  addr = uip_ds6_addr_lookup(&UIP_ND6_NS_BUF->tgtipaddr);
218  if(addr != NULL) {
219 #if UIP_ND6_DEF_MAXDADNS > 0
220  if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
221  /* DAD CASE */
222 #if UIP_CONF_IPV6_CHECKS
223  if(!uip_is_addr_solicited_node(&UIP_IP_BUF->destipaddr)) {
224  PRINTF("NS received is bad\n");
225  goto discard;
226  }
227 #endif /* UIP_CONF_IPV6_CHECKS */
228  if(addr->state != ADDR_TENTATIVE) {
230  uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
231  flags = UIP_ND6_NA_FLAG_OVERRIDE;
232  goto create_na;
233  } else {
234  /** \todo if I sent a NS before him, I win */
235  uip_ds6_dad_failed(addr);
236  goto discard;
237  }
238 #else /* UIP_ND6_DEF_MAXDADNS > 0 */
239  if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
240  /* DAD CASE */
241  goto discard;
242 #endif /* UIP_ND6_DEF_MAXDADNS > 0 */
243  }
244 #if UIP_CONF_IPV6_CHECKS
245  if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)) {
246  /**
247  * \NOTE do we do something here? we both are using the same address.
248  * If we are doing dad, we could cancel it, though we should receive a
249  * NA in response of DAD NS we sent, hence DAD will fail anyway. If we
250  * were not doing DAD, it means there is a duplicate in the network!
251  */
252  PRINTF("NS received is bad\n");
253  goto discard;
254  }
255 #endif /*UIP_CONF_IPV6_CHECKS */
256 
257  /* Address resolution case */
258  if(uip_is_addr_solicited_node(&UIP_IP_BUF->destipaddr)) {
259  uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr);
260  uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &UIP_ND6_NS_BUF->tgtipaddr);
261  flags = UIP_ND6_NA_FLAG_SOLICITED | UIP_ND6_NA_FLAG_OVERRIDE;
262  goto create_na;
263  }
264 
265  /* NUD CASE */
266  if(uip_ds6_addr_lookup(&UIP_IP_BUF->destipaddr) == addr) {
267  uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr);
268  uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &UIP_ND6_NS_BUF->tgtipaddr);
269  flags = UIP_ND6_NA_FLAG_SOLICITED | UIP_ND6_NA_FLAG_OVERRIDE;
270  goto create_na;
271  } else {
272 #if UIP_CONF_IPV6_CHECKS
273  PRINTF("NS received is bad\n");
274  goto discard;
275 #endif /* UIP_CONF_IPV6_CHECKS */
276  }
277  } else {
278  goto discard;
279  }
280 
281 
282 create_na:
283  /* If the node is a router it should set R flag in NAs */
284 #if UIP_CONF_ROUTER
285  flags = flags | UIP_ND6_NA_FLAG_ROUTER;
286 #endif
287  uip_ext_len = 0;
288  UIP_IP_BUF->vtc = 0x60;
289  UIP_IP_BUF->tcflow = 0;
290  UIP_IP_BUF->flow = 0;
291  UIP_IP_BUF->len[0] = 0; /* length will not be more than 255 */
292  UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_NA_LEN + UIP_ND6_OPT_LLAO_LEN;
293  UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
295 
296  UIP_ICMP_BUF->type = ICMP6_NA;
297  UIP_ICMP_BUF->icode = 0;
298 
299  UIP_ND6_NA_BUF->flagsreserved = flags;
300  memcpy(&UIP_ND6_NA_BUF->tgtipaddr, &addr->ipaddr, sizeof(uip_ipaddr_t));
301 
302  create_llao(&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_NA_LEN],
304 
305  UIP_ICMP_BUF->icmpchksum = 0;
306  UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
307 
308  uip_len =
309  UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NA_LEN + UIP_ND6_OPT_LLAO_LEN;
310 
311  UIP_STAT(++uip_stat.nd6.sent);
312  PRINTF("Sending NA to ");
313  PRINT6ADDR(&UIP_IP_BUF->destipaddr);
314  PRINTF(" from ");
315  PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
316  PRINTF(" with target address ");
317  PRINT6ADDR(&UIP_ND6_NA_BUF->tgtipaddr);
318  PRINTF("\n");
319  return;
320 
321 discard:
322  uip_len = 0;
323  return;
324 }
325 
326 
327 
328 /*------------------------------------------------------------------*/
329 void
330 uip_nd6_ns_output(uip_ipaddr_t * src, uip_ipaddr_t * dest, uip_ipaddr_t * tgt)
331 {
332  uip_ext_len = 0;
333  UIP_IP_BUF->vtc = 0x60;
334  UIP_IP_BUF->tcflow = 0;
335  UIP_IP_BUF->flow = 0;
336  UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
338 
339  if(dest == NULL) {
340  uip_create_solicited_node(tgt, &UIP_IP_BUF->destipaddr);
341  } else {
342  uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, dest);
343  }
344  UIP_ICMP_BUF->type = ICMP6_NS;
345  UIP_ICMP_BUF->icode = 0;
346  UIP_ND6_NS_BUF->reserved = 0;
347  uip_ipaddr_copy((uip_ipaddr_t *) &UIP_ND6_NS_BUF->tgtipaddr, tgt);
348  UIP_IP_BUF->len[0] = 0; /* length will not be more than 255 */
349  /*
350  * check if we add a SLLAO option: for DAD, MUST NOT, for NUD, MAY
351  * (here yes), for Address resolution , MUST
352  */
353  if(!(uip_ds6_is_my_addr(tgt))) {
354  if(src != NULL) {
355  uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, src);
356  } else {
357  uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
358  }
359  if (uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
360  PRINTF("Dropping NS due to no suitable source address\n");
361  uip_len = 0;
362  return;
363  }
364  UIP_IP_BUF->len[1] =
365  UIP_ICMPH_LEN + UIP_ND6_NS_LEN + UIP_ND6_OPT_LLAO_LEN;
366 
367  create_llao(&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_NS_LEN],
369 
370  uip_len =
371  UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NS_LEN + UIP_ND6_OPT_LLAO_LEN;
372  } else {
373  uip_create_unspecified(&UIP_IP_BUF->srcipaddr);
374  UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_NS_LEN;
375  uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NS_LEN;
376  }
377 
378  UIP_ICMP_BUF->icmpchksum = 0;
379  UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
380 
381  UIP_STAT(++uip_stat.nd6.sent);
382  PRINTF("Sending NS to ");
383  PRINT6ADDR(&UIP_IP_BUF->destipaddr);
384  PRINTF(" from ");
385  PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
386  PRINTF(" with target address ");
387  PRINT6ADDR(tgt);
388  PRINTF("\n");
389  return;
390 }
391 
392 
393 
394 /*------------------------------------------------------------------*/
395 void
397 {
398  uint8_t is_llchange;
399  uint8_t is_router;
400  uint8_t is_solicited;
401  uint8_t is_override;
402 
403  PRINTF("Received NA from ");
404  PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
405  PRINTF(" to ");
406  PRINT6ADDR(&UIP_IP_BUF->destipaddr);
407  PRINTF(" with target address ");
408  PRINT6ADDR((uip_ipaddr_t *) (&UIP_ND6_NA_BUF->tgtipaddr));
409  PRINTF("\n");
410  UIP_STAT(++uip_stat.nd6.recv);
411 
412  /*
413  * booleans. the three last one are not 0 or 1 but 0 or 0x80, 0x40, 0x20
414  * but it works. Be careful though, do not use tests such as is_router == 1
415  */
416  is_llchange = 0;
417  is_router = ((UIP_ND6_NA_BUF->flagsreserved & UIP_ND6_NA_FLAG_ROUTER));
418  is_solicited =
419  ((UIP_ND6_NA_BUF->flagsreserved & UIP_ND6_NA_FLAG_SOLICITED));
420  is_override =
421  ((UIP_ND6_NA_BUF->flagsreserved & UIP_ND6_NA_FLAG_OVERRIDE));
422 
423 #if UIP_CONF_IPV6_CHECKS
424  if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) ||
425  (UIP_ICMP_BUF->icode != 0) ||
426  (uip_is_addr_mcast(&UIP_ND6_NA_BUF->tgtipaddr)) ||
427  (is_solicited && uip_is_addr_mcast(&UIP_IP_BUF->destipaddr))) {
428  PRINTF("NA received is bad\n");
429  goto discard;
430  }
431 #endif /*UIP_CONF_IPV6_CHECKS */
432 
433  /* Options processing: we handle TLLAO, and must ignore others */
434  nd6_opt_offset = UIP_ND6_NA_LEN;
435  nd6_opt_llao = NULL;
436  while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) {
437 #if UIP_CONF_IPV6_CHECKS
438  if(UIP_ND6_OPT_HDR_BUF->len == 0) {
439  PRINTF("NA received is bad\n");
440  goto discard;
441  }
442 #endif /*UIP_CONF_IPV6_CHECKS */
443  switch (UIP_ND6_OPT_HDR_BUF->type) {
444  case UIP_ND6_OPT_TLLAO:
445  nd6_opt_llao = (uint8_t *)UIP_ND6_OPT_HDR_BUF;
446  break;
447  default:
448  PRINTF("ND option not supported in NA\n");
449  break;
450  }
451  nd6_opt_offset += (UIP_ND6_OPT_HDR_BUF->len << 3);
452  }
453  addr = uip_ds6_addr_lookup(&UIP_ND6_NA_BUF->tgtipaddr);
454  /* Message processing, including TLLAO if any */
455  if(addr != NULL) {
456 #if UIP_ND6_DEF_MAXDADNS > 0
457  if(addr->state == ADDR_TENTATIVE) {
458  uip_ds6_dad_failed(addr);
459  }
460 #endif /*UIP_ND6_DEF_MAXDADNS > 0 */
461  PRINTF("NA received is bad\n");
462  goto discard;
463  } else {
464  uip_lladdr_t *lladdr;
465  nbr = uip_ds6_nbr_lookup(&UIP_ND6_NA_BUF->tgtipaddr);
466  lladdr = (uip_lladdr_t *)uip_ds6_nbr_get_ll(nbr);
467  if(nbr == NULL) {
468  goto discard;
469  }
470  if(nd6_opt_llao != 0) {
471  is_llchange =
472  memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], (void *)lladdr,
473  UIP_LLADDR_LEN);
474  }
475  if(nbr->state == NBR_INCOMPLETE) {
476  if(nd6_opt_llao == NULL) {
477  goto discard;
478  }
479  memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
480  UIP_LLADDR_LEN);
481  if(is_solicited) {
482  nbr->state = NBR_REACHABLE;
483  nbr->nscount = 0;
484 
485  /* reachable time is stored in ms */
486  stimer_set(&(nbr->reachable), uip_ds6_if.reachable_time / 1000);
487 
488  } else {
489  nbr->state = NBR_STALE;
490  }
491  nbr->isrouter = is_router;
492  } else {
493  if(!is_override && is_llchange) {
494  if(nbr->state == NBR_REACHABLE) {
495  nbr->state = NBR_STALE;
496  }
497  goto discard;
498  } else {
499  if(is_override || (!is_override && nd6_opt_llao != 0 && !is_llchange)
500  || nd6_opt_llao == 0) {
501  if(nd6_opt_llao != 0) {
502  memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
503  UIP_LLADDR_LEN);
504  }
505  if(is_solicited) {
506  nbr->state = NBR_REACHABLE;
507  /* reachable time is stored in ms */
508  stimer_set(&(nbr->reachable), uip_ds6_if.reachable_time / 1000);
509  } else {
510  if(nd6_opt_llao != 0 && is_llchange) {
511  nbr->state = NBR_STALE;
512  }
513  }
514  }
515  }
516  if(nbr->isrouter && !is_router) {
517  defrt = uip_ds6_defrt_lookup(&UIP_IP_BUF->srcipaddr);
518  if(defrt != NULL) {
519  uip_ds6_defrt_rm(defrt);
520  }
521  }
522  nbr->isrouter = is_router;
523  }
524  }
525 #if UIP_CONF_IPV6_QUEUE_PKT
526  /* The nbr is now reachable, check if we had buffered a pkt for it */
527  /*if(nbr->queue_buf_len != 0) {
528  uip_len = nbr->queue_buf_len;
529  memcpy(UIP_IP_BUF, nbr->queue_buf, uip_len);
530  nbr->queue_buf_len = 0;
531  return;
532  }*/
533  if(uip_packetqueue_buflen(&nbr->packethandle) != 0) {
534  uip_len = uip_packetqueue_buflen(&nbr->packethandle);
535  memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len);
536  uip_packetqueue_free(&nbr->packethandle);
537  return;
538  }
539 
540 #endif /*UIP_CONF_IPV6_QUEUE_PKT */
541 
542 discard:
543  uip_len = 0;
544  return;
545 }
546 
547 
548 #if UIP_CONF_ROUTER
549 #if UIP_ND6_SEND_RA
550 /*---------------------------------------------------------------------------*/
551 void
552 uip_nd6_rs_input(void)
553 {
554 
555  PRINTF("Received RS from ");
556  PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
557  PRINTF(" to ");
558  PRINT6ADDR(&UIP_IP_BUF->destipaddr);
559  PRINTF("\n");
560  UIP_STAT(++uip_stat.nd6.recv);
561 
562 
563 #if UIP_CONF_IPV6_CHECKS
564  /*
565  * Check hop limit / icmp code
566  * target address must not be multicast
567  * if the NA is solicited, dest must not be multicast
568  */
569  if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) || (UIP_ICMP_BUF->icode != 0)) {
570  PRINTF("RS received is bad\n");
571  goto discard;
572  }
573 #endif /*UIP_CONF_IPV6_CHECKS */
574 
575  /* Only valid option is Source Link-Layer Address option any thing
576  else is discarded */
577  nd6_opt_offset = UIP_ND6_RS_LEN;
578  nd6_opt_llao = NULL;
579 
580  while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) {
581 #if UIP_CONF_IPV6_CHECKS
582  if(UIP_ND6_OPT_HDR_BUF->len == 0) {
583  PRINTF("RS received is bad\n");
584  goto discard;
585  }
586 #endif /*UIP_CONF_IPV6_CHECKS */
587  switch (UIP_ND6_OPT_HDR_BUF->type) {
588  case UIP_ND6_OPT_SLLAO:
589  nd6_opt_llao = (uint8_t *)UIP_ND6_OPT_HDR_BUF;
590  break;
591  default:
592  PRINTF("ND option not supported in RS\n");
593  break;
594  }
595  nd6_opt_offset += (UIP_ND6_OPT_HDR_BUF->len << 3);
596  }
597  /* Options processing: only SLLAO */
598  if(nd6_opt_llao != NULL) {
599 #if UIP_CONF_IPV6_CHECKS
600  if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
601  PRINTF("RS received is bad\n");
602  goto discard;
603  } else {
604 #endif /*UIP_CONF_IPV6_CHECKS */
605  if((nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr)) == NULL) {
606  /* we need to add the neighbor */
607  uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr,
608  (uip_lladdr_t *)&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], 0, NBR_STALE);
609  } else {
610  /* If LL address changed, set neighbor state to stale */
611  if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
612  uip_ds6_nbr_get_ll(nbr), UIP_LLADDR_LEN) != 0) {
613  uip_ds6_nbr_t nbr_data = *nbr;
614  uip_ds6_nbr_rm(nbr);
615  nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr,
616  (uip_lladdr_t *)&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], 0, NBR_STALE);
617  nbr->reachable = nbr_data.reachable;
618  nbr->sendns = nbr_data.sendns;
619  nbr->nscount = nbr_data.nscount;
620  }
621  nbr->isrouter = 0;
622  }
623 #if UIP_CONF_IPV6_CHECKS
624  }
625 #endif /*UIP_CONF_IPV6_CHECKS */
626  }
627 
628  /* Schedule a sollicited RA */
629  uip_ds6_send_ra_sollicited();
630 
631 discard:
632  uip_len = 0;
633  return;
634 }
635 
636 /*---------------------------------------------------------------------------*/
637 void
638 uip_nd6_ra_output(uip_ipaddr_t * dest)
639 {
640 
641  UIP_IP_BUF->vtc = 0x60;
642  UIP_IP_BUF->tcflow = 0;
643  UIP_IP_BUF->flow = 0;
644  UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
646 
647  if(dest == NULL) {
649  } else {
650  /* For sollicited RA */
651  uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, dest);
652  }
653  uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
654 
655  UIP_ICMP_BUF->type = ICMP6_RA;
656  UIP_ICMP_BUF->icode = 0;
657 
658  UIP_ND6_RA_BUF->cur_ttl = uip_ds6_if.cur_hop_limit;
659 
660  UIP_ND6_RA_BUF->flags_reserved =
661  (UIP_ND6_M_FLAG << 7) | (UIP_ND6_O_FLAG << 6);
662 
663  UIP_ND6_RA_BUF->router_lifetime = uip_htons(UIP_ND6_ROUTER_LIFETIME);
664  //UIP_ND6_RA_BUF->reachable_time = uip_htonl(uip_ds6_if.reachable_time);
665  //UIP_ND6_RA_BUF->retrans_timer = uip_htonl(uip_ds6_if.retrans_timer);
666  UIP_ND6_RA_BUF->reachable_time = 0;
667  UIP_ND6_RA_BUF->retrans_timer = 0;
668 
669  uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_RA_LEN;
670  nd6_opt_offset = UIP_ND6_RA_LEN;
671 
672 
673 #if !UIP_CONF_ROUTER
674  /* Prefix list */
675  for(prefix = uip_ds6_prefix_list;
676  prefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; prefix++) {
677  if((prefix->isused) && (prefix->advertise)) {
678  UIP_ND6_OPT_PREFIX_BUF->type = UIP_ND6_OPT_PREFIX_INFO;
679  UIP_ND6_OPT_PREFIX_BUF->len = UIP_ND6_OPT_PREFIX_INFO_LEN / 8;
680  UIP_ND6_OPT_PREFIX_BUF->preflen = prefix->length;
681  UIP_ND6_OPT_PREFIX_BUF->flagsreserved1 = prefix->l_a_reserved;
682  UIP_ND6_OPT_PREFIX_BUF->validlt = uip_htonl(prefix->vlifetime);
683  UIP_ND6_OPT_PREFIX_BUF->preferredlt = uip_htonl(prefix->plifetime);
684  UIP_ND6_OPT_PREFIX_BUF->reserved2 = 0;
685  uip_ipaddr_copy(&(UIP_ND6_OPT_PREFIX_BUF->prefix), &(prefix->ipaddr));
686  nd6_opt_offset += UIP_ND6_OPT_PREFIX_INFO_LEN;
687  uip_len += UIP_ND6_OPT_PREFIX_INFO_LEN;
688  }
689  }
690 #endif /* !UIP_CONF_ROUTER */
691 
692  /* Source link-layer option */
693  create_llao((uint8_t *)UIP_ND6_OPT_HDR_BUF, UIP_ND6_OPT_SLLAO);
694 
696  nd6_opt_offset += UIP_ND6_OPT_LLAO_LEN;
697 
698  /* MTU */
699  UIP_ND6_OPT_MTU_BUF->type = UIP_ND6_OPT_MTU;
700  UIP_ND6_OPT_MTU_BUF->len = UIP_ND6_OPT_MTU_LEN >> 3;
701  UIP_ND6_OPT_MTU_BUF->reserved = 0;
702  //UIP_ND6_OPT_MTU_BUF->mtu = uip_htonl(uip_ds6_if.link_mtu);
703  UIP_ND6_OPT_MTU_BUF->mtu = uip_htonl(1500);
704 
705  uip_len += UIP_ND6_OPT_MTU_LEN;
706  nd6_opt_offset += UIP_ND6_OPT_MTU_LEN;
707  UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
708  UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
709 
710  /*ICMP checksum */
711  UIP_ICMP_BUF->icmpchksum = 0;
712  UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
713 
714  UIP_STAT(++uip_stat.nd6.sent);
715  PRINTF("Sending RA to ");
716  PRINT6ADDR(&UIP_IP_BUF->destipaddr);
717  PRINTF(" from ");
718  PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
719  PRINTF("\n");
720  return;
721 }
722 #endif /* UIP_ND6_SEND_RA */
723 #endif /* UIP_CONF_ROUTER */
724 
725 #if !UIP_CONF_ROUTER
726 /*---------------------------------------------------------------------------*/
727 void
729 {
730  UIP_IP_BUF->vtc = 0x60;
731  UIP_IP_BUF->tcflow = 0;
732  UIP_IP_BUF->flow = 0;
733  UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
736  uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
737  UIP_ICMP_BUF->type = ICMP6_RS;
738  UIP_ICMP_BUF->icode = 0;
739  UIP_IP_BUF->len[0] = 0; /* length will not be more than 255 */
740 
741  if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
742  UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_RS_LEN;
743  uip_len = uip_l3_icmp_hdr_len + UIP_ND6_RS_LEN;
744  } else {
745  uip_len = uip_l3_icmp_hdr_len + UIP_ND6_RS_LEN + UIP_ND6_OPT_LLAO_LEN;
746  UIP_IP_BUF->len[1] =
747  UIP_ICMPH_LEN + UIP_ND6_RS_LEN + UIP_ND6_OPT_LLAO_LEN;
748 
749  create_llao(&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_RS_LEN],
751  }
752 
753  UIP_ICMP_BUF->icmpchksum = 0;
754  UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
755 
756  UIP_STAT(++uip_stat.nd6.sent);
757  PRINTF("Sending RS to ");
758  PRINT6ADDR(&UIP_IP_BUF->destipaddr);
759  PRINTF(" from ");
760  PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
761  PRINTF("\n");
762  return;
763 }
764 
765 
766 /*---------------------------------------------------------------------------*/
767 void
769 {
770  PRINTF("Received RA from ");
771  PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
772  PRINTF(" to ");
773  PRINT6ADDR(&UIP_IP_BUF->destipaddr);
774  PRINTF("\n");
775  UIP_STAT(++uip_stat.nd6.recv);
776 
777 #if UIP_CONF_IPV6_CHECKS
778  if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) ||
779  (!uip_is_addr_link_local(&UIP_IP_BUF->srcipaddr)) ||
780  (UIP_ICMP_BUF->icode != 0)) {
781  PRINTF("RA received is bad");
782  goto discard;
783  }
784 #endif /*UIP_CONF_IPV6_CHECKS */
785 
786  if(UIP_ND6_RA_BUF->cur_ttl != 0) {
787  uip_ds6_if.cur_hop_limit = UIP_ND6_RA_BUF->cur_ttl;
788  PRINTF("uip_ds6_if.cur_hop_limit %u\n", uip_ds6_if.cur_hop_limit);
789  }
790 
791  if(UIP_ND6_RA_BUF->reachable_time != 0) {
792  if(uip_ds6_if.base_reachable_time !=
793  uip_ntohl(UIP_ND6_RA_BUF->reachable_time)) {
794  uip_ds6_if.base_reachable_time = uip_ntohl(UIP_ND6_RA_BUF->reachable_time);
795  uip_ds6_if.reachable_time = uip_ds6_compute_reachable_time();
796  }
797  }
798  if(UIP_ND6_RA_BUF->retrans_timer != 0) {
799  uip_ds6_if.retrans_timer = uip_ntohl(UIP_ND6_RA_BUF->retrans_timer);
800  }
801 
802  /* Options processing */
803  nd6_opt_offset = UIP_ND6_RA_LEN;
804  while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) {
805  if(UIP_ND6_OPT_HDR_BUF->len == 0) {
806  PRINTF("RA received is bad");
807  goto discard;
808  }
809  switch (UIP_ND6_OPT_HDR_BUF->type) {
810  case UIP_ND6_OPT_SLLAO:
811  PRINTF("Processing SLLAO option in RA\n");
812  nd6_opt_llao = (uint8_t *) UIP_ND6_OPT_HDR_BUF;
813  nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr);
814  if(nbr == NULL) {
815  nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr,
816  (uip_lladdr_t *)&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
817  1, NBR_STALE);
818  } else {
819  if(nbr->state == NBR_INCOMPLETE) {
820  nbr->state = NBR_STALE;
821  }
822  uip_lladdr_t *lladdr = uip_ds6_nbr_get_ll(nbr);
823  if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
824  lladdr, UIP_LLADDR_LEN) != 0) {
825  memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
826  UIP_LLADDR_LEN);
827  nbr->state = NBR_STALE;
828  }
829  nbr->isrouter = 1;
830  }
831  break;
832  case UIP_ND6_OPT_MTU:
833  PRINTF("Processing MTU option in RA\n");
834  uip_ds6_if.link_mtu =
835  uip_ntohl(((uip_nd6_opt_mtu *) UIP_ND6_OPT_HDR_BUF)->mtu);
836  break;
837  case UIP_ND6_OPT_PREFIX_INFO:
838  PRINTF("Processing PREFIX option in RA\n");
839  nd6_opt_prefix_info = (uip_nd6_opt_prefix_info *) UIP_ND6_OPT_HDR_BUF;
840  if((uip_ntohl(nd6_opt_prefix_info->validlt) >=
841  uip_ntohl(nd6_opt_prefix_info->preferredlt))
842  && (!uip_is_addr_link_local(&nd6_opt_prefix_info->prefix))) {
843  /* on-link flag related processing */
844  if(nd6_opt_prefix_info->flagsreserved1 & UIP_ND6_RA_FLAG_ONLINK) {
845  prefix =
846  uip_ds6_prefix_lookup(&nd6_opt_prefix_info->prefix,
847  nd6_opt_prefix_info->preflen);
848  if(prefix == NULL) {
849  if(nd6_opt_prefix_info->validlt != 0) {
850  if(nd6_opt_prefix_info->validlt != UIP_ND6_INFINITE_LIFETIME) {
851  prefix = uip_ds6_prefix_add(&nd6_opt_prefix_info->prefix,
852  nd6_opt_prefix_info->preflen,
853  uip_ntohl(nd6_opt_prefix_info->
854  validlt));
855  } else {
856  prefix = uip_ds6_prefix_add(&nd6_opt_prefix_info->prefix,
857  nd6_opt_prefix_info->preflen, 0);
858  }
859  }
860  } else {
861  switch (nd6_opt_prefix_info->validlt) {
862  case 0:
863  uip_ds6_prefix_rm(prefix);
864  break;
866  prefix->isinfinite = 1;
867  break;
868  default:
869  PRINTF("Updating timer of prefix");
870  PRINT6ADDR(&prefix->ipaddr);
871  PRINTF("new value %lu\n", uip_ntohl(nd6_opt_prefix_info->validlt));
872  stimer_set(&prefix->vlifetime,
873  uip_ntohl(nd6_opt_prefix_info->validlt));
874  prefix->isinfinite = 0;
875  break;
876  }
877  }
878  }
879  /* End of on-link flag related processing */
880  /* autonomous flag related processing */
881  if((nd6_opt_prefix_info->flagsreserved1 & UIP_ND6_RA_FLAG_AUTONOMOUS)
882  && (nd6_opt_prefix_info->validlt != 0)
883  && (nd6_opt_prefix_info->preflen == UIP_DEFAULT_PREFIX_LEN)) {
884 
885  uip_ipaddr_copy(&ipaddr, &nd6_opt_prefix_info->prefix);
886  uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr);
887  addr = uip_ds6_addr_lookup(&ipaddr);
888  if((addr != NULL) && (addr->type == ADDR_AUTOCONF)) {
889  if(nd6_opt_prefix_info->validlt != UIP_ND6_INFINITE_LIFETIME) {
890  /* The processing below is defined in RFC4862 section 5.5.3 e */
891  if((uip_ntohl(nd6_opt_prefix_info->validlt) > 2 * 60 * 60) ||
892  (uip_ntohl(nd6_opt_prefix_info->validlt) >
893  stimer_remaining(&addr->vlifetime))) {
894  PRINTF("Updating timer of address");
895  PRINT6ADDR(&addr->ipaddr);
896  PRINTF("new value %lu\n",
897  uip_ntohl(nd6_opt_prefix_info->validlt));
898  stimer_set(&addr->vlifetime,
899  uip_ntohl(nd6_opt_prefix_info->validlt));
900  } else {
901  stimer_set(&addr->vlifetime, 2 * 60 * 60);
902  PRINTF("Updating timer of address ");
903  PRINT6ADDR(&addr->ipaddr);
904  PRINTF("new value %lu\n", (unsigned long)(2 * 60 * 60));
905  }
906  addr->isinfinite = 0;
907  } else {
908  addr->isinfinite = 1;
909  }
910  } else {
911  if(uip_ntohl(nd6_opt_prefix_info->validlt) ==
913  uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF);
914  } else {
915  uip_ds6_addr_add(&ipaddr, uip_ntohl(nd6_opt_prefix_info->validlt),
916  ADDR_AUTOCONF);
917  }
918  }
919  }
920  /* End of autonomous flag related processing */
921  }
922  break;
923  default:
924  PRINTF("ND option not supported in RA");
925  break;
926  }
927  nd6_opt_offset += (UIP_ND6_OPT_HDR_BUF->len << 3);
928  }
929 
930  defrt = uip_ds6_defrt_lookup(&UIP_IP_BUF->srcipaddr);
931  if(UIP_ND6_RA_BUF->router_lifetime != 0) {
932  if(nbr != NULL) {
933  nbr->isrouter = 1;
934  }
935  if(defrt == NULL) {
936  uip_ds6_defrt_add(&UIP_IP_BUF->srcipaddr,
937  (unsigned
938  long)(uip_ntohs(UIP_ND6_RA_BUF->router_lifetime)));
939  } else {
940  stimer_set(&(defrt->lifetime),
941  (unsigned long)(uip_ntohs(UIP_ND6_RA_BUF->router_lifetime)));
942  }
943  } else {
944  if(defrt != NULL) {
945  uip_ds6_defrt_rm(defrt);
946  }
947  }
948 
949 #if UIP_CONF_IPV6_QUEUE_PKT
950  /* If the nbr just became reachable (e.g. it was in NBR_INCOMPLETE state
951  * and we got a SLLAO), check if we had buffered a pkt for it */
952  /* if((nbr != NULL) && (nbr->queue_buf_len != 0)) {
953  uip_len = nbr->queue_buf_len;
954  memcpy(UIP_IP_BUF, nbr->queue_buf, uip_len);
955  nbr->queue_buf_len = 0;
956  return;
957  }*/
958  if(nbr != NULL && uip_packetqueue_buflen(&nbr->packethandle) != 0) {
959  uip_len = uip_packetqueue_buflen(&nbr->packethandle);
960  memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len);
961  uip_packetqueue_free(&nbr->packethandle);
962  return;
963  }
964 
965 #endif /*UIP_CONF_IPV6_QUEUE_PKT */
966 
967 discard:
968  uip_len = 0;
969  return;
970 }
971 #endif /* !UIP_CONF_ROUTER */
972 
973  /** @} */
974 #endif /* UIP_CONF_IPV6 */