Contiki-NG
Loading...
Searching...
No Matches
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 if(uip_l3_icmp_hdr_len + sizeof(uip_nd6_ns) > uip_len) {
176 LOG_ERR("Insufficient data for reading ND6 NS header fields");
177 goto discard;
178 }
179
180 uint8_t flags = 0;
181
182 LOG_INFO("Received NS from ");
183 LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr);
184 LOG_INFO_(" to ");
185 LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
186 LOG_INFO_(" with target address ");
187 LOG_INFO_6ADDR((uip_ipaddr_t *)(&UIP_ND6_NS_BUF->tgtipaddr));
188 LOG_INFO_("\n");
189 UIP_STAT(++uip_stat.nd6.recv);
190
191 if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) ||
192 (uip_is_addr_mcast(&UIP_ND6_NS_BUF->tgtipaddr)) ||
193 (UIP_ICMP_BUF->icode != 0)) {
194 LOG_ERR("Discarding invalid NS\n");
195 goto discard;
196 }
197
198 /* Options processing */
199 nd6_opt_llao = NULL;
200 nd6_opt_offset = UIP_ND6_NS_LEN;
201 while(uip_l3_icmp_hdr_len + nd6_opt_offset + UIP_ND6_OPT_HDR_LEN < uip_len) {
202 if(ND6_OPT_HDR_BUF(nd6_opt_offset)->len == 0) {
203 LOG_ERR("Discarding invalid NS\n");
204 goto discard;
205 }
206
207 switch(ND6_OPT_HDR_BUF(nd6_opt_offset)->type) {
208 case UIP_ND6_OPT_SLLAO:
209 if(uip_l3_icmp_hdr_len + nd6_opt_offset +
210 UIP_ND6_OPT_DATA_OFFSET + UIP_LLADDR_LEN > uip_len) {
211 LOG_ERR("Insufficient data for NS SLLAO option\n");
212 goto discard;
213 }
214 nd6_opt_llao = &uip_buf[uip_l3_icmp_hdr_len + nd6_opt_offset];
215
216 /* There must be NO option in a DAD NS */
217 if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
218 LOG_ERR("Discarding invalid NS\n");
219 goto discard;
220 } else {
221 uip_lladdr_t lladdr_aligned;
222 extract_lladdr_from_llao_aligned(&lladdr_aligned);
223 nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr);
224 if(nbr == NULL) {
225 uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned,
226 0, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL);
227 } else {
228 const uip_lladdr_t *lladdr = uip_ds6_nbr_get_ll(nbr);
229 if(lladdr == NULL) {
230 goto discard;
231 }
232 if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
233 lladdr, UIP_LLADDR_LEN) != 0) {
235 (const uip_lladdr_t *)&lladdr_aligned)
236 < 0) {
237 /* failed to update the lladdr */
238 goto discard;
239 }
240 nbr->state = NBR_STALE;
241 } else {
242 if(nbr->state == NBR_INCOMPLETE) {
243 nbr->state = NBR_STALE;
244 }
245 }
246 }
247 }
248 break;
249 default:
250 LOG_WARN("ND option not supported in NS");
251 break;
252 }
253 nd6_opt_offset += (ND6_OPT_HDR_BUF(nd6_opt_offset)->len << 3);
254 }
255
256 addr = uip_ds6_addr_lookup(&UIP_ND6_NS_BUF->tgtipaddr);
257 if(addr != NULL) {
258 if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
259 /* DAD CASE */
260#if UIP_ND6_DEF_MAXDADNS > 0
261 if(!uip_is_addr_solicited_node(&UIP_IP_BUF->destipaddr)) {
262 LOG_ERR("Discarding invalid NS\n");
263 goto discard;
264 }
265
266 if(addr->state != ADDR_TENTATIVE) {
268 uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
269 flags = UIP_ND6_NA_FLAG_OVERRIDE;
270 goto create_na;
271 } else {
272 /** \todo if I sent a NS before him, I win */
274 goto discard;
275 }
276#else /* UIP_ND6_DEF_MAXDADNS > 0 */
277 goto discard; /* DAD CASE */
278#endif /* UIP_ND6_DEF_MAXDADNS > 0 */
279 }
280
281 if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)) {
282 /**
283 * \NOTE do we do something here? we both are using the same address.
284 * If we are doing dad, we could cancel it, though we should receive a
285 * NA in response of DAD NS we sent, hence DAD will fail anyway. If we
286 * were not doing DAD, it means there is a duplicate in the network!
287 */
288 LOG_ERR("Discarding invalid NS\n");
289 goto discard;
290 }
291
292 /* Address resolution case */
293 if(uip_is_addr_solicited_node(&UIP_IP_BUF->destipaddr)) {
294 uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr);
295 uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &UIP_ND6_NS_BUF->tgtipaddr);
296 flags = UIP_ND6_NA_FLAG_SOLICITED | UIP_ND6_NA_FLAG_OVERRIDE;
297 goto create_na;
298 }
299
300 /* NUD CASE */
301 if(uip_ds6_addr_lookup(&UIP_IP_BUF->destipaddr) == addr) {
302 uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr);
303 uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &UIP_ND6_NS_BUF->tgtipaddr);
304 flags = UIP_ND6_NA_FLAG_SOLICITED | UIP_ND6_NA_FLAG_OVERRIDE;
305 goto create_na;
306 } else {
307 LOG_ERR("Discarding invalid NS\n");
308 goto discard;
309 }
310 } else {
311 goto discard;
312 }
313
314create_na:
315 /* If the node is a router it should set R flag in NAs */
316#if UIP_CONF_ROUTER
317 flags = flags | UIP_ND6_NA_FLAG_ROUTER;
318#endif
319 uipbuf_clear();
320 UIP_IP_BUF->vtc = 0x60;
321 UIP_IP_BUF->tcflow = 0;
322 UIP_IP_BUF->flow = 0;
323 uipbuf_set_len_field(UIP_IP_BUF, UIP_ICMPH_LEN + UIP_ND6_NA_LEN + UIP_ND6_OPT_LLAO_LEN);
324 UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
326
327 UIP_ICMP_BUF->type = ICMP6_NA;
328 UIP_ICMP_BUF->icode = 0;
329
330 UIP_ND6_NA_BUF->flagsreserved = flags;
331 memcpy(&UIP_ND6_NA_BUF->tgtipaddr, &addr->ipaddr, sizeof(uip_ipaddr_t));
332
333 create_llao(&uip_buf[uip_l3_icmp_hdr_len + UIP_ND6_NA_LEN],
334 UIP_ND6_OPT_TLLAO);
335
336 UIP_ICMP_BUF->icmpchksum = 0;
337 UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
338
339 uipbuf_set_len(UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NA_LEN + UIP_ND6_OPT_LLAO_LEN);
340
341 UIP_STAT(++uip_stat.nd6.sent);
342 LOG_INFO("Sending NA to ");
343 LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
344 LOG_INFO_(" from ");
345 LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr);
346 LOG_INFO_(" with target address ");
347 LOG_INFO_6ADDR(&UIP_ND6_NA_BUF->tgtipaddr);
348 LOG_INFO_("\n");
349 return;
350
351discard:
352 uipbuf_clear();
353 return;
354}
355#endif /* UIP_ND6_SEND_NA */
356
357/*------------------------------------------------------------------*/
358#if UIP_ND6_SEND_NS
359void
360uip_nd6_ns_output(const uip_ipaddr_t *src, const uip_ipaddr_t *dest,
361 uip_ipaddr_t *tgt)
362{
363 uipbuf_clear();
364 UIP_IP_BUF->vtc = 0x60;
365 UIP_IP_BUF->tcflow = 0;
366 UIP_IP_BUF->flow = 0;
367 UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
369
370 if(dest == NULL) {
371 uip_create_solicited_node(tgt, &UIP_IP_BUF->destipaddr);
372 } else {
373 uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, dest);
374 }
375 UIP_ICMP_BUF->type = ICMP6_NS;
376 UIP_ICMP_BUF->icode = 0;
377 UIP_ND6_NS_BUF->reserved = 0;
378 uip_ipaddr_copy((uip_ipaddr_t *)&UIP_ND6_NS_BUF->tgtipaddr, tgt);
379 /*
380 * check if we add a SLLAO option: for DAD, MUST NOT, for NUD, MAY
381 * (here yes), for Address resolution , MUST
382 */
383 if(!(uip_ds6_is_my_addr(tgt))) {
384 if(src != NULL) {
385 uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, src);
386 } else {
387 uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
388 }
389 if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
390 LOG_ERR("Dropping NS due to no suitable source address\n");
391 uipbuf_clear();
392 return;
393 }
394 uipbuf_set_len_field(UIP_IP_BUF, UIP_ICMPH_LEN + UIP_ND6_NS_LEN + UIP_ND6_OPT_LLAO_LEN);
395
396 create_llao(&uip_buf[uip_l3_icmp_hdr_len + UIP_ND6_NS_LEN],
397 UIP_ND6_OPT_SLLAO);
398
399 uip_len =
400 UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NS_LEN + UIP_ND6_OPT_LLAO_LEN;
401 } else {
403 UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_NS_LEN;
404 uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NS_LEN;
405 }
406
407 UIP_ICMP_BUF->icmpchksum = 0;
408 UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
409
410 UIP_STAT(++uip_stat.nd6.sent);
411 LOG_INFO("Sending NS to ");
412 LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
413 LOG_INFO_(" from ");
414 LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr);
415 LOG_INFO_(" with target address ");
416 LOG_INFO_6ADDR(tgt);
417 LOG_INFO_("\n");
418 return;
419}
420#endif /* UIP_ND6_SEND_NS */
421
422#if UIP_ND6_SEND_NS
423/*------------------------------------------------------------------*/
424/**
425 * Neighbor Advertisement Processing
426 *
427 * we might have to send a pkt that had been buffered while address
428 * resolution was performed (if we support buffering, see UIP_CONF_QUEUE_PKT)
429 *
430 * As per RFC 4861, on link layer that have addresses, TLLAO options MUST be
431 * included when responding to multicast solicitations, SHOULD be included in
432 * response to unicast (here we assume it is for now)
433 *
434 * NA can be received after sending NS for DAD, Address resolution or NUD. Can
435 * be unsolicited as well.
436 * It can trigger update of the state of the neighbor in the neighbor cache,
437 * router in the router list.
438 * If the NS was for DAD, it means DAD failed
439 *
440 */
441static void
442na_input(void)
443{
444 uint8_t is_llchange;
445 uint8_t is_router;
446 uint8_t is_solicited;
447 uint8_t is_override;
448 uip_lladdr_t lladdr_aligned;
449
450 LOG_INFO("Received NA from ");
451 LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr);
452 LOG_INFO_(" to ");
453 LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
454 LOG_INFO_(" with target address ");
455 LOG_INFO_6ADDR((uip_ipaddr_t *)(&UIP_ND6_NA_BUF->tgtipaddr));
456 LOG_INFO_("\n");
457 UIP_STAT(++uip_stat.nd6.recv);
458
459 /*
460 * booleans. the three last one are not 0 or 1 but 0 or 0x80, 0x40, 0x20
461 * but it works. Be careful though, do not use tests such as is_router == 1
462 */
463 is_llchange = 0;
464 is_router = ((UIP_ND6_NA_BUF->flagsreserved & UIP_ND6_NA_FLAG_ROUTER));
465 is_solicited =
466 ((UIP_ND6_NA_BUF->flagsreserved & UIP_ND6_NA_FLAG_SOLICITED));
467 is_override =
468 ((UIP_ND6_NA_BUF->flagsreserved & UIP_ND6_NA_FLAG_OVERRIDE));
469
470 if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) ||
471 (UIP_ICMP_BUF->icode != 0) ||
472 (uip_is_addr_mcast(&UIP_ND6_NA_BUF->tgtipaddr)) ||
473 (is_solicited && uip_is_addr_mcast(&UIP_IP_BUF->destipaddr))) {
474 LOG_ERR("Discarding invalid NA\n");
475 goto discard;
476 }
477
478 /* Options processing: we handle TLLAO, and must ignore others */
479 nd6_opt_offset = UIP_ND6_NA_LEN;
480 nd6_opt_llao = NULL;
481 while(uip_l3_icmp_hdr_len + nd6_opt_offset + UIP_ND6_OPT_HDR_LEN < uip_len) {
482 if(ND6_OPT_HDR_BUF(nd6_opt_offset)->len == 0) {
483 LOG_ERR("Discarding invalid NA\n");
484 goto discard;
485 }
486
487 switch(ND6_OPT_HDR_BUF(nd6_opt_offset)->type) {
488 case UIP_ND6_OPT_TLLAO:
489 /* Validate that the full TLLAO option fits within packet bounds */
490 if(uip_l3_icmp_hdr_len + nd6_opt_offset + UIP_ND6_OPT_LLAO_LEN > uip_len) {
491 LOG_ERR("TLLAO option extends beyond packet boundary\n");
492 goto discard;
493 }
494 nd6_opt_llao = (uint8_t *)ND6_OPT_HDR_BUF(nd6_opt_offset);
495 break;
496 default:
497 LOG_WARN("ND option not supported in NA\n");
498 break;
499 }
500 nd6_opt_offset += (ND6_OPT_HDR_BUF(nd6_opt_offset)->len << 3);
501 }
502 addr = uip_ds6_addr_lookup(&UIP_ND6_NA_BUF->tgtipaddr);
503 /* Message processing, including TLLAO if any */
504 if(addr != NULL) {
505#if UIP_ND6_DEF_MAXDADNS > 0
506 if(addr->state == ADDR_TENTATIVE) {
508 }
509#endif /*UIP_ND6_DEF_MAXDADNS > 0 */
510 LOG_ERR("Discarding invalid NA\n");
511 goto discard;
512 } else {
513 const uip_lladdr_t *lladdr;
514 nbr = uip_ds6_nbr_lookup(&UIP_ND6_NA_BUF->tgtipaddr);
515 if(nbr == NULL) {
516 goto discard;
517 }
518 lladdr = uip_ds6_nbr_get_ll(nbr);
519 if(lladdr == NULL) {
520 goto discard;
521 }
522 if(nd6_opt_llao != NULL) {
523 is_llchange =
524 memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], lladdr,
525 UIP_LLADDR_LEN) == 0 ? 0 : 1;
526 }
527 if(nbr->state == NBR_INCOMPLETE) {
528 if(nd6_opt_llao == NULL || !extract_lladdr_from_llao_aligned(&lladdr_aligned)) {
529 goto discard;
530 }
532 (const uip_lladdr_t *)&lladdr_aligned) < 0) {
533 /* failed to update the lladdr */
534 goto discard;
535 }
536
537 /* Note: No need to refresh the state of the nbr here.
538 * It has already been refreshed upon receiving the unicast IPv6 ND packet.
539 * See: uip_ds6_nbr_refresh_reachable_state()
540 */
541 if(!is_solicited) {
542 nbr->state = NBR_STALE;
543 }
544 nbr->isrouter = is_router;
545 } else { /* NBR is not INCOMPLETE */
546 if(!is_override && is_llchange) {
547 if(nbr->state == NBR_REACHABLE) {
548 nbr->state = NBR_STALE;
549 }
550 goto discard;
551 } else {
552 /**
553 * If this is an cache override, or same lladdr, or no llao -
554 * do updates of nbr states.
555 */
556 if(is_override || !is_llchange || nd6_opt_llao == NULL) {
557 if(nd6_opt_llao != NULL && is_llchange) {
558 if(!extract_lladdr_from_llao_aligned(&lladdr_aligned) ||
560 (const uip_lladdr_t *)&lladdr_aligned)
561 < 0) {
562 /* failed to update the lladdr */
563 goto discard;
564 }
565 }
566 /* Note: No need to refresh the state of the nbr here.
567 * It has already been refreshed upon receiving the unicast IPv6 ND packet.
568 * See: uip_ds6_nbr_refresh_reachable_state()
569 */
570 }
571 }
572 if(nbr->isrouter && !is_router) {
573 defrt = uip_ds6_defrt_lookup(&UIP_IP_BUF->srcipaddr);
574 if(defrt != NULL) {
575 uip_ds6_defrt_rm(defrt);
576 }
577 }
578 nbr->isrouter = is_router;
579 }
580 }
581#if UIP_CONF_IPV6_QUEUE_PKT
582 /* The nbr is now reachable, check if we had buffered a pkt for it */
583 if(uip_packetqueue_buflen(&nbr->packethandle) != 0) {
584 uip_len = uip_packetqueue_buflen(&nbr->packethandle);
585 memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len);
586 uip_packetqueue_free(&nbr->packethandle);
587 return;
588 }
589
590#endif /*UIP_CONF_IPV6_QUEUE_PKT */
591
592discard:
593 uipbuf_clear();
594 return;
595}
596#endif /* UIP_ND6_SEND_NS */
597
598#if UIP_CONF_ROUTER
599#if UIP_ND6_SEND_RA
600/*---------------------------------------------------------------------------*/
601static void
602rs_input(void)
603{
604
605 LOG_INFO("Received RS from ");
606 LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr);
607 LOG_INFO_(" to ");
608 LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
609 LOG_INFO_("\n");
610 UIP_STAT(++uip_stat.nd6.recv);
611
612 /*
613 * Check hop limit / icmp code
614 * target address must not be multicast
615 * if the NA is solicited, dest must not be multicast
616 */
617 if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) || (UIP_ICMP_BUF->icode != 0)) {
618 LOG_ERR("Discarding invalid RS\n");
619 goto discard;
620 }
621
622 /* Only valid option is Source Link-Layer Address option any thing
623 else is discarded */
624 nd6_opt_offset = UIP_ND6_RS_LEN;
625 nd6_opt_llao = NULL;
626
627 while(uip_l3_icmp_hdr_len + nd6_opt_offset + UIP_ND6_OPT_HDR_LEN < uip_len) {
628 if(ND6_OPT_HDR_BUF(nd6_opt_offset)->len == 0) {
629 LOG_ERR("Discarding invalid RS\n");
630 goto discard;
631 }
632
633 switch(ND6_OPT_HDR_BUF(nd6_opt_offset)->type) {
634 case UIP_ND6_OPT_SLLAO:
635 /* Validate that the full SLLAO option fits within packet bounds */
636 if(uip_l3_icmp_hdr_len + nd6_opt_offset + UIP_ND6_OPT_LLAO_LEN > uip_len) {
637 LOG_ERR("SLLAO option extends beyond packet boundary\n");
638 goto discard;
639 }
640 nd6_opt_llao = (uint8_t *)ND6_OPT_HDR_BUF(nd6_opt_offset);
641 break;
642 default:
643 LOG_WARN("ND option not supported in RS\n");
644 break;
645 }
646 nd6_opt_offset += (ND6_OPT_HDR_BUF(nd6_opt_offset)->len << 3);
647 }
648 /* Options processing: only SLLAO */
649 if(nd6_opt_llao != NULL) {
650 if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
651 LOG_ERR("Discarding invalid RS\n");
652 goto discard;
653 } else {
654 uip_lladdr_t lladdr_aligned;
655 extract_lladdr_from_llao_aligned(&lladdr_aligned);
656 if((nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr)) == NULL) {
657 /* we need to add the neighbor */
658 uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned,
659 0, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL);
660 } else {
661 /* If LL address changed, set neighbor state to stale */
662 const uip_lladdr_t *lladdr = uip_ds6_nbr_get_ll(nbr);
663 if(lladdr == NULL) {
664 goto discard;
665 }
666 if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
667 lladdr, UIP_LLADDR_LEN) != 0) {
668 uip_ds6_nbr_t nbr_data;
669 nbr_data = *nbr;
671 nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned,
672 0, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL);
673 if(nbr == NULL) {
674 goto discard;
675 }
676 nbr->reachable = nbr_data.reachable;
677 nbr->sendns = nbr_data.sendns;
678 nbr->nscount = nbr_data.nscount;
679 }
680 nbr->isrouter = 0;
681 }
682 }
683 }
684
685 /* Schedule a sollicited RA */
686 uip_ds6_send_ra_sollicited();
687
688discard:
689 uipbuf_clear();
690 return;
691}
692/*---------------------------------------------------------------------------*/
693void
694uip_nd6_ra_output(const uip_ipaddr_t *dest)
695{
696
697 UIP_IP_BUF->vtc = 0x60;
698 UIP_IP_BUF->tcflow = 0;
699 UIP_IP_BUF->flow = 0;
700 UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
702
703 if(dest == NULL) {
705 } else {
706 /* For sollicited RA */
707 uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, dest);
708 }
709 uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
710
711 UIP_ICMP_BUF->type = ICMP6_RA;
712 UIP_ICMP_BUF->icode = 0;
713
714 UIP_ND6_RA_BUF->cur_ttl = uip_ds6_if.cur_hop_limit;
715
716 UIP_ND6_RA_BUF->flags_reserved =
717 (UIP_ND6_M_FLAG << 7) | (UIP_ND6_O_FLAG << 6);
718
719 UIP_ND6_RA_BUF->router_lifetime = uip_htons(UIP_ND6_ROUTER_LIFETIME);
720 UIP_ND6_RA_BUF->reachable_time = 0;
721 UIP_ND6_RA_BUF->retrans_timer = 0;
722
723 uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_RA_LEN;
724 nd6_opt_offset = UIP_ND6_RA_LEN;
725
726 /* Prefix list */
727 for(prefix = uip_ds6_prefix_list;
728 prefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; prefix++) {
729 if((prefix->isused) && (prefix->advertise)) {
730 ND6_OPT_PREFIX_BUF(nd6_opt_offset)->type = UIP_ND6_OPT_PREFIX_INFO;
731 ND6_OPT_PREFIX_BUF(nd6_opt_offset)->len = UIP_ND6_OPT_PREFIX_INFO_LEN / 8;
732 ND6_OPT_PREFIX_BUF(nd6_opt_offset)->preflen = prefix->length;
733 ND6_OPT_PREFIX_BUF(nd6_opt_offset)->flagsreserved1 = prefix->l_a_reserved;
734 ND6_OPT_PREFIX_BUF(nd6_opt_offset)->validlt = uip_htonl(prefix->vlifetime);
735 ND6_OPT_PREFIX_BUF(nd6_opt_offset)->preferredlt = uip_htonl(prefix->plifetime);
736 ND6_OPT_PREFIX_BUF(nd6_opt_offset)->reserved2 = 0;
737 uip_ipaddr_copy(&(ND6_OPT_PREFIX_BUF(nd6_opt_offset)->prefix), &(prefix->ipaddr));
738 nd6_opt_offset += UIP_ND6_OPT_PREFIX_INFO_LEN;
739 uip_len += UIP_ND6_OPT_PREFIX_INFO_LEN;
740 }
741 }
742
743 /* Source link-layer option */
744 create_llao((uint8_t *)ND6_OPT_HDR_BUF(nd6_opt_offset), UIP_ND6_OPT_SLLAO);
745
747 nd6_opt_offset += UIP_ND6_OPT_LLAO_LEN;
748
749 /* MTU */
750 ND6_OPT_MTU_BUF(nd6_opt_offset)->type = UIP_ND6_OPT_MTU;
751 ND6_OPT_MTU_BUF(nd6_opt_offset)->len = UIP_ND6_OPT_MTU_LEN >> 3;
752 ND6_OPT_MTU_BUF(nd6_opt_offset)->reserved = 0;
753 ND6_OPT_MTU_BUF(nd6_opt_offset)->mtu = uip_htonl(1500);
754
755 uip_len += UIP_ND6_OPT_MTU_LEN;
756 nd6_opt_offset += UIP_ND6_OPT_MTU_LEN;
757
758#if UIP_ND6_RA_RDNSS
759 if(uip_nameserver_count() > 0) {
760 uint8_t i = 0;
761 uip_ipaddr_t *ip = &ND6_OPT_RDNSS_BUF(nd6_opt_offset)->ip;
762 uip_ipaddr_t *dns = NULL;
763 ND6_OPT_RDNSS_BUF(nd6_opt_offset)->type = UIP_ND6_OPT_RDNSS;
764 ND6_OPT_RDNSS_BUF(nd6_opt_offset)->reserved = 0;
765 ND6_OPT_RDNSS_BUF(nd6_opt_offset)->lifetime = uip_nameserver_next_expiration();
766 if(ND6_OPT_RDNSS_BUF(nd6_opt_offset)->lifetime != UIP_NAMESERVER_INFINITE_LIFETIME) {
767 ND6_OPT_RDNSS_BUF(nd6_opt_offset)->lifetime -= clock_seconds();
768 }
769 while((dns = uip_nameserver_get(i)) != NULL) {
770 uip_ipaddr_copy(ip++, dns);
771 i++;
772 }
773 ND6_OPT_RDNSS_BUF(nd6_opt_offset)->len = UIP_ND6_OPT_RDNSS_LEN + (i << 1);
774 LOG_INFO("%d nameservers reported\n", i);
775 uip_len += ND6_OPT_RDNSS_BUF(nd6_opt_offset)->len << 3;
776 nd6_opt_offset += ND6_OPT_RDNSS_BUF(nd6_opt_offset)->len << 3;
777 }
778#endif /* UIP_ND6_RA_RDNSS */
779
780 uipbuf_set_len_field(UIP_IP_BUF, uip_len - UIP_IPH_LEN);
781
782 /*ICMP checksum */
783 UIP_ICMP_BUF->icmpchksum = 0;
784 UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
785
786 UIP_STAT(++uip_stat.nd6.sent);
787 LOG_INFO("Sending RA to ");
788 LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
789 LOG_INFO_(" from ");
790 LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr);
791 LOG_INFO_("\n");
792 return;
793}
794#endif /* UIP_ND6_SEND_RA */
795#endif /* UIP_CONF_ROUTER */
796
797#if !UIP_CONF_ROUTER
798/*---------------------------------------------------------------------------*/
799void
801{
802 UIP_IP_BUF->vtc = 0x60;
803 UIP_IP_BUF->tcflow = 0;
804 UIP_IP_BUF->flow = 0;
805 UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
808 uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
809 UIP_ICMP_BUF->type = ICMP6_RS;
810 UIP_ICMP_BUF->icode = 0;
811
812 if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
813 UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_RS_LEN;
814 uip_len = uip_l3_icmp_hdr_len + UIP_ND6_RS_LEN;
815 } else {
816 uip_len = uip_l3_icmp_hdr_len + UIP_ND6_RS_LEN + UIP_ND6_OPT_LLAO_LEN;
817 uipbuf_set_len_field(UIP_IP_BUF, UIP_ICMPH_LEN + UIP_ND6_RS_LEN + UIP_ND6_OPT_LLAO_LEN);
818
819 create_llao(&uip_buf[uip_l3_icmp_hdr_len + UIP_ND6_RS_LEN],
820 UIP_ND6_OPT_SLLAO);
821 }
822
823 UIP_ICMP_BUF->icmpchksum = 0;
824 UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
825
826 UIP_STAT(++uip_stat.nd6.sent);
827 LOG_INFO("Sending RS to ");
828 LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
829 LOG_INFO_(" from ");
830 LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr);
831 LOG_INFO_("\n");
832 return;
833}
834/*---------------------------------------------------------------------------*/
835/**
836 * Process a Router Advertisement
837 *
838 * - Possible actions when receiving a RA: add router to router list,
839 * recalculate reachable time, update link hop limit, update retrans timer.
840 * - If MTU option: update MTU.
841 * - If SLLAO option: update entry in neighbor cache
842 * - If prefix option: start autoconf, add prefix to prefix list
843 */
844void
846{
847 uip_lladdr_t lladdr_aligned;
848
849 LOG_INFO("Received RA from ");
850 LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr);
851 LOG_INFO_(" to ");
852 LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
853 LOG_INFO_("\n");
854 UIP_STAT(++uip_stat.nd6.recv);
855
856 if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) ||
857 (!uip_is_addr_linklocal(&UIP_IP_BUF->srcipaddr)) ||
858 (UIP_ICMP_BUF->icode != 0)) {
859 LOG_ERR("Discarding invalid RA");
860 goto discard;
861 }
862
863 if(UIP_ND6_RA_BUF->cur_ttl != 0) {
864 uip_ds6_if.cur_hop_limit = UIP_ND6_RA_BUF->cur_ttl;
865 LOG_INFO("uip_ds6_if.cur_hop_limit %u\n", uip_ds6_if.cur_hop_limit);
866 }
867
868 if(UIP_ND6_RA_BUF->reachable_time != 0) {
869 if(uip_ds6_if.base_reachable_time !=
870 uip_ntohl(UIP_ND6_RA_BUF->reachable_time)) {
871 uip_ds6_if.base_reachable_time = uip_ntohl(UIP_ND6_RA_BUF->reachable_time);
873 }
874 }
875 if(UIP_ND6_RA_BUF->retrans_timer != 0) {
876 uip_ds6_if.retrans_timer = uip_ntohl(UIP_ND6_RA_BUF->retrans_timer);
877 }
878
879 /* Options processing */
880 nd6_opt_offset = UIP_ND6_RA_LEN;
881 while(uip_l3_icmp_hdr_len + nd6_opt_offset + UIP_ND6_OPT_HDR_LEN < uip_len) {
882 if(ND6_OPT_HDR_BUF(nd6_opt_offset)->len == 0) {
883 LOG_ERR("Discarding invalid RA");
884 goto discard;
885 }
886 switch(ND6_OPT_HDR_BUF(nd6_opt_offset)->type) {
887 case UIP_ND6_OPT_SLLAO:
888 LOG_DBG("Processing SLLAO option in RA\n");
889
890 /* Validate that the full SLLAO option fits within packet bounds */
891 if(uip_l3_icmp_hdr_len + nd6_opt_offset + UIP_ND6_OPT_LLAO_LEN > uip_len) {
892 LOG_ERR("SLLAO option extends beyond packet boundary\n");
893 goto discard;
894 }
895
896 nd6_opt_llao = (uint8_t *)ND6_OPT_HDR_BUF(nd6_opt_offset);
897 nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr);
898 if(!extract_lladdr_from_llao_aligned(&lladdr_aligned)) {
899 /* failed to extract llao - discard packet */
900 goto discard;
901 }
902 if(nbr == NULL) {
903 nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned,
904 1, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL);
905 } else {
906 const uip_lladdr_t *lladdr = uip_ds6_nbr_get_ll(nbr);
907 if(lladdr == NULL) {
908 goto discard;
909 }
910 if(nbr->state == NBR_INCOMPLETE) {
911 nbr->state = NBR_STALE;
912 }
913 if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
914 lladdr, UIP_LLADDR_LEN) != 0) {
915 /* change of link layer address */
917 (const uip_lladdr_t *)&lladdr_aligned) < 0) {
918 /* failed to update the lladdr */
919 goto discard;
920 }
921 nbr->state = NBR_STALE;
922 }
923 nbr->isrouter = 1;
924 }
925 break;
926 case UIP_ND6_OPT_MTU:
927 LOG_DBG("Processing MTU option in RA\n");
928
929 /* Validate that the full MTU option (8 bytes) fits within packet bounds */
930 if(uip_l3_icmp_hdr_len + nd6_opt_offset + UIP_ND6_OPT_MTU_LEN > uip_len) {
931 LOG_ERR("MTU option extends beyond packet boundary\n");
932 goto discard;
933 }
934
935 uip_ds6_if.link_mtu =
936 uip_ntohl(((uip_nd6_opt_mtu *)ND6_OPT_HDR_BUF(nd6_opt_offset))->mtu);
937 break;
938 case UIP_ND6_OPT_PREFIX_INFO:
939 LOG_DBG("Processing PREFIX option in RA\n");
940
941 /* Validate that the full PREFIX_INFO option (32 bytes) fits within packet bounds */
942 if(uip_l3_icmp_hdr_len + nd6_opt_offset + UIP_ND6_OPT_PREFIX_INFO_LEN > uip_len) {
943 LOG_ERR("PREFIX_INFO option extends beyond packet boundary\n");
944 goto discard;
945 }
946
947 /* Also validate the option len field matches expected PREFIX_INFO length */
948 if(ND6_OPT_HDR_BUF(nd6_opt_offset)->len != UIP_ND6_OPT_PREFIX_INFO_LEN / 8) {
949 LOG_ERR("PREFIX_INFO option has invalid length field (len=%u, expected=%u)\n",
950 ND6_OPT_HDR_BUF(nd6_opt_offset)->len, UIP_ND6_OPT_PREFIX_INFO_LEN / 8);
951 goto discard;
952 }
953
954 nd6_opt_prefix_info = (uip_nd6_opt_prefix_info *)ND6_OPT_HDR_BUF(nd6_opt_offset);
955 if((uip_ntohl(nd6_opt_prefix_info->validlt) >=
956 uip_ntohl(nd6_opt_prefix_info->preferredlt))
958 /* on-link flag related processing */
959 if(nd6_opt_prefix_info->flagsreserved1 & UIP_ND6_RA_FLAG_ONLINK) {
960 prefix =
961 uip_ds6_prefix_lookup(&nd6_opt_prefix_info->prefix,
962 nd6_opt_prefix_info->preflen);
963 if(prefix == NULL) {
964 if(nd6_opt_prefix_info->validlt != 0) {
966 prefix = uip_ds6_prefix_add(&nd6_opt_prefix_info->prefix,
967 nd6_opt_prefix_info->preflen,
968 uip_ntohl(nd6_opt_prefix_info->
969 validlt));
970 } else {
971 prefix = uip_ds6_prefix_add(&nd6_opt_prefix_info->prefix,
972 nd6_opt_prefix_info->preflen, 0);
973 }
974 }
975 } else {
976 switch(nd6_opt_prefix_info->validlt) {
977 case 0:
978 uip_ds6_prefix_rm(prefix);
979 break;
981 prefix->isinfinite = 1;
982 break;
983 default:
984 LOG_DBG("Updating timer of prefix ");
985 LOG_DBG_6ADDR(&prefix->ipaddr);
986 LOG_DBG_(" new value %" PRIu32 "\n", uip_ntohl(nd6_opt_prefix_info->validlt));
987 stimer_set(&prefix->vlifetime,
988 uip_ntohl(nd6_opt_prefix_info->validlt));
989 prefix->isinfinite = 0;
990 break;
991 }
992 }
993 }
994 /* End of on-link flag related processing */
995 /* autonomous flag related processing */
996 if((nd6_opt_prefix_info->flagsreserved1 & UIP_ND6_RA_FLAG_AUTONOMOUS)
997 && (nd6_opt_prefix_info->validlt != 0)
998 && (nd6_opt_prefix_info->preflen == UIP_DEFAULT_PREFIX_LEN)) {
999
1002 addr = uip_ds6_addr_lookup(&ipaddr);
1003 if((addr != NULL) && (addr->type == ADDR_AUTOCONF)) {
1005 /* The processing below is defined in RFC4862 section 5.5.3 e */
1006 if((uip_ntohl(nd6_opt_prefix_info->validlt) > 2 * 60 * 60) ||
1007 (uip_ntohl(nd6_opt_prefix_info->validlt) >
1008 stimer_remaining(&addr->vlifetime))) {
1009 LOG_DBG("Updating timer of address ");
1010 LOG_DBG_6ADDR(&addr->ipaddr);
1011 LOG_DBG_(" new value %lu\n",
1012 (unsigned long)uip_ntohl(nd6_opt_prefix_info->validlt));
1013 stimer_set(&addr->vlifetime,
1014 uip_ntohl(nd6_opt_prefix_info->validlt));
1015 } else {
1016 stimer_set(&addr->vlifetime, 2 * 60 * 60);
1017 LOG_DBG("Updating timer of address ");
1018 LOG_DBG_6ADDR(&addr->ipaddr);
1019 LOG_DBG_(" new value %lu\n", (unsigned long)(2 * 60 * 60));
1020 }
1021 addr->isinfinite = 0;
1022 } else {
1023 addr->isinfinite = 1;
1024 }
1025 } else {
1026 if(uip_ntohl(nd6_opt_prefix_info->validlt) ==
1028 uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF);
1029 } else {
1030 uip_ds6_addr_add(&ipaddr, uip_ntohl(nd6_opt_prefix_info->validlt),
1031 ADDR_AUTOCONF);
1032 }
1033 }
1034 }
1035 /* End of autonomous flag related processing */
1036 }
1037 break;
1038#if UIP_ND6_RA_RDNSS
1039 case UIP_ND6_OPT_RDNSS:
1040 LOG_DBG("Processing RDNSS option\n");
1041
1042 /*
1043 * Validate that the option length is sufficient for at least
1044 * one address.
1045 *
1046 * Minimum: type(1) + len(1) + reserved(2) + lifetime(4) + address(16) =
1047 * 24 bytes
1048 */
1049 if(ND6_OPT_RDNSS_BUF(nd6_opt_offset)->len < 3) {
1050 LOG_ERR("RDNSS option too short (len=%u)\n",
1051 ND6_OPT_RDNSS_BUF(nd6_opt_offset)->len);
1052 goto discard;
1053 }
1054
1055 /* Ensure that the full option fits within packet bounds. */
1056 uint16_t opt_full_len = ND6_OPT_RDNSS_BUF(nd6_opt_offset)->len << 3;
1057 if(uip_l3_icmp_hdr_len + nd6_opt_offset + opt_full_len > uip_len) {
1058 LOG_ERR("RDNSS option extends beyond packet boundary\n");
1059 goto discard;
1060 }
1061
1062 /* Calculate number of addresses based on validated length */
1063 uint8_t naddr = (ND6_OPT_RDNSS_BUF(nd6_opt_offset)->len - 1) / 2;
1064 uip_ipaddr_t *ip = (uip_ipaddr_t *)(&ND6_OPT_RDNSS_BUF(nd6_opt_offset)->ip);
1065 LOG_DBG("got %d nameservers\n", naddr);
1066 while(naddr-- > 0) {
1067 LOG_DBG("nameserver: ");
1068 LOG_DBG_6ADDR(ip);
1069 LOG_DBG_(" lifetime: %" PRIx32 "\n", uip_ntohl(ND6_OPT_RDNSS_BUF(nd6_opt_offset)->lifetime));
1070 uip_nameserver_update(ip, uip_ntohl(ND6_OPT_RDNSS_BUF(nd6_opt_offset)->lifetime));
1071 ip++;
1072 }
1073 break;
1074#endif /* UIP_ND6_RA_RDNSS */
1075 default:
1076 LOG_ERR("ND option not supported in RA\n");
1077 break;
1078 }
1079 nd6_opt_offset += (ND6_OPT_HDR_BUF(nd6_opt_offset)->len << 3);
1080 }
1081
1082 defrt = uip_ds6_defrt_lookup(&UIP_IP_BUF->srcipaddr);
1083 if(UIP_ND6_RA_BUF->router_lifetime != 0) {
1084 if(nbr != NULL) {
1085 nbr->isrouter = 1;
1086 }
1087 if(defrt == NULL) {
1088 uip_ds6_defrt_add(&UIP_IP_BUF->srcipaddr,
1089 (unsigned
1090 long)(uip_ntohs(UIP_ND6_RA_BUF->router_lifetime)));
1091 } else {
1092 stimer_set(&(defrt->lifetime),
1093 (unsigned long)(uip_ntohs(UIP_ND6_RA_BUF->router_lifetime)));
1094 }
1095 } else {
1096 if(defrt != NULL) {
1097 uip_ds6_defrt_rm(defrt);
1098 }
1099 }
1100
1101#if UIP_CONF_IPV6_QUEUE_PKT
1102 /* If the nbr just became reachable (e.g. it was in NBR_INCOMPLETE state
1103 * and we got a SLLAO), check if we had buffered a pkt for it */
1104 /* if((nbr != NULL) && (nbr->queue_buf_len != 0)) {
1105 uip_len = nbr->queue_buf_len;
1106 memcpy(UIP_IP_BUF, nbr->queue_buf, uip_len);
1107 nbr->queue_buf_len = 0;
1108 return;
1109 }*/
1110 if(nbr != NULL && uip_packetqueue_buflen(&nbr->packethandle) != 0) {
1111 uip_len = uip_packetqueue_buflen(&nbr->packethandle);
1112 memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len);
1113 uip_packetqueue_free(&nbr->packethandle);
1114 return;
1115 }
1116
1117#endif /*UIP_CONF_IPV6_QUEUE_PKT */
1118
1119discard:
1120 uipbuf_clear();
1121 return;
1122}
1123#endif /* !UIP_CONF_ROUTER */
1124/*------------------------------------------------------------------*/
1125/* ICMPv6 input handlers */
1126#if UIP_ND6_SEND_NA
1127UIP_ICMP6_HANDLER(ns_input_handler, ICMP6_NS, UIP_ICMP6_HANDLER_CODE_ANY,
1128 ns_input);
1129#endif
1130#if UIP_ND6_SEND_NS
1131UIP_ICMP6_HANDLER(na_input_handler, ICMP6_NA, UIP_ICMP6_HANDLER_CODE_ANY,
1132 na_input);
1133#endif
1134
1135#if UIP_CONF_ROUTER && UIP_ND6_SEND_RA
1136UIP_ICMP6_HANDLER(rs_input_handler, ICMP6_RS, UIP_ICMP6_HANDLER_CODE_ANY,
1137 rs_input);
1138#endif
1139
1140#if !UIP_CONF_ROUTER
1141UIP_ICMP6_HANDLER(ra_input_handler, ICMP6_RA, UIP_ICMP6_HANDLER_CODE_ANY,
1142 ra_input);
1143#endif
1144/*---------------------------------------------------------------------------*/
1145void
1147{
1148#if UIP_ND6_SEND_NA
1149 /* Only handle NSs if we are prepared to send out NAs */
1150 uip_icmp6_register_input_handler(&ns_input_handler);
1151#endif
1152
1153#if UIP_ND6_SEND_NS
1154 /*
1155 * Only handle NAs if we are prepared to send out NSs. */
1156 uip_icmp6_register_input_handler(&na_input_handler);
1157#endif
1158
1159#if UIP_CONF_ROUTER && UIP_ND6_SEND_RA
1160 /* Only accept RS if we are a router and happy to send out RAs */
1161 uip_icmp6_register_input_handler(&rs_input_handler);
1162#endif
1163
1164#if !UIP_CONF_ROUTER
1165 /* Only process RAs if we are not a router */
1166 uip_icmp6_register_input_handler(&ra_input_handler);
1167#endif
1168}
1169/*---------------------------------------------------------------------------*/
1170/** @} */
static volatile at86rf215_flags_t flags
The radio driver uses the following flags to keep track of the current state of the radio and IRQ eve...
Definition at86rf215.c:144
unsigned long clock_seconds(void)
Get the current value of the platform seconds.
Definition clock.c:130
static void stimer_set(struct stimer *t, unsigned long interval)
Set a timer.
Definition stimer.h:100
static unsigned long stimer_remaining(struct stimer *t)
The time until the timer expires.
Definition stimer.h:121
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:1777
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.
#define uip_create_unspecified(a)
set IP address a to unspecified
Definition uip.h:1771
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...
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.
#define uip_is_addr_unspecified(a)
Is IPv6 address a the unspecified address a is of type uip_ipaddr_t.
Definition uip.h:1725
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.
uip_ds6_nbr_t * uip_ds6_nbr_lookup(const uip_ipaddr_t *ipaddr)
Get the neighbor cache associated with a specified IPv6 address.
void uip_nd6_rs_output(void)
Neighbor Solicitation Processing.
Definition uip-nd6.c:800
#define uip_is_addr_mcast(a)
is address a multicast address, see RFC 4291 a is of type uip_ipaddr_t*
Definition uip.h:1860
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:351
#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:1146
#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:657
#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:1804
#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:1766
#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:1789
void uip_ds6_select_src(uip_ipaddr_t *src, uip_ipaddr_t *dst)
Source address selection, see RFC 3484.
Definition uip-ds6.c:529
#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:567
uip_ds6_prefix_t uip_ds6_prefix_list[UIP_DS6_PREFIX_NB]
Prefix list.
Definition uip-ds6.c:75
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:74
#define uip_create_linklocal_allnodes_mcast(a)
set IP address a to the link local all-nodes multicast address
Definition uip.h:1774
uint32_t uip_ds6_compute_reachable_time(void)
Compute the reachable time based on base reachable time, see RFC 4861.
Definition uip-ds6.c:744
#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:2345
#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.
Header file for generating non-cryptographic random numbers.
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...
A prefix list entry.
Definition uip-ds6.h:195
A neighbor solicitation constant part.
Definition uip-nd6.h:268
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:845
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)