The Ethernet article carries a table of EtherType values, and its second row reads:
0x0806 ARP
It went unexplained there. This page is the explanation.
And what it solves is a gap nobody sees until they look for it. IP knows which address to send to. Ethernet knows how to reach any card on the wire. Nothing says which card that address is at.
The gap between two layers
The two layers were kept separate deliberately. IP knows nothing of Ethernet and Ethernet knows nothing of IP, which is why IP runs over anything at all.
The price of that separation is needing something to translate between the two worlds, and that something is ARP.
RFC 826, from November 1982 by David C. Plummer, names itself after exactly that job: "An Ethernet Address Resolution Protocol -- or -- Converting Network Protocol Addresses to 48.bit Ethernet Address for Transmission on Ethernet Hardware".
The whole document is under ten pages, and has barely been touched since.
If you have never looked, start here
That translation table lives on every machine, and can be read.
$ arp -an
? (192.0.2.1) at 00:00:5e:00:53:01 on en0 ifscope [ethernet]
? (192.0.2.7) at 00:00:5e:00:53:07 on en0 ifscope [ethernet]
? (192.0.2.31) at 00:00:5e:00:53:11 on en0 permanent [ethernet]
Every row is an answer that was asked for once, and kept so it need not be asked again.
The word permanent means that entry does not expire, which on most machines covers the machine's own address and a few special ones. Rows without it disappear on their own when unused.
The question it actually asks is not the one people think
This is the most misunderstood point in the whole subject.
People assume a machine asks for the MAC of whatever it wants to talk to. That is true only when the destination is on the same wire.
Before asking, the machine makes one decision, by running the destination address through its own mask — the same arithmetic the subnetting article describes.
Same network? Ask for that destination's MAC directly.
Different network? Do not ask for the destination at all. Ask for the gateway's MAC instead.
The reason is plain: a machine on another network is not on this wire, so asking would reach nobody. The destination MAC in the frame is therefore always a neighbour's, while the destination address in the packet never changes.
This explains a symptom people meet often. Get one bit of the mask wrong and the machine immediately asks for the wrong party, and nobody answers, while everything else is correct.
The shape of the packet
off field octets meaning
0 hrd 2 hardware type, 1 = ethernet
2 pro 2 protocol type, 0x0800 = IPv4
4 hln 1 hardware address length, 6
5 pln 1 protocol address length, 4
6 op 2 1 = request, 2 = reply
8 sha 6 sender hardware address
14 spa 4 sender protocol address
18 tha 6 target hardware address
24 tpa 4 target protocol address
---
28
Notice that nothing in it ties the protocol to Ethernet or to IPv4. The hrd and pro fields say what is being translated between, and hln and pln give the lengths of both kinds of address.
RFC 826 mentions this itself: "Generalizations have been made which allow the protocol to be used for non-10Mbit Ethernet hardware" — foresight from 1982, and in practice almost nobody ever uses other values.
ARP does not run on IP
This matters more than it looks. ARP has its own EtherType, 0x0806, which means it does not sit on top of IP. It sits beside it.
Two consequences follow.
First, it cannot cross a router. It is not an IP packet, so there is nothing for a router to route — which is correct anyway, because the question of who is on this wire has no meaning across wires.
Second, it inherits nothing from IP whatsoever. No TTL, no checksum, no way to encrypt, no way to authenticate. Anything it wants it must build itself, and it built none of it.
That second point is the root of the security section below.
28 bytes that need 18 more of padding
Add the sizes up and compare against the minimum frame the Ethernet article explains the origin of.
ethernet header 14
ARP 28
--
42 on the wire
minimum frame 60 before FCS
padding needed 18
Every ARP packet on the wire therefore carries eighteen bytes of nothing — close to a third of the frame.
Those empty bytes are not ARP being wasteful. They come from the CSMA/CD slot time reasoning the Ethernet article covers, a constraint from the era of shared wire that is still with us.
Ask and answer
The question is a broadcast. The frame's destination is ff:ff:ff:ff:ff:ff, so every machine on the wire has to take it up and read it, and nearly all of them find it is not about them.
In that packet the tha field is six zero bytes, because that is the field being asked about.
The answer is a unicast, straight back to the asker, with no further broadcast.
The reason is in the packet layout. A question always carries the asker's own sha and spa, so the answering machine knows both the asker's MAC and its address before it replies.
The elegant side effect is that after one exchange both ends hold the other's details, although only one of them asked.
The cache, and a rule from 1982 that is still here
Answers are kept in a table, and that is what arp -an shows.
But the rule for when to keep them is far broader than people assume. RFC 826 gives the algorithm:
If the pair <protocol type, sender protocol address> is already in my translation table, update the sender hardware address field of the entry with the new information in the packet
And this step comes before checking whether the packet was addressed to us at all.
Which means that if our machine already knows an address, and any ARP packet claiming to come from that address passes by, the table is overwritten immediately, addressed to us or not.
The original intent was good. It keeps the table current without asking again; a machine whose network card is replaced gets relearned within seconds.
That intent rests on an assumption that everybody on the wire is telling the truth, which in 1982, on a wire with a handful of machines in one building, was entirely reasonable.
Why entries have to expire
Kept forever, the table would hold on to truths that have expired. A machine unplugged, a card replaced, or an address handed to somebody else by DHCP all make an old row wrong.
Expiry is therefore a self-repair mechanism, paid for by asking again periodically.
Probe and announcement
ARP is also used for two things that ask nobody anything at all, and RFC 5227, from 2008, defines both precisely.
probe spa = 0.0.0.0 tpa = 192.0.2.10
announcement spa = 192.0.2.10 tpa = 192.0.2.10
A probe asks whether an address is already in use, before a machine starts using one it has been given. The RFC requires the sender IP field to "be set to all zeroes, to avoid polluting ARP caches".
The reason for that zero reads straight off the cache rule above. Put a real address in, and if it turns out somebody already owns it, you have corrupted the whole wire's table before finding out.
An announcement declares that an address is now yours. The same address goes in both fields. It asks nobody; it simply makes every machine on the wire update its table under the rule above.
Two main uses. Just after configuring an address, so everybody learns it at once, and when failing over to a standby, because the address has moved to a different card and the whole wire has to be told to overwrite — otherwise everybody keeps sending to a machine that is gone until the entries expire.
Proxy ARP — answering for somebody else
RFC 1027, from 1987, describes a router answering ARP on behalf of machines on the other side.
The gateway can then respond for host B, saying that the network address for host B is that of the gateway itself
The asking machine believes the destination is on its own wire, sends the frame to the router, and the router routes it onward as usual.
The benefit is that a machine with a wrong mask or no gateway still works, which is why it appeared in an era when configuration was done entirely by hand.
And the same RFC warns about it heavily. Never answer for a machine on a different IP network, never answer when asker and target share a physical wire, and never under any circumstances answer for a broadcast address — doing which, it says, may produce what it calls a "Chernobyl effect", a network meltdown.
Today proxy ARP is something to switch off rather than on, because it hides misconfiguration instead of exposing it.
The whole layer rests on trust
Put three of the points above together.
One, ARP is not on top of IP, so it has no security machinery available to it at all.
Two, the table can be overwritten by a packet not addressed to us, under the 1982 rule.
Three, an announcement is a declaration nobody asked for and everybody must believe.
The result is that anybody on the same wire can state which address belongs to which MAC, and there is nothing in the protocol to check it against.
The most direct attack is telling the victim you are the gateway and telling the gateway you are the victim. Traffic in both directions then flows through the intruder, while everything above continues to work perfectly normally.
Note that nothing about the symptom looks wrong. Pages load, pings succeed, speed is barely different, because everything really does reach its destination. It merely stops on the way.
The fix that is not in the protocol
ARP cannot be fixed, because there is nothing there to fix. The fixes live one layer below and one layer above.
At the switch, remember which address belongs on which port, learned from what DHCP handed out, and discard ARP packets that contradict it.
At the layer above, accept that the path cannot be trusted and encrypt end to end. An intruder still sees traffic exists, but can neither read nor alter it.
That second one is why encrypting everything became this era's default. Not because networks got worse, but because we stopped assuming they were good.
The reverse problem — RARP and its descendants
If ARP answers which MAC an address is at, the reverse question is what address should my MAC be given.
RFC 903, from 1984, answered it with RARP, using exactly the same packet layout with a different EtherType.
The reason it had to be separate is more interesting than the protocol. The RFC says "RARP requires one or more server hosts to maintain a database of mappings from hardware address to protocol address".
That is the real difference. ARP works because every machine knows its own address and can answer about itself, with nobody at the centre. RARP needs somebody who knows on other machines' behalf, which means a server.
And once a server is required, sitting at the same layer as ARP is wasteful, because it cannot cross a router. That line therefore continued into BOOTP and then DHCP, which moved up onto UDP and crosses subnets with a relay.
On the IPv6 side
The IPv6 article already explained that ARP was replaced by NDP, which is ICMPv6. This page adds the missing angle: why that difference matters.
ARP EtherType 0x0806 broadcast to the whole wire
NDP ICMPv6 type 135 multicast to one group
Every difference traces back to a single one. ARP sits beside IP; NDP sits on IP.
Being on IP gives NDP everything IPv6 has, for free: its security machinery, its ability to authenticate, and the hop limit 255 trick the IPv6 article describes, which proves the sender really is on the same wire.
ARP has none of those — not because it was designed badly, but because it is in the wrong place.
That is this page's most widely applicable lesson. A protocol that places itself beside another layer rather than on top of it has to build everything itself, and usually does not.
Where it lies to you
"It is in arp -a, so that machine is still there." No. The row may be ten minutes old, the machine may be unplugged, the address may have been handed to somebody else. The table says what was once heard, not what is currently true.
"ARP works at layer two." Not wrong exactly, but it misses the point. It is not in layer two or layer three; it is the seam between them, and its not being on any layer is the reason it has nothing.
"A machine asks for the MAC of whatever it wants to reach." Only when that is on the same wire. Otherwise it asks for the gateway.
"A static entry makes it safe." It genuinely helps for that entry, but doing it for every pair on a network is unworkable, and it stops being right the moment anything changes. A workable fix has to be at the switch.
"ARP can be turned off." It cannot. Run IPv4 over Ethernet and you have ARP; there is no alternative at all. That is what makes this subject matter.
Worked examples from real work
Case 1 — a machine that drops in and out with no pattern
Ping succeeds sometimes and fails others, alternating, unrelated to time of day or load.
How to read it. Read the table repeatedly and see whether the value changes.
$ arp -an | grep 192.0.2.7
? (192.0.2.7) at 00:00:5e:00:53:07 on en0 ifscope [ethernet]
$ arp -an | grep 192.0.2.7
? (192.0.2.7) at 00:00:5e:00:53:aa on en0 ifscope [ethernet]
The MAC alternating between two values is the signature of a duplicate address. Two machines claim the same one, both answer ARP, and the table gets overwritten by whichever announced most recently.
The usual cause is somebody setting an address by hand on top of a DHCP pool.
Not yet proved. We know two MACs claim one address, but not which is legitimate. Read the first three bytes of each for the manufacturer, then find which port each is on from the switch's address table.
Case 2 — swapping a device leaves it unreachable for a while
A server is replaced with a new machine keeping the same address, and some clients cannot reach it for several minutes while others work immediately.
How to read it. The ones that cannot are the ones still holding the old row.
$ arp -an | grep 192.0.2.20
? (192.0.2.20) at 00:00:5e:00:53:20 on en0 ifscope [ethernet]
If that MAC belongs to the old machine, the entry has not expired. Frames are being sent to a card that no longer exists, and vanish silently.
The right fix is not waiting but having the new machine send an announcement, so the whole wire overwrites at once — which equipment built for failover does by itself.
Not yet proved. We can see a stale row, but not whether the new machine sent an announcement at all. Capture traffic during a failover to confirm.
Case 3 — one machine in the room cannot reach the internet
Every machine in the room works. One cannot even ping the gateway, although it has an address in the same range.
How to read it. Check whether that machine believes the gateway is on its own wire.
$ ifconfig en0 | grep 'inet '
inet 192.0.2.31 netmask 0xffffff00 broadcast 192.0.2.255
$ arp -an | grep 192.0.2.1
(nothing returned)
A correct mask with no gateway entry at all means it asked and nobody answered.
But if the mask is wrong — say 0xffffffc0 instead of 0xffffff00 — the machine calculates that the gateway is on a different network and goes looking for a gateway that does not exist, which also gets no answer, for an entirely different reason.
Not yet proved. An empty table says nobody answered, not how far the question travelled. Capture on that port to see whether an ARP request left at all.
Case 4 — checking whether somebody is impersonating the gateway
Nothing looks wrong, but it needs confirming that traffic is not being intercepted.
How to read it. Record the correct value, then compare periodically.
$ arp -an | grep 192.0.2.1
? (192.0.2.1) at 00:00:5e:00:53:01 on en0 ifscope [ethernet]
The first three bytes name the manufacturer. If the gateway is networking equipment from one vendor but the MAC belongs to a laptop manufacturer, that is a very clear signal.
Another quick check is whether any single MAC appears against more than one address, which is the signature of impersonating several machines at once.
Not yet proved. A correct MAC does not mean safety, because MACs can be forged too. This check catches only somebody not trying to hide. Real confidence comes from encryption, not from reading a table.
References
The original
- RFC 826 — An Ethernet Address Resolution Protocol David C. Plummer, November 1982 — the packet layout, the opcode values, and the cache update rule still in force today
- RFC 903 — A Reverse Address Resolution Protocol Finlayson, Mann, Mogul and Theimer, June 1984 — the reverse problem, and the need for a server that led RARP on to BOOTP and DHCP
Extensions and cautions
- RFC 5227 — IPv4 Address Conflict Detection Stuart Cheshire, July 2008 — the definitions of probe and announcement, and why a probe's sender IP must be zero
- RFC 1027 — Using ARP to Implement Transparent Subnet Gateways Carl-Mitchell and Quarterman, October 1987 — the definition of proxy ARP and the warning about what it calls a Chernobyl effect
What is on the machine
arp -anon macOS — the whole translation table, withpermanentmarking the rows that never expireifconfig en0 | grep 'inet '— the mask that decides who gets asked for
Related reading here
- Subnetting — the arithmetic that decides whether to ask for the destination or the gateway
- MAC address — the thing ARP finds
- Ethernet — the EtherType table this page explains one row of, and the minimum frame that forces the padding