00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
#include <linux/config.h>
00077
#include <asm/uaccess.h>
00078
#include <asm/system.h>
00079
#include <linux/types.h>
00080
#include <linux/kernel.h>
00081
#include <linux/sched.h>
00082
#include <linux/string.h>
00083
#include <linux/socket.h>
00084
#include <linux/sockios.h>
00085
#include <linux/in.h>
00086
#include <linux/inet.h>
00087
#include <linux/netdevice.h>
00088
#include <linux/skbuff.h>
00089
#include <linux/inetdevice.h>
00090
#include <linux/igmp.h>
00091
#include <linux/if_arp.h>
00092
#include <linux/rtnetlink.h>
00093
#include <net/ip.h>
00094
#include <net/protocol.h>
00095
#include <net/route.h>
00096
#include <net/sock.h>
00097
#include <net/checksum.h>
00098
#include <linux/netfilter_ipv4.h>
00099
#ifdef CONFIG_IP_MROUTE
00100
#include <linux/mroute.h>
00101
#endif
00102
00103
00104 #define IP_MAX_MEMBERSHIPS 20
00105
00106
#ifdef CONFIG_IP_MULTICAST
00107
00108
00109
#define IGMP_V1_Router_Present_Timeout (400*HZ)
00110
#define IGMP_V2_Router_Present_Timeout (400*HZ)
00111
#define IGMP_Unsolicited_Report_Interval (10*HZ)
00112
#define IGMP_Query_Response_Interval (10*HZ)
00113
#define IGMP_Unsolicited_Report_Count 2
00114
00115
00116
#define IGMP_Initial_Report_Delay (1)
00117
00118
00119
00120
00121
00122
00123
00124
00125
#define IGMP_V1_SEEN(in_dev) ((in_dev)->mr_v1_seen && \
00126
time_before(jiffies, (in_dev)->mr_v1_seen))
00127
#define IGMP_V2_SEEN(in_dev) ((in_dev)->mr_v2_seen && \
00128
time_before(jiffies, (in_dev)->mr_v2_seen))
00129
00130
static void igmpv3_add_delrec(
struct in_device *in_dev,
struct ip_mc_list *im);
00131
static void igmpv3_del_delrec(
struct in_device *in_dev, __u32 multiaddr);
00132
static void igmpv3_clear_delrec(
struct in_device *in_dev);
00133
static int sf_setstate(
struct ip_mc_list *pmc);
00134
static void sf_markstate(
struct ip_mc_list *pmc);
00135
#endif
00136
static void ip_mc_clear_src(
struct ip_mc_list *pmc);
00137
int ip_mc_add_src(
struct in_device *in_dev, __u32 *pmca,
int sfmode,
00138
int sfcount, __u32 *psfsrc,
int delta);
00139
00140 static void ip_ma_put(
struct ip_mc_list *im)
00141 {
00142
if (atomic_dec_and_test(&im->refcnt)) {
00143
in_dev_put(im->interface);
00144 kfree(im);
00145 }
00146 }
00147
00148
#ifdef CONFIG_IP_MULTICAST
00149
00150
00151
00152
00153
00154
static __inline__
void igmp_stop_timer(
struct ip_mc_list *im)
00155 {
00156 spin_lock_bh(&im->lock);
00157
if (del_timer(&im->timer))
00158 atomic_dec(&im->refcnt);
00159 im->tm_running=0;
00160 im->reporter = 0;
00161 im->unsolicit_count = 0;
00162 spin_unlock_bh(&im->lock);
00163 }
00164
00165
00166
static void igmp_start_timer(
struct ip_mc_list *im,
int max_delay)
00167 {
00168
int tv=
net_random() % max_delay;
00169
00170 im->tm_running=1;
00171
if (!mod_timer(&im->timer, jiffies+tv+2))
00172 atomic_inc(&im->refcnt);
00173 }
00174
00175
static void igmp_gq_start_timer(
struct in_device *in_dev)
00176 {
00177
int tv =
net_random() % in_dev->
mr_maxdelay;
00178
00179 in_dev->
mr_gq_running = 1;
00180
if (!mod_timer(&in_dev->
mr_gq_timer, jiffies+tv+2))
00181
in_dev_hold(in_dev);
00182 }
00183
00184
static void igmp_ifc_start_timer(
struct in_device *in_dev,
int delay)
00185 {
00186
int tv =
net_random() % delay;
00187
00188
if (!mod_timer(&in_dev->
mr_ifc_timer, jiffies+tv+2))
00189
in_dev_hold(in_dev);
00190 }
00191
00192
static void igmp_mod_timer(
struct ip_mc_list *im,
int max_delay)
00193 {
00194 spin_lock_bh(&im->lock);
00195 im->unsolicit_count = 0;
00196
if (del_timer(&im->timer)) {
00197
if ((
long)(im->timer.expires-jiffies) < max_delay) {
00198 add_timer(&im->timer);
00199 im->tm_running=1;
00200 spin_unlock_bh(&im->lock);
00201
return;
00202 }
00203 atomic_dec(&im->refcnt);
00204 }
00205 igmp_start_timer(im, max_delay);
00206 spin_unlock_bh(&im->lock);
00207 }
00208
00209
00210
00211
00212
00213
00214
#define IGMP_SIZE (sizeof(struct igmphdr)+sizeof(struct iphdr)+4)
00215
00216
00217
00218
static inline int
00219
output_maybe_reroute(
struct sk_buff *skb)
00220 {
00221
return skb->
dst->
output(skb);
00222 }
00223
00224
00225
static int is_in(
struct ip_mc_list *pmc,
struct ip_sf_list *psf,
int type,
00226
int gdeleted,
int sdeleted)
00227 {
00228
switch (type) {
00229
case IGMPV3_MODE_IS_INCLUDE:
00230
case IGMPV3_MODE_IS_EXCLUDE:
00231
if (gdeleted || sdeleted)
00232
return 0;
00233
return !(pmc->gsquery && !psf->sf_gsresp);
00234
case IGMPV3_CHANGE_TO_INCLUDE:
00235
if (gdeleted || sdeleted)
00236
return 0;
00237
return psf->sf_count[
MCAST_INCLUDE] != 0;
00238
case IGMPV3_CHANGE_TO_EXCLUDE:
00239
if (gdeleted || sdeleted)
00240
return 0;
00241
if (pmc->sfcount[
MCAST_EXCLUDE] == 0 ||
00242 psf->sf_count[
MCAST_INCLUDE])
00243
return 0;
00244
return pmc->sfcount[
MCAST_EXCLUDE] ==
00245 psf->sf_count[
MCAST_EXCLUDE];
00246
case IGMPV3_ALLOW_NEW_SOURCES:
00247
if (gdeleted || !psf->sf_crcount)
00248
return 0;
00249
return (pmc->sfmode ==
MCAST_INCLUDE) ^ sdeleted;
00250
case IGMPV3_BLOCK_OLD_SOURCES:
00251
if (pmc->sfmode ==
MCAST_INCLUDE)
00252
return gdeleted || (psf->sf_crcount && sdeleted);
00253
return psf->sf_crcount && !gdeleted && !sdeleted;
00254 }
00255
return 0;
00256 }
00257
00258
static int
00259 igmp_scount(
struct ip_mc_list *pmc,
int type,
int gdeleted,
int sdeleted)
00260 {
00261
struct ip_sf_list *psf;
00262
int scount = 0;
00263
00264
for (psf=pmc->sources; psf; psf=psf->sf_next) {
00265
if (!is_in(pmc, psf, type, gdeleted, sdeleted))
00266
continue;
00267 scount++;
00268 }
00269
return scount;
00270 }
00271
00272
static struct sk_buff *igmpv3_newpack(
struct net_device *dev,
int size)
00273 {
00274
struct sk_buff *skb;
00275
struct rtable *rt;
00276
struct iphdr *pip;
00277
struct igmpv3_report *pig;
00278 u32 dst;
00279
00280 dst = IGMPV3_ALL_MCR;
00281
if (
ip_route_output(&rt, dst, 0, 0, dev->
ifindex))
00282
return 0;
00283
if (rt->rt_src == 0) {
00284
ip_rt_put(rt);
00285
return 0;
00286 }
00287 skb =
alloc_skb(size + dev->
hard_header_len + 15, GFP_ATOMIC);
00288
if (skb == NULL) {
00289
ip_rt_put(rt);
00290
return 0;
00291 }
00292
00293 skb->dst = &rt->u.dst;
00294 skb->dev = dev;
00295
00296
skb_reserve(skb, (dev->
hard_header_len+15)&~15);
00297
00298 skb->nh.iph = pip =(
struct iphdr *)
skb_put(skb,
sizeof(
struct iphdr)+4);
00299
00300 pip->version = 4;
00301 pip->ihl = (
sizeof(
struct iphdr)+4)>>2;
00302 pip->tos = 0xc0;
00303 pip->frag_off = htons(IP_DF);
00304 pip->ttl = 1;
00305 pip->daddr = rt->rt_dst;
00306 pip->saddr = rt->rt_src;
00307 pip->protocol =
IPPROTO_IGMP;
00308 pip->tot_len = 0;
00309
ip_select_ident(pip, &rt->u.dst, NULL);
00310 ((u8*)&pip[1])[0] =
IPOPT_RA;
00311 ((u8*)&pip[1])[1] = 4;
00312 ((u8*)&pip[1])[2] = 0;
00313 ((u8*)&pip[1])[3] = 0;
00314
00315 pig =(
struct igmpv3_report *)
skb_put(skb,
sizeof(*pig));
00316 skb->h.igmph = (
struct igmphdr *)pig;
00317 pig->type = IGMPV3_HOST_MEMBERSHIP_REPORT;
00318 pig->resv1 = 0;
00319 pig->csum = 0;
00320 pig->resv2 = 0;
00321 pig->ngrec = 0;
00322
return skb;
00323 }
00324
00325
static int igmpv3_sendpack(
struct sk_buff *skb)
00326 {
00327
struct iphdr *pip = skb->
nh.iph;
00328
struct igmphdr *pig = skb->
h.igmph;
00329
int iplen, igmplen;
00330
00331 iplen = skb->
tail - (
unsigned char *)skb->
nh.iph;
00332 pip->tot_len = htons(iplen);
00333
ip_send_check(pip);
00334
00335 igmplen = skb->
tail - (
unsigned char *)skb->
h.igmph;
00336 pig->csum =
ip_compute_csum((
void *)skb->
h.igmph, igmplen);
00337
00338
return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, skb->
dev,
00339 output_maybe_reroute);
00340 }
00341
00342
static int grec_size(
struct ip_mc_list *pmc,
int type,
int gdel,
int sdel)
00343 {
00344
return sizeof(
struct igmpv3_grec) + 4*igmp_scount(pmc,type,gdel,sdel);
00345 }
00346
00347
static struct sk_buff *add_grhead(
struct sk_buff *skb,
struct ip_mc_list *pmc,
00348
int type,
struct igmpv3_grec **ppgr)
00349 {
00350
struct net_device *dev = pmc->interface->dev;
00351
struct igmpv3_report *pih;
00352
struct igmpv3_grec *pgr;
00353
00354
if (!skb)
00355 skb = igmpv3_newpack(dev, dev->
mtu);
00356
if (!skb)
00357
return 0;
00358 pgr = (
struct igmpv3_grec *)
skb_put(skb,
sizeof(
struct igmpv3_grec));
00359 pgr->grec_type = type;
00360 pgr->grec_auxwords = 0;
00361 pgr->grec_nsrcs = 0;
00362 pgr->grec_mca = pmc->multiaddr;
00363 pih = (
struct igmpv3_report *)skb->
h.igmph;
00364 pih->ngrec = htons(ntohs(pih->ngrec)+1);
00365 *ppgr = pgr;
00366
return skb;
00367 }
00368
00369
#define AVAILABLE(skb) ((skb) ? ((skb)->dev ? (skb)->dev->mtu - (skb)->len : \
00370
skb_tailroom(skb)) : 0)
00371
00372
static struct sk_buff *add_grec(
struct sk_buff *skb,
struct ip_mc_list *pmc,
00373
int type,
int gdeleted,
int sdeleted)
00374 {
00375
struct net_device *dev = pmc->interface->dev;
00376
struct igmpv3_report *pih;
00377
struct igmpv3_grec *pgr = 0;
00378
struct ip_sf_list *psf, *psf_next, *psf_prev, **psf_list;
00379
int scount, first, isquery, truncate;
00380
00381
if (pmc->multiaddr == IGMP_ALL_HOSTS)
00382
return skb;
00383
00384 isquery = type == IGMPV3_MODE_IS_INCLUDE ||
00385 type == IGMPV3_MODE_IS_EXCLUDE;
00386 truncate = type == IGMPV3_MODE_IS_EXCLUDE ||
00387 type == IGMPV3_CHANGE_TO_EXCLUDE;
00388
00389 psf_list = sdeleted ? &pmc->tomb : &pmc->sources;
00390
00391
if (!*psf_list) {
00392
if (type == IGMPV3_ALLOW_NEW_SOURCES ||
00393 type == IGMPV3_BLOCK_OLD_SOURCES)
00394
return skb;
00395
if (pmc->crcount || isquery) {
00396
00397
00398
00399
if (skb && AVAILABLE(skb) <
sizeof(
struct igmpv3_grec)+
00400 sizeof(__u32)) {
00401 igmpv3_sendpack(skb);
00402 skb = 0;
00403 }
00404 skb = add_grhead(skb, pmc, type, &pgr);
00405 }
00406
return skb;
00407 }
00408 pih = skb ? (
struct igmpv3_report *)skb->
h.igmph : 0;
00409
00410
00411
if (truncate) {
00412
if (pih && pih->ngrec &&
00413 AVAILABLE(skb) < grec_size(pmc, type, gdeleted, sdeleted)) {
00414
if (skb)
00415 igmpv3_sendpack(skb);
00416 skb = igmpv3_newpack(dev, dev->
mtu);
00417 }
00418 }
00419 first = 1;
00420 scount = 0;
00421 psf_prev = 0;
00422
for (psf=*psf_list; psf; psf=psf_next) {
00423 u32 *psrc;
00424
00425 psf_next = psf->sf_next;
00426
00427
if (!is_in(pmc, psf, type, gdeleted, sdeleted)) {
00428 psf_prev = psf;
00429
continue;
00430 }
00431
00432
00433
if (isquery)
00434 psf->sf_gsresp = 0;
00435
00436
if (AVAILABLE(skb) <
sizeof(u32) +
00437 first*
sizeof(
struct igmpv3_grec)) {
00438
if (truncate && !first)
00439
break;
00440
if (pgr)
00441 pgr->grec_nsrcs = htons(scount);
00442
if (skb)
00443 igmpv3_sendpack(skb);
00444 skb = igmpv3_newpack(dev, dev->
mtu);
00445 first = 1;
00446 scount = 0;
00447 }
00448
if (first) {
00449 skb = add_grhead(skb, pmc, type, &pgr);
00450 first = 0;
00451 }
00452 psrc = (u32 *)
skb_put(skb,
sizeof(u32));
00453 *psrc = psf->sf_inaddr;
00454 scount++;
00455
if ((type == IGMPV3_ALLOW_NEW_SOURCES ||
00456 type == IGMPV3_BLOCK_OLD_SOURCES) && psf->sf_crcount) {
00457 psf->sf_crcount--;
00458
if ((sdeleted || gdeleted) && psf->sf_crcount == 0) {
00459
if (psf_prev)
00460 psf_prev->sf_next = psf->sf_next;
00461
else
00462 *psf_list = psf->sf_next;
00463 kfree(psf);
00464
continue;
00465 }
00466 }
00467 psf_prev = psf;
00468 }
00469
if (pgr)
00470 pgr->grec_nsrcs = htons(scount);
00471
00472
if (isquery)
00473 pmc->gsquery = 0;
00474
return skb;
00475 }
00476
00477
static int igmpv3_send_report(
struct in_device *in_dev,
struct ip_mc_list *pmc)
00478 {
00479
struct sk_buff *skb = 0;
00480
int type;
00481
00482
if (!pmc) {
00483 read_lock(&in_dev->
lock);
00484
for (pmc=in_dev->
mc_list; pmc; pmc=pmc->next) {
00485
if (pmc->multiaddr == IGMP_ALL_HOSTS)
00486
continue;
00487 spin_lock_bh(&pmc->lock);
00488
if (pmc->sfcount[
MCAST_EXCLUDE])
00489 type = IGMPV3_MODE_IS_EXCLUDE;
00490
else
00491 type = IGMPV3_MODE_IS_INCLUDE;
00492 skb = add_grec(skb, pmc, type, 0, 0);
00493 spin_unlock_bh(&pmc->lock);
00494 }
00495 read_unlock(&in_dev->
lock);
00496 }
else {
00497 spin_lock_bh(&pmc->lock);
00498
if (pmc->sfcount[
MCAST_EXCLUDE])
00499 type = IGMPV3_MODE_IS_EXCLUDE;
00500
else
00501 type = IGMPV3_MODE_IS_INCLUDE;
00502 skb = add_grec(skb, pmc, type, 0, 0);
00503 spin_unlock_bh(&pmc->lock);
00504 }
00505
if (!skb)
00506
return 0;
00507
return igmpv3_sendpack(skb);
00508 }
00509
00510
00511
00512
00513
static void igmpv3_clear_zeros(
struct ip_sf_list **ppsf)
00514 {
00515
struct ip_sf_list *psf_prev, *psf_next, *psf;
00516
00517 psf_prev = 0;
00518
for (psf=*ppsf; psf; psf = psf_next) {
00519 psf_next = psf->sf_next;
00520
if (psf->sf_crcount == 0) {
00521
if (psf_prev)
00522 psf_prev->sf_next = psf->sf_next;
00523
else
00524 *ppsf = psf->sf_next;
00525 kfree(psf);
00526 }
else
00527 psf_prev = psf;
00528 }
00529 }
00530
00531
static void igmpv3_send_cr(
struct in_device *in_dev)
00532 {
00533
struct ip_mc_list *pmc, *pmc_prev, *pmc_next;
00534
struct sk_buff *skb = 0;
00535
int type, dtype;
00536
00537 read_lock(&in_dev->
lock);
00538 write_lock_bh(&in_dev->
mc_lock);
00539
00540
00541 pmc_prev = 0;
00542
for (pmc=in_dev->
mc_tomb; pmc; pmc=pmc_next) {
00543 pmc_next = pmc->next;
00544
if (pmc->sfmode ==
MCAST_INCLUDE) {
00545 type = IGMPV3_BLOCK_OLD_SOURCES;
00546 dtype = IGMPV3_BLOCK_OLD_SOURCES;
00547 skb = add_grec(skb, pmc, type, 1, 0);
00548 skb = add_grec(skb, pmc, dtype, 1, 1);
00549 }
00550
if (pmc->crcount) {
00551 pmc->crcount--;
00552
if (pmc->sfmode ==
MCAST_EXCLUDE) {
00553 type = IGMPV3_CHANGE_TO_INCLUDE;
00554 skb = add_grec(skb, pmc, type, 1, 0);
00555 }
00556
if (pmc->crcount == 0) {
00557 igmpv3_clear_zeros(&pmc->tomb);
00558 igmpv3_clear_zeros(&pmc->sources);
00559 }
00560 }
00561
if (pmc->crcount == 0 && !pmc->tomb && !pmc->sources) {
00562
if (pmc_prev)
00563 pmc_prev->next = pmc_next;
00564
else
00565 in_dev->
mc_tomb = pmc_next;
00566
in_dev_put(pmc->interface);
00567 kfree(pmc);
00568 }
else
00569 pmc_prev = pmc;
00570 }
00571 write_unlock_bh(&in_dev->
mc_lock);
00572
00573
00574
for (pmc=in_dev->
mc_list; pmc; pmc=pmc->next) {
00575 spin_lock_bh(&pmc->lock);
00576
if (pmc->sfcount[
MCAST_EXCLUDE]) {
00577 type = IGMPV3_BLOCK_OLD_SOURCES;
00578 dtype = IGMPV3_ALLOW_NEW_SOURCES;
00579 }
else {
00580 type = IGMPV3_ALLOW_NEW_SOURCES;
00581 dtype = IGMPV3_BLOCK_OLD_SOURCES;
00582 }
00583 skb = add_grec(skb, pmc, type, 0, 0);
00584 skb = add_grec(skb, pmc, dtype, 0, 1);
00585
00586
00587
if (pmc->crcount) {
00588 pmc->crcount--;
00589
if (pmc->sfmode ==
MCAST_EXCLUDE)
00590 type = IGMPV3_CHANGE_TO_EXCLUDE;
00591
else
00592 type = IGMPV3_CHANGE_TO_INCLUDE;
00593 skb = add_grec(skb, pmc, type, 0, 0);
00594 }
00595 spin_unlock_bh(&pmc->lock);
00596 }
00597 read_unlock(&in_dev->
lock);
00598
if (!skb)
00599
return;
00600 (
void) igmpv3_sendpack(skb);
00601 }
00602
00603
static int igmp_send_report(
struct in_device *in_dev,
struct ip_mc_list *pmc,
00604
int type)
00605 {
00606
struct sk_buff *skb;
00607
struct iphdr *iph;
00608
struct igmphdr *ih;
00609
struct rtable *rt;
00610
struct net_device *dev = in_dev->
dev;
00611 u32 group = pmc ? pmc->multiaddr : 0;
00612 u32 dst;
00613
00614
if (type == IGMPV3_HOST_MEMBERSHIP_REPORT)
00615
return igmpv3_send_report(in_dev, pmc);
00616
else if (type == IGMP_HOST_LEAVE_MESSAGE)
00617 dst = IGMP_ALL_ROUTER;
00618
else
00619 dst = group;
00620
00621
if (
ip_route_output(&rt, dst, 0, 0, dev->
ifindex))
00622
return -1;
00623
if (rt->rt_src == 0) {
00624
ip_rt_put(rt);
00625
return -1;
00626 }
00627
00628 skb=
alloc_skb(IGMP_SIZE+dev->
hard_header_len+15, GFP_ATOMIC);
00629
if (skb == NULL) {
00630
ip_rt_put(rt);
00631
return -1;
00632 }
00633
00634 skb->
dst = &rt->u.dst;
00635
00636
skb_reserve(skb, (dev->
hard_header_len+15)&~15);
00637
00638 skb->
nh.iph = iph = (
struct iphdr *)
skb_put(skb,
sizeof(
struct iphdr)+4);
00639
00640 iph->version = 4;
00641 iph->ihl = (
sizeof(
struct iphdr)+4)>>2;
00642 iph->tos = 0xc0;
00643 iph->frag_off = htons(IP_DF);
00644 iph->ttl = 1;
00645 iph->daddr = dst;
00646 iph->saddr = rt->rt_src;
00647 iph->protocol =
IPPROTO_IGMP;
00648 iph->tot_len = htons(IGMP_SIZE);
00649
ip_select_ident(iph, &rt->u.dst, NULL);
00650 ((u8*)&iph[1])[0] =
IPOPT_RA;
00651 ((u8*)&iph[1])[1] = 4;
00652 ((u8*)&iph[1])[2] = 0;
00653 ((u8*)&iph[1])[3] = 0;
00654
ip_send_check(iph);
00655
00656 ih = (
struct igmphdr *)
skb_put(skb,
sizeof(
struct igmphdr));
00657 ih->type=type;
00658 ih->code=0;
00659 ih->csum=0;
00660 ih->group=group;
00661 ih->csum=
ip_compute_csum((
void *)ih,
sizeof(
struct igmphdr));
00662
00663
return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
00664 output_maybe_reroute);
00665 }
00666
00667
static void igmp_gq_timer_expire(
unsigned long data)
00668 {
00669
struct in_device *in_dev = (
struct in_device *)data;
00670
00671 in_dev->
mr_gq_running = 0;
00672 igmpv3_send_report(in_dev, 0);
00673
__in_dev_put(in_dev);
00674 }
00675
00676
static void igmp_ifc_timer_expire(
unsigned long data)
00677 {
00678
struct in_device *in_dev = (
struct in_device *)data;
00679
00680 igmpv3_send_cr(in_dev);
00681
if (in_dev->
mr_ifc_count) {
00682 in_dev->
mr_ifc_count--;
00683 igmp_ifc_start_timer(in_dev, IGMP_Unsolicited_Report_Interval);
00684 }
00685
__in_dev_put(in_dev);
00686 }
00687
00688
static void igmp_ifc_event(
struct in_device *in_dev)
00689 {
00690
if (IGMP_V1_SEEN(in_dev) || IGMP_V2_SEEN(in_dev))
00691
return;
00692 in_dev->
mr_ifc_count = in_dev->
mr_qrv ? in_dev->
mr_qrv :
00693 IGMP_Unsolicited_Report_Count;
00694 igmp_ifc_start_timer(in_dev, 1);
00695 }
00696
00697
00698
static void igmp_timer_expire(
unsigned long data)
00699 {
00700
struct ip_mc_list *im=(
struct ip_mc_list *)data;
00701
struct in_device *in_dev = im->interface;
00702
00703 spin_lock(&im->lock);
00704 im->tm_running=0;
00705
00706
if (im->unsolicit_count) {
00707 im->unsolicit_count--;
00708 igmp_start_timer(im, IGMP_Unsolicited_Report_Interval);
00709 }
00710 im->reporter = 1;
00711 spin_unlock(&im->lock);
00712
00713
if (IGMP_V1_SEEN(in_dev))
00714 igmp_send_report(in_dev, im, IGMP_HOST_MEMBERSHIP_REPORT);
00715
else if (IGMP_V2_SEEN(in_dev))
00716 igmp_send_report(in_dev, im, IGMPV2_HOST_MEMBERSHIP_REPORT);
00717
else
00718 igmp_send_report(in_dev, im, IGMPV3_HOST_MEMBERSHIP_REPORT);
00719
00720
ip_ma_put(im);
00721 }
00722
00723
static void igmp_marksources(
struct ip_mc_list *pmc,
int nsrcs, __u32 *srcs)
00724 {
00725
struct ip_sf_list *psf;
00726
int i, scount;
00727
00728 scount = 0;
00729
for (psf=pmc->sources; psf; psf=psf->sf_next) {
00730
if (scount == nsrcs)
00731
break;
00732
for (i=0; i<nsrcs; i++)
00733
if (srcs[i] == psf->sf_inaddr) {
00734 psf->sf_gsresp = 1;
00735 scount++;
00736
break;
00737 }
00738 }
00739 }
00740
00741
static void igmp_heard_report(
struct in_device *in_dev, u32 group)
00742 {
00743
struct ip_mc_list *im;
00744
00745
00746
00747
if (group == IGMP_ALL_HOSTS)
00748
return;
00749
00750 read_lock(&in_dev->
lock);
00751
for (im=in_dev->
mc_list; im!=NULL; im=im->next) {
00752
if (im->multiaddr == group) {
00753 igmp_stop_timer(im);
00754
break;
00755 }
00756 }
00757 read_unlock(&in_dev->
lock);
00758 }
00759
00760
static void igmp_heard_query(
struct in_device *in_dev,
struct igmphdr *ih,
00761
int len)
00762 {
00763
struct igmpv3_query *ih3 = (
struct igmpv3_query *)ih;
00764
struct ip_mc_list *im;
00765 u32 group = ih->group;
00766
int max_delay;
00767
int mark = 0;
00768
00769
00770
if (len == 8) {
00771
if (ih->code == 0) {
00772
00773
00774 max_delay = IGMP_Query_Response_Interval;
00775 in_dev->
mr_v1_seen = jiffies +
00776 IGMP_V1_Router_Present_Timeout;
00777 group = 0;
00778 }
else {
00779
00780 max_delay = ih->code*(HZ/IGMP_TIMER_SCALE);
00781 in_dev->
mr_v2_seen = jiffies +
00782 IGMP_V2_Router_Present_Timeout;
00783 }
00784
00785 in_dev->
mr_ifc_count = 0;
00786
if (del_timer(&in_dev->
mr_ifc_timer))
00787
__in_dev_put(in_dev);
00788
00789 igmpv3_clear_delrec(in_dev);
00790 }
else if (len < 12) {
00791
return;
00792 }
else {
00793 max_delay = IGMPV3_MRC(ih3->code)*(HZ/IGMP_TIMER_SCALE);
00794
if (!max_delay)
00795 max_delay = 1;
00796 in_dev->
mr_maxdelay = max_delay;
00797
if (ih3->qrv)
00798 in_dev->
mr_qrv = ih3->qrv;
00799
if (!group) {
00800
if (ih3->nsrcs)
00801
return;
00802 igmp_gq_start_timer(in_dev);
00803
return;
00804 }
00805
00806 mark = ih3->nsrcs != 0;
00807 }
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819 read_lock(&in_dev->
lock);
00820
for (im=in_dev->
mc_list; im!=NULL; im=im->next) {
00821
if (group && group != im->multiaddr)
00822
continue;
00823
if (im->multiaddr == IGMP_ALL_HOSTS)
00824
continue;
00825 spin_lock_bh(&im->lock);
00826
if (im->tm_running)
00827 im->gsquery = im->gsquery && mark;
00828
else
00829 im->gsquery = mark;
00830
if (im->gsquery)
00831 igmp_marksources(im, ntohs(ih3->nsrcs), ih3->srcs);
00832 spin_unlock_bh(&im->lock);
00833 igmp_mod_timer(im, max_delay);
00834 }
00835 read_unlock(&in_dev->
lock);
00836 }
00837
00838
int igmp_rcv(
struct sk_buff *skb)
00839 {
00840
00841
struct igmphdr *ih = skb->
h.igmph;
00842
struct in_device *in_dev =
in_dev_get(skb->
dev);
00843
int len = skb->
len;
00844
00845
if (in_dev==NULL) {
00846
kfree_skb(skb);
00847
return 0;
00848 }
00849
00850
if (
skb_is_nonlinear(skb)) {
00851
if (
skb_linearize(skb, GFP_ATOMIC) != 0) {
00852
kfree_skb(skb);
00853
return -ENOMEM;
00854 }
00855 ih = skb->
h.igmph;
00856 }
00857
00858
if (len <
sizeof(
struct igmphdr) || ip_compute_csum((void *)ih, len)) {
00859
in_dev_put(in_dev);
00860
kfree_skb(skb);
00861
return 0;
00862 }
00863
00864
switch (ih->type) {
00865
case IGMP_HOST_MEMBERSHIP_QUERY:
00866 igmp_heard_query(in_dev, ih, len);
00867
break;
00868
case IGMP_HOST_MEMBERSHIP_REPORT:
00869
case IGMPV2_HOST_MEMBERSHIP_REPORT:
00870
case IGMPV3_HOST_MEMBERSHIP_REPORT:
00871
00872
if (((
struct rtable*)skb->
dst)->key.iif == 0)
00873
break;
00874 igmp_heard_report(in_dev, ih->group);
00875
break;
00876
case IGMP_PIM:
00877
#ifdef CONFIG_IP_PIMSM_V1
00878
in_dev_put(in_dev);
00879
return pim_rcv_v1(skb);
00880
#endif
00881
case IGMP_DVMRP:
00882
case IGMP_TRACE:
00883
case IGMP_HOST_LEAVE_MESSAGE:
00884
case IGMP_MTRACE:
00885
case IGMP_MTRACE_RESP:
00886
break;
00887
default:
00888
NETDEBUG(printk(KERN_DEBUG
"New IGMP type=%d, why we do not know about it?\n", ih->type));
00889 }
00890
in_dev_put(in_dev);
00891
kfree_skb(skb);
00892
return 0;
00893 }
00894
00895
#endif
00896
00897
00898
00899
00900
00901
00902 static void ip_mc_filter_add(
struct in_device *in_dev, u32 addr)
00903 {
00904
char buf[
MAX_ADDR_LEN];
00905
struct net_device *dev = in_dev->
dev;
00906
00907
00908
00909
00910
00911
00912
00913
00914
if (
arp_mc_map(addr, buf, dev, 0) == 0)
00915
dev_mc_add(dev,buf,dev->
addr_len,0);
00916 }
00917
00918
00919
00920
00921
00922 static void ip_mc_filter_del(
struct in_device *in_dev, u32 addr)
00923 {
00924
char buf[
MAX_ADDR_LEN];
00925
struct net_device *dev = in_dev->
dev;
00926
00927
if (
arp_mc_map(addr, buf, dev, 0) == 0)
00928
dev_mc_delete(dev,buf,dev->
addr_len,0);
00929 }
00930
00931
#ifdef CONFIG_IP_MULTICAST
00932
00933
00934
00935
static void igmpv3_add_delrec(
struct in_device *in_dev,
struct ip_mc_list *im)
00936 {
00937
struct ip_mc_list *pmc;
00938
00939
00940
00941
00942
00943
00944
00945 pmc = (
struct ip_mc_list *)kmalloc(
sizeof(*pmc), GFP_KERNEL);
00946
if (!pmc)
00947
return;
00948 memset(pmc, 0,
sizeof(*pmc));
00949 spin_lock_bh(&im->lock);
00950 pmc->interface = im->interface;
00951
in_dev_hold(in_dev);
00952 pmc->multiaddr = im->multiaddr;
00953 pmc->crcount = in_dev->
mr_qrv ? in_dev->
mr_qrv :
00954 IGMP_Unsolicited_Report_Count;
00955 pmc->sfmode = im->sfmode;
00956
if (pmc->sfmode ==
MCAST_INCLUDE) {
00957
struct ip_sf_list *psf;
00958
00959 pmc->tomb = im->tomb;
00960 pmc->sources = im->sources;
00961 im->tomb = im->sources = 0;
00962
for (psf=pmc->sources; psf; psf=psf->sf_next)
00963 psf->sf_crcount = pmc->crcount;
00964 }
00965 spin_unlock_bh(&im->lock);
00966
00967 write_lock_bh(&in_dev->
mc_lock);
00968 pmc->next = in_dev->
mc_tomb;
00969 in_dev->
mc_tomb = pmc;
00970 write_unlock_bh(&in_dev->
mc_lock);
00971 }
00972
00973
static void igmpv3_del_delrec(
struct in_device *in_dev, __u32 multiaddr)
00974 {
00975
struct ip_mc_list *pmc, *pmc_prev;
00976
struct ip_sf_list *psf, *psf_next;
00977
00978 write_lock_bh(&in_dev->
mc_lock);
00979 pmc_prev = 0;
00980
for (pmc=in_dev->
mc_tomb; pmc; pmc=pmc->next) {
00981
if (pmc->multiaddr == multiaddr)
00982
break;
00983 pmc_prev = pmc;
00984 }
00985
if (pmc) {
00986
if (pmc_prev)
00987 pmc_prev->next = pmc->next;
00988
else
00989 in_dev->
mc_tomb = pmc->next;
00990 }
00991 write_unlock_bh(&in_dev->
mc_lock);
00992
if (pmc) {
00993
for (psf=pmc->tomb; psf; psf=psf_next) {
00994 psf_next = psf->sf_next;
00995 kfree(psf);
00996 }
00997
in_dev_put(pmc->interface);
00998 kfree(pmc);
00999 }
01000 }
01001
01002
static void igmpv3_clear_delrec(
struct in_device *in_dev)
01003 {
01004
struct ip_mc_list *pmc, *nextpmc;
01005
01006 write_lock_bh(&in_dev->
mc_lock);
01007 pmc = in_dev->
mc_tomb;
01008 in_dev->
mc_tomb = 0;
01009 write_unlock_bh(&in_dev->
mc_lock);
01010
01011
for (; pmc; pmc = nextpmc) {
01012 nextpmc = pmc->next;
01013
ip_mc_clear_src(pmc);
01014
in_dev_put(pmc->interface);
01015 kfree(pmc);
01016 }
01017
01018 read_lock(&in_dev->
lock);
01019
for (pmc=in_dev->
mc_list; pmc; pmc=pmc->next) {
01020
struct ip_sf_list *psf, *psf_next;
01021
01022 spin_lock_bh(&pmc->lock);
01023 psf = pmc->tomb;
01024 pmc->tomb = 0;
01025 spin_unlock_bh(&pmc->lock);
01026
for (; psf; psf=psf_next) {
01027 psf_next = psf->sf_next;
01028 kfree(psf);
01029 }
01030 }
01031 read_unlock(&in_dev->
lock);
01032 }
01033
#endif
01034
01035 static void igmp_group_dropped(
struct ip_mc_list *im)
01036 {
01037
struct in_device *in_dev = im->interface;
01038
#ifdef CONFIG_IP_MULTICAST
01039
int reporter;
01040
#endif
01041
01042
if (im->loaded) {
01043 im->loaded = 0;
01044
ip_mc_filter_del(in_dev, im->multiaddr);
01045 }
01046
01047
#ifdef CONFIG_IP_MULTICAST
01048
if (im->multiaddr == IGMP_ALL_HOSTS)
01049
return;
01050
01051 reporter = im->reporter;
01052 igmp_stop_timer(im);
01053
01054
if (in_dev->
dev->
flags & IFF_UP) {
01055
if (IGMP_V1_SEEN(in_dev))
01056
goto done;
01057
if (IGMP_V2_SEEN(in_dev)) {
01058
if (reporter)
01059 igmp_send_report(in_dev, im, IGMP_HOST_LEAVE_MESSAGE);
01060
goto done;
01061 }
01062
01063 igmpv3_add_delrec(in_dev, im);
01064
01065 igmp_ifc_event(in_dev);
01066 }
01067 done:
01068
#endif
01069
ip_mc_clear_src(im);
01070 }
01071
01072 static void igmp_group_added(
struct ip_mc_list *im)
01073 {
01074
struct in_device *in_dev = im->interface;
01075
01076
if (im->loaded == 0) {
01077 im->loaded = 1;
01078
ip_mc_filter_add(in_dev, im->multiaddr);
01079 }
01080
01081
#ifdef CONFIG_IP_MULTICAST
01082
if (im->multiaddr == IGMP_ALL_HOSTS)
01083
return;
01084
01085
if (IGMP_V1_SEEN(in_dev) || IGMP_V2_SEEN(in_dev)) {
01086 spin_lock_bh(&im->lock);
01087 igmp_start_timer(im, IGMP_Initial_Report_Delay);
01088 spin_unlock_bh(&im->lock);
01089
return;
01090 }
01091
01092
01093 im->crcount = in_dev->
mr_qrv ? in_dev->
mr_qrv :
01094 IGMP_Unsolicited_Report_Count;
01095 igmp_ifc_event(in_dev);
01096
#endif
01097
}
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109 void ip_mc_inc_group(
struct in_device *in_dev, u32 addr)
01110 {
01111
struct ip_mc_list *im;
01112
01113 ASSERT_RTNL();
01114
01115
for (im=in_dev->
mc_list; im; im=im->next) {
01116
if (im->multiaddr == addr) {
01117 im->users++;
01118
ip_mc_add_src(in_dev, &addr,
MCAST_EXCLUDE, 0, 0, 0);
01119
goto out;
01120 }
01121 }
01122
01123 im = (
struct ip_mc_list *)kmalloc(
sizeof(*im), GFP_KERNEL);
01124
if (!im)
01125
goto out;
01126
01127 im->users=1;
01128 im->interface=in_dev;
01129
in_dev_hold(in_dev);
01130 im->multiaddr=addr;
01131
01132 im->sfmode =
MCAST_EXCLUDE;
01133 im->sfcount[
MCAST_INCLUDE] = 0;
01134 im->sfcount[
MCAST_EXCLUDE] = 1;
01135 im->sources = 0;
01136 im->tomb = 0;
01137 im->crcount = 0;
01138 atomic_set(&im->refcnt, 1);
01139 spin_lock_init(&im->lock);
01140
#ifdef CONFIG_IP_MULTICAST
01141
im->tm_running=0;
01142 init_timer(&im->timer);
01143 im->timer.data=(
unsigned long)im;
01144 im->timer.function=&igmp_timer_expire;
01145 im->unsolicit_count = IGMP_Unsolicited_Report_Count;
01146 im->reporter = 0;
01147 im->gsquery = 0;
01148
#endif
01149
im->loaded = 0;
01150 write_lock_bh(&in_dev->
lock);
01151 im->next=in_dev->
mc_list;
01152 in_dev->
mc_list=im;
01153 write_unlock_bh(&in_dev->
lock);
01154
#ifdef CONFIG_IP_MULTICAST
01155
igmpv3_del_delrec(in_dev, im->multiaddr);
01156
#endif
01157
igmp_group_added(im);
01158
if (in_dev->
dev->
flags & IFF_UP)
01159
ip_rt_multicast_event(in_dev);
01160 out:
01161
return;
01162 }
01163
01164
01165
01166
01167
01168 void ip_mc_dec_group(
struct in_device *in_dev, u32 addr)
01169 {
01170
struct ip_mc_list *i, **ip;
01171
01172 ASSERT_RTNL();
01173
01174
for (ip=&in_dev->
mc_list; (i=*ip)!=NULL; ip=&i->next) {
01175
if (i->multiaddr==addr) {
01176
if (--i->users == 0) {
01177 write_lock_bh(&in_dev->
lock);
01178 *ip = i->next;
01179 write_unlock_bh(&in_dev->
lock);
01180
igmp_group_dropped(i);
01181
01182
if (in_dev->
dev->
flags & IFF_UP)
01183
ip_rt_multicast_event(in_dev);
01184
01185
ip_ma_put(i);
01186
return;
01187 }
01188
break;
01189 }
01190 }
01191 }
01192
01193
01194
01195 void ip_mc_down(
struct in_device *in_dev)
01196 {
01197
struct ip_mc_list *i;
01198
01199 ASSERT_RTNL();
01200
01201
#ifdef CONFIG_IP_MULTICAST
01202
in_dev->
mr_ifc_count = 0;
01203
if (del_timer(&in_dev->
mr_ifc_timer))
01204
__in_dev_put(in_dev);
01205 in_dev->
mr_gq_running = 0;
01206
if (del_timer(&in_dev->
mr_gq_timer))
01207
__in_dev_put(in_dev);
01208
#endif
01209
01210
for (i=in_dev->
mc_list; i; i=i->next)
01211
igmp_group_dropped(i);
01212
01213
#ifdef CONFIG_IP_MULTICAST
01214
igmpv3_clear_delrec(in_dev);
01215
#endif
01216
01217
ip_mc_dec_group(in_dev, IGMP_ALL_HOSTS);
01218 }
01219
01220
01221
01222 void ip_mc_up(
struct in_device *in_dev)
01223 {
01224
struct ip_mc_list *i;
01225
01226 ASSERT_RTNL();
01227
01228 in_dev->
mc_tomb = 0;
01229
#ifdef CONFIG_IP_MULTICAST
01230
in_dev->
mr_gq_running = 0;
01231 init_timer(&in_dev->
mr_gq_timer);
01232 in_dev->
mr_gq_timer.data=(
unsigned long) in_dev;
01233 in_dev->
mr_gq_timer.function=&igmp_gq_timer_expire;
01234 in_dev->
mr_ifc_count = 0;
01235 init_timer(&in_dev->
mr_ifc_timer);
01236 in_dev->
mr_ifc_timer.data=(
unsigned long) in_dev;
01237 in_dev->
mr_ifc_timer.function=&igmp_ifc_timer_expire;
01238 in_dev->
mr_qrv = IGMP_Unsolicited_Report_Count;
01239
#endif
01240
01241 in_dev->
mc_lock = RW_LOCK_UNLOCKED;
01242
ip_mc_inc_group(in_dev, IGMP_ALL_HOSTS);
01243
01244
for (i=in_dev->
mc_list; i; i=i->next)
01245
igmp_group_added(i);
01246 }
01247
01248
01249
01250
01251
01252 void ip_mc_destroy_dev(
struct in_device *in_dev)
01253 {
01254
struct ip_mc_list *i;
01255
01256 ASSERT_RTNL();
01257
01258 write_lock_bh(&in_dev->
lock);
01259
while ((i = in_dev->
mc_list) != NULL) {
01260 in_dev->
mc_list = i->next;
01261 write_unlock_bh(&in_dev->
lock);
01262
01263
igmp_group_dropped(i);
01264
ip_ma_put(i);
01265
01266 write_lock_bh(&in_dev->
lock);
01267 }
01268 write_unlock_bh(&in_dev->
lock);
01269 }
01270
01271 static struct in_device *
ip_mc_find_dev(
struct ip_mreqn *imr)
01272 {
01273
struct rtable *rt;
01274
struct net_device *dev = NULL;
01275
struct in_device *idev = NULL;
01276
01277
if (imr->
imr_ifindex) {
01278 idev =
inetdev_by_index(imr->
imr_ifindex);
01279
if (idev)
01280
__in_dev_put(idev);
01281
return idev;
01282 }
01283
if (imr->
imr_address.
s_addr) {
01284 dev =
ip_dev_find(imr->
imr_address.
s_addr);
01285
if (!dev)
01286
return NULL;
01287
__dev_put(dev);
01288 }
01289
01290
if (!dev && !
ip_route_output(&rt, imr->
imr_multiaddr.
s_addr, 0, 0, 0)) {
01291 dev = rt->u.dst.dev;
01292
ip_rt_put(rt);
01293 }
01294
if (dev) {
01295 imr->
imr_ifindex = dev->
ifindex;
01296 idev =
__in_dev_get(dev);
01297 }
01298
return idev;
01299 }
01300
01301
01302
01303
01304 int sysctl_igmp_max_memberships =
IP_MAX_MEMBERSHIPS;
01305
01306
01307 static int ip_mc_del1_src(
struct ip_mc_list *pmc,
int sfmode,
01308 __u32 *psfsrc)
01309 {
01310
struct ip_sf_list *psf, *psf_prev;
01311
int rv = 0;
01312
01313 psf_prev = 0;
01314
for (psf=pmc->sources; psf; psf=psf->sf_next) {
01315
if (psf->sf_inaddr == *psfsrc)
01316
break;
01317 psf_prev = psf;
01318 }
01319
if (!psf || psf->sf_count[sfmode] == 0) {
01320
01321
return -ESRCH;
01322 }
01323 psf->sf_count[sfmode]--;
01324
if (psf->sf_count[sfmode] == 0) {
01325
ip_rt_multicast_event(pmc->interface);
01326 }
01327
if (!psf->sf_count[
MCAST_INCLUDE] && !psf->sf_count[
MCAST_EXCLUDE]) {
01328
#ifdef CONFIG_IP_MULTICAST
01329
struct in_device *in_dev = pmc->interface;
01330
#endif
01331
01332
01333
if (psf_prev)
01334 psf_prev->sf_next = psf->sf_next;
01335
else
01336 pmc->sources = psf->sf_next;
01337
#ifdef CONFIG_IP_MULTICAST
01338
if (psf->sf_oldin &&
01339 !IGMP_V1_SEEN(in_dev) && !IGMP_V2_SEEN(in_dev)) {
01340 psf->sf_crcount = in_dev->
mr_qrv ? in_dev->
mr_qrv :
01341 IGMP_Unsolicited_Report_Count;
01342 psf->sf_next = pmc->tomb;
01343 pmc->tomb = psf;
01344 rv = 1;
01345 }
else
01346
#endif
01347
kfree(psf);
01348 }
01349
return rv;
01350 }
01351
01352 int ip_mc_del_src(
struct in_device *in_dev, __u32 *pmca,
int sfmode,
01353
int sfcount, __u32 *psfsrc,
int delta)
01354 {
01355
struct ip_mc_list *pmc;
01356
int changerec = 0;
01357
int i, err;
01358
01359
if (!in_dev)
01360
return -ENODEV;
01361 read_lock(&in_dev->
lock);
01362
for (pmc=in_dev->
mc_list; pmc; pmc=pmc->next) {
01363
if (*pmca == pmc->multiaddr)
01364
break;
01365 }
01366
if (!pmc) {
01367
01368 read_unlock(&in_dev->
lock);
01369
return -ESRCH;
01370 }
01371 spin_lock_bh(&pmc->lock);
01372 read_unlock(&in_dev->
lock);
01373
#ifdef CONFIG_IP_MULTICAST
01374
sf_markstate(pmc);
01375
#endif
01376
if (!delta) {
01377 err = -EINVAL;
01378
if (!pmc->sfcount[sfmode])
01379
goto out_unlock;
01380 pmc->sfcount[sfmode]--;
01381 }
01382 err = 0;
01383
for (i=0; i<sfcount; i++) {
01384
int rv =
ip_mc_del1_src(pmc, sfmode, &psfsrc[i]);
01385
01386 changerec |= rv > 0;
01387
if (!err && rv < 0)
01388 err = rv;
01389 }
01390
if (pmc->sfmode ==
MCAST_EXCLUDE &&
01391 pmc->sfcount[
MCAST_EXCLUDE] == 0 &&
01392 pmc->sfcount[
MCAST_INCLUDE]) {
01393
#ifdef CONFIG_IP_MULTICAST
01394
struct ip_sf_list *psf;
01395
#endif
01396
01397
01398 pmc->sfmode =
MCAST_INCLUDE;
01399
#ifdef CONFIG_IP_MULTICAST
01400
pmc->crcount = in_dev->
mr_qrv ? in_dev->
mr_qrv :
01401 IGMP_Unsolicited_Report_Count;
01402 in_dev->
mr_ifc_count = pmc->crcount;
01403
for (psf=pmc->sources; psf; psf = psf->sf_next)
01404 psf->sf_crcount = 0;
01405 igmp_ifc_event(pmc->interface);
01406 }
else if (sf_setstate(pmc) || changerec) {
01407 igmp_ifc_event(pmc->interface);
01408
#endif
01409
}
01410 out_unlock:
01411 spin_unlock_bh(&pmc->lock);
01412
return err;
01413 }
01414
01415
01416
01417
01418 static int ip_mc_add1_src(
struct ip_mc_list *pmc,
int sfmode,
01419 __u32 *psfsrc,
int delta)
01420 {
01421
struct ip_sf_list *psf, *psf_prev;
01422
01423 psf_prev = 0;
01424
for (psf=pmc->sources; psf; psf=psf->sf_next) {
01425
if (psf->sf_inaddr == *psfsrc)
01426
break;
01427 psf_prev = psf;
01428 }
01429
if (!psf) {
01430 psf = (
struct ip_sf_list *)kmalloc(
sizeof(*psf), GFP_ATOMIC);
01431
if (!psf)
01432
return -ENOBUFS;
01433 memset(psf, 0,
sizeof(*psf));
01434 psf->sf_inaddr = *psfsrc;
01435
if (psf_prev) {
01436 psf_prev->sf_next = psf;
01437 }
else
01438 pmc->sources = psf;
01439 }
01440 psf->sf_count[sfmode]++;
01441
if (psf->sf_count[sfmode] == 1) {
01442
ip_rt_multicast_event(pmc->interface);
01443 }
01444
return 0;
01445 }
01446
01447
#ifdef CONFIG_IP_MULTICAST
01448
static void sf_markstate(
struct ip_mc_list *pmc)
01449 {
01450
struct ip_sf_list *psf;
01451
int mca_xcount = pmc->sfcount[
MCAST_EXCLUDE];
01452
01453
for (psf=pmc->sources; psf; psf=psf->sf_next)
01454
if (pmc->sfcount[
MCAST_EXCLUDE]) {
01455 psf->sf_oldin = mca_xcount ==
01456 psf->sf_count[
MCAST_EXCLUDE] &&
01457 !psf->sf_count[
MCAST_INCLUDE];
01458 }
else
01459 psf->sf_oldin = psf->sf_count[
MCAST_INCLUDE] != 0;
01460 }
01461
01462
static int sf_setstate(
struct ip_mc_list *pmc)
01463 {
01464
struct ip_sf_list *psf;
01465
int mca_xcount = pmc->sfcount[
MCAST_EXCLUDE];
01466
int qrv = pmc->interface->mr_qrv;
01467
int new_in, rv;
01468
01469 rv = 0;
01470
for (psf=pmc->sources; psf; psf=psf->sf_next) {
01471
if (pmc->sfcount[
MCAST_EXCLUDE]) {
01472 new_in = mca_xcount == psf->sf_count[
MCAST_EXCLUDE] &&
01473 !psf->sf_count[
MCAST_INCLUDE];
01474 }
else
01475 new_in = psf->sf_count[
MCAST_INCLUDE] != 0;
01476
if (new_in != psf->sf_oldin) {
01477 psf->sf_crcount = qrv;
01478 rv++;
01479 }
01480 }
01481
return rv;
01482 }
01483
#endif
01484
01485
01486
01487
01488 int ip_mc_add_src(
struct in_device *in_dev, __u32 *pmca,
int sfmode,
01489
int sfcount, __u32 *psfsrc,
int delta)
01490 {
01491
struct ip_mc_list *pmc;
01492
int isexclude;
01493
int i, err;
01494
01495
if (!in_dev)
01496
return -ENODEV;
01497 read_lock(&in_dev->
lock);
01498
for (pmc=in_dev->
mc_list; pmc; pmc=pmc->next) {
01499
if (*pmca == pmc->multiaddr)
01500
break;
01501 }
01502
if (!pmc) {
01503
01504 read_unlock(&in_dev->
lock);
01505
return -ESRCH;
01506 }
01507 spin_lock_bh(&pmc->lock);
01508 read_unlock(&in_dev->
lock);
01509
01510
#ifdef CONFIG_IP_MULTICAST
01511
sf_markstate(pmc);
01512
#endif
01513
isexclude = pmc->sfmode ==
MCAST_EXCLUDE;
01514
if (!delta)
01515 pmc->sfcount[sfmode]++;
01516 err = 0;
01517
for (i=0; i<sfcount; i++) {
01518 err =
ip_mc_add1_src(pmc, sfmode, &psfsrc[i], delta);
01519
if (err)
01520
break;
01521 }
01522
if (err) {
01523
int j;
01524
01525 pmc->sfcount[sfmode]--;
01526
for (j=0; j<i; j++)
01527 (
void)
ip_mc_del1_src(pmc, sfmode, &psfsrc[i]);
01528 }
else if (isexclude != (pmc->sfcount[
MCAST_EXCLUDE] != 0)) {
01529
#ifdef CONFIG_IP_MULTICAST
01530
struct in_device *in_dev = pmc->interface;
01531
struct ip_sf_list *psf;
01532
#endif
01533
01534
01535
if (pmc->sfcount[
MCAST_EXCLUDE])
01536 pmc->sfmode =
MCAST_EXCLUDE;
01537
else if (pmc->sfcount[
MCAST_INCLUDE])
01538 pmc->sfmode =
MCAST_INCLUDE;
01539
#ifdef CONFIG_IP_MULTICAST
01540
01541
01542 pmc->crcount = in_dev->
mr_qrv ? in_dev->
mr_qrv :
01543 IGMP_Unsolicited_Report_Count;
01544 in_dev->
mr_ifc_count = pmc->crcount;
01545
for (psf=pmc->sources; psf; psf = psf->sf_next)
01546 psf->sf_crcount = 0;
01547 igmp_ifc_event(in_dev);
01548 }
else if (sf_setstate(pmc)) {
01549 igmp_ifc_event(in_dev);
01550
#endif
01551
}
01552 spin_unlock_bh(&pmc->lock);
01553
return err;
01554 }
01555
01556 static void ip_mc_clear_src(
struct ip_mc_list *pmc)
01557 {
01558
struct ip_sf_list *psf, *nextpsf;
01559
01560
for (psf=pmc->tomb; psf; psf=nextpsf) {
01561 nextpsf = psf->sf_next;
01562 kfree(psf);
01563 }
01564 pmc->tomb = 0;
01565
for (psf=pmc->sources; psf; psf=nextpsf) {
01566 nextpsf = psf->sf_next;
01567 kfree(psf);
01568 }
01569 pmc->sources = 0;
01570 pmc->sfmode =
MCAST_EXCLUDE;
01571 pmc->sfcount[
MCAST_EXCLUDE] = 0;
01572 pmc->sfcount[
MCAST_EXCLUDE] = 1;
01573 }
01574
01575
01576
01577
01578
01579 int ip_mc_join_group(
struct sock *sk ,
struct ip_mreqn *imr)
01580 {
01581
int err;
01582 u32 addr = imr->
imr_multiaddr.
s_addr;
01583
struct ip_mc_socklist *iml, *i;
01584
struct in_device *in_dev;
01585
struct inet_opt *inet = &sk->
protinfo.af_inet;
01586
int count = 0;
01587
01588
if (!
MULTICAST(addr))
01589
return -EINVAL;
01590
01591 rtnl_shlock();
01592
01593 in_dev =
ip_mc_find_dev(imr);
01594
01595
if (!in_dev) {
01596 iml = NULL;
01597 err = -ENODEV;
01598
goto done;
01599 }
01600
01601 iml = (
struct ip_mc_socklist *)
sock_kmalloc(sk,
sizeof(*iml), GFP_KERNEL);
01602
01603 err = -EADDRINUSE;
01604
for (i = inet->mc_list; i; i = i->next) {
01605
if (memcmp(&i->multi, imr,
sizeof(*imr)) == 0) {
01606
01607
if (imr->imr_address.s_addr == 0) {
01608 i->count++;
01609 err = 0;
01610 }
01611
goto done;
01612 }
01613 count++;
01614 }
01615 err = -ENOBUFS;
01616
if (iml == NULL || count >=
sysctl_igmp_max_memberships)
01617
goto done;
01618 memcpy(&iml->multi, imr,
sizeof(*imr));
01619 iml->next = sk->
protinfo.af_inet.mc_list;
01620 iml->count = 1;
01621 iml->sflist = NULL;
01622 iml->sfmode =
MCAST_EXCLUDE;
01623 inet->mc_list = iml;
01624
ip_mc_inc_group(in_dev, addr);
01625 iml = NULL;
01626 err = 0;
01627
01628 done:
01629 rtnl_shunlock();
01630
if (iml)
01631
sock_kfree_s(sk, iml,
sizeof(*iml));
01632
return err;
01633 }
01634
01635 int ip_mc_leave_src(
struct sock *sk,
struct ip_mc_socklist *iml,
01636
struct in_device *in_dev)
01637 {
01638
int err;
01639
01640
if (iml->sflist == 0) {
01641
01642
return ip_mc_del_src(in_dev, &iml->multi.imr_multiaddr.s_addr,
01643 iml->sfmode, 0, 0, 0);
01644 }
01645 err =
ip_mc_del_src(in_dev, &iml->multi.imr_multiaddr.s_addr,
01646 iml->sfmode, iml->sflist->sl_count,
01647 iml->sflist->sl_addr, 0);
01648
sock_kfree_s(sk, iml->sflist, IP_SFLSIZE(iml->sflist->sl_max));
01649 iml->sflist = 0;
01650
return err;
01651 }
01652
01653
01654
01655
01656
01657 int ip_mc_leave_group(
struct sock *sk,
struct ip_mreqn *imr)
01658 {
01659
struct inet_opt *inet = &sk->
protinfo.af_inet;
01660
struct ip_mc_socklist *iml, **imlp;
01661
01662
rtnl_lock();
01663
for (imlp = &inet->mc_list; (iml = *imlp) != NULL; imlp = &iml->next) {
01664
if (iml->multi.imr_multiaddr.s_addr==imr->
imr_multiaddr.
s_addr &&
01665 iml->multi.imr_address.s_addr==imr->
imr_address.
s_addr &&
01666 (!imr->
imr_ifindex || iml->multi.imr_ifindex==imr->
imr_ifindex)) {
01667
struct in_device *in_dev;
01668
01669 in_dev =
inetdev_by_index(iml->multi.imr_ifindex);
01670
if (in_dev)
01671 (
void)
ip_mc_leave_src(sk, iml, in_dev);
01672
if (--iml->count) {
01673
rtnl_unlock();
01674
if (in_dev)
01675
in_dev_put(in_dev);
01676
return 0;
01677 }
01678
01679 *imlp = iml->next;
01680
01681
if (in_dev) {
01682
ip_mc_dec_group(in_dev, imr->
imr_multiaddr.
s_addr);
01683
in_dev_put(in_dev);
01684 }
01685
rtnl_unlock();
01686
sock_kfree_s(sk, iml,
sizeof(*iml));
01687
return 0;
01688 }
01689 }
01690
rtnl_unlock();
01691
return -EADDRNOTAVAIL;
01692 }
01693
01694 int ip_mc_source(
int add,
int omode,
struct sock *sk,
struct
01695
ip_mreq_source *mreqs,
int ifindex)
01696 {
01697
int err;
01698
struct ip_mreqn imr;
01699 u32 addr = mreqs->
imr_multiaddr;
01700
struct ip_mc_socklist *pmc;
01701
struct in_device *in_dev = 0;
01702
struct inet_opt *inet = &sk->
protinfo.af_inet;
01703
struct ip_sf_socklist *psl;
01704
int i, j, rv;
01705
01706
if (!
MULTICAST(addr))
01707
return -EINVAL;
01708
01709 rtnl_shlock();
01710
01711 imr.
imr_multiaddr.
s_addr = mreqs->
imr_multiaddr;
01712 imr.
imr_address.
s_addr = mreqs->
imr_interface;
01713 imr.
imr_ifindex = ifindex;
01714 in_dev =
ip_mc_find_dev(&imr);
01715
01716
if (!in_dev) {
01717 err = -ENODEV;
01718
goto done;
01719 }
01720 err = -EADDRNOTAVAIL;
01721
01722
for (pmc=inet->mc_list; pmc; pmc=pmc->next) {
01723
if (memcmp(&pmc->multi, mreqs, 2*
sizeof(__u32)) == 0)
01724
break;
01725 }
01726
if (!pmc)
01727
goto done;
01728
01729
if (pmc->sflist) {
01730
if (pmc->sfmode != omode)
01731
goto done;
01732 }
else if (pmc->sfmode != omode) {
01733
01734
ip_mc_del_src(in_dev, &mreqs->
imr_multiaddr, pmc->sfmode, 0,
01735 0, 0);
01736 pmc->sfmode = omode;
01737
ip_mc_add_src(in_dev, &mreqs->
imr_multiaddr, pmc->sfmode, 0,
01738 0, 0);
01739 }
01740
01741 psl = pmc->sflist;
01742
if (!add) {
01743
if (!psl)
01744
goto done;
01745 rv = !0;
01746
for (i=0; i<psl->sl_count; i++) {
01747 rv = memcmp(&psl->sl_addr, &mreqs->
imr_multiaddr,
01748
sizeof(__u32));
01749
if (rv >= 0)
01750
break;
01751 }
01752
if (!rv)
01753
goto done;
01754
01755
01756
ip_mc_del_src(in_dev, &mreqs->
imr_multiaddr, omode, 1,
01757 &mreqs->
imr_sourceaddr, 1);
01758
01759
for (j=i+1; j<psl->sl_count; j++)
01760 psl->sl_addr[j-1] = psl->sl_addr[j];
01761 psl->sl_count--;
01762 err = 0;
01763
goto done;
01764 }
01765
01766
01767
if (!psl || psl->sl_count == psl->sl_max) {
01768
struct ip_sf_socklist *newpsl;
01769
int count = IP_SFBLOCK;
01770
01771
if (psl)
01772 count += psl->sl_max;
01773 newpsl = (
struct ip_sf_socklist *)
sock_kmalloc(sk,
01774 IP_SFLSIZE(count), GFP_KERNEL);
01775
if (!newpsl) {
01776 err = -ENOBUFS;
01777
goto done;
01778 }
01779 newpsl->sl_max = count;
01780 newpsl->sl_count = count - IP_SFBLOCK;
01781
if (psl) {
01782
for (i=0; i<psl->sl_count; i++)
01783 newpsl->sl_addr[i] = psl->sl_addr[i];
01784
sock_kfree_s(sk, psl, IP_SFLSIZE(psl->sl_max));
01785 }
01786 pmc->sflist = psl = newpsl;
01787 }
01788 rv = 1;
01789
for (i=0; i<psl->sl_count; i++) {
01790 rv = memcmp(&psl->sl_addr, &mreqs->
imr_multiaddr,
01791
sizeof(__u32));
01792
if (rv >= 0)
01793
break;
01794 }
01795
if (rv == 0)
01796
goto done;
01797
for (j=psl->sl_count-1; j>=i; j--)
01798 psl->sl_addr[j+1] = psl->sl_addr[j];
01799 psl->sl_addr[i] = mreqs->
imr_sourceaddr;
01800 psl->sl_count++;
01801 err = 0;
01802
01803
ip_mc_add_src(in_dev, &mreqs->
imr_multiaddr, omode, 1,
01804 &mreqs->
imr_sourceaddr, 1);
01805 done:
01806 rtnl_shunlock();
01807
return err;
01808 }
01809
01810 int ip_mc_msfilter(
struct sock *sk,
struct ip_msfilter *msf,
int ifindex)
01811 {
01812
int err;
01813
struct ip_mreqn imr;
01814 u32 addr = msf->
imsf_multiaddr;
01815
struct ip_mc_socklist *pmc;
01816
struct in_device *in_dev;
01817
struct inet_opt *inet = &sk->
protinfo.af_inet;
01818
struct ip_sf_socklist *newpsl, *psl;
01819
01820
if (!
MULTICAST(addr))
01821
return -EINVAL;
01822
if (msf->
imsf_fmode !=
MCAST_INCLUDE &&
01823 msf->
imsf_fmode !=
MCAST_EXCLUDE)
01824
return -EINVAL;
01825
01826 rtnl_shlock();
01827
01828 imr.
imr_multiaddr.
s_addr = msf->
imsf_multiaddr;
01829 imr.
imr_address.
s_addr = msf->
imsf_interface;
01830 imr.
imr_ifindex = ifindex;
01831 in_dev =
ip_mc_find_dev(&imr);
01832
01833
if (!in_dev) {
01834 err = -ENODEV;
01835
goto done;
01836 }
01837 err = -EADDRNOTAVAIL;
01838
01839
for (pmc=inet->mc_list; pmc; pmc=pmc->next) {
01840
if (pmc->multi.imr_multiaddr.s_addr == msf->
imsf_multiaddr &&
01841 pmc->multi.imr_ifindex == imr.
imr_ifindex)
01842
break;
01843 }
01844
if (!pmc)
01845
goto done;
01846
if (msf->
imsf_numsrc) {
01847 newpsl = (
struct ip_sf_socklist *)
sock_kmalloc(sk,
01848 IP_SFLSIZE(msf->
imsf_numsrc), GFP_KERNEL);
01849
if (!newpsl) {
01850 err = -ENOBUFS;
01851
goto done;
01852 }
01853 newpsl->sl_max = newpsl->sl_count = msf->
imsf_numsrc;
01854 memcpy(newpsl->sl_addr, msf->
imsf_slist,
01855 msf->
imsf_numsrc *
sizeof(msf->
imsf_slist[0]));
01856 err =
ip_mc_add_src(in_dev, &msf->
imsf_multiaddr,
01857 msf->
imsf_fmode, newpsl->sl_count, newpsl->sl_addr, 0);
01858
if (err) {
01859
sock_kfree_s(sk, newpsl, IP_SFLSIZE(newpsl->sl_max));
01860
goto done;
01861 }
01862 }
else
01863 newpsl = 0;
01864 psl = pmc->sflist;
01865
if (psl) {
01866 (
void)
ip_mc_del_src(in_dev, &msf->
imsf_multiaddr, pmc->sfmode,
01867 psl->sl_count, psl->sl_addr, 0);
01868
sock_kfree_s(sk, psl, IP_SFLSIZE(psl->sl_max));
01869 }
else
01870 (
void)
ip_mc_del_src(in_dev, &msf->
imsf_multiaddr, pmc->sfmode,
01871 0, 0, 0);
01872 pmc->sflist = newpsl;
01873 pmc->sfmode = msf->
imsf_fmode;
01874 done:
01875 rtnl_shunlock();
01876
return err;
01877 }
01878
01879 int ip_mc_msfget(
struct sock *sk,
struct ip_msfilter *msf,
01880
struct ip_msfilter *optval,
int *optlen)
01881 {
01882
int err, len, count, copycount;
01883
struct ip_mreqn imr;
01884 u32 addr = msf->
imsf_multiaddr;
01885
struct ip_mc_socklist *pmc;
01886
struct in_device *in_dev;
01887
struct inet_opt *inet = &sk->
protinfo.af_inet;
01888
struct ip_sf_socklist *psl;
01889
01890
if (!
MULTICAST(addr))
01891
return -EINVAL;
01892
01893 rtnl_shlock();
01894
01895 imr.
imr_multiaddr.
s_addr = msf->
imsf_multiaddr;
01896 imr.
imr_address.
s_addr = msf->
imsf_interface;
01897 imr.
imr_ifindex = 0;
01898 in_dev =
ip_mc_find_dev(&imr);
01899
01900
if (!in_dev) {
01901 err = -ENODEV;
01902
goto done;
01903 }
01904 err = -EADDRNOTAVAIL;
01905
01906
for (pmc=inet->mc_list; pmc; pmc=pmc->next) {
01907
if (pmc->multi.imr_multiaddr.s_addr == msf->
imsf_multiaddr &&
01908 pmc->multi.imr_ifindex == imr.
imr_ifindex)
01909
break;
01910 }
01911
if (!pmc)
01912
goto done;
01913 msf->
imsf_fmode = pmc->sfmode;
01914 psl = pmc->sflist;
01915 rtnl_shunlock();
01916
if (!psl) {
01917 len = 0;
01918 count = 0;
01919 }
else {
01920 count = psl->sl_count;
01921 }
01922 copycount = count < msf->
imsf_numsrc ? count : msf->
imsf_numsrc;
01923 len = copycount *
sizeof(psl->sl_addr[0]);
01924 msf->
imsf_numsrc = count;
01925
if (put_user(
IP_MSFILTER_SIZE(copycount), optlen) ||
01926 copy_to_user((
void *)optval, msf,
IP_MSFILTER_SIZE(0))) {
01927
return -EFAULT;
01928 }
01929
if (len &&
01930 copy_to_user((
void *)&optval->imsf_slist[0], psl->sl_addr, len))
01931
return -EFAULT;
01932
return 0;
01933 done:
01934 rtnl_shunlock();
01935
return err;
01936 }
01937
01938 int ip_mc_gsfget(
struct sock *sk,
struct group_filter *gsf,
01939
struct group_filter *optval,
int *optlen)
01940 {
01941
int err, i, count, copycount;
01942
struct sockaddr_in *psin;
01943 u32 addr;
01944
struct ip_mc_socklist *pmc;
01945
struct inet_opt *inet = &sk->
protinfo.af_inet;
01946
struct ip_sf_socklist *psl;
01947
01948 psin = (
struct sockaddr_in *)&gsf->
gf_group;
01949
if (psin->sin_family != AF_INET)
01950
return -EINVAL;
01951 addr = psin->sin_addr.s_addr;
01952
if (!
MULTICAST(addr))
01953
return -EINVAL;
01954
01955 rtnl_shlock();
01956
01957 err = -EADDRNOTAVAIL;
01958
01959
for (pmc=inet->mc_list; pmc; pmc=pmc->next) {
01960
if (pmc->multi.imr_multiaddr.s_addr == addr &&
01961 pmc->multi.imr_ifindex == gsf->
gf_interface)
01962
break;
01963 }
01964
if (!pmc)
01965
goto done;
01966 gsf->
gf_fmode = pmc->sfmode;
01967 psl = pmc->sflist;
01968 rtnl_shunlock();
01969 count = psl ? psl->sl_count : 0;
01970 copycount = count < gsf->
gf_numsrc ? count : gsf->
gf_numsrc;
01971 gsf->
gf_numsrc = count;
01972
if (put_user(
GROUP_FILTER_SIZE(copycount), optlen) ||
01973 copy_to_user((
void *)optval, gsf,
GROUP_FILTER_SIZE(0))) {
01974
return -EFAULT;
01975 }
01976
for (i=0; i<copycount; i++) {
01977
struct sockaddr_in *psin;
01978
struct sockaddr_storage ss;
01979
01980 psin = (
struct sockaddr_in *)&ss;
01981 memset(&ss, 0,
sizeof(ss));
01982 psin->sin_family = AF_INET;
01983 psin->sin_addr.s_addr = psl->sl_addr[i];
01984
if (copy_to_user((
void *)&optval->gf_slist[i], &ss,
sizeof(ss)))
01985
return -EFAULT;
01986 }
01987
return 0;
01988 done:
01989 rtnl_shunlock();
01990
return err;
01991 }
01992
01993
01994
01995
01996 int ip_mc_sf_allow(
struct sock *sk, u32 loc_addr, u32 rmt_addr,
int dif)
01997 {
01998
struct inet_opt *inet = &sk->
protinfo.af_inet;
01999
struct ip_mc_socklist *pmc;
02000
struct ip_sf_socklist *psl;
02001
int i;
02002
02003
if (!
MULTICAST(loc_addr))
02004
return 1;
02005
02006
for (pmc=inet->mc_list; pmc; pmc=pmc->next) {
02007
if (pmc->multi.imr_multiaddr.s_addr == loc_addr &&
02008 pmc->multi.imr_ifindex == dif)
02009
break;
02010 }
02011
if (!pmc)
02012
return 1;
02013 psl = pmc->sflist;
02014
if (!psl)
02015
return pmc->sfmode ==
MCAST_EXCLUDE;
02016
02017
for (i=0; i<psl->sl_count; i++) {
02018
if (psl->sl_addr[i] == rmt_addr)
02019
break;
02020 }
02021
if (pmc->sfmode ==
MCAST_INCLUDE && i >= psl->sl_count)
02022
return 0;
02023
if (pmc->sfmode ==
MCAST_EXCLUDE && i < psl->sl_count)
02024
return 0;
02025
return 1;
02026 }
02027
02028
02029
02030
02031
02032 void ip_mc_drop_socket(
struct sock *sk)
02033 {
02034
struct inet_opt *inet = &sk->
protinfo.af_inet;
02035
struct ip_mc_socklist *iml;
02036
02037
if (inet->mc_list == NULL)
02038
return;
02039
02040
rtnl_lock();
02041
while ((iml = inet->mc_list) != NULL) {
02042
struct in_device *in_dev;
02043 inet->
mc_list = iml->next;
02044
02045
if ((in_dev =
inetdev_by_index(iml->multi.imr_ifindex)) != NULL) {
02046 (
void)
ip_mc_leave_src(sk, iml, in_dev);
02047
ip_mc_dec_group(in_dev, iml->multi.imr_multiaddr.s_addr);
02048
in_dev_put(in_dev);
02049 }
02050
sock_kfree_s(sk, iml,
sizeof(*iml));
02051
02052 }
02053
rtnl_unlock();
02054 }
02055
02056 int ip_check_mc(
struct in_device *in_dev, u32 mc_addr, u32 src_addr)
02057 {
02058
struct ip_mc_list *im;
02059
struct ip_sf_list *psf;
02060
int rv = 0;
02061
02062 read_lock(&in_dev->
lock);
02063
for (im=in_dev->
mc_list; im; im=im->next) {
02064
if (im->multiaddr == mc_addr)
02065
break;
02066 }
02067
02068
02069
02070
02071
02072
02073
02074
if (im) {
02075
for (psf=im->sources; psf; psf=psf->sf_next) {
02076
if (psf->sf_inaddr == src_addr)
02077
break;
02078 }
02079
if (psf)
02080 rv = psf->sf_count[
MCAST_INCLUDE] ||
02081 psf->sf_count[
MCAST_EXCLUDE] !=
02082 im->sfcount[
MCAST_EXCLUDE];
02083
else
02084 rv = im->sfcount[
MCAST_EXCLUDE] != 0;
02085 }
02086 read_unlock(&in_dev->
lock);
02087
return rv;
02088 }
02089
02090
02091 int ip_mc_procinfo(
char *buffer,
char **start, off_t offset,
int length)
02092 {
02093 off_t pos=0, begin=0;
02094
struct ip_mc_list *im;
02095
int len=0;
02096
struct net_device *dev;
02097
02098 len=sprintf(buffer,
"Idx\tDevice : Count Querier\tGroup Users Timer\tReporter\n");
02099
02100 read_lock(&
dev_base_lock);
02101
for(dev =
dev_base; dev; dev = dev->
next) {
02102
struct in_device *in_dev =
in_dev_get(dev);
02103
char *querier =
"NONE";
02104
02105
if (in_dev == NULL)
02106
continue;
02107
02108
#ifdef CONFIG_IP_MULTICAST
02109
querier = IGMP_V1_SEEN(in_dev) ?
"V1" :
"V2";
02110
#endif
02111
02112 len+=sprintf(buffer+len,
"%d\t%-10s: %5d %7s\n",
02113 dev->
ifindex, dev->
name, dev->
mc_count, querier);
02114
02115 read_lock(&in_dev->
lock);
02116
for (im = in_dev->
mc_list; im; im = im->next) {
02117 len+=sprintf(buffer+len,
02118
"\t\t\t\t%08lX %5d %d:%08lX\t\t%d\n",
02119 im->multiaddr, im->users,
02120 im->tm_running, im->timer.expires-jiffies, im->reporter);
02121
02122 pos=begin+len;
02123
if(pos<offset)
02124 {
02125 len=0;
02126 begin=pos;
02127 }
02128
if(pos>offset+length) {
02129 read_unlock(&in_dev->
lock);
02130
in_dev_put(in_dev);
02131
goto done;
02132 }
02133 }
02134 read_unlock(&in_dev->
lock);
02135
in_dev_put(in_dev);
02136 }
02137 done:
02138 read_unlock(&
dev_base_lock);
02139
02140 *start=buffer+(offset-begin);
02141 len-=(offset-begin);
02142
if(len>length)
02143 len=length;
02144
if(len<0)
02145 len=0;
02146
return len;
02147 }
02148
02149 int ip_mcf_procinfo(
char *buffer,
char **start, off_t offset,
int length)
02150 {
02151 off_t pos=0, begin=0;
02152
int len=0;
02153
int first = 1;
02154
struct net_device *dev;
02155
02156 read_lock(&
dev_base_lock);
02157
for(dev=
dev_base; dev; dev=dev->
next) {
02158
struct in_device *in_dev =
in_dev_get(dev);
02159
struct ip_mc_list *imc;
02160
02161
if (in_dev == NULL)
02162
continue;
02163
02164 read_lock(&in_dev->
lock);
02165
02166
for (imc=in_dev->
mc_list; imc; imc=imc->next) {
02167
struct ip_sf_list *psf;
02168
02169 spin_lock_bh(&imc->lock);
02170
for (psf=imc->sources; psf; psf=psf->sf_next) {
02171
if (first) {
02172 len += sprintf(buffer+len,
"%3s %6s "
02173
"%10s %10s %6s %6s\n",
"Idx",
02174
"Device",
"MCA",
"SRC",
"INC",
02175
"EXC");
02176 first = 0;
02177 }
02178 len += sprintf(buffer+len,
"%3d %6.6s 0x%08x "
02179
"0x%08x %6lu %6lu\n", dev->
ifindex,
02180 dev->
name, ntohl(imc->multiaddr),
02181 ntohl(psf->sf_inaddr),
02182 psf->sf_count[
MCAST_INCLUDE],
02183 psf->sf_count[
MCAST_EXCLUDE]);
02184 pos=begin+len;
02185
if(pos<offset)
02186 {
02187 len=0;
02188 begin=pos;
02189 }
02190
if(pos>offset+length) {
02191 spin_unlock_bh(&imc->lock);
02192 read_unlock(&in_dev->
lock);
02193
in_dev_put(in_dev);
02194
goto done;
02195 }
02196 }
02197 spin_unlock_bh(&imc->lock);
02198 }
02199 read_unlock(&in_dev->
lock);
02200
in_dev_put(in_dev);
02201 }
02202 done:
02203 read_unlock(&
dev_base_lock);
02204
02205 *start=buffer+(offset-begin);
02206 len-=(offset-begin);
02207
if(len>length)
02208 len=length;
02209
if(len<0)
02210 len=0;
02211
return len;
02212 }
02213