- Created src/arp.h: ARP packet struct, cache entry struct, operation codes, lookup/request/resolve/receive API, sysfs registration - Created src/arp.c: ARP cache with 32 entries, request/reply handling, ARP response to incoming requests for our IP, sysfs /sys/arp/table with formatted IP/MAC/interface/state columns - Created apps/arp/arp.c: reads and displays /sys/arp/table - Kernel calls arp_init() at boot, registered sysfs 'arp' namespace - Tested: clean boot, ARP initialized, arp app in CPIO
146 lines
4.3 KiB
C
146 lines
4.3 KiB
C
/**
|
|
* @file arp.h
|
|
* @brief Address Resolution Protocol (ARP) subsystem.
|
|
*
|
|
* Implements ARP (RFC 826) for mapping IPv4 addresses to Ethernet
|
|
* MAC addresses. Maintains an ARP cache and handles ARP requests
|
|
* and replies.
|
|
*
|
|
* The ARP table is exposed via sysfs at /sys/arp for userspace tools.
|
|
*/
|
|
|
|
#ifndef ARP_H
|
|
#define ARP_H
|
|
|
|
#include <stdint.h>
|
|
|
|
/** Maximum number of ARP cache entries. */
|
|
#define ARP_TABLE_SIZE 32
|
|
|
|
/** ARP hardware type: Ethernet */
|
|
#define ARP_HW_ETHER 1
|
|
|
|
/** ARP operation codes */
|
|
#define ARP_OP_REQUEST 1
|
|
#define ARP_OP_REPLY 2
|
|
|
|
/** ARP cache entry states */
|
|
#define ARP_STATE_FREE 0 /**< Unused slot. */
|
|
#define ARP_STATE_INCOMPLETE 1 /**< Request sent, awaiting reply. */
|
|
#define ARP_STATE_RESOLVED 2 /**< MAC address known. */
|
|
|
|
/* ================================================================
|
|
* ARP packet (28 bytes for IPv4-over-Ethernet)
|
|
* ================================================================ */
|
|
|
|
/**
|
|
* ARP packet structure for IPv4 over Ethernet.
|
|
* All multi-byte fields are in network byte order.
|
|
*/
|
|
typedef struct __attribute__((packed)) arp_packet {
|
|
uint16_t hw_type; /**< Hardware type (1 = Ethernet). */
|
|
uint16_t proto_type; /**< Protocol type (0x0800 = IPv4). */
|
|
uint8_t hw_len; /**< Hardware address length (6). */
|
|
uint8_t proto_len; /**< Protocol address length (4). */
|
|
uint16_t operation; /**< Operation (1=request, 2=reply). */
|
|
uint8_t sender_mac[6]; /**< Sender hardware address. */
|
|
uint32_t sender_ip; /**< Sender protocol address. */
|
|
uint8_t target_mac[6]; /**< Target hardware address. */
|
|
uint32_t target_ip; /**< Target protocol address. */
|
|
} arp_packet_t;
|
|
|
|
/** ARP packet size. */
|
|
#define ARP_PACKET_SIZE 28
|
|
|
|
/* ================================================================
|
|
* ARP cache entry
|
|
* ================================================================ */
|
|
|
|
/**
|
|
* ARP cache entry.
|
|
*/
|
|
typedef struct arp_entry {
|
|
uint32_t ip_addr; /**< IPv4 address (host byte order). */
|
|
uint8_t mac[6]; /**< Resolved MAC address. */
|
|
uint8_t state; /**< ARP_STATE_*. */
|
|
uint8_t iface_idx; /**< Ethernet interface index. */
|
|
uint32_t timestamp; /**< Time when entry was created (tick count). */
|
|
} arp_entry_t;
|
|
|
|
/* ================================================================
|
|
* Public API
|
|
* ================================================================ */
|
|
|
|
/**
|
|
* Initialize the ARP subsystem.
|
|
* Registers sysfs namespace "arp".
|
|
*/
|
|
void arp_init(void);
|
|
|
|
/**
|
|
* Look up an IP address in the ARP cache.
|
|
*
|
|
* @param ip IPv4 address (host byte order).
|
|
* @param mac Output: 6-byte MAC address if found.
|
|
* @return 0 if found and resolved, -1 if not in cache or incomplete.
|
|
*/
|
|
int arp_lookup(uint32_t ip, uint8_t *mac);
|
|
|
|
/**
|
|
* Send an ARP request for the given IP address.
|
|
*
|
|
* @param iface_idx Ethernet interface to send on.
|
|
* @param target_ip IP address to resolve (host byte order).
|
|
* @return 0 on success, -1 on failure.
|
|
*/
|
|
int arp_request(uint32_t iface_idx, uint32_t target_ip);
|
|
|
|
/**
|
|
* Resolve an IP address to a MAC address.
|
|
*
|
|
* Checks the ARP cache first. If not found, sends an ARP request
|
|
* and returns -1 (caller should retry later).
|
|
*
|
|
* @param iface_idx Ethernet interface index.
|
|
* @param ip IPv4 address (host byte order).
|
|
* @param mac Output: 6-byte MAC address.
|
|
* @return 0 if resolved, -1 if pending.
|
|
*/
|
|
int arp_resolve(uint32_t iface_idx, uint32_t ip, uint8_t *mac);
|
|
|
|
/**
|
|
* Process an incoming ARP packet.
|
|
*
|
|
* Called by the Ethernet subsystem when an ARP frame is received.
|
|
*
|
|
* @param data Raw ARP packet.
|
|
* @param len Packet length.
|
|
* @param iface_idx Interface the packet arrived on.
|
|
*/
|
|
void arp_receive(const void *data, uint32_t len, uint32_t iface_idx);
|
|
|
|
/**
|
|
* Add a static ARP entry.
|
|
*
|
|
* @param ip IPv4 address (host byte order).
|
|
* @param mac 6-byte MAC address.
|
|
* @param iface_idx Ethernet interface index.
|
|
* @return 0 on success, -1 if table full.
|
|
*/
|
|
int arp_add_static(uint32_t ip, const uint8_t *mac, uint32_t iface_idx);
|
|
|
|
/**
|
|
* Get an ARP table entry by index (for enumeration).
|
|
*
|
|
* @param index 0-based index.
|
|
* @return Pointer to entry, or NULL if out of range.
|
|
*/
|
|
const arp_entry_t *arp_get_entry(uint32_t index);
|
|
|
|
/**
|
|
* Get the number of active ARP entries.
|
|
*/
|
|
uint32_t arp_get_count(void);
|
|
|
|
#endif /* ARP_H */
|