leaving function in locked state
File: net/ipv4/.tmp_igmp.o.preproc
Full description: {AutomatonChecker of /usr/share/stanse/checkers/AutomatonChecker/kernel_locking_irq.xml} in function 'igmp_mcf_seq_next' leaving function in locked state [traces: 1]
Importance: 1
Checker: AutomatonChecker of /usr/share/stanse/checkers/AutomatonChecker/kernel_locking_irq.xml
Trace:
line 2325: not affected ==> the lock is still locked.
line 2326: not affected ==> the lock is still locked.
line 2326: not affected ==> the lock is still locked.
line 2327: not affected ==> the lock is still locked.
line 2328: not affected ==> the lock is still locked.
line 2329: not affected ==> the lock is still locked.
line 2334: not affected ==> the lock is still locked.
line 2335: not affected ==> the lock is still locked.
line 2385: not affected ==> the lock is still locked.
line 2388: not affected ==> the lock is still locked.
line 2389: not affected ==> the lock is still locked.
line 2390: Leaving function in locked state.[& . * im_1 lock]
This one is:
False positive index (the lower the better): 0
File contents (this file is distributed under the terms specified in the original file):
1|static void igmpv3_add_delrec(struct in_device *in_dev, struct ip_mc_list *im);
2|static void igmpv3_del_delrec(struct in_device *in_dev, __be32 multiaddr);
3|static void igmpv3_clear_delrec(struct in_device *in_dev);
4|static int sf_setstate(struct ip_mc_list *pmc);
5|static void sf_markstate(struct ip_mc_list *pmc);
6|
7|static void ip_mc_clear_src(struct ip_mc_list *pmc);
8|static int ip_mc_add_src(struct in_device *in_dev, __be32 *pmca, int sfmode,
9| int sfcount, __be32 *psfsrc, int delta);
10|
11|
12|static void ip_mc_list_reclaim(struct rcu_head *head)
13|{
14| kfree(({ const typeof( ((struct ip_mc_list *)0)->rcu ) *__mptr = (head); (struct ip_mc_list *)( (char *)__mptr - 1 );}));
15|}
16|
17|static void ip_ma_put(struct ip_mc_list *im)
18|{
19| if (atomic_dec_and_test(&im->refcnt)) {
20| in_dev_put(im->interface);
21| call_rcu_sched(&im->rcu, ip_mc_list_reclaim);
22| }
23|}
24|static void igmp_stop_timer(struct ip_mc_list *im)
25|{
26| __st_spin_lock_bh_st__(&im->lock);
27| if (del_timer(&im->timer))
28| atomic_dec(&im->refcnt);
29| im->tm_running = 0;
30| im->reporter = 0;
31| im->unsolicit_count = 0;
32| __st_spin_unlock_bh_st__(&im->lock);
33|}
34|
35|
36|static void igmp_start_timer(struct ip_mc_list *im, int max_delay)
37|{
38| int tv = random32() % max_delay;
39|
40| im->tm_running = 1;
41| if (!mod_timer(&im->timer, jiffies+tv+2))
42| atomic_inc(&im->refcnt);
43|}
44|
45|static void igmp_gq_start_timer(struct in_device *in_dev)
46|{
47| int tv = random32() % in_dev->mr_maxdelay;
48|
49| in_dev->mr_gq_running = 1;
50| if (!mod_timer(&in_dev->mr_gq_timer, jiffies+tv+2))
51| atomic_inc(&(in_dev)->refcnt);
52|}
53|
54|static void igmp_ifc_start_timer(struct in_device *in_dev, int delay)
55|{
56| int tv = random32() % delay;
57|
58| if (!mod_timer(&in_dev->mr_ifc_timer, jiffies+tv+2))
59| atomic_inc(&(in_dev)->refcnt);
60|}
61|
62|static void igmp_mod_timer(struct ip_mc_list *im, int max_delay)
63|{
64| __st_spin_lock_bh_st__(&im->lock);
65| im->unsolicit_count = 0;
66| if (del_timer(&im->timer)) {
67| if ((long)(im->timer.expires-jiffies) < max_delay) {
68| add_timer(&im->timer);
69| im->tm_running = 1;
70| __st_spin_unlock_bh_st__(&im->lock);
71| return;
72| }
73| atomic_dec(&im->refcnt);
74| }
75| igmp_start_timer(im, max_delay);
76| __st_spin_unlock_bh_st__(&im->lock);
77|}
78|static int is_in(struct ip_mc_list *pmc, struct ip_sf_list *psf, int type,
79| int gdeleted, int sdeleted)
80|{
81| switch (type) {
82| case 1:
83| case 2:
84| if (gdeleted || sdeleted)
85| return 0;
86| if (!(pmc->gsquery && !psf->sf_gsresp)) {
87| if (pmc->sfmode == 1)
88| return 1;
89|
90|
91|
92| if (psf->sf_count[1])
93| return type == 1;
94| return pmc->sfcount[0] ==
95| psf->sf_count[0];
96| }
97| return 0;
98| case 3:
99| if (gdeleted || sdeleted)
100| return 0;
101| return psf->sf_count[1] != 0;
102| case 4:
103| if (gdeleted || sdeleted)
104| return 0;
105| if (pmc->sfcount[0] == 0 ||
106| psf->sf_count[1])
107| return 0;
108| return pmc->sfcount[0] ==
109| psf->sf_count[0];
110| case 5:
111| if (gdeleted || !psf->sf_crcount)
112| return 0;
113| return (pmc->sfmode == 1) ^ sdeleted;
114| case 6:
115| if (pmc->sfmode == 1)
116| return gdeleted || (psf->sf_crcount && sdeleted);
117| return psf->sf_crcount && !gdeleted && !sdeleted;
118| }
119| return 0;
120|}
121|
122|static int
123|igmp_scount(struct ip_mc_list *pmc, int type, int gdeleted, int sdeleted)
124|{
125| struct ip_sf_list *psf;
126| int scount = 0;
127|
128| for (psf=pmc->sources; psf; psf=psf->sf_next) {
129| if (!is_in(pmc, psf, type, gdeleted, sdeleted))
130| continue;
131| scount++;
132| }
133| return scount;
134|}
135|
136|
137|
138|static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size)
139|{
140| struct sk_buff *skb;
141| struct rtable *rt;
142| struct iphdr *pip;
143| struct igmpv3_report *pig;
144| struct net *net = dev_net(dev);
145|
146| while (1) {
147| skb = alloc_skb(size + ((((dev)->hard_header_len+(dev)->needed_headroom+(dev)->needed_tailroom)&~(16 - 1)) + 16),
148| ((( gfp_t)0x20u)) | (( gfp_t)0x200u));
149| if (skb)
150| break;
151| size >>= 1;
152| if (size < 256)
153| return ((void *)0);
154| }
155| (*(unsigned int *)((skb)->cb)) = size;
156|
157| {
158| struct flowi fl = { .oif = dev->ifindex,
159| .nl_u.ip4_u.daddr = (( __be32)(__builtin_constant_p((__u32)((0xE0000016L))) ? ((__u32)( (((__u32)((0xE0000016L)) & (__u32)0x000000ffUL) << 24) | (((__u32)((0xE0000016L)) & (__u32)0x0000ff00UL) << 8) | (((__u32)((0xE0000016L)) & (__u32)0x00ff0000UL) >> 8) | (((__u32)((0xE0000016L)) & (__u32)0xff000000UL) >> 24))) : __fswab32((0xE0000016L)))),
160| .proto = IPPROTO_IGMP };
161| if (ip_route_output_key(net, &rt, &fl)) {
162| kfree_skb(skb);
163| return ((void *)0);
164| }
165| }
166| if (rt->rt_src == 0) {
167| kfree_skb(skb);
168| ip_rt_put(rt);
169| return ((void *)0);
170| }
171|
172| skb_dst_set(skb, &rt->dst);
173| skb->dev = dev;
174|
175| skb_reserve(skb, ((((dev)->hard_header_len+(dev)->needed_headroom)&~(16 - 1)) + 16));
176|
177| skb_reset_network_header(skb);
178| pip = ip_hdr(skb);
179| skb_put(skb, sizeof(struct iphdr) + 4);
180|
181| pip->version = 4;
182| pip->ihl = (sizeof(struct iphdr)+4)>>2;
183| pip->tos = 0xc0;
184| pip->frag_off = (( __be16)(__builtin_constant_p((__u16)((0x4000))) ? ((__u16)( (((__u16)((0x4000)) & (__u16)0x00ffU) << 8) | (((__u16)((0x4000)) & (__u16)0xff00U) >> 8))) : __fswab16((0x4000))));
185| pip->ttl = 1;
186| pip->daddr = rt->rt_dst;
187| pip->saddr = rt->rt_src;
188| pip->protocol = IPPROTO_IGMP;
189| pip->tot_len = 0;
190| ip_select_ident(pip, &rt->dst, ((void *)0));
191| ((u8*)&pip[1])[0] = (20|0x00|0x80);
192| ((u8*)&pip[1])[1] = 4;
193| ((u8*)&pip[1])[2] = 0;
194| ((u8*)&pip[1])[3] = 0;
195|
196| skb->transport_header = skb->network_header + sizeof(struct iphdr) + 4;
197| skb_put(skb, sizeof(*pig));
198| pig = igmpv3_report_hdr(skb);
199| pig->type = 0x22;
200| pig->resv1 = 0;
201| pig->csum = 0;
202| pig->resv2 = 0;
203| pig->ngrec = 0;
204| return skb;
205|}
206|
207|static int igmpv3_sendpack(struct sk_buff *skb)
208|{
209| struct igmphdr *pig = igmp_hdr(skb);
210| const int igmplen = skb->tail - skb->transport_header;
211|
212| pig->csum = ip_compute_csum(igmp_hdr(skb), igmplen);
213|
214| return ip_local_out(skb);
215|}
216|
217|static int grec_size(struct ip_mc_list *pmc, int type, int gdel, int sdel)
218|{
219| return sizeof(struct igmpv3_grec) + 4*igmp_scount(pmc, type, gdel, sdel);
220|}
221|
222|static struct sk_buff *add_grhead(struct sk_buff *skb, struct ip_mc_list *pmc,
223| int type, struct igmpv3_grec **ppgr)
224|{
225| struct net_device *dev = pmc->interface->dev;
226| struct igmpv3_report *pih;
227| struct igmpv3_grec *pgr;
228|
229| if (!skb)
230| skb = igmpv3_newpack(dev, dev->mtu);
231| if (!skb)
232| return ((void *)0);
233| pgr = (struct igmpv3_grec *)skb_put(skb, sizeof(struct igmpv3_grec));
234| pgr->grec_type = type;
235| pgr->grec_auxwords = 0;
236| pgr->grec_nsrcs = 0;
237| pgr->grec_mca = pmc->multiaddr;
238| pih = igmpv3_report_hdr(skb);
239| pih->ngrec = (( __be16)(__builtin_constant_p((__u16)(((__builtin_constant_p((__u16)(( __u16)(__be16)(pih->ngrec))) ? ((__u16)( (((__u16)(( __u16)(__be16)(pih->ngrec)) & (__u16)0x00ffU) << 8) | (((__u16)(( __u16)(__be16)(pih->ngrec)) & (__u16)0xff00U) >> 8))) : __fswab16(( __u16)(__be16)(pih->ngrec)))+1))) ? ((__u16)( (((__u16)(((__builtin_constant_p((__u16)(( __u16)(__be16)(pih->ngrec))) ? ((__u16)( (((__u16)(( __u16)(__be16)(pih->ngrec)) & (__u16)0x00ffU) << 8) | (((__u16)(( __u16)(__be16)(pih->ngrec)) & (__u16)0xff00U) >> 8))) : __fswab16(( __u16)(__be16)(pih->ngrec)))+1)) & (__u16)0x00ffU) << 8) | (((__u16)(((__builtin_constant_p((__u16)(( __u16)(__be16)(pih->ngrec))) ? ((__u16)( (((__u16)(( __u16)(__be16)(pih->ngrec)) & (__u16)0x00ffU) << 8) | (((__u16)(( __u16)(__be16)(pih->ngrec)) & (__u16)0xff00U) >> 8))) : __fswab16(( __u16)(__be16)(pih->ngrec)))+1)) & (__u16)0xff00U) >> 8))) : __fswab16(((__builtin_constant_p((__u16)(( __u16)(__be16)(pih->ngrec))) ? ((__u16)( (((__u16)(( __u16)(__be16)(pih->ngrec)) & (__u16)0x00ffU) << 8) | (((__u16)(( __u16)(__be16)(pih->ngrec)) & (__u16)0xff00U) >> 8))) : __fswab16(( __u16)(__be16)(pih->ngrec)))+1))));
240| *ppgr = pgr;
241| return skb;
242|}
243|
244|
245|
246|
247|static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc,
248| int type, int gdeleted, int sdeleted)
249|{
250| struct net_device *dev = pmc->interface->dev;
251| struct igmpv3_report *pih;
252| struct igmpv3_grec *pgr = ((void *)0);
253| struct ip_sf_list *psf, *psf_next, *psf_prev, **psf_list;
254| int scount, stotal, first, isquery, truncate;
255|
256| if (pmc->multiaddr == (( __be32)(__builtin_constant_p((__u32)((0xE0000001L))) ? ((__u32)( (((__u32)((0xE0000001L)) & (__u32)0x000000ffUL) << 24) | (((__u32)((0xE0000001L)) & (__u32)0x0000ff00UL) << 8) | (((__u32)((0xE0000001L)) & (__u32)0x00ff0000UL) >> 8) | (((__u32)((0xE0000001L)) & (__u32)0xff000000UL) >> 24))) : __fswab32((0xE0000001L)))))
257| return skb;
258|
259| isquery = type == 1 ||
260| type == 2;
261| truncate = type == 2 ||
262| type == 4;
263|
264| stotal = scount = 0;
265|
266| psf_list = sdeleted ? &pmc->tomb : &pmc->sources;
267|
268| if (!*psf_list)
269| goto empty_source;
270|
271| pih = skb ? igmpv3_report_hdr(skb) : ((void *)0);
272|
273|
274| if (truncate) {
275| if (pih && pih->ngrec &&
276| ((skb) ? ((skb)->dev ? (*(unsigned int *)((skb)->cb)) - (skb)->len : skb_tailroom(skb)) : 0) < grec_size(pmc, type, gdeleted, sdeleted)) {
277| if (skb)
278| igmpv3_sendpack(skb);
279| skb = igmpv3_newpack(dev, dev->mtu);
280| }
281| }
282| first = 1;
283| psf_prev = ((void *)0);
284| for (psf=*psf_list; psf; psf=psf_next) {
285| __be32 *psrc;
286|
287| psf_next = psf->sf_next;
288|
289| if (!is_in(pmc, psf, type, gdeleted, sdeleted)) {
290| psf_prev = psf;
291| continue;
292| }
293|
294|
295| if (isquery)
296| psf->sf_gsresp = 0;
297|
298| if (((skb) ? ((skb)->dev ? (*(unsigned int *)((skb)->cb)) - (skb)->len : skb_tailroom(skb)) : 0) < sizeof(__be32) +
299| first*sizeof(struct igmpv3_grec)) {
300| if (truncate && !first)
301| break;
302| if (pgr)
303| pgr->grec_nsrcs = (( __be16)(__builtin_constant_p((__u16)((scount))) ? ((__u16)( (((__u16)((scount)) & (__u16)0x00ffU) << 8) | (((__u16)((scount)) & (__u16)0xff00U) >> 8))) : __fswab16((scount))));
304| if (skb)
305| igmpv3_sendpack(skb);
306| skb = igmpv3_newpack(dev, dev->mtu);
307| first = 1;
308| scount = 0;
309| }
310| if (first) {
311| skb = add_grhead(skb, pmc, type, &pgr);
312| first = 0;
313| }
314| if (!skb)
315| return ((void *)0);
316| psrc = (__be32 *)skb_put(skb, sizeof(__be32));
317| *psrc = psf->sf_inaddr;
318| scount++; stotal++;
319| if ((type == 5 ||
320| type == 6) && psf->sf_crcount) {
321| psf->sf_crcount--;
322| if ((sdeleted || gdeleted) && psf->sf_crcount == 0) {
323| if (psf_prev)
324| psf_prev->sf_next = psf->sf_next;
325| else
326| *psf_list = psf->sf_next;
327| kfree(psf);
328| continue;
329| }
330| }
331| psf_prev = psf;
332| }
333|
334|empty_source:
335| if (!stotal) {
336| if (type == 5 ||
337| type == 6)
338| return skb;
339| if (pmc->crcount || isquery) {
340|
341| if (skb && ((skb) ? ((skb)->dev ? (*(unsigned int *)((skb)->cb)) - (skb)->len : skb_tailroom(skb)) : 0) 342| igmpv3_sendpack(skb);
343| skb = ((void *)0);
344| }
345| skb = add_grhead(skb, pmc, type, &pgr);
346| }
347| }
348| if (pgr)
349| pgr->grec_nsrcs = (( __be16)(__builtin_constant_p((__u16)((scount))) ? ((__u16)( (((__u16)((scount)) & (__u16)0x00ffU) << 8) | (((__u16)((scount)) & (__u16)0xff00U) >> 8))) : __fswab16((scount))));
350|
351| if (isquery)
352| pmc->gsquery = 0;
353| return skb;
354|}
355|
356|static int igmpv3_send_report(struct in_device *in_dev, struct ip_mc_list *pmc)
357|{
358| struct sk_buff *skb = ((void *)0);
359| int type;
360|
361| if (!pmc) {
362| __st_rcu_read_lock_st__();
363| for (pmc = ({ typeof(*(in_dev->mc_list)) *_________p1 = (typeof(*(in_dev->mc_list))* )(*(volatile typeof((in_dev->mc_list)) *)&((in_dev->mc_list))); do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !(rcu_read_lock_held() || (0))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 530); } } while (0); ; do { } while (0); ((typeof(*(in_dev->mc_list)) *)(_________p1)); }); pmc != ((void *)0); pmc = ({ typeof(*(pmc->next_rcu)) *_________p1 = (typeof(*(pmc->next_rcu))* )(*(volatile typeof((pmc->next_rcu)) *)&((pmc->next_rcu))); do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !(rcu_read_lock_held() || (0))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 530); } } while (0); ; do { } while (0); ((typeof(*(pmc->next_rcu)) *)(_________p1)); })) {
364| if (pmc->multiaddr == (( __be32)(__builtin_constant_p((__u32)((0xE0000001L))) ? ((__u32)( (((__u32)((0xE0000001L)) & (__u32)0x000000ffUL) << 24) | (((__u32)((0xE0000001L)) & (__u32)0x0000ff00UL) << 8) | (((__u32)((0xE0000001L)) & (__u32)0x00ff0000UL) >> 8) | (((__u32)((0xE0000001L)) & (__u32)0xff000000UL) >> 24))) : __fswab32((0xE0000001L)))))
365| continue;
366| __st_spin_lock_bh_st__(&pmc->lock);
367| if (pmc->sfcount[0])
368| type = 2;
369| else
370| type = 1;
371| skb = add_grec(skb, pmc, type, 0, 0);
372| __st_spin_unlock_bh_st__(&pmc->lock);
373| }
374| __st_rcu_read_unlock_st__();
375| } else {
376| __st_spin_lock_bh_st__(&pmc->lock);
377| if (pmc->sfcount[0])
378| type = 2;
379| else
380| type = 1;
381| skb = add_grec(skb, pmc, type, 0, 0);
382| __st_spin_unlock_bh_st__(&pmc->lock);
383| }
384| if (!skb)
385| return 0;
386| return igmpv3_sendpack(skb);
387|}
388|
389|
390|
391|
392|static void igmpv3_clear_zeros(struct ip_sf_list **ppsf)
393|{
394| struct ip_sf_list *psf_prev, *psf_next, *psf;
395|
396| psf_prev = ((void *)0);
397| for (psf=*ppsf; psf; psf = psf_next) {
398| psf_next = psf->sf_next;
399| if (psf->sf_crcount == 0) {
400| if (psf_prev)
401| psf_prev->sf_next = psf->sf_next;
402| else
403| *ppsf = psf->sf_next;
404| kfree(psf);
405| } else
406| psf_prev = psf;
407| }
408|}
409|
410|static void igmpv3_send_cr(struct in_device *in_dev)
411|{
412| struct ip_mc_list *pmc, *pmc_prev, *pmc_next;
413| struct sk_buff *skb = ((void *)0);
414| int type, dtype;
415|
416| __st_rcu_read_lock_st__();
417| __st_spin_lock_bh_st__(&in_dev->mc_tomb_lock);
418|
419|
420| pmc_prev = ((void *)0);
421| for (pmc=in_dev->mc_tomb; pmc; pmc=pmc_next) {
422| pmc_next = pmc->next;
423| if (pmc->sfmode == 1) {
424| type = 6;
425| dtype = 6;
426| skb = add_grec(skb, pmc, type, 1, 0);
427| skb = add_grec(skb, pmc, dtype, 1, 1);
428| }
429| if (pmc->crcount) {
430| if (pmc->sfmode == 0) {
431| type = 3;
432| skb = add_grec(skb, pmc, type, 1, 0);
433| }
434| pmc->crcount--;
435| if (pmc->crcount == 0) {
436| igmpv3_clear_zeros(&pmc->tomb);
437| igmpv3_clear_zeros(&pmc->sources);
438| }
439| }
440| if (pmc->crcount == 0 && !pmc->tomb && !pmc->sources) {
441| if (pmc_prev)
442| pmc_prev->next = pmc_next;
443| else
444| in_dev->mc_tomb = pmc_next;
445| in_dev_put(pmc->interface);
446| kfree(pmc);
447| } else
448| pmc_prev = pmc;
449| }
450| __st_spin_unlock_bh_st__(&in_dev->mc_tomb_lock);
451|
452|
453| for (pmc = ({ typeof(*(in_dev->mc_list)) *_________p1 = (typeof(*(in_dev->mc_list))* )(*(volatile typeof((in_dev->mc_list)) *)&((in_dev->mc_list))); do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !(rcu_read_lock_held() || (0))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 620); } } while (0); ; do { } while (0); ((typeof(*(in_dev->mc_list)) *)(_________p1)); }); pmc != ((void *)0); pmc = ({ typeof(*(pmc->next_rcu)) *_________p1 = (typeof(*(pmc->next_rcu))* )(*(volatile typeof((pmc->next_rcu)) *)&((pmc->next_rcu))); do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !(rcu_read_lock_held() || (0))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 620); } } while (0); ; do { } while (0); ((typeof(*(pmc->next_rcu)) *)(_________p1)); })) {
454| __st_spin_lock_bh_st__(&pmc->lock);
455| if (pmc->sfcount[0]) {
456| type = 6;
457| dtype = 5;
458| } else {
459| type = 5;
460| dtype = 6;
461| }
462| skb = add_grec(skb, pmc, type, 0, 0);
463| skb = add_grec(skb, pmc, dtype, 0, 1);
464|
465|
466| if (pmc->crcount) {
467| if (pmc->sfmode == 0)
468| type = 4;
469| else
470| type = 3;
471| skb = add_grec(skb, pmc, type, 0, 0);
472| pmc->crcount--;
473| }
474| __st_spin_unlock_bh_st__(&pmc->lock);
475| }
476| __st_rcu_read_unlock_st__();
477|
478| if (!skb)
479| return;
480| (void) igmpv3_sendpack(skb);
481|}
482|
483|static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc,
484| int type)
485|{
486| struct sk_buff *skb;
487| struct iphdr *iph;
488| struct igmphdr *ih;
489| struct rtable *rt;
490| struct net_device *dev = in_dev->dev;
491| struct net *net = dev_net(dev);
492| __be32 group = pmc ? pmc->multiaddr : 0;
493| __be32 dst;
494|
495| if (type == 0x22)
496| return igmpv3_send_report(in_dev, pmc);
497| else if (type == 0x17)
498| dst = (( __be32)(__builtin_constant_p((__u32)((0xE0000002L))) ? ((__u32)( (((__u32)((0xE0000002L)) & (__u32)0x000000ffUL) << 24) | (((__u32)((0xE0000002L)) & (__u32)0x0000ff00UL) << 8) | (((__u32)((0xE0000002L)) & (__u32)0x00ff0000UL) >> 8) | (((__u32)((0xE0000002L)) & (__u32)0xff000000UL) >> 24))) : __fswab32((0xE0000002L))));
499| else
500| dst = group;
501|
502| {
503| struct flowi fl = { .oif = dev->ifindex,
504| .nl_u.ip4_u.daddr = dst,
505| .proto = IPPROTO_IGMP };
506| if (ip_route_output_key(net, &rt, &fl))
507| return -1;
508| }
509| if (rt->rt_src == 0) {
510| ip_rt_put(rt);
511| return -1;
512| }
513|
514| skb = alloc_skb((sizeof(struct igmphdr)+sizeof(struct iphdr)+4)+((((dev)->hard_header_len+(dev)->needed_headroom+(dev)->needed_tailroom)&~(16 - 1)) + 16), ((( gfp_t)0x20u)));
515| if (skb == ((void *)0)) {
516| ip_rt_put(rt);
517| return -1;
518| }
519|
520| skb_dst_set(skb, &rt->dst);
521|
522| skb_reserve(skb, ((((dev)->hard_header_len+(dev)->needed_headroom)&~(16 - 1)) + 16));
523|
524| skb_reset_network_header(skb);
525| iph = ip_hdr(skb);
526| skb_put(skb, sizeof(struct iphdr) + 4);
527|
528| iph->version = 4;
529| iph->ihl = (sizeof(struct iphdr)+4)>>2;
530| iph->tos = 0xc0;
531| iph->frag_off = (( __be16)(__builtin_constant_p((__u16)((0x4000))) ? ((__u16)( (((__u16)((0x4000)) & (__u16)0x00ffU) << 8) | (((__u16)((0x4000)) & (__u16)0xff00U) >> 8))) : __fswab16((0x4000))));
532| iph->ttl = 1;
533| iph->daddr = dst;
534| iph->saddr = rt->rt_src;
535| iph->protocol = IPPROTO_IGMP;
536| ip_select_ident(iph, &rt->dst, ((void *)0));
537| ((u8*)&iph[1])[0] = (20|0x00|0x80);
538| ((u8*)&iph[1])[1] = 4;
539| ((u8*)&iph[1])[2] = 0;
540| ((u8*)&iph[1])[3] = 0;
541|
542| ih = (struct igmphdr *)skb_put(skb, sizeof(struct igmphdr));
543| ih->type = type;
544| ih->code = 0;
545| ih->csum = 0;
546| ih->group = group;
547| ih->csum = ip_compute_csum((void *)ih, sizeof(struct igmphdr));
548|
549| return ip_local_out(skb);
550|}
551|
552|static void igmp_gq_timer_expire(unsigned long data)
553|{
554| struct in_device *in_dev = (struct in_device *)data;
555|
556| in_dev->mr_gq_running = 0;
557| igmpv3_send_report(in_dev, ((void *)0));
558| atomic_dec(&(in_dev)->refcnt);
559|}
560|
561|static void igmp_ifc_timer_expire(unsigned long data)
562|{
563| struct in_device *in_dev = (struct in_device *)data;
564|
565| igmpv3_send_cr(in_dev);
566| if (in_dev->mr_ifc_count) {
567| in_dev->mr_ifc_count--;
568| igmp_ifc_start_timer(in_dev, (10*250));
569| }
570| atomic_dec(&(in_dev)->refcnt);
571|}
572|
573|static void igmp_ifc_event(struct in_device *in_dev)
574|{
575| if (((((*(dev_net(in_dev->dev))->ipv4.devconf_all)).data[IPV4_DEVCONF_FORCE_IGMP_VERSION - 1]) == 1 || ipv4_devconf_get(((in_dev)), IPV4_DEVCONF_FORCE_IGMP_VERSION) == 1 || ((in_dev)->mr_v1_seen && (({ unsigned long __dummy; typeof((in_dev)->mr_v1_seen) __dummy2; (void)(&__dummy == &__dummy2); 1; }) && ({ unsigned long __dummy; typeof(jiffies) __dummy2; (void)(&__dummy == &__dummy2); 1; }) && ((long)(jiffies) - (long)((in_dev)->mr_v1_seen) < 0)))) || ((((*(dev_net(in_dev->dev))->ipv4.devconf_all)).data[IPV4_DEVCONF_FORCE_IGMP_VERSION - 1]) == 2 || ipv4_devconf_get(((in_dev)), IPV4_DEVCONF_FORCE_IGMP_VERSION) == 2 || ((in_dev)->mr_v2_seen && (({ unsigned long __dummy; typeof((in_dev)->mr_v2_seen) __dummy2; (void)(&__dummy == &__dummy2); 1; }) && ({ unsigned long __dummy; typeof(jiffies) __dummy2; (void)(&__dummy == &__dummy2); 1; }) && ((long)(jiffies) - (long)((in_dev)->mr_v2_seen) < 0)))))
576| return;
577| in_dev->mr_ifc_count = in_dev->mr_qrv ? in_dev->mr_qrv :
578| 2;
579| igmp_ifc_start_timer(in_dev, 1);
580|}
581|
582|
583|static void igmp_timer_expire(unsigned long data)
584|{
585| struct ip_mc_list *im=(struct ip_mc_list *)data;
586| struct in_device *in_dev = im->interface;
587|
588| __st_spin_lock_st__(&im->lock);
589| im->tm_running = 0;
590|
591| if (im->unsolicit_count) {
592| im->unsolicit_count--;
593| igmp_start_timer(im, (10*250));
594| }
595| im->reporter = 1;
596| __st_spin_unlock_st__(&im->lock);
597|
598| if (((((*(dev_net(in_dev->dev))->ipv4.devconf_all)).data[IPV4_DEVCONF_FORCE_IGMP_VERSION - 1]) == 1 || ipv4_devconf_get(((in_dev)), IPV4_DEVCONF_FORCE_IGMP_VERSION) == 1 || ((in_dev)->mr_v1_seen && (({ unsigned long __dummy; typeof((in_dev)->mr_v1_seen) __dummy2; (void)(&__dummy == &__dummy2); 1; }) && ({ unsigned long __dummy; typeof(jiffies) __dummy2; (void)(&__dummy == &__dummy2); 1; }) && ((long)(jiffies) - (long)((in_dev)->mr_v1_seen) < 0)))))
599| igmp_send_report(in_dev, im, 0x12);
600| else if (((((*(dev_net(in_dev->dev))->ipv4.devconf_all)).data[IPV4_DEVCONF_FORCE_IGMP_VERSION - 1]) == 2 || ipv4_devconf_get(((in_dev)), IPV4_DEVCONF_FORCE_IGMP_VERSION) == 2 || ((in_dev)->mr_v2_seen && (({ unsigned long __dummy; typeof((in_dev)->mr_v2_seen) __dummy2; (void)(&__dummy == &__dummy2); 1; }) && ({ unsigned long __dummy; typeof(jiffies) __dummy2; (void)(&__dummy == &__dummy2); 1; }) && ((long)(jiffies) - (long)((in_dev)->mr_v2_seen) < 0)))))
601| igmp_send_report(in_dev, im, 0x16);
602| else
603| igmp_send_report(in_dev, im, 0x22);
604|
605| ip_ma_put(im);
606|}
607|
608|
609|static int igmp_xmarksources(struct ip_mc_list *pmc, int nsrcs, __be32 *srcs)
610|{
611| struct ip_sf_list *psf;
612| int i, scount;
613|
614| scount = 0;
615| for (psf=pmc->sources; psf; psf=psf->sf_next) {
616| if (scount == nsrcs)
617| break;
618| for (i=0; i 619|
620| if (pmc->sfcount[1] ||
621| pmc->sfcount[0] !=
622| psf->sf_count[0])
623| continue;
624| if (srcs[i] == psf->sf_inaddr) {
625| scount++;
626| break;
627| }
628| }
629| }
630| pmc->gsquery = 0;
631| if (scount == nsrcs)
632| return 0;
633| return 1;
634|}
635|
636|static int igmp_marksources(struct ip_mc_list *pmc, int nsrcs, __be32 *srcs)
637|{
638| struct ip_sf_list *psf;
639| int i, scount;
640|
641| if (pmc->sfmode == 0)
642| return igmp_xmarksources(pmc, nsrcs, srcs);
643|
644|
645| scount = 0;
646| for (psf=pmc->sources; psf; psf=psf->sf_next) {
647| if (scount == nsrcs)
648| break;
649| for (i=0; i 650| if (srcs[i] == psf->sf_inaddr) {
651| psf->sf_gsresp = 1;
652| scount++;
653| break;
654| }
655| }
656| if (!scount) {
657| pmc->gsquery = 0;
658| return 0;
659| }
660| pmc->gsquery = 1;
661| return 1;
662|}
663|
664|static void igmp_heard_report(struct in_device *in_dev, __be32 group)
665|{
666| struct ip_mc_list *im;
667|
668|
669|
670| if (group == (( __be32)(__builtin_constant_p((__u32)((0xE0000001L))) ? ((__u32)( (((__u32)((0xE0000001L)) & (__u32)0x000000ffUL) << 24) | (((__u32)((0xE0000001L)) & (__u32)0x0000ff00UL) << 8) | (((__u32)((0xE0000001L)) & (__u32)0x00ff0000UL) >> 8) | (((__u32)((0xE0000001L)) & (__u32)0xff000000UL) >> 24))) : __fswab32((0xE0000001L)))))
671| return;
672|
673| __st_rcu_read_lock_st__();
674| for (im = ({ typeof(*(in_dev->mc_list)) *_________p1 = (typeof(*(in_dev->mc_list))* )(*(volatile typeof((in_dev->mc_list)) *)&((in_dev->mc_list))); do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !(rcu_read_lock_held() || (0))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 841); } } while (0); ; do { } while (0); ((typeof(*(in_dev->mc_list)) *)(_________p1)); }); im != ((void *)0); im = ({ typeof(*(im->next_rcu)) *_________p1 = (typeof(*(im->next_rcu))* )(*(volatile typeof((im->next_rcu)) *)&((im->next_rcu))); do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !(rcu_read_lock_held() || (0))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 841); } } while (0); ; do { } while (0); ((typeof(*(im->next_rcu)) *)(_________p1)); })) {
675| if (im->multiaddr == group) {
676| igmp_stop_timer(im);
677| break;
678| }
679| }
680| __st_rcu_read_unlock_st__();
681|}
682|
683|static void igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb,
684| int len)
685|{
686| struct igmphdr *ih = igmp_hdr(skb);
687| struct igmpv3_query *ih3 = igmpv3_query_hdr(skb);
688| struct ip_mc_list *im;
689| __be32 group = ih->group;
690| int max_delay;
691| int mark = 0;
692|
693|
694| if (len == 8) {
695| if (ih->code == 0) {
696|
697|
698| max_delay = (10*250);
699| in_dev->mr_v1_seen = jiffies +
700| (400*250);
701| group = 0;
702| } else {
703|
704| max_delay = ih->code*(250/10);
705| in_dev->mr_v2_seen = jiffies +
706| (400*250);
707| }
708|
709| in_dev->mr_ifc_count = 0;
710| if (del_timer(&in_dev->mr_ifc_timer))
711| atomic_dec(&(in_dev)->refcnt);
712|
713| igmpv3_clear_delrec(in_dev);
714| } else if (len < 12) {
715| return;
716| } else if (((((*(dev_net(in_dev->dev))->ipv4.devconf_all)).data[IPV4_DEVCONF_FORCE_IGMP_VERSION - 1]) == 1 || ipv4_devconf_get(((in_dev)), IPV4_DEVCONF_FORCE_IGMP_VERSION) == 1 || ((in_dev)->mr_v1_seen && (({ unsigned long __dummy; typeof((in_dev)->mr_v1_seen) __dummy2; (void)(&__dummy == &__dummy2); 1; }) && ({ unsigned long __dummy; typeof(jiffies) __dummy2; (void)(&__dummy == &__dummy2); 1; }) && ((long)(jiffies) - (long)((in_dev)->mr_v1_seen) < 0))))) {
717|
718| max_delay = (10*250);
719| group = 0;
720| } else if (((((*(dev_net(in_dev->dev))->ipv4.devconf_all)).data[IPV4_DEVCONF_FORCE_IGMP_VERSION - 1]) == 2 || ipv4_devconf_get(((in_dev)), IPV4_DEVCONF_FORCE_IGMP_VERSION) == 2 || ((in_dev)->mr_v2_seen && (({ unsigned long __dummy; typeof((in_dev)->mr_v2_seen) __dummy2; (void)(&__dummy == &__dummy2); 1; }) && ({ unsigned long __dummy; typeof(jiffies) __dummy2; (void)(&__dummy == &__dummy2); 1; }) && ((long)(jiffies) - (long)((in_dev)->mr_v2_seen) < 0))))) {
721|
722|
723|
724|
725|
726|
727| max_delay = ((ih3->code) < (0x80) ? (ih3->code) : ((((4)>=32 ? (ih3->code) : ((1<<(4))-1) & (ih3->code)) | (1<<(4))) << (((3)>=32 ? ((ih3->code) >> (4)) : ((1<<(3))-1) & ((ih3->code) >> (4))) + (3))))*(250/10);
728| } else {
729| if (!pskb_may_pull(skb, sizeof(struct igmpv3_query)))
730| return;
731|
732| ih3 = igmpv3_query_hdr(skb);
733| if (ih3->nsrcs) {
734| if (!pskb_may_pull(skb, sizeof(struct igmpv3_query)
735| + (__builtin_constant_p((__u16)(( __u16)(__be16)(ih3->nsrcs))) ? ((__u16)( (((__u16)(( __u16)(__be16)(ih3->nsrcs)) & (__u16)0x00ffU) << 8) | (((__u16)(( __u16)(__be16)(ih3->nsrcs)) & (__u16)0xff00U) >> 8))) : __fswab16(( __u16)(__be16)(ih3->nsrcs)))*sizeof(__be32)))
736| return;
737| ih3 = igmpv3_query_hdr(skb);
738| }
739|
740| max_delay = ((ih3->code) < (0x80) ? (ih3->code) : ((((4)>=32 ? (ih3->code) : ((1<<(4))-1) & (ih3->code)) | (1<<(4))) << (((3)>=32 ? ((ih3->code) >> (4)) : ((1<<(3))-1) & ((ih3->code) >> (4))) + (3))))*(250/10);
741| if (!max_delay)
742| max_delay = 1;
743| in_dev->mr_maxdelay = max_delay;
744| if (ih3->qrv)
745| in_dev->mr_qrv = ih3->qrv;
746| if (!group) {
747| if (ih3->nsrcs)
748| return;
749| igmp_gq_start_timer(in_dev);
750| return;
751| }
752|
753| mark = ih3->nsrcs != 0;
754| }
755| __st_rcu_read_lock_st__();
756| for (im = ({ typeof(*(in_dev->mc_list)) *_________p1 = (typeof(*(in_dev->mc_list))* )(*(volatile typeof((in_dev->mc_list)) *)&((in_dev->mc_list))); do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !(rcu_read_lock_held() || (0))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 934); } } while (0); ; do { } while (0); ((typeof(*(in_dev->mc_list)) *)(_________p1)); }); im != ((void *)0); im = ({ typeof(*(im->next_rcu)) *_________p1 = (typeof(*(im->next_rcu))* )(*(volatile typeof((im->next_rcu)) *)&((im->next_rcu))); do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !(rcu_read_lock_held() || (0))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 934); } } while (0); ; do { } while (0); ((typeof(*(im->next_rcu)) *)(_________p1)); })) {
757| int changed;
758|
759| if (group && group != im->multiaddr)
760| continue;
761| if (im->multiaddr == (( __be32)(__builtin_constant_p((__u32)((0xE0000001L))) ? ((__u32)( (((__u32)((0xE0000001L)) & (__u32)0x000000ffUL) << 24) | (((__u32)((0xE0000001L)) & (__u32)0x0000ff00UL) << 8) | (((__u32)((0xE0000001L)) & (__u32)0x00ff0000UL) >> 8) | (((__u32)((0xE0000001L)) & (__u32)0xff000000UL) >> 24))) : __fswab32((0xE0000001L)))))
762| continue;
763| __st_spin_lock_bh_st__(&im->lock);
764| if (im->tm_running)
765| im->gsquery = im->gsquery && mark;
766| else
767| im->gsquery = mark;
768| changed = !im->gsquery ||
769| igmp_marksources(im, (__builtin_constant_p((__u16)(( __u16)(__be16)(ih3->nsrcs))) ? ((__u16)( (((__u16)(( __u16)(__be16)(ih3->nsrcs)) & (__u16)0x00ffU) << 8) | (((__u16)(( __u16)(__be16)(ih3->nsrcs)) & (__u16)0xff00U) >> 8))) : __fswab16(( __u16)(__be16)(ih3->nsrcs))), ih3->srcs);
770| __st_spin_unlock_bh_st__(&im->lock);
771| if (changed)
772| igmp_mod_timer(im, max_delay);
773| }
774| __st_rcu_read_unlock_st__();
775|}
776|
777|
778|int igmp_rcv(struct sk_buff *skb)
779|{
780|
781| struct igmphdr *ih;
782| struct in_device *in_dev = __in_dev_get_rcu(skb->dev);
783| int len = skb->len;
784|
785| if (in_dev == ((void *)0))
786| goto drop;
787|
788| if (!pskb_may_pull(skb, sizeof(struct igmphdr)))
789| goto drop;
790|
791| switch (skb->ip_summed) {
792| case 2:
793| if (!csum_fold(skb->csum))
794| break;
795|
796| case 0:
797| skb->csum = 0;
798| if (__skb_checksum_complete(skb))
799| goto drop;
800| }
801|
802| ih = igmp_hdr(skb);
803| switch (ih->type) {
804| case 0x11:
805| igmp_heard_query(in_dev, skb, len);
806| break;
807| case 0x12:
808| case 0x16:
809|
810| if (rt_is_output_route(skb_rtable(skb)))
811| break;
812|
813| if (skb->pkt_type == 2 ||
814| skb->pkt_type == 1)
815| igmp_heard_report(in_dev, ih->group);
816| break;
817| case 0x14:
818|
819| return pim_rcv_v1(skb);
820|
821| case 0x22:
822| case 0x13:
823| case 0x15:
824| case 0x17:
825| case 0x1f:
826| case 0x1e:
827| break;
828| default:
829| break;
830| }
831|
832|drop:
833| kfree_skb(skb);
834| return 0;
835|}
836|static void ip_mc_filter_add(struct in_device *in_dev, __be32 addr)
837|{
838| char buf[32];
839| struct net_device *dev = in_dev->dev;
840| if (arp_mc_map(addr, buf, dev, 0) == 0)
841| dev_mc_add(dev, buf);
842|}
843|
844|
845|
846|
847|
848|static void ip_mc_filter_del(struct in_device *in_dev, __be32 addr)
849|{
850| char buf[32];
851| struct net_device *dev = in_dev->dev;
852|
853| if (arp_mc_map(addr, buf, dev, 0) == 0)
854| dev_mc_del(dev, buf);
855|}
856|
857|
858|
859|
860|
861|static void igmpv3_add_delrec(struct in_device *in_dev, struct ip_mc_list *im)
862|{
863| struct ip_mc_list *pmc;
864|
865|
866|
867|
868|
869|
870|
871| pmc = kzalloc(sizeof(*pmc), __st_GFP_KERNEL_st__);
872| if (!pmc)
873| return;
874| __st_spin_lock_bh_st__(&im->lock);
875| pmc->interface = im->interface;
876| atomic_inc(&(in_dev)->refcnt);
877| pmc->multiaddr = im->multiaddr;
878| pmc->crcount = in_dev->mr_qrv ? in_dev->mr_qrv :
879| 2;
880| pmc->sfmode = im->sfmode;
881| if (pmc->sfmode == 1) {
882| struct ip_sf_list *psf;
883|
884| pmc->tomb = im->tomb;
885| pmc->sources = im->sources;
886| im->tomb = im->sources = ((void *)0);
887| for (psf=pmc->sources; psf; psf=psf->sf_next)
888| psf->sf_crcount = pmc->crcount;
889| }
890| __st_spin_unlock_bh_st__(&im->lock);
891|
892| __st_spin_lock_bh_st__(&in_dev->mc_tomb_lock);
893| pmc->next = in_dev->mc_tomb;
894| in_dev->mc_tomb = pmc;
895| __st_spin_unlock_bh_st__(&in_dev->mc_tomb_lock);
896|}
897|
898|static void igmpv3_del_delrec(struct in_device *in_dev, __be32 multiaddr)
899|{
900| struct ip_mc_list *pmc, *pmc_prev;
901| struct ip_sf_list *psf, *psf_next;
902|
903| __st_spin_lock_bh_st__(&in_dev->mc_tomb_lock);
904| pmc_prev = ((void *)0);
905| for (pmc=in_dev->mc_tomb; pmc; pmc=pmc->next) {
906| if (pmc->multiaddr == multiaddr)
907| break;
908| pmc_prev = pmc;
909| }
910| if (pmc) {
911| if (pmc_prev)
912| pmc_prev->next = pmc->next;
913| else
914| in_dev->mc_tomb = pmc->next;
915| }
916| __st_spin_unlock_bh_st__(&in_dev->mc_tomb_lock);
917| if (pmc) {
918| for (psf=pmc->tomb; psf; psf=psf_next) {
919| psf_next = psf->sf_next;
920| kfree(psf);
921| }
922| in_dev_put(pmc->interface);
923| kfree(pmc);
924| }
925|}
926|
927|static void igmpv3_clear_delrec(struct in_device *in_dev)
928|{
929| struct ip_mc_list *pmc, *nextpmc;
930|
931| __st_spin_lock_bh_st__(&in_dev->mc_tomb_lock);
932| pmc = in_dev->mc_tomb;
933| in_dev->mc_tomb = ((void *)0);
934| __st_spin_unlock_bh_st__(&in_dev->mc_tomb_lock);
935|
936| for (; pmc; pmc = nextpmc) {
937| nextpmc = pmc->next;
938| ip_mc_clear_src(pmc);
939| in_dev_put(pmc->interface);
940| kfree(pmc);
941| }
942|
943| __st_rcu_read_lock_st__();
944| for (pmc = ({ typeof(*(in_dev->mc_list)) *_________p1 = (typeof(*(in_dev->mc_list))* )(*(volatile typeof((in_dev->mc_list)) *)&((in_dev->mc_list))); do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !(rcu_read_lock_held() || (0))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 1138); } } while (0); ; do { } while (0); ((typeof(*(in_dev->mc_list)) *)(_________p1)); }); pmc != ((void *)0); pmc = ({ typeof(*(pmc->next_rcu)) *_________p1 = (typeof(*(pmc->next_rcu))* )(*(volatile typeof((pmc->next_rcu)) *)&((pmc->next_rcu))); do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !(rcu_read_lock_held() || (0))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 1138); } } while (0); ; do { } while (0); ((typeof(*(pmc->next_rcu)) *)(_________p1)); })) {
945| struct ip_sf_list *psf, *psf_next;
946|
947| __st_spin_lock_bh_st__(&pmc->lock);
948| psf = pmc->tomb;
949| pmc->tomb = ((void *)0);
950| __st_spin_unlock_bh_st__(&pmc->lock);
951| for (; psf; psf=psf_next) {
952| psf_next = psf->sf_next;
953| kfree(psf);
954| }
955| }
956| __st_rcu_read_unlock_st__();
957|}
958|
959|
960|static void igmp_group_dropped(struct ip_mc_list *im)
961|{
962| struct in_device *in_dev = im->interface;
963|
964| int reporter;
965|
966|
967| if (im->loaded) {
968| im->loaded = 0;
969| ip_mc_filter_del(in_dev, im->multiaddr);
970| }
971|
972|
973| if (im->multiaddr == (( __be32)(__builtin_constant_p((__u32)((0xE0000001L))) ? ((__u32)( (((__u32)((0xE0000001L)) & (__u32)0x000000ffUL) << 24) | (((__u32)((0xE0000001L)) & (__u32)0x0000ff00UL) << 8) | (((__u32)((0xE0000001L)) & (__u32)0x00ff0000UL) >> 8) | (((__u32)((0xE0000001L)) & (__u32)0xff000000UL) >> 24))) : __fswab32((0xE0000001L)))))
974| return;
975|
976| reporter = im->reporter;
977| igmp_stop_timer(im);
978|
979| if (!in_dev->dead) {
980| if (((((*(dev_net(in_dev->dev))->ipv4.devconf_all)).data[IPV4_DEVCONF_FORCE_IGMP_VERSION - 1]) == 1 || ipv4_devconf_get(((in_dev)), IPV4_DEVCONF_FORCE_IGMP_VERSION) == 1 || ((in_dev)->mr_v1_seen && (({ unsigned long __dummy; typeof((in_dev)->mr_v1_seen) __dummy2; (void)(&__dummy == &__dummy2); 1; }) && ({ unsigned long __dummy; typeof(jiffies) __dummy2; (void)(&__dummy == &__dummy2); 1; }) && ((long)(jiffies) - (long)((in_dev)->mr_v1_seen) < 0)))))
981| goto done;
982| if (((((*(dev_net(in_dev->dev))->ipv4.devconf_all)).data[IPV4_DEVCONF_FORCE_IGMP_VERSION - 1]) == 2 || ipv4_devconf_get(((in_dev)), IPV4_DEVCONF_FORCE_IGMP_VERSION) == 2 || ((in_dev)->mr_v2_seen && (({ unsigned long __dummy; typeof((in_dev)->mr_v2_seen) __dummy2; (void)(&__dummy == &__dummy2); 1; }) && ({ unsigned long __dummy; typeof(jiffies) __dummy2; (void)(&__dummy == &__dummy2); 1; }) && ((long)(jiffies) - (long)((in_dev)->mr_v2_seen) < 0))))) {
983| if (reporter)
984| igmp_send_report(in_dev, im, 0x17);
985| goto done;
986| }
987|
988| igmpv3_add_delrec(in_dev, im);
989|
990| igmp_ifc_event(in_dev);
991| }
992|done:
993|
994| ip_mc_clear_src(im);
995|}
996|
997|static void igmp_group_added(struct ip_mc_list *im)
998|{
999| struct in_device *in_dev = im->interface;
1000|
1001| if (im->loaded == 0) {
1002| im->loaded = 1;
1003| ip_mc_filter_add(in_dev, im->multiaddr);
1004| }
1005|
1006|
1007| if (im->multiaddr == (( __be32)(__builtin_constant_p((__u32)((0xE0000001L))) ? ((__u32)( (((__u32)((0xE0000001L)) & (__u32)0x000000ffUL) << 24) | (((__u32)((0xE0000001L)) & (__u32)0x0000ff00UL) << 8) | (((__u32)((0xE0000001L)) & (__u32)0x00ff0000UL) >> 8) | (((__u32)((0xE0000001L)) & (__u32)0xff000000UL) >> 24))) : __fswab32((0xE0000001L)))))
1008| return;
1009|
1010| if (in_dev->dead)
1011| return;
1012| if (((((*(dev_net(in_dev->dev))->ipv4.devconf_all)).data[IPV4_DEVCONF_FORCE_IGMP_VERSION - 1]) == 1 || ipv4_devconf_get(((in_dev)), IPV4_DEVCONF_FORCE_IGMP_VERSION) == 1 || ((in_dev)->mr_v1_seen && (({ unsigned long __dummy; typeof((in_dev)->mr_v1_seen) __dummy2; (void)(&__dummy == &__dummy2); 1; }) && ({ unsigned long __dummy; typeof(jiffies) __dummy2; (void)(&__dummy == &__dummy2); 1; }) && ((long)(jiffies) - (long)((in_dev)->mr_v1_seen) < 0)))) || ((((*(dev_net(in_dev->dev))->ipv4.devconf_all)).data[IPV4_DEVCONF_FORCE_IGMP_VERSION - 1]) == 2 || ipv4_devconf_get(((in_dev)), IPV4_DEVCONF_FORCE_IGMP_VERSION) == 2 || ((in_dev)->mr_v2_seen && (({ unsigned long __dummy; typeof((in_dev)->mr_v2_seen) __dummy2; (void)(&__dummy == &__dummy2); 1; }) && ({ unsigned long __dummy; typeof(jiffies) __dummy2; (void)(&__dummy == &__dummy2); 1; }) && ((long)(jiffies) - (long)((in_dev)->mr_v2_seen) < 0))))) {
1013| __st_spin_lock_bh_st__(&im->lock);
1014| igmp_start_timer(im, (1));
1015| __st_spin_unlock_bh_st__(&im->lock);
1016| return;
1017| }
1018|
1019|
1020| im->crcount = in_dev->mr_qrv ? in_dev->mr_qrv :
1021| 2;
1022| igmp_ifc_event(in_dev);
1023|
1024|}
1025|void ip_mc_inc_group(struct in_device *in_dev, __be32 addr)
1026|{
1027| struct ip_mc_list *im;
1028|
1029| do { if (__builtin_expect(!!(!rtnl_is_locked()), 0)) { printk("<3>" "RTNL: assertion failed at %s (%d)\n", "net/ipv4/.tmp_igmp.o.armored.c", 1234); dump_stack(); } } while(0);
1030|
1031| for (im = ({ do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !((lockdep_rtnl_is_held()))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 1236); } } while (0); ; ((typeof(*(in_dev->mc_list)) *)((in_dev->mc_list))); }); im != ((void *)0); im = ({ do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !((lockdep_rtnl_is_held()))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 1236); } } while (0); ; ((typeof(*(im->next_rcu)) *)((im->next_rcu))); })) {
1032| if (im->multiaddr == addr) {
1033| im->users++;
1034| ip_mc_add_src(in_dev, &addr, 0, 0, ((void *)0), 0);
1035| goto out;
1036| }
1037| }
1038|
1039| im = kzalloc(sizeof(*im), __st_GFP_KERNEL_st__);
1040| if (!im)
1041| goto out;
1042|
1043| im->users = 1;
1044| im->interface = in_dev;
1045| atomic_inc(&(in_dev)->refcnt);
1046| im->multiaddr = addr;
1047|
1048| im->sfmode = 0;
1049| im->sfcount[0] = 1;
1050| atomic_set(&im->refcnt, 1);
1051| do { spinlock_check(&im->lock); do { static struct lock_class_key __key; __raw_spin_lock_init((&(&im->lock)->rlock), "&(&im->lock)->rlock", &__key); } while (0); } while (0);
1052|
1053| do { static struct lock_class_key __key; setup_timer_key((&im->timer), "&im->timer", &__key, (&igmp_timer_expire), ((unsigned long)im)); } while (0);
1054| im->unsolicit_count = 2;
1055|
1056|
1057| im->next_rcu = in_dev->mc_list;
1058| in_dev->mc_count++;
1059| __st_rcu_assign_pointer_st__(in_dev->mc_list, im);
1060|
1061|
1062| igmpv3_del_delrec(in_dev, im->multiaddr);
1063|
1064| igmp_group_added(im);
1065| if (!in_dev->dead)
1066| ip_rt_multicast_event(in_dev);
1067|out:
1068| return;
1069|}
1070|extern typeof(ip_mc_inc_group) ip_mc_inc_group; extern void *__crc_ip_mc_inc_group ; static const unsigned long __kcrctab_ip_mc_inc_group = (unsigned long) &__crc_ip_mc_inc_group; static const char __kstrtab_ip_mc_inc_group[] = "" "ip_mc_inc_group"; static const struct kernel_symbol __ksymtab_ip_mc_inc_group = { (unsigned long)&ip_mc_inc_group, __kstrtab_ip_mc_inc_group };
1071|
1072|
1073|
1074|
1075|
1076|void ip_mc_rejoin_groups(struct in_device *in_dev)
1077|{
1078|
1079| struct ip_mc_list *im;
1080| int type;
1081|
1082| for (im = ({ typeof(*(in_dev->mc_list)) *_________p1 = (typeof(*(in_dev->mc_list))* )(*(volatile typeof((in_dev->mc_list)) *)&((in_dev->mc_list))); do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !(rcu_read_lock_held() || (0))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 1287); } } while (0); ; do { } while (0); ((typeof(*(in_dev->mc_list)) *)(_________p1)); }); im != ((void *)0); im = ({ typeof(*(im->next_rcu)) *_________p1 = (typeof(*(im->next_rcu))* )(*(volatile typeof((im->next_rcu)) *)&((im->next_rcu))); do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !(rcu_read_lock_held() || (0))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 1287); } } while (0); ; do { } while (0); ((typeof(*(im->next_rcu)) *)(_________p1)); })) {
1083| if (im->multiaddr == (( __be32)(__builtin_constant_p((__u32)((0xE0000001L))) ? ((__u32)( (((__u32)((0xE0000001L)) & (__u32)0x000000ffUL) << 24) | (((__u32)((0xE0000001L)) & (__u32)0x0000ff00UL) << 8) | (((__u32)((0xE0000001L)) & (__u32)0x00ff0000UL) >> 8) | (((__u32)((0xE0000001L)) & (__u32)0xff000000UL) >> 24))) : __fswab32((0xE0000001L)))))
1084| continue;
1085|
1086|
1087|
1088|
1089| if (((((*(dev_net(in_dev->dev))->ipv4.devconf_all)).data[IPV4_DEVCONF_FORCE_IGMP_VERSION - 1]) == 1 || ipv4_devconf_get(((in_dev)), IPV4_DEVCONF_FORCE_IGMP_VERSION) == 1 || ((in_dev)->mr_v1_seen && (({ unsigned long __dummy; typeof((in_dev)->mr_v1_seen) __dummy2; (void)(&__dummy == &__dummy2); 1; }) && ({ unsigned long __dummy; typeof(jiffies) __dummy2; (void)(&__dummy == &__dummy2); 1; }) && ((long)(jiffies) - (long)((in_dev)->mr_v1_seen) < 0)))))
1090| type = 0x12;
1091| else if (((((*(dev_net(in_dev->dev))->ipv4.devconf_all)).data[IPV4_DEVCONF_FORCE_IGMP_VERSION - 1]) == 2 || ipv4_devconf_get(((in_dev)), IPV4_DEVCONF_FORCE_IGMP_VERSION) == 2 || ((in_dev)->mr_v2_seen && (({ unsigned long __dummy; typeof((in_dev)->mr_v2_seen) __dummy2; (void)(&__dummy == &__dummy2); 1; }) && ({ unsigned long __dummy; typeof(jiffies) __dummy2; (void)(&__dummy == &__dummy2); 1; }) && ((long)(jiffies) - (long)((in_dev)->mr_v2_seen) < 0)))))
1092| type = 0x16;
1093| else
1094| type = 0x22;
1095| igmp_send_report(in_dev, im, type);
1096| }
1097|
1098|}
1099|extern typeof(ip_mc_rejoin_groups) ip_mc_rejoin_groups; extern void *__crc_ip_mc_rejoin_groups ; static const unsigned long __kcrctab_ip_mc_rejoin_groups = (unsigned long) &__crc_ip_mc_rejoin_groups; static const char __kstrtab_ip_mc_rejoin_groups[] = "" "ip_mc_rejoin_groups"; static const struct kernel_symbol __ksymtab_ip_mc_rejoin_groups = { (unsigned long)&ip_mc_rejoin_groups, __kstrtab_ip_mc_rejoin_groups };
1100|
1101|
1102|
1103|
1104|
1105|void ip_mc_dec_group(struct in_device *in_dev, __be32 addr)
1106|{
1107| struct ip_mc_list *i;
1108| struct ip_mc_list **ip;
1109|
1110| do { if (__builtin_expect(!!(!rtnl_is_locked()), 0)) { printk("<3>" "RTNL: assertion failed at %s (%d)\n", "net/ipv4/.tmp_igmp.o.armored.c", 1315); dump_stack(); } } while(0);
1111|
1112| for (ip = &in_dev->mc_list;
1113| (i = ({ do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !((lockdep_rtnl_is_held()))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 1318); } } while (0); ; ((typeof(*(*ip)) *)((*ip))); })) != ((void *)0);
1114| ip = &i->next_rcu) {
1115| if (i->multiaddr == addr) {
1116| if (--i->users == 0) {
1117| *ip = i->next_rcu;
1118| in_dev->mc_count--;
1119| igmp_group_dropped(i);
1120|
1121| if (!in_dev->dead)
1122| ip_rt_multicast_event(in_dev);
1123|
1124| ip_ma_put(i);
1125| return;
1126| }
1127| break;
1128| }
1129| }
1130|}
1131|extern typeof(ip_mc_dec_group) ip_mc_dec_group; extern void *__crc_ip_mc_dec_group ; static const unsigned long __kcrctab_ip_mc_dec_group = (unsigned long) &__crc_ip_mc_dec_group; static const char __kstrtab_ip_mc_dec_group[] = "" "ip_mc_dec_group"; static const struct kernel_symbol __ksymtab_ip_mc_dec_group = { (unsigned long)&ip_mc_dec_group, __kstrtab_ip_mc_dec_group };
1132|
1133|
1134|
1135|void ip_mc_unmap(struct in_device *in_dev)
1136|{
1137| struct ip_mc_list *pmc;
1138|
1139| do { if (__builtin_expect(!!(!rtnl_is_locked()), 0)) { printk("<3>" "RTNL: assertion failed at %s (%d)\n", "net/ipv4/.tmp_igmp.o.armored.c", 1344); dump_stack(); } } while(0);
1140|
1141| for (pmc = ({ do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !((lockdep_rtnl_is_held()))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 1346); } } while (0); ; ((typeof(*(in_dev->mc_list)) *)((in_dev->mc_list))); }); pmc != ((void *)0); pmc = ({ do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !((lockdep_rtnl_is_held()))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 1346); } } while (0); ; ((typeof(*(pmc->next_rcu)) *)((pmc->next_rcu))); }))
1142| igmp_group_dropped(pmc);
1143|}
1144|
1145|void ip_mc_remap(struct in_device *in_dev)
1146|{
1147| struct ip_mc_list *pmc;
1148|
1149| do { if (__builtin_expect(!!(!rtnl_is_locked()), 0)) { printk("<3>" "RTNL: assertion failed at %s (%d)\n", "net/ipv4/.tmp_igmp.o.armored.c", 1354); dump_stack(); } } while(0);
1150|
1151| for (pmc = ({ do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !((lockdep_rtnl_is_held()))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 1356); } } while (0); ; ((typeof(*(in_dev->mc_list)) *)((in_dev->mc_list))); }); pmc != ((void *)0); pmc = ({ do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !((lockdep_rtnl_is_held()))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 1356); } } while (0); ; ((typeof(*(pmc->next_rcu)) *)((pmc->next_rcu))); }))
1152| igmp_group_added(pmc);
1153|}
1154|
1155|
1156|
1157|void ip_mc_down(struct in_device *in_dev)
1158|{
1159| struct ip_mc_list *pmc;
1160|
1161| do { if (__builtin_expect(!!(!rtnl_is_locked()), 0)) { printk("<3>" "RTNL: assertion failed at %s (%d)\n", "net/ipv4/.tmp_igmp.o.armored.c", 1366); dump_stack(); } } while(0);
1162|
1163| for (pmc = ({ do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !((lockdep_rtnl_is_held()))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 1368); } } while (0); ; ((typeof(*(in_dev->mc_list)) *)((in_dev->mc_list))); }); pmc != ((void *)0); pmc = ({ do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !((lockdep_rtnl_is_held()))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 1368); } } while (0); ; ((typeof(*(pmc->next_rcu)) *)((pmc->next_rcu))); }))
1164| igmp_group_dropped(pmc);
1165|
1166|
1167| in_dev->mr_ifc_count = 0;
1168| if (del_timer(&in_dev->mr_ifc_timer))
1169| atomic_dec(&(in_dev)->refcnt);
1170| in_dev->mr_gq_running = 0;
1171| if (del_timer(&in_dev->mr_gq_timer))
1172| atomic_dec(&(in_dev)->refcnt);
1173| igmpv3_clear_delrec(in_dev);
1174|
1175|
1176| ip_mc_dec_group(in_dev, (( __be32)(__builtin_constant_p((__u32)((0xE0000001L))) ? ((__u32)( (((__u32)((0xE0000001L)) & (__u32)0x000000ffUL) << 24) | (((__u32)((0xE0000001L)) & (__u32)0x0000ff00UL) << 8) | (((__u32)((0xE0000001L)) & (__u32)0x00ff0000UL) >> 8) | (((__u32)((0xE0000001L)) & (__u32)0xff000000UL) >> 24))) : __fswab32((0xE0000001L)))));
1177|}
1178|
1179|void ip_mc_init_dev(struct in_device *in_dev)
1180|{
1181| do { if (__builtin_expect(!!(!rtnl_is_locked()), 0)) { printk("<3>" "RTNL: assertion failed at %s (%d)\n", "net/ipv4/.tmp_igmp.o.armored.c", 1386); dump_stack(); } } while(0);
1182|
1183| in_dev->mc_tomb = ((void *)0);
1184|
1185| in_dev->mr_gq_running = 0;
1186| do { static struct lock_class_key __key; setup_timer_key((&in_dev->mr_gq_timer), "&in_dev->mr_gq_timer", &__key, (igmp_gq_timer_expire), ((unsigned long)in_dev)); } while (0)
1187| ;
1188| in_dev->mr_ifc_count = 0;
1189| in_dev->mc_count = 0;
1190| do { static struct lock_class_key __key; setup_timer_key((&in_dev->mr_ifc_timer), "&in_dev->mr_ifc_timer", &__key, (igmp_ifc_timer_expire), ((unsigned long)in_dev)); } while (0)
1191| ;
1192| in_dev->mr_qrv = 2;
1193|
1194|
1195| do { spinlock_check(&in_dev->mc_tomb_lock); do { static struct lock_class_key __key; __raw_spin_lock_init((&(&in_dev->mc_tomb_lock)->rlock), "&(&in_dev->mc_tomb_lock)->rlock", &__key); } while (0); } while (0);
1196|}
1197|
1198|
1199|
1200|void ip_mc_up(struct in_device *in_dev)
1201|{
1202| struct ip_mc_list *pmc;
1203|
1204| do { if (__builtin_expect(!!(!rtnl_is_locked()), 0)) { printk("<3>" "RTNL: assertion failed at %s (%d)\n", "net/ipv4/.tmp_igmp.o.armored.c", 1409); dump_stack(); } } while(0);
1205|
1206| ip_mc_inc_group(in_dev, (( __be32)(__builtin_constant_p((__u32)((0xE0000001L))) ? ((__u32)( (((__u32)((0xE0000001L)) & (__u32)0x000000ffUL) << 24) | (((__u32)((0xE0000001L)) & (__u32)0x0000ff00UL) << 8) | (((__u32)((0xE0000001L)) & (__u32)0x00ff0000UL) >> 8) | (((__u32)((0xE0000001L)) & (__u32)0xff000000UL) >> 24))) : __fswab32((0xE0000001L)))));
1207|
1208| for (pmc = ({ do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !((lockdep_rtnl_is_held()))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 1413); } } while (0); ; ((typeof(*(in_dev->mc_list)) *)((in_dev->mc_list))); }); pmc != ((void *)0); pmc = ({ do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !((lockdep_rtnl_is_held()))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 1413); } } while (0); ; ((typeof(*(pmc->next_rcu)) *)((pmc->next_rcu))); }))
1209| igmp_group_added(pmc);
1210|}
1211|
1212|
1213|
1214|
1215|
1216|void ip_mc_destroy_dev(struct in_device *in_dev)
1217|{
1218| struct ip_mc_list *i;
1219|
1220| do { if (__builtin_expect(!!(!rtnl_is_locked()), 0)) { printk("<3>" "RTNL: assertion failed at %s (%d)\n", "net/ipv4/.tmp_igmp.o.armored.c", 1425); dump_stack(); } } while(0);
1221|
1222|
1223| ip_mc_down(in_dev);
1224|
1225| while ((i = ({ do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !((lockdep_rtnl_is_held()))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 1430); } } while (0); ; ((typeof(*(in_dev->mc_list)) *)((in_dev->mc_list))); })) != ((void *)0)) {
1226| in_dev->mc_list = i->next_rcu;
1227| in_dev->mc_count--;
1228|
1229| igmp_group_dropped(i);
1230| ip_ma_put(i);
1231| }
1232|}
1233|
1234|
1235|static struct in_device *ip_mc_find_dev(struct net *net, struct ip_mreqn *imr)
1236|{
1237| struct flowi fl = { .nl_u.ip4_u.daddr = imr->imr_multiaddr.s_addr };
1238| struct rtable *rt;
1239| struct net_device *dev = ((void *)0);
1240| struct in_device *idev = ((void *)0);
1241|
1242| if (imr->imr_ifindex) {
1243| idev = inetdev_by_index(net, imr->imr_ifindex);
1244| return idev;
1245| }
1246| if (imr->imr_address.s_addr) {
1247| dev = __ip_dev_find(net, imr->imr_address.s_addr, false);
1248| if (!dev)
1249| return ((void *)0);
1250| }
1251|
1252| if (!dev && !ip_route_output_key(net, &rt, &fl)) {
1253| dev = rt->dst.dev;
1254| ip_rt_put(rt);
1255| }
1256| if (dev) {
1257| imr->imr_ifindex = dev->ifindex;
1258| idev = __in_dev_get_rtnl(dev);
1259| }
1260| return idev;
1261|}
1262|
1263|
1264|
1265|
1266|int sysctl_igmp_max_memberships = 20;
1267|int sysctl_igmp_max_msf = 10;
1268|
1269|
1270|static int ip_mc_del1_src(struct ip_mc_list *pmc, int sfmode,
1271| __be32 *psfsrc)
1272|{
1273| struct ip_sf_list *psf, *psf_prev;
1274| int rv = 0;
1275|
1276| psf_prev = ((void *)0);
1277| for (psf=pmc->sources; psf; psf=psf->sf_next) {
1278| if (psf->sf_inaddr == *psfsrc)
1279| break;
1280| psf_prev = psf;
1281| }
1282| if (!psf || psf->sf_count[sfmode] == 0) {
1283|
1284| return -3;
1285| }
1286| psf->sf_count[sfmode]--;
1287| if (psf->sf_count[sfmode] == 0) {
1288| ip_rt_multicast_event(pmc->interface);
1289| }
1290| if (!psf->sf_count[1] && !psf->sf_count[0]) {
1291|
1292| struct in_device *in_dev = pmc->interface;
1293|
1294|
1295|
1296| if (psf_prev)
1297| psf_prev->sf_next = psf->sf_next;
1298| else
1299| pmc->sources = psf->sf_next;
1300|
1301| if (psf->sf_oldin &&
1302| !((((*(dev_net(in_dev->dev))->ipv4.devconf_all)).data[IPV4_DEVCONF_FORCE_IGMP_VERSION - 1]) == 1 || ipv4_devconf_get(((in_dev)), IPV4_DEVCONF_FORCE_IGMP_VERSION) == 1 || ((in_dev)->mr_v1_seen && (({ unsigned long __dummy; typeof((in_dev)->mr_v1_seen) __dummy2; (void)(&__dummy == &__dummy2); 1; }) && ({ unsigned long __dummy; typeof(jiffies) __dummy2; (void)(&__dummy == &__dummy2); 1; }) && ((long)(jiffies) - (long)((in_dev)->mr_v1_seen) < 0)))) && !((((*(dev_net(in_dev->dev))->ipv4.devconf_all)).data[IPV4_DEVCONF_FORCE_IGMP_VERSION - 1]) == 2 || ipv4_devconf_get(((in_dev)), IPV4_DEVCONF_FORCE_IGMP_VERSION) == 2 || ((in_dev)->mr_v2_seen && (({ unsigned long __dummy; typeof((in_dev)->mr_v2_seen) __dummy2; (void)(&__dummy == &__dummy2); 1; }) && ({ unsigned long __dummy; typeof(jiffies) __dummy2; (void)(&__dummy == &__dummy2); 1; }) && ((long)(jiffies) - (long)((in_dev)->mr_v2_seen) < 0))))) {
1303| psf->sf_crcount = in_dev->mr_qrv ? in_dev->mr_qrv :
1304| 2;
1305| psf->sf_next = pmc->tomb;
1306| pmc->tomb = psf;
1307| rv = 1;
1308| } else
1309|
1310| kfree(psf);
1311| }
1312| return rv;
1313|}
1314|
1315|
1316|
1317|
1318|
1319|static int ip_mc_del_src(struct in_device *in_dev, __be32 *pmca, int sfmode,
1320| int sfcount, __be32 *psfsrc, int delta)
1321|{
1322| struct ip_mc_list *pmc;
1323| int changerec = 0;
1324| int i, err;
1325|
1326| if (!in_dev)
1327| return -19;
1328| __st_rcu_read_lock_st__();
1329| for (pmc = ({ typeof(*(in_dev->mc_list)) *_________p1 = (typeof(*(in_dev->mc_list))* )(*(volatile typeof((in_dev->mc_list)) *)&((in_dev->mc_list))); do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !(rcu_read_lock_held() || (0))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 1534); } } while (0); ; do { } while (0); ((typeof(*(in_dev->mc_list)) *)(_________p1)); }); pmc != ((void *)0); pmc = ({ typeof(*(pmc->next_rcu)) *_________p1 = (typeof(*(pmc->next_rcu))* )(*(volatile typeof((pmc->next_rcu)) *)&((pmc->next_rcu))); do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !(rcu_read_lock_held() || (0))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 1534); } } while (0); ; do { } while (0); ((typeof(*(pmc->next_rcu)) *)(_________p1)); })) {
1330| if (*pmca == pmc->multiaddr)
1331| break;
1332| }
1333| if (!pmc) {
1334|
1335| __st_rcu_read_unlock_st__();
1336| return -3;
1337| }
1338| __st_spin_lock_bh_st__(&pmc->lock);
1339| __st_rcu_read_unlock_st__();
1340|
1341| sf_markstate(pmc);
1342|
1343| if (!delta) {
1344| err = -22;
1345| if (!pmc->sfcount[sfmode])
1346| goto out_unlock;
1347| pmc->sfcount[sfmode]--;
1348| }
1349| err = 0;
1350| for (i=0; i 1351| int rv = ip_mc_del1_src(pmc, sfmode, &psfsrc[i]);
1352|
1353| changerec |= rv > 0;
1354| if (!err && rv < 0)
1355| err = rv;
1356| }
1357| if (pmc->sfmode == 0 &&
1358| pmc->sfcount[0] == 0 &&
1359| pmc->sfcount[1]) {
1360|
1361| struct ip_sf_list *psf;
1362|
1363|
1364|
1365| pmc->sfmode = 1;
1366|
1367| pmc->crcount = in_dev->mr_qrv ? in_dev->mr_qrv :
1368| 2;
1369| in_dev->mr_ifc_count = pmc->crcount;
1370| for (psf=pmc->sources; psf; psf = psf->sf_next)
1371| psf->sf_crcount = 0;
1372| igmp_ifc_event(pmc->interface);
1373| } else if (sf_setstate(pmc) || changerec) {
1374| igmp_ifc_event(pmc->interface);
1375|
1376| }
1377|out_unlock:
1378| __st_spin_unlock_bh_st__(&pmc->lock);
1379| return err;
1380|}
1381|
1382|
1383|
1384|
1385|static int ip_mc_add1_src(struct ip_mc_list *pmc, int sfmode,
1386| __be32 *psfsrc, int delta)
1387|{
1388| struct ip_sf_list *psf, *psf_prev;
1389|
1390| psf_prev = ((void *)0);
1391| for (psf=pmc->sources; psf; psf=psf->sf_next) {
1392| if (psf->sf_inaddr == *psfsrc)
1393| break;
1394| psf_prev = psf;
1395| }
1396| if (!psf) {
1397| psf = kzalloc(sizeof(*psf), ((( gfp_t)0x20u)));
1398| if (!psf)
1399| return -105;
1400| psf->sf_inaddr = *psfsrc;
1401| if (psf_prev) {
1402| psf_prev->sf_next = psf;
1403| } else
1404| pmc->sources = psf;
1405| }
1406| psf->sf_count[sfmode]++;
1407| if (psf->sf_count[sfmode] == 1) {
1408| ip_rt_multicast_event(pmc->interface);
1409| }
1410| return 0;
1411|}
1412|
1413|
1414|static void sf_markstate(struct ip_mc_list *pmc)
1415|{
1416| struct ip_sf_list *psf;
1417| int mca_xcount = pmc->sfcount[0];
1418|
1419| for (psf=pmc->sources; psf; psf=psf->sf_next)
1420| if (pmc->sfcount[0]) {
1421| psf->sf_oldin = mca_xcount ==
1422| psf->sf_count[0] &&
1423| !psf->sf_count[1];
1424| } else
1425| psf->sf_oldin = psf->sf_count[1] != 0;
1426|}
1427|
1428|static int sf_setstate(struct ip_mc_list *pmc)
1429|{
1430| struct ip_sf_list *psf, *dpsf;
1431| int mca_xcount = pmc->sfcount[0];
1432| int qrv = pmc->interface->mr_qrv;
1433| int new_in, rv;
1434|
1435| rv = 0;
1436| for (psf=pmc->sources; psf; psf=psf->sf_next) {
1437| if (pmc->sfcount[0]) {
1438| new_in = mca_xcount == psf->sf_count[0] &&
1439| !psf->sf_count[1];
1440| } else
1441| new_in = psf->sf_count[1] != 0;
1442| if (new_in) {
1443| if (!psf->sf_oldin) {
1444| struct ip_sf_list *prev = ((void *)0);
1445|
1446| for (dpsf=pmc->tomb; dpsf; dpsf=dpsf->sf_next) {
1447| if (dpsf->sf_inaddr == psf->sf_inaddr)
1448| break;
1449| prev = dpsf;
1450| }
1451| if (dpsf) {
1452| if (prev)
1453| prev->sf_next = dpsf->sf_next;
1454| else
1455| pmc->tomb = dpsf->sf_next;
1456| kfree(dpsf);
1457| }
1458| psf->sf_crcount = qrv;
1459| rv++;
1460| }
1461| } else if (psf->sf_oldin) {
1462|
1463| psf->sf_crcount = 0;
1464|
1465|
1466|
1467|
1468| for (dpsf=pmc->tomb; dpsf; dpsf=dpsf->sf_next)
1469| if (dpsf->sf_inaddr == psf->sf_inaddr)
1470| break;
1471| if (!dpsf) {
1472| dpsf = kmalloc(sizeof(*dpsf), ((( gfp_t)0x20u)));
1473| if (!dpsf)
1474| continue;
1475| *dpsf = *psf;
1476|
1477| dpsf->sf_next = pmc->tomb;
1478| pmc->tomb = dpsf;
1479| }
1480| dpsf->sf_crcount = qrv;
1481| rv++;
1482| }
1483| }
1484| return rv;
1485|}
1486|
1487|
1488|
1489|
1490|
1491|static int ip_mc_add_src(struct in_device *in_dev, __be32 *pmca, int sfmode,
1492| int sfcount, __be32 *psfsrc, int delta)
1493|{
1494| struct ip_mc_list *pmc;
1495| int isexclude;
1496| int i, err;
1497|
1498| if (!in_dev)
1499| return -19;
1500| __st_rcu_read_lock_st__();
1501| for (pmc = ({ typeof(*(in_dev->mc_list)) *_________p1 = (typeof(*(in_dev->mc_list))* )(*(volatile typeof((in_dev->mc_list)) *)&((in_dev->mc_list))); do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !(rcu_read_lock_held() || (0))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 1706); } } while (0); ; do { } while (0); ((typeof(*(in_dev->mc_list)) *)(_________p1)); }); pmc != ((void *)0); pmc = ({ typeof(*(pmc->next_rcu)) *_________p1 = (typeof(*(pmc->next_rcu))* )(*(volatile typeof((pmc->next_rcu)) *)&((pmc->next_rcu))); do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !(rcu_read_lock_held() || (0))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 1706); } } while (0); ; do { } while (0); ((typeof(*(pmc->next_rcu)) *)(_________p1)); })) {
1502| if (*pmca == pmc->multiaddr)
1503| break;
1504| }
1505| if (!pmc) {
1506|
1507| __st_rcu_read_unlock_st__();
1508| return -3;
1509| }
1510| __st_spin_lock_bh_st__(&pmc->lock);
1511| __st_rcu_read_unlock_st__();
1512|
1513|
1514| sf_markstate(pmc);
1515|
1516| isexclude = pmc->sfmode == 0;
1517| if (!delta)
1518| pmc->sfcount[sfmode]++;
1519| err = 0;
1520| for (i=0; i 1521| err = ip_mc_add1_src(pmc, sfmode, &psfsrc[i], delta);
1522| if (err)
1523| break;
1524| }
1525| if (err) {
1526| int j;
1527|
1528| pmc->sfcount[sfmode]--;
1529| for (j=0; j 1530| (void) ip_mc_del1_src(pmc, sfmode, &psfsrc[i]);
1531| } else if (isexclude != (pmc->sfcount[0] != 0)) {
1532|
1533| struct ip_sf_list *psf;
1534| in_dev = pmc->interface;
1535|
1536|
1537|
1538| if (pmc->sfcount[0])
1539| pmc->sfmode = 0;
1540| else if (pmc->sfcount[1])
1541| pmc->sfmode = 1;
1542|
1543|
1544|
1545| pmc->crcount = in_dev->mr_qrv ? in_dev->mr_qrv :
1546| 2;
1547| in_dev->mr_ifc_count = pmc->crcount;
1548| for (psf=pmc->sources; psf; psf = psf->sf_next)
1549| psf->sf_crcount = 0;
1550| igmp_ifc_event(in_dev);
1551| } else if (sf_setstate(pmc)) {
1552| igmp_ifc_event(in_dev);
1553|
1554| }
1555| __st_spin_unlock_bh_st__(&pmc->lock);
1556| return err;
1557|}
1558|
1559|static void ip_mc_clear_src(struct ip_mc_list *pmc)
1560|{
1561| struct ip_sf_list *psf, *nextpsf;
1562|
1563| for (psf=pmc->tomb; psf; psf=nextpsf) {
1564| nextpsf = psf->sf_next;
1565| kfree(psf);
1566| }
1567| pmc->tomb = ((void *)0);
1568| for (psf=pmc->sources; psf; psf=nextpsf) {
1569| nextpsf = psf->sf_next;
1570| kfree(psf);
1571| }
1572| pmc->sources = ((void *)0);
1573| pmc->sfmode = 0;
1574| pmc->sfcount[1] = 0;
1575| pmc->sfcount[0] = 1;
1576|}
1577|
1578|
1579|
1580|
1581|
1582|int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr)
1583|{
1584| int err;
1585| __be32 addr = imr->imr_multiaddr.s_addr;
1586| struct ip_mc_socklist *iml = ((void *)0), *i;
1587| struct in_device *in_dev;
1588| struct inet_sock *inet = inet_sk(sk);
1589| struct net *net = sock_net(sk);
1590| int ifindex;
1591| int count = 0;
1592|
1593| if (!ipv4_is_multicast(addr))
1594| return -22;
1595|
1596| rtnl_lock();
1597|
1598| in_dev = ip_mc_find_dev(net, imr);
1599|
1600| if (!in_dev) {
1601| iml = ((void *)0);
1602| err = -19;
1603| goto done;
1604| }
1605|
1606| err = -98;
1607| ifindex = imr->imr_ifindex;
1608| for (i = ({ do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !((lockdep_rtnl_is_held()))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 1813); } } while (0); ; ((typeof(*(inet->mc_list)) *)((inet->mc_list))); }); i != ((void *)0); i = ({ do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !((lockdep_rtnl_is_held()))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 1813); } } while (0); ; ((typeof(*(i->next_rcu)) *)((i->next_rcu))); })) {
1609| if (i->multi.imr_multiaddr.s_addr == addr &&
1610| i->multi.imr_ifindex == ifindex)
1611| goto done;
1612| count++;
1613| }
1614| err = -105;
1615| if (count >= sysctl_igmp_max_memberships)
1616| goto done;
1617| iml = sock_kmalloc(sk, sizeof(*iml), __st_GFP_KERNEL_st__);
1618| if (iml == ((void *)0))
1619| goto done;
1620|
1621| __st_memcpy_st__(&iml->multi, imr, sizeof(*imr));
1622| iml->next_rcu = inet->mc_list;
1623| iml->sflist = ((void *)0);
1624| iml->sfmode = 0;
1625| __st_rcu_assign_pointer_st__(inet->mc_list, iml);
1626| ip_mc_inc_group(in_dev, addr);
1627| err = 0;
1628|done:
1629| rtnl_unlock();
1630| return err;
1631|}
1632|extern typeof(ip_mc_join_group) ip_mc_join_group; extern void *__crc_ip_mc_join_group ; static const unsigned long __kcrctab_ip_mc_join_group = (unsigned long) &__crc_ip_mc_join_group; static const char __kstrtab_ip_mc_join_group[] = "" "ip_mc_join_group"; static const struct kernel_symbol __ksymtab_ip_mc_join_group = { (unsigned long)&ip_mc_join_group, __kstrtab_ip_mc_join_group };
1633|
1634|static void ip_sf_socklist_reclaim(struct rcu_head *rp)
1635|{
1636| kfree(({ const typeof( ((struct ip_sf_socklist *)0)->rcu ) *__mptr = (rp); (struct ip_sf_socklist *)( (char *)__mptr - 1 );}));
1637|
1638|}
1639|
1640|static int ip_mc_leave_src(struct sock *sk, struct ip_mc_socklist *iml,
1641| struct in_device *in_dev)
1642|{
1643| struct ip_sf_socklist *psf = ({ do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !((lockdep_rtnl_is_held()))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 1848); } } while (0); ; ((typeof(*(iml->sflist)) *)((iml->sflist))); });
1644| int err;
1645|
1646| if (psf == ((void *)0)) {
1647|
1648| return ip_mc_del_src(in_dev, &iml->multi.imr_multiaddr.s_addr,
1649| iml->sfmode, 0, ((void *)0), 0);
1650| }
1651| err = ip_mc_del_src(in_dev, &iml->multi.imr_multiaddr.s_addr,
1652| iml->sfmode, psf->sl_count, psf->sl_addr, 0);
1653| __st_rcu_assign_pointer_st__(iml->sflist, ((void *)0));
1654|
1655| atomic_sub((sizeof(struct ip_sf_socklist) + (psf->sl_max) * sizeof(__be32)), &sk->sk_omem_alloc);
1656| call_rcu_sched(&psf->rcu, ip_sf_socklist_reclaim);
1657| return err;
1658|}
1659|
1660|
1661|static void ip_mc_socklist_reclaim(struct rcu_head *rp)
1662|{
1663| kfree(({ const typeof( ((struct ip_mc_socklist *)0)->rcu ) *__mptr = (rp); (struct ip_mc_socklist *)( (char *)__mptr - 1 );}));
1664|
1665|}
1666|
1667|
1668|
1669|
1670|
1671|
1672|int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)
1673|{
1674| struct inet_sock *inet = inet_sk(sk);
1675| struct ip_mc_socklist *iml;
1676| struct ip_mc_socklist **imlp;
1677| struct in_device *in_dev;
1678| struct net *net = sock_net(sk);
1679| __be32 group = imr->imr_multiaddr.s_addr;
1680| u32 ifindex;
1681| int ret = -99;
1682|
1683| rtnl_lock();
1684| in_dev = ip_mc_find_dev(net, imr);
1685| ifindex = imr->imr_ifindex;
1686| for (imlp = &inet->mc_list;
1687| (iml = ({ do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !((lockdep_rtnl_is_held()))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 1892); } } while (0); ; ((typeof(*(*imlp)) *)((*imlp))); })) != ((void *)0);
1688| imlp = &iml->next_rcu) {
1689| if (iml->multi.imr_multiaddr.s_addr != group)
1690| continue;
1691| if (ifindex) {
1692| if (iml->multi.imr_ifindex != ifindex)
1693| continue;
1694| } else if (imr->imr_address.s_addr && imr->imr_address.s_addr !=
1695| iml->multi.imr_address.s_addr)
1696| continue;
1697|
1698| (void) ip_mc_leave_src(sk, iml, in_dev);
1699|
1700| *imlp = iml->next_rcu;
1701|
1702| if (in_dev)
1703| ip_mc_dec_group(in_dev, group);
1704| rtnl_unlock();
1705|
1706| atomic_sub(sizeof(*iml), &sk->sk_omem_alloc);
1707| call_rcu_sched(&iml->rcu, ip_mc_socklist_reclaim);
1708| return 0;
1709| }
1710| if (!in_dev)
1711| ret = -19;
1712| rtnl_unlock();
1713| return ret;
1714|}
1715|
1716|int ip_mc_source(int add, int omode, struct sock *sk, struct
1717| ip_mreq_source *mreqs, int ifindex)
1718|{
1719| int err;
1720| struct ip_mreqn imr;
1721| __be32 addr = mreqs->imr_multiaddr;
1722| struct ip_mc_socklist *pmc;
1723| struct in_device *in_dev = ((void *)0);
1724| struct inet_sock *inet = inet_sk(sk);
1725| struct ip_sf_socklist *psl;
1726| struct net *net = sock_net(sk);
1727| int leavegroup = 0;
1728| int i, j, rv;
1729|
1730| if (!ipv4_is_multicast(addr))
1731| return -22;
1732|
1733| rtnl_lock();
1734|
1735| imr.imr_multiaddr.s_addr = mreqs->imr_multiaddr;
1736| imr.imr_address.s_addr = mreqs->imr_interface;
1737| imr.imr_ifindex = ifindex;
1738| in_dev = ip_mc_find_dev(net, &imr);
1739|
1740| if (!in_dev) {
1741| err = -19;
1742| goto done;
1743| }
1744| err = -99;
1745|
1746| for (pmc = ({ do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !((lockdep_rtnl_is_held()))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 1951); } } while (0); ; ((typeof(*(inet->mc_list)) *)((inet->mc_list))); }); pmc != ((void *)0); pmc = ({ do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !((lockdep_rtnl_is_held()))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 1951); } } while (0); ; ((typeof(*(pmc->next_rcu)) *)((pmc->next_rcu))); })) {
1747| if ((pmc->multi.imr_multiaddr.s_addr ==
1748| imr.imr_multiaddr.s_addr) &&
1749| (pmc->multi.imr_ifindex == imr.imr_ifindex))
1750| break;
1751| }
1752| if (!pmc) {
1753| err = -22;
1754| goto done;
1755| }
1756|
1757| if (pmc->sflist) {
1758| if (pmc->sfmode != omode) {
1759| err = -22;
1760| goto done;
1761| }
1762| } else if (pmc->sfmode != omode) {
1763|
1764| ip_mc_add_src(in_dev, &mreqs->imr_multiaddr, omode, 0, ((void *)0), 0);
1765| ip_mc_del_src(in_dev, &mreqs->imr_multiaddr, pmc->sfmode, 0,
1766| ((void *)0), 0);
1767| pmc->sfmode = omode;
1768| }
1769|
1770| psl = ({ do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !((lockdep_rtnl_is_held()))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 1975); } } while (0); ; ((typeof(*(pmc->sflist)) *)((pmc->sflist))); });
1771| if (!add) {
1772| if (!psl)
1773| goto done;
1774| rv = !0;
1775| for (i=0; isl_count; i++) {
1776| rv = memcmp(&psl->sl_addr[i], &mreqs->imr_sourceaddr,
1777| sizeof(__be32));
1778| if (rv == 0)
1779| break;
1780| }
1781| if (rv)
1782| goto done;
1783|
1784|
1785| if (psl->sl_count == 1 && omode == 1) {
1786| leavegroup = 1;
1787| goto done;
1788| }
1789|
1790|
1791| ip_mc_del_src(in_dev, &mreqs->imr_multiaddr, omode, 1,
1792| &mreqs->imr_sourceaddr, 1);
1793|
1794| for (j=i+1; jsl_count; j++)
1795| psl->sl_addr[j-1] = psl->sl_addr[j];
1796| psl->sl_count--;
1797| err = 0;
1798| goto done;
1799| }
1800|
1801|
1802| if (psl && psl->sl_count >= sysctl_igmp_max_msf) {
1803| err = -105;
1804| goto done;
1805| }
1806| if (!psl || psl->sl_count == psl->sl_max) {
1807| struct ip_sf_socklist *newpsl;
1808| int count = 10;
1809|
1810| if (psl)
1811| count += psl->sl_max;
1812| newpsl = sock_kmalloc(sk, (sizeof(struct ip_sf_socklist) + (count) * sizeof(__be32)), __st_GFP_KERNEL_st__);
1813| if (!newpsl) {
1814| err = -105;
1815| goto done;
1816| }
1817| newpsl->sl_max = count;
1818| newpsl->sl_count = count - 10;
1819| if (psl) {
1820| for (i=0; isl_count; i++)
1821| newpsl->sl_addr[i] = psl->sl_addr[i];
1822|
1823| atomic_sub((sizeof(struct ip_sf_socklist) + (psl->sl_max) * sizeof(__be32)), &sk->sk_omem_alloc);
1824| call_rcu_sched(&psl->rcu, ip_sf_socklist_reclaim);
1825| }
1826| __st_rcu_assign_pointer_st__(pmc->sflist, newpsl);
1827| psl = newpsl;
1828| }
1829| rv = 1;
1830| for (i=0; isl_count; i++) {
1831| rv = memcmp(&psl->sl_addr[i], &mreqs->imr_sourceaddr,
1832| sizeof(__be32));
1833| if (rv == 0)
1834| break;
1835| }
1836| if (rv == 0)
1837| goto done;
1838| for (j=psl->sl_count-1; j>=i; j--)
1839| psl->sl_addr[j+1] = psl->sl_addr[j];
1840| psl->sl_addr[i] = mreqs->imr_sourceaddr;
1841| psl->sl_count++;
1842| err = 0;
1843|
1844| ip_mc_add_src(in_dev, &mreqs->imr_multiaddr, omode, 1,
1845| &mreqs->imr_sourceaddr, 1);
1846|done:
1847| rtnl_unlock();
1848| if (leavegroup)
1849| return ip_mc_leave_group(sk, &imr);
1850| return err;
1851|}
1852|
1853|int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex)
1854|{
1855| int err = 0;
1856| struct ip_mreqn imr;
1857| __be32 addr = msf->imsf_multiaddr;
1858| struct ip_mc_socklist *pmc;
1859| struct in_device *in_dev;
1860| struct inet_sock *inet = inet_sk(sk);
1861| struct ip_sf_socklist *newpsl, *psl;
1862| struct net *net = sock_net(sk);
1863| int leavegroup = 0;
1864|
1865| if (!ipv4_is_multicast(addr))
1866| return -22;
1867| if (msf->imsf_fmode != 1 &&
1868| msf->imsf_fmode != 0)
1869| return -22;
1870|
1871| rtnl_lock();
1872|
1873| imr.imr_multiaddr.s_addr = msf->imsf_multiaddr;
1874| imr.imr_address.s_addr = msf->imsf_interface;
1875| imr.imr_ifindex = ifindex;
1876| in_dev = ip_mc_find_dev(net, &imr);
1877|
1878| if (!in_dev) {
1879| err = -19;
1880| goto done;
1881| }
1882|
1883|
1884| if (msf->imsf_fmode == 1 && msf->imsf_numsrc == 0) {
1885| leavegroup = 1;
1886| goto done;
1887| }
1888|
1889| for (pmc = ({ do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !((lockdep_rtnl_is_held()))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 2094); } } while (0); ; ((typeof(*(inet->mc_list)) *)((inet->mc_list))); }); pmc != ((void *)0); pmc = ({ do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !((lockdep_rtnl_is_held()))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 2094); } } while (0); ; ((typeof(*(pmc->next_rcu)) *)((pmc->next_rcu))); })) {
1890| if (pmc->multi.imr_multiaddr.s_addr == msf->imsf_multiaddr &&
1891| pmc->multi.imr_ifindex == imr.imr_ifindex)
1892| break;
1893| }
1894| if (!pmc) {
1895| err = -22;
1896| goto done;
1897| }
1898| if (msf->imsf_numsrc) {
1899| newpsl = sock_kmalloc(sk, (sizeof(struct ip_sf_socklist) + (msf->imsf_numsrc) * sizeof(__be32)),
1900| __st_GFP_KERNEL_st__);
1901| if (!newpsl) {
1902| err = -105;
1903| goto done;
1904| }
1905| newpsl->sl_max = newpsl->sl_count = msf->imsf_numsrc;
1906| __st_memcpy_st__(newpsl->sl_addr, msf->imsf_slist,
1907| msf->imsf_numsrc * sizeof(msf->imsf_slist[0]));
1908| err = ip_mc_add_src(in_dev, &msf->imsf_multiaddr,
1909| msf->imsf_fmode, newpsl->sl_count, newpsl->sl_addr, 0);
1910| if (err) {
1911| sock_kfree_s(sk, newpsl, (sizeof(struct ip_sf_socklist) + (newpsl->sl_max) * sizeof(__be32)));
1912| goto done;
1913| }
1914| } else {
1915| newpsl = ((void *)0);
1916| (void) ip_mc_add_src(in_dev, &msf->imsf_multiaddr,
1917| msf->imsf_fmode, 0, ((void *)0), 0);
1918| }
1919| psl = ({ do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !((lockdep_rtnl_is_held()))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 2124); } } while (0); ; ((typeof(*(pmc->sflist)) *)((pmc->sflist))); });
1920| if (psl) {
1921| (void) ip_mc_del_src(in_dev, &msf->imsf_multiaddr, pmc->sfmode,
1922| psl->sl_count, psl->sl_addr, 0);
1923|
1924| atomic_sub((sizeof(struct ip_sf_socklist) + (psl->sl_max) * sizeof(__be32)), &sk->sk_omem_alloc);
1925| call_rcu_sched(&psl->rcu, ip_sf_socklist_reclaim);
1926| } else
1927| (void) ip_mc_del_src(in_dev, &msf->imsf_multiaddr, pmc->sfmode,
1928| 0, ((void *)0), 0);
1929| __st_rcu_assign_pointer_st__(pmc->sflist, newpsl);
1930| pmc->sfmode = msf->imsf_fmode;
1931| err = 0;
1932|done:
1933| rtnl_unlock();
1934| if (leavegroup)
1935| err = ip_mc_leave_group(sk, &imr);
1936| return err;
1937|}
1938|
1939|int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf,
1940| struct ip_msfilter *optval, int *optlen)
1941|{
1942| int err, len, count, copycount;
1943| struct ip_mreqn imr;
1944| __be32 addr = msf->imsf_multiaddr;
1945| struct ip_mc_socklist *pmc;
1946| struct in_device *in_dev;
1947| struct inet_sock *inet = inet_sk(sk);
1948| struct ip_sf_socklist *psl;
1949| struct net *net = sock_net(sk);
1950|
1951| if (!ipv4_is_multicast(addr))
1952| return -22;
1953|
1954| rtnl_lock();
1955|
1956| imr.imr_multiaddr.s_addr = msf->imsf_multiaddr;
1957| imr.imr_address.s_addr = msf->imsf_interface;
1958| imr.imr_ifindex = 0;
1959| in_dev = ip_mc_find_dev(net, &imr);
1960|
1961| if (!in_dev) {
1962| err = -19;
1963| goto done;
1964| }
1965| err = -99;
1966|
1967| for (pmc = ({ do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !((lockdep_rtnl_is_held()))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 2172); } } while (0); ; ((typeof(*(inet->mc_list)) *)((inet->mc_list))); }); pmc != ((void *)0); pmc = ({ do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !((lockdep_rtnl_is_held()))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 2172); } } while (0); ; ((typeof(*(pmc->next_rcu)) *)((pmc->next_rcu))); })) {
1968| if (pmc->multi.imr_multiaddr.s_addr == msf->imsf_multiaddr &&
1969| pmc->multi.imr_ifindex == imr.imr_ifindex)
1970| break;
1971| }
1972| if (!pmc)
1973| goto done;
1974| msf->imsf_fmode = pmc->sfmode;
1975| psl = ({ do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !((lockdep_rtnl_is_held()))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 2180); } } while (0); ; ((typeof(*(pmc->sflist)) *)((pmc->sflist))); });
1976| rtnl_unlock();
1977| if (!psl) {
1978| len = 0;
1979| count = 0;
1980| } else {
1981| count = psl->sl_count;
1982| }
1983| copycount = count < msf->imsf_numsrc ? count : msf->imsf_numsrc;
1984| len = copycount * sizeof(psl->sl_addr[0]);
1985| msf->imsf_numsrc = count;
1986| if (__st_put_user_st__((sizeof(struct ip_msfilter) - sizeof(__u32) + (copycount) * sizeof(__u32)), optlen) ||
1987| copy_to_user(optval, msf, (sizeof(struct ip_msfilter) - sizeof(__u32) + (0) * sizeof(__u32)))) {
1988| return -14;
1989| }
1990| if (len &&
1991| copy_to_user(&optval->imsf_slist[0], psl->sl_addr, len))
1992| return -14;
1993| return 0;
1994|done:
1995| rtnl_unlock();
1996| return err;
1997|}
1998|
1999|int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf,
2000| struct group_filter *optval, int *optlen)
2001|{
2002| int err, i, count, copycount;
2003| struct sockaddr_in *psin;
2004| __be32 addr;
2005| struct ip_mc_socklist *pmc;
2006| struct inet_sock *inet = inet_sk(sk);
2007| struct ip_sf_socklist *psl;
2008|
2009| psin = (struct sockaddr_in *)&gsf->gf_group;
2010| if (psin->sin_family != 2)
2011| return -22;
2012| addr = psin->sin_addr.s_addr;
2013| if (!ipv4_is_multicast(addr))
2014| return -22;
2015|
2016| rtnl_lock();
2017|
2018| err = -99;
2019|
2020| for (pmc = ({ do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !((lockdep_rtnl_is_held()))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 2225); } } while (0); ; ((typeof(*(inet->mc_list)) *)((inet->mc_list))); }); pmc != ((void *)0); pmc = ({ do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !((lockdep_rtnl_is_held()))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 2225); } } while (0); ; ((typeof(*(pmc->next_rcu)) *)((pmc->next_rcu))); })) {
2021| if (pmc->multi.imr_multiaddr.s_addr == addr &&
2022| pmc->multi.imr_ifindex == gsf->gf_interface)
2023| break;
2024| }
2025| if (!pmc)
2026| goto done;
2027| gsf->gf_fmode = pmc->sfmode;
2028| psl = ({ do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !((lockdep_rtnl_is_held()))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 2233); } } while (0); ; ((typeof(*(pmc->sflist)) *)((pmc->sflist))); });
2029| rtnl_unlock();
2030| count = psl ? psl->sl_count : 0;
2031| copycount = count < gsf->gf_numsrc ? count : gsf->gf_numsrc;
2032| gsf->gf_numsrc = count;
2033| if (__st_put_user_st__((sizeof(struct group_filter) - sizeof(struct __kernel_sockaddr_storage) + (copycount) * sizeof(struct __kernel_sockaddr_storage)), optlen) ||
2034| copy_to_user(optval, gsf, (sizeof(struct group_filter) - sizeof(struct __kernel_sockaddr_storage) + (0) * sizeof(struct __kernel_sockaddr_storage)))) {
2035| return -14;
2036| }
2037| for (i=0; i 2038| struct __kernel_sockaddr_storage ss;
2039|
2040| psin = (struct sockaddr_in *)&ss;
2041| __st_memset_st__(&ss, 0, sizeof(ss));
2042| psin->sin_family = 2;
2043| psin->sin_addr.s_addr = psl->sl_addr[i];
2044| if (copy_to_user(&optval->gf_slist[i], &ss, sizeof(ss)))
2045| return -14;
2046| }
2047| return 0;
2048|done:
2049| rtnl_unlock();
2050| return err;
2051|}
2052|
2053|
2054|
2055|
2056|int ip_mc_sf_allow(struct sock *sk, __be32 loc_addr, __be32 rmt_addr, int dif)
2057|{
2058| struct inet_sock *inet = inet_sk(sk);
2059| struct ip_mc_socklist *pmc;
2060| struct ip_sf_socklist *psl;
2061| int i;
2062| int ret;
2063|
2064| ret = 1;
2065| if (!ipv4_is_multicast(loc_addr))
2066| goto out;
2067|
2068| __st_rcu_read_lock_st__();
2069| for (pmc = ({ typeof(*(inet->mc_list)) *_________p1 = (typeof(*(inet->mc_list))* )(*(volatile typeof((inet->mc_list)) *)&((inet->mc_list))); do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !(rcu_read_lock_held() || (0))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 2274); } } while (0); ; do { } while (0); ((typeof(*(inet->mc_list)) *)(_________p1)); }); pmc != ((void *)0); pmc = ({ typeof(*(pmc->next_rcu)) *_________p1 = (typeof(*(pmc->next_rcu))* )(*(volatile typeof((pmc->next_rcu)) *)&((pmc->next_rcu))); do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !(rcu_read_lock_held() || (0))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 2274); } } while (0); ; do { } while (0); ((typeof(*(pmc->next_rcu)) *)(_________p1)); })) {
2070| if (pmc->multi.imr_multiaddr.s_addr == loc_addr &&
2071| pmc->multi.imr_ifindex == dif)
2072| break;
2073| }
2074| ret = inet->mc_all;
2075| if (!pmc)
2076| goto unlock;
2077| psl = ({ typeof(*(pmc->sflist)) *_________p1 = (typeof(*(pmc->sflist))* )(*(volatile typeof((pmc->sflist)) *)&((pmc->sflist))); do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !(rcu_read_lock_held() || (0))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 2282); } } while (0); ; do { } while (0); ((typeof(*(pmc->sflist)) *)(_________p1)); });
2078| ret = (pmc->sfmode == 0);
2079| if (!psl)
2080| goto unlock;
2081|
2082| for (i=0; isl_count; i++) {
2083| if (psl->sl_addr[i] == rmt_addr)
2084| break;
2085| }
2086| ret = 0;
2087| if (pmc->sfmode == 1 && i >= psl->sl_count)
2088| goto unlock;
2089| if (pmc->sfmode == 0 && i < psl->sl_count)
2090| goto unlock;
2091| ret = 1;
2092|unlock:
2093| __st_rcu_read_unlock_st__();
2094|out:
2095| return ret;
2096|}
2097|
2098|
2099|
2100|
2101|
2102|void ip_mc_drop_socket(struct sock *sk)
2103|{
2104| struct inet_sock *inet = inet_sk(sk);
2105| struct ip_mc_socklist *iml;
2106| struct net *net = sock_net(sk);
2107|
2108| if (inet->mc_list == ((void *)0))
2109| return;
2110|
2111| rtnl_lock();
2112| while ((iml = ({ do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !((lockdep_rtnl_is_held()))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 2317); } } while (0); ; ((typeof(*(inet->mc_list)) *)((inet->mc_list))); })) != ((void *)0)) {
2113| struct in_device *in_dev;
2114|
2115| inet->mc_list = iml->next_rcu;
2116| in_dev = inetdev_by_index(net, iml->multi.imr_ifindex);
2117| (void) ip_mc_leave_src(sk, iml, in_dev);
2118| if (in_dev != ((void *)0))
2119| ip_mc_dec_group(in_dev, iml->multi.imr_multiaddr.s_addr);
2120|
2121| atomic_sub(sizeof(*iml), &sk->sk_omem_alloc);
2122| call_rcu_sched(&iml->rcu, ip_mc_socklist_reclaim);
2123| }
2124| rtnl_unlock();
2125|}
2126|
2127|int ip_check_mc(struct in_device *in_dev, __be32 mc_addr, __be32 src_addr, u16 proto)
2128|{
2129| struct ip_mc_list *im;
2130| struct ip_sf_list *psf;
2131| int rv = 0;
2132|
2133| __st_rcu_read_lock_st__();
2134| for (im = ({ typeof(*(in_dev->mc_list)) *_________p1 = (typeof(*(in_dev->mc_list))* )(*(volatile typeof((in_dev->mc_list)) *)&((in_dev->mc_list))); do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !(rcu_read_lock_held() || (0))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 2339); } } while (0); ; do { } while (0); ((typeof(*(in_dev->mc_list)) *)(_________p1)); }); im != ((void *)0); im = ({ typeof(*(im->next_rcu)) *_________p1 = (typeof(*(im->next_rcu))* )(*(volatile typeof((im->next_rcu)) *)&((im->next_rcu))); do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !(rcu_read_lock_held() || (0))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 2339); } } while (0); ; do { } while (0); ((typeof(*(im->next_rcu)) *)(_________p1)); })) {
2135| if (im->multiaddr == mc_addr)
2136| break;
2137| }
2138| if (im && proto == IPPROTO_IGMP) {
2139| rv = 1;
2140| } else if (im) {
2141| if (src_addr) {
2142| for (psf=im->sources; psf; psf=psf->sf_next) {
2143| if (psf->sf_inaddr == src_addr)
2144| break;
2145| }
2146| if (psf)
2147| rv = psf->sf_count[1] ||
2148| psf->sf_count[0] !=
2149| im->sfcount[0];
2150| else
2151| rv = im->sfcount[0] != 0;
2152| } else
2153| rv = 1;
2154| }
2155| __st_rcu_read_unlock_st__();
2156| return rv;
2157|}
2158|
2159|
2160|struct igmp_mc_iter_state {
2161| struct seq_net_private p;
2162| struct net_device *dev;
2163| struct in_device *in_dev;
2164|};
2165|
2166|
2167|
2168|static inline struct ip_mc_list *igmp_mc_get_first(struct seq_file *seq)
2169|{
2170| struct net *net = seq_file_net(seq);
2171| struct ip_mc_list *im = ((void *)0);
2172| struct igmp_mc_iter_state *state = ((struct igmp_mc_iter_state *)(seq)->private);
2173|
2174| state->in_dev = ((void *)0);
2175| for (state->dev = ({typeof (*(&(net)->dev_base_head)->next) *__ptr = (typeof (*(&(net)->dev_base_head)->next) *)(&(net)->dev_base_head)->next; ({ const typeof( ((typeof(*state->dev) *)0)->dev_list ) *__mptr = ((typeof((&(net)->dev_base_head)->next))({ typeof(*(__ptr)) *_________p1 = (typeof(*(__ptr))* )(*(volatile typeof((__ptr)) *)&((__ptr))); do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !(rcu_read_lock_held() || (1))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 2380); } } while (0); ; do { } while (0); ((typeof(*(__ptr)) *)(_________p1)); })); (typeof(*state->dev) *)( (char *)__mptr - 1 );}); }); __builtin_prefetch(state->dev->dev_list.next), &state->dev->dev_list != (&(net)->dev_base_head); state->dev = ({typeof (*state->dev->dev_list.next) *__ptr = (typeof (*state->dev->dev_list.next) *)state->dev->dev_list.next; ({ const typeof( ((typeof(*state->dev) *)0)->dev_list ) *__mptr = ((typeof(state->dev->dev_list.next))({ typeof(*(__ptr)) *_________p1 = (typeof(*(__ptr))* )(*(volatile typeof((__ptr)) *)&((__ptr))); do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !(rcu_read_lock_held() || (1))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 2380); } } while (0); ; do { } while (0); ((typeof(*(__ptr)) *)(_________p1)); })); (typeof(*state->dev) *)( (char *)__mptr - 1 );}); })) {
2176| struct in_device *in_dev;
2177|
2178| in_dev = __in_dev_get_rcu(state->dev);
2179| if (!in_dev)
2180| continue;
2181| im = ({ typeof(*(in_dev->mc_list)) *_________p1 = (typeof(*(in_dev->mc_list))* )(*(volatile typeof((in_dev->mc_list)) *)&((in_dev->mc_list))); do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !(rcu_read_lock_held() || (0))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 2386); } } while (0); ; do { } while (0); ((typeof(*(in_dev->mc_list)) *)(_________p1)); });
2182| if (im) {
2183| state->in_dev = in_dev;
2184| break;
2185| }
2186| }
2187| return im;
2188|}
2189|
2190|static struct ip_mc_list *igmp_mc_get_next(struct seq_file *seq, struct ip_mc_list *im)
2191|{
2192| struct igmp_mc_iter_state *state = ((struct igmp_mc_iter_state *)(seq)->private);
2193|
2194| im = ({ typeof(*(im->next_rcu)) *_________p1 = (typeof(*(im->next_rcu))* )(*(volatile typeof((im->next_rcu)) *)&((im->next_rcu))); do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !(rcu_read_lock_held() || (0))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 2399); } } while (0); ; do { } while (0); ((typeof(*(im->next_rcu)) *)(_________p1)); });
2195| while (!im) {
2196| state->dev = next_net_device_rcu(state->dev);
2197| if (!state->dev) {
2198| state->in_dev = ((void *)0);
2199| break;
2200| }
2201| state->in_dev = __in_dev_get_rcu(state->dev);
2202| if (!state->in_dev)
2203| continue;
2204| im = ({ typeof(*(state->in_dev->mc_list)) *_________p1 = (typeof(*(state->in_dev->mc_list))* )(*(volatile typeof((state->in_dev->mc_list)) *)&((state->in_dev->mc_list))); do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !(rcu_read_lock_held() || (0))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 2409); } } while (0); ; do { } while (0); ((typeof(*(state->in_dev->mc_list)) *)(_________p1)); });
2205| }
2206| return im;
2207|}
2208|
2209|static struct ip_mc_list *igmp_mc_get_idx(struct seq_file *seq, loff_t pos)
2210|{
2211| struct ip_mc_list *im = igmp_mc_get_first(seq);
2212| if (im)
2213| while (pos && (im = igmp_mc_get_next(seq, im)) != ((void *)0))
2214| --pos;
2215| return pos ? ((void *)0) : im;
2216|}
2217|
2218|static void *igmp_mc_seq_start(struct seq_file *seq, loff_t *pos)
2219|
2220|{
2221| __st_rcu_read_lock_st__();
2222| return *pos ? igmp_mc_get_idx(seq, *pos - 1) : ((void *)1);
2223|}
2224|
2225|static void *igmp_mc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2226|{
2227| struct ip_mc_list *im;
2228| if (v == ((void *)1))
2229| im = igmp_mc_get_first(seq);
2230| else
2231| im = igmp_mc_get_next(seq, v);
2232| ++*pos;
2233| return im;
2234|}
2235|
2236|static void igmp_mc_seq_stop(struct seq_file *seq, void *v)
2237|
2238|{
2239| struct igmp_mc_iter_state *state = ((struct igmp_mc_iter_state *)(seq)->private);
2240|
2241| state->in_dev = ((void *)0);
2242| state->dev = ((void *)0);
2243| __st_rcu_read_unlock_st__();
2244|}
2245|
2246|static int igmp_mc_seq_show(struct seq_file *seq, void *v)
2247|{
2248| if (v == ((void *)1))
2249| seq_puts(seq,
2250| "Idx\tDevice : Count Querier\tGroup Users Timer\tReporter\n");
2251| else {
2252| struct ip_mc_list *im = (struct ip_mc_list *)v;
2253| struct igmp_mc_iter_state *state = ((struct igmp_mc_iter_state *)(seq)->private);
2254| char *querier;
2255|
2256| querier = ((((*(dev_net(state->in_dev->dev))->ipv4.devconf_all)).data[IPV4_DEVCONF_FORCE_IGMP_VERSION - 1]) == 1 || ipv4_devconf_get(((state->in_dev)), IPV4_DEVCONF_FORCE_IGMP_VERSION) == 1 || ((state->in_dev)->mr_v1_seen && (({ unsigned long __dummy; typeof((state->in_dev)->mr_v1_seen) __dummy2; (void)(&__dummy == &__dummy2); 1; }) && ({ unsigned long __dummy; typeof(jiffies) __dummy2; (void)(&__dummy == &__dummy2); 1; }) && ((long)(jiffies) - (long)((state->in_dev)->mr_v1_seen) < 0)))) ? "V1" :
2257| ((((*(dev_net(state->in_dev->dev))->ipv4.devconf_all)).data[IPV4_DEVCONF_FORCE_IGMP_VERSION - 1]) == 2 || ipv4_devconf_get(((state->in_dev)), IPV4_DEVCONF_FORCE_IGMP_VERSION) == 2 || ((state->in_dev)->mr_v2_seen && (({ unsigned long __dummy; typeof((state->in_dev)->mr_v2_seen) __dummy2; (void)(&__dummy == &__dummy2); 1; }) && ({ unsigned long __dummy; typeof(jiffies) __dummy2; (void)(&__dummy == &__dummy2); 1; }) && ((long)(jiffies) - (long)((state->in_dev)->mr_v2_seen) < 0)))) ? "V2" :
2258| "V3";
2259|
2260|
2261|
2262|
2263| if (({ typeof(*(state->in_dev->mc_list)) *_________p1 = (typeof(*(state->in_dev->mc_list))* )(*(volatile typeof((state->in_dev->mc_list)) *)&((state->in_dev->mc_list))); do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !(rcu_read_lock_held() || (0))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 2468); } } while (0); ; do { } while (0); ((typeof(*(state->in_dev->mc_list)) *)(_________p1)); }) == im) {
2264| seq_printf(seq, "%d\t%-10s: %5d %7s\n",
2265| state->dev->ifindex, state->dev->name, state->in_dev->mc_count, querier);
2266| }
2267|
2268| seq_printf(seq,
2269| "\t\t\t\t%08X %5d %d:%08lX\t\t%d\n",
2270| im->multiaddr, im->users,
2271| im->tm_running, im->tm_running ?
2272| jiffies_to_clock_t(im->timer.expires-jiffies) : 0,
2273| im->reporter);
2274| }
2275| return 0;
2276|}
2277|
2278|static const struct seq_operations igmp_mc_seq_ops = {
2279| .start = igmp_mc_seq_start,
2280| .next = igmp_mc_seq_next,
2281| .stop = igmp_mc_seq_stop,
2282| .show = igmp_mc_seq_show,
2283|};
2284|
2285|static int igmp_mc_seq_open(struct inode *inode, struct file *file)
2286|{
2287| return seq_open_net(inode, file, &igmp_mc_seq_ops,
2288| sizeof(struct igmp_mc_iter_state));
2289|}
2290|
2291|static const struct file_operations igmp_mc_seq_fops = {
2292| .owner = ((struct module *)0),
2293| .open = igmp_mc_seq_open,
2294| .read = seq_read,
2295| .llseek = seq_lseek,
2296| .release = seq_release_net,
2297|};
2298|
2299|struct igmp_mcf_iter_state {
2300| struct seq_net_private p;
2301| struct net_device *dev;
2302| struct in_device *idev;
2303| struct ip_mc_list *im;
2304|};
2305|
2306|
2307|
2308|static inline struct ip_sf_list *igmp_mcf_get_first(struct seq_file *seq)
2309|{
2310| struct net *net = seq_file_net(seq);
2311| struct ip_sf_list *psf = ((void *)0);
2312| struct ip_mc_list *im = ((void *)0);
2313| struct igmp_mcf_iter_state *state = ((struct igmp_mcf_iter_state *)(seq)->private);
2314|
2315| state->idev = ((void *)0);
2316| state->im = ((void *)0);
2317| for (state->dev = ({typeof (*(&(net)->dev_base_head)->next) *__ptr = (typeof (*(&(net)->dev_base_head)->next) *)(&(net)->dev_base_head)->next; ({ const typeof( ((typeof(*state->dev) *)0)->dev_list ) *__mptr = ((typeof((&(net)->dev_base_head)->next))({ typeof(*(__ptr)) *_________p1 = (typeof(*(__ptr))* )(*(volatile typeof((__ptr)) *)&((__ptr))); do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !(rcu_read_lock_held() || (1))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 2522); } } while (0); ; do { } while (0); ((typeof(*(__ptr)) *)(_________p1)); })); (typeof(*state->dev) *)( (char *)__mptr - 1 );}); }); __builtin_prefetch(state->dev->dev_list.next), &state->dev->dev_list != (&(net)->dev_base_head); state->dev = ({typeof (*state->dev->dev_list.next) *__ptr = (typeof (*state->dev->dev_list.next) *)state->dev->dev_list.next; ({ const typeof( ((typeof(*state->dev) *)0)->dev_list ) *__mptr = ((typeof(state->dev->dev_list.next))({ typeof(*(__ptr)) *_________p1 = (typeof(*(__ptr))* )(*(volatile typeof((__ptr)) *)&((__ptr))); do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !(rcu_read_lock_held() || (1))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 2522); } } while (0); ; do { } while (0); ((typeof(*(__ptr)) *)(_________p1)); })); (typeof(*state->dev) *)( (char *)__mptr - 1 );}); })) {
2318| struct in_device *idev;
2319| idev = __in_dev_get_rcu(state->dev);
2320| if (idev == ((void *)0))
2321| continue;
2322| im = ({ typeof(*(idev->mc_list)) *_________p1 = (typeof(*(idev->mc_list))* )(*(volatile typeof((idev->mc_list)) *)&((idev->mc_list))); do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !(rcu_read_lock_held() || (0))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 2527); } } while (0); ; do { } while (0); ((typeof(*(idev->mc_list)) *)(_________p1)); });
2323| if (im != ((void *)0)) {
2324| __st_spin_lock_bh_st__(&im->lock);
|The lock is locked here. prev next
2325| psf = im->sources;
|not affected ==> the lock is still locked. prev next
2326| if (psf != ((void *)0)) {
|not affected ==> the lock is still locked. prev next
2327| state->im = im;
|not affected ==> the lock is still locked. prev next
2328| state->idev = idev;
|not affected ==> the lock is still locked. prev next
2329| break;
|not affected ==> the lock is still locked. prev next
2330| }
2331| __st_spin_unlock_bh_st__(&im->lock);
2332| }
2333| }
2334| return psf;
|not affected ==> the lock is still locked. prev next
2335|}
|not affected ==> the lock is still locked. prev next
2336|
2337|static struct ip_sf_list *igmp_mcf_get_next(struct seq_file *seq, struct ip_sf_list *psf)
2338|{
2339| struct igmp_mcf_iter_state *state = ((struct igmp_mcf_iter_state *)(seq)->private);
2340|
2341| psf = psf->sf_next;
2342| while (!psf) {
2343| __st_spin_unlock_bh_st__(&state->im->lock);
2344| state->im = state->im->next;
2345| while (!state->im) {
2346| state->dev = next_net_device_rcu(state->dev);
2347| if (!state->dev) {
2348| state->idev = ((void *)0);
2349| goto out;
2350| }
2351| state->idev = __in_dev_get_rcu(state->dev);
2352| if (!state->idev)
2353| continue;
2354| state->im = ({ typeof(*(state->idev->mc_list)) *_________p1 = (typeof(*(state->idev->mc_list))* )(*(volatile typeof((state->idev->mc_list)) *)&((state->idev->mc_list))); do { static bool __warned; if (debug_lockdep_rcu_enabled() && !__warned && !(rcu_read_lock_held() || (0))) { __warned = true; lockdep_rcu_dereference("net/ipv4/.tmp_igmp.o.armored.c", 2559); } } while (0); ; do { } while (0); ((typeof(*(state->idev->mc_list)) *)(_________p1)); });
2355| }
2356| if (!state->im)
2357| break;
2358| __st_spin_lock_bh_st__(&state->im->lock);
2359| psf = state->im->sources;
2360| }
2361|out:
2362| return psf;
2363|}
2364|
2365|static struct ip_sf_list *igmp_mcf_get_idx(struct seq_file *seq, loff_t pos)
2366|{
2367| struct ip_sf_list *psf = igmp_mcf_get_first(seq);
2368| if (psf)
2369| while (pos && (psf = igmp_mcf_get_next(seq, psf)) != ((void *)0))
2370| --pos;
2371| return pos ? ((void *)0) : psf;
2372|}
2373|
2374|static void *igmp_mcf_seq_start(struct seq_file *seq, loff_t *pos)
2375|
2376|{
2377| __st_rcu_read_lock_st__();
2378| return *pos ? igmp_mcf_get_idx(seq, *pos - 1) : ((void *)1);
2379|}
2380|
2381|static void *igmp_mcf_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2382|{
2383| struct ip_sf_list *psf;
2384| if (v == ((void *)1))
2385| psf = igmp_mcf_get_first(seq);
|not affected ==> the lock is still locked. prev next
2386| else
2387| psf = igmp_mcf_get_next(seq, v);
2388| ++*pos;
|not affected ==> the lock is still locked. prev next
2389| return psf;
|not affected ==> the lock is still locked. prev next
2390|}
|Leaving function in locked state.[& . * im_1 lock] prev
2391|
2392|static void igmp_mcf_seq_stop(struct seq_file *seq, void *v)
2393|
2394|{
2395| struct igmp_mcf_iter_state *state = ((struct igmp_mcf_iter_state *)(seq)->private);
2396| if (state->im != ((void *)0)) {
2397| __st_spin_unlock_bh_st__(&state->im->lock);
2398| state->im = ((void *)0);
2399| }
2400| state->idev = ((void *)0);
2401| state->dev = ((void *)0);
2402| __st_rcu_read_unlock_st__();
2403|}
2404|
2405|static int igmp_mcf_seq_show(struct seq_file *seq, void *v)
2406|{
2407| struct ip_sf_list *psf = (struct ip_sf_list *)v;
2408| struct igmp_mcf_iter_state *state = ((struct igmp_mcf_iter_state *)(seq)->private);
2409|
2410| if (v == ((void *)1)) {
2411| seq_printf(seq,
2412| "%3s %6s "
2413| "%10s %10s %6s %6s\n", "Idx",
2414| "Device", "MCA",
2415| "SRC", "INC", "EXC");
2416| } else {
2417| seq_printf(seq,
2418| "%3d %6.6s 0x%08x "
2419| "0x%08x %6lu %6lu\n",
2420| state->dev->ifindex, state->dev->name,
2421| (__builtin_constant_p((__u32)(( __u32)(__be32)(state->im->multiaddr))) ? ((__u32)( (((__u32)(( __u32)(__be32)(state->im->multiaddr)) & (__u32)0x000000ffUL) << 24) | (((__u32)(( __u32)(__be32)(state->im->multiaddr)) & (__u32)0x0000ff00UL) << 8) | (((__u32)(( __u32)(__be32)(state->im->multiaddr)) & (__u32)0x00ff0000UL) >> 8) | (((__u32)(( __u32)(__be32)(state->im->multiaddr)) & (__u32)0xff000000UL) >> 24))) : __fswab32(( __u32)(__be32)(state->im->multiaddr))),
2422| (__builtin_constant_p((__u32)(( __u32)(__be32)(psf->sf_inaddr))) ? ((__u32)( (((__u32)(( __u32)(__be32)(psf->sf_inaddr)) & (__u32)0x000000ffUL) << 24) | (((__u32)(( __u32)(__be32)(psf->sf_inaddr)) & (__u32)0x0000ff00UL) << 8) | (((__u32)(( __u32)(__be32)(psf->sf_inaddr)) & (__u32)0x00ff0000UL) >> 8) | (((__u32)(( __u32)(__be32)(psf->sf_inaddr)) & (__u32)0xff000000UL) >> 24))) : __fswab32(( __u32)(__be32)(psf->sf_inaddr))),
2423| psf->sf_count[1],
2424| psf->sf_count[0]);
2425| }
2426| return 0;
2427|}
2428|
2429|static const struct seq_operations igmp_mcf_seq_ops = {
2430| .start = igmp_mcf_seq_start,
2431| .next = igmp_mcf_seq_next,
2432| .stop = igmp_mcf_seq_stop,
2433| .show = igmp_mcf_seq_show,
2434|};
2435|
2436|static int igmp_mcf_seq_open(struct inode *inode, struct file *file)
2437|{
2438| return seq_open_net(inode, file, &igmp_mcf_seq_ops,
2439| sizeof(struct igmp_mcf_iter_state));
2440|}
2441|
2442|static const struct file_operations igmp_mcf_seq_fops = {
2443| .owner = ((struct module *)0),
2444| .open = igmp_mcf_seq_open,
2445| .read = seq_read,
2446| .llseek = seq_lseek,
2447| .release = seq_release_net,
2448|};
2449|
2450|static int igmp_net_init(struct net *net)
2451|{
2452| struct proc_dir_entry *pde;
2453|
2454| pde = proc_net_fops_create(net, "igmp", (00400|00040|00004), &igmp_mc_seq_fops);
2455| if (!pde)
2456| goto out_igmp;
2457| pde = proc_net_fops_create(net, "mcfilter", (00400|00040|00004), &igmp_mcf_seq_fops);
2458| if (!pde)
2459| goto out_mcfilter;
2460| return 0;
2461|
2462|out_mcfilter:
2463| proc_net_remove(net, "igmp");
2464|out_igmp:
2465| return -12;
2466|}
2467|
2468|static void igmp_net_exit(struct net *net)
2469|{
2470| proc_net_remove(net, "mcfilter");
2471| proc_net_remove(net, "igmp");
2472|}
2473|
2474|static struct pernet_operations igmp_net_ops = {
2475| .init = igmp_net_init,
2476| .exit = igmp_net_exit,
2477|};
2478|
2479|int igmp_mc_proc_init(void)
2480|{
2481| return register_pernet_subsys(&igmp_net_ops);
2482|}