arp.c File Reference

Address Resolution Protocol. More...

#include <stdint.h>
#include <string.h>
#include <byteswap.h>
#include <errno.h>
#include <gpxe/if_ether.h>
#include <gpxe/if_arp.h>
#include <gpxe/iobuf.h>
#include <gpxe/netdevice.h>
#include <gpxe/arp.h>

Go to the source code of this file.

Data Structures

struct  arp_entry
 An ARP cache entry. More...

Defines

#define NUM_ARP_ENTRIES   4
 Number of entries in the ARP cache.
#define arp_table_end   &arp_table[NUM_ARP_ENTRIES]

Functions

 FILE_LICENCE (GPL2_OR_LATER)
static struct arp_entryarp_find_entry (struct ll_protocol *ll_protocol, struct net_protocol *net_protocol, const void *net_addr)
 Find entry in the ARP cache.
int arp_resolve (struct net_device *netdev, struct net_protocol *net_protocol, const void *dest_net_addr, const void *source_net_addr, void *dest_ll_addr)
 Look up media-specific link-layer address in the ARP cache.
static struct arp_net_protocolarp_find_protocol (uint16_t net_proto)
 Identify ARP protocol.
static int arp_rx (struct io_buffer *iobuf, struct net_device *netdev, const void *ll_source __unused)
 Process incoming ARP packets.
static const char * arp_ntoa (const void *net_addr __unused)
 Transcribe ARP address.

Variables

static struct arp_entry arp_table [NUM_ARP_ENTRIES]
 The ARP cache.
static unsigned int next_new_arp_entry = 0
struct net_protocol arp_protocol
struct net_protocol arp_protocol __net_protocol
 ARP protocol.


Detailed Description

Address Resolution Protocol.

This file implements the address resolution protocol as defined in RFC826. The implementation is media-independent and protocol-independent; it is not limited to Ethernet or to IPv4.

Definition in file arp.c.


Define Documentation

#define NUM_ARP_ENTRIES   4

Number of entries in the ARP cache.

This is a global cache, covering all network interfaces, network-layer protocols and link-layer protocols.

Definition at line 58 of file arp.c.

Referenced by arp_rx().

#define arp_table_end   &arp_table[NUM_ARP_ENTRIES]

Definition at line 62 of file arp.c.

Referenced by arp_find_entry().


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER   ) 

static struct arp_entry* arp_find_entry ( struct ll_protocol ll_protocol,
struct net_protocol net_protocol,
const void *  net_addr 
) [static, read]

Find entry in the ARP cache.

Parameters:
ll_protocol Link-layer protocol
net_protocol Network-layer protocol
net_addr Network-layer address
Return values:
arp ARP cache entry, or NULL if not found

Definition at line 78 of file arp.c.

References arp_table, arp_table_end, arp_entry::ll_protocol, memcmp(), arp_entry::net_addr, net_protocol::net_addr_len, arp_entry::net_protocol, and NULL.

Referenced by arp_resolve(), and arp_rx().

00080                                         {
00081         struct arp_entry *arp;
00082 
00083         for ( arp = arp_table ; arp < arp_table_end ; arp++ ) {
00084                 if ( ( arp->ll_protocol == ll_protocol ) &&
00085                      ( arp->net_protocol == net_protocol ) &&
00086                      ( memcmp ( arp->net_addr, net_addr,
00087                                 net_protocol->net_addr_len ) == 0 ) )
00088                         return arp;
00089         }
00090         return NULL;
00091 }

int arp_resolve ( struct net_device netdev,
struct net_protocol net_protocol,
const void *  dest_net_addr,
const void *  source_net_addr,
void *  dest_ll_addr 
)

Look up media-specific link-layer address in the ARP cache.

Parameters:
netdev Network device
net_protocol Network-layer protocol
dest_net_addr Destination network-layer address
source_net_addr Source network-layer address
Return values:
dest_ll_addr Destination link layer address
rc Return status code
This function will use the ARP cache to look up the link-layer address for the link-layer protocol associated with the network device and the given network-layer protocol and addresses. If found, the destination link-layer address will be filled in in dest_ll_addr.

If no address is found in the ARP cache, an ARP request will be transmitted on the specified network device and -ENOENT will be returned.

Definition at line 113 of file arp.c.

References alloc_iob(), arphdr::ar_hln, arphdr::ar_hrd, arphdr::ar_op, arphdr::ar_pln, arphdr::ar_pro, arp_find_entry(), arp_protocol, ARPOP_REQUEST, DBG, ENOENT, ENOMEM, htons, iob_put, iob_reserve, net_device::ll_addr, arp_entry::ll_addr, ll_protocol::ll_addr_len, net_device::ll_broadcast, ll_protocol::ll_proto, net_device::ll_protocol, MAX_LL_ADDR_LEN, MAX_LL_HEADER_LEN, MAX_NET_ADDR_LEN, memcpy, memset(), ll_protocol::name, net_protocol::name, arp_entry::net_addr, net_protocol::net_addr_len, net_protocol::net_proto, net_tx(), ll_protocol::ntoa, and net_protocol::ntoa.

Referenced by ipv4_ll_addr().

00115                                        {
00116         struct ll_protocol *ll_protocol = netdev->ll_protocol;
00117         const struct arp_entry *arp;
00118         struct io_buffer *iobuf;
00119         struct arphdr *arphdr;
00120         int rc;
00121 
00122         /* Look for existing entry in ARP table */
00123         arp = arp_find_entry ( ll_protocol, net_protocol, dest_net_addr );
00124         if ( arp ) {
00125                 DBG ( "ARP cache hit: %s %s => %s %s\n",
00126                       net_protocol->name, net_protocol->ntoa ( arp->net_addr ),
00127                       ll_protocol->name, ll_protocol->ntoa ( arp->ll_addr ) );
00128                 memcpy ( dest_ll_addr, arp->ll_addr, ll_protocol->ll_addr_len);
00129                 return 0;
00130         }
00131         DBG ( "ARP cache miss: %s %s\n", net_protocol->name,
00132               net_protocol->ntoa ( dest_net_addr ) );
00133 
00134         /* Allocate ARP packet */
00135         iobuf = alloc_iob ( MAX_LL_HEADER_LEN + sizeof ( *arphdr ) +
00136                           2 * ( MAX_LL_ADDR_LEN + MAX_NET_ADDR_LEN ) );
00137         if ( ! iobuf )
00138                 return -ENOMEM;
00139         iob_reserve ( iobuf, MAX_LL_HEADER_LEN );
00140 
00141         /* Build up ARP request */
00142         arphdr = iob_put ( iobuf, sizeof ( *arphdr ) );
00143         arphdr->ar_hrd = ll_protocol->ll_proto;
00144         arphdr->ar_hln = ll_protocol->ll_addr_len;
00145         arphdr->ar_pro = net_protocol->net_proto;
00146         arphdr->ar_pln = net_protocol->net_addr_len;
00147         arphdr->ar_op = htons ( ARPOP_REQUEST );
00148         memcpy ( iob_put ( iobuf, ll_protocol->ll_addr_len ),
00149                  netdev->ll_addr, ll_protocol->ll_addr_len );
00150         memcpy ( iob_put ( iobuf, net_protocol->net_addr_len ),
00151                  source_net_addr, net_protocol->net_addr_len );
00152         memset ( iob_put ( iobuf, ll_protocol->ll_addr_len ),
00153                  0, ll_protocol->ll_addr_len );
00154         memcpy ( iob_put ( iobuf, net_protocol->net_addr_len ),
00155                  dest_net_addr, net_protocol->net_addr_len );
00156 
00157         /* Transmit ARP request */
00158         if ( ( rc = net_tx ( iobuf, netdev, &arp_protocol, 
00159                              netdev->ll_broadcast ) ) != 0 )
00160                 return rc;
00161 
00162         return -ENOENT;
00163 }

static struct arp_net_protocol* arp_find_protocol ( uint16_t  net_proto  )  [static, read]

Identify ARP protocol.

Parameters:
net_proto Network-layer protocol, in network-endian order
Return values:
arp_net_protocol ARP protocol, or NULL

Definition at line 172 of file arp.c.

References ARP_NET_PROTOCOLS, for_each_table_entry, net_protocol::net_proto, arp_net_protocol::net_protocol, and NULL.

Referenced by arp_rx().

00172                                                                           {
00173         struct arp_net_protocol *arp_net_protocol;
00174 
00175         for_each_table_entry ( arp_net_protocol, ARP_NET_PROTOCOLS ) {
00176                 if ( arp_net_protocol->net_protocol->net_proto == net_proto ) {
00177                         return arp_net_protocol;
00178                 }
00179         }
00180         return NULL;
00181 }

static int arp_rx ( struct io_buffer iobuf,
struct net_device netdev,
const void *ll_source  __unused 
) [static]

Process incoming ARP packets.

Parameters:
iobuf I/O buffer
netdev Network device
ll_source Link-layer source address
Return values:
rc Return status code
This handles ARP requests and responses as detailed in RFC826. The method detailed within the RFC is pretty optimised, handling requests and responses with basically a single code path and avoiding the need for extraneous ARP requests; read the RFC for details.

Definition at line 197 of file arp.c.

References arphdr::ar_hln, arphdr::ar_hrd, arphdr::ar_op, arphdr::ar_pln, arphdr::ar_pro, arp_find_entry(), arp_find_protocol(), arp_protocol, arp_sender_ha(), arp_sender_pa(), arp_table, arp_target_ha(), arp_target_pa(), ARPOP_REPLY, ARPOP_REQUEST, arp_net_protocol::check, io_buffer::data, DBG, free_iob(), htons, iob_disown, net_device::ll_addr, arp_entry::ll_addr, ll_protocol::ll_addr_len, ll_protocol::ll_proto, arp_entry::ll_protocol, net_device::ll_protocol, memcpy, ll_protocol::name, net_protocol::name, arp_entry::net_addr, net_protocol::net_addr_len, arp_entry::net_protocol, arp_net_protocol::net_protocol, net_tx(), next_new_arp_entry, ll_protocol::ntoa, net_protocol::ntoa, and NUM_ARP_ENTRIES.

00198                                                      {
00199         struct arphdr *arphdr = iobuf->data;
00200         struct arp_net_protocol *arp_net_protocol;
00201         struct net_protocol *net_protocol;
00202         struct ll_protocol *ll_protocol;
00203         struct arp_entry *arp;
00204         int merge = 0;
00205 
00206         /* Identify network-layer and link-layer protocols */
00207         arp_net_protocol = arp_find_protocol ( arphdr->ar_pro );
00208         if ( ! arp_net_protocol )
00209                 goto done;
00210         net_protocol = arp_net_protocol->net_protocol;
00211         ll_protocol = netdev->ll_protocol;
00212 
00213         /* Sanity checks */
00214         if ( ( arphdr->ar_hrd != ll_protocol->ll_proto ) ||
00215              ( arphdr->ar_hln != ll_protocol->ll_addr_len ) ||
00216              ( arphdr->ar_pln != net_protocol->net_addr_len ) )
00217                 goto done;
00218 
00219         /* See if we have an entry for this sender, and update it if so */
00220         arp = arp_find_entry ( ll_protocol, net_protocol,
00221                                arp_sender_pa ( arphdr ) );
00222         if ( arp ) {
00223                 memcpy ( arp->ll_addr, arp_sender_ha ( arphdr ),
00224                          arphdr->ar_hln );
00225                 merge = 1;
00226                 DBG ( "ARP cache update: %s %s => %s %s\n",
00227                       net_protocol->name, net_protocol->ntoa ( arp->net_addr ),
00228                       ll_protocol->name, ll_protocol->ntoa ( arp->ll_addr ) );
00229         }
00230 
00231         /* See if we own the target protocol address */
00232         if ( arp_net_protocol->check ( netdev, arp_target_pa ( arphdr ) ) != 0)
00233                 goto done;
00234         
00235         /* Create new ARP table entry if necessary */
00236         if ( ! merge ) {
00237                 arp = &arp_table[next_new_arp_entry++ % NUM_ARP_ENTRIES];
00238                 arp->ll_protocol = ll_protocol;
00239                 arp->net_protocol = net_protocol;
00240                 memcpy ( arp->ll_addr, arp_sender_ha ( arphdr ),
00241                          arphdr->ar_hln );
00242                 memcpy ( arp->net_addr, arp_sender_pa ( arphdr ),
00243                          arphdr->ar_pln);
00244                 DBG ( "ARP cache add: %s %s => %s %s\n",
00245                       net_protocol->name, net_protocol->ntoa ( arp->net_addr ),
00246                       ll_protocol->name, ll_protocol->ntoa ( arp->ll_addr ) );
00247         }
00248 
00249         /* If it's not a request, there's nothing more to do */
00250         if ( arphdr->ar_op != htons ( ARPOP_REQUEST ) )
00251                 goto done;
00252 
00253         /* Change request to a reply */
00254         DBG ( "ARP reply: %s %s => %s %s\n", net_protocol->name,
00255               net_protocol->ntoa ( arp_target_pa ( arphdr ) ),
00256               ll_protocol->name, ll_protocol->ntoa ( netdev->ll_addr ) );
00257         arphdr->ar_op = htons ( ARPOP_REPLY );
00258         memswap ( arp_sender_ha ( arphdr ), arp_target_ha ( arphdr ),
00259                  arphdr->ar_hln + arphdr->ar_pln );
00260         memcpy ( arp_sender_ha ( arphdr ), netdev->ll_addr, arphdr->ar_hln );
00261 
00262         /* Send reply */
00263         net_tx ( iob_disown ( iobuf ), netdev, &arp_protocol,
00264                  arp_target_ha ( arphdr ) );
00265 
00266  done:
00267         free_iob ( iobuf );
00268         return 0;
00269 }

static const char* arp_ntoa ( const void *net_addr  __unused  )  [static]

Transcribe ARP address.

Parameters:
net_addr ARP address
Return values:
string "<ARP>"
This operation is meaningless for the ARP protocol.

Definition at line 279 of file arp.c.

00279                                                                {
00280         return "<ARP>";
00281 }


Variable Documentation

struct arp_entry arp_table[NUM_ARP_ENTRIES] [static]

The ARP cache.

Definition at line 61 of file arp.c.

Referenced by arp_find_entry(), and arp_rx().

unsigned int next_new_arp_entry = 0 [static]

Definition at line 64 of file arp.c.

Referenced by arp_rx().

Definition at line 66 of file arp.c.

Referenced by arp_resolve(), arp_rx(), pxenv_undi_isr(), and pxenv_undi_transmit().

Initial value:

 {
        .name = "ARP",
        .net_proto = htons ( ETH_P_ARP ),
        .rx = arp_rx,
        .ntoa = arp_ntoa,
}
ARP protocol.

AoE protocol.

Definition at line 284 of file arp.c.


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