ipv4.c File Reference

IPv4 protocol. More...

#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_minirouteipv4_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_bufferipv4_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.


Detailed Description

IPv4 protocol.

Definition in file ipv4.c.


Function Documentation

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.

Parameters:
netdev Network device
address IPv4 address
netmask Subnet mask
gateway Gateway address (if any)
Return values:
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.

Parameters:
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.

Parameters:
dest Final destination address
Return values:
dest Next hop destination address
miniroute Routing table entry to use, or NULL if no route
If the route requires use of a gateway, the next hop destination address will be overwritten with the gateway address.

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.

Parameters:
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.

Parameters:
fragbug Fragment buffer

Definition at line 155 of file ipv4.c.

References free().

Referenced by ipv4_reassemble().

00155                                                          {
00156         free ( fragbuf );
00157 }

static struct io_buffer* ipv4_reassemble ( struct io_buffer iobuf  )  [static, read]

Fragment reassembler.

Parameters:
iobuf I/O buffer, fragment of the datagram
Return values:
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 }

static uint16_t ipv4_pshdr_chksum ( struct io_buffer iobuf,
uint16_t  csum 
) [static]

Add IPv4 pseudo-header checksum to existing checksum.

Parameters:
iobuf I/O buffer
csum Existing checksum
Return values:
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.

Parameters:
dest IPv4 destination address
src IPv4 source address
netdev Network device
ll_dest Link-layer destination address buffer
Return values:
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.

Parameters:
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
Return values:
rc Status
This function expects a transport-layer segment and prepends the IP header

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.

Parameters:
iobuf I/O buffer
netdev Network device
ll_source Link-layer destination source
This function expects an IP4 network datagram. It processes the headers and sends it to the transport layer.

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.

Parameters:
netdev Network device
net_addr Network-layer address
Return values:
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.

Parameters:
in IP address
Return values:
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 * ) &in;
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.

Parameters:
net_addr IP address
Return values:
string IP address in dotted-quad notation

Definition at line 522 of file ipv4.c.

References inet_ntoa().

00522                                                        {
00523         return inet_ntoa ( * ( ( struct in_addr * ) net_addr ) );
00524 }

static int ipv4_create_routes ( void   )  [static]

Create IPv4 routing table based on configured settings.

Return values:
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   ) 


Variable Documentation

uint16_t next_ident = 0 [static]

Definition at line 27 of file ipv4.c.

Referenced by ipv4_tx().

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 )

List of IPv4 miniroutes.

Definition at line 32 of file ipv4.c.

Referenced by route().

Initial value:

 {
        .name = "IP",
        .net_proto = htons ( ETH_P_IP ),
        .net_addr_len = sizeof ( struct in_addr ),
        .rx = ipv4_rx,
        .ntoa = ipv4_ntoa,
}
IPv4 protocol.

AoE protocol.

Definition at line 527 of file ipv4.c.

struct tcpip_net_protocol ipv4_tcpip_protocol __tcpip_net_protocol

Initial value:

 {
        .name = "IPv4",
        .sa_family = AF_INET,
        .tx = ipv4_tx,
}
IPv4 TCPIP net protocol.

Definition at line 536 of file ipv4.c.

struct arp_net_protocol ipv4_arp_protocol __arp_net_protocol

Initial value:

 {
        .net_protocol = &ipv4_protocol,
        .check = ipv4_arp_check,
}
IPv4 ARP protocol.

Definition at line 543 of file ipv4.c.

struct settings_applicator ipv4_settings_applicator __settings_applicator

Initial value:

 {
        .apply = ipv4_create_routes,
}
IPv4 settings applicator.

Definition at line 630 of file ipv4.c.


Generated on Tue Apr 6 20:01:55 2010 for gPXE by  doxygen 1.5.7.1