* [PATCH net] batman-adv: check incoming packet type for bla
2012-07-05 22:48 [PATCH net] Bug fix for batman-adv 2012-07-06 Antonio Quartulli
@ 2012-07-05 22:48 ` Antonio Quartulli
2012-07-05 22:51 ` [B.A.T.M.A.N.] [PATCH net] Bug fix for batman-adv 2012-07-06 Antonio Quartulli
[not found] ` <1341528514-27906-1-git-send-email-ordex-GaUfNO9RBHfsrOwW+9ziJQ@public.gmane.org>
2 siblings, 0 replies; 5+ messages in thread
From: Antonio Quartulli @ 2012-07-05 22:48 UTC (permalink / raw)
To: davem; +Cc: netdev, b.a.t.m.a.n, Simon Wunderlich, Simon Wunderlich
From: Simon Wunderlich <simon.wunderlich@s2003.tu-chemnitz.de>
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: Guido Iribarren <guidoiribarren@buenosaireslibre.org>
Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
---
net/batman-adv/bridge_loop_avoidance.c | 15 +++++++++++----
net/batman-adv/bridge_loop_avoidance.h | 5 +++--
net/batman-adv/soft-interface.c | 6 +++++-
3 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c
index 8bf9751..c5863f4 100644
--- a/net/batman-adv/bridge_loop_avoidance.c
+++ b/net/batman-adv/bridge_loop_avoidance.c
@@ -1351,6 +1351,7 @@ void bla_free(struct bat_priv *bat_priv)
* @bat_priv: the bat priv with all the soft interface information
* @skb: the frame to be checked
* @vid: the VLAN ID of the frame
+ * @is_bcast: the packet came in a broadcast packet type.
*
* bla_rx avoidance checks if:
* * we have to race for a claim
@@ -1361,7 +1362,8 @@ void bla_free(struct bat_priv *bat_priv)
* 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 claim search_claim, *claim = NULL;
@@ -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)))
/* 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;
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)
}
/* if it is a broadcast ... */
- if (is_multicast_ether_addr(ethhdr->h_dest)) {
- /* ... drop it. the responsible gateway is in charge. */
+ if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast) {
+ /* ... 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;
} else {
/* seems the client considers us as its best gateway.
diff --git a/net/batman-adv/bridge_loop_avoidance.h b/net/batman-adv/bridge_loop_avoidance.h
index e39f93a..dc5227b 100644
--- a/net/batman-adv/bridge_loop_avoidance.h
+++ b/net/batman-adv/bridge_loop_avoidance.h
@@ -23,7 +23,8 @@
#define _NET_BATMAN_ADV_BLA_H_
#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_is_backbone_gw(struct sk_buff *skb,
struct orig_node *orig_node, int hdr_size);
@@ -41,7 +42,7 @@ void bla_free(struct bat_priv *bat_priv);
#else /* ifdef CONFIG_BATMAN_ADV_BLA */
static inline int bla_rx(struct bat_priv *bat_priv, struct sk_buff *skb,
- short vid)
+ short vid, bool is_bcast)
{
return 0;
}
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index 6e2530b..a0ec0e4 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -256,7 +256,11 @@ void interface_rx(struct net_device *soft_iface,
struct bat_priv *bat_priv = netdev_priv(soft_iface);
struct ethhdr *ethhdr;
struct vlan_ethhdr *vhdr;
+ struct batman_header *batadv_header = (struct batman_header *)skb->data;
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 */
if (!pskb_may_pull(skb, hdr_size))
@@ -302,7 +306,7 @@ void interface_rx(struct net_device *soft_iface,
/* Let the bridge loop avoidance check the packet. If will
* 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;
netif_rx(skb);
--
1.7.9.4
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [B.A.T.M.A.N.] [PATCH net] Bug fix for batman-adv 2012-07-06
2012-07-05 22:48 [PATCH net] Bug fix for batman-adv 2012-07-06 Antonio Quartulli
2012-07-05 22:48 ` [PATCH net] batman-adv: check incoming packet type for bla Antonio Quartulli
@ 2012-07-05 22:51 ` Antonio Quartulli
[not found] ` <20120705225140.GA9745-E/2OGukznS5g9hUCZPvPmw@public.gmane.org>
[not found] ` <1341528514-27906-1-git-send-email-ordex-GaUfNO9RBHfsrOwW+9ziJQ@public.gmane.org>
2 siblings, 1 reply; 5+ messages in thread
From: Antonio Quartulli @ 2012-07-05 22:51 UTC (permalink / raw)
To: davem; +Cc: netdev, b.a.t.m.a.n
[-- Attachment #1: Type: text/plain, Size: 4380 bytes --]
On Fri, Jul 06, 2012 at 12:48:33 +0200, Antonio Quartulli wrote:
> here I have a fix intended for net/linux-3.5.
...
Hello David,
here you have our instructions to resolve the conflicts that you will hit while
merging net into net-next:
Conflict 1 (bridge_loop_avoidance.c):
<<<<<<<
int batadv_bla_rx(struct batadv_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)
>>>>>>>
resolves to:
int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid,
bool is_bcast)
Conflict 2 (bridge_loop_avoidance.h):
<<<<<<<
int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid);
int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid);
int batadv_bla_is_backbone_gw(struct sk_buff *skb,
struct batadv_orig_node *orig_node, int hdr_size);
int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset);
int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, uint8_t *orig);
int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
struct batadv_bcast_packet *bcast_packet,
int hdr_size);
void batadv_bla_update_orig_address(struct batadv_priv *bat_priv,
struct batadv_hard_iface *primary_if,
struct batadv_hard_iface *oldif);
int batadv_bla_init(struct batadv_priv *bat_priv);
void batadv_bla_free(struct batadv_priv *bat_priv);
=======
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_is_backbone_gw(struct sk_buff *skb,
struct orig_node *orig_node, int hdr_size);
int bla_claim_table_seq_print_text(struct seq_file *seq, void *offset);
int bla_is_backbone_gw_orig(struct bat_priv *bat_priv, uint8_t *orig);
int bla_check_bcast_duplist(struct bat_priv *bat_priv,
struct bcast_packet *bcast_packet, int hdr_size);
void bla_update_orig_address(struct bat_priv *bat_priv,
struct hard_iface *primary_if,
struct hard_iface *oldif);
int bla_init(struct bat_priv *bat_priv);
void bla_free(struct bat_priv *bat_priv);
>>>>>>>
resolves to:
int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid,
bool is_bcast);
int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid);
int batadv_bla_is_backbone_gw(struct sk_buff *skb,
struct batadv_orig_node *orig_node, int hdr_size);
int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset);
int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, uint8_t *orig);
int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
struct batadv_bcast_packet *bcast_packet,
int hdr_size);
void batadv_bla_update_orig_address(struct batadv_priv *bat_priv,
struct batadv_hard_iface *primary_if,
struct batadv_hard_iface *oldif);
int batadv_bla_init(struct batadv_priv *bat_priv);
void batadv_bla_free(struct batadv_priv *bat_priv);
Conflict 3 (bridge_loop_avoidance.h):
<<<<<<<
static inline int batadv_bla_rx(struct batadv_priv *bat_priv,
struct sk_buff *skb, short vid)
=======
static inline int bla_rx(struct bat_priv *bat_priv, struct sk_buff *skb,
short vid, bool is_bcast)
>>>>>>>
resolves to:
static inline int batadv_bla_rx(struct batadv_priv *bat_priv,
struct sk_buff *skb, short vid, bool is_bcast)
Conflict 4 (soft-interface.c):
<<<<<<<
__be16 ethertype = __constant_htons(BATADV_ETH_P_BATMAN);
=======
bool is_bcast;
is_bcast = (batadv_header->packet_type == BAT_BCAST);
>>>>>>>
resolves to:
bool is_bcast;
__be16 ethertype = __constant_htons(BATADV_ETH_P_BATMAN);
is_bcast = (batadv_header->packet_type == BATADV_BCAST);
Conflict 5 (soft-interface.c):
<<<<<<<
if (batadv_bla_rx(bat_priv, skb, vid))
=======
if (bla_rx(bat_priv, skb, vid, is_bcast))
>>>>>>>
resolves to:
if (batadv_bla_rx(bat_priv, skb, vid, is_bcast))
Wrong merge by git (soft-interface.c):
line 270 must look like this:
struct batadv_header *batadv_header = (struct batadv_header *)skb->data;
--
Antonio Quartulli
..each of us alone is worth nothing..
Ernesto "Che" Guevara
[-- Attachment #2: Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread