📄 myigmp.c
字号:
#define MYIGMP_Unsolicited_Report_Count 2#define MYIGMP_Initial_Report_Delay (1)#define MYIGMP_V1_SEEN(in_dev) (myipv4_devconf.force_igmp_version == 1 || \ (in_dev)->cnf.force_igmp_version == 1 || \ ((in_dev)->mr_v1_seen && \ time_before(jiffies, (in_dev)->mr_v1_seen)))#define MYIGMP_V2_SEEN(in_dev) (myipv4_devconf.force_igmp_version == 2 || \ (in_dev)->cnf.force_igmp_version == 2 || \ ((in_dev)->mr_v2_seen && \ time_before(jiffies, (in_dev)->mr_v2_seen)))#define IP_MAX_MEMBERSHIPS 20#define IP_MAX_MSF 10int sysctl_igmp_max_memberships = IP_MAX_MEMBERSHIPS;int sysctl_igmp_max_msf = IP_MAX_MSF;static void myip_ma_put(struct ip_mc_list *im){ if (atomic_dec_and_test(&im->refcnt)) { in_dev_put(im->interface); kfree(im); }}int myip_check_mc(struct in_device *in_dev, u32 mc_addr, u32 src_addr, u16 proto){ struct ip_mc_list *im; struct ip_sf_list *psf; int rv = 0; read_lock(&in_dev->mc_list_lock); for( im=in_dev->mc_list; im; im=im->next ){ if( im->multiaddr == mc_addr ) break; } if( im && proto == IPPROTO_IGMP ){ rv = 1; }else if( im ){ if( src_addr ){ for( psf=im->sources; psf; psf=psf->sf_next ){ if (psf->sf_inaddr == src_addr) break; } if (psf) rv = psf->sf_count[MCAST_INCLUDE] || psf->sf_count[MCAST_EXCLUDE] != im->sfcount[MCAST_EXCLUDE]; else rv = im->sfcount[MCAST_EXCLUDE] != 0; }else rv = 1; } read_unlock(&in_dev->mc_list_lock); return rv;}int myip_mc_sf_allow(struct sock *sk, u32 loc_addr, u32 rmt_addr, int dif){ struct inet_sock *inet = inet_sk(sk); struct ip_mc_socklist *pmc; struct ip_sf_socklist *psl; int i; if (!MULTICAST(loc_addr)) return 1; for( pmc=inet->mc_list; pmc; pmc=pmc->next ){ if (pmc->multi.imr_multiaddr.s_addr == loc_addr && pmc->multi.imr_ifindex == dif) break; } if (!pmc) return 1; psl = pmc->sflist; if (!psl) return pmc->sfmode == MCAST_EXCLUDE; for (i=0; i<psl->sl_count; i++) { if (psl->sl_addr[i] == rmt_addr) break; } if (pmc->sfmode == MCAST_INCLUDE && i >= psl->sl_count) return 0; if (pmc->sfmode == MCAST_EXCLUDE && i < psl->sl_count) return 0; return 1;}static void myigmp_ifc_start_timer(struct in_device *in_dev, int delay){ int tv = net_random() % delay; if( !mod_timer(&in_dev->mr_ifc_timer, jiffies+tv+2) ) in_dev_hold(in_dev);}static void myigmp_ifc_event(struct in_device *in_dev){ if( MYIGMP_V1_SEEN(in_dev) || MYIGMP_V2_SEEN(in_dev) ) return; in_dev->mr_ifc_count = in_dev->mr_qrv ? in_dev->mr_qrv : MYIGMP_Unsolicited_Report_Count; myigmp_ifc_start_timer(in_dev, 1);}static int myip_mc_add1_src(struct ip_mc_list *pmc, int sfmode, __u32 *psfsrc, int delta){ struct ip_sf_list *psf, *psf_prev; psf_prev = NULL; for( psf=pmc->sources; psf; psf=psf->sf_next ){ if( psf->sf_inaddr == *psfsrc ) break; psf_prev = psf; } if (!psf) { psf = kmalloc(sizeof(*psf), GFP_ATOMIC); if (!psf) return -ENOBUFS; memset(psf, 0, sizeof(*psf)); psf->sf_inaddr = *psfsrc; if (psf_prev) { psf_prev->sf_next = psf; } else pmc->sources = psf; } psf->sf_count[sfmode]++; if (psf->sf_count[sfmode] == 1) { ip_rt_multicast_event(pmc->interface); } return 0;}static int myip_mc_del1_src(struct ip_mc_list *pmc, int sfmode, __u32 *psfsrc){ struct ip_sf_list *psf, *psf_prev; int rv = 0; psf_prev = NULL; for (psf=pmc->sources; psf; psf=psf->sf_next) { if (psf->sf_inaddr == *psfsrc) break; psf_prev = psf; } if (!psf || psf->sf_count[sfmode] == 0) { return -ESRCH; } psf->sf_count[sfmode]--; if (psf->sf_count[sfmode] == 0) { myip_rt_multicast_event(pmc->interface); } if (!psf->sf_count[MCAST_INCLUDE] && !psf->sf_count[MCAST_EXCLUDE]) {#ifdef CONFIG_IP_MULTICAST struct in_device *in_dev = pmc->interface;#endif if (psf_prev) psf_prev->sf_next = psf->sf_next; else pmc->sources = psf->sf_next;#ifdef CONFIG_IP_MULTICAST if (psf->sf_oldin && !MYIGMP_V1_SEEN(in_dev) && !MYIGMP_V2_SEEN(in_dev)) { psf->sf_crcount = in_dev->mr_qrv ? in_dev->mr_qrv : MYIGMP_Unsolicited_Report_Count; psf->sf_next = pmc->tomb; pmc->tomb = psf; rv = 1; } else#endif kfree(psf); } return rv;}#ifdef CONFIG_IP_MULTICASTstatic void mysf_markstate(struct ip_mc_list *pmc){ struct ip_sf_list *psf; int mca_xcount = pmc->sfcount[MCAST_EXCLUDE]; for (psf=pmc->sources; psf; psf=psf->sf_next) if( pmc->sfcount[MCAST_EXCLUDE] ){ psf->sf_oldin = mca_xcount == psf->sf_count[MCAST_EXCLUDE] && !psf->sf_count[MCAST_INCLUDE]; } else psf->sf_oldin = psf->sf_count[MCAST_INCLUDE] != 0;}static int mysf_setstate(struct ip_mc_list *pmc){ return 0;}#endifstatic int myip_mc_add_src(struct in_device *in_dev, __u32 *pmca, int sfmode, int sfcount, __u32 *psfsrc, int delta){ struct ip_mc_list *pmc; int isexclude; int i, err; if (!in_dev) return -ENODEV; read_lock( &in_dev->mc_list_lock ); for( pmc = in_dev->mc_list; pmc; pmc = pmc->next ){ if( *pmca == pmc->multiaddr ) break; } if( !pmc ){ read_unlock( &in_dev->mc_list_lock ); return -ESRCH; } spin_lock_bh( &pmc->lock ); read_unlock( &in_dev->mc_list_lock ); #ifdef CONFIG_IP_MULTICAST mysf_markstate( pmc );#endif isexclude = pmc->sfmode == MCAST_EXCLUDE; if( !delta ) pmc->sfcount[sfmode]++; err = 0; for (i=0; i<sfcount; i++) { err = myip_mc_add1_src(pmc, sfmode, &psfsrc[i], delta); if( err ) break; } if (err) { int j; pmc->sfcount[sfmode]--; for( j=0; j<i; j++ ) (void) myip_mc_del1_src( pmc, sfmode, &psfsrc[i] ); }else if( isexclude != (pmc->sfcount[MCAST_EXCLUDE] != 0) ){#ifdef CONFIG_IP_MULTICAST struct in_device *in_dev = pmc->interface; struct ip_sf_list *psf;#endif if( pmc->sfcount[MCAST_EXCLUDE] ) pmc->sfmode = MCAST_EXCLUDE; else if( pmc->sfcount[MCAST_INCLUDE] ) pmc->sfmode = MCAST_INCLUDE;#ifdef CONFIG_IP_MULTICAST pmc->crcount = in_dev->mr_qrv ? in_dev->mr_qrv : MYIGMP_Unsolicited_Report_Count; in_dev->mr_ifc_count = pmc->crcount; for( psf=pmc->sources; psf; psf = psf->sf_next ) psf->sf_crcount = 0; myigmp_ifc_event(in_dev); }else if( mysf_setstate(pmc) ){ myigmp_ifc_event(in_dev);#endif } spin_unlock_bh(&pmc->lock); return err;}static void myigmp_timer_expire(unsigned long data){}static void myigmpv3_del_delrec(struct in_device *in_dev, __u32 multiaddr){ struct ip_mc_list *pmc, *pmc_prev; struct ip_sf_list *psf, *psf_next; spin_lock_bh(&in_dev->mc_tomb_lock); pmc_prev = NULL; for( pmc=in_dev->mc_tomb; pmc; pmc=pmc->next ){ if (pmc->multiaddr == multiaddr) break; pmc_prev = pmc; } if( pmc ){ if (pmc_prev) pmc_prev->next = pmc->next; else in_dev->mc_tomb = pmc->next; } spin_unlock_bh(&in_dev->mc_tomb_lock); if( pmc ){ for (psf=pmc->tomb; psf; psf=psf_next) { psf_next = psf->sf_next; kfree(psf); } in_dev_put(pmc->interface); kfree(pmc); }}static void myip_mc_filter_add(struct in_device *in_dev, u32 addr){ char buf[MAX_ADDR_LEN]; struct net_device *dev = in_dev->dev; if( myarp_mc_map(addr, buf, dev, 0) == 0 ) dev_mc_add( dev,buf,dev->addr_len,0 );}static void myip_mc_filter_del(struct in_device *in_dev, u32 addr){ char buf[MAX_ADDR_LEN]; struct net_device *dev = in_dev->dev; if( myarp_mc_map(addr, buf, dev, 0) == 0 ) dev_mc_delete(dev,buf,dev->addr_len,0);}static void myigmp_start_timer(struct ip_mc_list *im, int max_delay){ int tv = net_random() % max_delay; im->tm_running = 1; if( !mod_timer(&im->timer, jiffies+tv+2) ) atomic_inc( &im->refcnt );}static __inline__ void myigmp_stop_timer(struct ip_mc_list *im){ spin_lock_bh(&im->lock); if (del_timer(&im->timer)) atomic_dec(&im->refcnt); im->tm_running=0; im->reporter = 0; im->unsolicit_count = 0; spin_unlock_bh(&im->lock);}static int myigmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc, int type){ return 0;}static void myip_mc_clear_src(struct ip_mc_list *pmc){ struct ip_sf_list *psf, *nextpsf; for( psf=pmc->tomb; psf; psf=nextpsf ){ nextpsf = psf->sf_next; kfree(psf); } pmc->tomb = NULL; for (psf=pmc->sources; psf; psf=nextpsf) { nextpsf = psf->sf_next; kfree(psf); } pmc->sources = NULL; pmc->sfmode = MCAST_EXCLUDE; pmc->sfcount[MCAST_INCLUDE] = 0; pmc->sfcount[MCAST_EXCLUDE] = 1;}static void myigmpv3_add_delrec(struct in_device *in_dev, struct ip_mc_list *im){ struct ip_mc_list *pmc; pmc = kmalloc(sizeof(*pmc), GFP_KERNEL); if (!pmc) return; memset(pmc, 0, sizeof(*pmc)); spin_lock_bh(&im->lock); pmc->interface = im->interface; in_dev_hold(in_dev); pmc->multiaddr = im->multiaddr; pmc->crcount = in_dev->mr_qrv ? in_dev->mr_qrv : MYIGMP_Unsolicited_Report_Count; pmc->sfmode = im->sfmode; if (pmc->sfmode == MCAST_INCLUDE) { struct ip_sf_list *psf; pmc->tomb = im->tomb; pmc->sources = im->sources; im->tomb = im->sources = NULL; for (psf=pmc->sources; psf; psf=psf->sf_next) psf->sf_crcount = pmc->crcount; } spin_unlock_bh(&im->lock); spin_lock_bh(&in_dev->mc_tomb_lock); pmc->next = in_dev->mc_tomb; in_dev->mc_tomb = pmc; spin_unlock_bh(&in_dev->mc_tomb_lock);}static void myigmp_group_dropped(struct ip_mc_list *im){ struct in_device *in_dev = im->interface;#ifdef CONFIG_IP_MULTICAST int reporter;#endif if (im->loaded) { im->loaded = 0; myip_mc_filter_del(in_dev, im->multiaddr); }#ifdef CONFIG_IP_MULTICAST if (im->multiaddr == IGMP_ALL_HOSTS) return; reporter = im->reporter; myigmp_stop_timer(im); if (!in_dev->dead) { if( MYIGMP_V1_SEEN(in_dev) ) goto done; if( MYIGMP_V2_SEEN(in_dev) ){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -