⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 myigmp.c

📁 一个基于linux的TCP/IP协议栈的实现
💻 C
📖 第 1 页 / 共 2 页
字号:
#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 + -