Commit 2d3f6ccc authored by Simon Wunderlich's avatar Simon Wunderlich Committed by Antonio Quartulli

batman-adv: check incoming packet type for bla

If the gateway functionality is used, some broadcast packets (DHCP
requests) may be transmitted as unicast packets. As the bridge loop
avoidance code now only considers the payload Ethernet destination,
it may drop the DHCP request for clients which are claimed by other
backbone gateways, because it falsely infers from the broadcast address
that the right backbone gateway should havehandled the broadcast.

Fix this by checking and delegating the batman-adv packet type used
for transmission.
Reported-by: default avatarGuido Iribarren <guidoiribarren@buenosaireslibre.org>
Signed-off-by: default avatarSimon Wunderlich <siwu@hrz.tu-chemnitz.de>
parent 9e85a6f9
...@@ -1351,6 +1351,7 @@ void bla_free(struct bat_priv *bat_priv) ...@@ -1351,6 +1351,7 @@ void bla_free(struct bat_priv *bat_priv)
* @bat_priv: the bat priv with all the soft interface information * @bat_priv: the bat priv with all the soft interface information
* @skb: the frame to be checked * @skb: the frame to be checked
* @vid: the VLAN ID of the frame * @vid: the VLAN ID of the frame
* @is_bcast: the packet came in a broadcast packet type.
* *
* bla_rx avoidance checks if: * bla_rx avoidance checks if:
* * we have to race for a claim * * we have to race for a claim
...@@ -1361,7 +1362,8 @@ void bla_free(struct bat_priv *bat_priv) ...@@ -1361,7 +1362,8 @@ void bla_free(struct bat_priv *bat_priv)
* process the skb. * process the skb.
* *
*/ */
int bla_rx(struct bat_priv *bat_priv, struct sk_buff *skb, short vid) int bla_rx(struct bat_priv *bat_priv, struct sk_buff *skb, short vid,
bool is_bcast)
{ {
struct ethhdr *ethhdr; struct ethhdr *ethhdr;
struct claim search_claim, *claim = NULL; struct claim search_claim, *claim = NULL;
...@@ -1380,7 +1382,7 @@ int bla_rx(struct bat_priv *bat_priv, struct sk_buff *skb, short vid) ...@@ -1380,7 +1382,7 @@ int bla_rx(struct bat_priv *bat_priv, struct sk_buff *skb, short vid)
if (unlikely(atomic_read(&bat_priv->bla_num_requests))) if (unlikely(atomic_read(&bat_priv->bla_num_requests)))
/* don't allow broadcasts while requests are in flight */ /* don't allow broadcasts while requests are in flight */
if (is_multicast_ether_addr(ethhdr->h_dest)) if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast)
goto handled; goto handled;
memcpy(search_claim.addr, ethhdr->h_source, ETH_ALEN); memcpy(search_claim.addr, ethhdr->h_source, ETH_ALEN);
...@@ -1406,8 +1408,13 @@ int bla_rx(struct bat_priv *bat_priv, struct sk_buff *skb, short vid) ...@@ -1406,8 +1408,13 @@ int bla_rx(struct bat_priv *bat_priv, struct sk_buff *skb, short vid)
} }
/* if it is a broadcast ... */ /* if it is a broadcast ... */
if (is_multicast_ether_addr(ethhdr->h_dest)) { if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast) {
/* ... drop it. the responsible gateway is in charge. */ /* ... drop it. the responsible gateway is in charge.
*
* We need to check is_bcast because with the gateway
* feature, broadcasts (like DHCP requests) may be sent
* using a unicast packet type.
*/
goto handled; goto handled;
} else { } else {
/* seems the client considers us as its best gateway. /* seems the client considers us as its best gateway.
......
...@@ -23,7 +23,8 @@ ...@@ -23,7 +23,8 @@
#define _NET_BATMAN_ADV_BLA_H_ #define _NET_BATMAN_ADV_BLA_H_
#ifdef CONFIG_BATMAN_ADV_BLA #ifdef CONFIG_BATMAN_ADV_BLA
int bla_rx(struct bat_priv *bat_priv, struct sk_buff *skb, short vid); int bla_rx(struct bat_priv *bat_priv, struct sk_buff *skb, short vid,
bool is_bcast);
int bla_tx(struct bat_priv *bat_priv, struct sk_buff *skb, short vid); int bla_tx(struct bat_priv *bat_priv, struct sk_buff *skb, short vid);
int bla_is_backbone_gw(struct sk_buff *skb, int bla_is_backbone_gw(struct sk_buff *skb,
struct orig_node *orig_node, int hdr_size); struct orig_node *orig_node, int hdr_size);
...@@ -41,7 +42,7 @@ void bla_free(struct bat_priv *bat_priv); ...@@ -41,7 +42,7 @@ void bla_free(struct bat_priv *bat_priv);
#else /* ifdef CONFIG_BATMAN_ADV_BLA */ #else /* ifdef CONFIG_BATMAN_ADV_BLA */
static inline int bla_rx(struct bat_priv *bat_priv, struct sk_buff *skb, static inline int bla_rx(struct bat_priv *bat_priv, struct sk_buff *skb,
short vid) short vid, bool is_bcast)
{ {
return 0; return 0;
} }
......
...@@ -256,7 +256,11 @@ void interface_rx(struct net_device *soft_iface, ...@@ -256,7 +256,11 @@ void interface_rx(struct net_device *soft_iface,
struct bat_priv *bat_priv = netdev_priv(soft_iface); struct bat_priv *bat_priv = netdev_priv(soft_iface);
struct ethhdr *ethhdr; struct ethhdr *ethhdr;
struct vlan_ethhdr *vhdr; struct vlan_ethhdr *vhdr;
struct batman_header *batadv_header = (struct batman_header *)skb->data;
short vid __maybe_unused = -1; short vid __maybe_unused = -1;
bool is_bcast;
is_bcast = (batadv_header->packet_type == BAT_BCAST);
/* check if enough space is available for pulling, and pull */ /* check if enough space is available for pulling, and pull */
if (!pskb_may_pull(skb, hdr_size)) if (!pskb_may_pull(skb, hdr_size))
...@@ -302,7 +306,7 @@ void interface_rx(struct net_device *soft_iface, ...@@ -302,7 +306,7 @@ void interface_rx(struct net_device *soft_iface,
/* Let the bridge loop avoidance check the packet. If will /* Let the bridge loop avoidance check the packet. If will
* not handle it, we can safely push it up. * not handle it, we can safely push it up.
*/ */
if (bla_rx(bat_priv, skb, vid)) if (bla_rx(bat_priv, skb, vid, is_bcast))
goto out; goto out;
netif_rx(skb); netif_rx(skb);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment