--- zzzz-none-000/linux-2.6.39.4/net/ipv4/igmp.c 2011-08-03 19:43:28.000000000 +0000 +++ puma6-atom-6490-729/linux-2.6.39.4/net/ipv4/igmp.c 2021-11-10 13:38:18.000000000 +0000 @@ -114,7 +114,7 @@ #define IGMP_V1_Router_Present_Timeout (400*HZ) #define IGMP_V2_Router_Present_Timeout (400*HZ) -#define IGMP_Unsolicited_Report_Interval (10*HZ) +#define IGMP_Unsolicited_Report_Interval (1*HZ) #define IGMP_Query_Response_Interval (10*HZ) #define IGMP_Unsolicited_Report_Count 2 @@ -1206,6 +1206,7 @@ } /* else, v3 */ + if (im->sfmode == MCAST_EXCLUDE) im->crcount = in_dev->mr_qrv ? in_dev->mr_qrv : IGMP_Unsolicited_Report_Count; igmp_ifc_event(in_dev); @@ -1222,7 +1223,7 @@ * A socket has joined a multicast group on device dev. */ -void ip_mc_inc_group(struct in_device *in_dev, __be32 addr) +void ip_mc_inc_group_for_mode(struct in_device *in_dev, __be32 addr, int omode) { struct ip_mc_list *im; @@ -1231,7 +1232,7 @@ for_each_pmc_rtnl(in_dev, im) { if (im->multiaddr == addr) { im->users++; - ip_mc_add_src(in_dev, &addr, MCAST_EXCLUDE, 0, NULL, 0); + ip_mc_add_src(in_dev, &addr, omode, 0, NULL, 0); goto out; } } @@ -1244,9 +1245,15 @@ im->interface = in_dev; in_dev_hold(in_dev); im->multiaddr = addr; - /* initial mode is (EX, empty) */ - im->sfmode = MCAST_EXCLUDE; - im->sfcount[MCAST_EXCLUDE] = 1; + if (omode == MCAST_EXCLUDE) { + /* initial mode is (EX, empty) */ + im->sfmode = MCAST_EXCLUDE; + im->sfcount[MCAST_EXCLUDE] = 1; + } else { + im->sfmode = MCAST_INCLUDE; + im->sfcount[MCAST_INCLUDE] = 1; + im->sfcount[MCAST_EXCLUDE] = 0; + } atomic_set(&im->refcnt, 1); spin_lock_init(&im->lock); #ifdef CONFIG_IP_MULTICAST @@ -1298,6 +1305,11 @@ } EXPORT_SYMBOL(ip_mc_rejoin_groups); +void ip_mc_inc_group(struct in_device *in_dev, u32 addr) +{ + ip_mc_inc_group_for_mode(in_dev, addr, MCAST_EXCLUDE); +} + /* * A socket has left a multicast group on device dev */ @@ -1784,7 +1796,7 @@ /* * Join a multicast group */ -int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr) +int ip_mc_join_group_for_mode(struct sock *sk , struct ip_mreqn *imr, int omode) { int err; __be32 addr = imr->imr_multiaddr.s_addr; @@ -1826,15 +1838,15 @@ memcpy(&iml->multi, imr, sizeof(*imr)); iml->next_rcu = inet->mc_list; iml->sflist = NULL; - iml->sfmode = MCAST_EXCLUDE; + iml->sfmode = omode; rcu_assign_pointer(inet->mc_list, iml); - ip_mc_inc_group(in_dev, addr); + ip_mc_inc_group_for_mode(in_dev, addr, omode); err = 0; done: rtnl_unlock(); return err; } -EXPORT_SYMBOL(ip_mc_join_group); +EXPORT_SYMBOL(ip_mc_join_group_for_mode); static void ip_sf_socklist_reclaim(struct rcu_head *rp) { @@ -1842,6 +1854,12 @@ /* sk_omem_alloc should have been decreased by the caller*/ } +int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr) +{ + return ip_mc_join_group_for_mode(sk, imr, MCAST_EXCLUDE); +} +EXPORT_SYMBOL(ip_mc_join_group); + static int ip_mc_leave_src(struct sock *sk, struct ip_mc_socklist *iml, struct in_device *in_dev) { @@ -2266,9 +2284,10 @@ int i; int ret; - ret = 1; - if (!ipv4_is_multicast(loc_addr)) + if (!ipv4_is_multicast(loc_addr)) { + ret = sock_flag(sk, SOCK_BROADCAST) ? 1 : 0; goto out; + } rcu_read_lock(); for_each_pmc_rcu(inet, pmc) {