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 --- |