Address Resolution Protocol implementation and cache management.
More...
|
struct | ARP |
| Address Resolution Protocol packet structure. More...
|
|
|
typedef ARP * | PARP |
| Pointer to ARP packet structure.
|
|
|
void | ShowArp () |
| Display the current ARP cache contents to the standard output.
|
|
void | fShowArp (FILE *fp) |
| Display the current ARP cache contents to a specified file stream.
|
|
BOOL | GetArpMacFromIp (IPADDR4 ip, MACADR &ma) |
| Check if an IP address is in the ARP cache and retrieve its MAC address.
|
|
void | sendGratuitousArp (int interfaceNumber, IPADDR4 ip) |
| Send a Gratuitous ARP to announce interface presence and IP address.
|
|
BOOL | IsMyAddressUsedArpDetect (uint16_t timeout, int interface=0) |
| Detect if the interface's IP address is already in use on the network.
|
|
int | GetProperInterface4 (IPADDR4 dst) |
| Get the appropriate network interface for routing to a destination IP.
|
|
void | processArp (PoolPtr p, PEFRAME pF) |
| Process incoming ARP packets (internal use only)
|
|
void | AddCheckArp (MACADR *ma, IPADDR4 ip, int ifnum) |
| Add or update ARP cache entry (internal use only)
|
|
void | DeleteArpFromIp (IPADDR4 ip) |
| Delete ARP cache entry by IP address (internal use only)
|
|
void | RouteOut (PEFRAME pf, IPADDR4 ip, PoolPtr p) |
| Route packet to destination (internal use only)
|
|
void | RouteOutVia (PEFRAME pf, IPADDR4 ipfrom, IPADDR4 ipto, PoolPtr p, int intf) |
| Route packet via specific interface (internal use only)
|
|
void | AgeArp () |
| Age out old ARP cache entries (internal use only)
|
|
void | AddStaticArp (MACADR *ma, IPADDR4 ip, int ifnum) |
| Add static ARP entry (internal use only)
|
|
void | InitializeArp () |
| Initialize ARP subsystem (internal use only)
|
|
Address Resolution Protocol implementation and cache management.
#include< arp.h>
The Address Resolution Protocol (ARP) is a fundamental network protocol that maps Internet Protocol (IP) addresses to physical Media Access Control (MAC) addresses on local Ethernet networks. ARP enables devices to discover the hardware address of another device on the same network segment when only the IP address is known.
How ARP Works
When a device needs to communicate with another device on the local network:
- Cache Check: First checks local ARP cache for existing IP-to-MAC mapping
- ARP Request: If not found, broadcasts an ARP request to all devices
- ARP Reply: Target device responds with its MAC address
- Cache Update: Mapping is stored in local ARP cache for future use
- Communication: Original packet is sent using the resolved MAC address
ARP Cache Management
NetBurner maintains an ARP cache that stores recently resolved IP-to-MAC address mappings. This cache:
- Reduces network traffic by avoiding repeated ARP requests
- Ages out entries after a timeout period
- Can be queried programmatically
- Supports static entries for critical devices
Function Categories
Example Usage
Querying the ARP Cache
#include <arp.h>
void checkDevicePresence(
IPADDR4 deviceIP) {
iprintf("Device found: ");
iprintf("%02X:%02X:%02X:%02X:%02X:%02X\n",
mac.ma[0], mac.ma[1], mac.ma[2],
mac.ma[3], mac.ma[4], mac.ma[5]);
} else {
iprintf("Device not in ARP cache\n");
}
}
Used to store and manipulate IPv4 addresses in dual stack mode.
Definition nettypes.h:225
Used to store and manipulate MAC addresses.
Definition nettypes.h:69
BOOL GetArpMacFromIp(IPADDR4 ip, MACADR &ma)
Check if an IP address is in the ARP cache and retrieve its MAC address.
Displaying ARP Cache Contents
#include <arp.h>
void displayNetworkStatus() {
iprintf("=== Current ARP Cache ===\n");
iprintf("========================\n");
}
void logArpToFile() {
FILE *fp = fopen("arp.log", "a");
if (fp != NULL) {
fclose(fp);
}
}
void fShowArp(FILE *fp)
Display the current ARP cache contents to a specified file stream.
void ShowArp()
Display the current ARP cache contents to the standard output.
Sending Gratuitous ARP
#include <arp.h>
#include <netinterface.h>
void announceNewIPAddress(
int interface,
IPADDR4 newIP) {
ib->
ip4.cur_addr = newIP;
iprintf("Gratuitous ARP sent for new IP\n");
}
void UserMain(void *pd) {
}
Network interface configuration block class for interface control and configuration.
Definition netinterface.h:245
I4Record ip4
IPv4 configuration for "this" interface, see config_netobj.h for details.
Definition netinterface.h:247
IPADDR4 AsciiToIp4(const char *p)
Convert an ASCII IPv4 string to an IP address.
void sendGratuitousArp(int interfaceNumber, IPADDR4 ip)
Send a Gratuitous ARP to announce interface presence and IP address.
int32_t GetFirstInterface(void)
Returns the Interface Number of the first registered network interface.
InterfaceBlock * GetInterfaceBlock(int interface=0)
Get an InterfaceBlock control and configuration object.
void init()
System initialization. Ideally called at the beginning of all applications, since the easiest Recover...
IP Address Conflict Detection
#include <arp.h>
void checkIPConflict(int interface) {
iprintf("ERROR: IP address conflict detected!\n");
iprintf("Another device is using this IP address.\n");
} else {
iprintf("No IP conflict detected - address is available\n");
}
}
void UserMain(void *pd) {
}
BOOL IsMyAddressUsedArpDetect(uint16_t timeout, int interface=0)
Detect if the interface's IP address is already in use on the network.
#define TICKS_PER_SECOND
System clock ticks per second.
Definition constants.h:49
bool WaitForActiveNetwork(uint32_t ticks_to_wait=120 *TICKS_PER_SECOND, int interface=-1)
Wait for an active network connection on at least one interface.
Network Device Monitoring
#include <arp.h>
#include <icmp.h>
bool isDeviceReachable(
IPADDR4 deviceIP) {
return true;
}
}
void monitorCriticalDevices() {
if (!isDeviceReachable(plc)) {
iprintf("WARNING: PLC not reachable!\n");
}
if (!isDeviceReachable(gateway)) {
iprintf("WARNING: Gateway not reachable!\n");
}
}
int Ping4(IPADDR4 to, uint16_t id, uint16_t seq, uint16_t maxwaitticks)
Send a "ping" packet and wait the specified timeout for a response.
Best Practices
- Cache Checking: Always check GetArpMacFromIp() return value
- Gratuitous ARP: Send after IP changes to update network caches
- Conflict Detection: Use IsMyAddressUsedArpDetect() during startup
- Triggering Resolution: Send ping to force ARP resolution if needed
- Cache Monitoring: Use ShowArp() for debugging network issues
Troubleshooting
Device Not in Cache:
- Device may be offline or unreachable
- No recent communication with device
- Send ping or UDP packet to trigger ARP resolution
IP Address Conflict:
Stale Cache Entries:
- Entries age out automatically
- Power cycle or reset may be needed for recovery
- Use gratuitous ARP to update remote caches
Important Notes
- Note
- GetArpMacFromIp() only checks the cache - it does not send ARP requests. To force ARP resolution, send a ping or packet to the target first.
-
Gratuitous ARP should be sent whenever an interface IP address changes or during system initialization to ensure network-wide cache consistency.
-
ARP only works on the local network segment. Devices on different subnets require routing through a gateway.
- Warning
- IP address conflicts can cause serious network communication issues. Always use IsMyAddressUsedArpDetect() when configuring static IPs.
-
The ARP cache has limited size. Entries are aged out over time to make room for new entries.
Protocol Specifications
- RFC 826: Address Resolution Protocol (ARP) specification
- RFC 5227: IPv4 Address Conflict Detection (ACD)
- RFC 3927: Dynamic Configuration of IPv4 Link-Local Addresses
- See also
- groupICMP For ICMP/Ping functionality
-
groupNetInterface For network interface management
-
groupIPv4 For IPv4 address handling
◆ PARP
#include <arp.h>
Pointer to ARP packet structure.
Convenience typedef for pointer to ARP structure. Used throughout the NetBurner stack for packet processing.
◆ fShowArp()
void fShowArp |
( |
FILE * | fp | ) |
|
#include <arp.h>
Display the current ARP cache contents to a specified file stream.
Similar to ShowArp() but outputs to a specified FILE pointer instead of the standard output. This allows ARP cache contents to be written to:
- Log files on SD card or file system
- Network sockets
- Serial ports via fdopen()
- Any other FILE stream destination
- Parameters
-
fp | Pointer to FILE stream for output. Must be a valid, open FILE pointer (from fopen(), fdopen(), etc.) |
- Precondition
- fp must be a valid, open FILE pointer with write access
- Postcondition
- ARP cache contents are written to the specified FILE stream
- Note
- The FILE pointer must remain valid for the duration of the call
-
Does not close the FILE pointer - caller is responsible for fclose()
-
Output format is identical to ShowArp()
- Example: Logging to SD Card
#include <arp.h>
void logArpCache() {
FILE *fp = fopen("SD:/arp_cache.log", "a");
if (fp != NULL) {
fprintf(fp, "\n=== ARP Cache at %lu seconds ===\n", Secs);
fprintf(fp, "================================\n");
fclose(fp);
} else {
iprintf("ERROR: Could not open log file\n");
}
}
- Example: Sending via Network Socket
void sendArpCacheToClient(int clientFd) {
FILE *fp = fdopen(clientFd, "w");
if (fp != NULL) {
fprintf(fp, "Current ARP Cache:\r\n");
fprintf(fp, "==================\r\n");
fflush(fp);
}
}
- Example: Multiple Output Destinations
void reportArpCache() {
FILE *fp = fopen("SD:/network.log", "a");
if (fp) {
fclose(fp);
}
int serverFd = connect4(serverIP, serverPort, 0);
if (serverFd > 0) {
FILE *netfp = fdopen(serverFd, "w");
fflush(netfp);
}
}
int close(int fd)
Close the specified file descriptor and free the associated resources.
- Example: Custom Formatting Wrapper
void formattedArpReport(FILE *fp) {
fprintf(fp, "\n");
fprintf(fp, "╔════════════════════════════════════╗\n");
fprintf(fp, "║ ARP CACHE REPORT ║\n");
fprintf(fp, "║ %s", ctime(&now));
fprintf(fp, "╠════════════════════════════════════╣\n");
fprintf(fp, "╚════════════════════════════════════╝\n");
}
time_t time(time_t *pt)
Gets the current system GMT time.
- See also
- ShowArp() For output to standard stdio
-
GetArpMacFromIp() To query specific ARP entries
◆ GetArpMacFromIp()
#include <arp.h>
Check if an IP address is in the ARP cache and retrieve its MAC address.
Queries the local ARP cache to determine if a mapping exists for the specified IP address. If found, the corresponding MAC address is returned via the reference parameter.
This function ONLY checks the cache - it does not send ARP requests over the network. If the entry is not in the cache, you may need to send a packet (such as a ping) to the target IP to trigger ARP resolution first.
- Parameters
-
| ip | IP address to look up in the ARP cache |
[out] | ma | Reference to MACADR structure that will receive the MAC address if found. Only modified if the function returns TRUE. |
- Returns
- TRUE if the IP address was found in the cache and MAC address retrieved
-
FALSE if the IP address is not in the cache
- Precondition
- ip must be a valid IPv4 address
- Postcondition
- If TRUE is returned, ma contains the resolved MAC address
-
If FALSE is returned, ma is unmodified
- Note
- This function does NOT send ARP requests - it only checks the cache
-
To force ARP resolution, send a ping or packet to the target first
-
Cache entries age out over time - a FALSE result doesn't mean the device is offline, just that it's not in the current cache
- Example: Basic Cache Query
#include <arp.h>
void checkDevice(
IPADDR4 deviceIP) {
iprintf("Device MAC: %02X:%02X:%02X:%02X:%02X:%02X\n",
mac.ma[0], mac.ma[1], mac.ma[2],
mac.ma[3], mac.ma[4], mac.ma[5]);
} else {
iprintf("Device not in ARP cache\n");
}
}
- Example: Forcing ARP Resolution
#include <arp.h>
#include <icmp.h>
return true;
}
iprintf("Resolving MAC for ");
ShowIP(ip);
iprintf("...\n");
iprintf("MAC resolved successfully\n");
return true;
}
iprintf("Failed to resolve MAC - device may be offline\n");
return false;
}
- Example: Device Presence Detection
}
void monitorDevices() {
while (1) {
if (!isDevicePresent(plc)) {
iprintf("WARNING: PLC not responding\n");
}
if (!isDevicePresent(hmi)) {
iprintf("WARNING: HMI not responding\n");
}
}
}
- Example: MAC Address Filtering
bool isAuthorizedMAC(
const MACADR &mac) {
static const MACADR authorized[] = {
{{0x00, 0x11, 0x22, 0x33, 0x44, 0x55}},
{{0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}}
};
for (size_t i = 0; i < sizeof(authorized)/sizeof(authorized[0]); i++) {
if (memcmp(&mac, &authorized[i],
sizeof(
MACADR)) == 0) {
return true;
}
}
return false;
}
bool allowConnection(
IPADDR4 clientIP) {
return isAuthorizedMAC(mac);
}
return false;
}
- See also
- ShowArp() To display all cached entries
-
sendGratuitousArp() To announce device presence
-
Ping4() To trigger ARP resolution
◆ GetProperInterface4()
int GetProperInterface4 |
( |
IPADDR4 | dst | ) |
|
#include <arp.h>
Get the appropriate network interface for routing to a destination IP.
Determines which network interface should be used to reach a specific IPv4 destination address based on routing table and interface configuration.
- Parameters
-
dst | Destination IPv4 address to route to |
- Returns
- Interface number to use for routing to dst, or -1 if no route available
- Note
- This is primarily for internal stack use
-
Consider using GetInterfaceBlock() for interface queries
◆ IsMyAddressUsedArpDetect()
BOOL IsMyAddressUsedArpDetect |
( |
uint16_t | timeout, |
|
|
int | interface = 0 ) |
#include <arp.h>
Detect if the interface's IP address is already in use on the network.
Performs ARP-based IP address conflict detection by sending ARP probes and listening for replies. This is used to detect if another device on the network is already using the interface's configured IP address.
This function is critical for:
- Validating static IP configurations
- Detecting duplicate IPs during startup
- Implementing IPv4 Link-Local addressing (169.254.x.x)
- Preventing IP conflicts in dynamic reconfiguration
- Parameters
-
timeout | Maximum time to wait for replies, in seconds. Typical values are 1-5 seconds. Longer timeouts provide more reliable detection but delay startup. |
interface | Network interface number to check (default = 0 for primary interface). Use GetFirstInterface() for the default interface. |
- Returns
- TRUE if another device is already using this IP address (conflict detected)
-
FALSE if the IP address is available (no conflict)
- Precondition
- The interface must be initialized with a valid IP address
-
The network interface must be physically active (link up)
- Postcondition
- Function blocks for up to timeout seconds while probing
- Note
- This function blocks for the specified timeout period
-
Multiple ARP probes may be sent during the detection period
-
FALSE does not guarantee the IP is permanently available - conflicts can occur after this check completes
- Warning
- This function can take several seconds to complete. Do not call from time-critical code or ISRs.
-
A return value of FALSE does not prevent future conflicts. Another device may start using the IP after this check.
- Example: Startup IP Conflict Check
#include <arp.h>
void UserMain(void *pd) {
iprintf("Checking for IP address conflicts...\n");
iprintf("ERROR: IP address conflict detected!\n");
iprintf("Another device is using this IP address.\n");
iprintf("Please reconfigure the IP address.\n");
while (1) {
}
} else {
iprintf("No IP conflict - address is available\n");
}
}
- Example: Auto-Recovery from Conflict
bool findAvailableIP(
int interface,
IPADDR4 baseIP) {
for (int offset = 0; offset < 10; offset++) {
ib->
ip4.cur_addr = testIP;
iprintf("Testing ");
ShowIP(testIP);
iprintf("...\n");
iprintf("Available IP found: ");
ShowIP(testIP);
iprintf("\n");
return true;
}
ib->
ip4.cur_addr = oldIP;
}
return false;
}
- Example: Link-Local IP Assignment
#include <arp.h>
#include <stdlib.h>
IPADDR4 assignLinkLocalIP(
int interface) {
srand(Secs);
for (int attempts = 0; attempts < 100; attempts++) {
int hostBits = (rand() % 254) + 1;
IPADDR4 testIP = baseIP + hostBits;
ib->
ip4.cur_addr = testIP;
return testIP;
}
iprintf("Conflict on ");
ShowIP(testIP);
iprintf(" - trying another...\n");
}
return 0;
}
- Example: Configuration Validation
bool validateStaticIPConfig(const char *ipStr) {
ib->
ip4.cur_addr = newIP;
iprintf("Validating IP configuration: %s\n", ipStr);
if (conflict) {
iprintf("ERROR: IP %s is already in use!\n", ipStr);
ib->
ip4.cur_addr = oldIP;
return false;
} else {
iprintf("IP %s is available\n", ipStr);
return true;
}
}
- See also
- sendGratuitousArp() To announce IP after successful check
-
GetArpMacFromIp() To identify conflicting device's MAC
-
InterfaceIP4() To get interface IP address
◆ sendGratuitousArp()
void sendGratuitousArp |
( |
int | interfaceNumber, |
|
|
IPADDR4 | ip ) |
#include <arp.h>
Send a Gratuitous ARP to announce interface presence and IP address.
Sends a gratuitous ARP request/reply to inform all devices on the local network about this interface's IP-to-MAC address mapping. This updates the ARP caches of all devices on the network segment.
Gratuitous ARP should be sent whenever:
- The system boots up or an interface is initialized
- An IP address is changed or reconfigured
- Taking over an IP from another device (failover)
- After detecting and resolving an IP address conflict
- Parameters
-
interfaceNumber | Network interface number (0 for primary interface, use GetFirstInterface() for the default interface) |
ip | IP address to announce. Should be the interface's currently configured IP address. Must be a valid, non-zero IP address. |
- Precondition
- The interface must be initialized and have a valid IP address
-
interfaceNumber must be a valid interface number
- Postcondition
- Gratuitous ARP is broadcast on the specified interface
-
Other devices on the network will update their ARP caches
- Note
- This is a broadcast - all devices on the network segment will receive and process the announcement
-
It may take a few milliseconds for other devices to update their caches after receiving the gratuitous ARP
- Warning
- Do not send gratuitous ARP before the interface has a valid IP address - this will send an invalid announcement
-
Excessive gratuitous ARP sending can cause unnecessary network traffic. Only send when needed, not continuously.
- Example: Startup Announcement
#include <arp.h>
#include <netinterface.h>
void UserMain(void *pd) {
IPADDR4 myIP = InterfaceIP4(iface);
iprintf("Sent gratuitous ARP for ");
ShowIP(myIP);
iprintf("\n");
}
- Example: IP Address Change
#include <arp.h>
#include <netinterface.h>
void changeIPAddress(
IPADDR4 newIP) {
ib->
ip4.cur_addr = newIP;
iprintf("IP address changed to ");
ShowIP(newIP);
iprintf("\n");
iprintf("Gratuitous ARP sent - network caches updated\n");
}
- Example: Failover Scenario
void takeOverBackupIP(
IPADDR4 backupIP) {
iprintf("Taking over backup IP ");
ShowIP(backupIP);
iprintf("...\n");
ib->
ip4.cur_addr = backupIP;
for (int i = 0; i < 3; i++) {
}
iprintf("Failover complete - now responding on backup IP\n");
}
- Example: Post-Conflict Resolution
void resolveIPConflict() {
IPADDR4 currentIP = InterfaceIP4(iface);
ib->
ip4.cur_addr = newIP;
iprintf("IP conflict resolved - changed to ");
ShowIP(newIP);
iprintf("\n");
}
- Example: Multi-Interface System
void announceAllInterfaces() {
int numInterfaces = GetNumInterfaces();
for (int i = 0; i < numInterfaces; i++) {
if (ifaceIP != 0) {
iprintf("Interface %d announced\n", i);
}
}
}
- See also
- IsMyAddressUsedArpDetect() To detect IP conflicts
-
GetArpMacFromIp() To query ARP cache
-
InterfaceIP4() To get interface IP address
◆ ShowArp()
#include <arp.h>
Display the current ARP cache contents to the standard output.
Displays all entries in the ARP cache to the stdio serial port (typically the debug serial port). Each entry shows the IP address, MAC address, interface number, and entry status.
This function is useful for debugging network connectivity issues, verifying ARP resolution, and monitoring which devices are in the cache.
- Postcondition
- ARP cache contents are written to stdio serial port
- Note
- Output format includes IP address, MAC address, interface, and flags
-
Output goes to the default stdio serial port (cannot be redirected)
-
For file or socket output, use fShowArp() instead
- Output Format Example:
IP Address MAC Address Iface Flags
============================================
192.168.1.1 00:11:22:33:44:55 0 P
192.168.1.100 AA:BB:CC:DD:EE:FF 0
192.168.1.50 12:34:56:78:9A:BC 0 S
Where flags may be:
- P: Permanent entry
- S: Static entry
- (blank): Dynamic entry
- Example: Basic Debugging
void displayNetworkInfo() {
iprintf("\n=== Network ARP Cache ===\n");
iprintf("=========================\n\n");
}
- Example: Periodic Cache Display
void monitorArpCache(void *pd) {
while (1) {
iprintf("\n--- ARP Cache Update ---\n");
}
}
void UserMain(void *pd) {
OSSimpleTaskCreatewName(monitorArpCache,
MAIN_PRIO - 1,
"ArpMonitor");
}
#define MAIN_PRIO
Recommend UserMain priority.
Definition constants.h:130
- Example: Troubleshooting Connectivity
void troubleshootConnection(
IPADDR4 targetIP) {
iprintf("Checking connection to ");
ShowIP(targetIP);
iprintf("\n");
iprintf("\nSending ping...\n");
iprintf("\nUpdated ARP cache:\n");
}
- See also
- fShowArp() For output to FILE pointer
-
GetArpMacFromIp() To query specific ARP entries
◆ hard_size
Hardware address length (6 for MAC)
Hardware address length (HLEN). For Ethernet (MAC) this is 6 bytes.
◆ hard_Type
beuint16_t ARP::hard_Type |
Hardware type (1 for Ethernet)
Hardware type (HTYPE). For Ethernet this is 1. Network byte order (big-endian).
◆ op_code
Operation: 1=Request, 2=Reply.
Operation code. Network byte order (big-endian).
- 1 = ARP Request
- 2 = ARP Reply
- 3 = RARP Request
- 4 = RARP Reply
◆ prot_size
Protocol address length (4 for IPv4)
Protocol address length (PLEN). For IPv4 this is 4 bytes.
◆ prot_Type
beuint16_t ARP::prot_Type |
Protocol type (0x0800 for IPv4)
Protocol type (PTYPE). For IPv4 this is 0x0800. Network byte order (big-endian).
◆ sender_Ip
Sender IP address.
Sender protocol (IP) address. The IPv4 address of the device sending this ARP packet.
◆ sender_phy
Sender MAC address.
Sender hardware (MAC) address. The MAC address of the device sending this ARP packet.
◆ target_Ip
Target IP address.
Target protocol (IP) address. The IPv4 address being queried (in requests) or resolved (in replies).
- Note
- This structure is packed to match exact network packet format
-
All multi-byte fields use network byte order (big-endian)
-
Do not change structure without careful consideration of network compatibility
- Warning
- Structure changes will break network protocol compatibility
-
Always add new fields at the end to maintain compatibility
- Typical ARP Request Packet:
beuint16_t prot_Type
Protocol type (0x0800 for IPv4)
Definition arp.h:1037
uint8_t hard_size
Hardware address length (6 for MAC)
Definition arp.h:1038
beuint16_t hard_Type
Hardware type (1 for Ethernet)
Definition arp.h:1036
uint8_t prot_size
Protocol address length (4 for IPv4)
Definition arp.h:1039
beuint16_t op_code
Operation: 1=Request, 2=Reply.
Definition arp.h:1040
Address Resolution Protocol packet structure.
Definition arp.h:1035
- See also
- RFC 826 - Address Resolution Protocol specification
◆ target_phy
Target MAC address.
Target hardware (MAC) address. In ARP requests this is typically all zeros. In replies, this contains the requested MAC address.