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