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