| From foo@baz Sun May 27 17:33:38 CEST 2018 |
| From: "Linus Lüssing" <linus.luessing@c0d3.blue> |
| Date: Thu, 22 Mar 2018 00:21:32 +0100 |
| Subject: batman-adv: fix packet loss for broadcasted DHCP packets to a server |
| |
| From: "Linus Lüssing" <linus.luessing@c0d3.blue> |
| |
| [ Upstream commit a752c0a4524889cdc0765925258fd1fd72344100 ] |
| |
| DHCP connectivity issues can currently occur if the following conditions |
| are met: |
| |
| 1) A DHCP packet from a client to a server |
| 2) This packet has a multicast destination |
| 3) This destination has a matching entry in the translation table |
| (FF:FF:FF:FF:FF:FF for IPv4, 33:33:00:01:00:02/33:33:00:01:00:03 |
| for IPv6) |
| 4) The orig-node determined by TT for the multicast destination |
| does not match the orig-node determined by best-gateway-selection |
| |
| In this case the DHCP packet will be dropped. |
| |
| The "gateway-out-of-range" check is supposed to only be applied to |
| unicasted DHCP packets to a specific DHCP server. |
| |
| In that case dropping the the unicasted frame forces the client to |
| retry via a broadcasted one, but now directed to the new best |
| gateway. |
| |
| A DHCP packet with broadcast/multicast destination is already ensured to |
| always be delivered to the best gateway. Dropping a multicasted |
| DHCP packet here will only prevent completing DHCP as there is no |
| other fallback. |
| |
| So far, it seems the unicast check was implicitly performed by |
| expecting the batadv_transtable_search() to return NULL for multicast |
| destinations. However, a multicast address could have always ended up in |
| the translation table and in fact is now common. |
| |
| To fix this potential loss of a DHCP client-to-server packet to a |
| multicast address this patch adds an explicit multicast destination |
| check to reliably bail out of the gateway-out-of-range check for such |
| destinations. |
| |
| The issue and fix were tested in the following three node setup: |
| |
| - Line topology, A-B-C |
| - A: gateway client, DHCP client |
| - B: gateway server, hop-penalty increased: 30->60, DHCP server |
| - C: gateway server, code modifications to announce FF:FF:FF:FF:FF:FF |
| |
| Without this patch, A would never transmit its DHCP Discover packet |
| due to an always "out-of-range" condition. With this patch, |
| a full DHCP handshake between A and B was possible again. |
| |
| Fixes: be7af5cf9cae ("batman-adv: refactoring gateway handling code") |
| Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue> |
| Signed-off-by: Sven Eckelmann <sven@narfation.org> |
| Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de> |
| Signed-off-by: Sasha Levin <alexander.levin@microsoft.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/batman-adv/gateway_client.c | 3 +++ |
| 1 file changed, 3 insertions(+) |
| |
| --- a/net/batman-adv/gateway_client.c |
| +++ b/net/batman-adv/gateway_client.c |
| @@ -715,6 +715,9 @@ bool batadv_gw_out_of_range(struct batad |
| |
| vid = batadv_get_vid(skb, 0); |
| |
| + if (is_multicast_ether_addr(ethhdr->h_dest)) |
| + goto out; |
| + |
| orig_dst_node = batadv_transtable_search(bat_priv, ethhdr->h_source, |
| ethhdr->h_dest, vid); |
| if (!orig_dst_node) |