@@ -43,12 +43,14 @@ static void br_multicast_add_router(struct net_bridge *br,
4343static void br_ip4_multicast_leave_group (struct net_bridge * br ,
4444 struct net_bridge_port * port ,
4545 __be32 group ,
46- __u16 vid );
46+ __u16 vid ,
47+ const unsigned char * src );
48+
4749#if IS_ENABLED (CONFIG_IPV6 )
4850static void br_ip6_multicast_leave_group (struct net_bridge * br ,
4951 struct net_bridge_port * port ,
5052 const struct in6_addr * group ,
51- __u16 vid );
53+ __u16 vid , const unsigned char * src );
5254#endif
5355unsigned int br_mdb_rehash_seq ;
5456
@@ -711,7 +713,8 @@ struct net_bridge_port_group *br_multicast_new_port_group(
711713 struct net_bridge_port * port ,
712714 struct br_ip * group ,
713715 struct net_bridge_port_group __rcu * next ,
714- unsigned char flags )
716+ unsigned char flags ,
717+ const unsigned char * src )
715718{
716719 struct net_bridge_port_group * p ;
717720
@@ -726,12 +729,32 @@ struct net_bridge_port_group *br_multicast_new_port_group(
726729 hlist_add_head (& p -> mglist , & port -> mglist );
727730 setup_timer (& p -> timer , br_multicast_port_group_expired ,
728731 (unsigned long )p );
732+
733+ if (src )
734+ memcpy (p -> eth_addr , src , ETH_ALEN );
735+ else
736+ memset (p -> eth_addr , 0xff , ETH_ALEN );
737+
729738 return p ;
730739}
731740
741+ static bool br_port_group_equal (struct net_bridge_port_group * p ,
742+ struct net_bridge_port * port ,
743+ const unsigned char * src )
744+ {
745+ if (p -> port != port )
746+ return false;
747+
748+ if (!(port -> flags & BR_MULTICAST_TO_UNICAST ))
749+ return true;
750+
751+ return ether_addr_equal (src , p -> eth_addr );
752+ }
753+
732754static int br_multicast_add_group (struct net_bridge * br ,
733755 struct net_bridge_port * port ,
734- struct br_ip * group )
756+ struct br_ip * group ,
757+ const unsigned char * src )
735758{
736759 struct net_bridge_port_group __rcu * * pp ;
737760 struct net_bridge_port_group * p ;
@@ -758,13 +781,13 @@ static int br_multicast_add_group(struct net_bridge *br,
758781 for (pp = & mp -> ports ;
759782 (p = mlock_dereference (* pp , br )) != NULL ;
760783 pp = & p -> next ) {
761- if (p -> port == port )
784+ if (br_port_group_equal ( p , port , src ) )
762785 goto found ;
763786 if ((unsigned long )p -> port < (unsigned long )port )
764787 break ;
765788 }
766789
767- p = br_multicast_new_port_group (port , group , * pp , 0 );
790+ p = br_multicast_new_port_group (port , group , * pp , 0 , src );
768791 if (unlikely (!p ))
769792 goto err ;
770793 rcu_assign_pointer (* pp , p );
@@ -783,7 +806,8 @@ static int br_multicast_add_group(struct net_bridge *br,
783806static int br_ip4_multicast_add_group (struct net_bridge * br ,
784807 struct net_bridge_port * port ,
785808 __be32 group ,
786- __u16 vid )
809+ __u16 vid ,
810+ const unsigned char * src )
787811{
788812 struct br_ip br_group ;
789813
@@ -794,14 +818,15 @@ static int br_ip4_multicast_add_group(struct net_bridge *br,
794818 br_group .proto = htons (ETH_P_IP );
795819 br_group .vid = vid ;
796820
797- return br_multicast_add_group (br , port , & br_group );
821+ return br_multicast_add_group (br , port , & br_group , src );
798822}
799823
800824#if IS_ENABLED (CONFIG_IPV6 )
801825static int br_ip6_multicast_add_group (struct net_bridge * br ,
802826 struct net_bridge_port * port ,
803827 const struct in6_addr * group ,
804- __u16 vid )
828+ __u16 vid ,
829+ const unsigned char * src )
805830{
806831 struct br_ip br_group ;
807832
@@ -812,7 +837,7 @@ static int br_ip6_multicast_add_group(struct net_bridge *br,
812837 br_group .proto = htons (ETH_P_IPV6 );
813838 br_group .vid = vid ;
814839
815- return br_multicast_add_group (br , port , & br_group );
840+ return br_multicast_add_group (br , port , & br_group , src );
816841}
817842#endif
818843
@@ -1081,6 +1106,7 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge *br,
10811106 struct sk_buff * skb ,
10821107 u16 vid )
10831108{
1109+ const unsigned char * src ;
10841110 struct igmpv3_report * ih ;
10851111 struct igmpv3_grec * grec ;
10861112 int i ;
@@ -1121,12 +1147,14 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge *br,
11211147 continue ;
11221148 }
11231149
1150+ src = eth_hdr (skb )-> h_source ;
11241151 if ((type == IGMPV3_CHANGE_TO_INCLUDE ||
11251152 type == IGMPV3_MODE_IS_INCLUDE ) &&
11261153 ntohs (grec -> grec_nsrcs ) == 0 ) {
1127- br_ip4_multicast_leave_group (br , port , group , vid );
1154+ br_ip4_multicast_leave_group (br , port , group , vid , src );
11281155 } else {
1129- err = br_ip4_multicast_add_group (br , port , group , vid );
1156+ err = br_ip4_multicast_add_group (br , port , group , vid ,
1157+ src );
11301158 if (err )
11311159 break ;
11321160 }
@@ -1141,6 +1169,7 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br,
11411169 struct sk_buff * skb ,
11421170 u16 vid )
11431171{
1172+ const unsigned char * src ;
11441173 struct icmp6hdr * icmp6h ;
11451174 struct mld2_grec * grec ;
11461175 int i ;
@@ -1188,14 +1217,16 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br,
11881217 continue ;
11891218 }
11901219
1220+ src = eth_hdr (skb )-> h_source ;
11911221 if ((grec -> grec_type == MLD2_CHANGE_TO_INCLUDE ||
11921222 grec -> grec_type == MLD2_MODE_IS_INCLUDE ) &&
11931223 ntohs (* nsrcs ) == 0 ) {
11941224 br_ip6_multicast_leave_group (br , port , & grec -> grec_mca ,
1195- vid );
1225+ vid , src );
11961226 } else {
11971227 err = br_ip6_multicast_add_group (br , port ,
1198- & grec -> grec_mca , vid );
1228+ & grec -> grec_mca , vid ,
1229+ src );
11991230 if (err )
12001231 break ;
12011232 }
@@ -1511,7 +1542,8 @@ br_multicast_leave_group(struct net_bridge *br,
15111542 struct net_bridge_port * port ,
15121543 struct br_ip * group ,
15131544 struct bridge_mcast_other_query * other_query ,
1514- struct bridge_mcast_own_query * own_query )
1545+ struct bridge_mcast_own_query * own_query ,
1546+ const unsigned char * src )
15151547{
15161548 struct net_bridge_mdb_htable * mdb ;
15171549 struct net_bridge_mdb_entry * mp ;
@@ -1535,7 +1567,7 @@ br_multicast_leave_group(struct net_bridge *br,
15351567 for (pp = & mp -> ports ;
15361568 (p = mlock_dereference (* pp , br )) != NULL ;
15371569 pp = & p -> next ) {
1538- if (p -> port != port )
1570+ if (! br_port_group_equal ( p , port , src ) )
15391571 continue ;
15401572
15411573 rcu_assign_pointer (* pp , p -> next );
@@ -1566,7 +1598,7 @@ br_multicast_leave_group(struct net_bridge *br,
15661598 for (p = mlock_dereference (mp -> ports , br );
15671599 p != NULL ;
15681600 p = mlock_dereference (p -> next , br )) {
1569- if (p -> port != port )
1601+ if (! br_port_group_equal ( p , port , src ) )
15701602 continue ;
15711603
15721604 if (!hlist_unhashed (& p -> mglist ) &&
@@ -1617,7 +1649,8 @@ br_multicast_leave_group(struct net_bridge *br,
16171649static void br_ip4_multicast_leave_group (struct net_bridge * br ,
16181650 struct net_bridge_port * port ,
16191651 __be32 group ,
1620- __u16 vid )
1652+ __u16 vid ,
1653+ const unsigned char * src )
16211654{
16221655 struct br_ip br_group ;
16231656 struct bridge_mcast_own_query * own_query ;
@@ -1632,14 +1665,15 @@ static void br_ip4_multicast_leave_group(struct net_bridge *br,
16321665 br_group .vid = vid ;
16331666
16341667 br_multicast_leave_group (br , port , & br_group , & br -> ip4_other_query ,
1635- own_query );
1668+ own_query , src );
16361669}
16371670
16381671#if IS_ENABLED (CONFIG_IPV6 )
16391672static void br_ip6_multicast_leave_group (struct net_bridge * br ,
16401673 struct net_bridge_port * port ,
16411674 const struct in6_addr * group ,
1642- __u16 vid )
1675+ __u16 vid ,
1676+ const unsigned char * src )
16431677{
16441678 struct br_ip br_group ;
16451679 struct bridge_mcast_own_query * own_query ;
@@ -1654,7 +1688,7 @@ static void br_ip6_multicast_leave_group(struct net_bridge *br,
16541688 br_group .vid = vid ;
16551689
16561690 br_multicast_leave_group (br , port , & br_group , & br -> ip6_other_query ,
1657- own_query );
1691+ own_query , src );
16581692}
16591693#endif
16601694
@@ -1712,6 +1746,7 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,
17121746 u16 vid )
17131747{
17141748 struct sk_buff * skb_trimmed = NULL ;
1749+ const unsigned char * src ;
17151750 struct igmphdr * ih ;
17161751 int err ;
17171752
@@ -1731,13 +1766,14 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,
17311766 }
17321767
17331768 ih = igmp_hdr (skb );
1769+ src = eth_hdr (skb )-> h_source ;
17341770 BR_INPUT_SKB_CB (skb )-> igmp = ih -> type ;
17351771
17361772 switch (ih -> type ) {
17371773 case IGMP_HOST_MEMBERSHIP_REPORT :
17381774 case IGMPV2_HOST_MEMBERSHIP_REPORT :
17391775 BR_INPUT_SKB_CB (skb )-> mrouters_only = 1 ;
1740- err = br_ip4_multicast_add_group (br , port , ih -> group , vid );
1776+ err = br_ip4_multicast_add_group (br , port , ih -> group , vid , src );
17411777 break ;
17421778 case IGMPV3_HOST_MEMBERSHIP_REPORT :
17431779 err = br_ip4_multicast_igmp3_report (br , port , skb_trimmed , vid );
@@ -1746,7 +1782,7 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,
17461782 err = br_ip4_multicast_query (br , port , skb_trimmed , vid );
17471783 break ;
17481784 case IGMP_HOST_LEAVE_MESSAGE :
1749- br_ip4_multicast_leave_group (br , port , ih -> group , vid );
1785+ br_ip4_multicast_leave_group (br , port , ih -> group , vid , src );
17501786 break ;
17511787 }
17521788
@@ -1766,6 +1802,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
17661802 u16 vid )
17671803{
17681804 struct sk_buff * skb_trimmed = NULL ;
1805+ const unsigned char * src ;
17691806 struct mld_msg * mld ;
17701807 int err ;
17711808
@@ -1785,8 +1822,10 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
17851822
17861823 switch (mld -> mld_type ) {
17871824 case ICMPV6_MGM_REPORT :
1825+ src = eth_hdr (skb )-> h_source ;
17881826 BR_INPUT_SKB_CB (skb )-> mrouters_only = 1 ;
1789- err = br_ip6_multicast_add_group (br , port , & mld -> mld_mca , vid );
1827+ err = br_ip6_multicast_add_group (br , port , & mld -> mld_mca , vid ,
1828+ src );
17901829 break ;
17911830 case ICMPV6_MLD2_REPORT :
17921831 err = br_ip6_multicast_mld2_report (br , port , skb_trimmed , vid );
@@ -1795,7 +1834,8 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
17951834 err = br_ip6_multicast_query (br , port , skb_trimmed , vid );
17961835 break ;
17971836 case ICMPV6_MGM_REDUCTION :
1798- br_ip6_multicast_leave_group (br , port , & mld -> mld_mca , vid );
1837+ src = eth_hdr (skb )-> h_source ;
1838+ br_ip6_multicast_leave_group (br , port , & mld -> mld_mca , vid , src );
17991839 break ;
18001840 }
18011841
0 commit comments