iPXE
ipv6.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 <stdint.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <strings.h>
27 #include <errno.h>
28 #include <assert.h>
29 #include <byteswap.h>
30 #include <ipxe/iobuf.h>
31 #include <ipxe/tcpip.h>
32 #include <ipxe/if_ether.h>
33 #include <ipxe/crc32.h>
34 #include <ipxe/fragment.h>
35 #include <ipxe/ipstat.h>
36 #include <ipxe/ndp.h>
37 #include <ipxe/ipv6.h>
38 
39 /** @file
40  *
41  * IPv6 protocol
42  *
43  */
44 
45 /* Disambiguate the various error causes */
46 #define EINVAL_LEN __einfo_error ( EINFO_EINVAL_LEN )
47 #define EINFO_EINVAL_LEN \
48  __einfo_uniqify ( EINFO_EINVAL, 0x01, "Invalid length" )
49 #define ENOTSUP_VER __einfo_error ( EINFO_ENOTSUP_VER )
50 #define EINFO_ENOTSUP_VER \
51  __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Unsupported version" )
52 #define ENOTSUP_HDR __einfo_error ( EINFO_ENOTSUP_HDR )
53 #define EINFO_ENOTSUP_HDR \
54  __einfo_uniqify ( EINFO_ENOTSUP, 0x02, "Unsupported header type" )
55 #define ENOTSUP_OPT __einfo_error ( EINFO_ENOTSUP_OPT )
56 #define EINFO_ENOTSUP_OPT \
57  __einfo_uniqify ( EINFO_ENOTSUP, 0x03, "Unsupported option" )
58 
59 /** List of IPv6 miniroutes */
61 
62 /** IPv6 statistics */
63 static struct ip_statistics ipv6_stats;
64 
65 /** IPv6 statistics family */
67 ipv6_statistics_family __ip_statistics_family ( IP_STATISTICS_IPV6 ) = {
68  .version = 6,
69  .stats = &ipv6_stats,
70 };
71 
72 /**
73  * Determine debugging colour for IPv6 debug messages
74  *
75  * @v in IPv6 address
76  * @ret col Debugging colour (for DBGC())
77  */
78 static uint32_t ipv6col ( struct in6_addr *in ) {
79  return crc32_le ( 0, in, sizeof ( *in ) );
80 }
81 
82 /**
83  * Determine IPv6 address scope
84  *
85  * @v addr IPv6 address
86  * @ret scope Address scope
87  */
88 static unsigned int ipv6_scope ( const struct in6_addr *addr ) {
89 
90  /* Multicast addresses directly include a scope field */
91  if ( IN6_IS_ADDR_MULTICAST ( addr ) )
92  return ipv6_multicast_scope ( addr );
93 
94  /* Link-local addresses have link-local scope */
95  if ( IN6_IS_ADDR_LINKLOCAL ( addr ) )
96  return IPV6_SCOPE_LINK_LOCAL;
97 
98  /* Site-local addresses have site-local scope */
99  if ( IN6_IS_ADDR_SITELOCAL ( addr ) )
100  return IPV6_SCOPE_SITE_LOCAL;
101 
102  /* Unique local addresses do not directly map to a defined
103  * scope. They effectively have a scope which is wider than
104  * link-local but narrower than global. Since the only
105  * multicast packets that we transmit are link-local, we can
106  * simply choose an arbitrary scope between link-local and
107  * global.
108  */
109  if ( IN6_IS_ADDR_ULA ( addr ) )
111 
112  /* All other addresses are assumed to be global */
113  return IPV6_SCOPE_GLOBAL;
114 }
115 
116 /**
117  * Dump IPv6 routing table entry
118  *
119  * @v miniroute Routing table entry
120  */
121 static inline __attribute__ (( always_inline )) void
122 ipv6_dump_miniroute ( struct ipv6_miniroute *miniroute ) {
123  struct net_device *netdev = miniroute->netdev;
124 
125  DBGC ( netdev, "IPv6 %s has %s %s/%d", netdev->name,
126  ( ( miniroute->flags & IPV6_HAS_ADDRESS ) ?
127  "address" : "prefix" ),
128  inet6_ntoa ( &miniroute->address ), miniroute->prefix_len );
129  if ( miniroute->flags & IPV6_HAS_ROUTER )
130  DBGC ( netdev, " router %s", inet6_ntoa ( &miniroute->router ));
131  DBGC ( netdev, "\n" );
132 }
133 
134 /**
135  * Check if network device has a specific IPv6 address
136  *
137  * @v netdev Network device
138  * @v addr IPv6 address
139  * @ret has_addr Network device has this IPv6 address
140  */
141 int ipv6_has_addr ( struct net_device *netdev, struct in6_addr *addr ) {
142  struct ipv6_miniroute *miniroute;
143 
144  list_for_each_entry ( miniroute, &ipv6_miniroutes, list ) {
145  if ( ( miniroute->netdev == netdev ) &&
146  ( miniroute->flags & IPV6_HAS_ADDRESS ) &&
147  ( memcmp ( &miniroute->address, addr,
148  sizeof ( miniroute->address ) ) == 0 ) ) {
149  /* Found matching address */
150  return 1;
151  }
152  }
153  return 0;
154 }
155 
156 /**
157  * Count matching bits of an IPv6 routing table entry prefix
158  *
159  * @v miniroute Routing table entry
160  * @v address IPv6 address
161  * @ret match_len Number of matching prefix bits
162  */
163 static unsigned int ipv6_match_len ( struct ipv6_miniroute *miniroute,
164  struct in6_addr *address ) {
165  unsigned int match_len = 0;
166  unsigned int i;
167  uint32_t diff;
168 
169  for ( i = 0 ; i < ( sizeof ( address->s6_addr32 ) /
170  sizeof ( address->s6_addr32[0] ) ) ; i++ ) {
171 
172  diff = ntohl ( ~( ( ~( address->s6_addr32[i] ^
173  miniroute->address.s6_addr32[i] ) )
174  & miniroute->prefix_mask.s6_addr32[i] ) );
175  match_len += 32;
176  if ( diff ) {
177  match_len -= flsl ( diff );
178  break;
179  }
180  }
181 
182  return match_len;
183 }
184 
185 /**
186  * Find IPv6 routing table entry for a given address
187  *
188  * @v netdev Network device
189  * @v address IPv6 address
190  * @ret miniroute Routing table entry, or NULL if not found
191  */
192 static struct ipv6_miniroute * ipv6_miniroute ( struct net_device *netdev,
193  struct in6_addr *address ) {
194  struct ipv6_miniroute *miniroute;
195  unsigned int match_len;
196 
197  list_for_each_entry ( miniroute, &ipv6_miniroutes, list ) {
198  if ( miniroute->netdev != netdev )
199  continue;
200  match_len = ipv6_match_len ( miniroute, address );
201  if ( match_len < miniroute->prefix_len )
202  continue;
203  return miniroute;
204  }
205  return NULL;
206 }
207 
208 /**
209  * Add IPv6 routing table entry
210  *
211  * @v netdev Network device
212  * @v address IPv6 address (or prefix)
213  * @v prefix_len Prefix length
214  * @v router Router address (if any)
215  * @ret rc Return status code
216  */
218  unsigned int prefix_len, struct in6_addr *router ) {
219  struct ipv6_miniroute *miniroute;
221  unsigned int remaining;
222  unsigned int i;
223 
224  /* Find or create routing table entry */
225  miniroute = ipv6_miniroute ( netdev, address );
226  if ( miniroute ) {
227 
228  /* Remove from existing position in routing table */
229  list_del ( &miniroute->list );
230 
231  } else {
232 
233  /* Create new routing table entry */
234  miniroute = zalloc ( sizeof ( *miniroute ) );
235  if ( ! miniroute )
236  return -ENOMEM;
237  miniroute->netdev = netdev_get ( netdev );
238  memcpy ( &miniroute->address, address,
239  sizeof ( miniroute->address ) );
240 
241  /* Default to prefix length of 64 if none specified */
242  if ( ! prefix_len )
244  miniroute->prefix_len = prefix_len;
246 
247  /* Construct prefix mask */
248  remaining = prefix_len;
249  for ( prefix_mask = miniroute->prefix_mask.s6_addr ;
250  remaining >= 8 ; prefix_mask++, remaining -= 8 ) {
251  *prefix_mask = 0xff;
252  }
253  if ( remaining )
254  *prefix_mask = ( 0xff << ( 8 - remaining ) );
255  }
256 
257  /* Add to start of routing table */
258  list_add ( &miniroute->list, &ipv6_miniroutes );
259 
260  /* Set or update address, if applicable */
261  for ( i = 0 ; i < ( sizeof ( address->s6_addr32 ) /
262  sizeof ( address->s6_addr32[0] ) ) ; i++ ) {
263  if ( ( address->s6_addr32[i] &
264  ~miniroute->prefix_mask.s6_addr32[i] ) != 0 ) {
265  memcpy ( &miniroute->address, address,
266  sizeof ( miniroute->address ) );
267  miniroute->flags |= IPV6_HAS_ADDRESS;
268  }
269  }
270  if ( miniroute->prefix_len == IPV6_MAX_PREFIX_LEN )
271  miniroute->flags |= IPV6_HAS_ADDRESS;
272 
273  /* Update scope */
274  miniroute->scope = ipv6_scope ( &miniroute->address );
275 
276  /* Set or update router, if applicable */
277  if ( router ) {
278  memcpy ( &miniroute->router, router,
279  sizeof ( miniroute->router ) );
280  miniroute->flags |= IPV6_HAS_ROUTER;
281  }
282 
283  ipv6_dump_miniroute ( miniroute );
284  return 0;
285 }
286 
287 /**
288  * Delete IPv6 minirouting table entry
289  *
290  * @v miniroute Routing table entry
291  */
292 void ipv6_del_miniroute ( struct ipv6_miniroute *miniroute ) {
293 
294  netdev_put ( miniroute->netdev );
295  list_del ( &miniroute->list );
296  free ( miniroute );
297 }
298 
299 /**
300  * Perform IPv6 routing
301  *
302  * @v scope_id Destination address scope ID (for link-local addresses)
303  * @v dest Final destination address
304  * @ret dest Next hop destination address
305  * @ret miniroute Routing table entry to use, or NULL if no route
306  */
307 struct ipv6_miniroute * ipv6_route ( unsigned int scope_id,
308  struct in6_addr **dest ) {
309  struct ipv6_miniroute *miniroute;
310  struct ipv6_miniroute *chosen = NULL;
311  unsigned int best = 0;
312  unsigned int match_len;
313  unsigned int score;
314  unsigned int scope;
315 
316  /* Calculate destination address scope */
317  scope = ipv6_scope ( *dest );
318 
319  /* Find first usable route in routing table */
320  list_for_each_entry ( miniroute, &ipv6_miniroutes, list ) {
321 
322  /* Skip closed network devices */
323  if ( ! netdev_is_open ( miniroute->netdev ) )
324  continue;
325 
326  /* Skip entries with no usable source address */
327  if ( ! ( miniroute->flags & IPV6_HAS_ADDRESS ) )
328  continue;
329 
330  /* Skip entries with a non-matching scope ID, if
331  * destination specifies a scope ID.
332  */
333  if ( scope_id && ( miniroute->netdev->scope_id != scope_id ) )
334  continue;
335 
336  /* Skip entries that are out of scope */
337  if ( miniroute->scope < scope )
338  continue;
339 
340  /* Calculate match length */
341  match_len = ipv6_match_len ( miniroute, *dest );
342 
343  /* If destination is on-link, then use this route */
344  if ( match_len >= miniroute->prefix_len )
345  return miniroute;
346 
347  /* If destination is unicast, then skip off-link
348  * entries with no router.
349  */
350  if ( ! ( IN6_IS_ADDR_MULTICAST ( *dest ) ||
351  ( miniroute->flags & IPV6_HAS_ROUTER ) ) )
352  continue;
353 
354  /* Choose best route, defined as being the route with
355  * the smallest viable scope. If two routes both have
356  * the same scope, then prefer the route with the
357  * longest match length.
358  */
359  score = ( ( ( IPV6_SCOPE_MAX + 1 - miniroute->scope ) << 8 )
360  + match_len );
361  if ( score > best ) {
362  chosen = miniroute;
363  best = score;
364  }
365  }
366 
367  /* Return chosen route, if any */
368  if ( chosen ) {
369  if ( ! IN6_IS_ADDR_MULTICAST ( *dest ) )
370  *dest = &chosen->router;
371  return chosen;
372  }
373 
374  return NULL;
375 }
376 
377 /**
378  * Determine transmitting network device
379  *
380  * @v st_dest Destination network-layer address
381  * @ret netdev Transmitting network device, or NULL
382  */
383 static struct net_device * ipv6_netdev ( struct sockaddr_tcpip *st_dest ) {
384  struct sockaddr_in6 *sin6_dest = ( ( struct sockaddr_in6 * ) st_dest );
385  struct in6_addr *dest = &sin6_dest->sin6_addr;
386  struct ipv6_miniroute *miniroute;
387 
388  /* Find routing table entry */
389  miniroute = ipv6_route ( sin6_dest->sin6_scope_id, &dest );
390  if ( ! miniroute )
391  return NULL;
392 
393  return miniroute->netdev;
394 }
395 
396 /**
397  * Check that received options can be safely ignored
398  *
399  * @v iphdr IPv6 header
400  * @v options Options extension header
401  * @v len Maximum length of header
402  * @ret rc Return status code
403  */
404 static int ipv6_check_options ( struct ipv6_header *iphdr,
406  size_t len ) {
407  struct ipv6_option *option = options->options;
408  struct ipv6_option *end = ( ( ( void * ) options ) + len );
409 
410  while ( option < end ) {
411  if ( ! IPV6_CAN_IGNORE_OPT ( option->type ) ) {
412  DBGC ( ipv6col ( &iphdr->src ), "IPv6 unrecognised "
413  "option type %#02x:\n", option->type );
414  DBGC_HDA ( ipv6col ( &iphdr->src ), 0,
415  options, len );
416  return -ENOTSUP_OPT;
417  }
418  if ( option->type == IPV6_OPT_PAD1 ) {
419  option = ( ( ( void * ) option ) + 1 );
420  } else {
421  option = ( ( ( void * ) option->value ) + option->len );
422  }
423  }
424  return 0;
425 }
426 
427 /**
428  * Check if fragment matches fragment reassembly buffer
429  *
430  * @v fragment Fragment reassembly buffer
431  * @v iobuf I/O buffer
432  * @v hdrlen Length of non-fragmentable potion of I/O buffer
433  * @ret is_fragment Fragment matches this reassembly buffer
434  */
435 static int ipv6_is_fragment ( struct fragment *fragment,
436  struct io_buffer *iobuf, size_t hdrlen ) {
437  struct ipv6_header *frag_iphdr = fragment->iobuf->data;
438  struct ipv6_fragment_header *frag_fhdr =
440  sizeof ( *frag_fhdr ) );
441  struct ipv6_header *iphdr = iobuf->data;
442  struct ipv6_fragment_header *fhdr =
443  ( iobuf->data + hdrlen - sizeof ( *fhdr ) );
444 
445  return ( ( memcmp ( &iphdr->src, &frag_iphdr->src,
446  sizeof ( iphdr->src ) ) == 0 ) &&
447  ( fhdr->ident == frag_fhdr->ident ) );
448 }
449 
450 /**
451  * Get fragment offset
452  *
453  * @v iobuf I/O buffer
454  * @v hdrlen Length of non-fragmentable potion of I/O buffer
455  * @ret offset Offset
456  */
457 static size_t ipv6_fragment_offset ( struct io_buffer *iobuf, size_t hdrlen ) {
458  struct ipv6_fragment_header *fhdr =
459  ( iobuf->data + hdrlen - sizeof ( *fhdr ) );
460 
461  return ( ntohs ( fhdr->offset_more ) & IPV6_MASK_OFFSET );
462 }
463 
464 /**
465  * Check if more fragments exist
466  *
467  * @v iobuf I/O buffer
468  * @v hdrlen Length of non-fragmentable potion of I/O buffer
469  * @ret more_frags More fragments exist
470  */
471 static int ipv6_more_fragments ( struct io_buffer *iobuf, size_t hdrlen ) {
472  struct ipv6_fragment_header *fhdr =
473  ( iobuf->data + hdrlen - sizeof ( *fhdr ) );
474 
475  return ( fhdr->offset_more & htons ( IPV6_MASK_MOREFRAGS ) );
476 }
477 
478 /** Fragment reassembler */
481  .is_fragment = ipv6_is_fragment,
482  .fragment_offset = ipv6_fragment_offset,
483  .more_fragments = ipv6_more_fragments,
484  .stats = &ipv6_stats,
485 };
486 
487 /**
488  * Calculate IPv6 pseudo-header checksum
489  *
490  * @v iphdr IPv6 header
491  * @v len Payload length
492  * @v next_header Next header type
493  * @v csum Existing checksum
494  * @ret csum Updated checksum
495  */
496 static uint16_t ipv6_pshdr_chksum ( struct ipv6_header *iphdr, size_t len,
497  int next_header, uint16_t csum ) {
498  struct ipv6_pseudo_header pshdr;
499 
500  /* Build pseudo-header */
501  memcpy ( &pshdr.src, &iphdr->src, sizeof ( pshdr.src ) );
502  memcpy ( &pshdr.dest, &iphdr->dest, sizeof ( pshdr.dest ) );
503  pshdr.len = htonl ( len );
504  memset ( pshdr.zero, 0, sizeof ( pshdr.zero ) );
505  pshdr.next_header = next_header;
506 
507  /* Update the checksum value */
508  return tcpip_continue_chksum ( csum, &pshdr, sizeof ( pshdr ) );
509 }
510 
511 /**
512  * Transmit IPv6 packet
513  *
514  * @v iobuf I/O buffer
515  * @v tcpip Transport-layer protocol
516  * @v st_src Source network-layer address
517  * @v st_dest Destination network-layer address
518  * @v netdev Network device to use if no route found, or NULL
519  * @v trans_csum Transport-layer checksum to complete, or NULL
520  * @ret rc Status
521  *
522  * This function expects a transport-layer segment and prepends the
523  * IPv6 header
524  */
525 static int ipv6_tx ( struct io_buffer *iobuf,
527  struct sockaddr_tcpip *st_src,
528  struct sockaddr_tcpip *st_dest,
529  struct net_device *netdev,
530  uint16_t *trans_csum ) {
531  struct sockaddr_in6 *sin6_src = ( ( struct sockaddr_in6 * ) st_src );
532  struct sockaddr_in6 *sin6_dest = ( ( struct sockaddr_in6 * ) st_dest );
533  struct ipv6_miniroute *miniroute;
534  struct ipv6_header *iphdr;
535  struct in6_addr *src = NULL;
536  struct in6_addr *next_hop;
537  uint8_t ll_dest_buf[MAX_LL_ADDR_LEN];
538  const void *ll_dest;
539  size_t len;
540  int rc;
541 
542  /* Update statistics */
544 
545  /* Fill up the IPv6 header, except source address */
546  len = iob_len ( iobuf );
547  iphdr = iob_push ( iobuf, sizeof ( *iphdr ) );
548  memset ( iphdr, 0, sizeof ( *iphdr ) );
549  iphdr->ver_tc_label = htonl ( IPV6_VER );
550  iphdr->len = htons ( len );
551  iphdr->next_header = tcpip_protocol->tcpip_proto;
552  iphdr->hop_limit = IPV6_HOP_LIMIT;
553  memcpy ( &iphdr->dest, &sin6_dest->sin6_addr, sizeof ( iphdr->dest ) );
554 
555  /* Use routing table to identify next hop and transmitting netdev */
556  next_hop = &iphdr->dest;
557  if ( ( miniroute = ipv6_route ( sin6_dest->sin6_scope_id,
558  &next_hop ) ) != NULL ) {
559  src = &miniroute->address;
560  netdev = miniroute->netdev;
561  }
562  if ( ! netdev ) {
563  DBGC ( ipv6col ( &iphdr->dest ), "IPv6 has no route to %s\n",
564  inet6_ntoa ( &iphdr->dest ) );
566  rc = -ENETUNREACH;
567  goto err;
568  }
569  if ( sin6_src && ! IN6_IS_ADDR_UNSPECIFIED ( &sin6_src->sin6_addr ) )
570  src = &sin6_src->sin6_addr;
571  if ( src )
572  memcpy ( &iphdr->src, src, sizeof ( iphdr->src ) );
573 
574  /* Fix up checksums */
575  if ( trans_csum ) {
576  *trans_csum = ipv6_pshdr_chksum ( iphdr, len,
578  *trans_csum );
579  if ( ! *trans_csum )
580  *trans_csum = tcpip_protocol->zero_csum;
581  }
582 
583  /* Print IPv6 header for debugging */
584  DBGC2 ( ipv6col ( &iphdr->dest ), "IPv6 TX %s->",
585  inet6_ntoa ( &iphdr->src ) );
586  DBGC2 ( ipv6col ( &iphdr->dest ), "%s len %zd next %d\n",
587  inet6_ntoa ( &iphdr->dest ), len, iphdr->next_header );
588 
589  /* Calculate link-layer destination address, if possible */
590  if ( IN6_IS_ADDR_MULTICAST ( next_hop ) ) {
591  /* Multicast address */
593  if ( ( rc = netdev->ll_protocol->mc_hash ( AF_INET6, next_hop,
594  ll_dest_buf ) ) !=0){
595  DBGC ( ipv6col ( &iphdr->dest ), "IPv6 could not hash "
596  "multicast %s: %s\n", inet6_ntoa ( next_hop ),
597  strerror ( rc ) );
598  goto err;
599  }
600  ll_dest = ll_dest_buf;
601  } else {
602  /* Unicast address */
603  ll_dest = NULL;
604  }
605 
606  /* Update statistics */
608  ipv6_stats.out_octets += iob_len ( iobuf );
609 
610  /* Hand off to link layer (via NDP if applicable) */
611  if ( ll_dest ) {
612  if ( ( rc = net_tx ( iobuf, netdev, &ipv6_protocol, ll_dest,
613  netdev->ll_addr ) ) != 0 ) {
614  DBGC ( ipv6col ( &iphdr->dest ), "IPv6 could not "
615  "transmit packet via %s: %s\n",
616  netdev->name, strerror ( rc ) );
617  return rc;
618  }
619  } else {
620  if ( ( rc = ndp_tx ( iobuf, netdev, next_hop, &iphdr->src,
621  netdev->ll_addr ) ) != 0 ) {
622  DBGC ( ipv6col ( &iphdr->dest ), "IPv6 could not "
623  "transmit packet via %s: %s\n",
624  netdev->name, strerror ( rc ) );
625  return rc;
626  }
627  }
628 
629  return 0;
630 
631  err:
632  free_iob ( iobuf );
633  return rc;
634 }
635 
636 /**
637  * Process incoming IPv6 packets
638  *
639  * @v iobuf I/O buffer
640  * @v netdev Network device
641  * @v ll_dest Link-layer destination address
642  * @v ll_source Link-layer destination source
643  * @v flags Packet flags
644  * @ret rc Return status code
645  *
646  * This function expects an IPv6 network datagram. It processes the
647  * headers and sends it to the transport layer.
648  */
649 static int ipv6_rx ( struct io_buffer *iobuf, struct net_device *netdev,
650  const void *ll_dest __unused,
651  const void *ll_source __unused,
652  unsigned int flags __unused ) {
653  struct ipv6_header *iphdr = iobuf->data;
654  union ipv6_extension_header *ext;
655  union {
656  struct sockaddr_in6 sin6;
657  struct sockaddr_tcpip st;
658  } src, dest;
659  uint16_t pshdr_csum;
660  size_t len;
661  size_t hdrlen;
662  size_t extlen;
663  int this_header;
664  int next_header;
665  int rc;
666 
667  /* Update statistics */
669  ipv6_stats.in_octets += iob_len ( iobuf );
670  if ( flags & LL_BROADCAST ) {
672  } else if ( flags & LL_MULTICAST ) {
674  }
675 
676  /* Sanity check the IPv6 header */
677  if ( iob_len ( iobuf ) < sizeof ( *iphdr ) ) {
678  DBGC ( ipv6col ( &iphdr->src ), "IPv6 packet too short at %zd "
679  "bytes (min %zd bytes)\n", iob_len ( iobuf ),
680  sizeof ( *iphdr ) );
681  rc = -EINVAL_LEN;
682  goto err_header;
683  }
684  if ( ( iphdr->ver_tc_label & htonl ( IPV6_MASK_VER ) ) !=
685  htonl ( IPV6_VER ) ) {
686  DBGC ( ipv6col ( &iphdr->src ), "IPv6 version %#08x not "
687  "supported\n", ntohl ( iphdr->ver_tc_label ) );
688  rc = -ENOTSUP_VER;
689  goto err_header;
690  }
691 
692  /* Truncate packet to specified length */
693  len = ntohs ( iphdr->len );
694  if ( len > iob_len ( iobuf ) ) {
695  DBGC ( ipv6col ( &iphdr->src ), "IPv6 length too long at %zd "
696  "bytes (packet is %zd bytes)\n", len, iob_len ( iobuf ));
698  rc = -EINVAL_LEN;
699  goto err_other;
700  }
701  iob_unput ( iobuf, ( iob_len ( iobuf ) - len - sizeof ( *iphdr ) ) );
702  hdrlen = sizeof ( *iphdr );
703 
704  /* Print IPv6 header for debugging */
705  DBGC2 ( ipv6col ( &iphdr->src ), "IPv6 RX %s<-",
706  inet6_ntoa ( &iphdr->dest ) );
707  DBGC2 ( ipv6col ( &iphdr->src ), "%s len %zd next %d\n",
708  inet6_ntoa ( &iphdr->src ), len, iphdr->next_header );
709 
710  /* Discard unicast packets not destined for us */
711  if ( ( ! ( flags & LL_MULTICAST ) ) &&
712  ( ! ipv6_has_addr ( netdev, &iphdr->dest ) ) ) {
713  DBGC ( ipv6col ( &iphdr->src ), "IPv6 discarding non-local "
714  "unicast packet for %s\n", inet6_ntoa ( &iphdr->dest ) );
716  rc = -EPIPE;
717  goto err_other;
718  }
719 
720  /* Process any extension headers */
721  next_header = iphdr->next_header;
722  while ( 1 ) {
723 
724  /* Extract extension header */
725  this_header = next_header;
726  ext = ( iobuf->data + hdrlen );
727  extlen = sizeof ( ext->pad );
728  if ( iob_len ( iobuf ) < ( hdrlen + extlen ) ) {
729  DBGC ( ipv6col ( &iphdr->src ), "IPv6 too short for "
730  "extension header type %d at %zd bytes (min "
731  "%zd bytes)\n", this_header,
732  ( iob_len ( iobuf ) - hdrlen ), extlen );
733  rc = -EINVAL_LEN;
734  goto err_header;
735  }
736 
737  /* Determine size of extension header (if applicable) */
738  if ( ( this_header == IPV6_HOPBYHOP ) ||
739  ( this_header == IPV6_DESTINATION ) ||
740  ( this_header == IPV6_ROUTING ) ) {
741  /* Length field is present */
742  extlen += ext->common.len;
743  } else if ( this_header == IPV6_FRAGMENT ) {
744  /* Length field is reserved and ignored (RFC2460) */
745  } else {
746  /* Not an extension header; assume rest is payload */
747  break;
748  }
749  if ( iob_len ( iobuf ) < ( hdrlen + extlen ) ) {
750  DBGC ( ipv6col ( &iphdr->src ), "IPv6 too short for "
751  "extension header type %d at %zd bytes (min "
752  "%zd bytes)\n", this_header,
753  ( iob_len ( iobuf ) - hdrlen ), extlen );
754  rc = -EINVAL_LEN;
755  goto err_header;
756  }
757  hdrlen += extlen;
758  next_header = ext->common.next_header;
759  DBGC2 ( ipv6col ( &iphdr->src ), "IPv6 RX %s<-",
760  inet6_ntoa ( &iphdr->dest ) );
761  DBGC2 ( ipv6col ( &iphdr->src ), "%s ext type %d len %zd next "
762  "%d\n", inet6_ntoa ( &iphdr->src ), this_header,
763  extlen, next_header );
764 
765  /* Process this extension header */
766  if ( ( this_header == IPV6_HOPBYHOP ) ||
767  ( this_header == IPV6_DESTINATION ) ) {
768 
769  /* Check that all options can be ignored */
770  if ( ( rc = ipv6_check_options ( iphdr, &ext->options,
771  extlen ) ) != 0 )
772  goto err_header;
773 
774  } else if ( this_header == IPV6_FRAGMENT ) {
775 
776  /* Reassemble fragments */
777  iobuf = fragment_reassemble ( &ipv6_reassembler, iobuf,
778  &hdrlen );
779  if ( ! iobuf )
780  return 0;
781  iphdr = iobuf->data;
782  }
783  }
784 
785  /* Construct socket address, calculate pseudo-header checksum,
786  * and hand off to transport layer
787  */
788  memset ( &src, 0, sizeof ( src ) );
789  src.sin6.sin6_family = AF_INET6;
790  memcpy ( &src.sin6.sin6_addr, &iphdr->src,
791  sizeof ( src.sin6.sin6_addr ) );
792  src.sin6.sin6_scope_id = netdev->scope_id;
793  memset ( &dest, 0, sizeof ( dest ) );
794  dest.sin6.sin6_family = AF_INET6;
795  memcpy ( &dest.sin6.sin6_addr, &iphdr->dest,
796  sizeof ( dest.sin6.sin6_addr ) );
797  dest.sin6.sin6_scope_id = netdev->scope_id;
798  iob_pull ( iobuf, hdrlen );
799  pshdr_csum = ipv6_pshdr_chksum ( iphdr, iob_len ( iobuf ),
800  next_header, TCPIP_EMPTY_CSUM );
801  if ( ( rc = tcpip_rx ( iobuf, netdev, next_header, &src.st, &dest.st,
802  pshdr_csum, &ipv6_stats ) ) != 0 ) {
803  DBGC ( ipv6col ( &src.sin6.sin6_addr ), "IPv6 received packet "
804  "rejected by stack: %s\n", strerror ( rc ) );
805  return rc;
806  }
807 
808  return 0;
809 
810  err_header:
812  err_other:
813  free_iob ( iobuf );
814  return rc;
815 }
816 
817 /**
818  * Parse IPv6 address
819  *
820  * @v string IPv6 address string
821  * @ret in IPv6 address to fill in
822  * @ret rc Return status code
823  */
824 int inet6_aton ( const char *string, struct in6_addr *in ) {
825  uint16_t *word = in->s6_addr16;
826  uint16_t *end = ( word + ( sizeof ( in->s6_addr16 ) /
827  sizeof ( in->s6_addr16[0] ) ) );
828  uint16_t *pad = NULL;
829  const char *nptr = string;
830  char *endptr;
831  unsigned long value;
832  size_t pad_len;
833  size_t move_len;
834 
835  /* Parse string */
836  while ( 1 ) {
837 
838  /* Parse current word */
839  value = strtoul ( nptr, &endptr, 16 );
840  if ( value > 0xffff ) {
841  DBG ( "IPv6 invalid word value %#lx in \"%s\"\n",
842  value, string );
843  return -EINVAL;
844  }
845  *(word++) = htons ( value );
846 
847  /* Parse separator */
848  if ( ! *endptr )
849  break;
850  if ( *endptr != ':' ) {
851  DBG ( "IPv6 invalid separator '%c' in \"%s\"\n",
852  *endptr, string );
853  return -EINVAL;
854  }
855  if ( ( endptr == nptr ) && ( nptr != string ) ) {
856  if ( pad ) {
857  DBG ( "IPv6 invalid multiple \"::\" in "
858  "\"%s\"\n", string );
859  return -EINVAL;
860  }
861  pad = word;
862  }
863  nptr = ( endptr + 1 );
864 
865  /* Check for overrun */
866  if ( word == end ) {
867  DBG ( "IPv6 too many words in \"%s\"\n", string );
868  return -EINVAL;
869  }
870  }
871 
872  /* Insert padding if specified */
873  if ( pad ) {
874  move_len = ( ( ( void * ) word ) - ( ( void * ) pad ) );
875  pad_len = ( ( ( void * ) end ) - ( ( void * ) word ) );
876  memmove ( ( ( ( void * ) pad ) + pad_len ), pad, move_len );
877  memset ( pad, 0, pad_len );
878  } else if ( word != end ) {
879  DBG ( "IPv6 underlength address \"%s\"\n", string );
880  return -EINVAL;
881  }
882 
883  return 0;
884 }
885 
886 /**
887  * Convert IPv6 address to standard notation
888  *
889  * @v in IPv6 address
890  * @ret string IPv6 address string in canonical format
891  *
892  * RFC5952 defines the canonical format for IPv6 textual representation.
893  */
894 char * inet6_ntoa ( const struct in6_addr *in ) {
895  static char buf[41]; /* ":xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx" */
896  char *out = buf;
897  char *longest_start = NULL;
898  char *start = NULL;
899  int longest_len = 1;
900  int len = 0;
901  char *dest;
902  unsigned int i;
903  uint16_t value;
904 
905  /* Format address, keeping track of longest run of zeros */
906  for ( i = 0 ; i < ( sizeof ( in->s6_addr16 ) /
907  sizeof ( in->s6_addr16[0] ) ) ; i++ ) {
908  value = ntohs ( in->s6_addr16[i] );
909  if ( value == 0 ) {
910  if ( len++ == 0 )
911  start = out;
912  if ( len > longest_len ) {
913  longest_start = start;
914  longest_len = len;
915  }
916  } else {
917  len = 0;
918  }
919  out += sprintf ( out, ":%x", value );
920  }
921 
922  /* Abbreviate longest run of zeros, if applicable */
923  if ( longest_start ) {
924  dest = strcpy ( ( longest_start + 1 ),
925  ( longest_start + ( 2 * longest_len ) ) );
926  if ( dest[0] == '\0' )
927  dest[1] = '\0';
928  dest[0] = ':';
929  }
930  return ( ( longest_start == buf ) ? buf : ( buf + 1 ) );
931 }
932 
933 /**
934  * Transcribe IPv6 address
935  *
936  * @v net_addr IPv6 address
937  * @ret string IPv6 address in standard notation
938  *
939  */
940 static const char * ipv6_ntoa ( const void *net_addr ) {
941  return inet6_ntoa ( net_addr );
942 }
943 
944 /**
945  * Transcribe IPv6 socket address
946  *
947  * @v sa Socket address
948  * @ret string Socket address in standard notation
949  */
950 static const char * ipv6_sock_ntoa ( struct sockaddr *sa ) {
951  static char buf[ 39 /* "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx" */ +
952  1 /* "%" */ + NETDEV_NAME_LEN + 1 /* NUL */ ];
953  struct sockaddr_in6 *sin6 = ( ( struct sockaddr_in6 * ) sa );
954  struct in6_addr *in = &sin6->sin6_addr;
955  struct net_device *netdev;
956  const char *netdev_name;
957 
958  /* Identify network device, if applicable */
961  netdev_name = ( netdev ? netdev->name : "UNKNOWN" );
962  } else {
963  netdev_name = NULL;
964  }
965 
966  /* Format socket address */
967  snprintf ( buf, sizeof ( buf ), "%s%s%s", inet6_ntoa ( in ),
968  ( netdev_name ? "%" : "" ),
969  ( netdev_name ? netdev_name : "" ) );
970  return buf;
971 }
972 
973 /**
974  * Parse IPv6 socket address
975  *
976  * @v string Socket address string
977  * @v sa Socket address to fill in
978  * @ret rc Return status code
979  */
980 static int ipv6_sock_aton ( const char *string, struct sockaddr *sa ) {
981  struct sockaddr_in6 *sin6 = ( ( struct sockaddr_in6 * ) sa );
982  struct in6_addr in;
983  struct net_device *netdev;
984  size_t len;
985  char *tmp;
986  char *in_string;
987  char *netdev_string;
988  int rc;
989 
990  /* Create modifiable copy of string */
991  tmp = strdup ( string );
992  if ( ! tmp ) {
993  rc = -ENOMEM;
994  goto err_alloc;
995  }
996  in_string = tmp;
997 
998  /* Strip surrounding "[...]", if present */
999  len = strlen ( in_string );
1000  if ( ( in_string[0] == '[' ) && ( in_string[ len - 1 ] == ']' ) ) {
1001  in_string[ len - 1 ] = '\0';
1002  in_string++;
1003  }
1004 
1005  /* Split at network device name, if present */
1006  netdev_string = strchr ( in_string, '%' );
1007  if ( netdev_string )
1008  *(netdev_string++) = '\0';
1009 
1010  /* Parse IPv6 address portion */
1011  if ( ( rc = inet6_aton ( in_string, &in ) ) != 0 )
1012  goto err_inet6_aton;
1013 
1014  /* Parse scope ID, if applicable */
1015  if ( netdev_string ) {
1016 
1017  /* Parse explicit network device name, if present */
1018  netdev = find_netdev ( netdev_string );
1019  if ( ! netdev ) {
1020  rc = -ENODEV;
1021  goto err_find_netdev;
1022  }
1024 
1025  } else if ( IN6_IS_ADDR_LINKLOCAL ( &in ) ||
1026  IN6_IS_ADDR_MULTICAST ( &in ) ) {
1027 
1028  /* If no network device is explicitly specified for a
1029  * link-local or multicast address, default to using
1030  * "netX" (if existent).
1031  */
1033  if ( netdev )
1035  }
1036 
1037  /* Copy IPv6 address portion to socket address */
1038  memcpy ( &sin6->sin6_addr, &in, sizeof ( sin6->sin6_addr ) );
1039 
1040  err_find_netdev:
1041  err_inet6_aton:
1042  free ( tmp );
1043  err_alloc:
1044  return rc;
1045 }
1046 
1047 /** IPv6 protocol */
1048 struct net_protocol ipv6_protocol __net_protocol = {
1049  .name = "IPv6",
1050  .net_proto = htons ( ETH_P_IPV6 ),
1051  .net_addr_len = sizeof ( struct in6_addr ),
1052  .rx = ipv6_rx,
1053  .ntoa = ipv6_ntoa,
1054 };
1055 
1056 /** IPv6 TCPIP net protocol */
1057 struct tcpip_net_protocol ipv6_tcpip_protocol __tcpip_net_protocol = {
1058  .name = "IPv6",
1059  .sa_family = AF_INET6,
1060  .header_len = sizeof ( struct ipv6_header ),
1061  .net_protocol = &ipv6_protocol,
1062  .tx = ipv6_tx,
1063  .netdev = ipv6_netdev,
1064 };
1065 
1066 /** IPv6 socket address converter */
1067 struct sockaddr_converter ipv6_sockaddr_converter __sockaddr_converter = {
1068  .family = AF_INET6,
1069  .ntoa = ipv6_sock_ntoa,
1070  .aton = ipv6_sock_aton,
1071 };
1072 
1073 /**
1074  * Parse IPv6 address setting value
1075  *
1076  * @v type Setting type
1077  * @v value Formatted setting value
1078  * @v buf Buffer to contain raw value
1079  * @v len Length of buffer
1080  * @ret len Length of raw value, or negative error
1081  */
1083  const char *value, void *buf, size_t len ) {
1084  struct in6_addr ipv6;
1085  int rc;
1086 
1087  /* Parse IPv6 address */
1088  if ( ( rc = inet6_aton ( value, &ipv6 ) ) != 0 )
1089  return rc;
1090 
1091  /* Copy to buffer */
1092  if ( len > sizeof ( ipv6 ) )
1093  len = sizeof ( ipv6 );
1094  memcpy ( buf, &ipv6, len );
1095 
1096  return ( sizeof ( ipv6 ) );
1097 }
1098 
1099 /**
1100  * Format IPv6 address setting value
1101  *
1102  * @v type Setting type
1103  * @v raw Raw setting value
1104  * @v raw_len Length of raw setting value
1105  * @v buf Buffer to contain formatted value
1106  * @v len Length of buffer
1107  * @ret len Length of formatted value, or negative error
1108  */
1110  const void *raw, size_t raw_len, char *buf,
1111  size_t len ) {
1112  const struct in6_addr *ipv6 = raw;
1113 
1114  if ( raw_len < sizeof ( *ipv6 ) )
1115  return -EINVAL;
1116  return snprintf ( buf, len, "%s", inet6_ntoa ( ipv6 ) );
1117 }
1118 
1119 /** IPv6 settings scope */
1121 
1122 /** IPv6 address setting */
1123 const struct setting ip6_setting __setting ( SETTING_IP6, ip6 ) = {
1124  .name = "ip6",
1125  .description = "IPv6 address",
1126  .type = &setting_type_ipv6,
1127  .scope = &ipv6_settings_scope,
1128 };
1129 
1130 /** IPv6 prefix length setting */
1131 const struct setting len6_setting __setting ( SETTING_IP6, len6 ) = {
1132  .name = "len6",
1133  .description = "IPv6 prefix length",
1134  .type = &setting_type_int8,
1135  .scope = &ipv6_settings_scope,
1136 };
1137 
1138 /** Default gateway setting */
1139 const struct setting gateway6_setting __setting ( SETTING_IP6, gateway6 ) = {
1140  .name = "gateway6",
1141  .description = "IPv6 gateway",
1142  .type = &setting_type_ipv6,
1143  .scope = &ipv6_settings_scope,
1144 };
1145 
1146 /**
1147  * Check applicability of IPv6 link-local address setting
1148  *
1149  * @v settings Settings block
1150  * @v setting Setting to fetch
1151  * @ret applies Setting applies within this settings block
1152  */
1154  const struct setting *setting ) {
1155 
1156  return ( setting->scope == &ipv6_settings_scope );
1157 }
1158 
1159 /**
1160  * Fetch IPv6 link-local address setting
1161  *
1162  * @v settings Settings block
1163  * @v setting Setting to fetch
1164  * @v data Buffer to fill with setting data
1165  * @v len Length of buffer
1166  * @ret len Length of setting data, or negative error
1167  */
1168 static int ipv6_fetch ( struct settings *settings, struct setting *setting,
1169  void *data, size_t len ) {
1170  struct net_device *netdev =
1172  settings.settings );
1173  struct in6_addr ip6;
1174  uint8_t *len6;
1175  int prefix_len;
1176  int rc;
1177 
1178  /* Construct link-local address from EUI-64 as per RFC 2464 */
1179  memset ( &ip6, 0, sizeof ( ip6 ) );
1180  prefix_len = ipv6_link_local ( &ip6, netdev );
1181  if ( prefix_len < 0 ) {
1182  rc = prefix_len;
1183  return rc;
1184  }
1185 
1186  /* Handle setting */
1187  if ( setting_cmp ( setting, &ip6_setting ) == 0 ) {
1188 
1189  /* Return link-local ip6 */
1190  if ( len > sizeof ( ip6 ) )
1191  len = sizeof ( ip6 );
1192  memcpy ( data, &ip6, len );
1193  return sizeof ( ip6 );
1194 
1195  } else if ( setting_cmp ( setting, &len6_setting ) == 0 ) {
1196 
1197  /* Return prefix length */
1198  if ( len ) {
1199  len6 = data;
1200  *len6 = prefix_len;
1201  }
1202  return sizeof ( *len6 );
1203 
1204  }
1205 
1206  return -ENOENT;
1207 }
1208 
1209 /** IPv6 link-local address settings operations */
1211  .applies = ipv6_applies,
1212  .fetch = ipv6_fetch,
1213 };
1214 
1215 /**
1216  * Register IPv6 link-local address settings
1217  *
1218  * @v netdev Network device
1219  * @v priv Private data
1220  * @ret rc Return status code
1221  */
1222 static int ipv6_register_settings ( struct net_device *netdev, void *priv ) {
1223  struct settings *parent = netdev_settings ( netdev );
1224  struct settings *settings = priv;
1225  int rc;
1226 
1227  /* Initialise and register settings */
1231  if ( ( rc = register_settings ( settings, parent,
1232  IPV6_SETTINGS_NAME ) ) != 0 )
1233  return rc;
1234 
1235  return 0;
1236 }
1237 
1238 /** IPv6 network device driver */
1239 struct net_driver ipv6_driver __net_driver = {
1240  .name = "IPv6",
1241  .priv_len = sizeof ( struct settings ),
1242  .probe = ipv6_register_settings,
1243 };
1244 
1245 /**
1246  * Create IPv6 routing table based on configured settings
1247  *
1248  * @v netdev Network device
1249  * @v settings Settings block
1250  * @ret rc Return status code
1251  */
1252 static int ipv6_create_routes ( struct net_device *netdev,
1253  struct settings *settings ) {
1254  struct settings *child;
1255  struct settings *origin;
1256  struct in6_addr ip6_buf;
1257  struct in6_addr gateway6_buf;
1258  struct in6_addr *ip6 = &ip6_buf;
1259  struct in6_addr *gateway6 = &gateway6_buf;
1260  uint8_t len6;
1261  size_t len;
1262  int rc;
1263 
1264  /* First, create routing table for any child settings. We do
1265  * this depth-first and in reverse order so that the end
1266  * result reflects the relative priorities of the settings
1267  * blocks.
1268  */
1269  list_for_each_entry_reverse ( child, &settings->children, siblings )
1270  ipv6_create_routes ( netdev, child );
1271 
1272  /* Fetch IPv6 address, if any */
1273  len = fetch_setting ( settings, &ip6_setting, &origin, NULL,
1274  ip6, sizeof ( *ip6 ) );
1275  if ( ( len != sizeof ( *ip6 ) ) || ( origin != settings ) )
1276  return 0;
1277 
1278  /* Fetch prefix length, if defined */
1279  len = fetch_setting ( settings, &len6_setting, &origin, NULL,
1280  &len6, sizeof ( len6 ) );
1281  if ( ( len != sizeof ( len6 ) ) || ( origin != settings ) )
1282  len6 = 0;
1283  if ( len6 > IPV6_MAX_PREFIX_LEN )
1284  len6 = IPV6_MAX_PREFIX_LEN;
1285 
1286  /* Fetch gateway, if defined */
1287  len = fetch_setting ( settings, &gateway6_setting, &origin, NULL,
1288  gateway6, sizeof ( *gateway6 ) );
1289  if ( ( len != sizeof ( *gateway6 ) ) || ( origin != settings ) )
1290  gateway6 = NULL;
1291 
1292  /* Create or update route */
1293  if ( ( rc = ipv6_add_miniroute ( netdev, ip6, len6, gateway6 ) ) != 0){
1294  DBGC ( netdev, "IPv6 %s could not add route: %s\n",
1295  netdev->name, strerror ( rc ) );
1296  return rc;
1297  }
1298 
1299  return 0;
1300 }
1301 
1302 /**
1303  * Create IPv6 routing table based on configured settings
1304  *
1305  * @ret rc Return status code
1306  */
1307 static int ipv6_create_all_routes ( void ) {
1308  struct ipv6_miniroute *miniroute;
1309  struct ipv6_miniroute *tmp;
1310  struct net_device *netdev;
1311  struct settings *settings;
1312  int rc;
1313 
1314  /* Delete all existing routes */
1315  list_for_each_entry_safe ( miniroute, tmp, &ipv6_miniroutes, list )
1316  ipv6_del_miniroute ( miniroute );
1317 
1318  /* Create routes for each configured network device */
1319  for_each_netdev ( netdev ) {
1321  if ( ( rc = ipv6_create_routes ( netdev, settings ) ) != 0 )
1322  return rc;
1323  }
1324 
1325  return 0;
1326 }
1327 
1328 /** IPv6 settings applicator */
1329 struct settings_applicator ipv6_settings_applicator __settings_applicator = {
1331 };
1332 
1333 /* Drag in objects via ipv6_protocol */
1334 REQUIRING_SYMBOL ( ipv6_protocol );
1335 
1336 /* Drag in ICMPv6 */
1337 REQUIRE_OBJECT ( icmpv6 );
1338 
1339 /* Drag in NDP */
1340 REQUIRE_OBJECT ( ndp );
#define LL_MULTICAST
Packet is a multicast (including broadcast) packet.
Definition: netdevice.h:105
#define IPV6_DEFAULT_PREFIX_LEN
IPv6 default prefix length.
Definition: ipv6.h:29
static int ipv6_applies(struct settings *settings __unused, const struct setting *setting)
Check applicability of IPv6 link-local address setting.
Definition: ipv6.c:1153
#define iob_pull(iobuf, len)
Definition: iobuf.h:102
#define __attribute__(x)
Definition: compiler.h:10
static struct ip_statistics ipv6_stats
IPv6 statistics.
Definition: ipv6.c:63
#define EINVAL
Invalid argument.
Definition: errno.h:428
TCP/IP socket address.
Definition: tcpip.h:75
static const void * src
Definition: string.h:47
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
unsigned short uint16_t
Definition: stdint.h:11
IPv6 header.
Definition: ipv6.h:35
const char * name
Protocol name.
Definition: netdevice.h:66
#define ENOTSUP_OPT
Definition: ipv6.c:55
uint64_t origin
Origin.
Definition: hyperv.h:20
#define AF_INET6
IPv6 Internet addresses.
Definition: socket.h:64
unsigned long in_receives
ipSystemStatsInReceives
Definition: ipstat.h:50
unsigned long strtoul(const char *string, char **endp, int base)
Convert string to numeric value.
Definition: string.c:484
struct in6_addr src
Source address.
Definition: ipv6.h:150
Link-local address.
Definition: ipv6.h:284
__be32 in[4]
Definition: CIB_PRM.h:35
Global address scope.
Definition: ipv6.h:174
An IP system statistics family.
Definition: ipstat.h:169
char * inet6_ntoa(const struct in6_addr *in)
Convert IPv6 address to standard notation.
Definition: ipv6.c:894
struct net_protocol ipv6_protocol __net_protocol
IPv6 protocol.
Definition: ipv6.c:1048
#define TCPIP_EMPTY_CSUM
Empty checksum value.
Definition: tcpip.h:57
#define list_add(new, head)
Add a new entry to the head of a list.
Definition: list.h:69
static struct net_device * ipv6_netdev(struct sockaddr_tcpip *st_dest)
Determine transmitting network device.
Definition: ipv6.c:383
static int ipv6_sock_aton(const char *string, struct sockaddr *sa)
Parse IPv6 socket address.
Definition: ipv6.c:980
Error codes.
IPv6 option-based extension header.
Definition: ipv6.h:80
struct in_addr src
Definition: ip.h:44
#define ENOTSUP_VER
Definition: ipv6.c:49
IPv6 hop-by-hop options header type.
Definition: ipv6.h:136
unsigned long in_addr_errors
ipSystemStatsInAddrErrors
Definition: ipstat.h:76
struct settings * parent
Parent settings block.
Definition: settings.h:138
uint8_t scope
Scope.
Definition: ena.h:18
#define iob_push(iobuf, len)
Definition: iobuf.h:84
int tcpip_rx(struct io_buffer *iobuf, struct net_device *netdev, uint8_t tcpip_proto, struct sockaddr_tcpip *st_src, struct sockaddr_tcpip *st_dest, uint16_t pshdr_csum, struct ip_statistics *stats)
Process a received TCP/IP packet.
Definition: tcpip.c:40
struct ipv6_miniroute * ipv6_route(unsigned int scope_id, struct in6_addr **dest)
Perform IPv6 routing.
Definition: ipv6.c:307
#define IPV6_MAX_PREFIX_LEN
IPv6 maximum prefix length.
Definition: ipv6.h:32
I/O buffers.
A fragment reassembly buffer.
Definition: fragment.h:21
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:146
static unsigned int ipv6_scope(const struct in6_addr *addr)
Determine IPv6 address scope.
Definition: ipv6.c:88
uint64_t address
Base address.
Definition: ena.h:24
uint32_t type
Operating system type.
Definition: ena.h:12
#define sprintf(buf, fmt,...)
Write a formatted string to a buffer.
Definition: stdio.h:36
Link-local address scope.
Definition: ipv6.h:166
static int ipv6_rx(struct io_buffer *iobuf, struct net_device *netdev, const void *ll_dest __unused, const void *ll_source __unused, unsigned int flags __unused)
Process incoming IPv6 packets.
Definition: ipv6.c:649
#define IN6_IS_ADDR_SITELOCAL(addr)
Definition: in.h:74
#define EPIPE
Broken pipe.
Definition: errno.h:619
uint8_t tcpip_proto
Transport-layer protocol number.
Definition: tcpip.h:134
#define IPV6_CAN_IGNORE_OPT(type)
Test if IPv6 option can be safely ignored.
Definition: ipv6.h:77
#define DBGC(...)
Definition: compiler.h:505
static uint32_t ipv6col(struct in6_addr *in)
Determine debugging colour for IPv6 debug messages.
Definition: ipv6.c:78
struct sockaddr_in6 sin6
Definition: syslog.c:58
static uint16_t ipv6_pshdr_chksum(struct ipv6_header *iphdr, size_t len, int next_header, uint16_t csum)
Calculate IPv6 pseudo-header checksum.
Definition: ipv6.c:496
IPv6 type-length-value options.
Definition: ipv6.h:59
#define ENOENT
No such file or directory.
Definition: errno.h:514
int ipv6_add_miniroute(struct net_device *netdev, struct in6_addr *address, unsigned int prefix_len, struct in6_addr *router)
Add IPv6 routing table entry.
Definition: ipv6.c:217
int parse_ipv6_setting(const struct setting_type *type __unused, const char *value, void *buf, size_t len)
Parse IPv6 address setting value.
Definition: ipv6.c:1082
static int ipv6_register_settings(struct net_device *netdev, void *priv)
Register IPv6 link-local address settings.
Definition: ipv6.c:1222
IPv6 destination options header type.
Definition: ipv6.h:144
uint32_t string
Definition: multiboot.h:14
#define ntohl(value)
Definition: byteswap.h:134
A settings applicator.
Definition: settings.h:251
uint16_t sin6_scope_id
Scope ID (part of struct sockaddr_tcpip)
Definition: in.h:132
Pad1.
Definition: ipv6.h:71
#define ntohs(value)
Definition: byteswap.h:136
struct sockaddr_converter ipv6_sockaddr_converter __sockaddr_converter
IPv6 socket address converter.
Definition: ipv6.c:1067
IPv6 fragment header.
Definition: ipv6.h:100
static const char * ipv6_ntoa(const void *net_addr)
Transcribe IPv6 address.
Definition: ipv6.c:940
u32 pad[9]
Padding.
Definition: ar9003_mac.h:90
unsigned int flags
Flags.
Definition: ipv6.h:198
A fragment reassembler.
Definition: fragment.h:35
#define IP_STATISTICS_IPV6
Definition: ipstat.h:185
An IPv4 packet header.
Definition: ip.h:35
REQUIRING_SYMBOL(ipv6_protocol)
#define NETDEV_NAME_LEN
Maximum length of a network device name.
Definition: netdevice.h:340
#define htonl(value)
Definition: byteswap.h:133
unsigned int scope_id
Scope ID.
Definition: netdevice.h:360
A network upper-layer driver.
Definition: netdevice.h:473
static struct settings * netdev_settings(struct net_device *netdev)
Get per-netdevice configuration settings block.
Definition: netdevice.h:583
int inet6_aton(const char *string, struct in6_addr *in)
Parse IPv6 address.
Definition: ipv6.c:824
Organisation-local address scope.
Definition: ipv6.h:172
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:500
A doubly-linked list entry (or list head)
Definition: list.h:18
uint32_t len
Upper-layer packet length.
Definition: ipv6.h:154
An IPv6 address/routing table entry.
Definition: ipv6.h:180
static int ipv6_fetch(struct settings *settings, struct setting *setting, void *data, size_t len)
Fetch IPv6 link-local address setting.
Definition: ipv6.c:1168
const char * name
Name.
Definition: settings.h:28
u32 crc32_le(u32 seed, const void *data, size_t len)
Calculate 32-bit little-endian CRC checksum.
Definition: crc32.c:39
struct sockaddr_tcpip st
Definition: syslog.c:56
uint32_t start
Starting offset.
Definition: netvsc.h:12
struct in6_addr router
Router address.
Definition: ipv6.h:194
unsigned long tmp
Definition: linux_pci.h:63
static int ipv6_is_fragment(struct fragment *fragment, struct io_buffer *iobuf, size_t hdrlen)
Check if fragment matches fragment reassembly buffer.
Definition: ipv6.c:435
const struct setting ip6_setting __setting(SETTING_IP6, ip6)
IPv6 address setting.
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
void ipv6_del_miniroute(struct ipv6_miniroute *miniroute)
Delete IPv6 minirouting table entry.
Definition: ipv6.c:292
#define ENOMEM
Not enough space.
Definition: errno.h:534
void * memcpy(void *dest, const void *src, size_t len) __nonnull
const char * name
Name.
Definition: netdevice.h:475
IP statistics.
unsigned long in_mcast_pkts
ipSystemStatsInMcastPkts
Definition: ipstat.h:150
#define __unused
Declare a variable or data structure as unused.
Definition: compiler.h:573
static int netdev_is_open(struct net_device *netdev)
Check whether or not network device is open.
Definition: netdevice.h:658
unsigned int version
IP version.
Definition: ipstat.h:171
unsigned int scope
Scope.
Definition: ipv6.h:196
#define MAX_LL_ADDR_LEN
Maximum length of a link-layer address.
Definition: netdevice.h:36
Assertions.
IPv6 fragment header type.
Definition: ipv6.h:140
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
struct io_buffer * fragment_reassemble(struct fragment_reassembler *fragments, struct io_buffer *iobuf, size_t *hdrlen)
Reassemble packet.
Definition: fragment.c:88
static void netdev_put(struct net_device *netdev)
Drop reference to network device.
Definition: netdevice.h:572
#define container_of(ptr, type, field)
Get containing structure.
Definition: stddef.h:35
unsigned long out_no_routes
ipSystemStatsOutNoRoutes
Definition: ipstat.h:130
Socket address converter.
Definition: socket.h:115
IPv6 extension header.
Definition: ipv6.h:116
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:431
static struct fragment_reassembler ipv6_reassembler
Fragment reassembler.
Definition: ipv6.c:479
pseudo_bit_t value[0x00020]
Definition: arbel.h:13
#define DBGC_HDA(...)
Definition: compiler.h:506
uint16_t len
Definition: ip.h:38
struct in6_addr dest
Destination address.
Definition: ipv6.h:152
static int ipv6_create_all_routes(void)
Create IPv6 routing table based on configured settings.
Definition: ipv6.c:1307
#define IPV6_SETTINGS_NAME
IPv6 link-local address settings block name.
Definition: ipv6.h:292
#define list_for_each_entry_reverse(pos, head, member)
Iterate over entries in a list in reverse order.
Definition: list.h:444
IPv6 pseudo-header.
Definition: ipv6.h:148
static size_t ipv6_fragment_offset(struct io_buffer *iobuf, size_t hdrlen)
Get fragment offset.
Definition: ipv6.c:457
unsigned long in_truncated_pkts
ipSystemStatsInTruncatedPkts
Definition: ipstat.h:89
static struct net_device * netdev
Definition: gdbudp.c:52
struct net_device * last_opened_netdev(void)
Get most recently opened network device.
Definition: netdevice.c:1047
struct sockaddr sa
Definition: syslog.c:55
__be32 out[4]
Definition: CIB_PRM.h:36
struct io_buffer * iobuf
Reassembled packet.
Definition: fragment.h:25
Transport-network layer interface.
char * strcpy(char *dest, const char *src)
Copy string.
Definition: string.c:346
#define IPV6_HOP_LIMIT
IPv6 maximum hop limit.
Definition: ipv6.h:26
struct list_head list
List of miniroutes.
Definition: ipv6.h:182
IP6 address structure.
Definition: in.h:50
IPv6 routing header type.
Definition: ipv6.h:138
#define IN6_IS_ADDR_LINKLOCAL(addr)
Definition: in.h:70
#define IN6_IS_ADDR_UNSPECIFIED(addr)
Definition: in.h:61
IP system statistics.
Definition: ipstat.h:44
#define list_for_each_entry_safe(pos, tmp, head, member)
Iterate over entries in a list, safe against deletion of the current entry.
Definition: list.h:458
static size_t raw_len
Definition: base16.h:53
Generalized socket address structure.
Definition: socket.h:96
#define iob_unput(iobuf, len)
Definition: iobuf.h:135
int fetch_setting(struct settings *settings, const struct setting *setting, struct settings **origin, struct setting *fetched, void *data, size_t len)
Fetch setting.
Definition: settings.c:666
uint8_t flags
Flags.
Definition: ena.h:18
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
struct refcnt refcnt
Reference counter.
Definition: netdevice.h:354
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:624
#define for_each_netdev(netdev)
Iterate over all network devices.
Definition: netdevice.h:543
char * strchr(const char *src, int character)
Find character within a string.
Definition: string.c:271
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:155
#define IPV6_MASK_VER
IPv6 version mask.
Definition: ipv6.h:23
char * strdup(const char *src)
Duplicate string.
Definition: string.c:393
A network device.
Definition: netdevice.h:352
static struct settings_operations ipv6_settings_operations
IPv6 link-local address settings operations.
Definition: ipv6.c:1210
struct list_head ipv6_miniroutes
List of IPv6 miniroutes.
Definition: ipv6.c:60
#define ENODEV
No such device.
Definition: errno.h:509
size_t strlen(const char *src)
Get length of string.
Definition: string.c:243
struct net_driver ipv6_driver __net_driver
IPv6 network device driver.
Definition: ipv6.c:1239
Settings block operations.
Definition: settings.h:85
A settings block.
Definition: settings.h:132
unsigned char uint8_t
Definition: stdint.h:10
sa_family_t family
Socket address family.
Definition: socket.h:120
unsigned long out_mcast_pkts
ipSystemStatsOutMcastPkts
Definition: ipstat.h:155
A setting scope.
Definition: settings.h:176
struct net_device * netdev
Network device.
Definition: ipv6.h:185
static struct net_device * netdev_get(struct net_device *netdev)
Get reference to network device.
Definition: netdevice.h:561
struct in_addr dest
Definition: ip.h:45
static const char * ipv6_sock_ntoa(struct sockaddr *sa)
Transcribe IPv6 socket address.
Definition: ipv6.c:950
static void ipv6_dump_miniroute(struct ipv6_miniroute *miniroute)
Dump IPv6 routing table entry.
Definition: ipv6.c:122
#define EINVAL_LEN
Definition: ipv6.c:46
unsigned int uint32_t
Definition: stdint.h:12
Site-local address scope.
Definition: ipv6.h:170
IPv6 protocol.
struct net_device * find_netdev_by_scope_id(unsigned int scope_id)
Get network device by scope ID.
Definition: netdevice.c:1010
int(* mc_hash)(unsigned int af, const void *net_addr, void *ll_addr)
Hash multicast address.
Definition: netdevice.h:172
struct settings_applicator ipv6_settings_applicator __settings_applicator
IPv6 settings applicator.
Definition: ipv6.c:1329
void * memmove(void *dest, const void *src, size_t len) __nonnull
A setting.
Definition: settings.h:23
static int ipv6_more_fragments(struct io_buffer *iobuf, size_t hdrlen)
Check if more fragments exist.
Definition: ipv6.c:471
static int ipv6_check_options(struct ipv6_header *iphdr, struct ipv6_options_header *options, size_t len)
Check that received options can be safely ignored.
Definition: ipv6.c:404
uint16_t ext
Extended status.
Definition: ena.h:20
#define LL_BROADCAST
Packet is a broadcast packet.
Definition: netdevice.h:108
A network-layer protocol.
Definition: netdevice.h:64
static unsigned int ipv6_match_len(struct ipv6_miniroute *miniroute, struct in6_addr *address)
Count matching bits of an IPv6 routing table entry prefix.
Definition: ipv6.c:163
A transport-layer protocol of the TCP/IP stack (eg.
Definition: tcpip.h:104
static int ipv6_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 IPv6 packet.
Definition: ipv6.c:525
long pad_len
Definition: bigint.h:30
uint16_t zero_csum
Preferred zero checksum value.
Definition: tcpip.h:128
static int ipv6_create_routes(struct net_device *netdev, struct settings *settings)
Create IPv6 routing table based on configured settings.
Definition: ipv6.c:1252
#define IPV6_VER
IPv6 version.
Definition: ipv6.h:20
int order
Sibling ordering.
Definition: settings.h:148
int format_ipv6_setting(const struct setting_type *type __unused, const void *raw, size_t raw_len, char *buf, size_t len)
Format IPv6 address setting value.
Definition: ipv6.c:1109
char name[NETDEV_NAME_LEN]
Name of this network device.
Definition: netdevice.h:362
int net_tx(struct io_buffer *iobuf, struct net_device *netdev, struct net_protocol *net_protocol, const void *ll_dest, const void *ll_source)
Transmit network-layer packet.
Definition: netdevice.c:1073
#define DBGC2(...)
Definition: compiler.h:522
static struct tlan_private * priv
Definition: tlan.c:224
struct net_device * find_netdev(const char *name)
Get network device by name.
Definition: netdevice.c:988
unsigned long out_requests
ipSystemStatsOutRequests
Definition: ipstat.h:123
void * data
Start of data.
Definition: iobuf.h:48
#define IPV6_MASK_MOREFRAGS
More fragments.
Definition: ipv6.h:113
u32 addr
Definition: sky2.h:8
u8 rx[WPA_TKIP_MIC_KEY_LEN]
MIC key for packets from the AP.
Definition: wpa.h:234
static int ndp_tx(struct io_buffer *iobuf, struct net_device *netdev, const void *net_dest, const void *net_source, const void *ll_source)
Transmit packet, determining link-layer address via NDP.
Definition: ndp.h:195
struct in6_addr src
Source address.
Definition: ipv6.h:45
Routing table entry address is valid.
Definition: ipv6.h:204
unsigned short word
Definition: smc9000.h:39
if(len >=6 *4) __asm__ __volatile__("movsl" if(len >=5 *4) __asm__ __volatile__("movsl" if(len >=4 *4) __asm__ __volatile__("movsl" if(len >=3 *4) __asm__ __volatile__("movsl" if(len >=2 *4) __asm__ __volatile__("movsl" if(len >=1 *4) __asm__ __volatile__("movsl" if((len % 4) >=2) __asm__ __volatile__("movsw" if((len % 2) >=1) __asm__ __volatile__("movsb" return dest
Definition: string.h:150
uint32_t end
Ending offset.
Definition: netvsc.h:18
uint8_t data[48]
Additional event data.
Definition: ena.h:22
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
#define IN6_IS_ADDR_MULTICAST(addr)
Definition: in.h:67
Neighbour discovery protocol.
static int ipv6_link_local(struct in6_addr *addr, struct net_device *netdev)
Construct link-local address via EUI-64.
Definition: ipv6.h:235
__be32 raw[7]
Definition: CIB_PRM.h:28
Routing table entry router address is valid.
Definition: ipv6.h:206
Maximum scope.
Definition: ipv6.h:176
IPv6 socket address.
Definition: in.h:117
int(* apply)(void)
Apply updated settings.
Definition: settings.h:256
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition: vsprintf.c:382
int(* applies)(struct settings *settings, const struct setting *setting)
Check applicability of setting.
Definition: settings.h:98
struct list_head children
Child settings blocks.
Definition: settings.h:142
int register_settings(struct settings *settings, struct settings *parent, const char *name)
Register settings block.
Definition: settings.c:475
#define IPV6_MASK_OFFSET
Fragment offset mask.
Definition: ipv6.h:110
#define IN6_IS_ADDR_ULA(addr)
Definition: in.h:78
A network-layer protocol of the TCP/IP stack (eg.
Definition: tcpip.h:140
#define ETH_P_IPV6
Definition: if_ether.h:22
#define flsl(x)
Find last (i.e.
Definition: strings.h:157
FILE_LICENCE(GPL2_OR_LATER)
unsigned int prefix_len
Prefix length.
Definition: ipv6.h:190
const struct settings_scope ipv6_settings_scope
IPv6 settings scope.
Definition: ipv6.c:1120
uint8_t ll_addr[MAX_LL_ADDR_LEN]
Link-layer address.
Definition: netdevice.h:387
#define SETTING_IP6
IPv6 settings.
Definition: settings.h:67
uint8_t zero[3]
Zero padding.
Definition: ipv6.h:156
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
#define LIST_HEAD_INIT(list)
Initialise a static list head.
Definition: list.h:30
const struct settings_scope * scope
Setting scope (or NULL)
Definition: settings.h:49
uint32_t ident
Identification.
Definition: ipv6.h:106
uint16_t offset_more
Fragment offset (13 bits), reserved, more fragments (1 bit)
Definition: ipv6.h:104
Fragment reassembly.
uint8_t next_header
Next header.
Definition: ipv6.h:158
#define ENETUNREACH
Network unreachable.
Definition: errno.h:488
unsigned long in_hdr_errors
ipSystemStatsInHdrErrors
Definition: ipstat.h:65
struct ip_statistics_family ipv6_statistics_family __ip_statistics_family(IP_STATISTICS_IPV6)
IPv6 statistics family.
int setting_cmp(const struct setting *a, const struct setting *b)
Compare two settings.
Definition: settings.c:1120
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition: string.c:114
uint32_t len
Length.
Definition: ena.h:14
const char * name
Protocol name.
Definition: tcpip.h:142
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
String functions.
struct in6_addr address
IPv6 address (or prefix if no address is defined)
Definition: ipv6.h:188
unsigned long in_bcast_pkts
ipSystemStatsInBcastPkts
Definition: ipstat.h:160
#define htons(value)
Definition: byteswap.h:135
static struct ipv6_miniroute * ipv6_miniroute(struct net_device *netdev, struct in6_addr *address)
Find IPv6 routing table entry for a given address.
Definition: ipv6.c:192
struct in6_addr prefix_mask
IPv6 prefix mask (derived from prefix length)
Definition: ipv6.h:192
A setting type.
Definition: settings.h:191
unsigned long out_octets
ipSystemStatsOutOctets
Definition: ipstat.h:145
uint16_t tcpip_continue_chksum(uint16_t partial, const void *data, size_t len)
Calculate continued TCP/IP checkum.
Definition: x86_tcpip.c:45
struct in6_addr sin6_addr
IPv6 address.
Definition: in.h:134
struct ll_protocol * ll_protocol
Link-layer protocol.
Definition: netdevice.h:372
unsigned long out_transmits
ipSystemStatsOutTransmits
Definition: ipstat.h:138
REQUIRE_OBJECT(icmpv6)
static unsigned int ipv6_multicast_scope(const struct in6_addr *addr)
Get multicast address scope.
Definition: ipv6.h:274
String functions.
unsigned long in_octets
ipSystemStatsInOctets
Definition: ipstat.h:57
struct tcpip_net_protocol ipv6_tcpip_protocol __tcpip_net_protocol
IPv6 TCPIP net protocol.
Definition: ipv6.c:1057
struct list_head list
List of fragment reassembly buffers.
Definition: fragment.h:37
void * memset(void *dest, int character, size_t len) __nonnull
A persistent I/O buffer.
Definition: iobuf.h:33
size_t hdrlen
Length of non-fragmentable portion of reassembled packet.
Definition: fragment.h:27