Branch data Line data Source code
1 : : /*
2 : : * Linux NET3: Internet Group Management Protocol [IGMP]
3 : : *
4 : : * This code implements the IGMP protocol as defined in RFC1112. There has
5 : : * been a further revision of this protocol since which is now supported.
6 : : *
7 : : * If you have trouble with this module be careful what gcc you have used,
8 : : * the older version didn't come out right using gcc 2.5.8, the newer one
9 : : * seems to fall out with gcc 2.6.2.
10 : : *
11 : : * Authors:
12 : : * Alan Cox <alan@lxorguk.ukuu.org.uk>
13 : : *
14 : : * This program is free software; you can redistribute it and/or
15 : : * modify it under the terms of the GNU General Public License
16 : : * as published by the Free Software Foundation; either version
17 : : * 2 of the License, or (at your option) any later version.
18 : : *
19 : : * Fixes:
20 : : *
21 : : * Alan Cox : Added lots of __inline__ to optimise
22 : : * the memory usage of all the tiny little
23 : : * functions.
24 : : * Alan Cox : Dumped the header building experiment.
25 : : * Alan Cox : Minor tweaks ready for multicast routing
26 : : * and extended IGMP protocol.
27 : : * Alan Cox : Removed a load of inline directives. Gcc 2.5.8
28 : : * writes utterly bogus code otherwise (sigh)
29 : : * fixed IGMP loopback to behave in the manner
30 : : * desired by mrouted, fixed the fact it has been
31 : : * broken since 1.3.6 and cleaned up a few minor
32 : : * points.
33 : : *
34 : : * Chih-Jen Chang : Tried to revise IGMP to Version 2
35 : : * Tsu-Sheng Tsao E-mail: chihjenc@scf.usc.edu and tsusheng@scf.usc.edu
36 : : * The enhancements are mainly based on Steve Deering's
37 : : * ipmulti-3.5 source code.
38 : : * Chih-Jen Chang : Added the igmp_get_mrouter_info and
39 : : * Tsu-Sheng Tsao igmp_set_mrouter_info to keep track of
40 : : * the mrouted version on that device.
41 : : * Chih-Jen Chang : Added the max_resp_time parameter to
42 : : * Tsu-Sheng Tsao igmp_heard_query(). Using this parameter
43 : : * to identify the multicast router version
44 : : * and do what the IGMP version 2 specified.
45 : : * Chih-Jen Chang : Added a timer to revert to IGMP V2 router
46 : : * Tsu-Sheng Tsao if the specified time expired.
47 : : * Alan Cox : Stop IGMP from 0.0.0.0 being accepted.
48 : : * Alan Cox : Use GFP_ATOMIC in the right places.
49 : : * Christian Daudt : igmp timer wasn't set for local group
50 : : * memberships but was being deleted,
51 : : * which caused a "del_timer() called
52 : : * from %p with timer not initialized\n"
53 : : * message (960131).
54 : : * Christian Daudt : removed del_timer from
55 : : * igmp_timer_expire function (960205).
56 : : * Christian Daudt : igmp_heard_report now only calls
57 : : * igmp_timer_expire if tm->running is
58 : : * true (960216).
59 : : * Malcolm Beattie : ttl comparison wrong in igmp_rcv made
60 : : * igmp_heard_query never trigger. Expiry
61 : : * miscalculation fixed in igmp_heard_query
62 : : * and random() made to return unsigned to
63 : : * prevent negative expiry times.
64 : : * Alexey Kuznetsov: Wrong group leaving behaviour, backport
65 : : * fix from pending 2.1.x patches.
66 : : * Alan Cox: Forget to enable FDDI support earlier.
67 : : * Alexey Kuznetsov: Fixed leaving groups on device down.
68 : : * Alexey Kuznetsov: Accordance to igmp-v2-06 draft.
69 : : * David L Stevens: IGMPv3 support, with help from
70 : : * Vinay Kulkarni
71 : : */
72 : :
73 : : #include <linux/module.h>
74 : : #include <linux/slab.h>
75 : : #include <asm/uaccess.h>
76 : : #include <linux/types.h>
77 : : #include <linux/kernel.h>
78 : : #include <linux/jiffies.h>
79 : : #include <linux/string.h>
80 : : #include <linux/socket.h>
81 : : #include <linux/sockios.h>
82 : : #include <linux/in.h>
83 : : #include <linux/inet.h>
84 : : #include <linux/netdevice.h>
85 : : #include <linux/skbuff.h>
86 : : #include <linux/inetdevice.h>
87 : : #include <linux/igmp.h>
88 : : #include <linux/if_arp.h>
89 : : #include <linux/rtnetlink.h>
90 : : #include <linux/times.h>
91 : : #include <linux/pkt_sched.h>
92 : :
93 : : #include <net/net_namespace.h>
94 : : #include <net/arp.h>
95 : : #include <net/ip.h>
96 : : #include <net/protocol.h>
97 : : #include <net/route.h>
98 : : #include <net/sock.h>
99 : : #include <net/checksum.h>
100 : : #include <linux/netfilter_ipv4.h>
101 : : #ifdef CONFIG_IP_MROUTE
102 : : #include <linux/mroute.h>
103 : : #endif
104 : : #ifdef CONFIG_PROC_FS
105 : : #include <linux/proc_fs.h>
106 : : #include <linux/seq_file.h>
107 : : #endif
108 : :
109 : : #define IP_MAX_MEMBERSHIPS 20
110 : : #define IP_MAX_MSF 10
111 : :
112 : : #ifdef CONFIG_IP_MULTICAST
113 : : /* Parameter names and values are taken from igmp-v2-06 draft */
114 : :
115 : : #define IGMP_V1_Router_Present_Timeout (400*HZ)
116 : : #define IGMP_V2_Router_Present_Timeout (400*HZ)
117 : : #define IGMP_V2_Unsolicited_Report_Interval (10*HZ)
118 : : #define IGMP_V3_Unsolicited_Report_Interval (1*HZ)
119 : : #define IGMP_Query_Response_Interval (10*HZ)
120 : : #define IGMP_Unsolicited_Report_Count 2
121 : :
122 : :
123 : : #define IGMP_Initial_Report_Delay (1)
124 : :
125 : : /* IGMP_Initial_Report_Delay is not from IGMP specs!
126 : : * IGMP specs require to report membership immediately after
127 : : * joining a group, but we delay the first report by a
128 : : * small interval. It seems more natural and still does not
129 : : * contradict to specs provided this delay is small enough.
130 : : */
131 : :
132 : : #define IGMP_V1_SEEN(in_dev) \
133 : : (IPV4_DEVCONF_ALL(dev_net(in_dev->dev), FORCE_IGMP_VERSION) == 1 || \
134 : : IN_DEV_CONF_GET((in_dev), FORCE_IGMP_VERSION) == 1 || \
135 : : ((in_dev)->mr_v1_seen && \
136 : : time_before(jiffies, (in_dev)->mr_v1_seen)))
137 : : #define IGMP_V2_SEEN(in_dev) \
138 : : (IPV4_DEVCONF_ALL(dev_net(in_dev->dev), FORCE_IGMP_VERSION) == 2 || \
139 : : IN_DEV_CONF_GET((in_dev), FORCE_IGMP_VERSION) == 2 || \
140 : : ((in_dev)->mr_v2_seen && \
141 : : time_before(jiffies, (in_dev)->mr_v2_seen)))
142 : :
143 : 0 : static int unsolicited_report_interval(struct in_device *in_dev)
144 : : {
145 : : int interval_ms, interval_jiffies;
146 : :
147 [ # # ][ # # ]: 0 : if (IGMP_V1_SEEN(in_dev) || IGMP_V2_SEEN(in_dev))
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
148 : 0 : interval_ms = IN_DEV_CONF_GET(
149 : : in_dev,
150 : : IGMPV2_UNSOLICITED_REPORT_INTERVAL);
151 : : else /* v3 */
152 : : interval_ms = IN_DEV_CONF_GET(
153 : : in_dev,
154 : : IGMPV3_UNSOLICITED_REPORT_INTERVAL);
155 : :
156 : 0 : interval_jiffies = msecs_to_jiffies(interval_ms);
157 : :
158 : : /* _timer functions can't handle a delay of 0 jiffies so ensure
159 : : * we always return a positive value.
160 : : */
161 [ # # ]: 0 : if (interval_jiffies <= 0)
162 : : interval_jiffies = 1;
163 : 0 : return interval_jiffies;
164 : : }
165 : :
166 : : static void igmpv3_add_delrec(struct in_device *in_dev, struct ip_mc_list *im);
167 : : static void igmpv3_del_delrec(struct in_device *in_dev, __be32 multiaddr);
168 : : static void igmpv3_clear_delrec(struct in_device *in_dev);
169 : : static int sf_setstate(struct ip_mc_list *pmc);
170 : : static void sf_markstate(struct ip_mc_list *pmc);
171 : : #endif
172 : : static void ip_mc_clear_src(struct ip_mc_list *pmc);
173 : : static int ip_mc_add_src(struct in_device *in_dev, __be32 *pmca, int sfmode,
174 : : int sfcount, __be32 *psfsrc, int delta);
175 : :
176 : 0 : static void ip_ma_put(struct ip_mc_list *im)
177 : : {
178 [ # # ]: 0 : if (atomic_dec_and_test(&im->refcnt)) {
179 : 0 : in_dev_put(im->interface);
180 : 0 : kfree_rcu(im, rcu);
181 : : }
182 : 0 : }
183 : :
184 : : #define for_each_pmc_rcu(in_dev, pmc) \
185 : : for (pmc = rcu_dereference(in_dev->mc_list); \
186 : : pmc != NULL; \
187 : : pmc = rcu_dereference(pmc->next_rcu))
188 : :
189 : : #define for_each_pmc_rtnl(in_dev, pmc) \
190 : : for (pmc = rtnl_dereference(in_dev->mc_list); \
191 : : pmc != NULL; \
192 : : pmc = rtnl_dereference(pmc->next_rcu))
193 : :
194 : : #ifdef CONFIG_IP_MULTICAST
195 : :
196 : : /*
197 : : * Timer management
198 : : */
199 : :
200 : 0 : static void igmp_stop_timer(struct ip_mc_list *im)
201 : : {
202 : : spin_lock_bh(&im->lock);
203 [ # # ]: 0 : if (del_timer(&im->timer))
204 : 0 : atomic_dec(&im->refcnt);
205 : 0 : im->tm_running = 0;
206 : 0 : im->reporter = 0;
207 : 0 : im->unsolicit_count = 0;
208 : : spin_unlock_bh(&im->lock);
209 : 0 : }
210 : :
211 : : /* It must be called with locked im->lock */
212 : 0 : static void igmp_start_timer(struct ip_mc_list *im, int max_delay)
213 : : {
214 : 0 : int tv = prandom_u32() % max_delay;
215 : :
216 : 0 : im->tm_running = 1;
217 [ # # ]: 0 : if (!mod_timer(&im->timer, jiffies+tv+2))
218 : 0 : atomic_inc(&im->refcnt);
219 : 0 : }
220 : :
221 : 0 : static void igmp_gq_start_timer(struct in_device *in_dev)
222 : : {
223 : 0 : int tv = prandom_u32() % in_dev->mr_maxdelay;
224 : :
225 : 0 : in_dev->mr_gq_running = 1;
226 [ # # ]: 0 : if (!mod_timer(&in_dev->mr_gq_timer, jiffies+tv+2))
227 : 0 : in_dev_hold(in_dev);
228 : 0 : }
229 : :
230 : 0 : static void igmp_ifc_start_timer(struct in_device *in_dev, int delay)
231 : : {
232 : 0 : int tv = prandom_u32() % delay;
233 : :
234 [ # # ]: 0 : if (!mod_timer(&in_dev->mr_ifc_timer, jiffies+tv+2))
235 : 0 : in_dev_hold(in_dev);
236 : 0 : }
237 : :
238 : 0 : static void igmp_mod_timer(struct ip_mc_list *im, int max_delay)
239 : : {
240 : : spin_lock_bh(&im->lock);
241 : 0 : im->unsolicit_count = 0;
242 [ # # ]: 0 : if (del_timer(&im->timer)) {
243 [ # # ]: 0 : if ((long)(im->timer.expires-jiffies) < max_delay) {
244 : 0 : add_timer(&im->timer);
245 : 0 : im->tm_running = 1;
246 : : spin_unlock_bh(&im->lock);
247 : 0 : return;
248 : : }
249 : 0 : atomic_dec(&im->refcnt);
250 : : }
251 : 0 : igmp_start_timer(im, max_delay);
252 : : spin_unlock_bh(&im->lock);
253 : : }
254 : :
255 : :
256 : : /*
257 : : * Send an IGMP report.
258 : : */
259 : :
260 : : #define IGMP_SIZE (sizeof(struct igmphdr)+sizeof(struct iphdr)+4)
261 : :
262 : :
263 : 0 : static int is_in(struct ip_mc_list *pmc, struct ip_sf_list *psf, int type,
264 : : int gdeleted, int sdeleted)
265 : : {
266 [ # # # # : 0 : switch (type) {
# # ]
267 : : case IGMPV3_MODE_IS_INCLUDE:
268 : : case IGMPV3_MODE_IS_EXCLUDE:
269 [ # # ]: 0 : if (gdeleted || sdeleted)
270 : : return 0;
271 [ # # ][ # # ]: 0 : if (!(pmc->gsquery && !psf->sf_gsresp)) {
272 [ # # ]: 0 : if (pmc->sfmode == MCAST_INCLUDE)
273 : : return 1;
274 : : /* don't include if this source is excluded
275 : : * in all filters
276 : : */
277 [ # # ]: 0 : if (psf->sf_count[MCAST_INCLUDE])
278 : 0 : return type == IGMPV3_MODE_IS_INCLUDE;
279 : 0 : return pmc->sfcount[MCAST_EXCLUDE] ==
280 : 0 : psf->sf_count[MCAST_EXCLUDE];
281 : : }
282 : : return 0;
283 : : case IGMPV3_CHANGE_TO_INCLUDE:
284 [ # # ]: 0 : if (gdeleted || sdeleted)
285 : : return 0;
286 : 0 : return psf->sf_count[MCAST_INCLUDE] != 0;
287 : : case IGMPV3_CHANGE_TO_EXCLUDE:
288 [ # # ]: 0 : if (gdeleted || sdeleted)
289 : : return 0;
290 [ # # ][ # # ]: 0 : if (pmc->sfcount[MCAST_EXCLUDE] == 0 ||
291 : 0 : psf->sf_count[MCAST_INCLUDE])
292 : : return 0;
293 : 0 : return pmc->sfcount[MCAST_EXCLUDE] ==
294 : 0 : psf->sf_count[MCAST_EXCLUDE];
295 : : case IGMPV3_ALLOW_NEW_SOURCES:
296 [ # # ][ # # ]: 0 : if (gdeleted || !psf->sf_crcount)
297 : : return 0;
298 : 0 : return (pmc->sfmode == MCAST_INCLUDE) ^ sdeleted;
299 : : case IGMPV3_BLOCK_OLD_SOURCES:
300 [ # # ]: 0 : if (pmc->sfmode == MCAST_INCLUDE)
301 [ # # ][ # # ]: 0 : return gdeleted || (psf->sf_crcount && sdeleted);
[ # # ]
302 [ # # ][ # # ]: 0 : return psf->sf_crcount && !gdeleted && !sdeleted;
303 : : }
304 : : return 0;
305 : : }
306 : :
307 : : static int
308 : 0 : igmp_scount(struct ip_mc_list *pmc, int type, int gdeleted, int sdeleted)
309 : : {
310 : : struct ip_sf_list *psf;
311 : : int scount = 0;
312 : :
313 [ # # ]: 0 : for (psf = pmc->sources; psf; psf = psf->sf_next) {
314 [ # # ]: 0 : if (!is_in(pmc, psf, type, gdeleted, sdeleted))
315 : 0 : continue;
316 : 0 : scount++;
317 : : }
318 : 0 : return scount;
319 : : }
320 : :
321 : : #define igmp_skb_size(skb) (*(unsigned int *)((skb)->cb))
322 : :
323 : 0 : static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size)
324 : : {
325 : : struct sk_buff *skb;
326 : : struct rtable *rt;
327 : : struct iphdr *pip;
328 : : struct igmpv3_report *pig;
329 : : struct net *net = dev_net(dev);
330 : : struct flowi4 fl4;
331 : 0 : int hlen = LL_RESERVED_SPACE(dev);
332 : 0 : int tlen = dev->needed_tailroom;
333 : :
334 : : while (1) {
335 : 0 : skb = alloc_skb(size + hlen + tlen,
336 : : GFP_ATOMIC | __GFP_NOWARN);
337 [ # # ]: 0 : if (skb)
338 : : break;
339 : 0 : size >>= 1;
340 [ # # ]: 0 : if (size < 256)
341 : : return NULL;
342 : : }
343 : 0 : skb->priority = TC_PRIO_CONTROL;
344 : 0 : igmp_skb_size(skb) = size;
345 : :
346 : 0 : rt = ip_route_output_ports(net, &fl4, NULL, IGMPV3_ALL_MCR, 0,
347 : : 0, 0,
348 : : IPPROTO_IGMP, 0, dev->ifindex);
349 [ # # ]: 0 : if (IS_ERR(rt)) {
350 : 0 : kfree_skb(skb);
351 : 0 : return NULL;
352 : : }
353 : :
354 : 0 : skb_dst_set(skb, &rt->dst);
355 : 0 : skb->dev = dev;
356 : :
357 : : skb_reserve(skb, hlen);
358 : :
359 : : skb_reset_network_header(skb);
360 : : pip = ip_hdr(skb);
361 : 0 : skb_put(skb, sizeof(struct iphdr) + 4);
362 : :
363 : 0 : pip->version = 4;
364 : 0 : pip->ihl = (sizeof(struct iphdr)+4)>>2;
365 : 0 : pip->tos = 0xc0;
366 : 0 : pip->frag_off = htons(IP_DF);
367 : 0 : pip->ttl = 1;
368 : 0 : pip->daddr = fl4.daddr;
369 : 0 : pip->saddr = fl4.saddr;
370 : 0 : pip->protocol = IPPROTO_IGMP;
371 : 0 : pip->tot_len = 0; /* filled in later */
372 : : ip_select_ident(skb, &rt->dst, NULL);
373 : 0 : ((u8 *)&pip[1])[0] = IPOPT_RA;
374 : 0 : ((u8 *)&pip[1])[1] = 4;
375 : 0 : ((u8 *)&pip[1])[2] = 0;
376 : 0 : ((u8 *)&pip[1])[3] = 0;
377 : :
378 : 0 : skb->transport_header = skb->network_header + sizeof(struct iphdr) + 4;
379 : 0 : skb_put(skb, sizeof(*pig));
380 : : pig = igmpv3_report_hdr(skb);
381 : 0 : pig->type = IGMPV3_HOST_MEMBERSHIP_REPORT;
382 : 0 : pig->resv1 = 0;
383 : 0 : pig->csum = 0;
384 : 0 : pig->resv2 = 0;
385 : 0 : pig->ngrec = 0;
386 : 0 : return skb;
387 : : }
388 : :
389 : 0 : static int igmpv3_sendpack(struct sk_buff *skb)
390 : : {
391 : : struct igmphdr *pig = igmp_hdr(skb);
392 : 0 : const int igmplen = skb_tail_pointer(skb) - skb_transport_header(skb);
393 : :
394 : 0 : pig->csum = ip_compute_csum(igmp_hdr(skb), igmplen);
395 : :
396 : 0 : return ip_local_out(skb);
397 : : }
398 : :
399 : : static int grec_size(struct ip_mc_list *pmc, int type, int gdel, int sdel)
400 : : {
401 : 0 : return sizeof(struct igmpv3_grec) + 4*igmp_scount(pmc, type, gdel, sdel);
402 : : }
403 : :
404 : 0 : static struct sk_buff *add_grhead(struct sk_buff *skb, struct ip_mc_list *pmc,
405 : : int type, struct igmpv3_grec **ppgr)
406 : : {
407 : 0 : struct net_device *dev = pmc->interface->dev;
408 : : struct igmpv3_report *pih;
409 : : struct igmpv3_grec *pgr;
410 : :
411 [ # # ]: 0 : if (!skb)
412 : 0 : skb = igmpv3_newpack(dev, dev->mtu);
413 [ # # ]: 0 : if (!skb)
414 : : return NULL;
415 : 0 : pgr = (struct igmpv3_grec *)skb_put(skb, sizeof(struct igmpv3_grec));
416 : 0 : pgr->grec_type = type;
417 : 0 : pgr->grec_auxwords = 0;
418 : 0 : pgr->grec_nsrcs = 0;
419 : 0 : pgr->grec_mca = pmc->multiaddr;
420 : : pih = igmpv3_report_hdr(skb);
421 [ # # ][ # # ]: 0 : pih->ngrec = htons(ntohs(pih->ngrec)+1);
[ # # ][ # # ]
[ # # ]
422 : 0 : *ppgr = pgr;
423 : : return skb;
424 : : }
425 : :
426 : : #define AVAILABLE(skb) ((skb) ? ((skb)->dev ? igmp_skb_size(skb) - (skb)->len : \
427 : : skb_tailroom(skb)) : 0)
428 : :
429 : 0 : static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc,
430 : : int type, int gdeleted, int sdeleted)
431 : : {
432 : 0 : struct net_device *dev = pmc->interface->dev;
433 : : struct igmpv3_report *pih;
434 : 0 : struct igmpv3_grec *pgr = NULL;
435 : : struct ip_sf_list *psf, *psf_next, *psf_prev, **psf_list;
436 : : int scount, stotal, first, isquery, truncate;
437 : :
438 [ # # ]: 0 : if (pmc->multiaddr == IGMP_ALL_HOSTS)
439 : : return skb;
440 : :
441 : 0 : isquery = type == IGMPV3_MODE_IS_INCLUDE ||
442 : : type == IGMPV3_MODE_IS_EXCLUDE;
443 : 0 : truncate = type == IGMPV3_MODE_IS_EXCLUDE ||
444 : 0 : type == IGMPV3_CHANGE_TO_EXCLUDE;
445 : :
446 : : stotal = scount = 0;
447 : :
448 [ # # ]: 0 : psf_list = sdeleted ? &pmc->tomb : &pmc->sources;
449 : :
450 [ # # ]: 0 : if (!*psf_list)
451 : : goto empty_source;
452 : :
453 [ # # ]: 0 : pih = skb ? igmpv3_report_hdr(skb) : NULL;
454 : :
455 : : /* EX and TO_EX get a fresh packet, if needed */
456 [ # # ]: 0 : if (truncate) {
457 [ # # ]: 0 : if (pih && pih->ngrec &&
[ # # # # ]
458 [ # # ][ # # ]: 0 : AVAILABLE(skb) < grec_size(pmc, type, gdeleted, sdeleted)) {
459 [ # # ]: 0 : if (skb)
460 : 0 : igmpv3_sendpack(skb);
461 : 0 : skb = igmpv3_newpack(dev, dev->mtu);
462 : : }
463 : : }
464 : : first = 1;
465 : : psf_prev = NULL;
466 [ # # ]: 0 : for (psf = *psf_list; psf; psf = psf_next) {
467 : : __be32 *psrc;
468 : :
469 : 0 : psf_next = psf->sf_next;
470 : :
471 [ # # ]: 0 : if (!is_in(pmc, psf, type, gdeleted, sdeleted)) {
472 : : psf_prev = psf;
473 : 0 : continue;
474 : : }
475 : :
476 : : /* clear marks on query responses */
477 [ # # ]: 0 : if (isquery)
478 : 0 : psf->sf_gsresp = 0;
479 : :
480 [ # # ][ # # ]: 0 : if (AVAILABLE(skb) < sizeof(__be32) +
[ # # ]
481 : 0 : first*sizeof(struct igmpv3_grec)) {
482 [ # # ]: 0 : if (truncate && !first)
483 : : break; /* truncate these */
484 [ # # ]: 0 : if (pgr)
485 [ # # ]: 0 : pgr->grec_nsrcs = htons(scount);
486 [ # # ]: 0 : if (skb)
487 : 0 : igmpv3_sendpack(skb);
488 : 0 : skb = igmpv3_newpack(dev, dev->mtu);
489 : : first = 1;
490 : : scount = 0;
491 : : }
492 [ # # ]: 0 : if (first) {
493 : 0 : skb = add_grhead(skb, pmc, type, &pgr);
494 : : first = 0;
495 : : }
496 [ # # ]: 0 : if (!skb)
497 : : return NULL;
498 : 0 : psrc = (__be32 *)skb_put(skb, sizeof(__be32));
499 : 0 : *psrc = psf->sf_inaddr;
500 : 0 : scount++; stotal++;
501 [ # # ]: 0 : if ((type == IGMPV3_ALLOW_NEW_SOURCES ||
502 [ # # ]: 0 : type == IGMPV3_BLOCK_OLD_SOURCES) && psf->sf_crcount) {
503 : 0 : psf->sf_crcount--;
504 [ # # ][ # # ]: 0 : if ((sdeleted || gdeleted) && psf->sf_crcount == 0) {
505 [ # # ]: 0 : if (psf_prev)
506 : 0 : psf_prev->sf_next = psf->sf_next;
507 : : else
508 : 0 : *psf_list = psf->sf_next;
509 : 0 : kfree(psf);
510 : 0 : continue;
511 : : }
512 : : }
513 : : psf_prev = psf;
514 : : }
515 : :
516 : : empty_source:
517 [ # # ]: 0 : if (!stotal) {
518 [ # # ]: 0 : if (type == IGMPV3_ALLOW_NEW_SOURCES ||
519 : : type == IGMPV3_BLOCK_OLD_SOURCES)
520 : : return skb;
521 [ # # ][ # # ]: 0 : if (pmc->crcount || isquery) {
522 : : /* make sure we have room for group header */
523 [ # # ][ # # ]: 0 : if (skb && AVAILABLE(skb) < sizeof(struct igmpv3_grec)) {
[ # # ][ # # ]
524 : 0 : igmpv3_sendpack(skb);
525 : : skb = NULL; /* add_grhead will get a new one */
526 : : }
527 : 0 : skb = add_grhead(skb, pmc, type, &pgr);
528 : : }
529 : : }
530 [ # # ]: 0 : if (pgr)
531 [ # # ]: 0 : pgr->grec_nsrcs = htons(scount);
532 : :
533 [ # # ]: 0 : if (isquery)
534 : 0 : pmc->gsquery = 0; /* clear query state on report */
535 : 0 : return skb;
536 : : }
537 : :
538 : 0 : static int igmpv3_send_report(struct in_device *in_dev, struct ip_mc_list *pmc)
539 : : {
540 : : struct sk_buff *skb = NULL;
541 : : int type;
542 : :
543 [ # # ]: 0 : if (!pmc) {
544 : : rcu_read_lock();
545 [ # # ]: 0 : for_each_pmc_rcu(in_dev, pmc) {
546 [ # # ]: 0 : if (pmc->multiaddr == IGMP_ALL_HOSTS)
547 : 0 : continue;
548 : : spin_lock_bh(&pmc->lock);
549 [ # # ]: 0 : if (pmc->sfcount[MCAST_EXCLUDE])
550 : : type = IGMPV3_MODE_IS_EXCLUDE;
551 : : else
552 : : type = IGMPV3_MODE_IS_INCLUDE;
553 : 0 : skb = add_grec(skb, pmc, type, 0, 0);
554 : : spin_unlock_bh(&pmc->lock);
555 : : }
556 : : rcu_read_unlock();
557 : : } else {
558 : : spin_lock_bh(&pmc->lock);
559 [ # # ]: 0 : if (pmc->sfcount[MCAST_EXCLUDE])
560 : : type = IGMPV3_MODE_IS_EXCLUDE;
561 : : else
562 : : type = IGMPV3_MODE_IS_INCLUDE;
563 : 0 : skb = add_grec(skb, pmc, type, 0, 0);
564 : : spin_unlock_bh(&pmc->lock);
565 : : }
566 [ # # ]: 0 : if (!skb)
567 : : return 0;
568 : 0 : return igmpv3_sendpack(skb);
569 : : }
570 : :
571 : : /*
572 : : * remove zero-count source records from a source filter list
573 : : */
574 : 0 : static void igmpv3_clear_zeros(struct ip_sf_list **ppsf)
575 : : {
576 : : struct ip_sf_list *psf_prev, *psf_next, *psf;
577 : :
578 : : psf_prev = NULL;
579 [ # # ]: 0 : for (psf = *ppsf; psf; psf = psf_next) {
580 : 0 : psf_next = psf->sf_next;
581 [ # # ]: 0 : if (psf->sf_crcount == 0) {
582 [ # # ]: 0 : if (psf_prev)
583 : 0 : psf_prev->sf_next = psf->sf_next;
584 : : else
585 : 0 : *ppsf = psf->sf_next;
586 : 0 : kfree(psf);
587 : : } else
588 : : psf_prev = psf;
589 : : }
590 : 0 : }
591 : :
592 : 0 : static void igmpv3_send_cr(struct in_device *in_dev)
593 : : {
594 : : struct ip_mc_list *pmc, *pmc_prev, *pmc_next;
595 : : struct sk_buff *skb = NULL;
596 : : int type, dtype;
597 : :
598 : : rcu_read_lock();
599 : : spin_lock_bh(&in_dev->mc_tomb_lock);
600 : :
601 : : /* deleted MCA's */
602 : : pmc_prev = NULL;
603 [ # # ]: 0 : for (pmc = in_dev->mc_tomb; pmc; pmc = pmc_next) {
604 : 0 : pmc_next = pmc->next;
605 [ # # ]: 0 : if (pmc->sfmode == MCAST_INCLUDE) {
606 : : type = IGMPV3_BLOCK_OLD_SOURCES;
607 : : dtype = IGMPV3_BLOCK_OLD_SOURCES;
608 : 0 : skb = add_grec(skb, pmc, type, 1, 0);
609 : 0 : skb = add_grec(skb, pmc, dtype, 1, 1);
610 : : }
611 [ # # ]: 0 : if (pmc->crcount) {
612 [ # # ]: 0 : if (pmc->sfmode == MCAST_EXCLUDE) {
613 : : type = IGMPV3_CHANGE_TO_INCLUDE;
614 : 0 : skb = add_grec(skb, pmc, type, 1, 0);
615 : : }
616 : 0 : pmc->crcount--;
617 [ # # ]: 0 : if (pmc->crcount == 0) {
618 : 0 : igmpv3_clear_zeros(&pmc->tomb);
619 : 0 : igmpv3_clear_zeros(&pmc->sources);
620 : : }
621 : : }
622 [ # # ][ # # ]: 0 : if (pmc->crcount == 0 && !pmc->tomb && !pmc->sources) {
[ # # ]
623 [ # # ]: 0 : if (pmc_prev)
624 : 0 : pmc_prev->next = pmc_next;
625 : : else
626 : 0 : in_dev->mc_tomb = pmc_next;
627 : 0 : in_dev_put(pmc->interface);
628 : 0 : kfree(pmc);
629 : : } else
630 : : pmc_prev = pmc;
631 : : }
632 : : spin_unlock_bh(&in_dev->mc_tomb_lock);
633 : :
634 : : /* change recs */
635 [ # # ]: 0 : for_each_pmc_rcu(in_dev, pmc) {
636 : : spin_lock_bh(&pmc->lock);
637 [ # # ]: 0 : if (pmc->sfcount[MCAST_EXCLUDE]) {
638 : : type = IGMPV3_BLOCK_OLD_SOURCES;
639 : : dtype = IGMPV3_ALLOW_NEW_SOURCES;
640 : : } else {
641 : : type = IGMPV3_ALLOW_NEW_SOURCES;
642 : : dtype = IGMPV3_BLOCK_OLD_SOURCES;
643 : : }
644 : 0 : skb = add_grec(skb, pmc, type, 0, 0);
645 : 0 : skb = add_grec(skb, pmc, dtype, 0, 1); /* deleted sources */
646 : :
647 : : /* filter mode changes */
648 [ # # ]: 0 : if (pmc->crcount) {
649 [ # # ]: 0 : if (pmc->sfmode == MCAST_EXCLUDE)
650 : : type = IGMPV3_CHANGE_TO_EXCLUDE;
651 : : else
652 : : type = IGMPV3_CHANGE_TO_INCLUDE;
653 : 0 : skb = add_grec(skb, pmc, type, 0, 0);
654 : 0 : pmc->crcount--;
655 : : }
656 : : spin_unlock_bh(&pmc->lock);
657 : : }
658 : : rcu_read_unlock();
659 : :
660 [ # # ]: 0 : if (!skb)
661 : 0 : return;
662 : 0 : (void) igmpv3_sendpack(skb);
663 : : }
664 : :
665 : 0 : static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc,
666 : : int type)
667 : : {
668 : : struct sk_buff *skb;
669 : : struct iphdr *iph;
670 : : struct igmphdr *ih;
671 : : struct rtable *rt;
672 : 0 : struct net_device *dev = in_dev->dev;
673 : : struct net *net = dev_net(dev);
674 [ # # ]: 0 : __be32 group = pmc ? pmc->multiaddr : 0;
675 : : struct flowi4 fl4;
676 : : __be32 dst;
677 : : int hlen, tlen;
678 : :
679 [ # # ]: 0 : if (type == IGMPV3_HOST_MEMBERSHIP_REPORT)
680 : 0 : return igmpv3_send_report(in_dev, pmc);
681 [ # # ]: 0 : else if (type == IGMP_HOST_LEAVE_MESSAGE)
682 : : dst = IGMP_ALL_ROUTER;
683 : : else
684 : : dst = group;
685 : :
686 : 0 : rt = ip_route_output_ports(net, &fl4, NULL, dst, 0,
687 : : 0, 0,
688 : : IPPROTO_IGMP, 0, dev->ifindex);
689 [ # # ]: 0 : if (IS_ERR(rt))
690 : : return -1;
691 : :
692 : 0 : hlen = LL_RESERVED_SPACE(dev);
693 : 0 : tlen = dev->needed_tailroom;
694 : 0 : skb = alloc_skb(IGMP_SIZE + hlen + tlen, GFP_ATOMIC);
695 [ # # ]: 0 : if (skb == NULL) {
696 : : ip_rt_put(rt);
697 : 0 : return -1;
698 : : }
699 : 0 : skb->priority = TC_PRIO_CONTROL;
700 : :
701 : 0 : skb_dst_set(skb, &rt->dst);
702 : :
703 : : skb_reserve(skb, hlen);
704 : :
705 : : skb_reset_network_header(skb);
706 : : iph = ip_hdr(skb);
707 : 0 : skb_put(skb, sizeof(struct iphdr) + 4);
708 : :
709 : 0 : iph->version = 4;
710 : 0 : iph->ihl = (sizeof(struct iphdr)+4)>>2;
711 : 0 : iph->tos = 0xc0;
712 : 0 : iph->frag_off = htons(IP_DF);
713 : 0 : iph->ttl = 1;
714 : 0 : iph->daddr = dst;
715 : 0 : iph->saddr = fl4.saddr;
716 : 0 : iph->protocol = IPPROTO_IGMP;
717 : : ip_select_ident(skb, &rt->dst, NULL);
718 : 0 : ((u8 *)&iph[1])[0] = IPOPT_RA;
719 : 0 : ((u8 *)&iph[1])[1] = 4;
720 : 0 : ((u8 *)&iph[1])[2] = 0;
721 : 0 : ((u8 *)&iph[1])[3] = 0;
722 : :
723 : 0 : ih = (struct igmphdr *)skb_put(skb, sizeof(struct igmphdr));
724 : 0 : ih->type = type;
725 : 0 : ih->code = 0;
726 : 0 : ih->csum = 0;
727 : 0 : ih->group = group;
728 : 0 : ih->csum = ip_compute_csum((void *)ih, sizeof(struct igmphdr));
729 : :
730 : 0 : return ip_local_out(skb);
731 : : }
732 : :
733 : 0 : static void igmp_gq_timer_expire(unsigned long data)
734 : : {
735 : 0 : struct in_device *in_dev = (struct in_device *)data;
736 : :
737 : 0 : in_dev->mr_gq_running = 0;
738 : 0 : igmpv3_send_report(in_dev, NULL);
739 : : in_dev_put(in_dev);
740 : 0 : }
741 : :
742 : 0 : static void igmp_ifc_timer_expire(unsigned long data)
743 : : {
744 : 0 : struct in_device *in_dev = (struct in_device *)data;
745 : :
746 : 0 : igmpv3_send_cr(in_dev);
747 [ # # ]: 0 : if (in_dev->mr_ifc_count) {
748 : 0 : in_dev->mr_ifc_count--;
749 : 0 : igmp_ifc_start_timer(in_dev,
750 : : unsolicited_report_interval(in_dev));
751 : : }
752 : : in_dev_put(in_dev);
753 : 0 : }
754 : :
755 : 0 : static void igmp_ifc_event(struct in_device *in_dev)
756 : : {
757 [ # # ][ # # ]: 0 : if (IGMP_V1_SEEN(in_dev) || IGMP_V2_SEEN(in_dev))
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
758 : 0 : return;
759 [ # # ]: 0 : in_dev->mr_ifc_count = in_dev->mr_qrv ? in_dev->mr_qrv :
760 : : IGMP_Unsolicited_Report_Count;
761 : 0 : igmp_ifc_start_timer(in_dev, 1);
762 : : }
763 : :
764 : :
765 : 0 : static void igmp_timer_expire(unsigned long data)
766 : : {
767 : 0 : struct ip_mc_list *im = (struct ip_mc_list *)data;
768 : 0 : struct in_device *in_dev = im->interface;
769 : :
770 : : spin_lock(&im->lock);
771 : 0 : im->tm_running = 0;
772 : :
773 [ # # ]: 0 : if (im->unsolicit_count) {
774 : 0 : im->unsolicit_count--;
775 : 0 : igmp_start_timer(im, unsolicited_report_interval(in_dev));
776 : : }
777 : 0 : im->reporter = 1;
778 : : spin_unlock(&im->lock);
779 : :
780 [ # # ][ # # ]: 0 : if (IGMP_V1_SEEN(in_dev))
[ # # ][ # # ]
781 : 0 : igmp_send_report(in_dev, im, IGMP_HOST_MEMBERSHIP_REPORT);
782 [ # # ][ # # ]: 0 : else if (IGMP_V2_SEEN(in_dev))
[ # # ][ # # ]
783 : 0 : igmp_send_report(in_dev, im, IGMPV2_HOST_MEMBERSHIP_REPORT);
784 : : else
785 : 0 : igmp_send_report(in_dev, im, IGMPV3_HOST_MEMBERSHIP_REPORT);
786 : :
787 : 0 : ip_ma_put(im);
788 : 0 : }
789 : :
790 : : /* mark EXCLUDE-mode sources */
791 : 0 : static int igmp_xmarksources(struct ip_mc_list *pmc, int nsrcs, __be32 *srcs)
792 : : {
793 : : struct ip_sf_list *psf;
794 : : int i, scount;
795 : :
796 : : scount = 0;
797 [ # # ]: 0 : for (psf = pmc->sources; psf; psf = psf->sf_next) {
798 [ # # ]: 0 : if (scount == nsrcs)
799 : : break;
800 [ # # ]: 0 : for (i = 0; i < nsrcs; i++) {
801 : : /* skip inactive filters */
802 [ # # ][ # # ]: 0 : if (psf->sf_count[MCAST_INCLUDE] ||
803 : 0 : pmc->sfcount[MCAST_EXCLUDE] !=
804 : 0 : psf->sf_count[MCAST_EXCLUDE])
805 : : break;
806 [ # # ]: 0 : if (srcs[i] == psf->sf_inaddr) {
807 : 0 : scount++;
808 : 0 : break;
809 : : }
810 : : }
811 : : }
812 : 0 : pmc->gsquery = 0;
813 [ # # ]: 0 : if (scount == nsrcs) /* all sources excluded */
814 : : return 0;
815 : 0 : return 1;
816 : : }
817 : :
818 : 0 : static int igmp_marksources(struct ip_mc_list *pmc, int nsrcs, __be32 *srcs)
819 : : {
820 : : struct ip_sf_list *psf;
821 : : int i, scount;
822 : :
823 [ # # ]: 0 : if (pmc->sfmode == MCAST_EXCLUDE)
824 : 0 : return igmp_xmarksources(pmc, nsrcs, srcs);
825 : :
826 : : /* mark INCLUDE-mode sources */
827 : : scount = 0;
828 [ # # ]: 0 : for (psf = pmc->sources; psf; psf = psf->sf_next) {
829 [ # # ]: 0 : if (scount == nsrcs)
830 : : break;
831 [ # # ]: 0 : for (i = 0; i < nsrcs; i++)
832 [ # # ]: 0 : if (srcs[i] == psf->sf_inaddr) {
833 : 0 : psf->sf_gsresp = 1;
834 : 0 : scount++;
835 : 0 : break;
836 : : }
837 : : }
838 [ # # ]: 0 : if (!scount) {
839 : 0 : pmc->gsquery = 0;
840 : 0 : return 0;
841 : : }
842 : 0 : pmc->gsquery = 1;
843 : 0 : return 1;
844 : : }
845 : :
846 : : /* return true if packet was dropped */
847 : 0 : static bool igmp_heard_report(struct in_device *in_dev, __be32 group)
848 : : {
849 : : struct ip_mc_list *im;
850 : :
851 : : /* Timers are only set for non-local groups */
852 : :
853 [ # # ]: 0 : if (group == IGMP_ALL_HOSTS)
854 : : return false;
855 : :
856 : : rcu_read_lock();
857 [ # # ]: 0 : for_each_pmc_rcu(in_dev, im) {
858 [ # # ]: 0 : if (im->multiaddr == group) {
859 : 0 : igmp_stop_timer(im);
860 : : break;
861 : : }
862 : : }
863 : : rcu_read_unlock();
864 : : return false;
865 : : }
866 : :
867 : : /* return true if packet was dropped */
868 : 0 : static bool igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb,
869 : : int len)
870 : : {
871 : : struct igmphdr *ih = igmp_hdr(skb);
872 : : struct igmpv3_query *ih3 = igmpv3_query_hdr(skb);
873 : : struct ip_mc_list *im;
874 : 0 : __be32 group = ih->group;
875 : : int max_delay;
876 : : int mark = 0;
877 : :
878 : :
879 [ # # ]: 0 : if (len == 8) {
880 [ # # ]: 0 : if (ih->code == 0) {
881 : : /* Alas, old v1 router presents here. */
882 : :
883 : : max_delay = IGMP_Query_Response_Interval;
884 : 0 : in_dev->mr_v1_seen = jiffies +
885 : : IGMP_V1_Router_Present_Timeout;
886 : : group = 0;
887 : : } else {
888 : : /* v2 router present */
889 : 0 : max_delay = ih->code*(HZ/IGMP_TIMER_SCALE);
890 : 0 : in_dev->mr_v2_seen = jiffies +
891 : : IGMP_V2_Router_Present_Timeout;
892 : : }
893 : : /* cancel the interface change timer */
894 : 0 : in_dev->mr_ifc_count = 0;
895 [ # # ]: 0 : if (del_timer(&in_dev->mr_ifc_timer))
896 : 0 : __in_dev_put(in_dev);
897 : : /* clear deleted report items */
898 : 0 : igmpv3_clear_delrec(in_dev);
899 [ # # ]: 0 : } else if (len < 12) {
900 : : return true; /* ignore bogus packet; freed by caller */
901 [ # # ][ # # ]: 0 : } else if (IGMP_V1_SEEN(in_dev)) {
[ # # ][ # # ]
902 : : /* This is a v3 query with v1 queriers present */
903 : : max_delay = IGMP_Query_Response_Interval;
904 : : group = 0;
905 [ # # ][ # # ]: 0 : } else if (IGMP_V2_SEEN(in_dev)) {
[ # # ][ # # ]
906 : : /* this is a v3 query with v2 queriers present;
907 : : * Interpretation of the max_delay code is problematic here.
908 : : * A real v2 host would use ih_code directly, while v3 has a
909 : : * different encoding. We use the v3 encoding as more likely
910 : : * to be intended in a v3 query.
911 : : */
912 [ # # ]: 0 : max_delay = IGMPV3_MRC(ih3->code)*(HZ/IGMP_TIMER_SCALE);
913 [ # # ]: 0 : if (!max_delay)
914 : : max_delay = 1; /* can't mod w/ 0 */
915 : : } else { /* v3 */
916 [ # # ]: 0 : if (!pskb_may_pull(skb, sizeof(struct igmpv3_query)))
917 : : return true;
918 : :
919 : : ih3 = igmpv3_query_hdr(skb);
920 [ # # ]: 0 : if (ih3->nsrcs) {
921 [ # # ][ # # ]: 0 : if (!pskb_may_pull(skb, sizeof(struct igmpv3_query)
922 : 0 : + ntohs(ih3->nsrcs)*sizeof(__be32)))
923 : : return true;
924 : : ih3 = igmpv3_query_hdr(skb);
925 : : }
926 : :
927 [ # # ]: 0 : max_delay = IGMPV3_MRC(ih3->code)*(HZ/IGMP_TIMER_SCALE);
928 [ # # ]: 0 : if (!max_delay)
929 : : max_delay = 1; /* can't mod w/ 0 */
930 : 0 : in_dev->mr_maxdelay = max_delay;
931 [ # # ]: 0 : if (ih3->qrv)
932 : 0 : in_dev->mr_qrv = ih3->qrv;
933 [ # # ]: 0 : if (!group) { /* general query */
934 [ # # ]: 0 : if (ih3->nsrcs)
935 : : return false; /* no sources allowed */
936 : 0 : igmp_gq_start_timer(in_dev);
937 : 0 : return false;
938 : : }
939 : : /* mark sources to include, if group & source-specific */
940 : 0 : mark = ih3->nsrcs != 0;
941 : : }
942 : :
943 : : /*
944 : : * - Start the timers in all of our membership records
945 : : * that the query applies to for the interface on
946 : : * which the query arrived excl. those that belong
947 : : * to a "local" group (224.0.0.X)
948 : : * - For timers already running check if they need to
949 : : * be reset.
950 : : * - Use the igmp->igmp_code field as the maximum
951 : : * delay possible
952 : : */
953 : : rcu_read_lock();
954 [ # # ]: 0 : for_each_pmc_rcu(in_dev, im) {
955 : : int changed;
956 : :
957 [ # # ][ # # ]: 0 : if (group && group != im->multiaddr)
958 : 0 : continue;
959 [ # # ]: 0 : if (im->multiaddr == IGMP_ALL_HOSTS)
960 : 0 : continue;
961 : : spin_lock_bh(&im->lock);
962 [ # # ]: 0 : if (im->tm_running)
963 [ # # ][ # # ]: 0 : im->gsquery = im->gsquery && mark;
964 : : else
965 : 0 : im->gsquery = mark;
966 [ # # # # ]: 0 : changed = !im->gsquery ||
967 [ # # ]: 0 : igmp_marksources(im, ntohs(ih3->nsrcs), ih3->srcs);
968 : : spin_unlock_bh(&im->lock);
969 [ # # ]: 0 : if (changed)
970 : 0 : igmp_mod_timer(im, max_delay);
971 : : }
972 : : rcu_read_unlock();
973 : 0 : return false;
974 : : }
975 : :
976 : : /* called in rcu_read_lock() section */
977 : 0 : int igmp_rcv(struct sk_buff *skb)
978 : : {
979 : : /* This basically follows the spec line by line -- see RFC1112 */
980 : : struct igmphdr *ih;
981 : 0 : struct in_device *in_dev = __in_dev_get_rcu(skb->dev);
982 : 0 : int len = skb->len;
983 : : bool dropped = true;
984 : :
985 [ # # ]: 0 : if (in_dev == NULL)
986 : : goto drop;
987 : :
988 [ # # ]: 0 : if (!pskb_may_pull(skb, sizeof(struct igmphdr)))
989 : : goto drop;
990 : :
991 [ # # # ]: 0 : switch (skb->ip_summed) {
992 : : case CHECKSUM_COMPLETE:
993 [ # # ]: 0 : if (!csum_fold(skb->csum))
994 : : break;
995 : : /* fall through */
996 : : case CHECKSUM_NONE:
997 : 0 : skb->csum = 0;
998 [ # # ]: 0 : if (__skb_checksum_complete(skb))
999 : : goto drop;
1000 : : }
1001 : :
1002 : : ih = igmp_hdr(skb);
1003 [ # # # ]: 0 : switch (ih->type) {
1004 : : case IGMP_HOST_MEMBERSHIP_QUERY:
1005 : 0 : dropped = igmp_heard_query(in_dev, skb, len);
1006 : 0 : break;
1007 : : case IGMP_HOST_MEMBERSHIP_REPORT:
1008 : : case IGMPV2_HOST_MEMBERSHIP_REPORT:
1009 : : /* Is it our report looped back? */
1010 [ # # ]: 0 : if (rt_is_output_route(skb_rtable(skb)))
1011 : : break;
1012 : : /* don't rely on MC router hearing unicast reports */
1013 [ # # ]: 0 : if (skb->pkt_type == PACKET_MULTICAST ||
1014 : : skb->pkt_type == PACKET_BROADCAST)
1015 : 0 : dropped = igmp_heard_report(in_dev, ih->group);
1016 : : break;
1017 : : case IGMP_PIM:
1018 : : #ifdef CONFIG_IP_PIMSM_V1
1019 : : return pim_rcv_v1(skb);
1020 : : #endif
1021 : : case IGMPV3_HOST_MEMBERSHIP_REPORT:
1022 : : case IGMP_DVMRP:
1023 : : case IGMP_TRACE:
1024 : : case IGMP_HOST_LEAVE_MESSAGE:
1025 : : case IGMP_MTRACE:
1026 : : case IGMP_MTRACE_RESP:
1027 : : break;
1028 : : default:
1029 : : break;
1030 : : }
1031 : :
1032 : : drop:
1033 [ # # ]: 0 : if (dropped)
1034 : 0 : kfree_skb(skb);
1035 : : else
1036 : 0 : consume_skb(skb);
1037 : 0 : return 0;
1038 : : }
1039 : :
1040 : : #endif
1041 : :
1042 : :
1043 : : /*
1044 : : * Add a filter to a device
1045 : : */
1046 : :
1047 : 0 : static void ip_mc_filter_add(struct in_device *in_dev, __be32 addr)
1048 : : {
1049 : : char buf[MAX_ADDR_LEN];
1050 : 0 : struct net_device *dev = in_dev->dev;
1051 : :
1052 : : /* Checking for IFF_MULTICAST here is WRONG-WRONG-WRONG.
1053 : : We will get multicast token leakage, when IFF_MULTICAST
1054 : : is changed. This check should be done in ndo_set_rx_mode
1055 : : routine. Something sort of:
1056 : : if (dev->mc_list && dev->flags&IFF_MULTICAST) { do it; }
1057 : : --ANK
1058 : : */
1059 [ # # ]: 0 : if (arp_mc_map(addr, buf, dev, 0) == 0)
1060 : 0 : dev_mc_add(dev, buf);
1061 : 0 : }
1062 : :
1063 : : /*
1064 : : * Remove a filter from a device
1065 : : */
1066 : :
1067 : 0 : static void ip_mc_filter_del(struct in_device *in_dev, __be32 addr)
1068 : : {
1069 : : char buf[MAX_ADDR_LEN];
1070 : 0 : struct net_device *dev = in_dev->dev;
1071 : :
1072 [ # # ]: 0 : if (arp_mc_map(addr, buf, dev, 0) == 0)
1073 : 0 : dev_mc_del(dev, buf);
1074 : 0 : }
1075 : :
1076 : : #ifdef CONFIG_IP_MULTICAST
1077 : : /*
1078 : : * deleted ip_mc_list manipulation
1079 : : */
1080 : 0 : static void igmpv3_add_delrec(struct in_device *in_dev, struct ip_mc_list *im)
1081 : : {
1082 : : struct ip_mc_list *pmc;
1083 : :
1084 : : /* this is an "ip_mc_list" for convenience; only the fields below
1085 : : * are actually used. In particular, the refcnt and users are not
1086 : : * used for management of the delete list. Using the same structure
1087 : : * for deleted items allows change reports to use common code with
1088 : : * non-deleted or query-response MCA's.
1089 : : */
1090 : : pmc = kzalloc(sizeof(*pmc), GFP_KERNEL);
1091 [ # # ]: 0 : if (!pmc)
1092 : 0 : return;
1093 : : spin_lock_bh(&im->lock);
1094 : 0 : pmc->interface = im->interface;
1095 : 0 : in_dev_hold(in_dev);
1096 : 0 : pmc->multiaddr = im->multiaddr;
1097 [ # # ]: 0 : pmc->crcount = in_dev->mr_qrv ? in_dev->mr_qrv :
1098 : : IGMP_Unsolicited_Report_Count;
1099 : 0 : pmc->sfmode = im->sfmode;
1100 [ # # ]: 0 : if (pmc->sfmode == MCAST_INCLUDE) {
1101 : : struct ip_sf_list *psf;
1102 : :
1103 : 0 : pmc->tomb = im->tomb;
1104 : 0 : pmc->sources = im->sources;
1105 : 0 : im->tomb = im->sources = NULL;
1106 [ # # ]: 0 : for (psf = pmc->sources; psf; psf = psf->sf_next)
1107 : 0 : psf->sf_crcount = pmc->crcount;
1108 : : }
1109 : : spin_unlock_bh(&im->lock);
1110 : :
1111 : : spin_lock_bh(&in_dev->mc_tomb_lock);
1112 : 0 : pmc->next = in_dev->mc_tomb;
1113 : 0 : in_dev->mc_tomb = pmc;
1114 : : spin_unlock_bh(&in_dev->mc_tomb_lock);
1115 : : }
1116 : :
1117 : 0 : static void igmpv3_del_delrec(struct in_device *in_dev, __be32 multiaddr)
1118 : : {
1119 : : struct ip_mc_list *pmc, *pmc_prev;
1120 : : struct ip_sf_list *psf, *psf_next;
1121 : :
1122 : : spin_lock_bh(&in_dev->mc_tomb_lock);
1123 : : pmc_prev = NULL;
1124 [ # # ]: 0 : for (pmc = in_dev->mc_tomb; pmc; pmc = pmc->next) {
1125 [ # # ]: 0 : if (pmc->multiaddr == multiaddr)
1126 : : break;
1127 : : pmc_prev = pmc;
1128 : : }
1129 [ # # ]: 0 : if (pmc) {
1130 [ # # ]: 0 : if (pmc_prev)
1131 : 0 : pmc_prev->next = pmc->next;
1132 : : else
1133 : 0 : in_dev->mc_tomb = pmc->next;
1134 : : }
1135 : : spin_unlock_bh(&in_dev->mc_tomb_lock);
1136 [ # # ]: 0 : if (pmc) {
1137 [ # # ]: 0 : for (psf = pmc->tomb; psf; psf = psf_next) {
1138 : 0 : psf_next = psf->sf_next;
1139 : 0 : kfree(psf);
1140 : : }
1141 : 0 : in_dev_put(pmc->interface);
1142 : 0 : kfree(pmc);
1143 : : }
1144 : 0 : }
1145 : :
1146 : 0 : static void igmpv3_clear_delrec(struct in_device *in_dev)
1147 : : {
1148 : : struct ip_mc_list *pmc, *nextpmc;
1149 : :
1150 : : spin_lock_bh(&in_dev->mc_tomb_lock);
1151 : 0 : pmc = in_dev->mc_tomb;
1152 : 0 : in_dev->mc_tomb = NULL;
1153 : : spin_unlock_bh(&in_dev->mc_tomb_lock);
1154 : :
1155 [ # # ]: 0 : for (; pmc; pmc = nextpmc) {
1156 : 0 : nextpmc = pmc->next;
1157 : 0 : ip_mc_clear_src(pmc);
1158 : 0 : in_dev_put(pmc->interface);
1159 : 0 : kfree(pmc);
1160 : : }
1161 : : /* clear dead sources, too */
1162 : : rcu_read_lock();
1163 [ # # ]: 0 : for_each_pmc_rcu(in_dev, pmc) {
1164 : : struct ip_sf_list *psf, *psf_next;
1165 : :
1166 : : spin_lock_bh(&pmc->lock);
1167 : 0 : psf = pmc->tomb;
1168 : 0 : pmc->tomb = NULL;
1169 : : spin_unlock_bh(&pmc->lock);
1170 [ # # ]: 0 : for (; psf; psf = psf_next) {
1171 : 0 : psf_next = psf->sf_next;
1172 : 0 : kfree(psf);
1173 : : }
1174 : : }
1175 : : rcu_read_unlock();
1176 : 0 : }
1177 : : #endif
1178 : :
1179 : 0 : static void igmp_group_dropped(struct ip_mc_list *im)
1180 : : {
1181 : 0 : struct in_device *in_dev = im->interface;
1182 : : #ifdef CONFIG_IP_MULTICAST
1183 : : int reporter;
1184 : : #endif
1185 : :
1186 [ # # ]: 0 : if (im->loaded) {
1187 : 0 : im->loaded = 0;
1188 : 0 : ip_mc_filter_del(in_dev, im->multiaddr);
1189 : : }
1190 : :
1191 : : #ifdef CONFIG_IP_MULTICAST
1192 [ # # ]: 0 : if (im->multiaddr == IGMP_ALL_HOSTS)
1193 : : return;
1194 : :
1195 : 0 : reporter = im->reporter;
1196 : 0 : igmp_stop_timer(im);
1197 : :
1198 [ # # ]: 0 : if (!in_dev->dead) {
1199 [ # # ][ # # ]: 0 : if (IGMP_V1_SEEN(in_dev))
[ # # ][ # # ]
1200 : : return;
1201 [ # # ][ # # ]: 0 : if (IGMP_V2_SEEN(in_dev)) {
[ # # ][ # # ]
1202 [ # # ]: 0 : if (reporter)
1203 : 0 : igmp_send_report(in_dev, im, IGMP_HOST_LEAVE_MESSAGE);
1204 : : return;
1205 : : }
1206 : : /* IGMPv3 */
1207 : 0 : igmpv3_add_delrec(in_dev, im);
1208 : :
1209 : 0 : igmp_ifc_event(in_dev);
1210 : : }
1211 : : #endif
1212 : : }
1213 : :
1214 : 0 : static void igmp_group_added(struct ip_mc_list *im)
1215 : : {
1216 : 0 : struct in_device *in_dev = im->interface;
1217 : :
1218 [ # # ]: 0 : if (im->loaded == 0) {
1219 : 0 : im->loaded = 1;
1220 : 0 : ip_mc_filter_add(in_dev, im->multiaddr);
1221 : : }
1222 : :
1223 : : #ifdef CONFIG_IP_MULTICAST
1224 [ # # ]: 0 : if (im->multiaddr == IGMP_ALL_HOSTS)
1225 : : return;
1226 : :
1227 [ # # ]: 0 : if (in_dev->dead)
1228 : : return;
1229 [ # # ][ # # ]: 0 : if (IGMP_V1_SEEN(in_dev) || IGMP_V2_SEEN(in_dev)) {
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1230 : : spin_lock_bh(&im->lock);
1231 : 0 : igmp_start_timer(im, IGMP_Initial_Report_Delay);
1232 : : spin_unlock_bh(&im->lock);
1233 : : return;
1234 : : }
1235 : : /* else, v3 */
1236 : :
1237 [ # # ]: 0 : im->crcount = in_dev->mr_qrv ? in_dev->mr_qrv :
1238 : : IGMP_Unsolicited_Report_Count;
1239 : 0 : igmp_ifc_event(in_dev);
1240 : : #endif
1241 : : }
1242 : :
1243 : :
1244 : : /*
1245 : : * Multicast list managers
1246 : : */
1247 : :
1248 : : static u32 ip_mc_hash(const struct ip_mc_list *im)
1249 : : {
1250 : : return hash_32((__force u32)im->multiaddr, MC_HASH_SZ_LOG);
1251 : : }
1252 : :
1253 : 0 : static void ip_mc_hash_add(struct in_device *in_dev,
1254 : 0 : struct ip_mc_list *im)
1255 : : {
1256 : : struct ip_mc_list __rcu **mc_hash;
1257 : : u32 hash;
1258 : :
1259 : 0 : mc_hash = rtnl_dereference(in_dev->mc_hash);
1260 [ # # ]: 0 : if (mc_hash) {
1261 : : hash = ip_mc_hash(im);
1262 : 0 : im->next_hash = mc_hash[hash];
1263 : 0 : rcu_assign_pointer(mc_hash[hash], im);
1264 : 0 : return;
1265 : : }
1266 : :
1267 : : /* do not use a hash table for small number of items */
1268 [ # # ]: 0 : if (in_dev->mc_count < 4)
1269 : : return;
1270 : :
1271 : : mc_hash = kzalloc(sizeof(struct ip_mc_list *) << MC_HASH_SZ_LOG,
1272 : : GFP_KERNEL);
1273 [ # # ]: 0 : if (!mc_hash)
1274 : : return;
1275 : :
1276 [ # # ]: 0 : for_each_pmc_rtnl(in_dev, im) {
1277 : : hash = ip_mc_hash(im);
1278 : 0 : im->next_hash = mc_hash[hash];
1279 : 0 : RCU_INIT_POINTER(mc_hash[hash], im);
1280 : : }
1281 : :
1282 : 0 : rcu_assign_pointer(in_dev->mc_hash, mc_hash);
1283 : : }
1284 : :
1285 : : static void ip_mc_hash_remove(struct in_device *in_dev,
1286 : : struct ip_mc_list *im)
1287 : : {
1288 : : struct ip_mc_list __rcu **mc_hash = rtnl_dereference(in_dev->mc_hash);
1289 : : struct ip_mc_list *aux;
1290 : :
1291 [ # # ]: 0 : if (!mc_hash)
1292 : : return;
1293 : 0 : mc_hash += ip_mc_hash(im);
1294 [ # # ]: 0 : while ((aux = rtnl_dereference(*mc_hash)) != im)
1295 : 0 : mc_hash = &aux->next_hash;
1296 : 0 : *mc_hash = im->next_hash;
1297 : : }
1298 : :
1299 : :
1300 : : /*
1301 : : * A socket has joined a multicast group on device dev.
1302 : : */
1303 : :
1304 : 0 : void ip_mc_inc_group(struct in_device *in_dev, __be32 addr)
1305 : : {
1306 : : struct ip_mc_list *im;
1307 : :
1308 [ # # ]: 0 : ASSERT_RTNL();
1309 : :
1310 [ # # ]: 0 : for_each_pmc_rtnl(in_dev, im) {
1311 [ # # ]: 0 : if (im->multiaddr == addr) {
1312 : 0 : im->users++;
1313 : 0 : ip_mc_add_src(in_dev, &addr, MCAST_EXCLUDE, 0, NULL, 0);
1314 : 0 : goto out;
1315 : : }
1316 : : }
1317 : :
1318 : : im = kzalloc(sizeof(*im), GFP_KERNEL);
1319 [ # # ]: 0 : if (!im)
1320 : : goto out;
1321 : :
1322 : 0 : im->users = 1;
1323 : 0 : im->interface = in_dev;
1324 : 0 : in_dev_hold(in_dev);
1325 : 0 : im->multiaddr = addr;
1326 : : /* initial mode is (EX, empty) */
1327 : 0 : im->sfmode = MCAST_EXCLUDE;
1328 : 0 : im->sfcount[MCAST_EXCLUDE] = 1;
1329 : 0 : atomic_set(&im->refcnt, 1);
1330 : 0 : spin_lock_init(&im->lock);
1331 : : #ifdef CONFIG_IP_MULTICAST
1332 : 0 : setup_timer(&im->timer, &igmp_timer_expire, (unsigned long)im);
1333 : 0 : im->unsolicit_count = IGMP_Unsolicited_Report_Count;
1334 : : #endif
1335 : :
1336 : 0 : im->next_rcu = in_dev->mc_list;
1337 : 0 : in_dev->mc_count++;
1338 : 0 : rcu_assign_pointer(in_dev->mc_list, im);
1339 : :
1340 : 0 : ip_mc_hash_add(in_dev, im);
1341 : :
1342 : : #ifdef CONFIG_IP_MULTICAST
1343 : 0 : igmpv3_del_delrec(in_dev, im->multiaddr);
1344 : : #endif
1345 : 0 : igmp_group_added(im);
1346 [ # # ]: 0 : if (!in_dev->dead)
1347 : 0 : ip_rt_multicast_event(in_dev);
1348 : : out:
1349 : 0 : return;
1350 : : }
1351 : : EXPORT_SYMBOL(ip_mc_inc_group);
1352 : :
1353 : : /*
1354 : : * Resend IGMP JOIN report; used by netdev notifier.
1355 : : */
1356 : 0 : static void ip_mc_rejoin_groups(struct in_device *in_dev)
1357 : : {
1358 : : #ifdef CONFIG_IP_MULTICAST
1359 : : struct ip_mc_list *im;
1360 : : int type;
1361 : :
1362 [ # # ]: 0 : ASSERT_RTNL();
1363 : :
1364 [ # # ]: 0 : for_each_pmc_rtnl(in_dev, im) {
1365 [ # # ]: 0 : if (im->multiaddr == IGMP_ALL_HOSTS)
1366 : 0 : continue;
1367 : :
1368 : : /* a failover is happening and switches
1369 : : * must be notified immediately
1370 : : */
1371 [ # # ][ # # ]: 0 : if (IGMP_V1_SEEN(in_dev))
[ # # ][ # # ]
1372 : : type = IGMP_HOST_MEMBERSHIP_REPORT;
1373 [ # # ][ # # ]: 0 : else if (IGMP_V2_SEEN(in_dev))
[ # # ][ # # ]
1374 : : type = IGMPV2_HOST_MEMBERSHIP_REPORT;
1375 : : else
1376 : : type = IGMPV3_HOST_MEMBERSHIP_REPORT;
1377 : 0 : igmp_send_report(in_dev, im, type);
1378 : : }
1379 : : #endif
1380 : 0 : }
1381 : :
1382 : : /*
1383 : : * A socket has left a multicast group on device dev
1384 : : */
1385 : :
1386 : 0 : void ip_mc_dec_group(struct in_device *in_dev, __be32 addr)
1387 : : {
1388 : : struct ip_mc_list *i;
1389 : : struct ip_mc_list __rcu **ip;
1390 : :
1391 [ # # ]: 0 : ASSERT_RTNL();
1392 : :
1393 [ # # ]: 0 : for (ip = &in_dev->mc_list;
1394 : 0 : (i = rtnl_dereference(*ip)) != NULL;
1395 : 0 : ip = &i->next_rcu) {
1396 [ # # ]: 0 : if (i->multiaddr == addr) {
1397 [ # # ]: 0 : if (--i->users == 0) {
1398 : : ip_mc_hash_remove(in_dev, i);
1399 : 0 : *ip = i->next_rcu;
1400 : 0 : in_dev->mc_count--;
1401 : 0 : igmp_group_dropped(i);
1402 : 0 : ip_mc_clear_src(i);
1403 : :
1404 [ # # ]: 0 : if (!in_dev->dead)
1405 : 0 : ip_rt_multicast_event(in_dev);
1406 : :
1407 : 0 : ip_ma_put(i);
1408 : 0 : return;
1409 : : }
1410 : : break;
1411 : : }
1412 : : }
1413 : : }
1414 : : EXPORT_SYMBOL(ip_mc_dec_group);
1415 : :
1416 : : /* Device changing type */
1417 : :
1418 : 0 : void ip_mc_unmap(struct in_device *in_dev)
1419 : : {
1420 : : struct ip_mc_list *pmc;
1421 : :
1422 [ # # ]: 0 : ASSERT_RTNL();
1423 : :
1424 [ # # ]: 0 : for_each_pmc_rtnl(in_dev, pmc)
1425 : 0 : igmp_group_dropped(pmc);
1426 : 0 : }
1427 : :
1428 : 0 : void ip_mc_remap(struct in_device *in_dev)
1429 : : {
1430 : : struct ip_mc_list *pmc;
1431 : :
1432 [ # # ]: 0 : ASSERT_RTNL();
1433 : :
1434 [ # # ]: 0 : for_each_pmc_rtnl(in_dev, pmc)
1435 : 0 : igmp_group_added(pmc);
1436 : 0 : }
1437 : :
1438 : : /* Device going down */
1439 : :
1440 : 0 : void ip_mc_down(struct in_device *in_dev)
1441 : : {
1442 : : struct ip_mc_list *pmc;
1443 : :
1444 [ # # ]: 0 : ASSERT_RTNL();
1445 : :
1446 [ # # ]: 0 : for_each_pmc_rtnl(in_dev, pmc)
1447 : 0 : igmp_group_dropped(pmc);
1448 : :
1449 : : #ifdef CONFIG_IP_MULTICAST
1450 : 0 : in_dev->mr_ifc_count = 0;
1451 [ # # ]: 0 : if (del_timer(&in_dev->mr_ifc_timer))
1452 : 0 : __in_dev_put(in_dev);
1453 : 0 : in_dev->mr_gq_running = 0;
1454 [ # # ]: 0 : if (del_timer(&in_dev->mr_gq_timer))
1455 : 0 : __in_dev_put(in_dev);
1456 : 0 : igmpv3_clear_delrec(in_dev);
1457 : : #endif
1458 : :
1459 : 0 : ip_mc_dec_group(in_dev, IGMP_ALL_HOSTS);
1460 : 0 : }
1461 : :
1462 : 0 : void ip_mc_init_dev(struct in_device *in_dev)
1463 : : {
1464 [ # # ]: 0 : ASSERT_RTNL();
1465 : :
1466 : : #ifdef CONFIG_IP_MULTICAST
1467 : 0 : setup_timer(&in_dev->mr_gq_timer, igmp_gq_timer_expire,
1468 : : (unsigned long)in_dev);
1469 : 0 : setup_timer(&in_dev->mr_ifc_timer, igmp_ifc_timer_expire,
1470 : : (unsigned long)in_dev);
1471 : 0 : in_dev->mr_qrv = IGMP_Unsolicited_Report_Count;
1472 : : #endif
1473 : :
1474 : 0 : spin_lock_init(&in_dev->mc_tomb_lock);
1475 : 0 : }
1476 : :
1477 : : /* Device going up */
1478 : :
1479 : 0 : void ip_mc_up(struct in_device *in_dev)
1480 : : {
1481 : : struct ip_mc_list *pmc;
1482 : :
1483 [ # # ]: 0 : ASSERT_RTNL();
1484 : :
1485 : 0 : ip_mc_inc_group(in_dev, IGMP_ALL_HOSTS);
1486 : :
1487 [ # # ]: 0 : for_each_pmc_rtnl(in_dev, pmc)
1488 : 0 : igmp_group_added(pmc);
1489 : 0 : }
1490 : :
1491 : : /*
1492 : : * Device is about to be destroyed: clean up.
1493 : : */
1494 : :
1495 : 0 : void ip_mc_destroy_dev(struct in_device *in_dev)
1496 : : {
1497 : : struct ip_mc_list *i;
1498 : :
1499 [ # # ]: 0 : ASSERT_RTNL();
1500 : :
1501 : : /* Deactivate timers */
1502 : 0 : ip_mc_down(in_dev);
1503 : :
1504 [ # # ]: 0 : while ((i = rtnl_dereference(in_dev->mc_list)) != NULL) {
1505 : 0 : in_dev->mc_list = i->next_rcu;
1506 : 0 : in_dev->mc_count--;
1507 : :
1508 : : /* We've dropped the groups in ip_mc_down already */
1509 : 0 : ip_mc_clear_src(i);
1510 : 0 : ip_ma_put(i);
1511 : : }
1512 : 0 : }
1513 : :
1514 : : /* RTNL is locked */
1515 : 0 : static struct in_device *ip_mc_find_dev(struct net *net, struct ip_mreqn *imr)
1516 : : {
1517 : 0 : struct net_device *dev = NULL;
1518 : : struct in_device *idev = NULL;
1519 : :
1520 [ # # ]: 0 : if (imr->imr_ifindex) {
1521 : 0 : idev = inetdev_by_index(net, imr->imr_ifindex);
1522 : 0 : return idev;
1523 : : }
1524 [ # # ]: 0 : if (imr->imr_address.s_addr) {
1525 : 0 : dev = __ip_dev_find(net, imr->imr_address.s_addr, false);
1526 [ # # ]: 0 : if (!dev)
1527 : : return NULL;
1528 : : }
1529 : :
1530 [ # # ]: 0 : if (!dev) {
1531 : 0 : struct rtable *rt = ip_route_output(net,
1532 : : imr->imr_multiaddr.s_addr,
1533 : : 0, 0, 0);
1534 [ # # ]: 0 : if (!IS_ERR(rt)) {
1535 : 0 : dev = rt->dst.dev;
1536 : : ip_rt_put(rt);
1537 : : }
1538 : : }
1539 [ # # ]: 0 : if (dev) {
1540 : 0 : imr->imr_ifindex = dev->ifindex;
1541 : : idev = __in_dev_get_rtnl(dev);
1542 : : }
1543 : 0 : return idev;
1544 : : }
1545 : :
1546 : : /*
1547 : : * Join a socket to a group
1548 : : */
1549 : : int sysctl_igmp_max_memberships __read_mostly = IP_MAX_MEMBERSHIPS;
1550 : : int sysctl_igmp_max_msf __read_mostly = IP_MAX_MSF;
1551 : :
1552 : :
1553 : 0 : static int ip_mc_del1_src(struct ip_mc_list *pmc, int sfmode,
1554 : : __be32 *psfsrc)
1555 : : {
1556 : : struct ip_sf_list *psf, *psf_prev;
1557 : : int rv = 0;
1558 : :
1559 : : psf_prev = NULL;
1560 [ # # ]: 0 : for (psf = pmc->sources; psf; psf = psf->sf_next) {
1561 [ # # ]: 0 : if (psf->sf_inaddr == *psfsrc)
1562 : : break;
1563 : : psf_prev = psf;
1564 : : }
1565 [ # # ][ # # ]: 0 : if (!psf || psf->sf_count[sfmode] == 0) {
1566 : : /* source filter not found, or count wrong => bug */
1567 : : return -ESRCH;
1568 : : }
1569 : 0 : psf->sf_count[sfmode]--;
1570 [ # # ]: 0 : if (psf->sf_count[sfmode] == 0) {
1571 : 0 : ip_rt_multicast_event(pmc->interface);
1572 : : }
1573 [ # # ][ # # ]: 0 : if (!psf->sf_count[MCAST_INCLUDE] && !psf->sf_count[MCAST_EXCLUDE]) {
1574 : : #ifdef CONFIG_IP_MULTICAST
1575 : 0 : struct in_device *in_dev = pmc->interface;
1576 : : #endif
1577 : :
1578 : : /* no more filters for this source */
1579 [ # # ]: 0 : if (psf_prev)
1580 : 0 : psf_prev->sf_next = psf->sf_next;
1581 : : else
1582 : 0 : pmc->sources = psf->sf_next;
1583 : : #ifdef CONFIG_IP_MULTICAST
1584 [ # # ][ # # ]: 0 : if (psf->sf_oldin &&
1585 [ # # ][ # # ]: 0 : !IGMP_V1_SEEN(in_dev) && !IGMP_V2_SEEN(in_dev)) {
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1586 [ # # ]: 0 : psf->sf_crcount = in_dev->mr_qrv ? in_dev->mr_qrv :
1587 : : IGMP_Unsolicited_Report_Count;
1588 : 0 : psf->sf_next = pmc->tomb;
1589 : 0 : pmc->tomb = psf;
1590 : 0 : rv = 1;
1591 : : } else
1592 : : #endif
1593 : 0 : kfree(psf);
1594 : : }
1595 : 0 : return rv;
1596 : : }
1597 : :
1598 : : #ifndef CONFIG_IP_MULTICAST
1599 : : #define igmp_ifc_event(x) do { } while (0)
1600 : : #endif
1601 : :
1602 : 0 : static int ip_mc_del_src(struct in_device *in_dev, __be32 *pmca, int sfmode,
1603 : : int sfcount, __be32 *psfsrc, int delta)
1604 : : {
1605 : 0 : struct ip_mc_list *pmc;
1606 : : int changerec = 0;
1607 : : int i, err;
1608 : :
1609 [ # # ]: 0 : if (!in_dev)
1610 : : return -ENODEV;
1611 : : rcu_read_lock();
1612 [ # # ]: 0 : for_each_pmc_rcu(in_dev, pmc) {
1613 [ # # ]: 0 : if (*pmca == pmc->multiaddr)
1614 : : break;
1615 : : }
1616 [ # # ]: 0 : if (!pmc) {
1617 : : /* MCA not found?? bug */
1618 : : rcu_read_unlock();
1619 : 0 : return -ESRCH;
1620 : : }
1621 : : spin_lock_bh(&pmc->lock);
1622 : : rcu_read_unlock();
1623 : : #ifdef CONFIG_IP_MULTICAST
1624 : 0 : sf_markstate(pmc);
1625 : : #endif
1626 [ # # ]: 0 : if (!delta) {
1627 : : err = -EINVAL;
1628 [ # # ]: 0 : if (!pmc->sfcount[sfmode])
1629 : : goto out_unlock;
1630 : 0 : pmc->sfcount[sfmode]--;
1631 : : }
1632 : : err = 0;
1633 [ # # ]: 0 : for (i = 0; i < sfcount; i++) {
1634 : 0 : int rv = ip_mc_del1_src(pmc, sfmode, &psfsrc[i]);
1635 : :
1636 : 0 : changerec |= rv > 0;
1637 [ # # ]: 0 : if (!err && rv < 0)
1638 : : err = rv;
1639 : : }
1640 [ # # ][ # # ]: 0 : if (pmc->sfmode == MCAST_EXCLUDE &&
1641 [ # # ]: 0 : pmc->sfcount[MCAST_EXCLUDE] == 0 &&
1642 : 0 : pmc->sfcount[MCAST_INCLUDE]) {
1643 : : #ifdef CONFIG_IP_MULTICAST
1644 : : struct ip_sf_list *psf;
1645 : : #endif
1646 : :
1647 : : /* filter mode change */
1648 : 0 : pmc->sfmode = MCAST_INCLUDE;
1649 : : #ifdef CONFIG_IP_MULTICAST
1650 [ # # ]: 0 : pmc->crcount = in_dev->mr_qrv ? in_dev->mr_qrv :
1651 : : IGMP_Unsolicited_Report_Count;
1652 : 0 : in_dev->mr_ifc_count = pmc->crcount;
1653 [ # # ]: 0 : for (psf = pmc->sources; psf; psf = psf->sf_next)
1654 : 0 : psf->sf_crcount = 0;
1655 : 0 : igmp_ifc_event(pmc->interface);
1656 [ # # ][ # # ]: 0 : } else if (sf_setstate(pmc) || changerec) {
1657 : 0 : igmp_ifc_event(pmc->interface);
1658 : : #endif
1659 : : }
1660 : : out_unlock:
1661 : : spin_unlock_bh(&pmc->lock);
1662 : 0 : return err;
1663 : : }
1664 : :
1665 : : /*
1666 : : * Add multicast single-source filter to the interface list
1667 : : */
1668 : 0 : static int ip_mc_add1_src(struct ip_mc_list *pmc, int sfmode,
1669 : : __be32 *psfsrc)
1670 : : {
1671 : : struct ip_sf_list *psf, *psf_prev;
1672 : :
1673 : : psf_prev = NULL;
1674 [ # # ]: 0 : for (psf = pmc->sources; psf; psf = psf->sf_next) {
1675 [ # # ]: 0 : if (psf->sf_inaddr == *psfsrc)
1676 : : break;
1677 : : psf_prev = psf;
1678 : : }
1679 [ # # ]: 0 : if (!psf) {
1680 : : psf = kzalloc(sizeof(*psf), GFP_ATOMIC);
1681 [ # # ]: 0 : if (!psf)
1682 : : return -ENOBUFS;
1683 : 0 : psf->sf_inaddr = *psfsrc;
1684 [ # # ]: 0 : if (psf_prev) {
1685 : 0 : psf_prev->sf_next = psf;
1686 : : } else
1687 : 0 : pmc->sources = psf;
1688 : : }
1689 : 0 : psf->sf_count[sfmode]++;
1690 [ # # ]: 0 : if (psf->sf_count[sfmode] == 1) {
1691 : 0 : ip_rt_multicast_event(pmc->interface);
1692 : : }
1693 : : return 0;
1694 : : }
1695 : :
1696 : : #ifdef CONFIG_IP_MULTICAST
1697 : 0 : static void sf_markstate(struct ip_mc_list *pmc)
1698 : : {
1699 : : struct ip_sf_list *psf;
1700 : 0 : int mca_xcount = pmc->sfcount[MCAST_EXCLUDE];
1701 : :
1702 [ # # ]: 0 : for (psf = pmc->sources; psf; psf = psf->sf_next)
1703 [ # # ]: 0 : if (pmc->sfcount[MCAST_EXCLUDE]) {
1704 : 0 : psf->sf_oldin = mca_xcount ==
1705 [ # # ][ # # ]: 0 : psf->sf_count[MCAST_EXCLUDE] &&
1706 : 0 : !psf->sf_count[MCAST_INCLUDE];
1707 : : } else
1708 : 0 : psf->sf_oldin = psf->sf_count[MCAST_INCLUDE] != 0;
1709 : 0 : }
1710 : :
1711 : 0 : static int sf_setstate(struct ip_mc_list *pmc)
1712 : : {
1713 : : struct ip_sf_list *psf, *dpsf;
1714 : 0 : int mca_xcount = pmc->sfcount[MCAST_EXCLUDE];
1715 : 0 : int qrv = pmc->interface->mr_qrv;
1716 : : int new_in, rv;
1717 : :
1718 : : rv = 0;
1719 [ # # ]: 0 : for (psf = pmc->sources; psf; psf = psf->sf_next) {
1720 [ # # ]: 0 : if (pmc->sfcount[MCAST_EXCLUDE]) {
1721 [ # # ][ # # ]: 0 : new_in = mca_xcount == psf->sf_count[MCAST_EXCLUDE] &&
1722 : 0 : !psf->sf_count[MCAST_INCLUDE];
1723 : : } else
1724 : 0 : new_in = psf->sf_count[MCAST_INCLUDE] != 0;
1725 [ # # ]: 0 : if (new_in) {
1726 [ # # ]: 0 : if (!psf->sf_oldin) {
1727 : : struct ip_sf_list *prev = NULL;
1728 : :
1729 [ # # ]: 0 : for (dpsf = pmc->tomb; dpsf; dpsf = dpsf->sf_next) {
1730 [ # # ]: 0 : if (dpsf->sf_inaddr == psf->sf_inaddr)
1731 : : break;
1732 : : prev = dpsf;
1733 : : }
1734 [ # # ]: 0 : if (dpsf) {
1735 [ # # ]: 0 : if (prev)
1736 : 0 : prev->sf_next = dpsf->sf_next;
1737 : : else
1738 : 0 : pmc->tomb = dpsf->sf_next;
1739 : 0 : kfree(dpsf);
1740 : : }
1741 : 0 : psf->sf_crcount = qrv;
1742 : 0 : rv++;
1743 : : }
1744 [ # # ]: 0 : } else if (psf->sf_oldin) {
1745 : :
1746 : 0 : psf->sf_crcount = 0;
1747 : : /*
1748 : : * add or update "delete" records if an active filter
1749 : : * is now inactive
1750 : : */
1751 [ # # ]: 0 : for (dpsf = pmc->tomb; dpsf; dpsf = dpsf->sf_next)
1752 [ # # ]: 0 : if (dpsf->sf_inaddr == psf->sf_inaddr)
1753 : : break;
1754 [ # # ]: 0 : if (!dpsf) {
1755 : : dpsf = kmalloc(sizeof(*dpsf), GFP_ATOMIC);
1756 [ # # ]: 0 : if (!dpsf)
1757 : 0 : continue;
1758 : 0 : *dpsf = *psf;
1759 : : /* pmc->lock held by callers */
1760 : 0 : dpsf->sf_next = pmc->tomb;
1761 : 0 : pmc->tomb = dpsf;
1762 : : }
1763 : 0 : dpsf->sf_crcount = qrv;
1764 : 0 : rv++;
1765 : : }
1766 : : }
1767 : 0 : return rv;
1768 : : }
1769 : : #endif
1770 : :
1771 : : /*
1772 : : * Add multicast source filter list to the interface list
1773 : : */
1774 : 0 : static int ip_mc_add_src(struct in_device *in_dev, __be32 *pmca, int sfmode,
1775 : : int sfcount, __be32 *psfsrc, int delta)
1776 : : {
1777 : 0 : struct ip_mc_list *pmc;
1778 : : int isexclude;
1779 : : int i, err;
1780 : :
1781 [ # # ]: 0 : if (!in_dev)
1782 : : return -ENODEV;
1783 : : rcu_read_lock();
1784 [ # # ]: 0 : for_each_pmc_rcu(in_dev, pmc) {
1785 [ # # ]: 0 : if (*pmca == pmc->multiaddr)
1786 : : break;
1787 : : }
1788 [ # # ]: 0 : if (!pmc) {
1789 : : /* MCA not found?? bug */
1790 : : rcu_read_unlock();
1791 : 0 : return -ESRCH;
1792 : : }
1793 : : spin_lock_bh(&pmc->lock);
1794 : : rcu_read_unlock();
1795 : :
1796 : : #ifdef CONFIG_IP_MULTICAST
1797 : 0 : sf_markstate(pmc);
1798 : : #endif
1799 : 0 : isexclude = pmc->sfmode == MCAST_EXCLUDE;
1800 [ # # ]: 0 : if (!delta)
1801 : 0 : pmc->sfcount[sfmode]++;
1802 : : err = 0;
1803 [ # # ]: 0 : for (i = 0; i < sfcount; i++) {
1804 : 0 : err = ip_mc_add1_src(pmc, sfmode, &psfsrc[i]);
1805 [ # # ]: 0 : if (err)
1806 : : break;
1807 : : }
1808 [ # # ]: 0 : if (err) {
1809 : : int j;
1810 : :
1811 [ # # ]: 0 : if (!delta)
1812 : 0 : pmc->sfcount[sfmode]--;
1813 [ # # ]: 0 : for (j = 0; j < i; j++)
1814 : 0 : (void) ip_mc_del1_src(pmc, sfmode, &psfsrc[j]);
1815 [ # # ]: 0 : } else if (isexclude != (pmc->sfcount[MCAST_EXCLUDE] != 0)) {
1816 : : #ifdef CONFIG_IP_MULTICAST
1817 : : struct ip_sf_list *psf;
1818 : 0 : in_dev = pmc->interface;
1819 : : #endif
1820 : :
1821 : : /* filter mode change */
1822 [ # # ]: 0 : if (pmc->sfcount[MCAST_EXCLUDE])
1823 : 0 : pmc->sfmode = MCAST_EXCLUDE;
1824 [ # # ]: 0 : else if (pmc->sfcount[MCAST_INCLUDE])
1825 : 0 : pmc->sfmode = MCAST_INCLUDE;
1826 : : #ifdef CONFIG_IP_MULTICAST
1827 : : /* else no filters; keep old mode for reports */
1828 : :
1829 [ # # ]: 0 : pmc->crcount = in_dev->mr_qrv ? in_dev->mr_qrv :
1830 : : IGMP_Unsolicited_Report_Count;
1831 : 0 : in_dev->mr_ifc_count = pmc->crcount;
1832 [ # # ]: 0 : for (psf = pmc->sources; psf; psf = psf->sf_next)
1833 : 0 : psf->sf_crcount = 0;
1834 : 0 : igmp_ifc_event(in_dev);
1835 [ # # ]: 0 : } else if (sf_setstate(pmc)) {
1836 : 0 : igmp_ifc_event(in_dev);
1837 : : #endif
1838 : : }
1839 : : spin_unlock_bh(&pmc->lock);
1840 : 0 : return err;
1841 : : }
1842 : :
1843 : 0 : static void ip_mc_clear_src(struct ip_mc_list *pmc)
1844 : : {
1845 : : struct ip_sf_list *psf, *nextpsf;
1846 : :
1847 [ # # ]: 0 : for (psf = pmc->tomb; psf; psf = nextpsf) {
1848 : 0 : nextpsf = psf->sf_next;
1849 : 0 : kfree(psf);
1850 : : }
1851 : 0 : pmc->tomb = NULL;
1852 [ # # ]: 0 : for (psf = pmc->sources; psf; psf = nextpsf) {
1853 : 0 : nextpsf = psf->sf_next;
1854 : 0 : kfree(psf);
1855 : : }
1856 : 0 : pmc->sources = NULL;
1857 : 0 : pmc->sfmode = MCAST_EXCLUDE;
1858 : 0 : pmc->sfcount[MCAST_INCLUDE] = 0;
1859 : 0 : pmc->sfcount[MCAST_EXCLUDE] = 1;
1860 : 0 : }
1861 : :
1862 : :
1863 : : /*
1864 : : * Join a multicast group
1865 : : */
1866 : 0 : int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr)
1867 : : {
1868 : : int err;
1869 : 0 : __be32 addr = imr->imr_multiaddr.s_addr;
1870 : : struct ip_mc_socklist *iml = NULL, *i;
1871 : : struct in_device *in_dev;
1872 : : struct inet_sock *inet = inet_sk(sk);
1873 : : struct net *net = sock_net(sk);
1874 : : int ifindex;
1875 : : int count = 0;
1876 : :
1877 [ # # ]: 0 : if (!ipv4_is_multicast(addr))
1878 : : return -EINVAL;
1879 : :
1880 : 0 : rtnl_lock();
1881 : :
1882 : 0 : in_dev = ip_mc_find_dev(net, imr);
1883 : :
1884 [ # # ]: 0 : if (!in_dev) {
1885 : : iml = NULL;
1886 : : err = -ENODEV;
1887 : : goto done;
1888 : : }
1889 : :
1890 : : err = -EADDRINUSE;
1891 : 0 : ifindex = imr->imr_ifindex;
1892 [ # # ]: 0 : for_each_pmc_rtnl(inet, i) {
1893 [ # # ][ # # ]: 0 : if (i->multi.imr_multiaddr.s_addr == addr &&
1894 : 0 : i->multi.imr_ifindex == ifindex)
1895 : : goto done;
1896 : 0 : count++;
1897 : : }
1898 : : err = -ENOBUFS;
1899 [ # # ]: 0 : if (count >= sysctl_igmp_max_memberships)
1900 : : goto done;
1901 : 0 : iml = sock_kmalloc(sk, sizeof(*iml), GFP_KERNEL);
1902 [ # # ]: 0 : if (iml == NULL)
1903 : : goto done;
1904 : :
1905 : 0 : memcpy(&iml->multi, imr, sizeof(*imr));
1906 : 0 : iml->next_rcu = inet->mc_list;
1907 : 0 : iml->sflist = NULL;
1908 : 0 : iml->sfmode = MCAST_EXCLUDE;
1909 : 0 : rcu_assign_pointer(inet->mc_list, iml);
1910 : 0 : ip_mc_inc_group(in_dev, addr);
1911 : : err = 0;
1912 : : done:
1913 : 0 : rtnl_unlock();
1914 : 0 : return err;
1915 : : }
1916 : : EXPORT_SYMBOL(ip_mc_join_group);
1917 : :
1918 : 0 : static int ip_mc_leave_src(struct sock *sk, struct ip_mc_socklist *iml,
1919 : : struct in_device *in_dev)
1920 : : {
1921 : 0 : struct ip_sf_socklist *psf = rtnl_dereference(iml->sflist);
1922 : : int err;
1923 : :
1924 [ # # ]: 0 : if (psf == NULL) {
1925 : : /* any-source empty exclude case */
1926 : 0 : return ip_mc_del_src(in_dev, &iml->multi.imr_multiaddr.s_addr,
1927 : 0 : iml->sfmode, 0, NULL, 0);
1928 : : }
1929 : 0 : err = ip_mc_del_src(in_dev, &iml->multi.imr_multiaddr.s_addr,
1930 : 0 : iml->sfmode, psf->sl_count, psf->sl_addr, 0);
1931 : 0 : RCU_INIT_POINTER(iml->sflist, NULL);
1932 : : /* decrease mem now to avoid the memleak warning */
1933 : 0 : atomic_sub(IP_SFLSIZE(psf->sl_max), &sk->sk_omem_alloc);
1934 : 0 : kfree_rcu(psf, rcu);
1935 : 0 : return err;
1936 : : }
1937 : :
1938 : : /*
1939 : : * Ask a socket to leave a group.
1940 : : */
1941 : :
1942 : 0 : int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)
1943 : : {
1944 : : struct inet_sock *inet = inet_sk(sk);
1945 : : struct ip_mc_socklist *iml;
1946 : : struct ip_mc_socklist __rcu **imlp;
1947 : : struct in_device *in_dev;
1948 : : struct net *net = sock_net(sk);
1949 : 0 : __be32 group = imr->imr_multiaddr.s_addr;
1950 : : u32 ifindex;
1951 : : int ret = -EADDRNOTAVAIL;
1952 : :
1953 : 0 : rtnl_lock();
1954 : 0 : in_dev = ip_mc_find_dev(net, imr);
1955 : 0 : ifindex = imr->imr_ifindex;
1956 [ # # ]: 0 : for (imlp = &inet->mc_list;
1957 : 0 : (iml = rtnl_dereference(*imlp)) != NULL;
1958 : 0 : imlp = &iml->next_rcu) {
1959 [ # # ]: 0 : if (iml->multi.imr_multiaddr.s_addr != group)
1960 : 0 : continue;
1961 [ # # ]: 0 : if (ifindex) {
1962 [ # # ]: 0 : if (iml->multi.imr_ifindex != ifindex)
1963 : 0 : continue;
1964 [ # # ][ # # ]: 0 : } else if (imr->imr_address.s_addr && imr->imr_address.s_addr !=
1965 : 0 : iml->multi.imr_address.s_addr)
1966 : 0 : continue;
1967 : :
1968 : 0 : (void) ip_mc_leave_src(sk, iml, in_dev);
1969 : :
1970 : 0 : *imlp = iml->next_rcu;
1971 : :
1972 [ # # ]: 0 : if (in_dev)
1973 : 0 : ip_mc_dec_group(in_dev, group);
1974 : 0 : rtnl_unlock();
1975 : : /* decrease mem now to avoid the memleak warning */
1976 : 0 : atomic_sub(sizeof(*iml), &sk->sk_omem_alloc);
1977 : 0 : kfree_rcu(iml, rcu);
1978 : 0 : return 0;
1979 : : }
1980 [ # # ]: 0 : if (!in_dev)
1981 : : ret = -ENODEV;
1982 : 0 : rtnl_unlock();
1983 : 0 : return ret;
1984 : : }
1985 : : EXPORT_SYMBOL(ip_mc_leave_group);
1986 : :
1987 : 0 : int ip_mc_source(int add, int omode, struct sock *sk, struct
1988 : : ip_mreq_source *mreqs, int ifindex)
1989 : : {
1990 : : int err;
1991 : : struct ip_mreqn imr;
1992 : 0 : __be32 addr = mreqs->imr_multiaddr;
1993 : : struct ip_mc_socklist *pmc;
1994 : : struct in_device *in_dev = NULL;
1995 : : struct inet_sock *inet = inet_sk(sk);
1996 : : struct ip_sf_socklist *psl;
1997 : : struct net *net = sock_net(sk);
1998 : : int leavegroup = 0;
1999 : : int i, j, rv;
2000 : :
2001 [ # # ]: 0 : if (!ipv4_is_multicast(addr))
2002 : : return -EINVAL;
2003 : :
2004 : 0 : rtnl_lock();
2005 : :
2006 : 0 : imr.imr_multiaddr.s_addr = mreqs->imr_multiaddr;
2007 : 0 : imr.imr_address.s_addr = mreqs->imr_interface;
2008 : 0 : imr.imr_ifindex = ifindex;
2009 : 0 : in_dev = ip_mc_find_dev(net, &imr);
2010 : :
2011 [ # # ]: 0 : if (!in_dev) {
2012 : : err = -ENODEV;
2013 : : goto done;
2014 : : }
2015 : : err = -EADDRNOTAVAIL;
2016 : :
2017 [ # # ]: 0 : for_each_pmc_rtnl(inet, pmc) {
2018 [ # # ]: 0 : if ((pmc->multi.imr_multiaddr.s_addr ==
2019 [ # # ]: 0 : imr.imr_multiaddr.s_addr) &&
2020 : 0 : (pmc->multi.imr_ifindex == imr.imr_ifindex))
2021 : : break;
2022 : : }
2023 [ # # ]: 0 : if (!pmc) { /* must have a prior join */
2024 : : err = -EINVAL;
2025 : : goto done;
2026 : : }
2027 : : /* if a source filter was set, must be the same mode as before */
2028 [ # # ]: 0 : if (pmc->sflist) {
2029 [ # # ]: 0 : if (pmc->sfmode != omode) {
2030 : : err = -EINVAL;
2031 : : goto done;
2032 : : }
2033 [ # # ]: 0 : } else if (pmc->sfmode != omode) {
2034 : : /* allow mode switches for empty-set filters */
2035 : 0 : ip_mc_add_src(in_dev, &mreqs->imr_multiaddr, omode, 0, NULL, 0);
2036 : 0 : ip_mc_del_src(in_dev, &mreqs->imr_multiaddr, pmc->sfmode, 0,
2037 : : NULL, 0);
2038 : 0 : pmc->sfmode = omode;
2039 : : }
2040 : :
2041 : 0 : psl = rtnl_dereference(pmc->sflist);
2042 [ # # ]: 0 : if (!add) {
2043 [ # # ]: 0 : if (!psl)
2044 : : goto done; /* err = -EADDRNOTAVAIL */
2045 : : rv = !0;
2046 [ # # ]: 0 : for (i = 0; i < psl->sl_count; i++) {
2047 : 0 : rv = memcmp(&psl->sl_addr[i], &mreqs->imr_sourceaddr,
2048 : : sizeof(__be32));
2049 [ # # ]: 0 : if (rv == 0)
2050 : : break;
2051 : : }
2052 [ # # ]: 0 : if (rv) /* source not found */
2053 : : goto done; /* err = -EADDRNOTAVAIL */
2054 : :
2055 : : /* special case - (INCLUDE, empty) == LEAVE_GROUP */
2056 [ # # ][ # # ]: 0 : if (psl->sl_count == 1 && omode == MCAST_INCLUDE) {
2057 : : leavegroup = 1;
2058 : : goto done;
2059 : : }
2060 : :
2061 : : /* update the interface filter */
2062 : 0 : ip_mc_del_src(in_dev, &mreqs->imr_multiaddr, omode, 1,
2063 : : &mreqs->imr_sourceaddr, 1);
2064 : :
2065 [ # # ]: 0 : for (j = i+1; j < psl->sl_count; j++)
2066 : 0 : psl->sl_addr[j-1] = psl->sl_addr[j];
2067 : 0 : psl->sl_count--;
2068 : : err = 0;
2069 : 0 : goto done;
2070 : : }
2071 : : /* else, add a new source to the filter */
2072 : :
2073 [ # # ][ # # ]: 0 : if (psl && psl->sl_count >= sysctl_igmp_max_msf) {
2074 : : err = -ENOBUFS;
2075 : : goto done;
2076 : : }
2077 [ # # ][ # # ]: 0 : if (!psl || psl->sl_count == psl->sl_max) {
2078 : : struct ip_sf_socklist *newpsl;
2079 : : int count = IP_SFBLOCK;
2080 : :
2081 [ # # ]: 0 : if (psl)
2082 : 0 : count += psl->sl_max;
2083 : 0 : newpsl = sock_kmalloc(sk, IP_SFLSIZE(count), GFP_KERNEL);
2084 [ # # ]: 0 : if (!newpsl) {
2085 : : err = -ENOBUFS;
2086 : : goto done;
2087 : : }
2088 : 0 : newpsl->sl_max = count;
2089 : 0 : newpsl->sl_count = count - IP_SFBLOCK;
2090 [ # # ]: 0 : if (psl) {
2091 [ # # ]: 0 : for (i = 0; i < psl->sl_count; i++)
2092 : 0 : newpsl->sl_addr[i] = psl->sl_addr[i];
2093 : : /* decrease mem now to avoid the memleak warning */
2094 : 0 : atomic_sub(IP_SFLSIZE(psl->sl_max), &sk->sk_omem_alloc);
2095 : 0 : kfree_rcu(psl, rcu);
2096 : : }
2097 : 0 : rcu_assign_pointer(pmc->sflist, newpsl);
2098 : : psl = newpsl;
2099 : : }
2100 : : rv = 1; /* > 0 for insert logic below if sl_count is 0 */
2101 [ # # ]: 0 : for (i = 0; i < psl->sl_count; i++) {
2102 : 0 : rv = memcmp(&psl->sl_addr[i], &mreqs->imr_sourceaddr,
2103 : : sizeof(__be32));
2104 [ # # ]: 0 : if (rv == 0)
2105 : : break;
2106 : : }
2107 [ # # ]: 0 : if (rv == 0) /* address already there is an error */
2108 : : goto done;
2109 [ # # ]: 0 : for (j = psl->sl_count-1; j >= i; j--)
2110 : 0 : psl->sl_addr[j+1] = psl->sl_addr[j];
2111 : 0 : psl->sl_addr[i] = mreqs->imr_sourceaddr;
2112 : 0 : psl->sl_count++;
2113 : : err = 0;
2114 : : /* update the interface list */
2115 : 0 : ip_mc_add_src(in_dev, &mreqs->imr_multiaddr, omode, 1,
2116 : : &mreqs->imr_sourceaddr, 1);
2117 : : done:
2118 : 0 : rtnl_unlock();
2119 [ # # ]: 0 : if (leavegroup)
2120 : 0 : return ip_mc_leave_group(sk, &imr);
2121 : : return err;
2122 : : }
2123 : :
2124 : 0 : int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex)
2125 : : {
2126 : : int err = 0;
2127 : : struct ip_mreqn imr;
2128 : 0 : __be32 addr = msf->imsf_multiaddr;
2129 : : struct ip_mc_socklist *pmc;
2130 : : struct in_device *in_dev;
2131 : : struct inet_sock *inet = inet_sk(sk);
2132 : : struct ip_sf_socklist *newpsl, *psl;
2133 : : struct net *net = sock_net(sk);
2134 : : int leavegroup = 0;
2135 : :
2136 [ # # ]: 0 : if (!ipv4_is_multicast(addr))
2137 : : return -EINVAL;
2138 [ # # ]: 0 : if (msf->imsf_fmode != MCAST_INCLUDE &&
2139 : : msf->imsf_fmode != MCAST_EXCLUDE)
2140 : : return -EINVAL;
2141 : :
2142 : 0 : rtnl_lock();
2143 : :
2144 : 0 : imr.imr_multiaddr.s_addr = msf->imsf_multiaddr;
2145 : 0 : imr.imr_address.s_addr = msf->imsf_interface;
2146 : 0 : imr.imr_ifindex = ifindex;
2147 : 0 : in_dev = ip_mc_find_dev(net, &imr);
2148 : :
2149 [ # # ]: 0 : if (!in_dev) {
2150 : : err = -ENODEV;
2151 : : goto done;
2152 : : }
2153 : :
2154 : : /* special case - (INCLUDE, empty) == LEAVE_GROUP */
2155 [ # # ][ # # ]: 0 : if (msf->imsf_fmode == MCAST_INCLUDE && msf->imsf_numsrc == 0) {
2156 : : leavegroup = 1;
2157 : : goto done;
2158 : : }
2159 : :
2160 [ # # ]: 0 : for_each_pmc_rtnl(inet, pmc) {
2161 [ # # ][ # # ]: 0 : if (pmc->multi.imr_multiaddr.s_addr == msf->imsf_multiaddr &&
2162 : 0 : pmc->multi.imr_ifindex == imr.imr_ifindex)
2163 : : break;
2164 : : }
2165 [ # # ]: 0 : if (!pmc) { /* must have a prior join */
2166 : : err = -EINVAL;
2167 : : goto done;
2168 : : }
2169 [ # # ]: 0 : if (msf->imsf_numsrc) {
2170 : 0 : newpsl = sock_kmalloc(sk, IP_SFLSIZE(msf->imsf_numsrc),
2171 : : GFP_KERNEL);
2172 [ # # ]: 0 : if (!newpsl) {
2173 : : err = -ENOBUFS;
2174 : : goto done;
2175 : : }
2176 : 0 : newpsl->sl_max = newpsl->sl_count = msf->imsf_numsrc;
2177 : 0 : memcpy(newpsl->sl_addr, msf->imsf_slist,
2178 : 0 : msf->imsf_numsrc * sizeof(msf->imsf_slist[0]));
2179 : 0 : err = ip_mc_add_src(in_dev, &msf->imsf_multiaddr,
2180 : 0 : msf->imsf_fmode, newpsl->sl_count, newpsl->sl_addr, 0);
2181 [ # # ]: 0 : if (err) {
2182 : 0 : sock_kfree_s(sk, newpsl, IP_SFLSIZE(newpsl->sl_max));
2183 : 0 : goto done;
2184 : : }
2185 : : } else {
2186 : : newpsl = NULL;
2187 : 0 : (void) ip_mc_add_src(in_dev, &msf->imsf_multiaddr,
2188 : : msf->imsf_fmode, 0, NULL, 0);
2189 : : }
2190 : 0 : psl = rtnl_dereference(pmc->sflist);
2191 [ # # ]: 0 : if (psl) {
2192 : 0 : (void) ip_mc_del_src(in_dev, &msf->imsf_multiaddr, pmc->sfmode,
2193 : 0 : psl->sl_count, psl->sl_addr, 0);
2194 : : /* decrease mem now to avoid the memleak warning */
2195 : 0 : atomic_sub(IP_SFLSIZE(psl->sl_max), &sk->sk_omem_alloc);
2196 : 0 : kfree_rcu(psl, rcu);
2197 : : } else
2198 : 0 : (void) ip_mc_del_src(in_dev, &msf->imsf_multiaddr, pmc->sfmode,
2199 : : 0, NULL, 0);
2200 : 0 : rcu_assign_pointer(pmc->sflist, newpsl);
2201 : 0 : pmc->sfmode = msf->imsf_fmode;
2202 : : err = 0;
2203 : : done:
2204 : 0 : rtnl_unlock();
2205 [ # # ]: 0 : if (leavegroup)
2206 : 0 : err = ip_mc_leave_group(sk, &imr);
2207 : 0 : return err;
2208 : : }
2209 : :
2210 : 0 : int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf,
2211 : : struct ip_msfilter __user *optval, int __user *optlen)
2212 : : {
2213 : : int err, len, count, copycount;
2214 : : struct ip_mreqn imr;
2215 : 0 : __be32 addr = msf->imsf_multiaddr;
2216 : : struct ip_mc_socklist *pmc;
2217 : : struct in_device *in_dev;
2218 : : struct inet_sock *inet = inet_sk(sk);
2219 : : struct ip_sf_socklist *psl;
2220 : : struct net *net = sock_net(sk);
2221 : :
2222 [ # # ]: 0 : if (!ipv4_is_multicast(addr))
2223 : : return -EINVAL;
2224 : :
2225 : 0 : rtnl_lock();
2226 : :
2227 : 0 : imr.imr_multiaddr.s_addr = msf->imsf_multiaddr;
2228 : 0 : imr.imr_address.s_addr = msf->imsf_interface;
2229 : 0 : imr.imr_ifindex = 0;
2230 : 0 : in_dev = ip_mc_find_dev(net, &imr);
2231 : :
2232 [ # # ]: 0 : if (!in_dev) {
2233 : : err = -ENODEV;
2234 : : goto done;
2235 : : }
2236 : : err = -EADDRNOTAVAIL;
2237 : :
2238 [ # # ]: 0 : for_each_pmc_rtnl(inet, pmc) {
2239 [ # # ][ # # ]: 0 : if (pmc->multi.imr_multiaddr.s_addr == msf->imsf_multiaddr &&
2240 : 0 : pmc->multi.imr_ifindex == imr.imr_ifindex)
2241 : : break;
2242 : : }
2243 [ # # ]: 0 : if (!pmc) /* must have a prior join */
2244 : : goto done;
2245 : 0 : msf->imsf_fmode = pmc->sfmode;
2246 : 0 : psl = rtnl_dereference(pmc->sflist);
2247 : 0 : rtnl_unlock();
2248 [ # # ]: 0 : if (!psl) {
2249 : : len = 0;
2250 : : count = 0;
2251 : : } else {
2252 : 0 : count = psl->sl_count;
2253 : : }
2254 : 0 : copycount = count < msf->imsf_numsrc ? count : msf->imsf_numsrc;
2255 : 0 : len = copycount * sizeof(psl->sl_addr[0]);
2256 : 0 : msf->imsf_numsrc = count;
2257 [ # # ][ # # ]: 0 : if (put_user(IP_MSFILTER_SIZE(copycount), optlen) ||
2258 : : copy_to_user(optval, msf, IP_MSFILTER_SIZE(0))) {
2259 : : return -EFAULT;
2260 : : }
2261 [ # # ][ # # ]: 0 : if (len &&
2262 : 0 : copy_to_user(&optval->imsf_slist[0], psl->sl_addr, len))
2263 : : return -EFAULT;
2264 : : return 0;
2265 : : done:
2266 : 0 : rtnl_unlock();
2267 : 0 : return err;
2268 : : }
2269 : :
2270 : 0 : int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf,
2271 : : struct group_filter __user *optval, int __user *optlen)
2272 : : {
2273 : : int err, i, count, copycount;
2274 : : struct sockaddr_in *psin;
2275 : : __be32 addr;
2276 : : struct ip_mc_socklist *pmc;
2277 : : struct inet_sock *inet = inet_sk(sk);
2278 : : struct ip_sf_socklist *psl;
2279 : :
2280 : : psin = (struct sockaddr_in *)&gsf->gf_group;
2281 [ # # ]: 0 : if (psin->sin_family != AF_INET)
2282 : : return -EINVAL;
2283 : 0 : addr = psin->sin_addr.s_addr;
2284 [ # # ]: 0 : if (!ipv4_is_multicast(addr))
2285 : : return -EINVAL;
2286 : :
2287 : 0 : rtnl_lock();
2288 : :
2289 : : err = -EADDRNOTAVAIL;
2290 : :
2291 [ # # ]: 0 : for_each_pmc_rtnl(inet, pmc) {
2292 [ # # ][ # # ]: 0 : if (pmc->multi.imr_multiaddr.s_addr == addr &&
2293 : 0 : pmc->multi.imr_ifindex == gsf->gf_interface)
2294 : : break;
2295 : : }
2296 [ # # ]: 0 : if (!pmc) /* must have a prior join */
2297 : : goto done;
2298 : 0 : gsf->gf_fmode = pmc->sfmode;
2299 : 0 : psl = rtnl_dereference(pmc->sflist);
2300 : 0 : rtnl_unlock();
2301 [ # # ]: 0 : count = psl ? psl->sl_count : 0;
2302 : 0 : copycount = count < gsf->gf_numsrc ? count : gsf->gf_numsrc;
2303 : 0 : gsf->gf_numsrc = count;
2304 [ # # ][ # # ]: 0 : if (put_user(GROUP_FILTER_SIZE(copycount), optlen) ||
2305 : : copy_to_user(optval, gsf, GROUP_FILTER_SIZE(0))) {
2306 : : return -EFAULT;
2307 : : }
2308 [ # # ]: 0 : for (i = 0; i < copycount; i++) {
2309 : : struct sockaddr_storage ss;
2310 : :
2311 : : psin = (struct sockaddr_in *)&ss;
2312 : 0 : memset(&ss, 0, sizeof(ss));
2313 : 0 : psin->sin_family = AF_INET;
2314 : 0 : psin->sin_addr.s_addr = psl->sl_addr[i];
2315 [ # # ]: 0 : if (copy_to_user(&optval->gf_slist[i], &ss, sizeof(ss)))
2316 : 0 : return -EFAULT;
2317 : : }
2318 : : return 0;
2319 : : done:
2320 : 0 : rtnl_unlock();
2321 : 0 : return err;
2322 : : }
2323 : :
2324 : : /*
2325 : : * check if a multicast source filter allows delivery for a given <src,dst,intf>
2326 : : */
2327 : 0 : int ip_mc_sf_allow(struct sock *sk, __be32 loc_addr, __be32 rmt_addr, int dif)
2328 : : {
2329 : : struct inet_sock *inet = inet_sk(sk);
2330 : : struct ip_mc_socklist *pmc;
2331 : : struct ip_sf_socklist *psl;
2332 : : int i;
2333 : : int ret;
2334 : :
2335 : : ret = 1;
2336 [ - + ]: 30 : if (!ipv4_is_multicast(loc_addr))
2337 : : goto out;
2338 : :
2339 : : rcu_read_lock();
2340 [ # # ]: 0 : for_each_pmc_rcu(inet, pmc) {
2341 [ # # ][ # # ]: 0 : if (pmc->multi.imr_multiaddr.s_addr == loc_addr &&
2342 : 0 : pmc->multi.imr_ifindex == dif)
2343 : : break;
2344 : : }
2345 : 0 : ret = inet->mc_all;
2346 [ # # ]: 0 : if (!pmc)
2347 : : goto unlock;
2348 : 0 : psl = rcu_dereference(pmc->sflist);
2349 : 0 : ret = (pmc->sfmode == MCAST_EXCLUDE);
2350 [ # # ]: 0 : if (!psl)
2351 : : goto unlock;
2352 : :
2353 [ # # ]: 0 : for (i = 0; i < psl->sl_count; i++) {
2354 [ # # ]: 0 : if (psl->sl_addr[i] == rmt_addr)
2355 : : break;
2356 : : }
2357 : : ret = 0;
2358 [ # # ][ # # ]: 0 : if (pmc->sfmode == MCAST_INCLUDE && i >= psl->sl_count)
2359 : : goto unlock;
2360 [ # # ][ # # ]: 0 : if (pmc->sfmode == MCAST_EXCLUDE && i < psl->sl_count)
2361 : : goto unlock;
2362 : : ret = 1;
2363 : : unlock:
2364 : : rcu_read_unlock();
2365 : : out:
2366 : 30 : return ret;
2367 : : }
2368 : :
2369 : : /*
2370 : : * A socket is closing.
2371 : : */
2372 : :
2373 : 0 : void ip_mc_drop_socket(struct sock *sk)
2374 : : {
2375 : : struct inet_sock *inet = inet_sk(sk);
2376 : : struct ip_mc_socklist *iml;
2377 : : struct net *net = sock_net(sk);
2378 : :
2379 [ - + ]: 178 : if (inet->mc_list == NULL)
2380 : 178 : return;
2381 : :
2382 : 0 : rtnl_lock();
2383 [ # # ]: 0 : while ((iml = rtnl_dereference(inet->mc_list)) != NULL) {
2384 : : struct in_device *in_dev;
2385 : :
2386 : 0 : inet->mc_list = iml->next_rcu;
2387 : 0 : in_dev = inetdev_by_index(net, iml->multi.imr_ifindex);
2388 : 0 : (void) ip_mc_leave_src(sk, iml, in_dev);
2389 [ # # ]: 0 : if (in_dev != NULL)
2390 : 0 : ip_mc_dec_group(in_dev, iml->multi.imr_multiaddr.s_addr);
2391 : : /* decrease mem now to avoid the memleak warning */
2392 : 0 : atomic_sub(sizeof(*iml), &sk->sk_omem_alloc);
2393 : 0 : kfree_rcu(iml, rcu);
2394 : : }
2395 : 0 : rtnl_unlock();
2396 : : }
2397 : :
2398 : : /* called with rcu_read_lock() */
2399 : 0 : int ip_check_mc_rcu(struct in_device *in_dev, __be32 mc_addr, __be32 src_addr, u16 proto)
2400 : : {
2401 : : struct ip_mc_list *im;
2402 : : struct ip_mc_list __rcu **mc_hash;
2403 : : struct ip_sf_list *psf;
2404 : : int rv = 0;
2405 : :
2406 : 20 : mc_hash = rcu_dereference(in_dev->mc_hash);
2407 [ - + ]: 20 : if (mc_hash) {
2408 : : u32 hash = hash_32((__force u32)mc_addr, MC_HASH_SZ_LOG);
2409 : :
2410 [ # # ]: 0 : for (im = rcu_dereference(mc_hash[hash]);
2411 : : im != NULL;
2412 : 0 : im = rcu_dereference(im->next_hash)) {
2413 [ # # ]: 0 : if (im->multiaddr == mc_addr)
2414 : : break;
2415 : : }
2416 : : } else {
2417 [ + + ]: 40 : for_each_pmc_rcu(in_dev, im) {
2418 [ + - ]: 20 : if (im->multiaddr == mc_addr)
2419 : : break;
2420 : : }
2421 : : }
2422 [ + - ]: 20 : if (im && proto == IPPROTO_IGMP) {
2423 : : rv = 1;
2424 [ - + ]: 20 : } else if (im) {
2425 [ # # ]: 0 : if (src_addr) {
2426 [ # # ]: 20 : for (psf = im->sources; psf; psf = psf->sf_next) {
2427 [ # # ]: 0 : if (psf->sf_inaddr == src_addr)
2428 : : break;
2429 : : }
2430 [ # # ]: 0 : if (psf)
2431 [ # # ][ # # ]: 0 : rv = psf->sf_count[MCAST_INCLUDE] ||
2432 : 0 : psf->sf_count[MCAST_EXCLUDE] !=
2433 : 0 : im->sfcount[MCAST_EXCLUDE];
2434 : : else
2435 : 0 : rv = im->sfcount[MCAST_EXCLUDE] != 0;
2436 : : } else
2437 : : rv = 1; /* unspecified source; tentatively allow */
2438 : : }
2439 : 0 : return rv;
2440 : : }
2441 : :
2442 : : #if defined(CONFIG_PROC_FS)
2443 : : struct igmp_mc_iter_state {
2444 : : struct seq_net_private p;
2445 : : struct net_device *dev;
2446 : : struct in_device *in_dev;
2447 : : };
2448 : :
2449 : : #define igmp_mc_seq_private(seq) ((struct igmp_mc_iter_state *)(seq)->private)
2450 : :
2451 : : static inline struct ip_mc_list *igmp_mc_get_first(struct seq_file *seq)
2452 : : {
2453 : : struct net *net = seq_file_net(seq);
2454 : : struct ip_mc_list *im = NULL;
2455 : : struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq);
2456 : :
2457 : 2 : state->in_dev = NULL;
2458 [ + - ][ + - ]: 3 : for_each_netdev_rcu(net, state->dev) {
2459 : : struct in_device *in_dev;
2460 : :
2461 : 2 : in_dev = __in_dev_get_rcu(state->dev);
2462 [ - + ][ - + ]: 2 : if (!in_dev)
2463 : 0 : continue;
2464 : 2 : im = rcu_dereference(in_dev->mc_list);
2465 [ + - ][ + - ]: 2 : if (im) {
2466 : 2 : state->in_dev = in_dev;
2467 : : break;
2468 : : }
2469 : : }
2470 : : return im;
2471 : : }
2472 : :
2473 : : static struct ip_mc_list *igmp_mc_get_next(struct seq_file *seq, struct ip_mc_list *im)
2474 : : {
2475 : : struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq);
2476 : :
2477 : : im = rcu_dereference(im->next_rcu);
2478 [ + + ][ + + ]: 9 : while (!im) {
2479 : 16 : state->dev = next_net_device_rcu(state->dev);
2480 [ + + ][ + + ]: 6 : if (!state->dev) {
2481 : 2 : state->in_dev = NULL;
2482 : : break;
2483 : : }
2484 : 4 : state->in_dev = __in_dev_get_rcu(state->dev);
2485 [ - + ][ - + ]: 4 : if (!state->in_dev)
2486 : 0 : continue;
2487 : 4 : im = rcu_dereference(state->in_dev->mc_list);
2488 : : }
2489 : : return im;
2490 : : }
2491 : :
2492 : 0 : static struct ip_mc_list *igmp_mc_get_idx(struct seq_file *seq, loff_t pos)
2493 : : {
2494 : 2 : struct ip_mc_list *im = igmp_mc_get_first(seq);
2495 [ + - ]: 1 : if (im)
2496 [ + - ][ + - ]: 4 : while (pos && (im = igmp_mc_get_next(seq, im)) != NULL)
2497 : 1 : --pos;
2498 [ # # ]: 0 : return pos ? NULL : im;
2499 : : }
2500 : :
2501 : 0 : static void *igmp_mc_seq_start(struct seq_file *seq, loff_t *pos)
2502 : : __acquires(rcu)
2503 : : {
2504 : : rcu_read_lock();
2505 [ + + ]: 2 : return *pos ? igmp_mc_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
2506 : : }
2507 : :
2508 : 2 : static void *igmp_mc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2509 : : {
2510 : : struct ip_mc_list *im;
2511 [ + + ]: 3 : if (v == SEQ_START_TOKEN)
2512 : : im = igmp_mc_get_first(seq);
2513 : : else
2514 : : im = igmp_mc_get_next(seq, v);
2515 : 3 : ++*pos;
2516 : 3 : return im;
2517 : : }
2518 : :
2519 : 0 : static void igmp_mc_seq_stop(struct seq_file *seq, void *v)
2520 : : __releases(rcu)
2521 : : {
2522 : 2 : struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq);
2523 : :
2524 : 2 : state->in_dev = NULL;
2525 : 2 : state->dev = NULL;
2526 : : rcu_read_unlock();
2527 : 2 : }
2528 : :
2529 : 0 : static int igmp_mc_seq_show(struct seq_file *seq, void *v)
2530 : : {
2531 [ + + ]: 3 : if (v == SEQ_START_TOKEN)
2532 : 1 : seq_puts(seq,
2533 : : "Idx\tDevice : Count Querier\tGroup Users Timer\tReporter\n");
2534 : : else {
2535 : : struct ip_mc_list *im = (struct ip_mc_list *)v;
2536 : 2 : struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq);
2537 : : char *querier;
2538 : : long delta;
2539 : :
2540 : : #ifdef CONFIG_IP_MULTICAST
2541 [ + - ][ + - ]: 4 : querier = IGMP_V1_SEEN(state->in_dev) ? "V1" :
[ - + ][ # # ]
2542 [ + - ][ + - ]: 2 : IGMP_V2_SEEN(state->in_dev) ? "V2" :
[ - + ][ # # ]
2543 : : "V3";
2544 : : #else
2545 : : querier = "NONE";
2546 : : #endif
2547 : :
2548 [ + ]: 2 : if (rcu_dereference(state->in_dev->mc_list) == im) {
2549 : 2 : seq_printf(seq, "%d\t%-10s: %5d %7s\n",
2550 : 4 : state->dev->ifindex, state->dev->name, state->in_dev->mc_count, querier);
2551 : : }
2552 : :
2553 : 2 : delta = im->timer.expires - jiffies;
2554 [ - + ]: 2 : seq_printf(seq,
2555 : : "\t\t\t\t%08X %5d %d:%08lX\t\t%d\n",
2556 : : im->multiaddr, im->users,
2557 : 2 : im->tm_running,
2558 : : im->tm_running ? jiffies_delta_to_clock_t(delta) : 0,
2559 : 2 : im->reporter);
2560 : : }
2561 : 3 : return 0;
2562 : : }
2563 : :
2564 : : static const struct seq_operations igmp_mc_seq_ops = {
2565 : : .start = igmp_mc_seq_start,
2566 : : .next = igmp_mc_seq_next,
2567 : : .stop = igmp_mc_seq_stop,
2568 : : .show = igmp_mc_seq_show,
2569 : : };
2570 : :
2571 : 0 : static int igmp_mc_seq_open(struct inode *inode, struct file *file)
2572 : : {
2573 : 1 : return seq_open_net(inode, file, &igmp_mc_seq_ops,
2574 : : sizeof(struct igmp_mc_iter_state));
2575 : : }
2576 : :
2577 : : static const struct file_operations igmp_mc_seq_fops = {
2578 : : .owner = THIS_MODULE,
2579 : : .open = igmp_mc_seq_open,
2580 : : .read = seq_read,
2581 : : .llseek = seq_lseek,
2582 : : .release = seq_release_net,
2583 : : };
2584 : :
2585 : : struct igmp_mcf_iter_state {
2586 : : struct seq_net_private p;
2587 : : struct net_device *dev;
2588 : : struct in_device *idev;
2589 : : struct ip_mc_list *im;
2590 : : };
2591 : :
2592 : : #define igmp_mcf_seq_private(seq) ((struct igmp_mcf_iter_state *)(seq)->private)
2593 : :
2594 : : static inline struct ip_sf_list *igmp_mcf_get_first(struct seq_file *seq)
2595 : : {
2596 : : struct net *net = seq_file_net(seq);
2597 : : struct ip_sf_list *psf = NULL;
2598 : : struct ip_mc_list *im = NULL;
2599 : : struct igmp_mcf_iter_state *state = igmp_mcf_seq_private(seq);
2600 : :
2601 : 2 : state->idev = NULL;
2602 : 2 : state->im = NULL;
2603 [ + + ][ + + ]: 8 : for_each_netdev_rcu(net, state->dev) {
2604 : : struct in_device *idev;
2605 : 6 : idev = __in_dev_get_rcu(state->dev);
2606 [ - + ][ - + ]: 6 : if (unlikely(idev == NULL))
2607 : 0 : continue;
2608 : 6 : im = rcu_dereference(idev->mc_list);
2609 [ + + ][ + + ]: 6 : if (likely(im != NULL)) {
2610 : : spin_lock_bh(&im->lock);
2611 : 4 : psf = im->sources;
2612 [ - + - + ]: 5 : if (likely(psf != NULL)) {
2613 : 0 : state->im = im;
2614 : 0 : state->idev = idev;
2615 : : break;
2616 : : }
2617 : : spin_unlock_bh(&im->lock);
2618 : : }
2619 : : }
2620 : : return psf;
2621 : : }
2622 : :
2623 : 0 : static struct ip_sf_list *igmp_mcf_get_next(struct seq_file *seq, struct ip_sf_list *psf)
2624 : : {
2625 : 0 : struct igmp_mcf_iter_state *state = igmp_mcf_seq_private(seq);
2626 : :
2627 : 0 : psf = psf->sf_next;
2628 [ # # ]: 0 : while (!psf) {
2629 : 0 : spin_unlock_bh(&state->im->lock);
2630 : 0 : state->im = state->im->next;
2631 [ # # ]: 0 : while (!state->im) {
2632 : 0 : state->dev = next_net_device_rcu(state->dev);
2633 [ # # ]: 0 : if (!state->dev) {
2634 : 0 : state->idev = NULL;
2635 : : goto out;
2636 : : }
2637 : 0 : state->idev = __in_dev_get_rcu(state->dev);
2638 [ # # ]: 0 : if (!state->idev)
2639 : 0 : continue;
2640 : 0 : state->im = rcu_dereference(state->idev->mc_list);
2641 : : }
2642 [ # # ]: 0 : if (!state->im)
2643 : : break;
2644 : : spin_lock_bh(&state->im->lock);
2645 : 0 : psf = state->im->sources;
2646 : : }
2647 : : out:
2648 : 0 : return psf;
2649 : : }
2650 : :
2651 : 0 : static struct ip_sf_list *igmp_mcf_get_idx(struct seq_file *seq, loff_t pos)
2652 : : {
2653 : 0 : struct ip_sf_list *psf = igmp_mcf_get_first(seq);
2654 [ - + ]: 1 : if (psf)
2655 [ # # ][ # # ]: 0 : while (pos && (psf = igmp_mcf_get_next(seq, psf)) != NULL)
2656 : 0 : --pos;
2657 [ + ]: 1 : return pos ? NULL : psf;
2658 : : }
2659 : :
2660 : 0 : static void *igmp_mcf_seq_start(struct seq_file *seq, loff_t *pos)
2661 : : __acquires(rcu)
2662 : : {
2663 : : rcu_read_lock();
2664 [ + + ]: 2 : return *pos ? igmp_mcf_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
2665 : : }
2666 : :
2667 : 0 : static void *igmp_mcf_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2668 : : {
2669 : : struct ip_sf_list *psf;
2670 [ + - ]: 1 : if (v == SEQ_START_TOKEN)
2671 : : psf = igmp_mcf_get_first(seq);
2672 : : else
2673 : 0 : psf = igmp_mcf_get_next(seq, v);
2674 : 1 : ++*pos;
2675 : 1 : return psf;
2676 : : }
2677 : :
2678 : 0 : static void igmp_mcf_seq_stop(struct seq_file *seq, void *v)
2679 : : __releases(rcu)
2680 : : {
2681 : 2 : struct igmp_mcf_iter_state *state = igmp_mcf_seq_private(seq);
2682 [ - + ]: 2 : if (likely(state->im != NULL)) {
2683 : : spin_unlock_bh(&state->im->lock);
2684 : 0 : state->im = NULL;
2685 : : }
2686 : 0 : state->idev = NULL;
2687 : 0 : state->dev = NULL;
2688 : : rcu_read_unlock();
2689 : 2 : }
2690 : :
2691 : 0 : static int igmp_mcf_seq_show(struct seq_file *seq, void *v)
2692 : : {
2693 : : struct ip_sf_list *psf = (struct ip_sf_list *)v;
2694 : 1 : struct igmp_mcf_iter_state *state = igmp_mcf_seq_private(seq);
2695 : :
2696 [ + - ]: 1 : if (v == SEQ_START_TOKEN) {
2697 : 1 : seq_printf(seq,
2698 : : "%3s %6s "
2699 : : "%10s %10s %6s %6s\n", "Idx",
2700 : : "Device", "MCA",
2701 : : "SRC", "INC", "EXC");
2702 : : } else {
2703 [ # # ][ # # ]: 0 : seq_printf(seq,
2704 : : "%3d %6.6s 0x%08x "
2705 : : "0x%08x %6lu %6lu\n",
2706 : 0 : state->dev->ifindex, state->dev->name,
2707 : 0 : ntohl(state->im->multiaddr),
2708 : 0 : ntohl(psf->sf_inaddr),
2709 : : psf->sf_count[MCAST_INCLUDE],
2710 : : psf->sf_count[MCAST_EXCLUDE]);
2711 : : }
2712 : 1 : return 0;
2713 : : }
2714 : :
2715 : : static const struct seq_operations igmp_mcf_seq_ops = {
2716 : : .start = igmp_mcf_seq_start,
2717 : : .next = igmp_mcf_seq_next,
2718 : : .stop = igmp_mcf_seq_stop,
2719 : : .show = igmp_mcf_seq_show,
2720 : : };
2721 : :
2722 : 0 : static int igmp_mcf_seq_open(struct inode *inode, struct file *file)
2723 : : {
2724 : 1 : return seq_open_net(inode, file, &igmp_mcf_seq_ops,
2725 : : sizeof(struct igmp_mcf_iter_state));
2726 : : }
2727 : :
2728 : : static const struct file_operations igmp_mcf_seq_fops = {
2729 : : .owner = THIS_MODULE,
2730 : : .open = igmp_mcf_seq_open,
2731 : : .read = seq_read,
2732 : : .llseek = seq_lseek,
2733 : : .release = seq_release_net,
2734 : : };
2735 : :
2736 : 0 : static int __net_init igmp_net_init(struct net *net)
2737 : : {
2738 : : struct proc_dir_entry *pde;
2739 : :
2740 : 0 : pde = proc_create("igmp", S_IRUGO, net->proc_net, &igmp_mc_seq_fops);
2741 [ # # ]: 0 : if (!pde)
2742 : : goto out_igmp;
2743 : 0 : pde = proc_create("mcfilter", S_IRUGO, net->proc_net,
2744 : : &igmp_mcf_seq_fops);
2745 [ # # ]: 0 : if (!pde)
2746 : : goto out_mcfilter;
2747 : : return 0;
2748 : :
2749 : : out_mcfilter:
2750 : 0 : remove_proc_entry("igmp", net->proc_net);
2751 : : out_igmp:
2752 : : return -ENOMEM;
2753 : : }
2754 : :
2755 : 0 : static void __net_exit igmp_net_exit(struct net *net)
2756 : : {
2757 : 0 : remove_proc_entry("mcfilter", net->proc_net);
2758 : 0 : remove_proc_entry("igmp", net->proc_net);
2759 : 0 : }
2760 : :
2761 : : static struct pernet_operations igmp_net_ops = {
2762 : : .init = igmp_net_init,
2763 : : .exit = igmp_net_exit,
2764 : : };
2765 : : #endif
2766 : :
2767 : 0 : static int igmp_netdev_event(struct notifier_block *this,
2768 : : unsigned long event, void *ptr)
2769 : : {
2770 : 0 : struct net_device *dev = netdev_notifier_info_to_dev(ptr);
2771 : : struct in_device *in_dev;
2772 : :
2773 [ # # ]: 0 : switch (event) {
2774 : : case NETDEV_RESEND_IGMP:
2775 : : in_dev = __in_dev_get_rtnl(dev);
2776 [ # # ]: 0 : if (in_dev)
2777 : 0 : ip_mc_rejoin_groups(in_dev);
2778 : : break;
2779 : : default:
2780 : : break;
2781 : : }
2782 : 0 : return NOTIFY_DONE;
2783 : : }
2784 : :
2785 : : static struct notifier_block igmp_notifier = {
2786 : : .notifier_call = igmp_netdev_event,
2787 : : };
2788 : :
2789 : 0 : int __init igmp_mc_init(void)
2790 : : {
2791 : : #if defined(CONFIG_PROC_FS)
2792 : : int err;
2793 : :
2794 : 0 : err = register_pernet_subsys(&igmp_net_ops);
2795 [ # # ]: 0 : if (err)
2796 : : return err;
2797 : 0 : err = register_netdevice_notifier(&igmp_notifier);
2798 [ # # ]: 0 : if (err)
2799 : : goto reg_notif_fail;
2800 : : return 0;
2801 : :
2802 : : reg_notif_fail:
2803 : 0 : unregister_pernet_subsys(&igmp_net_ops);
2804 : 0 : return err;
2805 : : #else
2806 : : return register_netdevice_notifier(&igmp_notifier);
2807 : : #endif
2808 : : }
|