#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <byteswap.h>
#include <gpxe/list.h>
#include <gpxe/in.h>
#include <gpxe/arp.h>
#include <gpxe/if_ether.h>
#include <gpxe/iobuf.h>
#include <gpxe/netdevice.h>
#include <gpxe/ip.h>
#include <gpxe/tcpip.h>
#include <gpxe/dhcp.h>
#include <gpxe/settings.h>
Go to the source code of this file.
Functions | |
| FILE_LICENCE (GPL2_OR_LATER) | |
| static | LIST_HEAD (frag_buffers) |
| List of fragment reassembly buffers. | |
| static struct ipv4_miniroute *__malloc | add_ipv4_miniroute (struct net_device *netdev, struct in_addr address, struct in_addr netmask, struct in_addr gateway) |
| Add IPv4 minirouting table entry. | |
| static void | del_ipv4_miniroute (struct ipv4_miniroute *miniroute) |
| Delete IPv4 minirouting table entry. | |
| static struct ipv4_miniroute * | ipv4_route (struct in_addr *dest) |
| Perform IPv4 routing. | |
| static void | ipv4_frag_expired (struct retry_timer *timer __unused, int over) |
| Fragment reassembly counter timeout. | |
| static void | free_fragbuf (struct frag_buffer *fragbuf) |
| Free fragment buffer. | |
| static struct io_buffer * | ipv4_reassemble (struct io_buffer *iobuf) |
| Fragment reassembler. | |
| static uint16_t | ipv4_pshdr_chksum (struct io_buffer *iobuf, uint16_t csum) |
| Add IPv4 pseudo-header checksum to existing checksum. | |
| static int | ipv4_ll_addr (struct in_addr dest, struct in_addr src, struct net_device *netdev, uint8_t *ll_dest) |
| Determine link-layer address. | |
| 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. | |
| static int | ipv4_rx (struct io_buffer *iobuf, struct net_device *netdev __unused, const void *ll_source __unused) |
| Process incoming packets. | |
| static int | ipv4_arp_check (struct net_device *netdev, const void *net_addr) |
| Check existence of IPv4 address for ARP. | |
| char * | inet_ntoa (struct in_addr in) |
| Convert IPv4 address to dotted-quad notation. | |
| static const char * | ipv4_ntoa (const void *net_addr) |
| Transcribe IP address. | |
| static int | ipv4_create_routes (void) |
| Create IPv4 routing table based on configured settings. | |
| REQUIRE_OBJECT (icmp) | |
Variables | |
| static uint16_t | next_ident = 0 |
| struct net_protocol | ipv4_protocol |
| struct list_head | ipv4_miniroutes = LIST_HEAD_INIT ( ipv4_miniroutes ) |
| List of IPv4 miniroutes. | |
| struct net_protocol ipv4_protocol | __net_protocol |
| IPv4 protocol. | |
| struct tcpip_net_protocol ipv4_tcpip_protocol | __tcpip_net_protocol |
| IPv4 TCPIP net protocol. | |
| struct arp_net_protocol ipv4_arp_protocol | __arp_net_protocol |
| IPv4 ARP protocol. | |
| struct setting ip_setting | __setting |
| IPv4 address setting. | |
| struct settings_applicator ipv4_settings_applicator | __settings_applicator |
| IPv4 settings applicator. | |
Definition in file ipv4.c.
| FILE_LICENCE | ( | GPL2_OR_LATER | ) |
| static LIST_HEAD | ( | frag_buffers | ) | [static] |
List of fragment reassembly buffers.
| static struct ipv4_miniroute* __malloc add_ipv4_miniroute | ( | struct net_device * | netdev, | |
| struct in_addr | address, | |||
| struct in_addr | netmask, | |||
| struct in_addr | gateway | |||
| ) | [static, read] |
Add IPv4 minirouting table entry.
| netdev | Network device | |
| address | IPv4 address | |
| netmask | Subnet mask | |
| gateway | Gateway address (if any) |
| miniroute | Routing table entry, or NULL |
Definition at line 47 of file ipv4.c.
References ipv4_miniroute::address, DBG, ipv4_miniroute::gateway, inet_ntoa(), ipv4_miniroute::list, list_add, list_add_tail, malloc(), net_device::name, ipv4_miniroute::netdev, netdev_get(), ipv4_miniroute::netmask, NULL, and in_addr::s_addr.
Referenced by ipv4_create_routes().
00048 { 00049 struct ipv4_miniroute *miniroute; 00050 00051 DBG ( "IPv4 add %s", inet_ntoa ( address ) ); 00052 DBG ( "/%s ", inet_ntoa ( netmask ) ); 00053 if ( gateway.s_addr ) 00054 DBG ( "gw %s ", inet_ntoa ( gateway ) ); 00055 DBG ( "via %s\n", netdev->name ); 00056 00057 /* Allocate and populate miniroute structure */ 00058 miniroute = malloc ( sizeof ( *miniroute ) ); 00059 if ( ! miniroute ) { 00060 DBG ( "IPv4 could not add miniroute\n" ); 00061 return NULL; 00062 } 00063 00064 /* Record routing information */ 00065 miniroute->netdev = netdev_get ( netdev ); 00066 miniroute->address = address; 00067 miniroute->netmask = netmask; 00068 miniroute->gateway = gateway; 00069 00070 /* Add to end of list if we have a gateway, otherwise 00071 * to start of list. 00072 */ 00073 if ( gateway.s_addr ) { 00074 list_add_tail ( &miniroute->list, &ipv4_miniroutes ); 00075 } else { 00076 list_add ( &miniroute->list, &ipv4_miniroutes ); 00077 } 00078 00079 return miniroute; 00080 }
| static void del_ipv4_miniroute | ( | struct ipv4_miniroute * | miniroute | ) | [static] |
Delete IPv4 minirouting table entry.
| miniroute | Routing table entry |
Definition at line 87 of file ipv4.c.
References ipv4_miniroute::address, DBG, free(), ipv4_miniroute::gateway, inet_ntoa(), ipv4_miniroute::list, list_del, net_device::name, ipv4_miniroute::netdev, netdev_put(), ipv4_miniroute::netmask, and in_addr::s_addr.
Referenced by ipv4_create_routes().
00087 { 00088 00089 DBG ( "IPv4 del %s", inet_ntoa ( miniroute->address ) ); 00090 DBG ( "/%s ", inet_ntoa ( miniroute->netmask ) ); 00091 if ( miniroute->gateway.s_addr ) 00092 DBG ( "gw %s ", inet_ntoa ( miniroute->gateway ) ); 00093 DBG ( "via %s\n", miniroute->netdev->name ); 00094 00095 netdev_put ( miniroute->netdev ); 00096 list_del ( &miniroute->list ); 00097 free ( miniroute ); 00098 }
| static struct ipv4_miniroute* ipv4_route | ( | struct in_addr * | dest | ) | [static, read] |
Perform IPv4 routing.
| dest | Final destination address |
| dest | Next hop destination address | |
| miniroute | Routing table entry to use, or NULL if no route |
Definition at line 110 of file ipv4.c.
References ipv4_miniroute::address, ipv4_miniroute::gateway, INADDR_BROADCAST, ipv4_miniroute::list, list_for_each_entry, ipv4_miniroute::netdev, netdev_is_open(), ipv4_miniroute::netmask, NULL, and in_addr::s_addr.
Referenced by ipv4_tx().
00110 { 00111 struct ipv4_miniroute *miniroute; 00112 int local; 00113 int has_gw; 00114 00115 /* Never attempt to route the broadcast address */ 00116 if ( dest->s_addr == INADDR_BROADCAST ) 00117 return NULL; 00118 00119 /* Find first usable route in routing table */ 00120 list_for_each_entry ( miniroute, &ipv4_miniroutes, list ) { 00121 if ( ! netdev_is_open ( miniroute->netdev ) ) 00122 continue; 00123 local = ( ( ( dest->s_addr ^ miniroute->address.s_addr ) 00124 & miniroute->netmask.s_addr ) == 0 ); 00125 has_gw = ( miniroute->gateway.s_addr ); 00126 if ( local || has_gw ) { 00127 if ( ! local ) 00128 *dest = miniroute->gateway; 00129 return miniroute; 00130 } 00131 } 00132 00133 return NULL; 00134 }
| static void ipv4_frag_expired | ( | struct retry_timer *timer | __unused, | |
| int | over | |||
| ) | [static] |
Fragment reassembly counter timeout.
| timer | Retry timer | |
| over | If asserted, the timer is greater than MAX_TIMEOUT |
Definition at line 142 of file ipv4.c.
References DBG.
Referenced by ipv4_reassemble().
00143 { 00144 if ( over ) { 00145 DBG ( "Fragment reassembly timeout" ); 00146 /* Free the fragment buffer */ 00147 } 00148 }
| static void free_fragbuf | ( | struct frag_buffer * | fragbuf | ) | [static] |
Free fragment buffer.
| fragbug | Fragment buffer |
Definition at line 155 of file ipv4.c.
References free().
Referenced by ipv4_reassemble().
00155 { 00156 free ( fragbuf ); 00157 }
Fragment reassembler.
| iobuf | I/O buffer, fragment of the datagram |
| frag_iob | Reassembled packet, or NULL |
Check if the fragment belongs to any fragment series
Check if the packet is the expected fragment
The offset of the new packet must be equal to the length of the data accumulated so far (the length of the reassembled I/O buffer
Append the contents of the fragment to the reassembled I/O buffer
Check if the fragment series is over
Check if the fragment is the first in the fragment series
Create a new fragment buffer
Definition at line 165 of file ipv4.c.
References alloc_iob(), io_buffer::data, retry_timer::expired, frag_buffer::frag_iob, frag_buffer::frag_timer, iphdr::frags, free_fragbuf(), free_iob(), iphdr::ident, frag_buffer::ident, iob_len(), iob_pull, iob_put, IP_FRAG_IOB_SIZE, IP_FRAG_TIMEOUT, IP_MASK_MOREFRAGS, IP_MASK_OFFSET, ipv4_frag_expired(), frag_buffer::list, list_add, list_for_each_entry, malloc(), memcpy, NULL, in_addr::s_addr, iphdr::src, frag_buffer::src, start_timer(), and retry_timer::timeout.
Referenced by ipv4_rx().
00165 { 00166 struct iphdr *iphdr = iobuf->data; 00167 struct frag_buffer *fragbuf; 00168 00169 /** 00170 * Check if the fragment belongs to any fragment series 00171 */ 00172 list_for_each_entry ( fragbuf, &frag_buffers, list ) { 00173 if ( fragbuf->ident == iphdr->ident && 00174 fragbuf->src.s_addr == iphdr->src.s_addr ) { 00175 /** 00176 * Check if the packet is the expected fragment 00177 * 00178 * The offset of the new packet must be equal to the 00179 * length of the data accumulated so far (the length of 00180 * the reassembled I/O buffer 00181 */ 00182 if ( iob_len ( fragbuf->frag_iob ) == 00183 ( iphdr->frags & IP_MASK_OFFSET ) ) { 00184 /** 00185 * Append the contents of the fragment to the 00186 * reassembled I/O buffer 00187 */ 00188 iob_pull ( iobuf, sizeof ( *iphdr ) ); 00189 memcpy ( iob_put ( fragbuf->frag_iob, 00190 iob_len ( iobuf ) ), 00191 iobuf->data, iob_len ( iobuf ) ); 00192 free_iob ( iobuf ); 00193 00194 /** Check if the fragment series is over */ 00195 if ( ! ( iphdr->frags & IP_MASK_MOREFRAGS ) ) { 00196 iobuf = fragbuf->frag_iob; 00197 free_fragbuf ( fragbuf ); 00198 return iobuf; 00199 } 00200 00201 } else { 00202 /* Discard the fragment series */ 00203 free_fragbuf ( fragbuf ); 00204 free_iob ( iobuf ); 00205 } 00206 return NULL; 00207 } 00208 } 00209 00210 /** Check if the fragment is the first in the fragment series */ 00211 if ( iphdr->frags & IP_MASK_MOREFRAGS && 00212 ( ( iphdr->frags & IP_MASK_OFFSET ) == 0 ) ) { 00213 00214 /** Create a new fragment buffer */ 00215 fragbuf = ( struct frag_buffer* ) malloc ( sizeof( *fragbuf ) ); 00216 fragbuf->ident = iphdr->ident; 00217 fragbuf->src = iphdr->src; 00218 00219 /* Set up the reassembly I/O buffer */ 00220 fragbuf->frag_iob = alloc_iob ( IP_FRAG_IOB_SIZE ); 00221 iob_pull ( iobuf, sizeof ( *iphdr ) ); 00222 memcpy ( iob_put ( fragbuf->frag_iob, iob_len ( iobuf ) ), 00223 iobuf->data, iob_len ( iobuf ) ); 00224 free_iob ( iobuf ); 00225 00226 /* Set the reassembly timer */ 00227 fragbuf->frag_timer.timeout = IP_FRAG_TIMEOUT; 00228 fragbuf->frag_timer.expired = ipv4_frag_expired; 00229 start_timer ( &fragbuf->frag_timer ); 00230 00231 /* Add the fragment buffer to the list of fragment buffers */ 00232 list_add ( &fragbuf->list, &frag_buffers ); 00233 } 00234 00235 return NULL; 00236 }
Add IPv4 pseudo-header checksum to existing checksum.
| iobuf | I/O buffer | |
| csum | Existing checksum |
| csum | Updated checksum |
Definition at line 245 of file ipv4.c.
References io_buffer::data, iphdr::dest, ipv4_pseudo_header::dest, htons, iob_len(), IP_MASK_HLEN, ipv4_pseudo_header::len, iphdr::protocol, ipv4_pseudo_header::protocol, iphdr::src, ipv4_pseudo_header::src, tcpip_continue_chksum(), iphdr::verhdrlen, and ipv4_pseudo_header::zero_padding.
Referenced by ipv4_rx(), and ipv4_tx().
00245 { 00246 struct ipv4_pseudo_header pshdr; 00247 struct iphdr *iphdr = iobuf->data; 00248 size_t hdrlen = ( ( iphdr->verhdrlen & IP_MASK_HLEN ) * 4 ); 00249 00250 /* Build pseudo-header */ 00251 pshdr.src = iphdr->src; 00252 pshdr.dest = iphdr->dest; 00253 pshdr.zero_padding = 0x00; 00254 pshdr.protocol = iphdr->protocol; 00255 pshdr.len = htons ( iob_len ( iobuf ) - hdrlen ); 00256 00257 /* Update the checksum value */ 00258 return tcpip_continue_chksum ( csum, &pshdr, sizeof ( pshdr ) ); 00259 }
| static int ipv4_ll_addr | ( | struct in_addr | dest, | |
| struct in_addr | src, | |||
| struct net_device * | netdev, | |||
| uint8_t * | ll_dest | |||
| ) | [static] |
Determine link-layer address.
| dest | IPv4 destination address | |
| src | IPv4 source address | |
| netdev | Network device | |
| ll_dest | Link-layer destination address buffer |
| rc | Return status code |
Definition at line 270 of file ipv4.c.
References AF_INET, arp_resolve(), IN_MULTICAST, INADDR_BROADCAST, ipv4_protocol, ll_protocol::ll_addr_len, net_device::ll_broadcast, net_device::ll_protocol, ll_protocol::mc_hash, memcpy, ntohl, and in_addr::s_addr.
Referenced by ipv4_tx().
00271 { 00272 struct ll_protocol *ll_protocol = netdev->ll_protocol; 00273 00274 if ( dest.s_addr == INADDR_BROADCAST ) { 00275 /* Broadcast address */ 00276 memcpy ( ll_dest, netdev->ll_broadcast, 00277 ll_protocol->ll_addr_len ); 00278 return 0; 00279 } else if ( IN_MULTICAST ( ntohl ( dest.s_addr ) ) ) { 00280 return ll_protocol->mc_hash ( AF_INET, &dest, ll_dest ); 00281 } else { 00282 /* Unicast address: resolve via ARP */ 00283 return arp_resolve ( netdev, &ipv4_protocol, &dest, 00284 &src, ll_dest ); 00285 } 00286 }
| 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 | |||
| ) | [static] |
Transmit IP packet.
| iobuf | I/O buffer | |
| tcpip | Transport-layer protocol | |
| st_src | Source network-layer address | |
| st_dest | Destination network-layer address | |
| netdev | Network device to use if no route found, or NULL | |
| trans_csum | Transport-layer checksum to complete, or NULL |
| rc | Status |
Definition at line 301 of file ipv4.c.
References ipv4_miniroute::address, iphdr::chksum, DBG, iphdr::dest, ENETUNREACH, free_iob(), htons, iphdr::ident, IN_MULTICAST, INADDR_BROADCAST, inet_ntoa(), iob_len(), iob_push, IP_TOS, IP_TTL, IP_VER, ipv4_ll_addr(), ipv4_protocol, ipv4_pshdr_chksum(), ipv4_route(), iphdr::len, MAX_LL_ADDR_LEN, memset(), net_device::name, net_tx(), ipv4_miniroute::netdev, next_ident, ntohl, ntohs, NULL, iphdr::protocol, in_addr::s_addr, iphdr::service, sockaddr_in::sin_addr, iphdr::src, strerror(), tcpip_chksum(), tcpip_protocol::tcpip_proto, iphdr::ttl, and iphdr::verhdrlen.
00306 { 00307 struct iphdr *iphdr = iob_push ( iobuf, sizeof ( *iphdr ) ); 00308 struct sockaddr_in *sin_src = ( ( struct sockaddr_in * ) st_src ); 00309 struct sockaddr_in *sin_dest = ( ( struct sockaddr_in * ) st_dest ); 00310 struct ipv4_miniroute *miniroute; 00311 struct in_addr next_hop; 00312 uint8_t ll_dest[MAX_LL_ADDR_LEN]; 00313 int rc; 00314 00315 /* Fill up the IP header, except source address */ 00316 memset ( iphdr, 0, sizeof ( *iphdr ) ); 00317 iphdr->verhdrlen = ( IP_VER | ( sizeof ( *iphdr ) / 4 ) ); 00318 iphdr->service = IP_TOS; 00319 iphdr->len = htons ( iob_len ( iobuf ) ); 00320 iphdr->ident = htons ( ++next_ident ); 00321 iphdr->ttl = IP_TTL; 00322 iphdr->protocol = tcpip_protocol->tcpip_proto; 00323 iphdr->dest = sin_dest->sin_addr; 00324 00325 /* Use routing table to identify next hop and transmitting netdev */ 00326 next_hop = iphdr->dest; 00327 if ( sin_src ) 00328 iphdr->src = sin_src->sin_addr; 00329 if ( ( next_hop.s_addr != INADDR_BROADCAST ) && 00330 ( ! IN_MULTICAST ( ntohl ( next_hop.s_addr ) ) ) && 00331 ( ( miniroute = ipv4_route ( &next_hop ) ) != NULL ) ) { 00332 iphdr->src = miniroute->address; 00333 netdev = miniroute->netdev; 00334 } 00335 if ( ! netdev ) { 00336 DBG ( "IPv4 has no route to %s\n", inet_ntoa ( iphdr->dest ) ); 00337 rc = -ENETUNREACH; 00338 goto err; 00339 } 00340 00341 /* Determine link-layer destination address */ 00342 if ( ( rc = ipv4_ll_addr ( next_hop, iphdr->src, netdev, 00343 ll_dest ) ) != 0 ) { 00344 DBG ( "IPv4 has no link-layer address for %s: %s\n", 00345 inet_ntoa ( next_hop ), strerror ( rc ) ); 00346 goto err; 00347 } 00348 00349 /* Fix up checksums */ 00350 if ( trans_csum ) 00351 *trans_csum = ipv4_pshdr_chksum ( iobuf, *trans_csum ); 00352 iphdr->chksum = tcpip_chksum ( iphdr, sizeof ( *iphdr ) ); 00353 00354 /* Print IP4 header for debugging */ 00355 DBG ( "IPv4 TX %s->", inet_ntoa ( iphdr->src ) ); 00356 DBG ( "%s len %d proto %d id %04x csum %04x\n", 00357 inet_ntoa ( iphdr->dest ), ntohs ( iphdr->len ), iphdr->protocol, 00358 ntohs ( iphdr->ident ), ntohs ( iphdr->chksum ) ); 00359 00360 /* Hand off to link layer */ 00361 if ( ( rc = net_tx ( iobuf, netdev, &ipv4_protocol, ll_dest ) ) != 0 ) { 00362 DBG ( "IPv4 could not transmit packet via %s: %s\n", 00363 netdev->name, strerror ( rc ) ); 00364 return rc; 00365 } 00366 00367 return 0; 00368 00369 err: 00370 free_iob ( iobuf ); 00371 return rc; 00372 }
| static int ipv4_rx | ( | struct io_buffer * | iobuf, | |
| struct net_device *netdev | __unused, | |||
| const void *ll_source | __unused | |||
| ) | [static] |
Process incoming packets.
| iobuf | I/O buffer | |
| netdev | Network device | |
| ll_source | Link-layer destination source |
Definition at line 384 of file ipv4.c.
References AF_INET, iphdr::chksum, io_buffer::data, DBG, iphdr::dest, dest, EINVAL, iphdr::frags, free_iob(), htons, iphdr::ident, inet_ntoa(), iob_len(), iob_pull, iob_unput, IP_MASK_HLEN, IP_MASK_MOREFRAGS, IP_MASK_OFFSET, IP_MASK_VER, IP_VER, ipv4_pshdr_chksum(), ipv4_reassemble(), iphdr::len, memset(), ntohs, iphdr::protocol, iphdr::src, src, strerror(), tcpip_chksum(), TCPIP_EMPTY_CSUM, tcpip_rx(), and iphdr::verhdrlen.
00385 { 00386 struct iphdr *iphdr = iobuf->data; 00387 size_t hdrlen; 00388 size_t len; 00389 union { 00390 struct sockaddr_in sin; 00391 struct sockaddr_tcpip st; 00392 } src, dest; 00393 uint16_t csum; 00394 uint16_t pshdr_csum; 00395 int rc; 00396 00397 /* Sanity check the IPv4 header */ 00398 if ( iob_len ( iobuf ) < sizeof ( *iphdr ) ) { 00399 DBG ( "IPv4 packet too short at %zd bytes (min %zd bytes)\n", 00400 iob_len ( iobuf ), sizeof ( *iphdr ) ); 00401 goto err; 00402 } 00403 if ( ( iphdr->verhdrlen & IP_MASK_VER ) != IP_VER ) { 00404 DBG ( "IPv4 version %#02x not supported\n", iphdr->verhdrlen ); 00405 goto err; 00406 } 00407 hdrlen = ( ( iphdr->verhdrlen & IP_MASK_HLEN ) * 4 ); 00408 if ( hdrlen < sizeof ( *iphdr ) ) { 00409 DBG ( "IPv4 header too short at %zd bytes (min %zd bytes)\n", 00410 hdrlen, sizeof ( *iphdr ) ); 00411 goto err; 00412 } 00413 if ( hdrlen > iob_len ( iobuf ) ) { 00414 DBG ( "IPv4 header too long at %zd bytes " 00415 "(packet is %zd bytes)\n", hdrlen, iob_len ( iobuf ) ); 00416 goto err; 00417 } 00418 if ( ( csum = tcpip_chksum ( iphdr, hdrlen ) ) != 0 ) { 00419 DBG ( "IPv4 checksum incorrect (is %04x including checksum " 00420 "field, should be 0000)\n", csum ); 00421 goto err; 00422 } 00423 len = ntohs ( iphdr->len ); 00424 if ( len < hdrlen ) { 00425 DBG ( "IPv4 length too short at %zd bytes " 00426 "(header is %zd bytes)\n", len, hdrlen ); 00427 goto err; 00428 } 00429 if ( len > iob_len ( iobuf ) ) { 00430 DBG ( "IPv4 length too long at %zd bytes " 00431 "(packet is %zd bytes)\n", len, iob_len ( iobuf ) ); 00432 goto err; 00433 } 00434 00435 /* Print IPv4 header for debugging */ 00436 DBG ( "IPv4 RX %s<-", inet_ntoa ( iphdr->dest ) ); 00437 DBG ( "%s len %d proto %d id %04x csum %04x\n", 00438 inet_ntoa ( iphdr->src ), ntohs ( iphdr->len ), iphdr->protocol, 00439 ntohs ( iphdr->ident ), ntohs ( iphdr->chksum ) ); 00440 00441 /* Truncate packet to correct length, calculate pseudo-header 00442 * checksum and then strip off the IPv4 header. 00443 */ 00444 iob_unput ( iobuf, ( iob_len ( iobuf ) - len ) ); 00445 pshdr_csum = ipv4_pshdr_chksum ( iobuf, TCPIP_EMPTY_CSUM ); 00446 iob_pull ( iobuf, hdrlen ); 00447 00448 /* Fragment reassembly */ 00449 if ( ( iphdr->frags & htons ( IP_MASK_MOREFRAGS ) ) || 00450 ( ( iphdr->frags & htons ( IP_MASK_OFFSET ) ) != 0 ) ) { 00451 /* Pass the fragment to ipv4_reassemble() which either 00452 * returns a fully reassembled I/O buffer or NULL. 00453 */ 00454 iobuf = ipv4_reassemble ( iobuf ); 00455 if ( ! iobuf ) 00456 return 0; 00457 } 00458 00459 /* Construct socket addresses and hand off to transport layer */ 00460 memset ( &src, 0, sizeof ( src ) ); 00461 src.sin.sin_family = AF_INET; 00462 src.sin.sin_addr = iphdr->src; 00463 memset ( &dest, 0, sizeof ( dest ) ); 00464 dest.sin.sin_family = AF_INET; 00465 dest.sin.sin_addr = iphdr->dest; 00466 if ( ( rc = tcpip_rx ( iobuf, iphdr->protocol, &src.st, 00467 &dest.st, pshdr_csum ) ) != 0 ) { 00468 DBG ( "IPv4 received packet rejected by stack: %s\n", 00469 strerror ( rc ) ); 00470 return rc; 00471 } 00472 00473 return 0; 00474 00475 err: 00476 free_iob ( iobuf ); 00477 return -EINVAL; 00478 }
| static int ipv4_arp_check | ( | struct net_device * | netdev, | |
| const void * | net_addr | |||
| ) | [static] |
Check existence of IPv4 address for ARP.
| netdev | Network device | |
| net_addr | Network-layer address |
| rc | Return status code |
Definition at line 487 of file ipv4.c.
References ipv4_miniroute::address, ENOENT, ipv4_miniroute::list, list_for_each_entry, ipv4_miniroute::netdev, and in_addr::s_addr.
00487 { 00488 const struct in_addr *address = net_addr; 00489 struct ipv4_miniroute *miniroute; 00490 00491 list_for_each_entry ( miniroute, &ipv4_miniroutes, list ) { 00492 if ( ( miniroute->netdev == netdev ) && 00493 ( miniroute->address.s_addr == address->s_addr ) ) { 00494 /* Found matching address */ 00495 return 0; 00496 } 00497 } 00498 return -ENOENT; 00499 }
| char* inet_ntoa | ( | struct in_addr | in | ) |
Convert IPv4 address to dotted-quad notation.
| in | IP address |
| string | IP address in dotted-quad notation |
Definition at line 507 of file ipv4.c.
References sprintf.
Referenced by add_ipv4_miniroute(), apply_dns_settings(), boot_next_server_and_filename(), del_ipv4_miniroute(), dhcp_deliver_iob(), dhcp_proxy_rx(), dhcp_proxy_tx(), dhcp_pxebs_accept(), dhcp_pxebs_rx(), dhcp_pxebs_tx(), dhcp_request_rx(), dhcp_request_tx(), dhcp_rx_offer(), dns_xfer_deliver_raw(), efi_snp_mcast_ip_to_mac(), fetchf_ipv4(), ibft_ipaddr(), ipv4_ntoa(), ipv4_rx(), ipv4_tx(), pxe_tftp_open(), pxenv_udp_open(), pxenv_udp_read(), pxenv_udp_write(), pxenv_undi_get_mcast_address(), route(), start_pxebs(), tftp_apply_settings(), and tftp_process_multicast().
00507 { 00508 static char buf[16]; /* "xxx.xxx.xxx.xxx" */ 00509 uint8_t *bytes = ( uint8_t * ) ∈ 00510 00511 sprintf ( buf, "%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3] ); 00512 return buf; 00513 }
| static const char* ipv4_ntoa | ( | const void * | net_addr | ) | [static] |
Transcribe IP address.
| net_addr | IP address |
| string | IP address in dotted-quad notation |
Definition at line 522 of file ipv4.c.
References inet_ntoa().
| static int ipv4_create_routes | ( | void | ) | [static] |
Create IPv4 routing table based on configured settings.
| rc | Return status code |
Definition at line 584 of file ipv4.c.
References add_ipv4_miniroute(), del_ipv4_miniroute(), ENOMEM, fetch_ipv4_setting(), for_each_netdev, htonl, IN_CLASSA, IN_CLASSA_NET, IN_CLASSB, IN_CLASSB_NET, IN_CLASSC, IN_CLASSC_NET, list_for_each_entry_safe, netdev, netdev_settings(), ntohl, and in_addr::s_addr.
00584 { 00585 struct ipv4_miniroute *miniroute; 00586 struct ipv4_miniroute *tmp; 00587 struct net_device *netdev; 00588 struct settings *settings; 00589 struct in_addr address = { 0 }; 00590 struct in_addr netmask = { 0 }; 00591 struct in_addr gateway = { 0 }; 00592 00593 /* Delete all existing routes */ 00594 list_for_each_entry_safe ( miniroute, tmp, &ipv4_miniroutes, list ) 00595 del_ipv4_miniroute ( miniroute ); 00596 00597 /* Create a route for each configured network device */ 00598 for_each_netdev ( netdev ) { 00599 settings = netdev_settings ( netdev ); 00600 /* Get IPv4 address */ 00601 address.s_addr = 0; 00602 fetch_ipv4_setting ( settings, &ip_setting, &address ); 00603 if ( ! address.s_addr ) 00604 continue; 00605 /* Get subnet mask */ 00606 fetch_ipv4_setting ( settings, &netmask_setting, &netmask ); 00607 /* Calculate default netmask, if necessary */ 00608 if ( ! netmask.s_addr ) { 00609 if ( IN_CLASSA ( ntohl ( address.s_addr ) ) ) { 00610 netmask.s_addr = htonl ( IN_CLASSA_NET ); 00611 } else if ( IN_CLASSB ( ntohl ( address.s_addr ) ) ) { 00612 netmask.s_addr = htonl ( IN_CLASSB_NET ); 00613 } else if ( IN_CLASSC ( ntohl ( address.s_addr ) ) ) { 00614 netmask.s_addr = htonl ( IN_CLASSC_NET ); 00615 } 00616 } 00617 /* Get default gateway, if present */ 00618 fetch_ipv4_setting ( settings, &gateway_setting, &gateway ); 00619 /* Configure route */ 00620 miniroute = add_ipv4_miniroute ( netdev, address, 00621 netmask, gateway ); 00622 if ( ! miniroute ) 00623 return -ENOMEM; 00624 } 00625 00626 return 0; 00627 }
| REQUIRE_OBJECT | ( | icmp | ) |
uint16_t next_ident = 0 [static] |
| struct net_protocol ipv4_protocol |
Definition at line 29 of file ipv4.c.
Referenced by ipv4_ll_addr(), ipv4_tx(), pxenv_undi_isr(), and pxenv_undi_transmit().
| struct list_head ipv4_miniroutes = LIST_HEAD_INIT ( ipv4_miniroutes ) |
| struct tcpip_net_protocol ipv4_tcpip_protocol __tcpip_net_protocol |
| struct arp_net_protocol ipv4_arp_protocol __arp_net_protocol |
| struct settings_applicator ipv4_settings_applicator __settings_applicator |
1.5.7.1