diff options
| -rw-r--r-- | net/batman-adv/bridge_loop_avoidance.c | 44 |
1 files changed, 34 insertions, 10 deletions
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index 6f0d9ec37950..a957c8140721 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c | |||
| @@ -800,11 +800,6 @@ static int batadv_check_claim_group(struct batadv_priv *bat_priv, | |||
| 800 | bla_dst = (struct batadv_bla_claim_dst *)hw_dst; | 800 | bla_dst = (struct batadv_bla_claim_dst *)hw_dst; |
| 801 | bla_dst_own = &bat_priv->bla.claim_dest; | 801 | bla_dst_own = &bat_priv->bla.claim_dest; |
| 802 | 802 | ||
| 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 | |||
| 808 | /* if announcement packet, use the source, | 803 | /* if announcement packet, use the source, |
| 809 | * otherwise assume it is in the hw_src | 804 | * otherwise assume it is in the hw_src |
| 810 | */ | 805 | */ |
| @@ -866,12 +861,13 @@ static int batadv_bla_process_claim(struct batadv_priv *bat_priv, | |||
| 866 | struct batadv_hard_iface *primary_if, | 861 | struct batadv_hard_iface *primary_if, |
| 867 | struct sk_buff *skb) | 862 | struct sk_buff *skb) |
| 868 | { | 863 | { |
| 869 | struct batadv_bla_claim_dst *bla_dst; | 864 | struct batadv_bla_claim_dst *bla_dst, *bla_dst_own; |
| 870 | uint8_t *hw_src, *hw_dst; | 865 | uint8_t *hw_src, *hw_dst; |
| 871 | struct vlan_ethhdr *vhdr; | 866 | struct vlan_hdr *vhdr, vhdr_buf; |
| 872 | struct ethhdr *ethhdr; | 867 | struct ethhdr *ethhdr; |
| 873 | struct arphdr *arphdr; | 868 | struct arphdr *arphdr; |
| 874 | unsigned short vid; | 869 | unsigned short vid; |
| 870 | int vlan_depth = 0; | ||
| 875 | __be16 proto; | 871 | __be16 proto; |
| 876 | int headlen; | 872 | int headlen; |
| 877 | int ret; | 873 | int ret; |
| @@ -882,9 +878,24 @@ static int batadv_bla_process_claim(struct batadv_priv *bat_priv, | |||
| 882 | proto = ethhdr->h_proto; | 878 | proto = ethhdr->h_proto; |
| 883 | headlen = ETH_HLEN; | 879 | headlen = ETH_HLEN; |
| 884 | if (vid & BATADV_VLAN_HAS_TAG) { | 880 | if (vid & BATADV_VLAN_HAS_TAG) { |
| 885 | vhdr = vlan_eth_hdr(skb); | 881 | /* Traverse the VLAN/Ethertypes. |
| 886 | proto = vhdr->h_vlan_encapsulated_proto; | 882 | * |
| 887 | headlen += VLAN_HLEN; | 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)); | ||
| 888 | } | 899 | } |
| 889 | 900 | ||
| 890 | if (proto != htons(ETH_P_ARP)) | 901 | if (proto != htons(ETH_P_ARP)) |
| @@ -914,6 +925,19 @@ static int batadv_bla_process_claim(struct batadv_priv *bat_priv, | |||
| 914 | hw_src = (uint8_t *)arphdr + sizeof(struct arphdr); | 925 | hw_src = (uint8_t *)arphdr + sizeof(struct arphdr); |
| 915 | hw_dst = hw_src + ETH_ALEN + 4; | 926 | hw_dst = hw_src + ETH_ALEN + 4; |
| 916 | bla_dst = (struct batadv_bla_claim_dst *)hw_dst; | 927 | 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; | ||
| 917 | 941 | ||
| 918 | /* check if it is a claim frame. */ | 942 | /* check if it is a claim frame. */ |
| 919 | ret = batadv_check_claim_group(bat_priv, primary_if, hw_src, hw_dst, | 943 | ret = batadv_check_claim_group(bat_priv, primary_if, hw_src, hw_dst, |
