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 netmask Subnet mask
81  * @v gateway Gateway address (if any)
82  * @ret rc Return status code
83  */
84 static int add_ipv4_miniroute ( struct net_device *netdev,
85  struct in_addr address, struct in_addr netmask,
86  struct in_addr gateway ) {
87  struct ipv4_miniroute *miniroute;
88  struct in_addr hostmask;
89  struct in_addr broadcast;
90 
91  /* Calculate host mask */
92  hostmask.s_addr = ( IN_IS_SMALL ( netmask.s_addr ) ?
93  INADDR_NONE : ~netmask.s_addr );
94  broadcast.s_addr = ( address.s_addr | hostmask.s_addr );
95 
96  /* Print debugging information */
97  DBGC ( netdev, "IPv4 add %s", inet_ntoa ( address ) );
98  DBGC ( netdev, "/%s ", inet_ntoa ( netmask ) );
99  DBGC ( netdev, "bc %s ", inet_ntoa ( broadcast ) );
100  if ( gateway.s_addr )
101  DBGC ( netdev, "gw %s ", inet_ntoa ( gateway ) );
102  DBGC ( netdev, "via %s\n", netdev->name );
103 
104  /* Allocate and populate miniroute structure */
105  miniroute = malloc ( sizeof ( *miniroute ) );
106  if ( ! miniroute ) {
107  DBGC ( netdev, "IPv4 could not add miniroute\n" );
108  return -ENOMEM;
109  }
110 
111  /* Record routing information */
112  miniroute->netdev = netdev_get ( netdev );
113  miniroute->address = address;
114  miniroute->netmask = netmask;
115  miniroute->hostmask = hostmask;
116  miniroute->gateway = gateway;
117 
118  /* Add to end of list if we have a gateway, otherwise
119  * to start of list.
120  */
121  if ( gateway.s_addr ) {
122  list_add_tail ( &miniroute->list, &ipv4_miniroutes );
123  } else {
124  list_add ( &miniroute->list, &ipv4_miniroutes );
125  }
126 
127  return 0;
128 }
129 
130 /**
131  * Delete IPv4 minirouting table entry
132  *
133  * @v miniroute Routing table entry
134  */
135 static void del_ipv4_miniroute ( struct ipv4_miniroute *miniroute ) {
136  struct net_device *netdev = miniroute->netdev;
137 
138  DBGC ( netdev, "IPv4 del %s", inet_ntoa ( miniroute->address ) );
139  DBGC ( netdev, "/%s ", inet_ntoa ( miniroute->netmask ) );
140  if ( miniroute->gateway.s_addr )
141  DBGC ( netdev, "gw %s ", inet_ntoa ( miniroute->gateway ) );
142  DBGC ( netdev, "via %s\n", miniroute->netdev->name );
143 
144  netdev_put ( miniroute->netdev );
145  list_del ( &miniroute->list );
146  free ( miniroute );
147 }
148 
149 /**
150  * Perform IPv4 routing
151  *
152  * @v scope_id Destination address scope ID
153  * @v dest Final destination address
154  * @ret dest Next hop destination address
155  * @ret miniroute Routing table entry to use, or NULL if no route
156  *
157  * If the route requires use of a gateway, the next hop destination
158  * address will be overwritten with the gateway address.
159  */
160 static struct ipv4_miniroute * ipv4_route ( unsigned int scope_id,
161  struct in_addr *dest ) {
162  struct ipv4_miniroute *miniroute;
163 
164  /* Find first usable route in routing table */
165  list_for_each_entry ( miniroute, &ipv4_miniroutes, list ) {
166 
167  /* Skip closed network devices */
168  if ( ! netdev_is_open ( miniroute->netdev ) )
169  continue;
170 
171  if ( IN_IS_MULTICAST ( dest->s_addr ) ) {
172 
173  /* If destination is non-global, and the scope ID
174  * matches this network device, then use this route.
175  */
176  if ( miniroute->netdev->scope_id == scope_id )
177  return miniroute;
178 
179  } else {
180 
181  /* If destination is an on-link global
182  * address, then use this route.
183  */
184  if ( ( ( dest->s_addr ^ miniroute->address.s_addr )
185  & miniroute->netmask.s_addr ) == 0 )
186  return miniroute;
187 
188  /* If destination is an off-link global
189  * address, and we have a default gateway,
190  * then use this route.
191  */
192  if ( miniroute->gateway.s_addr ) {
193  *dest = miniroute->gateway;
194  return miniroute;
195  }
196  }
197  }
198 
199  return NULL;
200 }
201 
202 /**
203  * Determine transmitting network device
204  *
205  * @v st_dest Destination network-layer address
206  * @ret netdev Transmitting network device, or NULL
207  */
208 static struct net_device * ipv4_netdev ( struct sockaddr_tcpip *st_dest ) {
209  struct sockaddr_in *sin_dest = ( ( struct sockaddr_in * ) st_dest );
210  struct in_addr dest = sin_dest->sin_addr;
211  struct ipv4_miniroute *miniroute;
212 
213  /* Find routing table entry */
214  miniroute = ipv4_route ( sin_dest->sin_scope_id, &dest );
215  if ( ! miniroute )
216  return NULL;
217 
218  return miniroute->netdev;
219 }
220 
221 /**
222  * Check if IPv4 fragment matches fragment reassembly buffer
223  *
224  * @v fragment Fragment reassembly buffer
225  * @v iobuf I/O buffer
226  * @v hdrlen Length of non-fragmentable potion of I/O buffer
227  * @ret is_fragment Fragment matches this reassembly buffer
228  */
229 static int ipv4_is_fragment ( struct fragment *fragment,
230  struct io_buffer *iobuf,
231  size_t hdrlen __unused ) {
232  struct iphdr *frag_iphdr = fragment->iobuf->data;
233  struct iphdr *iphdr = iobuf->data;
234 
235  return ( ( iphdr->src.s_addr == frag_iphdr->src.s_addr ) &&
236  ( iphdr->ident == frag_iphdr->ident ) );
237 }
238 
239 /**
240  * Get IPv4 fragment offset
241  *
242  * @v iobuf I/O buffer
243  * @v hdrlen Length of non-fragmentable potion of I/O buffer
244  * @ret offset Offset
245  */
246 static size_t ipv4_fragment_offset ( struct io_buffer *iobuf,
247  size_t hdrlen __unused ) {
248  struct iphdr *iphdr = iobuf->data;
249 
250  return ( ( ntohs ( iphdr->frags ) & IP_MASK_OFFSET ) << 3 );
251 }
252 
253 /**
254  * Check if more fragments exist
255  *
256  * @v iobuf I/O buffer
257  * @v hdrlen Length of non-fragmentable potion of I/O buffer
258  * @ret more_frags More fragments exist
259  */
260 static int ipv4_more_fragments ( struct io_buffer *iobuf,
261  size_t hdrlen __unused ) {
262  struct iphdr *iphdr = iobuf->data;
263 
264  return ( iphdr->frags & htons ( IP_MASK_MOREFRAGS ) );
265 }
266 
267 /** IPv4 fragment reassembler */
270  .is_fragment = ipv4_is_fragment,
271  .fragment_offset = ipv4_fragment_offset,
272  .more_fragments = ipv4_more_fragments,
273  .stats = &ipv4_stats,
274 };
275 
276 /**
277  * Add IPv4 pseudo-header checksum to existing checksum
278  *
279  * @v iobuf I/O buffer
280  * @v csum Existing checksum
281  * @ret csum Updated checksum
282  */
283 static uint16_t ipv4_pshdr_chksum ( struct io_buffer *iobuf, uint16_t csum ) {
284  struct ipv4_pseudo_header pshdr;
285  struct iphdr *iphdr = iobuf->data;
286  size_t hdrlen = ( ( iphdr->verhdrlen & IP_MASK_HLEN ) * 4 );
287 
288  /* Build pseudo-header */
289  pshdr.src = iphdr->src;
290  pshdr.dest = iphdr->dest;
291  pshdr.zero_padding = 0x00;
292  pshdr.protocol = iphdr->protocol;
293  pshdr.len = htons ( iob_len ( iobuf ) - hdrlen );
294 
295  /* Update the checksum value */
296  return tcpip_continue_chksum ( csum, &pshdr, sizeof ( pshdr ) );
297 }
298 
299 /**
300  * Transmit IP packet
301  *
302  * @v iobuf I/O buffer
303  * @v tcpip Transport-layer protocol
304  * @v st_src Source network-layer address
305  * @v st_dest Destination network-layer address
306  * @v netdev Network device to use if no route found, or NULL
307  * @v trans_csum Transport-layer checksum to complete, or NULL
308  * @ret rc Status
309  *
310  * This function expects a transport-layer segment and prepends the IP header
311  */
312 static int ipv4_tx ( struct io_buffer *iobuf,
314  struct sockaddr_tcpip *st_src,
315  struct sockaddr_tcpip *st_dest,
316  struct net_device *netdev,
317  uint16_t *trans_csum ) {
318  struct iphdr *iphdr = iob_push ( iobuf, sizeof ( *iphdr ) );
319  struct sockaddr_in *sin_src = ( ( struct sockaddr_in * ) st_src );
320  struct sockaddr_in *sin_dest = ( ( struct sockaddr_in * ) st_dest );
321  struct ipv4_miniroute *miniroute;
322  struct in_addr next_hop;
323  struct in_addr hostmask = { .s_addr = INADDR_NONE };
324  uint8_t ll_dest_buf[MAX_LL_ADDR_LEN];
325  const void *ll_dest;
326  int rc;
327 
328  /* Start profiling */
329  profile_start ( &ipv4_tx_profiler );
330 
331  /* Update statistics */
333 
334  /* Fill up the IP header, except source address */
335  memset ( iphdr, 0, sizeof ( *iphdr ) );
336  iphdr->verhdrlen = ( IP_VER | ( sizeof ( *iphdr ) / 4 ) );
337  iphdr->service = IP_TOS;
338  iphdr->len = htons ( iob_len ( iobuf ) );
339  iphdr->ttl = IP_TTL;
341  iphdr->dest = sin_dest->sin_addr;
342 
343  /* Use routing table to identify next hop and transmitting netdev */
344  next_hop = iphdr->dest;
345  if ( sin_src )
346  iphdr->src = sin_src->sin_addr;
347  if ( ( next_hop.s_addr != INADDR_BROADCAST ) &&
348  ( ( miniroute = ipv4_route ( sin_dest->sin_scope_id,
349  &next_hop ) ) != NULL ) ) {
350  iphdr->src = miniroute->address;
351  hostmask = miniroute->hostmask;
352  netdev = miniroute->netdev;
353  }
354  if ( ! netdev ) {
355  DBGC ( sin_dest->sin_addr, "IPv4 has no route to %s\n",
356  inet_ntoa ( iphdr->dest ) );
358  rc = -ENETUNREACH;
359  goto err;
360  }
361 
362  /* (Ab)use the "ident" field to convey metadata about the
363  * network device statistics into packet traces. Useful for
364  * extracting debug information from non-debug builds.
365  */
366  iphdr->ident = htons ( ( (++next_ident_high) << 8 ) |
367  ( ( netdev->rx_stats.bad & 0xf ) << 4 ) |
368  ( ( netdev->rx_stats.good & 0xf ) << 0 ) );
369 
370  /* Fix up checksums */
371  if ( trans_csum ) {
372  *trans_csum = ipv4_pshdr_chksum ( iobuf, *trans_csum );
373  if ( ! *trans_csum )
374  *trans_csum = tcpip_protocol->zero_csum;
375  }
376  iphdr->chksum = tcpip_chksum ( iphdr, sizeof ( *iphdr ) );
377 
378  /* Print IP4 header for debugging */
379  DBGC2 ( sin_dest->sin_addr, "IPv4 TX %s->", inet_ntoa ( iphdr->src ) );
380  DBGC2 ( sin_dest->sin_addr, "%s len %d proto %d id %04x csum %04x\n",
381  inet_ntoa ( iphdr->dest ), ntohs ( iphdr->len ),
382  iphdr->protocol, ntohs ( iphdr->ident ),
383  ntohs ( iphdr->chksum ) );
384 
385  /* Calculate link-layer destination address, if possible */
386  if ( ( ( ~next_hop.s_addr ) & hostmask.s_addr ) == 0 ) {
387  /* Broadcast address */
389  ll_dest = netdev->ll_broadcast;
390  } else if ( IN_IS_MULTICAST ( next_hop.s_addr ) ) {
391  /* Multicast address */
393  if ( ( rc = netdev->ll_protocol->mc_hash ( AF_INET, &next_hop,
394  ll_dest_buf ) ) !=0){
395  DBGC ( sin_dest->sin_addr, "IPv4 could not hash "
396  "multicast %s: %s\n",
397  inet_ntoa ( next_hop ), strerror ( rc ) );
398  goto err;
399  }
400  ll_dest = ll_dest_buf;
401  } else {
402  /* Unicast address */
403  ll_dest = NULL;
404  }
405 
406  /* Update statistics */
408  ipv4_stats.out_octets += iob_len ( iobuf );
409 
410  /* Hand off to link layer (via ARP if applicable) */
411  if ( ll_dest ) {
412  if ( ( rc = net_tx ( iobuf, netdev, &ipv4_protocol, ll_dest,
413  netdev->ll_addr ) ) != 0 ) {
414  DBGC ( sin_dest->sin_addr, "IPv4 could not transmit "
415  "packet via %s: %s\n",
416  netdev->name, strerror ( rc ) );
417  return rc;
418  }
419  } else {
420  if ( ( rc = arp_tx ( iobuf, netdev, &ipv4_protocol, &next_hop,
421  &iphdr->src, netdev->ll_addr ) ) != 0 ) {
422  DBGC ( sin_dest->sin_addr, "IPv4 could not transmit "
423  "packet via %s: %s\n",
424  netdev->name, strerror ( rc ) );
425  return rc;
426  }
427  }
428 
429  profile_stop ( &ipv4_tx_profiler );
430  return 0;
431 
432  err:
433  free_iob ( iobuf );
434  return rc;
435 }
436 
437 /**
438  * Check if network device has any IPv4 address
439  *
440  * @v netdev Network device
441  * @ret has_any_addr Network device has any IPv4 address
442  */
444  struct ipv4_miniroute *miniroute;
445 
446  list_for_each_entry ( miniroute, &ipv4_miniroutes, list ) {
447  if ( miniroute->netdev == netdev )
448  return 1;
449  }
450  return 0;
451 }
452 
453 /**
454  * Check if network device has a specific IPv4 address
455  *
456  * @v netdev Network device
457  * @v addr IPv4 address
458  * @ret has_addr Network device has this IPv4 address
459  */
460 static int ipv4_has_addr ( struct net_device *netdev, struct in_addr addr ) {
461  struct ipv4_miniroute *miniroute;
462 
463  list_for_each_entry ( miniroute, &ipv4_miniroutes, list ) {
464  if ( ( miniroute->netdev == netdev ) &&
465  ( miniroute->address.s_addr == addr.s_addr ) ) {
466  /* Found matching address */
467  return 1;
468  }
469  }
470  return 0;
471 }
472 
473 /**
474  * Process incoming packets
475  *
476  * @v iobuf I/O buffer
477  * @v netdev Network device
478  * @v ll_dest Link-layer destination address
479  * @v ll_source Link-layer destination source
480  * @v flags Packet flags
481  * @ret rc Return status code
482  *
483  * This function expects an IP4 network datagram. It processes the headers
484  * and sends it to the transport layer.
485  */
486 static int ipv4_rx ( struct io_buffer *iobuf,
487  struct net_device *netdev,
488  const void *ll_dest __unused,
489  const void *ll_source __unused,
490  unsigned int flags ) {
491  struct iphdr *iphdr = iobuf->data;
492  size_t hdrlen;
493  size_t len;
494  union {
495  struct sockaddr_in sin;
496  struct sockaddr_tcpip st;
497  } src, dest;
498  uint16_t csum;
499  uint16_t pshdr_csum;
500  int rc;
501 
502  /* Start profiling */
503  profile_start ( &ipv4_rx_profiler );
504 
505  /* Update statistics */
507  ipv4_stats.in_octets += iob_len ( iobuf );
508  if ( flags & LL_BROADCAST ) {
510  } else if ( flags & LL_MULTICAST ) {
512  }
513 
514  /* Sanity check the IPv4 header */
515  if ( iob_len ( iobuf ) < sizeof ( *iphdr ) ) {
516  DBGC ( iphdr->src, "IPv4 packet too short at %zd bytes (min "
517  "%zd bytes)\n", iob_len ( iobuf ), sizeof ( *iphdr ) );
518  goto err_header;
519  }
520  if ( ( iphdr->verhdrlen & IP_MASK_VER ) != IP_VER ) {
521  DBGC ( iphdr->src, "IPv4 version %#02x not supported\n",
522  iphdr->verhdrlen );
523  goto err_header;
524  }
525  hdrlen = ( ( iphdr->verhdrlen & IP_MASK_HLEN ) * 4 );
526  if ( hdrlen < sizeof ( *iphdr ) ) {
527  DBGC ( iphdr->src, "IPv4 header too short at %zd bytes (min "
528  "%zd bytes)\n", hdrlen, sizeof ( *iphdr ) );
529  goto err_header;
530  }
531  if ( hdrlen > iob_len ( iobuf ) ) {
532  DBGC ( iphdr->src, "IPv4 header too long at %zd bytes "
533  "(packet is %zd bytes)\n", hdrlen, iob_len ( iobuf ) );
534  goto err_header;
535  }
536  if ( ( csum = tcpip_chksum ( iphdr, hdrlen ) ) != 0 ) {
537  DBGC ( iphdr->src, "IPv4 checksum incorrect (is %04x "
538  "including checksum field, should be 0000)\n", csum );
539  goto err_header;
540  }
541  len = ntohs ( iphdr->len );
542  if ( len < hdrlen ) {
543  DBGC ( iphdr->src, "IPv4 length too short at %zd bytes "
544  "(header is %zd bytes)\n", len, hdrlen );
545  goto err_header;
546  }
547  if ( len > iob_len ( iobuf ) ) {
548  DBGC ( iphdr->src, "IPv4 length too long at %zd bytes "
549  "(packet is %zd bytes)\n", len, iob_len ( iobuf ) );
551  goto err_other;
552  }
553 
554  /* Truncate packet to correct length */
555  iob_unput ( iobuf, ( iob_len ( iobuf ) - len ) );
556 
557  /* Print IPv4 header for debugging */
558  DBGC2 ( iphdr->src, "IPv4 RX %s<-", inet_ntoa ( iphdr->dest ) );
559  DBGC2 ( iphdr->src, "%s len %d proto %d id %04x csum %04x\n",
561  ntohs ( iphdr->ident ), ntohs ( iphdr->chksum ) );
562 
563  /* Discard unicast packets not destined for us */
564  if ( ( ! ( flags & LL_MULTICAST ) ) &&
565  ( iphdr->dest.s_addr != INADDR_BROADCAST ) &&
567  ( ! ipv4_has_addr ( netdev, iphdr->dest ) ) ) {
568  DBGC ( iphdr->src, "IPv4 discarding non-local unicast packet "
569  "for %s\n", inet_ntoa ( iphdr->dest ) );
571  goto err_other;
572  }
573 
574  /* Perform fragment reassembly if applicable */
576  /* Pass the fragment to fragment_reassemble() which returns
577  * either a fully reassembled I/O buffer or NULL.
578  */
579  iobuf = fragment_reassemble ( &ipv4_reassembler, iobuf,
580  &hdrlen );
581  if ( ! iobuf )
582  return 0;
583  iphdr = iobuf->data;
584  }
585 
586  /* Construct socket addresses, calculate pseudo-header
587  * checksum, and hand off to transport layer
588  */
589  memset ( &src, 0, sizeof ( src ) );
590  src.sin.sin_family = AF_INET;
591  src.sin.sin_addr = iphdr->src;
592  memset ( &dest, 0, sizeof ( dest ) );
593  dest.sin.sin_family = AF_INET;
594  dest.sin.sin_addr = iphdr->dest;
595  pshdr_csum = ipv4_pshdr_chksum ( iobuf, TCPIP_EMPTY_CSUM );
596  iob_pull ( iobuf, hdrlen );
597  if ( ( rc = tcpip_rx ( iobuf, netdev, iphdr->protocol, &src.st,
598  &dest.st, pshdr_csum, &ipv4_stats ) ) != 0 ) {
599  DBGC ( src.sin.sin_addr, "IPv4 received packet rejected by "
600  "stack: %s\n", strerror ( rc ) );
601  return rc;
602  }
603 
604  profile_stop ( &ipv4_rx_profiler );
605  return 0;
606 
607  err_header:
609  err_other:
610  free_iob ( iobuf );
611  return -EINVAL;
612 }
613 
614 /**
615  * Check existence of IPv4 address for ARP
616  *
617  * @v netdev Network device
618  * @v net_addr Network-layer address
619  * @ret rc Return status code
620  */
621 static int ipv4_arp_check ( struct net_device *netdev, const void *net_addr ) {
622  const struct in_addr *address = net_addr;
623 
624  if ( ipv4_has_addr ( netdev, *address ) )
625  return 0;
626 
627  return -ENOENT;
628 }
629 
630 /**
631  * Parse IPv4 address
632  *
633  * @v string IPv4 address string
634  * @ret in IPv4 address to fill in
635  * @ret ok IPv4 address is valid
636  *
637  * Note that this function returns nonzero iff the address is valid,
638  * to match the standard BSD API function of the same name. Unlike
639  * most other iPXE functions, a zero therefore indicates failure.
640  */
641 int inet_aton ( const char *string, struct in_addr *in ) {
642  const char *separator = "...";
643  uint8_t *byte = ( ( uint8_t * ) in );
644  char *endp;
645  unsigned long value;
646 
647  while ( 1 ) {
648  value = strtoul ( string, &endp, 0 );
649  if ( string == endp )
650  return 0;
651  if ( value > 0xff )
652  return 0;
653  *(byte++) = value;
654  if ( *endp != *separator )
655  return 0;
656  if ( ! *(separator++) )
657  return 1;
658  string = ( endp + 1 );
659  }
660 }
661 
662 /**
663  * Convert IPv4 address to dotted-quad notation
664  *
665  * @v in IPv4 address
666  * @ret string IPv4 address in dotted-quad notation
667  */
668 char * inet_ntoa ( struct in_addr in ) {
669  static char buf[16]; /* "xxx.xxx.xxx.xxx" */
670  uint8_t *bytes = ( uint8_t * ) &in;
671 
672  sprintf ( buf, "%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3] );
673  return buf;
674 }
675 
676 /**
677  * Transcribe IPv4 address
678  *
679  * @v net_addr IPv4 address
680  * @ret string IPv4 address in dotted-quad notation
681  *
682  */
683 static const char * ipv4_ntoa ( const void *net_addr ) {
684  return inet_ntoa ( * ( ( struct in_addr * ) net_addr ) );
685 }
686 
687 /**
688  * Transcribe IPv4 socket address
689  *
690  * @v sa Socket address
691  * @ret string Socket address in standard notation
692  */
693 static const char * ipv4_sock_ntoa ( struct sockaddr *sa ) {
694  struct sockaddr_in *sin = ( ( struct sockaddr_in * ) sa );
695 
696  return inet_ntoa ( sin->sin_addr );
697 }
698 
699 /**
700  * Parse IPv4 socket address
701  *
702  * @v string Socket address string
703  * @v sa Socket address to fill in
704  * @ret rc Return status code
705  */
706 static int ipv4_sock_aton ( const char *string, struct sockaddr *sa ) {
707  struct sockaddr_in *sin = ( ( struct sockaddr_in * ) sa );
708  struct in_addr in;
709 
710  if ( inet_aton ( string, &in ) ) {
711  sin->sin_addr = in;
712  return 0;
713  }
714  return -EINVAL;
715 }
716 
717 /** IPv4 protocol */
718 struct net_protocol ipv4_protocol __net_protocol = {
719  .name = "IP",
720  .net_proto = htons ( ETH_P_IP ),
721  .net_addr_len = sizeof ( struct in_addr ),
722  .rx = ipv4_rx,
723  .ntoa = ipv4_ntoa,
724 };
725 
726 /** IPv4 TCPIP net protocol */
727 struct tcpip_net_protocol ipv4_tcpip_protocol __tcpip_net_protocol = {
728  .name = "IPv4",
729  .sa_family = AF_INET,
730  .header_len = sizeof ( struct iphdr ),
731  .net_protocol = &ipv4_protocol,
732  .tx = ipv4_tx,
733  .netdev = ipv4_netdev,
734 };
735 
736 /** IPv4 ARP protocol */
737 struct arp_net_protocol ipv4_arp_protocol __arp_net_protocol = {
738  .net_protocol = &ipv4_protocol,
739  .check = ipv4_arp_check,
740 };
741 
742 /** IPv4 socket address converter */
743 struct sockaddr_converter ipv4_sockaddr_converter __sockaddr_converter = {
744  .family = AF_INET,
745  .ntoa = ipv4_sock_ntoa,
746  .aton = ipv4_sock_aton,
747 };
748 
749 /******************************************************************************
750  *
751  * Settings
752  *
753  ******************************************************************************
754  */
755 
756 /**
757  * Parse IPv4 address setting value
758  *
759  * @v type Setting type
760  * @v value Formatted setting value
761  * @v buf Buffer to contain raw value
762  * @v len Length of buffer
763  * @ret len Length of raw value, or negative error
764  */
766  const char *value, void *buf, size_t len ) {
767  struct in_addr ipv4;
768 
769  /* Parse IPv4 address */
770  if ( inet_aton ( value, &ipv4 ) == 0 )
771  return -EINVAL;
772 
773  /* Copy to buffer */
774  if ( len > sizeof ( ipv4 ) )
775  len = sizeof ( ipv4 );
776  memcpy ( buf, &ipv4, len );
777 
778  return ( sizeof ( ipv4 ) );
779 }
780 
781 /**
782  * Format IPv4 address setting value
783  *
784  * @v type Setting type
785  * @v raw Raw setting value
786  * @v raw_len Length of raw setting value
787  * @v buf Buffer to contain formatted value
788  * @v len Length of buffer
789  * @ret len Length of formatted value, or negative error
790  */
792  const void *raw, size_t raw_len, char *buf,
793  size_t len ) {
794  const struct in_addr *ipv4 = raw;
795 
796  if ( raw_len < sizeof ( *ipv4 ) )
797  return -EINVAL;
798  return snprintf ( buf, len, "%s", inet_ntoa ( *ipv4 ) );
799 }
800 
801 /** IPv4 address setting */
802 const struct setting ip_setting __setting ( SETTING_IP4, ip ) = {
803  .name = "ip",
804  .description = "IP address",
805  .tag = DHCP_EB_YIADDR,
806  .type = &setting_type_ipv4,
807 };
808 
809 /** IPv4 subnet mask setting */
810 const struct setting netmask_setting __setting ( SETTING_IP4, netmask ) = {
811  .name = "netmask",
812  .description = "Subnet mask",
813  .tag = DHCP_SUBNET_MASK,
814  .type = &setting_type_ipv4,
815 };
816 
817 /** Default gateway setting */
818 const struct setting gateway_setting __setting ( SETTING_IP4, gateway ) = {
819  .name = "gateway",
820  .description = "Default gateway",
821  .tag = DHCP_ROUTERS,
822  .type = &setting_type_ipv4,
823 };
824 
825 /**
826  * Send gratuitous ARP, if applicable
827  *
828  * @v netdev Network device
829  * @v address IPv4 address
830  * @v netmask Subnet mask
831  * @v gateway Gateway address (if any)
832  * @ret rc Return status code
833  */
834 static int ipv4_gratuitous_arp ( struct net_device *netdev,
835  struct in_addr address,
836  struct in_addr netmask __unused,
837  struct in_addr gateway __unused ) {
838  int rc;
839 
840  /* Do nothing if network device already has this IPv4 address */
841  if ( ipv4_has_addr ( netdev, address ) )
842  return 0;
843 
844  /* Transmit gratuitous ARP */
845  DBGC ( netdev, "IPv4 sending gratuitous ARP for %s via %s\n",
846  inet_ntoa ( address ), netdev->name );
847  if ( ( rc = arp_tx_request ( netdev, &ipv4_protocol, &address,
848  &address ) ) != 0 ) {
849  DBGC ( netdev, "IPv4 could not transmit gratuitous ARP: %s\n",
850  strerror ( rc ) );
851  /* Treat failures as non-fatal */
852  }
853 
854  return 0;
855 }
856 
857 /**
858  * Process IPv4 network device settings
859  *
860  * @v apply Application method
861  * @ret rc Return status code
862  */
863 static int ipv4_settings ( int ( * apply ) ( struct net_device *netdev,
864  struct in_addr address,
865  struct in_addr netmask,
866  struct in_addr gateway ) ) {
867  struct net_device *netdev;
868  struct settings *settings;
869  struct in_addr address = { 0 };
870  struct in_addr netmask = { 0 };
871  struct in_addr gateway = { 0 };
872  int rc;
873 
874  /* Process settings for each network device */
875  for_each_netdev ( netdev ) {
876 
877  /* Get network device settings */
879 
880  /* Get IPv4 address */
881  address.s_addr = 0;
882  fetch_ipv4_setting ( settings, &ip_setting, &address );
883  if ( ! address.s_addr )
884  continue;
885 
886  /* Get subnet mask */
887  fetch_ipv4_setting ( settings, &netmask_setting, &netmask );
888 
889  /* Calculate default netmask, if necessary */
890  if ( ! netmask.s_addr ) {
891  if ( IN_IS_CLASSA ( address.s_addr ) ) {
892  netmask.s_addr = INADDR_NET_CLASSA;
893  } else if ( IN_IS_CLASSB ( address.s_addr ) ) {
894  netmask.s_addr = INADDR_NET_CLASSB;
895  } else if ( IN_IS_CLASSC ( address.s_addr ) ) {
896  netmask.s_addr = INADDR_NET_CLASSC;
897  }
898  }
899 
900  /* Get default gateway, if present */
901  fetch_ipv4_setting ( settings, &gateway_setting, &gateway );
902 
903  /* Apply settings */
904  if ( ( rc = apply ( netdev, address, netmask, gateway ) ) != 0 )
905  return rc;
906  }
907 
908  return 0;
909 }
910 
911 /**
912  * Create IPv4 routing table based on configured settings
913  *
914  * @ret rc Return status code
915  */
916 static int ipv4_create_routes ( void ) {
917  struct ipv4_miniroute *miniroute;
918  struct ipv4_miniroute *tmp;
919  int rc;
920 
921  /* Send gratuitous ARPs for any new IPv4 addresses */
923 
924  /* Delete all existing routes */
926  del_ipv4_miniroute ( miniroute );
927 
928  /* Create a route for each configured network device */
929  if ( ( rc = ipv4_settings ( add_ipv4_miniroute ) ) != 0 )
930  return rc;
931 
932  return 0;
933 }
934 
935 /** IPv4 settings applicator */
936 struct settings_applicator ipv4_settings_applicator __settings_applicator = {
938 };
939 
940 /* Drag in objects via ipv4_protocol */
941 REQUIRING_SYMBOL ( ipv4_protocol );
942 
943 /* Drag in ICMPv4 */
944 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:102
Address Resolution Protocol.
struct in_addr netmask
Subnet mask.
Definition: ip.h:72
#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:743
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:693
Dynamic Host Configuration Protocol.
struct net_protocol ipv4_protocol __net_protocol
IPv4 protocol.
Definition: ipv4.c:718
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:460
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:60
static void del_ipv4_miniroute(struct ipv4_miniroute *miniroute)
Delete IPv4 minirouting table entry.
Definition: ipv4.c:135
An IP system statistics family.
Definition: ipstat.h:169
#define TCPIP_EMPTY_CSUM
Empty checksum value.
Definition: tcpip.h:57
#define list_add(new, head)
Add a new entry to the head of a list.
Definition: list.h:69
#define IP_STATISTICS_IPV4
Definition: ipstat.h:184
#define IP_VER
Definition: ip.h:22
Error codes.
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:84
#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: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:146
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.
#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
static void const void * src
Definition: crypto.h:244
struct net_device * netdev
Network device.
Definition: ip.h:63
#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:936
#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
static struct ipv4_miniroute * ipv4_route(unsigned int scope_id, struct in_addr *dest)
Perform IPv4 routing.
Definition: ipv4.c:160
A data structure for storing profiling information.
Definition: profile.h:26
uint16_t ident
Definition: ip.h:39
static int ipv4_create_routes(void)
Create IPv4 routing table based on configured settings.
Definition: ipv4.c:916
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:171
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:791
An IPv4 packet header.
Definition: ip.h:35
struct in_addr address
IPv4 address.
Definition: ip.h:66
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:583
struct in_addr hostmask
Host mask.
Definition: ip.h:86
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:621
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:56
static const char * ipv4_ntoa(const void *net_addr)
Transcribe IPv4 address.
Definition: ipv4.c:683
unsigned long tmp
Definition: linux_pci.h:53
static int ipv4_gratuitous_arp(struct net_device *netdev, struct in_addr address, struct in_addr netmask __unused, struct in_addr gateway __unused)
Send gratuitous ARP, if applicable.
Definition: ipv4.c:834
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:727
#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:260
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:246
static int netdev_is_open(struct net_device *netdev)
Check whether or not network device is open.
Definition: netdevice.h:658
unsigned int version
IP version.
Definition: ipstat.h:171
int ipv4_has_any_addr(struct net_device *netdev)
Check if network device has any IPv4 address.
Definition: ipv4.c:443
#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:572
unsigned long out_no_routes
ipSystemStatsOutNoRoutes
Definition: ipstat.h:130
Socket address converter.
Definition: socket.h:115
An IPv4 address/routing table entry.
Definition: ip.h:58
static int ipv4_settings(int(*apply)(struct net_device *netdev, struct in_addr address, struct in_addr netmask, struct in_addr gateway))
Process IPv4 network device settings.
Definition: ipv4.c:863
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:431
uint16_t len
Definition: ip.h:38
struct in_addr gateway
Gateway address, or zero for no gateway.
Definition: ip.h:88
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition: list.h:93
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:55
uint8_t verhdrlen
Definition: ip.h:36
static struct fragment_reassembler ipv4_reassembler
IPv4 fragment reassembler.
Definition: ipv4.c:268
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:158
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:283
IP system statistics.
Definition: ipstat.h:44
static void * dest
Definition: strings.h:176
#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
pseudo_bit_t value[0x00020]
Definition: arbel.h:13
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:66
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:135
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
IP address structure.
Definition: in.h:41
#define for_each_netdev(netdev)
Iterate over all network devices.
Definition: netdevice.h:543
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:155
static struct net_device * ipv4_netdev(struct sockaddr_tcpip *st_dest)
Determine transmitting network device.
Definition: ipv4.c:208
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:641
A network device.
Definition: netdevice.h:352
struct arp_net_protocol ipv4_arp_protocol __arp_net_protocol
IPv4 ARP protocol.
Definition: ipv4.c:737
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:668
#define IP_MASK_VER
Definition: ip.h:23
A settings block.
Definition: settings.h:132
u32 addr
Definition: sky2.h:8
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:561
struct in_addr dest
Definition: ip.h:45
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:486
An IPv4 pseudo header.
Definition: ip.h:49
void * malloc(size_t size)
Allocate memory.
Definition: malloc.c:583
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
static int add_ipv4_miniroute(struct net_device *netdev, struct in_addr address, struct in_addr netmask, struct in_addr gateway)
Add IPv4 minirouting table entry.
Definition: ipv4.c:84
A setting.
Definition: settings.h:23
#define LL_BROADCAST
Packet is a broadcast packet.
Definition: netdevice.h:108
A network-layer protocol.
Definition: netdevice.h:64
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.
#define __unused
Declare a variable or data structure as unused.
Definition: compiler.h:573
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:229
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:371
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:765
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
uint32_t len
Length.
Definition: ena.h:14
uint32_t type
Operating system type.
Definition: ena.h:12
#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:48
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:706
#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
struct sockaddr_in sin
Definition: syslog.c:57
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:312
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
#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:33
uint8_t flags
Flags.
Definition: ena.h:18