mcast.c (efd15f5f4ff63f6ac5d80850686e3d2cc8c4481b) mcast.c (89225d1ce6af3916bf32aecbe9d83f571a098588)
1/*
2 * Multicast support for IPv6
3 * Linux INET6 implementation
4 *
5 * Authors:
6 * Pedro Roque <roque@di.fc.ul.pt>
7 *
8 * Based on linux/ipv4/igmp.c and linux/ipv4/ip_sockglue.c

--- 30 unchanged lines hidden (view full) ---

39#include <linux/in6.h>
40#include <linux/netdevice.h>
41#include <linux/if_arp.h>
42#include <linux/route.h>
43#include <linux/init.h>
44#include <linux/proc_fs.h>
45#include <linux/seq_file.h>
46#include <linux/slab.h>
1/*
2 * Multicast support for IPv6
3 * Linux INET6 implementation
4 *
5 * Authors:
6 * Pedro Roque <roque@di.fc.ul.pt>
7 *
8 * Based on linux/ipv4/igmp.c and linux/ipv4/ip_sockglue.c

--- 30 unchanged lines hidden (view full) ---

39#include <linux/in6.h>
40#include <linux/netdevice.h>
41#include <linux/if_arp.h>
42#include <linux/route.h>
43#include <linux/init.h>
44#include <linux/proc_fs.h>
45#include <linux/seq_file.h>
46#include <linux/slab.h>
47#include <linux/pkt_sched.h>
47#include <net/mld.h>
48
49#include <linux/netfilter.h>
50#include <linux/netfilter_ipv6.h>
51
52#include <net/net_namespace.h>
53#include <net/sock.h>
54#include <net/snmp.h>

--- 46 unchanged lines hidden (view full) ---

101 int sfmode, int sfcount, const struct in6_addr *psfsrc,
102 int delta);
103static int ip6_mc_add_src(struct inet6_dev *idev, const struct in6_addr *pmca,
104 int sfmode, int sfcount, const struct in6_addr *psfsrc,
105 int delta);
106static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml,
107 struct inet6_dev *idev);
108
48#include <net/mld.h>
49
50#include <linux/netfilter.h>
51#include <linux/netfilter_ipv6.h>
52
53#include <net/net_namespace.h>
54#include <net/sock.h>
55#include <net/snmp.h>

--- 46 unchanged lines hidden (view full) ---

102 int sfmode, int sfcount, const struct in6_addr *psfsrc,
103 int delta);
104static int ip6_mc_add_src(struct inet6_dev *idev, const struct in6_addr *pmca,
105 int sfmode, int sfcount, const struct in6_addr *psfsrc,
106 int delta);
107static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml,
108 struct inet6_dev *idev);
109
109
110#define IGMP6_UNSOLICITED_IVAL (10*HZ)
111#define MLD_QRV_DEFAULT 2
110#define MLD_QRV_DEFAULT 2
111/* RFC3810, 9.2. Query Interval */
112#define MLD_QI_DEFAULT (125 * HZ)
113/* RFC3810, 9.3. Query Response Interval */
114#define MLD_QRI_DEFAULT (10 * HZ)
112
115
116/* RFC3810, 8.1 Query Version Distinctions */
117#define MLD_V1_QUERY_LEN 24
118#define MLD_V2_QUERY_LEN_MIN 28
119
113#define MLD_V1_SEEN(idev) (dev_net((idev)->dev)->ipv6.devconf_all->force_mld_version == 1 || \
114 (idev)->cnf.force_mld_version == 1 || \
115 ((idev)->mc_v1_seen && \
116 time_before(jiffies, (idev)->mc_v1_seen)))
117
118#define IPV6_MLD_MAX_MSF 64
119
120int sysctl_mld_max_msf __read_mostly = IPV6_MLD_MAX_MSF;
121
122/*
123 * socket join on multicast group
124 */
125
126#define for_each_pmc_rcu(np, pmc) \
127 for (pmc = rcu_dereference(np->ipv6_mc_list); \
128 pmc != NULL; \
129 pmc = rcu_dereference(pmc->next))
130
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
126
127int sysctl_mld_max_msf __read_mostly = IPV6_MLD_MAX_MSF;
128
129/*
130 * socket join on multicast group
131 */
132
133#define for_each_pmc_rcu(np, pmc) \
134 for (pmc = rcu_dereference(np->ipv6_mc_list); \
135 pmc != NULL; \
136 pmc = rcu_dereference(pmc->next))
137
138static int unsolicited_report_interval(struct inet6_dev *idev)
139{
140 int iv;
141
142 if (MLD_V1_SEEN(idev))
143 iv = idev->cnf.mldv1_unsolicited_report_interval;
144 else
145 iv = idev->cnf.mldv2_unsolicited_report_interval;
146
147 return iv > 0 ? iv : 1;
148}
149
131int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
132{
133 struct net_device *dev = NULL;
134 struct ipv6_mc_socklist *mc_lst;
135 struct ipv6_pinfo *np = inet6_sk(sk);
136 struct net *net = sock_net(sk);
137 int err;
138

--- 840 unchanged lines hidden (view full) ---

979 read_unlock_bh(&idev->lock);
980 }
981 rcu_read_unlock();
982 return rv;
983}
984
985static void mld_gq_start_timer(struct inet6_dev *idev)
986{
150int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
151{
152 struct net_device *dev = NULL;
153 struct ipv6_mc_socklist *mc_lst;
154 struct ipv6_pinfo *np = inet6_sk(sk);
155 struct net *net = sock_net(sk);
156 int err;
157

--- 840 unchanged lines hidden (view full) ---

998 read_unlock_bh(&idev->lock);
999 }
1000 rcu_read_unlock();
1001 return rv;
1002}
1003
1004static void mld_gq_start_timer(struct inet6_dev *idev)
1005{
987 int tv = net_random() % idev->mc_maxdelay;
1006 unsigned long tv = net_random() % idev->mc_maxdelay;
988
989 idev->mc_gq_running = 1;
990 if (!mod_timer(&idev->mc_gq_timer, jiffies+tv+2))
991 in6_dev_hold(idev);
992}
993
1007
1008 idev->mc_gq_running = 1;
1009 if (!mod_timer(&idev->mc_gq_timer, jiffies+tv+2))
1010 in6_dev_hold(idev);
1011}
1012
994static void mld_ifc_start_timer(struct inet6_dev *idev, int delay)
1013static void mld_ifc_start_timer(struct inet6_dev *idev, unsigned long delay)
995{
1014{
996 int tv = net_random() % delay;
1015 unsigned long tv = net_random() % delay;
997
998 if (!mod_timer(&idev->mc_ifc_timer, jiffies+tv+2))
999 in6_dev_hold(idev);
1000}
1001
1016
1017 if (!mod_timer(&idev->mc_ifc_timer, jiffies+tv+2))
1018 in6_dev_hold(idev);
1019}
1020
1002static void mld_dad_start_timer(struct inet6_dev *idev, int delay)
1021static void mld_dad_start_timer(struct inet6_dev *idev, unsigned long delay)
1003{
1022{
1004 int tv = net_random() % delay;
1023 unsigned long tv = net_random() % delay;
1005
1006 if (!mod_timer(&idev->mc_dad_timer, jiffies+tv+2))
1007 in6_dev_hold(idev);
1008}
1009
1010/*
1011 * IGMP handling (alias multicast ICMPv6 messages)
1012 */

--- 79 unchanged lines hidden (view full) ---

1092 if (!scount) {
1093 pmc->mca_flags &= ~MAF_GSQUERY;
1094 return false;
1095 }
1096 pmc->mca_flags |= MAF_GSQUERY;
1097 return true;
1098}
1099
1024
1025 if (!mod_timer(&idev->mc_dad_timer, jiffies+tv+2))
1026 in6_dev_hold(idev);
1027}
1028
1029/*
1030 * IGMP handling (alias multicast ICMPv6 messages)
1031 */

--- 79 unchanged lines hidden (view full) ---

1111 if (!scount) {
1112 pmc->mca_flags &= ~MAF_GSQUERY;
1113 return false;
1114 }
1115 pmc->mca_flags |= MAF_GSQUERY;
1116 return true;
1117}
1118
1119static void mld_set_v1_mode(struct inet6_dev *idev)
1120{
1121 /* RFC3810, relevant sections:
1122 * - 9.1. Robustness Variable
1123 * - 9.2. Query Interval
1124 * - 9.3. Query Response Interval
1125 * - 9.12. Older Version Querier Present Timeout
1126 */
1127 unsigned long switchback;
1128
1129 switchback = (idev->mc_qrv * idev->mc_qi) + idev->mc_qri;
1130
1131 idev->mc_v1_seen = jiffies + switchback;
1132}
1133
1134static void mld_update_qrv(struct inet6_dev *idev,
1135 const struct mld2_query *mlh2)
1136{
1137 /* RFC3810, relevant sections:
1138 * - 5.1.8. QRV (Querier's Robustness Variable)
1139 * - 9.1. Robustness Variable
1140 */
1141
1142 /* The value of the Robustness Variable MUST NOT be zero,
1143 * and SHOULD NOT be one. Catch this here if we ever run
1144 * into such a case in future.
1145 */
1146 WARN_ON(idev->mc_qrv == 0);
1147
1148 if (mlh2->mld2q_qrv > 0)
1149 idev->mc_qrv = mlh2->mld2q_qrv;
1150
1151 if (unlikely(idev->mc_qrv < 2)) {
1152 net_warn_ratelimited("IPv6: MLD: clamping QRV from %u to %u!\n",
1153 idev->mc_qrv, MLD_QRV_DEFAULT);
1154 idev->mc_qrv = MLD_QRV_DEFAULT;
1155 }
1156}
1157
1158static void mld_update_qi(struct inet6_dev *idev,
1159 const struct mld2_query *mlh2)
1160{
1161 /* RFC3810, relevant sections:
1162 * - 5.1.9. QQIC (Querier's Query Interval Code)
1163 * - 9.2. Query Interval
1164 * - 9.12. Older Version Querier Present Timeout
1165 * (the [Query Interval] in the last Query received)
1166 */
1167 unsigned long mc_qqi;
1168
1169 if (mlh2->mld2q_qqic < 128) {
1170 mc_qqi = mlh2->mld2q_qqic;
1171 } else {
1172 unsigned long mc_man, mc_exp;
1173
1174 mc_exp = MLDV2_QQIC_EXP(mlh2->mld2q_qqic);
1175 mc_man = MLDV2_QQIC_MAN(mlh2->mld2q_qqic);
1176
1177 mc_qqi = (mc_man | 0x10) << (mc_exp + 3);
1178 }
1179
1180 idev->mc_qi = mc_qqi * HZ;
1181}
1182
1183static void mld_update_qri(struct inet6_dev *idev,
1184 const struct mld2_query *mlh2)
1185{
1186 /* RFC3810, relevant sections:
1187 * - 5.1.3. Maximum Response Code
1188 * - 9.3. Query Response Interval
1189 */
1190 unsigned long mc_qri, mc_mrc = ntohs(mlh2->mld2q_mrc);
1191
1192 if (mc_mrc < 32768) {
1193 mc_qri = mc_mrc;
1194 } else {
1195 unsigned long mc_man, mc_exp;
1196
1197 mc_exp = MLDV2_MRC_EXP(mc_mrc);
1198 mc_man = MLDV2_MRC_MAN(mc_mrc);
1199
1200 mc_qri = (mc_man | 0x1000) << (mc_exp + 3);
1201 }
1202
1203 idev->mc_qri = msecs_to_jiffies(mc_qri);
1204}
1205
1100/* called with rcu_read_lock() */
1101int igmp6_event_query(struct sk_buff *skb)
1102{
1103 struct mld2_query *mlh2 = NULL;
1104 struct ifmcaddr6 *ma;
1105 const struct in6_addr *group;
1106 unsigned long max_delay;
1107 struct inet6_dev *idev;

--- 21 unchanged lines hidden (view full) ---

1129 mld = (struct mld_msg *)icmp6_hdr(skb);
1130 group = &mld->mld_mca;
1131 group_type = ipv6_addr_type(group);
1132
1133 if (group_type != IPV6_ADDR_ANY &&
1134 !(group_type&IPV6_ADDR_MULTICAST))
1135 return -EINVAL;
1136
1206/* called with rcu_read_lock() */
1207int igmp6_event_query(struct sk_buff *skb)
1208{
1209 struct mld2_query *mlh2 = NULL;
1210 struct ifmcaddr6 *ma;
1211 const struct in6_addr *group;
1212 unsigned long max_delay;
1213 struct inet6_dev *idev;

--- 21 unchanged lines hidden (view full) ---

1235 mld = (struct mld_msg *)icmp6_hdr(skb);
1236 group = &mld->mld_mca;
1237 group_type = ipv6_addr_type(group);
1238
1239 if (group_type != IPV6_ADDR_ANY &&
1240 !(group_type&IPV6_ADDR_MULTICAST))
1241 return -EINVAL;
1242
1137 if (len == 24) {
1138 int switchback;
1243 if (len == MLD_V1_QUERY_LEN) {
1139 /* MLDv1 router present */
1244 /* MLDv1 router present */
1245 max_delay = msecs_to_jiffies(ntohs(mld->mld_maxdelay));
1140
1246
1141 /* Translate milliseconds to jiffies */
1142 max_delay = (ntohs(mld->mld_maxdelay)*HZ)/1000;
1247 mld_set_v1_mode(idev);
1143
1248
1144 switchback = (idev->mc_qrv + 1) * max_delay;
1145 idev->mc_v1_seen = jiffies + switchback;
1249 /* cancel MLDv2 report timer */
1250 idev->mc_gq_running = 0;
1251 if (del_timer(&idev->mc_gq_timer))
1252 __in6_dev_put(idev);
1146
1147 /* cancel the interface change timer */
1148 idev->mc_ifc_count = 0;
1149 if (del_timer(&idev->mc_ifc_timer))
1150 __in6_dev_put(idev);
1151 /* clear deleted report items */
1152 mld_clear_delrec(idev);
1253
1254 /* cancel the interface change timer */
1255 idev->mc_ifc_count = 0;
1256 if (del_timer(&idev->mc_ifc_timer))
1257 __in6_dev_put(idev);
1258 /* clear deleted report items */
1259 mld_clear_delrec(idev);
1153 } else if (len >= 28) {
1260 } else if (len >= MLD_V2_QUERY_LEN_MIN) {
1154 int srcs_offset = sizeof(struct mld2_query) -
1155 sizeof(struct icmp6hdr);
1261 int srcs_offset = sizeof(struct mld2_query) -
1262 sizeof(struct icmp6hdr);
1263
1264 /* hosts need to stay in MLDv1 mode, discard MLDv2 queries */
1265 if (MLD_V1_SEEN(idev))
1266 return 0;
1156 if (!pskb_may_pull(skb, srcs_offset))
1157 return -EINVAL;
1158
1159 mlh2 = (struct mld2_query *)skb_transport_header(skb);
1267 if (!pskb_may_pull(skb, srcs_offset))
1268 return -EINVAL;
1269
1270 mlh2 = (struct mld2_query *)skb_transport_header(skb);
1160 max_delay = (MLDV2_MRC(ntohs(mlh2->mld2q_mrc))*HZ)/1000;
1161 if (!max_delay)
1162 max_delay = 1;
1271
1272 max_delay = max(msecs_to_jiffies(MLDV2_MRC(ntohs(mlh2->mld2q_mrc))), 1UL);
1273
1163 idev->mc_maxdelay = max_delay;
1274 idev->mc_maxdelay = max_delay;
1164 if (mlh2->mld2q_qrv)
1165 idev->mc_qrv = mlh2->mld2q_qrv;
1275
1276 mld_update_qrv(idev, mlh2);
1277 mld_update_qi(idev, mlh2);
1278 mld_update_qri(idev, mlh2);
1279
1166 if (group_type == IPV6_ADDR_ANY) { /* general query */
1167 if (mlh2->mld2q_nsrcs)
1168 return -EINVAL; /* no sources allowed */
1169
1170 mld_gq_start_timer(idev);
1171 return 0;
1172 }
1173 /* mark sources to include, if group & source-specific */

--- 197 unchanged lines hidden (view full) ---

1371 size += hlen + tlen;
1372 /* limit our allocations to order-0 page */
1373 size = min_t(int, size, SKB_MAX_ORDER(0, 0));
1374 skb = sock_alloc_send_skb(sk, size, 1, &err);
1375
1376 if (!skb)
1377 return NULL;
1378
1280 if (group_type == IPV6_ADDR_ANY) { /* general query */
1281 if (mlh2->mld2q_nsrcs)
1282 return -EINVAL; /* no sources allowed */
1283
1284 mld_gq_start_timer(idev);
1285 return 0;
1286 }
1287 /* mark sources to include, if group & source-specific */

--- 197 unchanged lines hidden (view full) ---

1485 size += hlen + tlen;
1486 /* limit our allocations to order-0 page */
1487 size = min_t(int, size, SKB_MAX_ORDER(0, 0));
1488 skb = sock_alloc_send_skb(sk, size, 1, &err);
1489
1490 if (!skb)
1491 return NULL;
1492
1493 skb->priority = TC_PRIO_CONTROL;
1379 skb_reserve(skb, hlen);
1380
1381 if (__ipv6_get_lladdr(idev, &addr_buf, IFA_F_TENTATIVE)) {
1382 /* <draft-ietf-magma-mld-source-05.txt>:
1383 * use unspecified address as the source address
1384 * when a valid link-local address is not available.
1385 */
1386 saddr = &in6addr_any;

--- 377 unchanged lines hidden (view full) ---

1764
1765 if (skb == NULL) {
1766 rcu_read_lock();
1767 IP6_INC_STATS(net, __in6_dev_get(dev),
1768 IPSTATS_MIB_OUTDISCARDS);
1769 rcu_read_unlock();
1770 return;
1771 }
1494 skb_reserve(skb, hlen);
1495
1496 if (__ipv6_get_lladdr(idev, &addr_buf, IFA_F_TENTATIVE)) {
1497 /* <draft-ietf-magma-mld-source-05.txt>:
1498 * use unspecified address as the source address
1499 * when a valid link-local address is not available.
1500 */
1501 saddr = &in6addr_any;

--- 377 unchanged lines hidden (view full) ---

1879
1880 if (skb == NULL) {
1881 rcu_read_lock();
1882 IP6_INC_STATS(net, __in6_dev_get(dev),
1883 IPSTATS_MIB_OUTDISCARDS);
1884 rcu_read_unlock();
1885 return;
1886 }
1772
1887 skb->priority = TC_PRIO_CONTROL;
1773 skb_reserve(skb, hlen);
1774
1775 if (ipv6_get_lladdr(dev, &addr_buf, IFA_F_TENTATIVE)) {
1776 /* <draft-ietf-magma-mld-source-05.txt>:
1777 * use unspecified address as the source address
1778 * when a valid link-local address is not available.
1779 */
1780 saddr = &in6addr_any;

--- 370 unchanged lines hidden (view full) ---

2151{
2152 unsigned long delay;
2153
2154 if (ma->mca_flags & MAF_NOREPORT)
2155 return;
2156
2157 igmp6_send(&ma->mca_addr, ma->idev->dev, ICMPV6_MGM_REPORT);
2158
1888 skb_reserve(skb, hlen);
1889
1890 if (ipv6_get_lladdr(dev, &addr_buf, IFA_F_TENTATIVE)) {
1891 /* <draft-ietf-magma-mld-source-05.txt>:
1892 * use unspecified address as the source address
1893 * when a valid link-local address is not available.
1894 */
1895 saddr = &in6addr_any;

--- 370 unchanged lines hidden (view full) ---

2266{
2267 unsigned long delay;
2268
2269 if (ma->mca_flags & MAF_NOREPORT)
2270 return;
2271
2272 igmp6_send(&ma->mca_addr, ma->idev->dev, ICMPV6_MGM_REPORT);
2273
2159 delay = net_random() % IGMP6_UNSOLICITED_IVAL;
2274 delay = net_random() % unsolicited_report_interval(ma->idev);
2160
2161 spin_lock_bh(&ma->mca_lock);
2162 if (del_timer(&ma->mca_timer)) {
2163 atomic_dec(&ma->mca_refcnt);
2164 delay = ma->mca_timer.expires - jiffies;
2165 }
2166
2167 if (!mod_timer(&ma->mca_timer, jiffies + delay))

--- 149 unchanged lines hidden (view full) ---

2317 setup_timer(&idev->mc_gq_timer, mld_gq_timer_expire,
2318 (unsigned long)idev);
2319 idev->mc_tomb = NULL;
2320 idev->mc_ifc_count = 0;
2321 setup_timer(&idev->mc_ifc_timer, mld_ifc_timer_expire,
2322 (unsigned long)idev);
2323 setup_timer(&idev->mc_dad_timer, mld_dad_timer_expire,
2324 (unsigned long)idev);
2275
2276 spin_lock_bh(&ma->mca_lock);
2277 if (del_timer(&ma->mca_timer)) {
2278 atomic_dec(&ma->mca_refcnt);
2279 delay = ma->mca_timer.expires - jiffies;
2280 }
2281
2282 if (!mod_timer(&ma->mca_timer, jiffies + delay))

--- 149 unchanged lines hidden (view full) ---

2432 setup_timer(&idev->mc_gq_timer, mld_gq_timer_expire,
2433 (unsigned long)idev);
2434 idev->mc_tomb = NULL;
2435 idev->mc_ifc_count = 0;
2436 setup_timer(&idev->mc_ifc_timer, mld_ifc_timer_expire,
2437 (unsigned long)idev);
2438 setup_timer(&idev->mc_dad_timer, mld_dad_timer_expire,
2439 (unsigned long)idev);
2440
2325 idev->mc_qrv = MLD_QRV_DEFAULT;
2441 idev->mc_qrv = MLD_QRV_DEFAULT;
2326 idev->mc_maxdelay = IGMP6_UNSOLICITED_IVAL;
2442 idev->mc_qi = MLD_QI_DEFAULT;
2443 idev->mc_qri = MLD_QRI_DEFAULT;
2444
2445 idev->mc_maxdelay = unsolicited_report_interval(idev);
2327 idev->mc_v1_seen = 0;
2328 write_unlock_bh(&idev->lock);
2329}
2330
2331/*
2332 * Device is about to be destroyed: clean up.
2333 */
2334

--- 397 unchanged lines hidden ---
2446 idev->mc_v1_seen = 0;
2447 write_unlock_bh(&idev->lock);
2448}
2449
2450/*
2451 * Device is about to be destroyed: clean up.
2452 */
2453

--- 397 unchanged lines hidden ---