#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_entry * | arp_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_protocol * | arp_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. | |
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 NUM_ARP_ENTRIES 4 |
| #define arp_table_end &arp_table[NUM_ARP_ENTRIES] |
| 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.
| ll_protocol | Link-layer protocol | |
| net_protocol | Network-layer protocol | |
| net_addr | Network-layer address |
| 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.
| netdev | Network device | |
| net_protocol | Network-layer protocol | |
| dest_net_addr | Destination network-layer address | |
| source_net_addr | Source network-layer address |
| dest_ll_addr | Destination link layer address | |
| rc | Return status code |
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.
| net_proto | Network-layer protocol, in network-endian order |
| 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.
| iobuf | I/O buffer | |
| netdev | Network device | |
| ll_source | Link-layer source address |
| rc | Return status code |
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] |
unsigned int next_new_arp_entry = 0 [static] |
| struct net_protocol arp_protocol |
Definition at line 66 of file arp.c.
Referenced by arp_resolve(), arp_rx(), pxenv_undi_isr(), and pxenv_undi_transmit().
1.5.7.1