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