aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/ipv6/mcast.c34
1 files changed, 21 insertions, 13 deletions
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 8992ff262789..f86e26b7296c 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -95,6 +95,7 @@ static void mld_ifc_event(struct inet6_dev *idev);
95static void mld_add_delrec(struct inet6_dev *idev, struct ifmcaddr6 *pmc); 95static void mld_add_delrec(struct inet6_dev *idev, struct ifmcaddr6 *pmc);
96static void mld_del_delrec(struct inet6_dev *idev, const struct in6_addr *addr); 96static void mld_del_delrec(struct inet6_dev *idev, const struct in6_addr *addr);
97static void mld_clear_delrec(struct inet6_dev *idev); 97static void mld_clear_delrec(struct inet6_dev *idev);
98static bool mld_in_v1_mode(const struct inet6_dev *idev);
98static int sf_setstate(struct ifmcaddr6 *pmc); 99static int sf_setstate(struct ifmcaddr6 *pmc);
99static void sf_markstate(struct ifmcaddr6 *pmc); 100static void sf_markstate(struct ifmcaddr6 *pmc);
100static void ip6_mc_clear_src(struct ifmcaddr6 *pmc); 101static void ip6_mc_clear_src(struct ifmcaddr6 *pmc);
@@ -117,11 +118,6 @@ static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml,
117#define MLD_V1_QUERY_LEN 24 118#define MLD_V1_QUERY_LEN 24
118#define MLD_V2_QUERY_LEN_MIN 28 119#define MLD_V2_QUERY_LEN_MIN 28
119 120
120#define MLD_V1_SEEN(idev) (dev_net((idev)->dev)->ipv6.devconf_all->force_mld_version == 1 || \
121 (idev)->cnf.force_mld_version == 1 || \
122 ((idev)->mc_v1_seen && \
123 time_before(jiffies, (idev)->mc_v1_seen)))
124
125#define IPV6_MLD_MAX_MSF 64 121#define IPV6_MLD_MAX_MSF 64
126 122
127int sysctl_mld_max_msf __read_mostly = IPV6_MLD_MAX_MSF; 123int sysctl_mld_max_msf __read_mostly = IPV6_MLD_MAX_MSF;
@@ -139,7 +135,7 @@ static int unsolicited_report_interval(struct inet6_dev *idev)
139{ 135{
140 int iv; 136 int iv;
141 137
142 if (MLD_V1_SEEN(idev)) 138 if (mld_in_v1_mode(idev))
143 iv = idev->cnf.mldv1_unsolicited_report_interval; 139 iv = idev->cnf.mldv1_unsolicited_report_interval;
144 else 140 else
145 iv = idev->cnf.mldv2_unsolicited_report_interval; 141 iv = idev->cnf.mldv2_unsolicited_report_interval;
@@ -695,7 +691,7 @@ static void igmp6_group_added(struct ifmcaddr6 *mc)
695 if (!(dev->flags & IFF_UP) || (mc->mca_flags & MAF_NOREPORT)) 691 if (!(dev->flags & IFF_UP) || (mc->mca_flags & MAF_NOREPORT))
696 return; 692 return;
697 693
698 if (MLD_V1_SEEN(mc->idev)) { 694 if (mld_in_v1_mode(mc->idev)) {
699 igmp6_join_group(mc); 695 igmp6_join_group(mc);
700 return; 696 return;
701 } 697 }
@@ -1116,6 +1112,18 @@ static bool mld_marksources(struct ifmcaddr6 *pmc, int nsrcs,
1116 return true; 1112 return true;
1117} 1113}
1118 1114
1115static bool mld_in_v1_mode(const struct inet6_dev *idev)
1116{
1117 if (dev_net(idev->dev)->ipv6.devconf_all->force_mld_version == 1)
1118 return true;
1119 if (idev->cnf.force_mld_version == 1)
1120 return true;
1121 if (idev->mc_v1_seen && time_before(jiffies, idev->mc_v1_seen))
1122 return true;
1123
1124 return false;
1125}
1126
1119static void mld_set_v1_mode(struct inet6_dev *idev) 1127static void mld_set_v1_mode(struct inet6_dev *idev)
1120{ 1128{
1121 /* RFC3810, relevant sections: 1129 /* RFC3810, relevant sections:
@@ -1262,7 +1270,7 @@ int igmp6_event_query(struct sk_buff *skb)
1262 sizeof(struct icmp6hdr); 1270 sizeof(struct icmp6hdr);
1263 1271
1264 /* hosts need to stay in MLDv1 mode, discard MLDv2 queries */ 1272 /* hosts need to stay in MLDv1 mode, discard MLDv2 queries */
1265 if (MLD_V1_SEEN(idev)) 1273 if (mld_in_v1_mode(idev))
1266 return 0; 1274 return 0;
1267 if (!pskb_may_pull(skb, srcs_offset)) 1275 if (!pskb_may_pull(skb, srcs_offset))
1268 return -EINVAL; 1276 return -EINVAL;
@@ -1942,7 +1950,7 @@ err_out:
1942 1950
1943static void mld_resend_report(struct inet6_dev *idev) 1951static void mld_resend_report(struct inet6_dev *idev)
1944{ 1952{
1945 if (MLD_V1_SEEN(idev)) { 1953 if (mld_in_v1_mode(idev)) {
1946 struct ifmcaddr6 *mcaddr; 1954 struct ifmcaddr6 *mcaddr;
1947 read_lock_bh(&idev->lock); 1955 read_lock_bh(&idev->lock);
1948 for (mcaddr = idev->mc_list; mcaddr; mcaddr = mcaddr->next) { 1956 for (mcaddr = idev->mc_list; mcaddr; mcaddr = mcaddr->next) {
@@ -2006,7 +2014,7 @@ static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode,
2006 else 2014 else
2007 pmc->mca_sources = psf->sf_next; 2015 pmc->mca_sources = psf->sf_next;
2008 if (psf->sf_oldin && !(pmc->mca_flags & MAF_NOREPORT) && 2016 if (psf->sf_oldin && !(pmc->mca_flags & MAF_NOREPORT) &&
2009 !MLD_V1_SEEN(idev)) { 2017 !mld_in_v1_mode(idev)) {
2010 psf->sf_crcount = idev->mc_qrv; 2018 psf->sf_crcount = idev->mc_qrv;
2011 psf->sf_next = pmc->mca_tomb; 2019 psf->sf_next = pmc->mca_tomb;
2012 pmc->mca_tomb = psf; 2020 pmc->mca_tomb = psf;
@@ -2306,7 +2314,7 @@ static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml,
2306 2314
2307static void igmp6_leave_group(struct ifmcaddr6 *ma) 2315static void igmp6_leave_group(struct ifmcaddr6 *ma)
2308{ 2316{
2309 if (MLD_V1_SEEN(ma->idev)) { 2317 if (mld_in_v1_mode(ma->idev)) {
2310 if (ma->mca_flags & MAF_LAST_REPORTER) 2318 if (ma->mca_flags & MAF_LAST_REPORTER)
2311 igmp6_send(&ma->mca_addr, ma->idev->dev, 2319 igmp6_send(&ma->mca_addr, ma->idev->dev,
2312 ICMPV6_MGM_REDUCTION); 2320 ICMPV6_MGM_REDUCTION);
@@ -2340,7 +2348,7 @@ static void mld_ifc_timer_expire(unsigned long data)
2340 2348
2341static void mld_ifc_event(struct inet6_dev *idev) 2349static void mld_ifc_event(struct inet6_dev *idev)
2342{ 2350{
2343 if (MLD_V1_SEEN(idev)) 2351 if (mld_in_v1_mode(idev))
2344 return; 2352 return;
2345 idev->mc_ifc_count = idev->mc_qrv; 2353 idev->mc_ifc_count = idev->mc_qrv;
2346 mld_ifc_start_timer(idev, 1); 2354 mld_ifc_start_timer(idev, 1);
@@ -2351,7 +2359,7 @@ static void igmp6_timer_handler(unsigned long data)
2351{ 2359{
2352 struct ifmcaddr6 *ma = (struct ifmcaddr6 *) data; 2360 struct ifmcaddr6 *ma = (struct ifmcaddr6 *) data;
2353 2361
2354 if (MLD_V1_SEEN(ma->idev)) 2362 if (mld_in_v1_mode(ma->idev))
2355 igmp6_send(&ma->mca_addr, ma->idev->dev, ICMPV6_MGM_REPORT); 2363 igmp6_send(&ma->mca_addr, ma->idev->dev, ICMPV6_MGM_REPORT);
2356 else 2364 else
2357 mld_send_report(ma->idev, ma); 2365 mld_send_report(ma->idev, ma);