aboutsummaryrefslogtreecommitdiffstats
path: root/net
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
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')
-rw-r--r--net/bridge/br_device.c2
-rw-r--r--net/bridge/br_input.c2
-rw-r--r--net/bridge/br_multicast.c44
-rw-r--r--net/bridge/br_private.h6
4 files changed, 25 insertions, 29 deletions
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index ca04163635da..e6b7fecb3af1 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -64,7 +64,7 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
64 br_flood_deliver(br, skb, false); 64 br_flood_deliver(br, skb, false);
65 goto out; 65 goto out;
66 } 66 }
67 if (br_multicast_rcv(br, NULL, skb)) { 67 if (br_multicast_rcv(br, NULL, skb, vid)) {
68 kfree_skb(skb); 68 kfree_skb(skb);
69 goto out; 69 goto out;
70 } 70 }
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index a2fd37ec35f7..7e73c32e205d 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -80,7 +80,7 @@ int br_handle_frame_finish(struct sk_buff *skb)
80 br_fdb_update(br, p, eth_hdr(skb)->h_source, vid); 80 br_fdb_update(br, p, eth_hdr(skb)->h_source, vid);
81 81
82 if (!is_broadcast_ether_addr(dest) && is_multicast_ether_addr(dest) && 82 if (!is_broadcast_ether_addr(dest) && is_multicast_ether_addr(dest) &&
83 br_multicast_rcv(br, p, skb)) 83 br_multicast_rcv(br, p, skb, vid))
84 goto drop; 84 goto drop;
85 85
86 if (p->state == BR_STATE_LEARNING) 86 if (p->state == BR_STATE_LEARNING)
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
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index e14c33b42f75..2e8244efb262 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -451,7 +451,8 @@ extern int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __us
451extern unsigned int br_mdb_rehash_seq; 451extern unsigned int br_mdb_rehash_seq;
452extern int br_multicast_rcv(struct net_bridge *br, 452extern int br_multicast_rcv(struct net_bridge *br,
453 struct net_bridge_port *port, 453 struct net_bridge_port *port,
454 struct sk_buff *skb); 454 struct sk_buff *skb,
455 u16 vid);
455extern struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br, 456extern struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br,
456 struct sk_buff *skb, u16 vid); 457 struct sk_buff *skb, u16 vid);
457extern void br_multicast_add_port(struct net_bridge_port *port); 458extern void br_multicast_add_port(struct net_bridge_port *port);
@@ -522,7 +523,8 @@ static inline bool br_multicast_querier_exists(struct net_bridge *br,
522#else 523#else
523static inline int br_multicast_rcv(struct net_bridge *br, 524static inline int br_multicast_rcv(struct net_bridge *br,
524 struct net_bridge_port *port, 525 struct net_bridge_port *port,
525 struct sk_buff *skb) 526 struct sk_buff *skb,
527 u16 vid)
526{ 528{
527 return 0; 529 return 0;
528} 530}