]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
arp: ignore invalid ARP probes according to RFC5227 (#145)
authorLaszlo Toth <laszlth@gmail.com>
Fri, 23 Dec 2022 13:31:43 +0000 (08:31 -0500)
committerGitHub <noreply@github.com>
Fri, 23 Dec 2022 13:31:43 +0000 (13:31 +0000)
Some network devices can send probes where the source address in the frame
does not match the sender in the ARP request, due to firmware bugs or
crafted packets.
Without verification this can cause to fail the defense, so we lose the
address, then request a new one. This might lead to the DHCP address pool
being exhausted and all sorts of problems like frequent IP changes.

A real life example is that some Cisco devices can send ARP probes in bursts,
where the frame's source address is clearly invalid, so hosts running dhcpcd
release addresses frequently, e.g., Raspberry Pis.
Example output:
"invalid ARP probe, sender hw address mismatch (00:be:75:xx:xx:xx, 00:00:00:yy:yy:yy)"

RFC5227, Section 1.1 describes that the two addresses must match in case
of ARP probes, so add the extra check and log a warning if we receive an
invalid packet like that.

Signed-off-by: Laszlo Toth <laszlth@gmail.com>
src/arp.c

index 5445e757344986b2cbf08b35d40dee0db266a687..79946f024120c24f229dd198d93f9a81ad9df866 100644 (file)
--- a/src/arp.c
+++ b/src/arp.c
@@ -232,6 +232,9 @@ arp_packet(struct interface *ifp, uint8_t *data, size_t len,
        const struct iarp_state *state;
        struct arp_state *astate, *astaten;
        uint8_t *hw_s, *hw_t;
+#ifndef KERNEL_RFC5227
+       bool is_probe;
+#endif /* KERNEL_RFC5227 */
 
        /* Copy the frame header source and destination out */
        memset(&arm, 0, sizeof(arm));
@@ -284,6 +287,23 @@ arp_packet(struct interface *ifp, uint8_t *data, size_t len,
        memcpy(&arm.tha, hw_t, ar.ar_hln);
        memcpy(&arm.tip.s_addr, hw_t + ar.ar_hln, ar.ar_pln);
 
+#ifndef KERNEL_RFC5227
+       /* During ARP probe the 'sender hardware address' MUST contain the hardware
+        * address of the interface sending the packet. RFC5227, 1.1 */
+       is_probe = ar.ar_op == htons(ARPOP_REQUEST) && IN_IS_ADDR_UNSPECIFIED(&arm.sip) &&
+           bpf_flags & BPF_BCAST;
+       if (is_probe && falen > 0 && (falen != ar.ar_hln ||
+           memcmp(&arm.sha, &arm.fsha, ar.ar_hln))) {
+               char abuf[HWADDR_LEN * 3];
+               char fbuf[HWADDR_LEN * 3];
+               hwaddr_ntoa(&arm.sha, ar.ar_hln, abuf, sizeof(abuf));
+               hwaddr_ntoa(&arm.fsha, falen, fbuf, sizeof(fbuf));
+               logwarnx("%s: invalid ARP probe, sender hw address mismatch (%s, %s)",
+                   ifp->name, abuf, fbuf);
+               return;
+       }
+#endif /* KERNEL_RFC5227 */
+
        /* Match the ARP probe to our states.
         * Ignore Unicast Poll, RFC1122. */
        state = ARP_CSTATE(ifp);