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

📄 igmp.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	struct ip_sf_socklist *psl;	if (!MULTICAST(addr))		return -EINVAL;	rtnl_lock();	imr.imr_multiaddr.s_addr = msf->imsf_multiaddr;	imr.imr_address.s_addr = msf->imsf_interface;	imr.imr_ifindex = 0;	in_dev = ip_mc_find_dev(&imr);	if (!in_dev) {		err = -ENODEV;		goto done;	}	err = -EADDRNOTAVAIL;	for (pmc=inet->mc_list; pmc; pmc=pmc->next) {		if (pmc->multi.imr_multiaddr.s_addr == msf->imsf_multiaddr &&		    pmc->multi.imr_ifindex == imr.imr_ifindex)			break;	}	if (!pmc)		/* must have a prior join */		goto done;	msf->imsf_fmode = pmc->sfmode;	psl = pmc->sflist;	rtnl_unlock();	if (!psl) {		len = 0;		count = 0;	} else {		count = psl->sl_count;	}	copycount = count < msf->imsf_numsrc ? count : msf->imsf_numsrc;	len = copycount * sizeof(psl->sl_addr[0]);	msf->imsf_numsrc = count;	if (put_user(IP_MSFILTER_SIZE(copycount), optlen) ||	    copy_to_user(optval, msf, IP_MSFILTER_SIZE(0))) {		return -EFAULT;	}	if (len &&	    copy_to_user(&optval->imsf_slist[0], psl->sl_addr, len))		return -EFAULT;	return 0;done:	rtnl_unlock();	return err;}int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf,	struct group_filter __user *optval, int __user *optlen){	int err, i, count, copycount;	struct sockaddr_in *psin;	__be32 addr;	struct ip_mc_socklist *pmc;	struct inet_sock *inet = inet_sk(sk);	struct ip_sf_socklist *psl;	psin = (struct sockaddr_in *)&gsf->gf_group;	if (psin->sin_family != AF_INET)		return -EINVAL;	addr = psin->sin_addr.s_addr;	if (!MULTICAST(addr))		return -EINVAL;	rtnl_lock();	err = -EADDRNOTAVAIL;	for (pmc=inet->mc_list; pmc; pmc=pmc->next) {		if (pmc->multi.imr_multiaddr.s_addr == addr &&		    pmc->multi.imr_ifindex == gsf->gf_interface)			break;	}	if (!pmc)		/* must have a prior join */		goto done;	gsf->gf_fmode = pmc->sfmode;	psl = pmc->sflist;	rtnl_unlock();	count = psl ? psl->sl_count : 0;	copycount = count < gsf->gf_numsrc ? count : gsf->gf_numsrc;	gsf->gf_numsrc = count;	if (put_user(GROUP_FILTER_SIZE(copycount), optlen) ||	    copy_to_user(optval, gsf, GROUP_FILTER_SIZE(0))) {		return -EFAULT;	}	for (i=0; i<copycount; i++) {		struct sockaddr_storage ss;		psin = (struct sockaddr_in *)&ss;		memset(&ss, 0, sizeof(ss));		psin->sin_family = AF_INET;		psin->sin_addr.s_addr = psl->sl_addr[i];		if (copy_to_user(&optval->gf_slist[i], &ss, sizeof(ss)))			return -EFAULT;	}	return 0;done:	rtnl_unlock();	return err;}/* * check if a multicast source filter allows delivery for a given <src,dst,intf> */int ip_mc_sf_allow(struct sock *sk, __be32 loc_addr, __be32 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;}/* *	A socket is closing. */void ip_mc_drop_socket(struct sock *sk){	struct inet_sock *inet = inet_sk(sk);	struct ip_mc_socklist *iml;	if (inet->mc_list == NULL)		return;	rtnl_lock();	while ((iml = inet->mc_list) != NULL) {		struct in_device *in_dev;		inet->mc_list = iml->next;		in_dev = inetdev_by_index(iml->multi.imr_ifindex);		(void) ip_mc_leave_src(sk, iml, in_dev);		if (in_dev != NULL) {			ip_mc_dec_group(in_dev, iml->multi.imr_multiaddr.s_addr);			in_dev_put(in_dev);		}		sock_kfree_s(sk, iml, sizeof(*iml));	}	rtnl_unlock();}int ip_check_mc(struct in_device *in_dev, __be32 mc_addr, __be32 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; /* unspecified source; tentatively allow */	}	read_unlock(&in_dev->mc_list_lock);	return rv;}#if defined(CONFIG_PROC_FS)struct igmp_mc_iter_state {	struct net_device *dev;	struct in_device *in_dev;};#define	igmp_mc_seq_private(seq)	((struct igmp_mc_iter_state *)(seq)->private)static inline struct ip_mc_list *igmp_mc_get_first(struct seq_file *seq){	struct ip_mc_list *im = NULL;	struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq);	state->in_dev = NULL;	for_each_netdev(&init_net, state->dev) {		struct in_device *in_dev;		in_dev = in_dev_get(state->dev);		if (!in_dev)			continue;		read_lock(&in_dev->mc_list_lock);		im = in_dev->mc_list;		if (im) {			state->in_dev = in_dev;			break;		}		read_unlock(&in_dev->mc_list_lock);		in_dev_put(in_dev);	}	return im;}static struct ip_mc_list *igmp_mc_get_next(struct seq_file *seq, struct ip_mc_list *im){	struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq);	im = im->next;	while (!im) {		if (likely(state->in_dev != NULL)) {			read_unlock(&state->in_dev->mc_list_lock);			in_dev_put(state->in_dev);		}		state->dev = next_net_device(state->dev);		if (!state->dev) {			state->in_dev = NULL;			break;		}		state->in_dev = in_dev_get(state->dev);		if (!state->in_dev)			continue;		read_lock(&state->in_dev->mc_list_lock);		im = state->in_dev->mc_list;	}	return im;}static struct ip_mc_list *igmp_mc_get_idx(struct seq_file *seq, loff_t pos){	struct ip_mc_list *im = igmp_mc_get_first(seq);	if (im)		while (pos && (im = igmp_mc_get_next(seq, im)) != NULL)			--pos;	return pos ? NULL : im;}static void *igmp_mc_seq_start(struct seq_file *seq, loff_t *pos){	read_lock(&dev_base_lock);	return *pos ? igmp_mc_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;}static void *igmp_mc_seq_next(struct seq_file *seq, void *v, loff_t *pos){	struct ip_mc_list *im;	if (v == SEQ_START_TOKEN)		im = igmp_mc_get_first(seq);	else		im = igmp_mc_get_next(seq, v);	++*pos;	return im;}static void igmp_mc_seq_stop(struct seq_file *seq, void *v){	struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq);	if (likely(state->in_dev != NULL)) {		read_unlock(&state->in_dev->mc_list_lock);		in_dev_put(state->in_dev);		state->in_dev = NULL;	}	state->dev = NULL;	read_unlock(&dev_base_lock);}static int igmp_mc_seq_show(struct seq_file *seq, void *v){	if (v == SEQ_START_TOKEN)		seq_puts(seq,			 "Idx\tDevice    : Count Querier\tGroup    Users Timer\tReporter\n");	else {		struct ip_mc_list *im = (struct ip_mc_list *)v;		struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq);		char   *querier;#ifdef CONFIG_IP_MULTICAST		querier = IGMP_V1_SEEN(state->in_dev) ? "V1" :			  IGMP_V2_SEEN(state->in_dev) ? "V2" :			  "V3";#else		querier = "NONE";#endif		if (state->in_dev->mc_list == im) {			seq_printf(seq, "%d\t%-10s: %5d %7s\n",				   state->dev->ifindex, state->dev->name, state->dev->mc_count, querier);		}		seq_printf(seq,			   "\t\t\t\t%08X %5d %d:%08lX\t\t%d\n",			   im->multiaddr, im->users,			   im->tm_running, im->tm_running ?			   jiffies_to_clock_t(im->timer.expires-jiffies) : 0,			   im->reporter);	}	return 0;}static const struct seq_operations igmp_mc_seq_ops = {	.start	=	igmp_mc_seq_start,	.next	=	igmp_mc_seq_next,	.stop	=	igmp_mc_seq_stop,	.show	=	igmp_mc_seq_show,};static int igmp_mc_seq_open(struct inode *inode, struct file *file){	return seq_open_private(file, &igmp_mc_seq_ops,			sizeof(struct igmp_mc_iter_state));}static const struct file_operations igmp_mc_seq_fops = {	.owner		=	THIS_MODULE,	.open		=	igmp_mc_seq_open,	.read		=	seq_read,	.llseek		=	seq_lseek,	.release	=	seq_release_private,};struct igmp_mcf_iter_state {	struct net_device *dev;	struct in_device *idev;	struct ip_mc_list *im;};#define igmp_mcf_seq_private(seq)	((struct igmp_mcf_iter_state *)(seq)->private)static inline struct ip_sf_list *igmp_mcf_get_first(struct seq_file *seq){	struct ip_sf_list *psf = NULL;	struct ip_mc_list *im = NULL;	struct igmp_mcf_iter_state *state = igmp_mcf_seq_private(seq);	state->idev = NULL;	state->im = NULL;	for_each_netdev(&init_net, state->dev) {		struct in_device *idev;		idev = in_dev_get(state->dev);		if (unlikely(idev == NULL))			continue;		read_lock(&idev->mc_list_lock);		im = idev->mc_list;		if (likely(im != NULL)) {			spin_lock_bh(&im->lock);			psf = im->sources;			if (likely(psf != NULL)) {				state->im = im;				state->idev = idev;				break;			}			spin_unlock_bh(&im->lock);		}		read_unlock(&idev->mc_list_lock);		in_dev_put(idev);	}	return psf;}static struct ip_sf_list *igmp_mcf_get_next(struct seq_file *seq, struct ip_sf_list *psf){	struct igmp_mcf_iter_state *state = igmp_mcf_seq_private(seq);	psf = psf->sf_next;	while (!psf) {		spin_unlock_bh(&state->im->lock);		state->im = state->im->next;		while (!state->im) {			if (likely(state->idev != NULL)) {				read_unlock(&state->idev->mc_list_lock);				in_dev_put(state->idev);			}			state->dev = next_net_device(state->dev);			if (!state->dev) {				state->idev = NULL;				goto out;			}			state->idev = in_dev_get(state->dev);			if (!state->idev)				continue;			read_lock(&state->idev->mc_list_lock);			state->im = state->idev->mc_list;		}		if (!state->im)			break;		spin_lock_bh(&state->im->lock);		psf = state->im->sources;	}out:	return psf;}static struct ip_sf_list *igmp_mcf_get_idx(struct seq_file *seq, loff_t pos){	struct ip_sf_list *psf = igmp_mcf_get_first(seq);	if (psf)		while (pos && (psf = igmp_mcf_get_next(seq, psf)) != NULL)			--pos;	return pos ? NULL : psf;}static void *igmp_mcf_seq_start(struct seq_file *seq, loff_t *pos){	read_lock(&dev_base_lock);	return *pos ? igmp_mcf_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;}static void *igmp_mcf_seq_next(struct seq_file *seq, void *v, loff_t *pos){	struct ip_sf_list *psf;	if (v == SEQ_START_TOKEN)		psf = igmp_mcf_get_first(seq);	else		psf = igmp_mcf_get_next(seq, v);	++*pos;	return psf;}static void igmp_mcf_seq_stop(struct seq_file *seq, void *v){	struct igmp_mcf_iter_state *state = igmp_mcf_seq_private(seq);	if (likely(state->im != NULL)) {		spin_unlock_bh(&state->im->lock);		state->im = NULL;	}	if (likely(state->idev != NULL)) {		read_unlock(&state->idev->mc_list_lock);		in_dev_put(state->idev);		state->idev = NULL;	}	state->dev = NULL;	read_unlock(&dev_base_lock);}static int igmp_mcf_seq_show(struct seq_file *seq, void *v){	struct ip_sf_list *psf = (struct ip_sf_list *)v;	struct igmp_mcf_iter_state *state = igmp_mcf_seq_private(seq);	if (v == SEQ_START_TOKEN) {		seq_printf(seq,			   "%3s %6s "			   "%10s %10s %6s %6s\n", "Idx",			   "Device", "MCA",			   "SRC", "INC", "EXC");	} else {		seq_printf(seq,			   "%3d %6.6s 0x%08x "			   "0x%08x %6lu %6lu\n",			   state->dev->ifindex, state->dev->name,			   ntohl(state->im->multiaddr),			   ntohl(psf->sf_inaddr),			   psf->sf_count[MCAST_INCLUDE],			   psf->sf_count[MCAST_EXCLUDE]);	}	return 0;}static const struct seq_operations igmp_mcf_seq_ops = {	.start	=	igmp_mcf_seq_start,	.next	=	igmp_mcf_seq_next,	.stop	=	igmp_mcf_seq_stop,	.show	=	igmp_mcf_seq_show,};static int igmp_mcf_seq_open(struct inode *inode, struct file *file){	return seq_open_private(file, &igmp_mcf_seq_ops,			sizeof(struct igmp_mcf_iter_state));}static const struct file_operations igmp_mcf_seq_fops = {	.owner		=	THIS_MODULE,	.open		=	igmp_mcf_seq_open,	.read		=	seq_read,	.llseek		=	seq_lseek,	.release	=	seq_release_private,};int __init igmp_mc_proc_init(void){	proc_net_fops_create(&init_net, "igmp", S_IRUGO, &igmp_mc_seq_fops);	proc_net_fops_create(&init_net, "mcfilter", S_IRUGO, &igmp_mcf_seq_fops);	return 0;}#endifEXPORT_SYMBOL(ip_mc_dec_group);EXPORT_SYMBOL(ip_mc_inc_group);EXPORT_SYMBOL(ip_mc_join_group);EXPORT_SYMBOL(ip_mc_rejoin_group);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -