Skip to content

Commit d46b6bf

Browse files
Simon Wunderlichordex
authored andcommitted
batman-adv: drop QinQ claim frames in bridge loop avoidance
Since bridge loop avoidance only supports untagged or simple 802.1q tagged VLAN claim frames, claim frames with stacked VLAN headers (QinQ) should be detected and dropped. Transporting the over the mesh may cause problems on the receivers, or create bogus entries in the local tt tables. Reported-by: Antonio Quartulli <antonio@open-mesh.com> Signed-off-by: Simon Wunderlich <simon@open-mesh.com> Signed-off-by: Marek Lindner <mareklindner@neomailbox.ch> Signed-off-by: Antonio Quartulli <antonio@meshcoding.com>
1 parent 640d7ef commit d46b6bf

File tree

1 file changed

+34
-10
lines changed

1 file changed

+34
-10
lines changed

net/batman-adv/bridge_loop_avoidance.c

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -800,11 +800,6 @@ static int batadv_check_claim_group(struct batadv_priv *bat_priv,
800800
bla_dst = (struct batadv_bla_claim_dst *)hw_dst;
801801
bla_dst_own = &bat_priv->bla.claim_dest;
802802

803-
/* check if it is a claim packet in general */
804-
if (memcmp(bla_dst->magic, bla_dst_own->magic,
805-
sizeof(bla_dst->magic)) != 0)
806-
return 0;
807-
808803
/* if announcement packet, use the source,
809804
* otherwise assume it is in the hw_src
810805
*/
@@ -866,12 +861,13 @@ static int batadv_bla_process_claim(struct batadv_priv *bat_priv,
866861
struct batadv_hard_iface *primary_if,
867862
struct sk_buff *skb)
868863
{
869-
struct batadv_bla_claim_dst *bla_dst;
864+
struct batadv_bla_claim_dst *bla_dst, *bla_dst_own;
870865
uint8_t *hw_src, *hw_dst;
871-
struct vlan_ethhdr *vhdr;
866+
struct vlan_hdr *vhdr, vhdr_buf;
872867
struct ethhdr *ethhdr;
873868
struct arphdr *arphdr;
874869
unsigned short vid;
870+
int vlan_depth = 0;
875871
__be16 proto;
876872
int headlen;
877873
int ret;
@@ -882,9 +878,24 @@ static int batadv_bla_process_claim(struct batadv_priv *bat_priv,
882878
proto = ethhdr->h_proto;
883879
headlen = ETH_HLEN;
884880
if (vid & BATADV_VLAN_HAS_TAG) {
885-
vhdr = vlan_eth_hdr(skb);
886-
proto = vhdr->h_vlan_encapsulated_proto;
887-
headlen += VLAN_HLEN;
881+
/* Traverse the VLAN/Ethertypes.
882+
*
883+
* At this point it is known that the first protocol is a VLAN
884+
* header, so start checking at the encapsulated protocol.
885+
*
886+
* The depth of the VLAN headers is recorded to drop BLA claim
887+
* frames encapsulated into multiple VLAN headers (QinQ).
888+
*/
889+
do {
890+
vhdr = skb_header_pointer(skb, headlen, VLAN_HLEN,
891+
&vhdr_buf);
892+
if (!vhdr)
893+
return 0;
894+
895+
proto = vhdr->h_vlan_encapsulated_proto;
896+
headlen += VLAN_HLEN;
897+
vlan_depth++;
898+
} while (proto == htons(ETH_P_8021Q));
888899
}
889900

890901
if (proto != htons(ETH_P_ARP))
@@ -914,6 +925,19 @@ static int batadv_bla_process_claim(struct batadv_priv *bat_priv,
914925
hw_src = (uint8_t *)arphdr + sizeof(struct arphdr);
915926
hw_dst = hw_src + ETH_ALEN + 4;
916927
bla_dst = (struct batadv_bla_claim_dst *)hw_dst;
928+
bla_dst_own = &bat_priv->bla.claim_dest;
929+
930+
/* check if it is a claim frame in general */
931+
if (memcmp(bla_dst->magic, bla_dst_own->magic,
932+
sizeof(bla_dst->magic)) != 0)
933+
return 0;
934+
935+
/* check if there is a claim frame encapsulated deeper in (QinQ) and
936+
* drop that, as this is not supported by BLA but should also not be
937+
* sent via the mesh.
938+
*/
939+
if (vlan_depth > 1)
940+
return 1;
917941

918942
/* check if it is a claim frame. */
919943
ret = batadv_check_claim_group(bat_priv, primary_if, hw_src, hw_dst,

0 commit comments

Comments
 (0)