aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge/br_multicast.c
diff options
context:
space:
mode:
authorVlad Yasevich <vyasevic@redhat.com>2013-10-28 15:45:07 -0400
committerDavid S. Miller <davem@davemloft.net>2013-10-29 17:40:08 -0400
commit06499098a02b9ed906a7b6060f2c60fb813918d4 (patch)
treec111ac98dd6790a2d2c04cca7a37d55abbff2b2c /net/bridge/br_multicast.c
parent911aeb108493caa45b4ca08313ee0600e943cd2b (diff)
bridge: pass correct vlan id to multicast code
Currently multicast code attempts to extrace the vlan id from the skb even when vlan filtering is disabled. This can lead to mdb entries being created with the wrong vlan id. Pass the already extracted vlan id to the multicast filtering code to make the correct id is used in creation as well as lookup. Signed-off-by: Vlad Yasevich <vyasevic@redhat.com> Acked-by: Toshiaki Makita <makita.toshiaki@lab.ntt.co.jp> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge/br_multicast.c')
-rw-r--r--net/bridge/br_multicast.c44
1 files changed, 19 insertions, 25 deletions
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 8b0b610ca2c9..686284ff3d6a 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -947,7 +947,8 @@ void br_multicast_disable_port(struct net_bridge_port *port)
947 947
948static int br_ip4_multicast_igmp3_report(struct net_bridge *br, 948static int br_ip4_multicast_igmp3_report(struct net_bridge *br,
949 struct net_bridge_port *port, 949 struct net_bridge_port *port,
950 struct sk_buff *skb) 950 struct sk_buff *skb,
951 u16 vid)
951{ 952{
952 struct igmpv3_report *ih; 953 struct igmpv3_report *ih;
953 struct igmpv3_grec *grec; 954 struct igmpv3_grec *grec;
@@ -957,12 +958,10 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge *br,
957 int type; 958 int type;
958 int err = 0; 959 int err = 0;
959 __be32 group; 960 __be32 group;
960 u16 vid = 0;
961 961
962 if (!pskb_may_pull(skb, sizeof(*ih))) 962 if (!pskb_may_pull(skb, sizeof(*ih)))
963 return -EINVAL; 963 return -EINVAL;
964 964
965 br_vlan_get_tag(skb, &vid);
966 ih = igmpv3_report_hdr(skb); 965 ih = igmpv3_report_hdr(skb);
967 num = ntohs(ih->ngrec); 966 num = ntohs(ih->ngrec);
968 len = sizeof(*ih); 967 len = sizeof(*ih);
@@ -1005,7 +1004,8 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge *br,
1005#if IS_ENABLED(CONFIG_IPV6) 1004#if IS_ENABLED(CONFIG_IPV6)
1006static int br_ip6_multicast_mld2_report(struct net_bridge *br, 1005static int br_ip6_multicast_mld2_report(struct net_bridge *br,
1007 struct net_bridge_port *port, 1006 struct net_bridge_port *port,
1008 struct sk_buff *skb) 1007 struct sk_buff *skb,
1008 u16 vid)
1009{ 1009{
1010 struct icmp6hdr *icmp6h; 1010 struct icmp6hdr *icmp6h;
1011 struct mld2_grec *grec; 1011 struct mld2_grec *grec;
@@ -1013,12 +1013,10 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br,
1013 int len; 1013 int len;
1014 int num; 1014 int num;
1015 int err = 0; 1015 int err = 0;
1016 u16 vid = 0;
1017 1016
1018 if (!pskb_may_pull(skb, sizeof(*icmp6h))) 1017 if (!pskb_may_pull(skb, sizeof(*icmp6h)))
1019 return -EINVAL; 1018 return -EINVAL;
1020 1019
1021 br_vlan_get_tag(skb, &vid);
1022 icmp6h = icmp6_hdr(skb); 1020 icmp6h = icmp6_hdr(skb);
1023 num = ntohs(icmp6h->icmp6_dataun.un_data16[1]); 1021 num = ntohs(icmp6h->icmp6_dataun.un_data16[1]);
1024 len = sizeof(*icmp6h); 1022 len = sizeof(*icmp6h);
@@ -1141,7 +1139,8 @@ static void br_multicast_query_received(struct net_bridge *br,
1141 1139
1142static int br_ip4_multicast_query(struct net_bridge *br, 1140static int br_ip4_multicast_query(struct net_bridge *br,
1143 struct net_bridge_port *port, 1141 struct net_bridge_port *port,
1144 struct sk_buff *skb) 1142 struct sk_buff *skb,
1143 u16 vid)
1145{ 1144{
1146 const struct iphdr *iph = ip_hdr(skb); 1145 const struct iphdr *iph = ip_hdr(skb);
1147 struct igmphdr *ih = igmp_hdr(skb); 1146 struct igmphdr *ih = igmp_hdr(skb);
@@ -1153,7 +1152,6 @@ static int br_ip4_multicast_query(struct net_bridge *br,
1153 unsigned long now = jiffies; 1152 unsigned long now = jiffies;
1154 __be32 group; 1153 __be32 group;
1155 int err = 0; 1154 int err = 0;
1156 u16 vid = 0;
1157 1155
1158 spin_lock(&br->multicast_lock); 1156 spin_lock(&br->multicast_lock);
1159 if (!netif_running(br->dev) || 1157 if (!netif_running(br->dev) ||
@@ -1189,7 +1187,6 @@ static int br_ip4_multicast_query(struct net_bridge *br,
1189 if (!group) 1187 if (!group)
1190 goto out; 1188 goto out;
1191 1189
1192 br_vlan_get_tag(skb, &vid);
1193 mp = br_mdb_ip4_get(mlock_dereference(br->mdb, br), group, vid); 1190 mp = br_mdb_ip4_get(mlock_dereference(br->mdb, br), group, vid);
1194 if (!mp) 1191 if (!mp)
1195 goto out; 1192 goto out;
@@ -1219,7 +1216,8 @@ out:
1219#if IS_ENABLED(CONFIG_IPV6) 1216#if IS_ENABLED(CONFIG_IPV6)
1220static int br_ip6_multicast_query(struct net_bridge *br, 1217static int br_ip6_multicast_query(struct net_bridge *br,
1221 struct net_bridge_port *port, 1218 struct net_bridge_port *port,
1222 struct sk_buff *skb) 1219 struct sk_buff *skb,
1220 u16 vid)
1223{ 1221{
1224 const struct ipv6hdr *ip6h = ipv6_hdr(skb); 1222 const struct ipv6hdr *ip6h = ipv6_hdr(skb);
1225 struct mld_msg *mld; 1223 struct mld_msg *mld;
@@ -1231,7 +1229,6 @@ static int br_ip6_multicast_query(struct net_bridge *br,
1231 unsigned long now = jiffies; 1229 unsigned long now = jiffies;
1232 const struct in6_addr *group = NULL; 1230 const struct in6_addr *group = NULL;
1233 int err = 0; 1231 int err = 0;
1234 u16 vid = 0;
1235 1232
1236 spin_lock(&br->multicast_lock); 1233 spin_lock(&br->multicast_lock);
1237 if (!netif_running(br->dev) || 1234 if (!netif_running(br->dev) ||
@@ -1265,7 +1262,6 @@ static int br_ip6_multicast_query(struct net_bridge *br,
1265 if (!group) 1262 if (!group)
1266 goto out; 1263 goto out;
1267 1264
1268 br_vlan_get_tag(skb, &vid);
1269 mp = br_mdb_ip6_get(mlock_dereference(br->mdb, br), group, vid); 1265 mp = br_mdb_ip6_get(mlock_dereference(br->mdb, br), group, vid);
1270 if (!mp) 1266 if (!mp)
1271 goto out; 1267 goto out;
@@ -1439,7 +1435,8 @@ static void br_ip6_multicast_leave_group(struct net_bridge *br,
1439 1435
1440static int br_multicast_ipv4_rcv(struct net_bridge *br, 1436static int br_multicast_ipv4_rcv(struct net_bridge *br,
1441 struct net_bridge_port *port, 1437 struct net_bridge_port *port,
1442 struct sk_buff *skb) 1438 struct sk_buff *skb,
1439 u16 vid)
1443{ 1440{
1444 struct sk_buff *skb2 = skb; 1441 struct sk_buff *skb2 = skb;
1445 const struct iphdr *iph; 1442 const struct iphdr *iph;
@@ -1447,7 +1444,6 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,
1447 unsigned int len; 1444 unsigned int len;
1448 unsigned int offset; 1445 unsigned int offset;
1449 int err; 1446 int err;
1450 u16 vid = 0;
1451 1447
1452 /* We treat OOM as packet loss for now. */ 1448 /* We treat OOM as packet loss for now. */
1453 if (!pskb_may_pull(skb, sizeof(*iph))) 1449 if (!pskb_may_pull(skb, sizeof(*iph)))
@@ -1508,7 +1504,6 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,
1508 1504
1509 err = 0; 1505 err = 0;
1510 1506
1511 br_vlan_get_tag(skb2, &vid);
1512 BR_INPUT_SKB_CB(skb)->igmp = 1; 1507 BR_INPUT_SKB_CB(skb)->igmp = 1;
1513 ih = igmp_hdr(skb2); 1508 ih = igmp_hdr(skb2);
1514 1509
@@ -1519,10 +1514,10 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,
1519 err = br_ip4_multicast_add_group(br, port, ih->group, vid); 1514 err = br_ip4_multicast_add_group(br, port, ih->group, vid);
1520 break; 1515 break;
1521 case IGMPV3_HOST_MEMBERSHIP_REPORT: 1516 case IGMPV3_HOST_MEMBERSHIP_REPORT:
1522 err = br_ip4_multicast_igmp3_report(br, port, skb2); 1517 err = br_ip4_multicast_igmp3_report(br, port, skb2, vid);
1523 break; 1518 break;
1524 case IGMP_HOST_MEMBERSHIP_QUERY: 1519 case IGMP_HOST_MEMBERSHIP_QUERY:
1525 err = br_ip4_multicast_query(br, port, skb2); 1520 err = br_ip4_multicast_query(br, port, skb2, vid);
1526 break; 1521 break;
1527 case IGMP_HOST_LEAVE_MESSAGE: 1522 case IGMP_HOST_LEAVE_MESSAGE:
1528 br_ip4_multicast_leave_group(br, port, ih->group, vid); 1523 br_ip4_multicast_leave_group(br, port, ih->group, vid);
@@ -1540,7 +1535,8 @@ err_out:
1540#if IS_ENABLED(CONFIG_IPV6) 1535#if IS_ENABLED(CONFIG_IPV6)
1541static int br_multicast_ipv6_rcv(struct net_bridge *br, 1536static int br_multicast_ipv6_rcv(struct net_bridge *br,
1542 struct net_bridge_port *port, 1537 struct net_bridge_port *port,
1543 struct sk_buff *skb) 1538 struct sk_buff *skb,
1539 u16 vid)
1544{ 1540{
1545 struct sk_buff *skb2; 1541 struct sk_buff *skb2;
1546 const struct ipv6hdr *ip6h; 1542 const struct ipv6hdr *ip6h;
@@ -1550,7 +1546,6 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
1550 unsigned int len; 1546 unsigned int len;
1551 int offset; 1547 int offset;
1552 int err; 1548 int err;
1553 u16 vid = 0;
1554 1549
1555 if (!pskb_may_pull(skb, sizeof(*ip6h))) 1550 if (!pskb_may_pull(skb, sizeof(*ip6h)))
1556 return -EINVAL; 1551 return -EINVAL;
@@ -1640,7 +1635,6 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
1640 1635
1641 err = 0; 1636 err = 0;
1642 1637
1643 br_vlan_get_tag(skb, &vid);
1644 BR_INPUT_SKB_CB(skb)->igmp = 1; 1638 BR_INPUT_SKB_CB(skb)->igmp = 1;
1645 1639
1646 switch (icmp6_type) { 1640 switch (icmp6_type) {
@@ -1657,10 +1651,10 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
1657 break; 1651 break;
1658 } 1652 }
1659 case ICMPV6_MLD2_REPORT: 1653 case ICMPV6_MLD2_REPORT:
1660 err = br_ip6_multicast_mld2_report(br, port, skb2); 1654 err = br_ip6_multicast_mld2_report(br, port, skb2, vid);
1661 break; 1655 break;
1662 case ICMPV6_MGM_QUERY: 1656 case ICMPV6_MGM_QUERY:
1663 err = br_ip6_multicast_query(br, port, skb2); 1657 err = br_ip6_multicast_query(br, port, skb2, vid);
1664 break; 1658 break;
1665 case ICMPV6_MGM_REDUCTION: 1659 case ICMPV6_MGM_REDUCTION:
1666 { 1660 {
@@ -1681,7 +1675,7 @@ out:
1681#endif 1675#endif
1682 1676
1683int br_multicast_rcv(struct net_bridge *br, struct net_bridge_port *port, 1677int br_multicast_rcv(struct net_bridge *br, struct net_bridge_port *port,
1684 struct sk_buff *skb) 1678 struct sk_buff *skb, u16 vid)
1685{ 1679{
1686 BR_INPUT_SKB_CB(skb)->igmp = 0; 1680 BR_INPUT_SKB_CB(skb)->igmp = 0;
1687 BR_INPUT_SKB_CB(skb)->mrouters_only = 0; 1681 BR_INPUT_SKB_CB(skb)->mrouters_only = 0;
@@ -1691,10 +1685,10 @@ int br_multicast_rcv(struct net_bridge *br, struct net_bridge_port *port,
1691 1685
1692 switch (skb->protocol) { 1686 switch (skb->protocol) {
1693 case htons(ETH_P_IP): 1687 case htons(ETH_P_IP):
1694 return br_multicast_ipv4_rcv(br, port, skb); 1688 return br_multicast_ipv4_rcv(br, port, skb, vid);
1695#if IS_ENABLED(CONFIG_IPV6) 1689#if IS_ENABLED(CONFIG_IPV6)
1696 case htons(ETH_P_IPV6): 1690 case htons(ETH_P_IPV6):
1697 return br_multicast_ipv6_rcv(br, port, skb); 1691 return br_multicast_ipv6_rcv(br, port, skb, vid);
1698#endif 1692#endif
1699 } 1693 }
1700 1694