iPXE
ipv4.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
3  * Copyright (C) 2006 Nikhil Chandru Rao
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  * 02110-1301, USA.
19  *
20  * You can also choose to distribute this program under the terms of
21  * the Unmodified Binary Distribution Licence (as given in the file
22  * COPYING.UBDL), provided that you have satisfied its requirements.
23  */
24 
25 #include <string.h>
26 #include <stdint.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <errno.h>
30 #include <byteswap.h>
31 #include <ipxe/list.h>
32 #include <ipxe/in.h>
33 #include <ipxe/arp.h>
34 #include <ipxe/if_ether.h>
35 #include <ipxe/iobuf.h>
36 #include <ipxe/netdevice.h>
37 #include <ipxe/ip.h>
38 #include <ipxe/tcpip.h>
39 #include <ipxe/dhcp.h>
40 #include <ipxe/settings.h>
41 #include <ipxe/fragment.h>
42 #include <ipxe/ipstat.h>
43 #include <ipxe/profile.h>
44 
45 /** @file
46  *
47  * IPv4 protocol
48  *
49  */
50 
51 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
52 
53 /* Unique IP datagram identification number (high byte) */
55 
56 /** List of IPv4 miniroutes */
58 
59 /** IPv4 statistics */
60 static struct ip_statistics ipv4_stats;
61 
62 /** IPv4 statistics family */
64 ipv4_stats_family __ip_statistics_family ( IP_STATISTICS_IPV4 ) = {
65  .version = 4,
66  .stats = &ipv4_stats,
67 };
68 
69 /** Transmit profiler */
70 static struct profiler ipv4_tx_profiler __profiler = { .name = "ipv4.tx" };
71 
72 /** Receive profiler */
73 static struct profiler ipv4_rx_profiler __profiler = { .name = "ipv4.rx" };
74 
75 /**
76  * Add IPv4 minirouting table entry
77  *
78  * @v netdev Network device
79  * @v address IPv4 address
80  * @v network Subnet address
81  * @v netmask Subnet mask
82  * @v gateway Gateway address (if any)
83  * @ret rc Return status code
84  */
85 static int ipv4_add_miniroute ( struct net_device *netdev,
86  struct in_addr address,
87  struct in_addr network,
88  struct in_addr netmask,
89  struct in_addr gateway ) {
90  struct ipv4_miniroute *miniroute;
91  struct ipv4_miniroute *before;
92  struct in_addr hostmask;
93  struct in_addr broadcast;
94 
95  /* Calculate host mask */
96  if ( gateway.s_addr || IN_IS_SMALL ( netmask.s_addr ) ) {
97  hostmask.s_addr = INADDR_NONE;
98  } else {
99  hostmask.s_addr = ~netmask.s_addr;
100  }
101  broadcast.s_addr = ( network.s_addr | hostmask.s_addr );
102 
103  /* Print debugging information */
104  DBGC ( netdev, "IPv4 add %s", inet_ntoa ( address ) );
105  DBGC ( netdev, " for %s", inet_ntoa ( network ) );
106  DBGC ( netdev, "/%s ", inet_ntoa ( netmask ) );
107  DBGC ( netdev, "bc %s ", inet_ntoa ( broadcast ) );
108  if ( gateway.s_addr )
109  DBGC ( netdev, "gw %s ", inet_ntoa ( gateway ) );
110  DBGC ( netdev, "via %s\n", netdev->name );
111 
112  /* Allocate and populate miniroute structure */
113  miniroute = malloc ( sizeof ( *miniroute ) );
114  if ( ! miniroute ) {
115  DBGC ( netdev, "IPv4 could not add miniroute\n" );
116  return -ENOMEM;
117  }
118 
119  /* Record routing information */
120  miniroute->netdev = netdev_get ( netdev );
121  miniroute->address = address;
122  miniroute->network = network;
123  miniroute->netmask = netmask;
124  miniroute->hostmask = hostmask;
125  miniroute->gateway = gateway;
126 
127  /* Add to routing table ahead of any less specific routes */
129  if ( netmask.s_addr & ~before->netmask.s_addr )
130  break;
131  }
132  list_add_tail ( &miniroute->list, &before->list );
133 
134  return 0;
135 }
136 
137 /**
138  * Add static route minirouting table entries
139  *
140  * @v netdev Network device
141  * @v address IPv4 address
142  * @v routes Static routes
143  * @v len Length of static routes
144  * @ret rc Return status code
145  */
146 static int ipv4_add_static ( struct net_device *netdev, struct in_addr address,
147  const void *routes, size_t len ) {
148  const struct {
149  struct in_addr address;
150  } __attribute__ (( packed )) *encoded;
151  struct in_addr netmask;
152  struct in_addr network;
153  struct in_addr gateway;
154  unsigned int width;
155  unsigned int masklen;
156  size_t remaining;
157  const void *data;
158  int rc;
159 
160  /* Parse and add static routes */
161  for ( data = routes, remaining = len ; remaining ; ) {
162 
163  /* Extract subnet mask width */
164  width = *( ( uint8_t * ) data );
165  data++;
166  remaining--;
167  masklen = ( ( width + 7 ) / 8 );
168 
169  /* Check remaining length */
170  if ( ( masklen + sizeof ( gateway ) ) > remaining ) {
171  DBGC ( netdev, "IPv4 invalid static route:\n" );
172  DBGC_HDA ( netdev, 0, routes, len );
173  return -EINVAL;
174  }
175 
176  /* Calculate subnet mask */
177  if ( width ) {
178  netmask.s_addr = htonl ( -1UL << ( 32 - width ) );
179  } else {
180  netmask.s_addr = 0;
181  }
182 
183  /* Extract network address */
184  encoded = data;
185  network.s_addr = ( encoded->address.s_addr & netmask.s_addr );
186  data += masklen;
187  remaining -= masklen;
188 
189  /* Extract gateway address */
190  encoded = data;
191  gateway.s_addr = encoded->address.s_addr;
192  data += sizeof ( gateway );
193  remaining -= sizeof ( gateway );
194 
195  /* Add route */
196  if ( ( rc = ipv4_add_miniroute ( netdev, address, network,
197  netmask, gateway ) ) != 0 )
198  return rc;
199  }
200 
201  return 0;
202 }
203 
204 /**
205  * Add IPv4 minirouting table entries
206  *
207  * @v netdev Network device
208  * @v address IPv4 address
209  * @ret rc Return status code
210  */
211 static int ipv4_add_miniroutes ( struct net_device *netdev,
212  struct in_addr address ) {
213  struct settings *settings = netdev_settings ( netdev );
214  struct in_addr none = { 0 };
215  struct in_addr netmask;
216  struct in_addr gateway;
217  struct in_addr network;
218  void *routes;
219  int len;
220  int rc;
221 
222  /* Get subnet mask */
223  fetch_ipv4_setting ( settings, &netmask_setting, &netmask );
224 
225  /* Calculate default netmask, if necessary */
226  if ( ! netmask.s_addr ) {
227  if ( IN_IS_CLASSA ( address.s_addr ) ) {
228  netmask.s_addr = INADDR_NET_CLASSA;
229  } else if ( IN_IS_CLASSB ( address.s_addr ) ) {
230  netmask.s_addr = INADDR_NET_CLASSB;
231  } else if ( IN_IS_CLASSC ( address.s_addr ) ) {
232  netmask.s_addr = INADDR_NET_CLASSC;
233  }
234  }
235 
236  /* Get default gateway, if present */
237  fetch_ipv4_setting ( settings, &gateway_setting, &gateway );
238 
239  /* Get static routes, if present */
240  len = fetch_raw_setting_copy ( settings, &static_route_setting,
241  &routes );
242 
243  /* Add local address */
244  network.s_addr = ( address.s_addr & netmask.s_addr );
245  if ( ( rc = ipv4_add_miniroute ( netdev, address, network, netmask,
246  none ) ) != 0 )
247  goto done;
248 
249  /* Add static routes or default gateway, as applicable */
250  if ( len >= 0 ) {
251  if ( ( rc = ipv4_add_static ( netdev, address, routes,
252  len ) ) != 0 )
253  goto done;
254  } else if ( gateway.s_addr ) {
256  gateway ) ) != 0 )
257  goto done;
258  }
259 
260  done:
261  free ( routes );
262  return rc;
263 }
264 
265 /**
266  * Delete IPv4 minirouting table entry
267  *
268  * @v miniroute Routing table entry
269  */
270 static void ipv4_del_miniroute ( struct ipv4_miniroute *miniroute ) {
271  struct net_device *netdev = miniroute->netdev;
272 
273  DBGC ( netdev, "IPv4 del %s", inet_ntoa ( miniroute->address ) );
274  DBGC ( netdev, " for %s", inet_ntoa ( miniroute->network ) );
275  DBGC ( netdev, "/%s ", inet_ntoa ( miniroute->netmask ) );
276  if ( miniroute->gateway.s_addr )
277  DBGC ( netdev, "gw %s ", inet_ntoa ( miniroute->gateway ) );
278  DBGC ( netdev, "via %s\n", miniroute->netdev->name );
279 
280  netdev_put ( miniroute->netdev );
281  list_del ( &miniroute->list );
282  free ( miniroute );
283 }
284 
285 /**
286  * Delete IPv4 minirouting table entries
287  *
288  */
289 static void ipv4_del_miniroutes ( void ) {
290  struct ipv4_miniroute *miniroute;
291  struct ipv4_miniroute *tmp;
292 
293  /* Delete all existing routes */
295  ipv4_del_miniroute ( miniroute );
296 }
297 
298 /**
299  * Perform IPv4 routing
300  *
301  * @v scope_id Destination address scope ID
302  * @v dest Final destination address
303  * @ret dest Next hop destination address
304  * @ret miniroute Routing table entry to use, or NULL if no route
305  *
306  * If the route requires use of a gateway, the next hop destination
307  * address will be overwritten with the gateway address.
308  */
309 struct ipv4_miniroute * ipv4_route ( unsigned int scope_id,
310  struct in_addr *dest ) {
311  struct ipv4_miniroute *miniroute;
312 
313  /* Find first usable route in routing table */
314  list_for_each_entry ( miniroute, &ipv4_miniroutes, list ) {
315 
316  /* Skip closed network devices */
317  if ( ! netdev_is_open ( miniroute->netdev ) )
318  continue;
319 
320  if ( IN_IS_MULTICAST ( dest->s_addr ) ) {
321 
322  /* If destination is non-global, and the scope
323  * ID matches this network device, then use
324  * the first matching route.
325  */
326  if ( miniroute->netdev->scope_id == scope_id )
327  return miniroute;
328 
329  } else {
330 
331  /* If destination is global, then use the
332  * first matching route (via its gateway if
333  * specified).
334  */
335  if ( ( ( dest->s_addr ^ miniroute->network.s_addr )
336  & miniroute->netmask.s_addr ) == 0 ) {
337  if ( miniroute->gateway.s_addr )
338  *dest = miniroute->gateway;
339  return miniroute;
340  }
341  }
342  }
343 
344  return NULL;
345 }
346 
347 /**
348  * Determine transmitting network device
349  *
350  * @v st_dest Destination network-layer address
351  * @ret netdev Transmitting network device, or NULL
352  */
353 static struct net_device * ipv4_netdev ( struct sockaddr_tcpip *st_dest ) {
354  struct sockaddr_in *sin_dest = ( ( struct sockaddr_in * ) st_dest );
355  struct in_addr dest = sin_dest->sin_addr;
356  struct ipv4_miniroute *miniroute;
357 
358  /* Find routing table entry */
359  miniroute = ipv4_route ( sin_dest->sin_scope_id, &dest );
360  if ( ! miniroute )
361  return NULL;
362 
363  return miniroute->netdev;
364 }
365 
366 /**
367  * Check if IPv4 fragment matches fragment reassembly buffer
368  *
369  * @v fragment Fragment reassembly buffer
370  * @v iobuf I/O buffer
371  * @v hdrlen Length of non-fragmentable potion of I/O buffer
372  * @ret is_fragment Fragment matches this reassembly buffer
373  */
374 static int ipv4_is_fragment ( struct fragment *fragment,
375  struct io_buffer *iobuf,
376  size_t hdrlen __unused ) {
377  struct iphdr *frag_iphdr = fragment->iobuf->data;
378  struct iphdr *iphdr = iobuf->data;
379 
380  return ( ( iphdr->src.s_addr == frag_iphdr->src.s_addr ) &&
381  ( iphdr->ident == frag_iphdr->ident ) );
382 }
383 
384 /**
385  * Get IPv4 fragment offset
386  *
387  * @v iobuf I/O buffer
388  * @v hdrlen Length of non-fragmentable potion of I/O buffer
389  * @ret offset Offset
390  */
391 static size_t ipv4_fragment_offset ( struct io_buffer *iobuf,
392  size_t hdrlen __unused ) {
393  struct iphdr *iphdr = iobuf->data;
394 
395  return ( ( ntohs ( iphdr->frags ) & IP_MASK_OFFSET ) << 3 );
396 }
397 
398 /**
399  * Check if more fragments exist
400  *
401  * @v iobuf I/O buffer
402  * @v hdrlen Length of non-fragmentable potion of I/O buffer
403  * @ret more_frags More fragments exist
404  */
405 static int ipv4_more_fragments ( struct io_buffer *iobuf,
406  size_t hdrlen __unused ) {
407  struct iphdr *iphdr = iobuf->data;
408 
409  return ( iphdr->frags & htons ( IP_MASK_MOREFRAGS ) );
410 }
411 
412 /** IPv4 fragment reassembler */
415  .is_fragment = ipv4_is_fragment,
416  .fragment_offset = ipv4_fragment_offset,
417  .more_fragments = ipv4_more_fragments,
418  .stats = &ipv4_stats,
419 };
420 
421 /**
422  * Add IPv4 pseudo-header checksum to existing checksum
423  *
424  * @v iobuf I/O buffer
425  * @v csum Existing checksum
426  * @ret csum Updated checksum
427  */
428 static uint16_t ipv4_pshdr_chksum ( struct io_buffer *iobuf, uint16_t csum ) {
429  struct ipv4_pseudo_header pshdr;
430  struct iphdr *iphdr = iobuf->data;
431  size_t hdrlen = ( ( iphdr->verhdrlen & IP_MASK_HLEN ) * 4 );
432 
433  /* Build pseudo-header */
434  pshdr.src = iphdr->src;
435  pshdr.dest = iphdr->dest;
436  pshdr.zero_padding = 0x00;
437  pshdr.protocol = iphdr->protocol;
438  pshdr.len = htons ( iob_len ( iobuf ) - hdrlen );
439 
440  /* Update the checksum value */
441  return tcpip_continue_chksum ( csum, &pshdr, sizeof ( pshdr ) );
442 }
443 
444 /**
445  * Transmit IP packet
446  *
447  * @v iobuf I/O buffer
448  * @v tcpip Transport-layer protocol
449  * @v st_src Source network-layer address
450  * @v st_dest Destination network-layer address
451  * @v netdev Network device to use if no route found, or NULL
452  * @v trans_csum Transport-layer checksum to complete, or NULL
453  * @ret rc Status
454  *
455  * This function expects a transport-layer segment and prepends the IP header
456  */
457 static int ipv4_tx ( struct io_buffer *iobuf,
459  struct sockaddr_tcpip *st_src,
460  struct sockaddr_tcpip *st_dest,
461  struct net_device *netdev,
462  uint16_t *trans_csum ) {
463  struct iphdr *iphdr = iob_push ( iobuf, sizeof ( *iphdr ) );
464  struct sockaddr_in *sin_src = ( ( struct sockaddr_in * ) st_src );
465  struct sockaddr_in *sin_dest = ( ( struct sockaddr_in * ) st_dest );
466  struct ipv4_miniroute *miniroute;
467  struct in_addr next_hop;
468  struct in_addr hostmask = { .s_addr = INADDR_NONE };
469  uint8_t ll_dest_buf[MAX_LL_ADDR_LEN];
470  const void *ll_dest;
471  int rc;
472 
473  /* Start profiling */
474  profile_start ( &ipv4_tx_profiler );
475 
476  /* Update statistics */
478 
479  /* Fill up the IP header, except source address */
480  memset ( iphdr, 0, sizeof ( *iphdr ) );
481  iphdr->verhdrlen = ( IP_VER | ( sizeof ( *iphdr ) / 4 ) );
482  iphdr->service = IP_TOS;
483  iphdr->len = htons ( iob_len ( iobuf ) );
484  iphdr->ttl = IP_TTL;
486  iphdr->dest = sin_dest->sin_addr;
487 
488  /* Use routing table to identify next hop and transmitting netdev */
489  next_hop = iphdr->dest;
490  if ( sin_src )
491  iphdr->src = sin_src->sin_addr;
492  if ( ( next_hop.s_addr != INADDR_BROADCAST ) &&
493  ( ( miniroute = ipv4_route ( sin_dest->sin_scope_id,
494  &next_hop ) ) != NULL ) ) {
495  iphdr->src = miniroute->address;
496  hostmask = miniroute->hostmask;
497  netdev = miniroute->netdev;
498  }
499  if ( ! netdev ) {
500  DBGC ( sin_dest->sin_addr, "IPv4 has no route to %s\n",
501  inet_ntoa ( iphdr->dest ) );
503  rc = -ENETUNREACH;
504  goto err;
505  }
506 
507  /* (Ab)use the "ident" field to convey metadata about the
508  * network device statistics into packet traces. Useful for
509  * extracting debug information from non-debug builds.
510  */
511  iphdr->ident = htons ( ( (++next_ident_high) << 8 ) |
512  ( ( netdev->rx_stats.bad & 0xf ) << 4 ) |
513  ( ( netdev->rx_stats.good & 0xf ) << 0 ) );
514 
515  /* Fix up checksums */
516  if ( trans_csum ) {
517  *trans_csum = ipv4_pshdr_chksum ( iobuf, *trans_csum );
518  if ( ! *trans_csum )
519  *trans_csum = tcpip_protocol->zero_csum;
520  }
521  iphdr->chksum = tcpip_chksum ( iphdr, sizeof ( *iphdr ) );
522 
523  /* Print IP4 header for debugging */
524  DBGC2 ( sin_dest->sin_addr, "IPv4 TX %s->", inet_ntoa ( iphdr->src ) );
525  DBGC2 ( sin_dest->sin_addr, "%s len %d proto %d id %04x csum %04x\n",
526  inet_ntoa ( iphdr->dest ), ntohs ( iphdr->len ),
527  iphdr->protocol, ntohs ( iphdr->ident ),
528  ntohs ( iphdr->chksum ) );
529 
530  /* Calculate link-layer destination address, if possible */
531  if ( ( ( ~next_hop.s_addr ) & hostmask.s_addr ) == 0 ) {
532  /* Broadcast address */
534  ll_dest = netdev->ll_broadcast;
535  } else if ( IN_IS_MULTICAST ( next_hop.s_addr ) ) {
536  /* Multicast address */
538  if ( ( rc = netdev->ll_protocol->mc_hash ( AF_INET, &next_hop,
539  ll_dest_buf ) ) !=0){
540  DBGC ( sin_dest->sin_addr, "IPv4 could not hash "
541  "multicast %s: %s\n",
542  inet_ntoa ( next_hop ), strerror ( rc ) );
543  goto err;
544  }
545  ll_dest = ll_dest_buf;
546  } else {
547  /* Unicast address */
548  ll_dest = NULL;
549  }
550 
551  /* Update statistics */
553  ipv4_stats.out_octets += iob_len ( iobuf );
554 
555  /* Hand off to link layer (via ARP if applicable) */
556  if ( ll_dest ) {
557  if ( ( rc = net_tx ( iobuf, netdev, &ipv4_protocol, ll_dest,
558  netdev->ll_addr ) ) != 0 ) {
559  DBGC ( sin_dest->sin_addr, "IPv4 could not transmit "
560  "packet via %s: %s\n",
561  netdev->name, strerror ( rc ) );
562  return rc;
563  }
564  } else {
565  if ( ( rc = arp_tx ( iobuf, netdev, &ipv4_protocol, &next_hop,
566  &iphdr->src, netdev->ll_addr ) ) != 0 ) {
567  DBGC ( sin_dest->sin_addr, "IPv4 could not transmit "
568  "packet via %s: %s\n",
569  netdev->name, strerror ( rc ) );
570  return rc;
571  }
572  }
573 
574  profile_stop ( &ipv4_tx_profiler );
575  return 0;
576 
577  err:
578  free_iob ( iobuf );
579  return rc;
580 }
581 
582 /**
583  * Check if network device has any IPv4 address
584  *
585  * @v netdev Network device
586  * @ret has_any_addr Network device has any IPv4 address
587  */
589  struct ipv4_miniroute *miniroute;
590 
591  list_for_each_entry ( miniroute, &ipv4_miniroutes, list ) {
592  if ( miniroute->netdev == netdev )
593  return 1;
594  }
595  return 0;
596 }
597 
598 /**
599  * Check if network device has a specific IPv4 address
600  *
601  * @v netdev Network device
602  * @v addr IPv4 address
603  * @ret has_addr Network device has this IPv4 address
604  */
605 static int ipv4_has_addr ( struct net_device *netdev, struct in_addr addr ) {
606  struct ipv4_miniroute *miniroute;
607 
608  list_for_each_entry ( miniroute, &ipv4_miniroutes, list ) {
609  if ( ( miniroute->netdev == netdev ) &&
610  ( miniroute->address.s_addr == addr.s_addr ) ) {
611  /* Found matching address */
612  return 1;
613  }
614  }
615  return 0;
616 }
617 
618 /**
619  * Process incoming packets
620  *
621  * @v iobuf I/O buffer
622  * @v netdev Network device
623  * @v ll_dest Link-layer destination address
624  * @v ll_source Link-layer destination source
625  * @v flags Packet flags
626  * @ret rc Return status code
627  *
628  * This function expects an IP4 network datagram. It processes the headers
629  * and sends it to the transport layer.
630  */
631 static int ipv4_rx ( struct io_buffer *iobuf,
632  struct net_device *netdev,
633  const void *ll_dest __unused,
634  const void *ll_source __unused,
635  unsigned int flags ) {
636  struct iphdr *iphdr = iobuf->data;
637  size_t hdrlen;
638  size_t len;
639  union {
640  struct sockaddr_in sin;
641  struct sockaddr_tcpip st;
642  } src, dest;
643  uint16_t csum;
644  uint16_t pshdr_csum;
645  int rc;
646 
647  /* Start profiling */
648  profile_start ( &ipv4_rx_profiler );
649 
650  /* Update statistics */
652  ipv4_stats.in_octets += iob_len ( iobuf );
653  if ( flags & LL_BROADCAST ) {
655  } else if ( flags & LL_MULTICAST ) {
657  }
658 
659  /* Sanity check the IPv4 header */
660  if ( iob_len ( iobuf ) < sizeof ( *iphdr ) ) {
661  DBGC ( iphdr->src, "IPv4 packet too short at %zd bytes (min "
662  "%zd bytes)\n", iob_len ( iobuf ), sizeof ( *iphdr ) );
663  goto err_header;
664  }
665  if ( ( iphdr->verhdrlen & IP_MASK_VER ) != IP_VER ) {
666  DBGC ( iphdr->src, "IPv4 version %#02x not supported\n",
667  iphdr->verhdrlen );
668  goto err_header;
669  }
670  hdrlen = ( ( iphdr->verhdrlen & IP_MASK_HLEN ) * 4 );
671  if ( hdrlen < sizeof ( *iphdr ) ) {
672  DBGC ( iphdr->src, "IPv4 header too short at %zd bytes (min "
673  "%zd bytes)\n", hdrlen, sizeof ( *iphdr ) );
674  goto err_header;
675  }
676  if ( hdrlen > iob_len ( iobuf ) ) {
677  DBGC ( iphdr->src, "IPv4 header too long at %zd bytes "
678  "(packet is %zd bytes)\n", hdrlen, iob_len ( iobuf ) );
679  goto err_header;
680  }
681  if ( ( csum = tcpip_chksum ( iphdr, hdrlen ) ) != 0 ) {
682  DBGC ( iphdr->src, "IPv4 checksum incorrect (is %04x "
683  "including checksum field, should be 0000)\n", csum );
684  goto err_header;
685  }
686  len = ntohs ( iphdr->len );
687  if ( len < hdrlen ) {
688  DBGC ( iphdr->src, "IPv4 length too short at %zd bytes "
689  "(header is %zd bytes)\n", len, hdrlen );
690  goto err_header;
691  }
692  if ( len > iob_len ( iobuf ) ) {
693  DBGC ( iphdr->src, "IPv4 length too long at %zd bytes "
694  "(packet is %zd bytes)\n", len, iob_len ( iobuf ) );
696  goto err_other;
697  }
698 
699  /* Truncate packet to correct length */
700  iob_unput ( iobuf, ( iob_len ( iobuf ) - len ) );
701 
702  /* Print IPv4 header for debugging */
703  DBGC2 ( iphdr->src, "IPv4 RX %s<-", inet_ntoa ( iphdr->dest ) );
704  DBGC2 ( iphdr->src, "%s len %d proto %d id %04x csum %04x\n",
706  ntohs ( iphdr->ident ), ntohs ( iphdr->chksum ) );
707 
708  /* Discard unicast packets not destined for us */
709  if ( ( ! ( flags & LL_MULTICAST ) ) &&
710  ( iphdr->dest.s_addr != INADDR_BROADCAST ) &&
712  ( ! ipv4_has_addr ( netdev, iphdr->dest ) ) ) {
713  DBGC ( iphdr->src, "IPv4 discarding non-local unicast packet "
714  "for %s\n", inet_ntoa ( iphdr->dest ) );
716  goto err_other;
717  }
718 
719  /* Perform fragment reassembly if applicable */
721  /* Pass the fragment to fragment_reassemble() which returns
722  * either a fully reassembled I/O buffer or NULL.
723  */
724  iobuf = fragment_reassemble ( &ipv4_reassembler, iobuf,
725  &hdrlen );
726  if ( ! iobuf )
727  return 0;
728  iphdr = iobuf->data;
729  }
730 
731  /* Construct socket addresses, calculate pseudo-header
732  * checksum, and hand off to transport layer
733  */
734  memset ( &src, 0, sizeof ( src ) );
735  src.sin.sin_family = AF_INET;
736  src.sin.sin_addr = iphdr->src;
737  memset ( &dest, 0, sizeof ( dest ) );
738  dest.sin.sin_family = AF_INET;
739  dest.sin.sin_addr = iphdr->dest;
740  pshdr_csum = ipv4_pshdr_chksum ( iobuf, TCPIP_EMPTY_CSUM );
741  iob_pull ( iobuf, hdrlen );
742  if ( ( rc = tcpip_rx ( iobuf, netdev, iphdr->protocol, &src.st,
743  &dest.st, pshdr_csum, &ipv4_stats ) ) != 0 ) {
744  DBGC ( src.sin.sin_addr, "IPv4 received packet rejected by "
745  "stack: %s\n", strerror ( rc ) );
746  return rc;
747  }
748 
749  profile_stop ( &ipv4_rx_profiler );
750  return 0;
751 
752  err_header:
754  err_other:
755  free_iob ( iobuf );
756  return -EINVAL;
757 }
758 
759 /**
760  * Check existence of IPv4 address for ARP
761  *
762  * @v netdev Network device
763  * @v net_addr Network-layer address
764  * @ret rc Return status code
765  */
766 static int ipv4_arp_check ( struct net_device *netdev, const void *net_addr ) {
767  const struct in_addr *address = net_addr;
768 
769  if ( ipv4_has_addr ( netdev, *address ) )
770  return 0;
771 
772  return -ENOENT;
773 }
774 
775 /**
776  * Parse IPv4 address
777  *
778  * @v string IPv4 address string
779  * @ret in IPv4 address to fill in
780  * @ret ok IPv4 address is valid
781  *
782  * Note that this function returns nonzero iff the address is valid,
783  * to match the standard BSD API function of the same name. Unlike
784  * most other iPXE functions, a zero therefore indicates failure.
785  */
786 int inet_aton ( const char *string, struct in_addr *in ) {
787  const char *separator = "...";
788  uint8_t *byte = ( ( uint8_t * ) in );
789  char *endp;
790  unsigned long value;
791 
792  while ( 1 ) {
793  value = strtoul ( string, &endp, 0 );
794  if ( string == endp )
795  return 0;
796  if ( value > 0xff )
797  return 0;
798  *(byte++) = value;
799  if ( *endp != *separator )
800  return 0;
801  if ( ! *(separator++) )
802  return 1;
803  string = ( endp + 1 );
804  }
805 }
806 
807 /**
808  * Convert IPv4 address to dotted-quad notation
809  *
810  * @v in IPv4 address
811  * @ret string IPv4 address in dotted-quad notation
812  */
813 char * inet_ntoa ( struct in_addr in ) {
814  static char buf[16]; /* "xxx.xxx.xxx.xxx" */
815  uint8_t *bytes = ( uint8_t * ) &in;
816 
817  sprintf ( buf, "%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3] );
818  return buf;
819 }
820 
821 /**
822  * Transcribe IPv4 address
823  *
824  * @v net_addr IPv4 address
825  * @ret string IPv4 address in dotted-quad notation
826  *
827  */
828 static const char * ipv4_ntoa ( const void *net_addr ) {
829  return inet_ntoa ( * ( ( struct in_addr * ) net_addr ) );
830 }
831 
832 /**
833  * Transcribe IPv4 socket address
834  *
835  * @v sa Socket address
836  * @ret string Socket address in standard notation
837  */
838 static const char * ipv4_sock_ntoa ( struct sockaddr *sa ) {
839  struct sockaddr_in *sin = ( ( struct sockaddr_in * ) sa );
840 
841  return inet_ntoa ( sin->sin_addr );
842 }
843 
844 /**
845  * Parse IPv4 socket address
846  *
847  * @v string Socket address string
848  * @v sa Socket address to fill in
849  * @ret rc Return status code
850  */
851 static int ipv4_sock_aton ( const char *string, struct sockaddr *sa ) {
852  struct sockaddr_in *sin = ( ( struct sockaddr_in * ) sa );
853  struct in_addr in;
854 
855  if ( inet_aton ( string, &in ) ) {
856  sin->sin_addr = in;
857  return 0;
858  }
859  return -EINVAL;
860 }
861 
862 /** IPv4 protocol */
863 struct net_protocol ipv4_protocol __net_protocol = {
864  .name = "IP",
865  .net_proto = htons ( ETH_P_IP ),
866  .net_addr_len = sizeof ( struct in_addr ),
867  .rx = ipv4_rx,
868  .ntoa = ipv4_ntoa,
869 };
870 
871 /** IPv4 TCPIP net protocol */
872 struct tcpip_net_protocol ipv4_tcpip_protocol __tcpip_net_protocol = {
873  .name = "IPv4",
874  .sa_family = AF_INET,
875  .header_len = sizeof ( struct iphdr ),
876  .net_protocol = &ipv4_protocol,
877  .tx = ipv4_tx,
878  .netdev = ipv4_netdev,
879 };
880 
881 /** IPv4 ARP protocol */
882 struct arp_net_protocol ipv4_arp_protocol __arp_net_protocol = {
883  .net_protocol = &ipv4_protocol,
884  .check = ipv4_arp_check,
885 };
886 
887 /** IPv4 socket address converter */
888 struct sockaddr_converter ipv4_sockaddr_converter __sockaddr_converter = {
889  .family = AF_INET,
890  .ntoa = ipv4_sock_ntoa,
891  .aton = ipv4_sock_aton,
892 };
893 
894 /******************************************************************************
895  *
896  * Settings
897  *
898  ******************************************************************************
899  */
900 
901 /**
902  * Parse IPv4 address setting value
903  *
904  * @v type Setting type
905  * @v value Formatted setting value
906  * @v buf Buffer to contain raw value
907  * @v len Length of buffer
908  * @ret len Length of raw value, or negative error
909  */
911  const char *value, void *buf, size_t len ) {
912  struct in_addr ipv4;
913 
914  /* Parse IPv4 address */
915  if ( inet_aton ( value, &ipv4 ) == 0 )
916  return -EINVAL;
917 
918  /* Copy to buffer */
919  if ( len > sizeof ( ipv4 ) )
920  len = sizeof ( ipv4 );
921  memcpy ( buf, &ipv4, len );
922 
923  return ( sizeof ( ipv4 ) );
924 }
925 
926 /**
927  * Format IPv4 address setting value
928  *
929  * @v type Setting type
930  * @v raw Raw setting value
931  * @v raw_len Length of raw setting value
932  * @v buf Buffer to contain formatted value
933  * @v len Length of buffer
934  * @ret len Length of formatted value, or negative error
935  */
937  const void *raw, size_t raw_len, char *buf,
938  size_t len ) {
939  const struct in_addr *ipv4 = raw;
940 
941  if ( raw_len < sizeof ( *ipv4 ) )
942  return -EINVAL;
943  return snprintf ( buf, len, "%s", inet_ntoa ( *ipv4 ) );
944 }
945 
946 /** IPv4 address setting */
947 const struct setting ip_setting __setting ( SETTING_IP4, ip ) = {
948  .name = "ip",
949  .description = "IP address",
950  .tag = DHCP_EB_YIADDR,
951  .type = &setting_type_ipv4,
952 };
953 
954 /** IPv4 subnet mask setting */
955 const struct setting netmask_setting __setting ( SETTING_IP4, netmask ) = {
956  .name = "netmask",
957  .description = "Subnet mask",
958  .tag = DHCP_SUBNET_MASK,
959  .type = &setting_type_ipv4,
960 };
961 
962 /** Default gateway setting */
963 const struct setting gateway_setting __setting ( SETTING_IP4, gateway ) = {
964  .name = "gateway",
965  .description = "Default gateway",
966  .tag = DHCP_ROUTERS,
967  .type = &setting_type_ipv4,
968 };
969 
970 /** Classless static routes setting */
971 const struct setting static_route_setting __setting ( SETTING_IP4,
972  static_routes ) = {
973  .name = "static-routes",
974  .description = "Static routes",
975  .tag = DHCP_STATIC_ROUTES,
976  .type = &setting_type_hex,
977 };
978 
979 /**
980  * Send gratuitous ARP, if applicable
981  *
982  * @v netdev Network device
983  * @v address IPv4 address
984  * @ret rc Return status code
985  */
986 static int ipv4_gratuitous_arp ( struct net_device *netdev,
987  struct in_addr address ) {
988  int rc;
989 
990  /* Do nothing if network device already has this IPv4 address */
991  if ( ipv4_has_addr ( netdev, address ) )
992  return 0;
993 
994  /* Transmit gratuitous ARP */
995  DBGC ( netdev, "IPv4 sending gratuitous ARP for %s via %s\n",
996  inet_ntoa ( address ), netdev->name );
997  if ( ( rc = arp_tx_request ( netdev, &ipv4_protocol, &address,
998  &address ) ) != 0 ) {
999  DBGC ( netdev, "IPv4 could not transmit gratuitous ARP: %s\n",
1000  strerror ( rc ) );
1001  /* Treat failures as non-fatal */
1002  }
1003 
1004  return 0;
1005 }
1006 
1007 /**
1008  * Process IPv4 network device settings
1009  *
1010  * @v apply Application method
1011  * @ret rc Return status code
1012  */
1013 static int ipv4_settings ( int ( * apply ) ( struct net_device *netdev,
1014  struct in_addr address ) ) {
1015  struct net_device *netdev;
1016  struct settings *settings;
1017  struct in_addr address;
1018  int rc;
1019 
1020  /* Process settings for each network device */
1021  for_each_netdev ( netdev ) {
1022 
1023  /* Get network device settings */
1025 
1026  /* Get IPv4 address */
1027  fetch_ipv4_setting ( settings, &ip_setting, &address );
1028  if ( ! address.s_addr )
1029  continue;
1030 
1031  /* Apply settings */
1032  if ( ( rc = apply ( netdev, address ) ) != 0 )
1033  return rc;
1034  }
1035 
1036  return 0;
1037 }
1038 
1039 /**
1040  * Create IPv4 routing table based on configured settings
1041  *
1042  * @ret rc Return status code
1043  */
1044 static int ipv4_apply_routes ( void ) {
1045  int rc;
1046 
1047  /* Send gratuitous ARPs for any new IPv4 addresses */
1049 
1050  /* Delete all existing routes */
1052 
1053  /* Create routes for each configured network device */
1054  if ( ( rc = ipv4_settings ( ipv4_add_miniroutes ) ) != 0 )
1055  return rc;
1056 
1057  return 0;
1058 }
1059 
1060 /** IPv4 settings applicator */
1061 struct settings_applicator ipv4_settings_applicator __settings_applicator = {
1063 };
1064 
1065 /* Drag in objects via ipv4_protocol */
1066 REQUIRING_SYMBOL ( ipv4_protocol );
1067 
1068 /* Drag in ICMPv4 */
1069 REQUIRE_OBJECT ( icmpv4 );
#define LL_MULTICAST
Packet is a multicast (including broadcast) packet.
Definition: netdevice.h:105
#define SETTING_IP4
IPv4 settings.
Definition: settings.h:65
#define iob_pull(iobuf, len)
Definition: iobuf.h:106
Address Resolution Protocol.
struct in_addr netmask
Subnet mask.
Definition: ip.h:98
#define __attribute__(x)
Definition: compiler.h:10
#define EINVAL
Invalid argument.
Definition: errno.h:428
TCP/IP socket address.
Definition: tcpip.h:75
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
struct sockaddr_converter ipv4_sockaddr_converter __sockaddr_converter
IPv4 socket address converter.
Definition: ipv4.c:888
unsigned short uint16_t
Definition: stdint.h:11
#define IN_IS_CLASSA(addr)
Definition: in.h:27
const char * name
Protocol name.
Definition: netdevice.h:66
static const char * ipv4_sock_ntoa(struct sockaddr *sa)
Transcribe IPv4 socket address.
Definition: ipv4.c:838
Dynamic Host Configuration Protocol.
static void ipv4_del_miniroute(struct ipv4_miniroute *miniroute)
Delete IPv4 minirouting table entry.
Definition: ipv4.c:270
struct net_protocol ipv4_protocol __net_protocol
IPv4 protocol.
Definition: ipv4.c:863
static int ipv4_has_addr(struct net_device *netdev, struct in_addr addr)
Check if network device has a specific IPv4 address.
Definition: ipv4.c:605
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
__be32 in[4]
Definition: CIB_PRM.h:35
struct list_head list
List of miniroutes.
Definition: ip.h:65
An IP system statistics family.
Definition: ipstat.h:169
#define TCPIP_EMPTY_CSUM
Empty checksum value.
Definition: tcpip.h:57
int fetch_raw_setting_copy(struct settings *settings, const struct setting *setting, void **data)
Fetch value of setting.
Definition: settings.c:821
static int ipv4_gratuitous_arp(struct net_device *netdev, struct in_addr address)
Send gratuitous ARP, if applicable.
Definition: ipv4.c:986
#define IP_STATISTICS_IPV4
Definition: ipstat.h:184
#define IP_VER
Definition: ip.h:22
Error codes.
static void ipv4_del_miniroutes(void)
Delete IPv4 minirouting table entries.
Definition: ipv4.c:289
struct in_addr src
Definition: ip.h:44
unsigned long in_addr_errors
ipSystemStatsInAddrErrors
Definition: ipstat.h:76
#define iob_push(iobuf, len)
Definition: iobuf.h:88
#define DHCP_ROUTERS
Routers.
Definition: dhcp.h:68
int fetch_ipv4_setting(struct settings *settings, const struct setting *setting, struct in_addr *inp)
Fetch value of IPv4 address setting.
Definition: settings.c:912
uint8_t zero_padding
Definition: ip.h:52
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
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:152
REQUIRING_SYMBOL(ipv4_protocol)
uint64_t address
Base address.
Definition: ena.h:24
const struct setting ip_setting __setting(SETTING_IP4, ip)
IPv4 address setting.
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
uint8_t tcpip_proto
Transport-layer protocol number.
Definition: tcpip.h:134
#define ETH_P_IP
Definition: if_ether.h:18
struct net_device * netdev
Network device.
Definition: ip.h:72
#define IN_IS_CLASSB(addr)
Definition: in.h:29
#define DBGC(...)
Definition: compiler.h:505
struct settings_applicator ipv4_settings_applicator __settings_applicator
IPv4 settings applicator.
Definition: ipv4.c:1061
int32_t before
Initial microcode version.
Definition: ucode.h:16
#define ENOENT
No such file or directory.
Definition: errno.h:514
const uint8_t * ll_broadcast
Link-layer broadcast address.
Definition: netdevice.h:389
uint16_t chksum
Definition: ip.h:43
A settings applicator.
Definition: settings.h:251
IP protocol.
IPv4 socket address.
Definition: in.h:84
#define ntohs(value)
Definition: byteswap.h:136
A data structure for storing profiling information.
Definition: profile.h:26
uint16_t ident
Definition: ip.h:39
uint16_t frags
Definition: ip.h:40
A fragment reassembler.
Definition: fragment.h:35
static void profile_stop(struct profiler *profiler)
Stop profiling.
Definition: profile.h:173
int format_ipv4_setting(const struct setting_type *type __unused, const void *raw, size_t raw_len, char *buf, size_t len)
Format IPv4 address setting value.
Definition: ipv4.c:936
An IPv4 packet header.
Definition: ip.h:35
#define htonl(value)
Definition: byteswap.h:133
struct in_addr address
IPv4 address.
Definition: ip.h:83
unsigned int scope_id
Scope ID.
Definition: netdevice.h:360
static struct settings * netdev_settings(struct net_device *netdev)
Get per-netdevice configuration settings block.
Definition: netdevice.h:586
struct in_addr hostmask
Host mask.
Definition: ip.h:133
static int ipv4_add_static(struct net_device *netdev, struct in_addr address, const void *routes, size_t len)
Add static route minirouting table entries.
Definition: ipv4.c:146
REQUIRE_OBJECT(icmpv4)
A doubly-linked list entry (or list head)
Definition: list.h:18
static int ipv4_arp_check(struct net_device *netdev, const void *net_addr)
Check existence of IPv4 address for ARP.
Definition: ipv4.c:766
static int arp_tx(struct io_buffer *iobuf, struct net_device *netdev, struct net_protocol *net_protocol, const void *net_dest, const void *net_source, const void *ll_source)
Transmit packet, determining link-layer address via ARP.
Definition: arp.h:51
const char * name
Name.
Definition: settings.h:28
#define IN_IS_SMALL(mask)
Definition: in.h:36
#define IP_TTL
Definition: ip.h:32
struct sockaddr_tcpip st
Definition: syslog.c:57
static const char * ipv4_ntoa(const void *net_addr)
Transcribe IPv4 address.
Definition: ipv4.c:828
unsigned long tmp
Definition: linux_pci.h:64
struct ip_statistics_family ipv4_stats_family __ip_statistics_family(IP_STATISTICS_IPV4)
IPv4 statistics family.
A network-layer protocol that relies upon ARP.
Definition: arp.h:17
uint16_t sin_scope_id
Scope ID (part of struct sockaddr_tcpip)
Definition: in.h:98
struct tcpip_net_protocol ipv4_tcpip_protocol __tcpip_net_protocol
IPv4 TCPIP net protocol.
Definition: ipv4.c:872
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
uint16_t len
Definition: ip.h:54
#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: profile.h:28
struct in_addr dest
Definition: ip.h:51
IP statistics.
static int ipv4_more_fragments(struct io_buffer *iobuf, size_t hdrlen __unused)
Check if more fragments exist.
Definition: ipv4.c:405
unsigned long in_mcast_pkts
ipSystemStatsInMcastPkts
Definition: ipstat.h:150
static size_t ipv4_fragment_offset(struct io_buffer *iobuf, size_t hdrlen __unused)
Get IPv4 fragment offset.
Definition: ipv4.c:391
static int netdev_is_open(struct net_device *netdev)
Check whether or not network device is open.
Definition: netdevice.h:661
unsigned int version
IP version.
Definition: ipstat.h:171
int ipv4_has_any_addr(struct net_device *netdev)
Check if network device has any IPv4 address.
Definition: ipv4.c:588
#define MAX_LL_ADDR_LEN
Maximum length of a link-layer address.
Definition: netdevice.h:36
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:575
unsigned long out_no_routes
ipSystemStatsOutNoRoutes
Definition: ipstat.h:130
Socket address converter.
Definition: socket.h:115
static const void * src
Definition: string.h:47
An IPv4 address/routing table entry.
Definition: ip.h:63
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:431
pseudo_bit_t value[0x00020]
Definition: arbel.h:13
#define DBGC_HDA(...)
Definition: compiler.h:506
#define __unused
Declare a variable or data structure as unused.
Definition: compiler.h:573
uint16_t len
Definition: ip.h:38
struct in_addr gateway
Gateway address, or zero.
Definition: ip.h:108
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition: list.h:93
ring len
Length.
Definition: dwmac.h:231
#define DHCP_STATIC_ROUTES
Classless static routes.
Definition: dhcp.h:348
struct net_protocol * net_protocol
Network-layer protocol.
Definition: arp.h:19
#define INADDR_NET_CLASSC
Definition: in.h:25
unsigned long in_truncated_pkts
ipSystemStatsInTruncatedPkts
Definition: ipstat.h:89
static struct net_device * netdev
Definition: gdbudp.c:52
struct sockaddr sa
Definition: syslog.c:56
uint8_t verhdrlen
Definition: ip.h:36
static struct fragment_reassembler ipv4_reassembler
IPv4 fragment reassembler.
Definition: ipv4.c:413
struct io_buffer * iobuf
Reassembled packet.
Definition: fragment.h:25
Transport-network layer interface.
#define INADDR_BROADCAST
Definition: in.h:21
#define IP_MASK_MOREFRAGS
Definition: ip.h:27
static void profile_start(struct profiler *profiler)
Start profiling.
Definition: profile.h:160
Profiling.
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
static uint16_t ipv4_pshdr_chksum(struct io_buffer *iobuf, uint16_t csum)
Add IPv4 pseudo-header checksum to existing checksum.
Definition: ipv4.c:428
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
int arp_tx_request(struct net_device *netdev, struct net_protocol *net_protocol, const void *net_dest, const void *net_source)
Transmit ARP request.
Definition: arp.c:59
Linked lists.
#define DHCP_SUBNET_MASK
Subnet mask.
Definition: dhcp.h:65
Configuration settings.
static size_t raw_len
Definition: base16.h:53
static struct profiler ipv4_tx_profiler __profiler
Transmit profiler.
Definition: ipv4.c:70
Generalized socket address structure.
Definition: socket.h:96
#define iob_unput(iobuf, len)
Definition: iobuf.h:139
uint8_t flags
Flags.
Definition: ena.h:18
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 ipv4_miniroute * ipv4_route(unsigned int scope_id, struct in_addr *dest)
Perform IPv4 routing.
Definition: ipv4.c:309
IP address structure.
Definition: in.h:41
#define for_each_netdev(netdev)
Iterate over all network devices.
Definition: netdevice.h:546
struct net_device_stats rx_stats
RX statistics.
Definition: netdevice.h:425
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:159
static struct net_device * ipv4_netdev(struct sockaddr_tcpip *st_dest)
Determine transmitting network device.
Definition: ipv4.c:353
uint32_t addr
Buffer address.
Definition: dwmac.h:20
static struct ip_statistics ipv4_stats
IPv4 statistics.
Definition: ipv4.c:60
unsigned int bad
Count of error completions.
Definition: netdevice.h:295
int inet_aton(const char *string, struct in_addr *in)
Parse IPv4 address.
Definition: ipv4.c:786
A network device.
Definition: netdevice.h:352
struct arp_net_protocol ipv4_arp_protocol __arp_net_protocol
IPv4 ARP protocol.
Definition: ipv4.c:882
IP4_t ip
Destination IP address.
Definition: pxe_api.h:58
char * inet_ntoa(struct in_addr in)
Convert IPv4 address to dotted-quad notation.
Definition: ipv4.c:813
#define IP_MASK_VER
Definition: ip.h:23
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
static struct net_device * netdev_get(struct net_device *netdev)
Get reference to network device.
Definition: netdevice.h:564
struct in_addr dest
Definition: ip.h:45
struct in_addr network
Subnet network address.
Definition: ip.h:92
static int ipv4_rx(struct io_buffer *iobuf, struct net_device *netdev, const void *ll_dest __unused, const void *ll_source __unused, unsigned int flags)
Process incoming packets.
Definition: ipv4.c:631
An IPv4 pseudo header.
Definition: ip.h:49
void * malloc(size_t size)
Allocate memory.
Definition: malloc.c:620
int(* mc_hash)(unsigned int af, const void *net_addr, void *ll_addr)
Hash multicast address.
Definition: netdevice.h:172
#define IP_MASK_OFFSET
Definition: ip.h:25
struct list_head ipv4_miniroutes
List of IPv4 miniroutes.
Definition: ipv4.c:57
A setting.
Definition: settings.h:23
static int ipv4_settings(int(*apply)(struct net_device *netdev, struct in_addr address))
Process IPv4 network device settings.
Definition: ipv4.c:1013
#define LL_BROADCAST
Packet is a broadcast packet.
Definition: netdevice.h:108
A network-layer protocol.
Definition: netdevice.h:64
static int ipv4_add_miniroute(struct net_device *netdev, struct in_addr address, struct in_addr network, struct in_addr netmask, struct in_addr gateway)
Add IPv4 minirouting table entry.
Definition: ipv4.c:85
uint32_t s_addr
Definition: in.h:42
A transport-layer protocol of the TCP/IP stack (eg.
Definition: tcpip.h:104
Network device management.
static int ipv4_add_miniroutes(struct net_device *netdev, struct in_addr address)
Add IPv4 minirouting table entries.
Definition: ipv4.c:211
unsigned long out_bcast_pkts
ipSystemStatsOutBcastPkts
Definition: ipstat.h:165
uint16_t zero_csum
Preferred zero checksum value.
Definition: tcpip.h:128
struct in_addr sin_addr
IPv4 address.
Definition: in.h:100
#define IP_MASK_HLEN
Definition: ip.h:24
uint8_t protocol
Definition: ip.h:42
static int ipv4_is_fragment(struct fragment *fragment, struct io_buffer *iobuf, size_t hdrlen __unused)
Check if IPv4 fragment matches fragment reassembly buffer.
Definition: ipv4.c:374
unsigned int good
Count of successful completions.
Definition: netdevice.h:293
char name[NETDEV_NAME_LEN]
Name of this network device.
Definition: netdevice.h:362
#define IP_TOS
Definition: ip.h:31
#define DHCP_EB_YIADDR
"Your" IP address
Definition: dhcp.h:373
int parse_ipv4_setting(const struct setting_type *type __unused, const char *value, void *buf, size_t len)
Parse IPv4 address setting value.
Definition: ipv4.c:910
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
#define INADDR_NET_CLASSA
Definition: in.h:23
unsigned long out_requests
ipSystemStatsOutRequests
Definition: ipstat.h:123
void * data
Start of data.
Definition: iobuf.h:52
uint8_t protocol
Definition: ip.h:53
u8 rx[WPA_TKIP_MIC_KEY_LEN]
MIC key for packets from the AP.
Definition: wpa.h:234
static int ipv4_sock_aton(const char *string, struct sockaddr *sa)
Parse IPv4 socket address.
Definition: ipv4.c:851
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
uint8_t data[48]
Additional event data.
Definition: ena.h:22
#define INADDR_NET_CLASSB
Definition: in.h:24
__be32 raw[7]
Definition: CIB_PRM.h:28
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
A network-layer protocol of the TCP/IP stack (eg.
Definition: tcpip.h:140
#define IN_IS_MULTICAST(addr)
Definition: in.h:33
static int ipv4_apply_routes(void)
Create IPv4 routing table based on configured settings.
Definition: ipv4.c:1044
struct sockaddr_in sin
Definition: syslog.c:58
uint8_t ll_addr[MAX_LL_ADDR_LEN]
Link-layer address.
Definition: netdevice.h:387
#define IN_IS_CLASSC(addr)
Definition: in.h:31
#define LIST_HEAD_INIT(list)
Initialise a static list head.
Definition: list.h:30
uint8_t ttl
Definition: ip.h:41
struct in_addr src
Definition: ip.h:50
uint8_t bytes[64]
Definition: ib_mad.h:16
static uint8_t next_ident_high
Definition: ipv4.c:54
Fragment reassembly.
uint16_t tcpip_chksum(const void *data, size_t len)
Calculate TCP/IP checkum.
Definition: tcpip.c:203
static int ipv4_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 IP packet.
Definition: ipv4.c:457
Definition: 3c5x9.c:35
uint8_t service
Definition: ip.h:37
#define ENETUNREACH
Network unreachable.
Definition: errno.h:488
unsigned long in_hdr_errors
ipSystemStatsInHdrErrors
Definition: ipstat.h:65
const char * name
Protocol name.
Definition: tcpip.h:142
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
#define INADDR_NONE
Definition: in.h:19
String functions.
unsigned long in_bcast_pkts
ipSystemStatsInBcastPkts
Definition: ipstat.h:160
#define htons(value)
Definition: byteswap.h:135
struct bofm_section_header done
Definition: bofm_test.c:46
#define AF_INET
IPv4 Internet addresses.
Definition: socket.h:63
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 ll_protocol * ll_protocol
Link-layer protocol.
Definition: netdevice.h:372
unsigned long out_transmits
ipSystemStatsOutTransmits
Definition: ipstat.h:138
unsigned long in_octets
ipSystemStatsInOctets
Definition: ipstat.h:57
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:37