iPXE
ndp.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2013 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 */
19
20FILE_LICENCE ( GPL2_OR_LATER );
21FILE_SECBOOT ( PERMITTED );
22
23#include <stdlib.h>
24#include <stdio.h>
25#include <string.h>
26#include <errno.h>
27#include <byteswap.h>
28#include <ipxe/in.h>
29#include <ipxe/iobuf.h>
30#include <ipxe/tcpip.h>
31#include <ipxe/ipv6.h>
32#include <ipxe/icmpv6.h>
33#include <ipxe/neighbour.h>
34#include <ipxe/dhcpv6.h>
35#include <ipxe/timer.h>
36#include <ipxe/ndp.h>
37
38/** @file
39 *
40 * IPv6 neighbour discovery protocol
41 *
42 */
43
44/** Router discovery minimum timeout */
45#define IPV6CONF_MIN_TIMEOUT ( TICKS_PER_SEC / 8 )
46
47/** Router discovery maximum timeout */
48#define IPV6CONF_MAX_TIMEOUT ( TICKS_PER_SEC * 3 )
49
50/** Router discovery blocked link retry timeout */
51#define IPV6CONF_BLOCK_TIMEOUT ( TICKS_PER_SEC )
52
53/** Router discovery maximum number of deferrals */
54#define IPV6CONF_MAX_DEFERRALS 180
55
56static struct ipv6conf * ipv6conf_demux ( struct net_device *netdev );
57static int
59 struct in6_addr *router,
61 size_t len );
62
63/**
64 * Transmit NDP packet with link-layer address option
65 *
66 * @v netdev Network device
67 * @v sin6_src Source socket address
68 * @v sin6_dest Destination socket address
69 * @v data NDP header
70 * @v len Size of NDP header
71 * @v option_type NDP option type
72 * @ret rc Return status code
73 */
74static int ndp_tx_ll_addr ( struct net_device *netdev,
75 struct sockaddr_in6 *sin6_src,
76 struct sockaddr_in6 *sin6_dest,
77 const void *data, size_t len,
78 unsigned int option_type ) {
79 struct sockaddr_tcpip *st_src =
80 ( ( struct sockaddr_tcpip * ) sin6_src );
81 struct sockaddr_tcpip *st_dest =
82 ( ( struct sockaddr_tcpip * ) sin6_dest );
83 struct ll_protocol *ll_protocol = netdev->ll_protocol;
84 struct io_buffer *iobuf;
85 struct ndp_ll_addr_option *ll_addr_opt;
86 union ndp_header *ndp;
87 size_t option_len;
88 int rc;
89
90 /* Allocate and populate buffer */
91 option_len = ( ( sizeof ( *ll_addr_opt ) +
93 ~( NDP_OPTION_BLKSZ - 1 ) );
94 iobuf = alloc_iob ( MAX_LL_NET_HEADER_LEN + len + option_len );
95 if ( ! iobuf )
96 return -ENOMEM;
98 memcpy ( iob_put ( iobuf, len ), data, len );
99 ll_addr_opt = iob_put ( iobuf, option_len );
100 ll_addr_opt->header.type = option_type;
101 ll_addr_opt->header.blocks = ( option_len / NDP_OPTION_BLKSZ );
102 memcpy ( ll_addr_opt->ll_addr, netdev->ll_addr,
104 ndp = iobuf->data;
105 ndp->icmp.chksum = tcpip_chksum ( ndp, ( len + option_len ) );
106
107 /* Transmit packet */
108 if ( ( rc = tcpip_tx ( iobuf, &icmpv6_protocol, st_src, st_dest,
109 netdev, &ndp->icmp.chksum ) ) != 0 ) {
110 DBGC ( netdev, "NDP %s could not transmit packet: %s\n",
111 netdev->name, strerror ( rc ) );
112 return rc;
113 }
114
115 return 0;
116}
117
118/**
119 * Transmit NDP neighbour discovery request
120 *
121 * @v netdev Network device
122 * @v net_protocol Network-layer protocol
123 * @v net_dest Destination network-layer address
124 * @v net_source Source network-layer address
125 * @ret rc Return status code
126 */
127static int ndp_tx_request ( struct net_device *netdev,
129 const void *net_dest, const void *net_source ) {
130 struct sockaddr_in6 sin6_src;
131 struct sockaddr_in6 sin6_dest;
132 struct ndp_neighbour_header neigh;
133 int rc;
134
135 /* Construct source address */
136 memset ( &sin6_src, 0, sizeof ( sin6_src ) );
137 sin6_src.sin6_family = AF_INET6;
138 memcpy ( &sin6_src.sin6_addr, net_source,
139 sizeof ( sin6_src.sin6_addr ) );
140
141 /* Construct multicast destination address */
142 memset ( &sin6_dest, 0, sizeof ( sin6_dest ) );
143 sin6_dest.sin6_family = AF_INET6;
144 sin6_dest.sin6_scope_id = netdev->scope_id;
145 ipv6_solicited_node ( &sin6_dest.sin6_addr, net_dest );
146
147 /* Construct neighbour header */
148 memset ( &neigh, 0, sizeof ( neigh ) );
150 memcpy ( &neigh.target, net_dest, sizeof ( neigh.target ) );
151
152 /* Transmit neighbour discovery packet */
153 if ( ( rc = ndp_tx_ll_addr ( netdev, &sin6_src, &sin6_dest, &neigh,
154 sizeof ( neigh ),
155 NDP_OPT_LL_SOURCE ) ) != 0 )
156 return rc;
157
158 return 0;
159}
160
161/** NDP neighbour discovery protocol */
163 .name = "NDP",
164 .tx_request = ndp_tx_request,
165};
166
167/**
168 * Transmit NDP router solicitation
169 *
170 * @v netdev Network device
171 * @ret rc Return status code
172 */
175 struct sockaddr_in6 sin6_dest;
176 int rc;
177
178 /* Construct multicast destination address */
179 memset ( &sin6_dest, 0, sizeof ( sin6_dest ) );
180 sin6_dest.sin6_family = AF_INET6;
181 sin6_dest.sin6_scope_id = netdev->scope_id;
182 ipv6_all_routers ( &sin6_dest.sin6_addr );
183
184 /* Construct router solicitation */
185 memset ( &rsol, 0, sizeof ( rsol ) );
187
188 /* Transmit packet */
189 if ( ( rc = ndp_tx_ll_addr ( netdev, NULL, &sin6_dest, &rsol,
190 sizeof ( rsol ), NDP_OPT_LL_SOURCE ) ) !=0)
191 return rc;
192
193 return 0;
194}
195
196/**
197 * Process NDP neighbour solicitation source link-layer address option
198 *
199 * @v netdev Network device
200 * @v sin6_src Source socket address
201 * @v ndp NDP packet
202 * @v option NDP option
203 * @v len NDP option length
204 * @ret rc Return status code
205 */
206static int
208 struct sockaddr_in6 *sin6_src,
209 union ndp_header *ndp,
210 union ndp_option *option,
211 size_t len ) {
212 struct ndp_neighbour_header *neigh = &ndp->neigh;
213 struct ndp_ll_addr_option *ll_addr_opt = &option->ll_addr;
214 struct ll_protocol *ll_protocol = netdev->ll_protocol;
215 int rc;
216
217 /* Silently ignore neighbour solicitations for addresses we do
218 * not own.
219 */
220 if ( ! ipv6_has_addr ( netdev, &neigh->target ) )
221 return 0;
222
223 /* Sanity check */
224 if ( offsetof ( typeof ( *ll_addr_opt ),
225 ll_addr[ll_protocol->ll_addr_len] ) > len ) {
226 DBGC ( netdev, "NDP %s neighbour solicitation link-layer "
227 "address option too short at %zd bytes\n",
228 netdev->name, len );
229 return -EINVAL;
230 }
231
232 /* Create or update neighbour cache entry */
233 if ( ( rc = neighbour_define ( netdev, &ipv6_protocol,
234 &sin6_src->sin6_addr,
235 ll_addr_opt->ll_addr ) ) != 0 ) {
236 DBGC ( netdev, "NDP %s could not define %s => %s: %s\n",
237 netdev->name, inet6_ntoa ( &sin6_src->sin6_addr ),
238 ll_protocol->ntoa ( ll_addr_opt->ll_addr ),
239 strerror ( rc ) );
240 return rc;
241 }
242
243 /* Convert neighbour header to advertisement */
244 memset ( neigh, 0, offsetof ( typeof ( *neigh ), target ) );
247
248 /* Send neighbour advertisement */
249 if ( ( rc = ndp_tx_ll_addr ( netdev, NULL, sin6_src, neigh,
250 sizeof ( *neigh ),
251 NDP_OPT_LL_TARGET ) ) != 0 )
252 return rc;
253
254 return 0;
255}
256
257/**
258 * Process NDP neighbour advertisement target link-layer address option
259 *
260 * @v netdev Network device
261 * @v sin6_src Source socket address
262 * @v ndp NDP packet
263 * @v option NDP option
264 * @v len NDP option length
265 * @ret rc Return status code
266 */
267static int
269 struct sockaddr_in6 *sin6_src
270 __unused,
271 union ndp_header *ndp,
272 union ndp_option *option,
273 size_t len ) {
274 struct ndp_neighbour_header *neigh = &ndp->neigh;
275 struct ndp_ll_addr_option *ll_addr_opt = &option->ll_addr;
276 struct ll_protocol *ll_protocol = netdev->ll_protocol;
277 int rc;
278
279 /* Sanity check */
280 if ( offsetof ( typeof ( *ll_addr_opt ),
281 ll_addr[ll_protocol->ll_addr_len] ) > len ) {
282 DBGC ( netdev, "NDP %s neighbour advertisement link-layer "
283 "address option too short at %zd bytes\n",
284 netdev->name, len );
285 return -EINVAL;
286 }
287
288 /* Update neighbour cache entry, if any */
289 if ( ( rc = neighbour_update ( netdev, &ipv6_protocol, &neigh->target,
290 ll_addr_opt->ll_addr ) ) != 0 ) {
291 DBGC ( netdev, "NDP %s could not update %s => %s: %s\n",
292 netdev->name, inet6_ntoa ( &neigh->target ),
293 ll_protocol->ntoa ( ll_addr_opt->ll_addr ),
294 strerror ( rc ) );
295 return rc;
296 }
297
298 return 0;
299}
300
301/**
302 * Process NDP router advertisement source link-layer address option
303 *
304 * @v netdev Network device
305 * @v sin6_src Source socket address
306 * @v ndp NDP packet
307 * @v option NDP option
308 * @v len NDP option length
309 * @ret rc Return status code
310 */
311static int
313 struct sockaddr_in6 *sin6_src,
314 union ndp_header *ndp __unused,
315 union ndp_option *option, size_t len ) {
316 struct ndp_ll_addr_option *ll_addr_opt = &option->ll_addr;
317 struct ll_protocol *ll_protocol = netdev->ll_protocol;
318 int rc;
319
320 /* Sanity check */
321 if ( offsetof ( typeof ( *ll_addr_opt ),
322 ll_addr[ll_protocol->ll_addr_len] ) > len ) {
323 DBGC ( netdev, "NDP %s router advertisement link-layer address "
324 "option too short at %zd bytes\n", netdev->name, len );
325 return -EINVAL;
326 }
327
328 /* Define neighbour cache entry */
329 if ( ( rc = neighbour_define ( netdev, &ipv6_protocol,
330 &sin6_src->sin6_addr,
331 ll_addr_opt->ll_addr ) ) != 0 ) {
332 DBGC ( netdev, "NDP %s could not define %s => %s: %s\n",
333 netdev->name, inet6_ntoa ( &sin6_src->sin6_addr ),
334 ll_protocol->ntoa ( ll_addr_opt->ll_addr ),
335 strerror ( rc ) );
336 return rc;
337 }
338
339 return 0;
340}
341
342/**
343 * Process NDP router advertisement prefix information option
344 *
345 * @v netdev Network device
346 * @v sin6_src Source socket address
347 * @v ndp NDP packet
348 * @v option NDP option
349 * @v len NDP option length
350 * @ret rc Return status code
351 */
352static int
354 struct sockaddr_in6 *sin6_src,
355 union ndp_header *ndp,
356 union ndp_option *option, size_t len ) {
357 struct ndp_router_advertisement_header *radv = &ndp->radv;
358 struct ndp_prefix_information_option *prefix_opt = &option->prefix;
359
360 /* Sanity check */
361 if ( sizeof ( *prefix_opt ) > len ) {
362 DBGC ( netdev, "NDP %s router advertisement prefix option too "
363 "short at %zd bytes\n", netdev->name, len );
364 return -EINVAL;
365 }
366
367 DBGC ( netdev, "NDP %s found %sdefault router %s ",
368 netdev->name, ( radv->lifetime ? "" : "non-" ),
369 inet6_ntoa ( &sin6_src->sin6_addr ) );
370 DBGC ( netdev, "for %s-link %sautonomous prefix %s/%d\n",
371 ( ( prefix_opt->flags & NDP_PREFIX_ON_LINK ) ? "on" : "off" ),
372 ( ( prefix_opt->flags & NDP_PREFIX_AUTONOMOUS ) ? "" : "non-" ),
373 inet6_ntoa ( &prefix_opt->prefix ), prefix_opt->prefix_len );
374
375 return 0;
376}
377
378/** An NDP option handler */
380 /** ICMPv6 type */
382 /** Option type */
384 /**
385 * Handle received option
386 *
387 * @v netdev Network device
388 * @v sin6_src Source socket address
389 * @v ndp NDP packet
390 * @v option NDP option
391 * @ret rc Return status code
392 */
393 int ( * rx ) ( struct net_device *netdev, struct sockaddr_in6 *sin6_src,
394 union ndp_header *ndp, union ndp_option *option,
395 size_t len );
396};
397
398/** NDP option handlers */
400 {
402 .option_type = NDP_OPT_LL_SOURCE,
404 },
405 {
407 .option_type = NDP_OPT_LL_TARGET,
409 },
410 {
411 .icmp_type = ICMPV6_ROUTER_ADVERTISEMENT,
412 .option_type = NDP_OPT_LL_SOURCE,
414 },
415 {
416 .icmp_type = ICMPV6_ROUTER_ADVERTISEMENT,
417 .option_type = NDP_OPT_PREFIX,
419 },
420};
421
422/**
423 * Process received NDP option
424 *
425 * @v netdev Network device
426 * @v sin6_src Source socket address
427 * @v ndp NDP packet
428 * @v option NDP option
429 * @v len Option length
430 * @ret rc Return status code
431 */
432static int ndp_rx_option ( struct net_device *netdev,
433 struct sockaddr_in6 *sin6_src, union ndp_header *ndp,
434 union ndp_option *option, size_t len ) {
435 struct ndp_option_handler *handler;
436 unsigned int i;
437
438 /* Locate a suitable option handler, if any */
439 for ( i = 0 ; i < ( sizeof ( ndp_option_handlers ) /
440 sizeof ( ndp_option_handlers[0] ) ) ; i++ ) {
441 handler = &ndp_option_handlers[i];
442 if ( ( handler->icmp_type == ndp->icmp.type ) &&
443 ( handler->option_type == option->header.type ) ) {
444 return handler->rx ( netdev, sin6_src, ndp,
445 option, len );
446 }
447 }
448
449 /* Silently ignore unknown options as per RFC 4861 */
450 return 0;
451}
452
453/**
454 * Process received NDP packet options
455 *
456 * @v netdev Network device
457 * @v sin6_src Source socket address
458 * @v ndp NDP header
459 * @v offset Offset to NDP options
460 * @v len Length of NDP packet
461 * @ret rc Return status code
462 */
463static int ndp_rx_options ( struct net_device *netdev,
464 struct sockaddr_in6 *sin6_src,
465 union ndp_header *ndp, size_t offset, size_t len ) {
466 union ndp_option *option;
467 size_t remaining;
468 size_t option_len;
469 int rc;
470
471 /* Sanity check */
472 if ( len < offset ) {
473 DBGC ( netdev, "NDP %s packet too short at %zd bytes (min %zd "
474 "bytes)\n", netdev->name, len, offset );
475 return -EINVAL;
476 }
477
478 /* Search for option */
479 option = ( ( ( void * ) ndp ) + offset );
480 remaining = ( len - offset );
481 while ( remaining ) {
482
483 /* Sanity check */
484 if ( ( remaining < sizeof ( option->header ) ) ||
485 ( option->header.blocks == 0 ) ||
486 ( remaining < ( option->header.blocks *
487 NDP_OPTION_BLKSZ ) ) ) {
488 DBGC ( netdev, "NDP %s bad option length:\n",
489 netdev->name );
490 DBGC_HDA ( netdev, 0, option, remaining );
491 return -EINVAL;
492 }
493 option_len = ( option->header.blocks * NDP_OPTION_BLKSZ );
494
495 /* Handle option */
496 if ( ( rc = ndp_rx_option ( netdev, sin6_src, ndp, option,
497 option_len ) ) != 0 )
498 return rc;
499
500 /* Move to next option */
501 option = ( ( ( void * ) option ) + option_len );
502 remaining -= option_len;
503 }
504
505 return 0;
506}
507
508/**
509 * Process received NDP neighbour solicitation or advertisement
510 *
511 * @v iobuf I/O buffer
512 * @v netdev Network device
513 * @v sin6_src Source socket address
514 * @v sin6_dest Destination socket address
515 * @ret rc Return status code
516 */
517static int ndp_rx_neighbour ( struct io_buffer *iobuf,
518 struct net_device *netdev,
519 struct sockaddr_in6 *sin6_src,
520 struct sockaddr_in6 *sin6_dest __unused ) {
521 union ndp_header *ndp = iobuf->data;
522 struct ndp_neighbour_header *neigh = &ndp->neigh;
523 size_t len = iob_len ( iobuf );
524 int rc;
525
526 /* Process options */
527 if ( ( rc = ndp_rx_options ( netdev, sin6_src, ndp,
528 offsetof ( typeof ( *neigh ), option ),
529 len ) ) != 0 )
530 goto err_options;
531
532 err_options:
533 free_iob ( iobuf );
534 return rc;
535}
536
537/**
538 * Process received NDP router advertisement
539 *
540 * @v iobuf I/O buffer
541 * @v netdev Network device
542 * @v sin6_src Source socket address
543 * @v sin6_dest Destination socket address
544 * @ret rc Return status code
545 */
546static int
548 struct net_device *netdev,
549 struct sockaddr_in6 *sin6_src,
550 struct sockaddr_in6 *sin6_dest __unused ) {
551 union ndp_header *ndp = iobuf->data;
552 struct ndp_router_advertisement_header *radv = &ndp->radv;
553 struct in6_addr *router = &sin6_src->sin6_addr;
554 size_t len = iob_len ( iobuf );
555 int rc;
556
557 /* Process options */
558 if ( ( rc = ndp_rx_options ( netdev, sin6_src, ndp,
559 offsetof ( typeof ( *radv ), option ),
560 len ) ) != 0 )
561 goto err_options;
562
563 /* Pass to IPv6 autoconfiguration */
564 if ( ( rc = ipv6conf_rx_router_advertisement ( netdev, router,
565 radv, len ) ) != 0 )
566 goto err_ipv6conf;
567
568 err_ipv6conf:
569 err_options:
570 free_iob ( iobuf );
571 return rc;
572}
573
574/** NDP ICMPv6 handlers */
575struct icmpv6_handler ndp_handlers[] __icmpv6_handler = {
576 {
578 .rx = ndp_rx_neighbour,
579 },
580 {
582 .rx = ndp_rx_neighbour,
583 },
584 {
587 },
588};
589
590/****************************************************************************
591 *
592 * NDP settings
593 *
594 */
595
596/** An NDP prefix settings block */
598 /** Settings interface */
600 /** Name */
601 char name[4];
602 /** Prefix information option */
604};
605
606/** An NDP settings block */
608 /** Reference counter */
610 /** Settings interface */
612 /** Router address */
614 /** Router lifetime */
615 unsigned int lifetime;
616 /** Length of NDP options */
617 size_t len;
618 /** NDP options */
620};
621
622/** NDP settings scope */
624
625/**
626 * Construct NDP tag
627 *
628 * @v type NDP option type
629 * @v offset Starting offset of data
630 * @v len Length of data (or 0 to use all remaining data)
631 * @ret tag NDP tag
632 */
633#define NDP_TAG( type, offset, len ) \
634 ( ( (len) << 16 ) | ( (offset) << 8 ) | (type) )
635
636/**
637 * Extract NDP tag type
638 *
639 * @v tag NDP tag
640 * @ret type NDP option type
641 */
642#define NDP_TAG_TYPE( tag ) ( ( (tag) >> 0 ) & 0xff )
643
644/**
645 * Extract NDP tag offset
646 *
647 * @v tag NDP tag
648 * @ret offset Starting offset of data
649 */
650#define NDP_TAG_OFFSET( tag ) ( ( (tag) >> 8 ) & 0xff )
651
652/**
653 * Extract NDP tag length
654 *
655 * @v tag NDP tag
656 * @ret len Length of data (or 0 to use all remaining data)
657 */
658#define NDP_TAG_LEN( tag ) ( ( (tag) >> 16 ) & 0xff )
659
660/**
661 * Extract NDP tag instance
662 *
663 * @v tag NDP tag
664 * @ret instance Instance
665 */
666#define NDP_TAG_INSTANCE( tag ) ( ( (tag) >> 24 ) & 0xff )
667
668/**
669 * Check applicability of NDP setting
670 *
671 * @v settings Settings block
672 * @v setting Setting to fetch
673 * @ret applies Setting applies within this settings block
674 */
676 const struct setting *setting ) {
677
678 return ( setting->scope == &ndp_settings_scope );
679}
680
681/**
682 * Fetch value of NDP setting
683 *
684 * @v settings Settings block
685 * @v setting Setting to fetch
686 * @v data Buffer to fill with setting data
687 * @v len Length of buffer
688 * @ret len Length of setting data, or negative error
689 */
690static int ndp_fetch ( struct settings *settings,
691 struct setting *setting,
692 void *data, size_t len ) {
693 struct ndp_settings *ndpset =
695 struct net_device *netdev =
697 settings.settings );
698 union ndp_option *option;
699 unsigned int tag_type;
700 unsigned int tag_offset;
701 unsigned int tag_len;
702 unsigned int tag_instance;
703 size_t offset;
704 size_t option_len;
705 void *option_data;
706
707 /* Parse setting tag */
708 tag_type = NDP_TAG_TYPE ( setting->tag );
709 tag_offset = NDP_TAG_OFFSET ( setting->tag );
710 tag_len = NDP_TAG_LEN ( setting->tag );
711 tag_instance = NDP_TAG_INSTANCE ( setting->tag );
712
713 /* Scan through NDP options for requested type. We can assume
714 * that the options are well-formed, otherwise they would have
715 * been rejected prior to being stored.
716 */
717 for ( offset = 0 ; offset < ndpset->len ; offset += option_len ) {
718
719 /* Calculate option length */
720 option = ( ( ( void * ) ndpset->options ) + offset );
721 option_len = ( option->header.blocks * NDP_OPTION_BLKSZ );
722
723 /* Skip options that do not match this tag */
724 if ( option->header.type != tag_type )
725 continue;
726
727 /* Skip previous instances of this option */
728 if ( tag_instance-- != 0 )
729 continue;
730
731 /* Sanity check */
732 if ( ( tag_offset + tag_len ) > option_len ) {
733 DBGC ( netdev, "NDP %s option %d too short\n",
734 netdev->name, tag_type );
735 return -EINVAL;
736 }
737 if ( ! tag_len )
738 tag_len = ( option_len - tag_offset );
739 option_data = ( ( ( void * ) option ) + tag_offset );
740
741 /* Copy data to output buffer */
742 if ( len > tag_len )
743 len = tag_len;
744 memcpy ( data, option_data, len );
745
746 /* Default to hex if no type is specified */
747 if ( ! setting->type )
748 setting->type = &setting_type_hex;
749
750 return tag_len;
751 }
752
753 return -ENOENT;
754}
755
756/** NDP settings operations */
758 .applies = ndp_applies,
759 .fetch = ndp_fetch,
760};
761
762/**
763 * Check applicability of NDP per-prefix setting
764 *
765 * @v settings Settings block
766 * @v setting Setting to fetch
767 * @ret applies Setting applies within this settings block
768 */
770 const struct setting *setting ) {
771
772 return ( setting->scope == &ipv6_settings_scope );
773}
774
775/**
776 * Fetch value of NDP IPv6 address setting
777 *
778 * @v settings Settings block
779 * @v data Buffer to fill with setting data
780 * @v len Length of buffer
781 * @ret len Length of setting data, or negative error
782 */
783static int ndp_prefix_fetch_ip6 ( struct settings *settings, void *data,
784 size_t len ) {
785 struct ndp_prefix_settings *prefset =
787 struct ndp_settings *ndpset =
789 struct net_device *netdev =
790 container_of ( ndpset->settings.parent, struct net_device,
791 settings.settings );
793 struct in6_addr *ip6 = &prefix->prefix;
794 struct in6_addr slaac;
795 int prefix_len;
796 int rc;
797
798 /* Skip dead prefixes */
799 if ( ! prefix->valid )
800 return -ENOENT;
801
802 /* Construct IPv6 address via SLAAC, if applicable */
803 if ( prefix->flags & NDP_PREFIX_AUTONOMOUS ) {
804 memcpy ( &slaac, ip6, sizeof ( slaac ) );
805 prefix_len = ipv6_eui64 ( &slaac, netdev );
806 if ( prefix_len == prefix->prefix_len ) {
807 /* Correctly configured prefix: use SLAAC address */
808 ip6 = &slaac;
809 } else if ( prefix_len < 0 ) {
810 /* Link layer does not support SLAAC */
811 rc = prefix_len;
812 DBGC ( netdev, "NDP %s does not support SLAAC: %s\n",
813 netdev->name, strerror ( rc ) );
814 } else {
815 /* Prefix length incorrect: assume a badly
816 * configured router and ignore SLAAC address.
817 */
818 DBGC ( netdev, "NDP %s ignoring misconfigured SLAAC "
819 "on prefix %s/%d\n", netdev->name,
820 inet6_ntoa ( ip6 ), prefix->prefix_len );
821 }
822 }
823
824 /* Fill in IPv6 address */
825 if ( len > sizeof ( *ip6 ) )
826 len = sizeof ( *ip6 );
827 memcpy ( data, ip6, len );
828
829 return sizeof ( *ip6 );
830}
831
832/**
833 * Fetch value of NDP prefix length setting
834 *
835 * @v settings Settings block
836 * @v data Buffer to fill with setting data
837 * @v len Length of buffer
838 * @ret len Length of setting data, or negative error
839 */
840static int ndp_prefix_fetch_len6 ( struct settings *settings, void *data,
841 size_t len ) {
842 struct ndp_prefix_settings *prefset =
845 uint8_t *len6;
846
847 /* Fill in prefix length */
848 if ( len >= sizeof ( *len6 ) ) {
849 /* We treat an off-link prefix as having a prefix
850 * length covering the entire IPv6 address.
851 */
852 len6 = data;
853 *len6 = ( ( prefix->flags & NDP_PREFIX_ON_LINK ) ?
854 prefix->prefix_len : -1UL );
855 }
856
857 return sizeof ( *len6 );
858}
859
860/**
861 * Fetch value of NDP router address setting
862 *
863 * @v settings Settings block
864 * @v data Buffer to fill with setting data
865 * @v len Length of buffer
866 * @ret len Length of setting data, or negative error
867 */
869 void *data, size_t len ) {
870 struct ndp_settings *ndpset =
872
873 /* Treat non-routing router as non-existent */
874 if ( ! ndpset->lifetime )
875 return -ENOENT;
876
877 /* Fill in router address */
878 if ( len > sizeof ( ndpset->router ) )
879 len = sizeof ( ndpset->router );
880 memcpy ( data, &ndpset->router, len );
881
882 return sizeof ( ndpset->router );
883}
884
885/** An NDP per-prefix setting operation */
887 /** Generic setting */
888 const struct setting *setting;
889 /**
890 * Fetch value of setting
891 *
892 * @v settings Settings block
893 * @v data Buffer to fill with setting data
894 * @v len Length of buffer
895 * @ret len Length of setting data, or negative error
896 */
897 int ( * fetch ) ( struct settings *settings, void *data, size_t len );
898};
899
900/** NDP per-prefix settings operations */
906
907/**
908 * Fetch value of NDP pre-prefix setting
909 *
910 * @v settings Settings block
911 * @v setting Setting to fetch
912 * @v data Buffer to fill with setting data
913 * @v len Length of buffer
914 * @ret len Length of setting data, or negative error
915 */
916static int ndp_prefix_fetch ( struct settings *settings,
917 struct setting *setting,
918 void *data, size_t len ) {
919 struct ndp_prefix_operation *op;
920 unsigned int i;
921
922 /* Handle per-prefix settings */
923 for ( i = 0 ; i < ( sizeof ( ndp_prefix_operations ) /
924 sizeof ( ndp_prefix_operations[0] ) ) ; i++ ) {
926 if ( setting_cmp ( setting, op->setting ) == 0 )
927 return op->fetch ( settings, data, len );
928 }
929
930 return -ENOENT;
931}
932
933/** NDP per-prefix settings operations */
935 .applies = ndp_prefix_applies,
936 .fetch = ndp_prefix_fetch,
937};
938
939/**
940 * Register NDP settings
941 *
942 * @v netdev Network device
943 * @v router Router address
944 * @v lifetime Router lifetime
945 * @v options NDP options
946 * @v len Length of options
947 * @ret rc Return status code
948 */
950 struct in6_addr *router,
951 unsigned int lifetime,
952 union ndp_option *options, size_t len ) {
954 union ndp_option *option;
955 struct ndp_settings *ndpset;
956 struct ndp_prefix_settings *prefset;
957 size_t offset;
958 size_t option_len;
959 unsigned int prefixes;
960 unsigned int instance;
961 int order;
962 int rc;
963
964 /* Count number of prefix options. We can assume that the
965 * options are well-formed, otherwise they would have been
966 * rejected prior to being stored.
967 */
969 for ( prefixes = 0, offset = 0 ; offset < len ; offset += option_len ) {
970
971 /* Skip non-prefix options */
972 option = ( ( ( void * ) options ) + offset );
973 option_len = ( option->header.blocks * NDP_OPTION_BLKSZ );
974 if ( option->header.type != NDP_OPT_PREFIX )
975 continue;
976
977 /* Count number of prefixes */
978 prefixes++;
979
980 /* Increase overall order if we have SLAAC addresses */
981 if ( option->prefix.flags & NDP_PREFIX_AUTONOMOUS )
982 order = IPV6_ORDER_SLAAC;
983 }
984
985 /* Allocate and initialise structure */
986 ndpset = zalloc ( sizeof ( *ndpset ) + len +
987 ( prefixes * sizeof ( *prefset ) ) );
988 if ( ! ndpset ) {
989 rc = -ENOMEM;
990 goto err_alloc;
991 }
992 ref_init ( &ndpset->refcnt, NULL );
994 &ndpset->refcnt, &ndp_settings_scope );
995 ndpset->settings.order = order;
996 memcpy ( &ndpset->router, router, sizeof ( ndpset->router ) );
997 ndpset->lifetime = lifetime;
998 ndpset->len = len;
999 memcpy ( ndpset->options, options, len );
1000 prefset = ( ( ( void * ) ndpset->options ) + len );
1001
1002 /* Register settings */
1003 if ( ( rc = register_settings ( &ndpset->settings, parent,
1004 NDP_SETTINGS_NAME ) ) != 0 )
1005 goto err_register;
1006
1007 /* Construct and register per-prefix settings */
1008 for ( instance = 0, offset = 0 ; offset < len ; offset += option_len ) {
1009
1010 /* Skip non-prefix options */
1011 option = ( ( ( void * ) ndpset->options ) + offset );
1012 option_len = ( option->header.blocks * NDP_OPTION_BLKSZ );
1013 if ( option->header.type != NDP_OPT_PREFIX )
1014 continue;
1015
1016 /* Initialise structure */
1017 settings_init ( &prefset->settings,
1019 &ndpset->refcnt, &ndp_settings_scope );
1020 prefset->settings.order =
1021 ( ( option->prefix.flags & NDP_PREFIX_AUTONOMOUS ) ?
1023 prefset->prefix = &option->prefix;
1024 snprintf ( prefset->name, sizeof ( prefset->name ), "%d",
1025 instance++ );
1026
1027 /* Register settings */
1028 if ( ( rc = register_settings ( &prefset->settings,
1029 &ndpset->settings,
1030 prefset->name ) ) != 0 )
1031 goto err_register_prefix;
1032
1033 /* Move to next per-prefix settings */
1034 prefset++;
1035 }
1036 assert ( instance == prefixes );
1037
1038 ref_put ( &ndpset->refcnt );
1039 return 0;
1040
1041 err_register_prefix:
1042 unregister_settings ( &ndpset->settings );
1043 err_register:
1044 ref_put ( &ndpset->refcnt );
1045 err_alloc:
1046 return rc;
1047}
1048
1049/** DNS server setting */
1050const struct setting ndp_dns6_setting __setting ( SETTING_IP6_EXTRA, dns6 ) = {
1051 .name = "dns6",
1052 .description = "DNS server",
1053 .tag = NDP_TAG ( NDP_OPT_RDNSS,
1054 offsetof ( struct ndp_rdnss_option, addresses ), 0 ),
1055 .type = &setting_type_ipv6,
1056 .scope = &ndp_settings_scope,
1057};
1058
1059/** DNS search list setting */
1060const struct setting ndp_dnssl_setting __setting ( SETTING_IP_EXTRA, dnssl ) = {
1061 .name = "dnssl",
1062 .description = "DNS search list",
1063 .tag = NDP_TAG ( NDP_OPT_DNSSL,
1064 offsetof ( struct ndp_dnssl_option, names ), 0 ),
1065 .type = &setting_type_dnssl,
1066 .scope = &ndp_settings_scope,
1067};
1068
1069/****************************************************************************
1070 *
1071 * IPv6 autoconfiguration
1072 *
1073 */
1074
1075/** An IPv6 configurator */
1076struct ipv6conf {
1077 /** Reference count */
1079 /** List of configurators */
1081
1082 /** Job control interface */
1084 /** DHCPv6 interface */
1086
1087 /** Network device being configured */
1089
1090 /** Retransmission timer */
1092
1093 /** Deferred discovery counter */
1094 unsigned int deferred;
1095};
1096
1097/** List of IPv6 configurators */
1098static LIST_HEAD ( ipv6confs );
1099
1100/**
1101 * Free IPv6 configurator
1102 *
1103 * @v refcnt Reference count
1104 */
1105static void ipv6conf_free ( struct refcnt *refcnt ) {
1106 struct ipv6conf *ipv6conf =
1107 container_of ( refcnt, struct ipv6conf, refcnt );
1108
1110 free ( ipv6conf );
1111}
1112
1113/**
1114 * Identify IPv6 configurator by network device
1115 *
1116 * @v netdev Network device
1117 * @ret ipv6 IPv6 configurator, or NULL
1118 */
1119static struct ipv6conf * ipv6conf_demux ( struct net_device *netdev ) {
1120 struct ipv6conf *ipv6conf;
1121
1122 list_for_each_entry ( ipv6conf, &ipv6confs, list ) {
1123 if ( ipv6conf->netdev == netdev )
1124 return ipv6conf;
1125 }
1126 return NULL;
1127}
1128
1129/**
1130 * Finish IPv6 autoconfiguration
1131 *
1132 * @v ipv6 IPv6 configurator
1133 * @v rc Reason for finishing
1134 */
1135static void ipv6conf_done ( struct ipv6conf *ipv6conf, int rc ) {
1136
1137 /* Shut down interfaces */
1140
1141 /* Stop timer */
1143
1144 /* Remove from list and drop list's reference */
1145 list_del ( &ipv6conf->list );
1146 ref_put ( &ipv6conf->refcnt );
1147}
1148
1149/**
1150 * Handle IPv6 configurator timer expiry
1151 *
1152 * @v timer Retry timer
1153 * @v fail Failure indicator
1154 */
1155static void ipv6conf_expired ( struct retry_timer *timer, int fail ) {
1156 struct ipv6conf *ipv6conf =
1157 container_of ( timer, struct ipv6conf, timer );
1158 struct net_device *netdev = ipv6conf->netdev;
1159
1160 /* If we have failed, terminate autoconfiguration */
1161 if ( fail ) {
1163 return;
1164 }
1165
1166 /* Otherwise, transmit router solicitation and restart timer */
1169
1170 /* If link is blocked, defer router discovery timeout */
1171 if ( netdev_link_blocked ( netdev ) &&
1173 DBGC ( netdev, "NDP %s deferring discovery timeout\n",
1174 netdev->name );
1176 }
1177}
1178
1179/**
1180 * Handle router advertisement during IPv6 autoconfiguration
1181 *
1182 * @v netdev Network device
1183 * @v router Router address
1184 * @v radv Router advertisement
1185 * @v len Length of router advertisement
1186 * @ret rc Return status code
1187 *
1188 * This function assumes that the router advertisement is well-formed,
1189 * since it must have already passed through option processing.
1190 */
1191static int
1193 struct in6_addr *router,
1195 size_t len ) {
1196 struct ipv6conf *ipv6conf;
1197 size_t option_len;
1198 int stateful;
1199 int rc;
1200
1201 /* Identify IPv6 configurator, if any */
1203
1204 /* Do nothing unless IPv6 autoconfiguration is in progress */
1205 if ( ! ipv6conf )
1206 return 0;
1207
1208 /* If this is not the first solicited router advertisement, ignore it */
1209 if ( ! timer_running ( &ipv6conf->timer ) )
1210 return 0;
1211
1212 /* Stop router solicitation timer */
1214
1215 /* Register NDP settings */
1216 option_len = ( len - offsetof ( typeof ( *radv ), option ) );
1217 if ( ( rc = ndp_register_settings ( netdev, router,
1218 ntohl ( radv->lifetime ),
1219 radv->option, option_len ) ) != 0 )
1220 return rc;
1221
1222 /* Start DHCPv6 if required */
1223 if ( radv->flags & ( NDP_ROUTER_MANAGED | NDP_ROUTER_OTHER ) ) {
1224 stateful = ( radv->flags & NDP_ROUTER_MANAGED );
1225 if ( ( rc = start_dhcpv6 ( &ipv6conf->dhcp, netdev, router,
1226 stateful ) ) != 0 ) {
1227 DBGC ( netdev, "NDP %s could not start state%s DHCPv6: "
1228 "%s\n", netdev->name,
1229 ( stateful ? "ful" : "less" ), strerror ( rc ) );
1231 return rc;
1232 }
1233 return 0;
1234 }
1235
1236 /* Otherwise, terminate autoconfiguration */
1237 ipv6conf_done ( ipv6conf, 0 );
1238
1239 return 0;
1240}
1241
1242/** IPv6 configurator job interface operations */
1245};
1246
1247/** IPv6 configurator job interface descriptor */
1249 INTF_DESC ( struct ipv6conf, job, ipv6conf_job_op );
1250
1251/** IPv6 configurator DHCPv6 interface operations */
1254};
1255
1256/** IPv6 configurator DHCPv6 interface descriptor */
1258 INTF_DESC ( struct ipv6conf, dhcp, ipv6conf_dhcp_op );
1259
1260/**
1261 * Start IPv6 autoconfiguration
1262 *
1263 * @v job Job control interface
1264 * @v netdev Network device
1265 * @ret rc Return status code
1266 */
1267int start_ipv6conf ( struct interface *job, struct net_device *netdev ) {
1268 struct ipv6conf *ipv6conf;
1269
1270 /* Allocate and initialise structure */
1271 ipv6conf = zalloc ( sizeof ( *ipv6conf ) );
1272 if ( ! ipv6conf )
1273 return -ENOMEM;
1277 timer_init ( &ipv6conf->timer, ipv6conf_expired, &ipv6conf->refcnt );
1278 set_timer_limits ( &ipv6conf->timer, IPV6CONF_MIN_TIMEOUT,
1281
1282 /* Start timer to initiate router solicitation */
1284
1285 /* Attach parent interface, transfer reference to list, and return */
1287 list_add ( &ipv6conf->list, &ipv6confs );
1288 return 0;
1289}
1290
1291/** IPv6 network device configurator */
1293 .name = "ipv6",
1294 .start = start_ipv6conf,
1295};
static int options
Definition 3c515.c:286
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
typeof(acpi_finder=acpi_find)
ACPI table finder.
Definition acpi.c:48
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
unsigned char uint8_t
Definition stdint.h:10
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
uint16_t offset
Offset to command line.
Definition bzimage.h:3
int start_dhcpv6(struct interface *job, struct net_device *netdev, struct in6_addr *router, int stateful)
Start DHCPv6.
Definition dhcpv6.c:1000
Dynamic Host Configuration Protocol for IPv6.
static struct dns_server dns6
IPv6 DNS server list.
Definition dns.c:86
ring len
Length.
Definition dwmac.h:226
const struct setting gateway6_setting
const struct setting len6_setting
const struct setting ip6_setting
uint8_t data[48]
Additional event data.
Definition ena.h:11
Error codes.
static struct net_device * netdev
Definition gdbudp.c:53
#define AF_INET6
IPv6 Internet addresses.
Definition socket.h:65
#define __unused
Declare a variable or data structure as unused.
Definition compiler.h:573
#define DBGC(...)
Definition compiler.h:505
#define DBGC_HDA(...)
Definition compiler.h:506
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define ENOENT
No such file or directory.
Definition errno.h:515
#define EINVAL
Invalid argument.
Definition errno.h:429
#define ETIMEDOUT
Connection timed out.
Definition errno.h:670
#define ENOMEM
Not enough space.
Definition errno.h:535
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
#define SETTING_IP_EXTRA
IPv4 additional settings.
Definition settings.h:71
#define SETTING_IP6_EXTRA
IPv6 additional settings.
Definition settings.h:69
ICMPv6 protocol.
#define __icmpv6_handler
Declare an ICMPv6 handler.
Definition icmpv6.h:42
#define ICMPV6_NEIGHBOUR_SOLICITATION
ICMPv6 neighbour solicitation.
Definition icmpv6.h:69
#define ICMPV6_ROUTER_SOLICITATION
ICMPv6 router solicitation.
Definition icmpv6.h:63
#define ICMPV6_NEIGHBOUR_ADVERTISEMENT
ICMPv6 neighbour advertisement.
Definition icmpv6.h:72
#define ICMPV6_ROUTER_ADVERTISEMENT
ICMPv6 router advertisement.
Definition icmpv6.h:66
#define ntohl(value)
Definition byteswap.h:135
#define __setting(setting_order, name)
Declare a configuration setting.
Definition settings.h:57
static void settings_init(struct settings *settings, struct settings_operations *op, struct refcnt *refcnt, const struct settings_scope *default_scope)
Initialise a settings block.
Definition settings.h:503
Transport-network layer interface.
iPXE timers
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition interface.c:250
void intf_plug_plug(struct interface *a, struct interface *b)
Plug two object interfaces together.
Definition interface.c:108
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
Definition interface.c:279
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition interface.h:81
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
Definition interface.h:204
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition interface.h:33
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition iobuf.c:131
I/O buffers.
#define iob_put(iobuf, len)
Definition iobuf.h:125
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:160
#define iob_reserve(iobuf, len)
Definition iobuf.h:72
char * inet6_ntoa(const struct in6_addr *in)
Convert IPv6 address to standard notation.
Definition ipv6.c:895
int ipv6_has_addr(struct net_device *netdev, struct in6_addr *addr)
Check if network device has a specific IPv6 address.
Definition ipv6.c:142
const struct settings_scope ipv6_settings_scope
IPv6 settings scope.
Definition ipv6.c:1121
IPv6 protocol.
static int ipv6_eui64(struct in6_addr *addr, struct net_device *netdev)
Construct local IPv6 address via EUI-64.
Definition ipv6.h:217
static void ipv6_solicited_node(struct in6_addr *addr, const struct in6_addr *unicast)
Construct solicited-node multicast address.
Definition ipv6.h:249
static void ipv6_all_routers(struct in6_addr *addr)
Construct all-routers multicast address.
Definition ipv6.h:263
@ IPV6_ORDER_PREFIX_ONLY
No address.
Definition ipv6.h:283
@ IPV6_ORDER_SLAAC
Address assigned via SLAAC.
Definition ipv6.h:287
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition list.h:432
#define list_del(list)
Delete an entry from a list.
Definition list.h:120
#define LIST_HEAD(list)
Declare a static list head.
Definition list.h:38
#define list_add(new, head)
Add a new entry to the head of a list.
Definition list.h:70
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:662
static int ndp_rx_router_advertisement(struct io_buffer *iobuf, struct net_device *netdev, struct sockaddr_in6 *sin6_src, struct sockaddr_in6 *sin6_dest __unused)
Process received NDP router advertisement.
Definition ndp.c:547
static int ndp_register_settings(struct net_device *netdev, struct in6_addr *router, unsigned int lifetime, union ndp_option *options, size_t len)
Register NDP settings.
Definition ndp.c:949
static struct ndp_option_handler ndp_option_handlers[]
NDP option handlers.
Definition ndp.c:399
static int ndp_rx_router_advertisement_ll_source(struct net_device *netdev, struct sockaddr_in6 *sin6_src, union ndp_header *ndp __unused, union ndp_option *option, size_t len)
Process NDP router advertisement source link-layer address option.
Definition ndp.c:312
#define IPV6CONF_BLOCK_TIMEOUT
Router discovery blocked link retry timeout.
Definition ndp.c:51
static int ndp_rx_option(struct net_device *netdev, struct sockaddr_in6 *sin6_src, union ndp_header *ndp, union ndp_option *option, size_t len)
Process received NDP option.
Definition ndp.c:432
static int ndp_fetch(struct settings *settings, struct setting *setting, void *data, size_t len)
Fetch value of NDP setting.
Definition ndp.c:690
static int ndp_rx_router_advertisement_prefix(struct net_device *netdev, struct sockaddr_in6 *sin6_src, union ndp_header *ndp, union ndp_option *option, size_t len)
Process NDP router advertisement prefix information option.
Definition ndp.c:353
static int ndp_prefix_applies(struct settings *settings __unused, const struct setting *setting)
Check applicability of NDP per-prefix setting.
Definition ndp.c:769
static int ndp_prefix_fetch(struct settings *settings, struct setting *setting, void *data, size_t len)
Fetch value of NDP pre-prefix setting.
Definition ndp.c:916
static struct interface_descriptor ipv6conf_job_desc
IPv6 configurator job interface descriptor.
Definition ndp.c:1248
static int ndp_rx_neighbour(struct io_buffer *iobuf, struct net_device *netdev, struct sockaddr_in6 *sin6_src, struct sockaddr_in6 *sin6_dest __unused)
Process received NDP neighbour solicitation or advertisement.
Definition ndp.c:517
#define IPV6CONF_MIN_TIMEOUT
Router discovery minimum timeout.
Definition ndp.c:45
static const struct settings_scope ndp_settings_scope
NDP settings scope.
Definition ndp.c:623
int start_ipv6conf(struct interface *job, struct net_device *netdev)
Start IPv6 autoconfiguration.
Definition ndp.c:1267
#define IPV6CONF_MAX_DEFERRALS
Router discovery maximum number of deferrals.
Definition ndp.c:54
static int ndp_prefix_fetch_len6(struct settings *settings, void *data, size_t len)
Fetch value of NDP prefix length setting.
Definition ndp.c:840
static int ndp_rx_neighbour_solicitation_ll_source(struct net_device *netdev, struct sockaddr_in6 *sin6_src, union ndp_header *ndp, union ndp_option *option, size_t len)
Process NDP neighbour solicitation source link-layer address option.
Definition ndp.c:207
static int ndp_tx_request(struct net_device *netdev, struct net_protocol *net_protocol __unused, const void *net_dest, const void *net_source)
Transmit NDP neighbour discovery request.
Definition ndp.c:127
static int ndp_rx_options(struct net_device *netdev, struct sockaddr_in6 *sin6_src, union ndp_header *ndp, size_t offset, size_t len)
Process received NDP packet options.
Definition ndp.c:463
static int ndp_prefix_fetch_ip6(struct settings *settings, void *data, size_t len)
Fetch value of NDP IPv6 address setting.
Definition ndp.c:783
#define NDP_TAG_INSTANCE(tag)
Extract NDP tag instance.
Definition ndp.c:666
#define IPV6CONF_MAX_TIMEOUT
Router discovery maximum timeout.
Definition ndp.c:48
#define NDP_TAG(type, offset, len)
Construct NDP tag.
Definition ndp.c:633
static void ipv6conf_expired(struct retry_timer *timer, int fail)
Handle IPv6 configurator timer expiry.
Definition ndp.c:1155
static int ipv6conf_rx_router_advertisement(struct net_device *netdev, struct in6_addr *router, struct ndp_router_advertisement_header *radv, size_t len)
Handle router advertisement during IPv6 autoconfiguration.
Definition ndp.c:1192
struct neighbour_discovery ndp_discovery
NDP neighbour discovery protocol.
Definition ndp.c:162
static struct ndp_prefix_operation ndp_prefix_operations[]
NDP per-prefix settings operations.
Definition ndp.c:901
static struct interface_operation ipv6conf_job_op[]
IPv6 configurator job interface operations.
Definition ndp.c:1243
static int ndp_prefix_fetch_gateway6(struct settings *settings, void *data, size_t len)
Fetch value of NDP router address setting.
Definition ndp.c:868
static struct interface_operation ipv6conf_dhcp_op[]
IPv6 configurator DHCPv6 interface operations.
Definition ndp.c:1252
#define NDP_TAG_LEN(tag)
Extract NDP tag length.
Definition ndp.c:658
#define NDP_TAG_TYPE(tag)
Extract NDP tag type.
Definition ndp.c:642
static int ndp_tx_ll_addr(struct net_device *netdev, struct sockaddr_in6 *sin6_src, struct sockaddr_in6 *sin6_dest, const void *data, size_t len, unsigned int option_type)
Transmit NDP packet with link-layer address option.
Definition ndp.c:74
static int ndp_rx_neighbour_advertisement_ll_target(struct net_device *netdev, struct sockaddr_in6 *sin6_src __unused, union ndp_header *ndp, union ndp_option *option, size_t len)
Process NDP neighbour advertisement target link-layer address option.
Definition ndp.c:268
static struct settings_operations ndp_settings_operations
NDP settings operations.
Definition ndp.c:757
static struct ipv6conf * ipv6conf_demux(struct net_device *netdev)
Identify IPv6 configurator by network device.
Definition ndp.c:1119
static void ipv6conf_done(struct ipv6conf *ipv6conf, int rc)
Finish IPv6 autoconfiguration.
Definition ndp.c:1135
static void ipv6conf_free(struct refcnt *refcnt)
Free IPv6 configurator.
Definition ndp.c:1105
static int ndp_tx_router_solicitation(struct net_device *netdev)
Transmit NDP router solicitation.
Definition ndp.c:173
static int ndp_applies(struct settings *settings __unused, const struct setting *setting)
Check applicability of NDP setting.
Definition ndp.c:675
#define NDP_TAG_OFFSET(tag)
Extract NDP tag offset.
Definition ndp.c:650
static struct interface_descriptor ipv6conf_dhcp_desc
IPv6 configurator DHCPv6 interface descriptor.
Definition ndp.c:1257
static struct settings_operations ndp_prefix_settings_operations
NDP per-prefix settings operations.
Definition ndp.c:934
Neighbour discovery protocol.
#define NDP_PREFIX_ON_LINK
NDP on-link flag.
Definition ndp.h:66
#define NDP_OPT_LL_TARGET
NDP target link-layer address option.
Definition ndp.h:34
#define NDP_SETTINGS_NAME
NDP settings block name.
Definition ndp.h:203
#define NDP_OPT_LL_SOURCE
NDP source link-layer address option.
Definition ndp.h:31
#define NDP_NEIGHBOUR_SOLICITED
NDP solicited flag.
Definition ndp.h:133
#define NDP_ROUTER_MANAGED
NDP managed address configuration.
Definition ndp.h:157
#define NDP_OPT_PREFIX
NDP prefix information option.
Definition ndp.h:45
#define NDP_OPT_RDNSS
NDP recursive DNS server option.
Definition ndp.h:72
#define NDP_OPT_DNSSL
NDP DNS search list option.
Definition ndp.h:87
#define NDP_OPTION_BLKSZ
NDP option block size.
Definition ndp.h:28
#define NDP_PREFIX_AUTONOMOUS
NDP autonomous address configuration flag.
Definition ndp.h:69
#define NDP_ROUTER_OTHER
NDP other configuration.
Definition ndp.h:160
#define NDP_NEIGHBOUR_OVERRIDE
NDP override flag.
Definition ndp.h:136
int neighbour_update(struct net_device *netdev, struct net_protocol *net_protocol, const void *net_dest, const void *ll_dest)
Update existing neighbour cache entry.
Definition neighbour.c:441
int neighbour_define(struct net_device *netdev, struct net_protocol *net_protocol, const void *net_dest, const void *ll_dest)
Define neighbour cache entry.
Definition neighbour.c:466
Neighbour discovery.
static int netdev_link_blocked(struct net_device *netdev)
Check link block state of network device.
Definition netdevice.h:651
static struct net_device * netdev_get(struct net_device *netdev)
Get reference to network device.
Definition netdevice.h:565
static void netdev_put(struct net_device *netdev)
Drop reference to network device.
Definition netdevice.h:576
#define __net_device_configurator
Declare a network device configurator.
Definition netdevice.h:337
#define MAX_LL_NET_HEADER_LEN
Maximum combined length of a link-layer and network-layer header.
Definition netdevice.h:59
static struct settings * netdev_settings(struct net_device *netdev)
Get per-netdevice configuration settings block.
Definition netdevice.h:587
static uint16_t struct vmbus_xfer_pages_operations * op
Definition netvsc.h:327
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
#define ref_put(refcnt)
Drop reference to object.
Definition refcnt.h:107
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition refcnt.h:65
void start_timer(struct retry_timer *timer)
Start timer.
Definition retry.c:94
void start_timer_fixed(struct retry_timer *timer, unsigned long timeout)
Start timer with a specified timeout.
Definition retry.c:65
void stop_timer(struct retry_timer *timer)
Stop timer.
Definition retry.c:118
static void start_timer_nodelay(struct retry_timer *timer)
Start timer with no delay.
Definition retry.h:100
int register_settings(struct settings *settings, struct settings *parent, const char *name)
Register settings block.
Definition settings.c:476
void unregister_settings(struct settings *settings)
Unregister settings block.
Definition settings.c:515
int setting_cmp(const struct setting *a, const struct setting *b)
Compare two settings.
Definition settings.c:1121
#define offsetof(type, field)
Get offset of a field within a structure.
Definition stddef.h:25
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
uint8_t type
Type.
Definition icmp.h:22
uint16_t chksum
Checksum.
Definition icmp.h:26
An ICMPv6 handler.
Definition icmpv6.h:20
IP6 address structure.
Definition in.h:51
An object interface descriptor.
Definition interface.h:56
An object interface operation.
Definition interface.h:18
An object interface.
Definition interface.h:125
A persistent I/O buffer.
Definition iobuf.h:38
void * data
Start of data.
Definition iobuf.h:53
An IPv6 configurator.
Definition ndp.c:1076
struct interface job
Job control interface.
Definition ndp.c:1083
struct refcnt refcnt
Reference count.
Definition ndp.c:1078
struct interface dhcp
DHCPv6 interface.
Definition ndp.c:1085
struct retry_timer timer
Retransmission timer.
Definition ndp.c:1091
unsigned int deferred
Deferred discovery counter.
Definition ndp.c:1094
struct list_head list
List of configurators.
Definition ndp.c:1080
struct net_device * netdev
Network device being configured.
Definition ndp.c:1088
A doubly-linked list entry (or list head)
Definition list.h:19
A link-layer protocol.
Definition netdevice.h:115
const char *(* ntoa)(const void *ll_addr)
Transcribe link-layer address.
Definition netdevice.h:164
uint8_t ll_addr_len
Link-layer address length.
Definition netdevice.h:199
NDP DNS search list.
Definition ndp.h:90
NDP source or target link-layer address option.
Definition ndp.h:37
struct ndp_option_header header
NDP option header.
Definition ndp.h:39
uint8_t ll_addr[0]
Link-layer address.
Definition ndp.h:41
An NDP neighbour solicitation or advertisement header.
Definition ndp.h:116
struct icmp_header icmp
ICMPv6 header.
Definition ndp.h:118
uint8_t flags
Flags.
Definition ndp.h:120
struct in6_addr target
Target address.
Definition ndp.h:124
An NDP option handler.
Definition ndp.c:379
int(* rx)(struct net_device *netdev, struct sockaddr_in6 *sin6_src, union ndp_header *ndp, union ndp_option *option, size_t len)
Handle received option.
Definition ndp.c:393
uint8_t option_type
Option type.
Definition ndp.c:383
uint8_t icmp_type
ICMPv6 type.
Definition ndp.c:381
uint8_t blocks
Length (in blocks of 8 bytes)
Definition ndp.h:24
uint8_t type
Type.
Definition ndp.h:22
NDP prefix information.
Definition ndp.h:48
uint8_t flags
Flags.
Definition ndp.h:54
uint8_t prefix_len
Prefix length.
Definition ndp.h:52
struct in6_addr prefix
Prefix.
Definition ndp.h:62
An NDP per-prefix setting operation.
Definition ndp.c:886
int(* fetch)(struct settings *settings, void *data, size_t len)
Fetch value of setting.
Definition ndp.c:897
const struct setting * setting
Generic setting.
Definition ndp.c:888
An NDP prefix settings block.
Definition ndp.c:597
char name[4]
Name.
Definition ndp.c:601
struct settings settings
Settings interface.
Definition ndp.c:599
struct ndp_prefix_information_option * prefix
Prefix information option.
Definition ndp.c:603
NDP recursive DNS server.
Definition ndp.h:75
An NDP router advertisement header.
Definition ndp.h:139
union ndp_option option[0]
Options.
Definition ndp.h:153
uint16_t lifetime
Router lifetime.
Definition ndp.h:147
An NDP router solicitation header.
Definition ndp.h:163
struct icmp_header icmp
ICMPv6 header.
Definition ndp.h:165
An NDP settings block.
Definition ndp.c:607
unsigned int lifetime
Router lifetime.
Definition ndp.c:615
struct settings settings
Settings interface.
Definition ndp.c:611
union ndp_option options[0]
NDP options.
Definition ndp.c:619
struct in6_addr router
Router address.
Definition ndp.c:613
struct refcnt refcnt
Reference counter.
Definition ndp.c:609
size_t len
Length of NDP options.
Definition ndp.c:617
A neighbour discovery protocol.
Definition neighbour.h:20
A network device configurator.
Definition netdevice.h:314
A network device.
Definition netdevice.h:353
A network-layer protocol.
Definition netdevice.h:65
A long option, as used for getopt_long()
Definition getopt.h:25
A reference counter.
Definition refcnt.h:27
A retry timer.
Definition retry.h:22
A setting.
Definition settings.h:24
const struct settings_scope * scope
Setting scope (or NULL)
Definition settings.h:50
const struct setting_type * type
Setting type.
Definition settings.h:37
uint64_t tag
Setting tag, if applicable.
Definition settings.h:44
Settings block operations.
Definition settings.h:86
A setting scope.
Definition settings.h:177
A settings block.
Definition settings.h:133
int order
Sibling ordering.
Definition settings.h:149
struct settings * parent
Parent settings block.
Definition settings.h:139
IPv6 socket address.
Definition in.h:118
struct in6_addr sin6_addr
IPv6 address.
Definition in.h:135
uint16_t sin6_scope_id
Scope ID (part of struct sockaddr_tcpip)
Definition in.h:133
sa_family_t sin6_family
Socket address family (part of struct sockaddr)
Definition in.h:123
TCP/IP socket address.
Definition tcpip.h:76
A timer.
Definition timer.h:29
int tcpip_tx(struct io_buffer *iobuf, struct tcpip_protocol *tcpip_protocol, struct sockaddr_tcpip *st_src, struct sockaddr_tcpip *st_dest, struct net_device *netdev, uint16_t *trans_csum)
Transmit a TCP/IP packet.
Definition tcpip.c:92
uint16_t tcpip_chksum(const void *data, size_t len)
Calculate TCP/IP checkum.
Definition tcpip.c:204
An NDP header.
Definition ndp.h:173
struct ndp_router_advertisement_header radv
Router advertisement header.
Definition ndp.h:181
struct ndp_neighbour_header neigh
Neighbour solicitation or advertisement header.
Definition ndp.h:177
struct icmp_header icmp
ICMPv6 header.
Definition ndp.h:175
An NDP option.
Definition ndp.h:102
char prefix[4]
Definition vmconsole.c:53
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition vsprintf.c:383
u32 lifetime
For Lifetime-type KDEs, the lifetime in seconds.
Definition wpa.h:27