diff options
Diffstat (limited to 'net/bridge/br_multicast.c')
-rw-r--r-- | net/bridge/br_multicast.c | 37 |
1 files changed, 30 insertions, 7 deletions
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 0dd3cd90962c..ed5dc684a4ce 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c | |||
@@ -39,6 +39,16 @@ static void br_multicast_start_querier(struct net_bridge *br, | |||
39 | struct bridge_mcast_own_query *query); | 39 | struct bridge_mcast_own_query *query); |
40 | static void br_multicast_add_router(struct net_bridge *br, | 40 | static void br_multicast_add_router(struct net_bridge *br, |
41 | struct net_bridge_port *port); | 41 | struct net_bridge_port *port); |
42 | static void br_ip4_multicast_leave_group(struct net_bridge *br, | ||
43 | struct net_bridge_port *port, | ||
44 | __be32 group, | ||
45 | __u16 vid); | ||
46 | #if IS_ENABLED(CONFIG_IPV6) | ||
47 | static void br_ip6_multicast_leave_group(struct net_bridge *br, | ||
48 | struct net_bridge_port *port, | ||
49 | const struct in6_addr *group, | ||
50 | __u16 vid); | ||
51 | #endif | ||
42 | unsigned int br_mdb_rehash_seq; | 52 | unsigned int br_mdb_rehash_seq; |
43 | 53 | ||
44 | static inline int br_ip_equal(const struct br_ip *a, const struct br_ip *b) | 54 | static inline int br_ip_equal(const struct br_ip *a, const struct br_ip *b) |
@@ -1022,9 +1032,15 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge *br, | |||
1022 | continue; | 1032 | continue; |
1023 | } | 1033 | } |
1024 | 1034 | ||
1025 | err = br_ip4_multicast_add_group(br, port, group, vid); | 1035 | if ((type == IGMPV3_CHANGE_TO_INCLUDE || |
1026 | if (err) | 1036 | type == IGMPV3_MODE_IS_INCLUDE) && |
1027 | break; | 1037 | ntohs(grec->grec_nsrcs) == 0) { |
1038 | br_ip4_multicast_leave_group(br, port, group, vid); | ||
1039 | } else { | ||
1040 | err = br_ip4_multicast_add_group(br, port, group, vid); | ||
1041 | if (err) | ||
1042 | break; | ||
1043 | } | ||
1028 | } | 1044 | } |
1029 | 1045 | ||
1030 | return err; | 1046 | return err; |
@@ -1083,10 +1099,17 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br, | |||
1083 | continue; | 1099 | continue; |
1084 | } | 1100 | } |
1085 | 1101 | ||
1086 | err = br_ip6_multicast_add_group(br, port, &grec->grec_mca, | 1102 | if ((grec->grec_type == MLD2_CHANGE_TO_INCLUDE || |
1087 | vid); | 1103 | grec->grec_type == MLD2_MODE_IS_INCLUDE) && |
1088 | if (err) | 1104 | ntohs(*nsrcs) == 0) { |
1089 | break; | 1105 | br_ip6_multicast_leave_group(br, port, &grec->grec_mca, |
1106 | vid); | ||
1107 | } else { | ||
1108 | err = br_ip6_multicast_add_group(br, port, | ||
1109 | &grec->grec_mca, vid); | ||
1110 | if (!err) | ||
1111 | break; | ||
1112 | } | ||
1090 | } | 1113 | } |
1091 | 1114 | ||
1092 | return err; | 1115 | return err; |