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