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