kernel: fix bridge proxyarp issue with some broken DHCP clients
authorFelix Fietkau <nbd@nbd.name>
Fri, 5 Jan 2024 10:58:15 +0000 (11:58 +0100)
committerFelix Fietkau <nbd@nbd.name>
Fri, 5 Jan 2024 11:00:23 +0000 (12:00 +0100)
There are broken devices in the wild that handle duplicate IP address
detection by sending out ARP requests for the IP that they received from a
DHCP server and refuse the address if they get a reply.
When proxyarp is enabled, they would go into a loop of requesting an address
and then NAKing it again.

Fixes: https://github.com/openwrt/openwrt/issues/14309
Signed-off-by: Felix Fietkau <nbd@nbd.name>
target/linux/generic/pending-5.15/151-net-bridge-do-not-send-arp-replies-if-src-and-target.patch [new file with mode: 0644]
target/linux/generic/pending-6.1/151-net-bridge-do-not-send-arp-replies-if-src-and-target.patch [new file with mode: 0644]

diff --git a/target/linux/generic/pending-5.15/151-net-bridge-do-not-send-arp-replies-if-src-and-target.patch b/target/linux/generic/pending-5.15/151-net-bridge-do-not-send-arp-replies-if-src-and-target.patch
new file mode 100644 (file)
index 0000000..f420d21
--- /dev/null
@@ -0,0 +1,37 @@
+From: Felix Fietkau <nbd@nbd.name>
+Date: Thu, 4 Jan 2024 15:21:21 +0100
+Subject: [PATCH] net: bridge: do not send arp replies if src and target hw
+ addr is the same
+
+There are broken devices in the wild that handle duplicate IP address
+detection by sending out ARP requests for the IP that they received from a
+DHCP server and refuse the address if they get a reply.
+When proxyarp is enabled, they would go into a loop of requesting an address
+and then NAKing it again.
+
+Link: https://github.com/openwrt/openwrt/issues/14309
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/net/bridge/br_arp_nd_proxy.c
++++ b/net/bridge/br_arp_nd_proxy.c
+@@ -204,7 +204,10 @@ void br_do_proxy_suppress_arp(struct sk_
+                       if ((p && (p->flags & BR_PROXYARP)) ||
+                           (f->dst && (f->dst->flags & (BR_PROXYARP_WIFI |
+                                                        BR_NEIGH_SUPPRESS)))) {
+-                              if (!vid)
++                              replied = true;
++                              if (!memcmp(n->ha, sha, dev->addr_len))
++                                      replied = false;
++                              else if (!vid)
+                                       br_arp_send(br, p, skb->dev, sip, tip,
+                                                   sha, n->ha, sha, 0, 0);
+                               else
+@@ -212,7 +215,6 @@ void br_do_proxy_suppress_arp(struct sk_
+                                                   sha, n->ha, sha,
+                                                   skb->vlan_proto,
+                                                   skb_vlan_tag_get(skb));
+-                              replied = true;
+                       }
+                       /* If we have replied or as long as we know the
diff --git a/target/linux/generic/pending-6.1/151-net-bridge-do-not-send-arp-replies-if-src-and-target.patch b/target/linux/generic/pending-6.1/151-net-bridge-do-not-send-arp-replies-if-src-and-target.patch
new file mode 100644 (file)
index 0000000..f420d21
--- /dev/null
@@ -0,0 +1,37 @@
+From: Felix Fietkau <nbd@nbd.name>
+Date: Thu, 4 Jan 2024 15:21:21 +0100
+Subject: [PATCH] net: bridge: do not send arp replies if src and target hw
+ addr is the same
+
+There are broken devices in the wild that handle duplicate IP address
+detection by sending out ARP requests for the IP that they received from a
+DHCP server and refuse the address if they get a reply.
+When proxyarp is enabled, they would go into a loop of requesting an address
+and then NAKing it again.
+
+Link: https://github.com/openwrt/openwrt/issues/14309
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/net/bridge/br_arp_nd_proxy.c
++++ b/net/bridge/br_arp_nd_proxy.c
+@@ -204,7 +204,10 @@ void br_do_proxy_suppress_arp(struct sk_
+                       if ((p && (p->flags & BR_PROXYARP)) ||
+                           (f->dst && (f->dst->flags & (BR_PROXYARP_WIFI |
+                                                        BR_NEIGH_SUPPRESS)))) {
+-                              if (!vid)
++                              replied = true;
++                              if (!memcmp(n->ha, sha, dev->addr_len))
++                                      replied = false;
++                              else if (!vid)
+                                       br_arp_send(br, p, skb->dev, sip, tip,
+                                                   sha, n->ha, sha, 0, 0);
+                               else
+@@ -212,7 +215,6 @@ void br_do_proxy_suppress_arp(struct sk_
+                                                   sha, n->ha, sha,
+                                                   skb->vlan_proto,
+                                                   skb_vlan_tag_get(skb));
+-                              replied = true;
+                       }
+                       /* If we have replied or as long as we know the