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

📄 ip_sockglue.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 2 页
字号:
			 *	Check the arguments are allowable			 */			err = -EFAULT;			if (optlen >= sizeof(struct ip_mreqn)) {				if (copy_from_user(&mreq,optval,sizeof(mreq)))					break;			} else {				memset(&mreq, 0, sizeof(mreq));				if (optlen >= sizeof(struct in_addr) &&				    copy_from_user(&mreq.imr_address,optval,sizeof(struct in_addr)))					break;			}			if (!mreq.imr_ifindex) {				if (mreq.imr_address.s_addr == INADDR_ANY) {					inet->mc_index = 0;					inet->mc_addr  = 0;					err = 0;					break;				}				dev = ip_dev_find(mreq.imr_address.s_addr);				if (dev) {					mreq.imr_ifindex = dev->ifindex;					dev_put(dev);				}			} else				dev = __dev_get_by_index(mreq.imr_ifindex);			err = -EADDRNOTAVAIL;			if (!dev)				break;			err = -EINVAL;			if (sk->sk_bound_dev_if &&			    mreq.imr_ifindex != sk->sk_bound_dev_if)				break;			inet->mc_index = mreq.imr_ifindex;			inet->mc_addr  = mreq.imr_address.s_addr;			err = 0;			break;		}		case IP_ADD_MEMBERSHIP:		case IP_DROP_MEMBERSHIP: 		{			struct ip_mreqn mreq;			if (optlen < sizeof(struct ip_mreq))				goto e_inval;			err = -EFAULT;			if (optlen >= sizeof(struct ip_mreqn)) {				if(copy_from_user(&mreq,optval,sizeof(mreq)))					break;			} else {				memset(&mreq, 0, sizeof(mreq));				if (copy_from_user(&mreq,optval,sizeof(struct ip_mreq)))					break; 			}			if (optname == IP_ADD_MEMBERSHIP)				err = ip_mc_join_group(sk, &mreq);			else				err = ip_mc_leave_group(sk, &mreq);			break;		}		case IP_MSFILTER:		{			extern int sysctl_optmem_max;			extern int sysctl_igmp_max_msf;			struct ip_msfilter *msf;			if (optlen < IP_MSFILTER_SIZE(0))				goto e_inval;			if (optlen > sysctl_optmem_max) {				err = -ENOBUFS;				break;			}			msf = (struct ip_msfilter *)kmalloc(optlen, GFP_KERNEL);			if (msf == 0) {				err = -ENOBUFS;				break;			}			err = -EFAULT;			if (copy_from_user(msf, optval, optlen)) {				kfree(msf);				break;			}			/* numsrc >= (1G-4) overflow in 32 bits */			if (msf->imsf_numsrc >= 0x3ffffffcU ||			    msf->imsf_numsrc > sysctl_igmp_max_msf) {				kfree(msf);				err = -ENOBUFS;				break;			}			if (IP_MSFILTER_SIZE(msf->imsf_numsrc) > optlen) {				kfree(msf);				err = -EINVAL;				break;			}			err = ip_mc_msfilter(sk, msf, 0);			kfree(msf);			break;		}		case IP_BLOCK_SOURCE:		case IP_UNBLOCK_SOURCE:		case IP_ADD_SOURCE_MEMBERSHIP:		case IP_DROP_SOURCE_MEMBERSHIP:		{			struct ip_mreq_source mreqs;			int omode, add;			if (optlen != sizeof(struct ip_mreq_source))				goto e_inval;			if (copy_from_user(&mreqs, optval, sizeof(mreqs))) {				err = -EFAULT;				break;			}			if (optname == IP_BLOCK_SOURCE) {				omode = MCAST_EXCLUDE;				add = 1;			} else if (optname == IP_UNBLOCK_SOURCE) {				omode = MCAST_EXCLUDE;				add = 0;			} else if (optname == IP_ADD_SOURCE_MEMBERSHIP) {				struct ip_mreqn mreq;				mreq.imr_multiaddr.s_addr = mreqs.imr_multiaddr;				mreq.imr_address.s_addr = mreqs.imr_interface;				mreq.imr_ifindex = 0;				err = ip_mc_join_group(sk, &mreq);				if (err)					break;				omode = MCAST_INCLUDE;				add = 1;			} else /*IP_DROP_SOURCE_MEMBERSHIP */ {				omode = MCAST_INCLUDE;				add = 0;			}			err = ip_mc_source(add, omode, sk, &mreqs, 0);			break;		}		case MCAST_JOIN_GROUP:		case MCAST_LEAVE_GROUP: 		{			struct group_req greq;			struct sockaddr_in *psin;			struct ip_mreqn mreq;			if (optlen < sizeof(struct group_req))				goto e_inval;			err = -EFAULT;			if(copy_from_user(&greq, optval, sizeof(greq)))				break;			psin = (struct sockaddr_in *)&greq.gr_group;			if (psin->sin_family != AF_INET)				goto e_inval;			memset(&mreq, 0, sizeof(mreq));			mreq.imr_multiaddr = psin->sin_addr;			mreq.imr_ifindex = greq.gr_interface;			if (optname == MCAST_JOIN_GROUP)				err = ip_mc_join_group(sk, &mreq);			else				err = ip_mc_leave_group(sk, &mreq);			break;		}		case MCAST_JOIN_SOURCE_GROUP:		case MCAST_LEAVE_SOURCE_GROUP:		case MCAST_BLOCK_SOURCE:		case MCAST_UNBLOCK_SOURCE:		{			struct group_source_req greqs;			struct ip_mreq_source mreqs;			struct sockaddr_in *psin;			int omode, add;			if (optlen != sizeof(struct group_source_req))				goto e_inval;			if (copy_from_user(&greqs, optval, sizeof(greqs))) {				err = -EFAULT;				break;			}			if (greqs.gsr_group.ss_family != AF_INET ||			    greqs.gsr_source.ss_family != AF_INET) {				err = -EADDRNOTAVAIL;				break;			}			psin = (struct sockaddr_in *)&greqs.gsr_group;			mreqs.imr_multiaddr = psin->sin_addr.s_addr;			psin = (struct sockaddr_in *)&greqs.gsr_source;			mreqs.imr_sourceaddr = psin->sin_addr.s_addr;			mreqs.imr_interface = 0; /* use index for mc_source */			if (optname == MCAST_BLOCK_SOURCE) {				omode = MCAST_EXCLUDE;				add = 1;			} else if (optname == MCAST_UNBLOCK_SOURCE) {				omode = MCAST_EXCLUDE;				add = 0;			} else if (optname == MCAST_JOIN_SOURCE_GROUP) {				struct ip_mreqn mreq;				psin = (struct sockaddr_in *)&greqs.gsr_group;				mreq.imr_multiaddr = psin->sin_addr;				mreq.imr_address.s_addr = 0;				mreq.imr_ifindex = greqs.gsr_interface;				err = ip_mc_join_group(sk, &mreq);				if (err)					break;				greqs.gsr_interface = mreq.imr_ifindex;				omode = MCAST_INCLUDE;				add = 1;			} else /* MCAST_LEAVE_SOURCE_GROUP */ {				omode = MCAST_INCLUDE;				add = 0;			}			err = ip_mc_source(add, omode, sk, &mreqs,				greqs.gsr_interface);			break;		}		case MCAST_MSFILTER:		{			extern int sysctl_optmem_max;			extern int sysctl_igmp_max_msf;			struct sockaddr_in *psin;			struct ip_msfilter *msf = NULL;			struct group_filter *gsf = NULL;			int msize, i, ifindex;			if (optlen < GROUP_FILTER_SIZE(0))				goto e_inval;			if (optlen > sysctl_optmem_max) {				err = -ENOBUFS;				break;			}			gsf = (struct group_filter *)kmalloc(optlen,GFP_KERNEL);			if (gsf == 0) {				err = -ENOBUFS;				break;			}			err = -EFAULT;			if (copy_from_user(gsf, optval, optlen)) {				goto mc_msf_out;			}			/* numsrc >= (4G-140)/128 overflow in 32 bits */			if (gsf->gf_numsrc >= 0x1ffffff ||			    gsf->gf_numsrc > sysctl_igmp_max_msf) {				err = -ENOBUFS;				goto mc_msf_out;			}			if (GROUP_FILTER_SIZE(gsf->gf_numsrc) > optlen) {				err = -EINVAL;				goto mc_msf_out;			}			msize = IP_MSFILTER_SIZE(gsf->gf_numsrc);			msf = (struct ip_msfilter *)kmalloc(msize,GFP_KERNEL);			if (msf == 0) {				err = -ENOBUFS;				goto mc_msf_out;			}			ifindex = gsf->gf_interface;			psin = (struct sockaddr_in *)&gsf->gf_group;			if (psin->sin_family != AF_INET) {				err = -EADDRNOTAVAIL;				goto mc_msf_out;			}			msf->imsf_multiaddr = psin->sin_addr.s_addr;			msf->imsf_interface = 0;			msf->imsf_fmode = gsf->gf_fmode;			msf->imsf_numsrc = gsf->gf_numsrc;			err = -EADDRNOTAVAIL;			for (i=0; i<gsf->gf_numsrc; ++i) {				psin = (struct sockaddr_in *)&gsf->gf_slist[i];				if (psin->sin_family != AF_INET)					goto mc_msf_out;				msf->imsf_slist[i] = psin->sin_addr.s_addr;			}			kfree(gsf);			gsf = NULL;			err = ip_mc_msfilter(sk, msf, ifindex);mc_msf_out:			if (msf)				kfree(msf);			if (gsf)				kfree(gsf);			break;		}		case IP_ROUTER_ALERT:				err = ip_ra_control(sk, val ? 1 : 0, NULL);			break;		case IP_FREEBIND:			if (optlen<1)				goto e_inval;			inet->freebind = !!val; 	                break;			 		case IP_IPSEC_POLICY:		case IP_XFRM_POLICY:			err = xfrm_user_policy(sk, optname, optval, optlen);			break;		default:#ifdef CONFIG_NETFILTER			err = nf_setsockopt(sk, PF_INET, optname, optval, 					    optlen);#else			err = -ENOPROTOOPT;#endif			break;	}	release_sock(sk);	return err;e_inval:	release_sock(sk);	return -EINVAL;}/* *	Get the options. Note for future reference. The GET of IP options gets the *	_received_ ones. The set sets the _sent_ ones. */int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen){	struct inet_opt *inet = inet_sk(sk);	int val;	int len;		if(level!=SOL_IP)		return -EOPNOTSUPP;#ifdef CONFIG_IP_MROUTE	if(optname>=MRT_BASE && optname <=MRT_BASE+10)	{		return ip_mroute_getsockopt(sk,optname,optval,optlen);	}#endif	if(get_user(len,optlen))		return -EFAULT;	if(len < 0)		return -EINVAL;			lock_sock(sk);	switch(optname)	{		case IP_OPTIONS:			{				unsigned char optbuf[sizeof(struct ip_options)+40];				struct ip_options * opt = (struct ip_options*)optbuf;				opt->optlen = 0;				if (inet->opt)					memcpy(optbuf, inet->opt,					       sizeof(struct ip_options)+					       inet->opt->optlen);				release_sock(sk);				if (opt->optlen == 0) 					return put_user(0, optlen);				ip_options_undo(opt);				len = min_t(unsigned int, len, opt->optlen);				if(put_user(len, optlen))					return -EFAULT;				if(copy_to_user(optval, opt->__data, len))					return -EFAULT;				return 0;			}		case IP_PKTINFO:			val = (inet->cmsg_flags & IP_CMSG_PKTINFO) != 0;			break;		case IP_RECVTTL:			val = (inet->cmsg_flags & IP_CMSG_TTL) != 0;			break;		case IP_RECVTOS:			val = (inet->cmsg_flags & IP_CMSG_TOS) != 0;			break;		case IP_RECVOPTS:			val = (inet->cmsg_flags & IP_CMSG_RECVOPTS) != 0;			break;		case IP_RETOPTS:			val = (inet->cmsg_flags & IP_CMSG_RETOPTS) != 0;			break;		case IP_TOS:			val = inet->tos;			break;		case IP_TTL:			val = (inet->uc_ttl == -1 ?			       sysctl_ip_default_ttl :			       inet->uc_ttl);			break;		case IP_HDRINCL:			val = inet->hdrincl;			break;		case IP_MTU_DISCOVER:			val = inet->pmtudisc;			break;		case IP_MTU:		{			struct dst_entry *dst;			val = 0;			dst = sk_dst_get(sk);			if (dst) {				val = dst_pmtu(dst) - dst->header_len;				dst_release(dst);			}			if (!val) {				release_sock(sk);				return -ENOTCONN;			}			break;		}		case IP_RECVERR:			val = inet->recverr;			break;		case IP_MULTICAST_TTL:			val = inet->mc_ttl;			break;		case IP_MULTICAST_LOOP:			val = inet->mc_loop;			break;		case IP_MULTICAST_IF:		{			struct in_addr addr;			len = min_t(unsigned int, len, sizeof(struct in_addr));			addr.s_addr = inet->mc_addr;			release_sock(sk);  			if(put_user(len, optlen))  				return -EFAULT;			if(copy_to_user(optval, &addr, len))				return -EFAULT;			return 0;		}		case IP_MSFILTER:		{			struct ip_msfilter msf;			int err;			if (len < IP_MSFILTER_SIZE(0)) {				release_sock(sk);				return -EINVAL;			}			if (copy_from_user(&msf, optval, IP_MSFILTER_SIZE(0))) {				release_sock(sk);				return -EFAULT;			}			err = ip_mc_msfget(sk, &msf,				(struct ip_msfilter __user *)optval, optlen);			release_sock(sk);			return err;		}		case MCAST_MSFILTER:		{			struct group_filter gsf;			int err;			if (len < GROUP_FILTER_SIZE(0)) {				release_sock(sk);				return -EINVAL;			}			if (copy_from_user(&gsf, optval, GROUP_FILTER_SIZE(0))) {				release_sock(sk);				return -EFAULT;			}			err = ip_mc_gsfget(sk, &gsf,				(struct group_filter __user *)optval, optlen);			release_sock(sk);			return err;		}		case IP_PKTOPTIONS:				{			struct msghdr msg;			release_sock(sk);			if (sk->sk_type != SOCK_STREAM)				return -ENOPROTOOPT;			msg.msg_control = optval;			msg.msg_controllen = len;			msg.msg_flags = 0;			if (inet->cmsg_flags & IP_CMSG_PKTINFO) {				struct in_pktinfo info;				info.ipi_addr.s_addr = inet->rcv_saddr;				info.ipi_spec_dst.s_addr = inet->rcv_saddr;				info.ipi_ifindex = inet->mc_index;				put_cmsg(&msg, SOL_IP, IP_PKTINFO, sizeof(info), &info);			}			if (inet->cmsg_flags & IP_CMSG_TTL) {				int hlim = inet->mc_ttl;				put_cmsg(&msg, SOL_IP, IP_TTL, sizeof(hlim), &hlim);			}			len -= msg.msg_controllen;			return put_user(len, optlen);		}		case IP_FREEBIND: 			val = inet->freebind; 			break; 		default:#ifdef CONFIG_NETFILTER			val = nf_getsockopt(sk, PF_INET, optname, optval, 					    &len);			release_sock(sk);			if (val >= 0)				val = put_user(len, optlen);			return val;#else			release_sock(sk);			return -ENOPROTOOPT;#endif	}	release_sock(sk);		if (len < sizeof(int) && len > 0 && val>=0 && val<255) {		unsigned char ucval = (unsigned char)val;		len = 1;		if(put_user(len, optlen))			return -EFAULT;		if(copy_to_user(optval,&ucval,1))			return -EFAULT;	} else {		len = min_t(unsigned int, sizeof(int), len);		if(put_user(len, optlen))			return -EFAULT;		if(copy_to_user(optval,&val,len))			return -EFAULT;	}	return 0;}EXPORT_SYMBOL(ip_cmsg_recv);#ifdef CONFIG_IP_SCTP_MODULEEXPORT_SYMBOL(ip_getsockopt);EXPORT_SYMBOL(ip_setsockopt);#endif

⌨️ 快捷键说明

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