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

📄 ip_sockglue.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 2 页
字号:
	/* If optlen==0, it is equivalent to val == 0 */#ifdef CONFIG_IP_MROUTE	if (optname >= MRT_BASE && optname <= (MRT_BASE + 10))		return ip_mroute_setsockopt(sk,optname,optval,optlen);#endif	err = 0;	lock_sock(sk);	switch (optname) {		case IP_OPTIONS:		{			struct ip_options * opt = NULL;			if (optlen > 40 || optlen < 0)				goto e_inval;			err = ip_options_get(&opt, optval, optlen, 1);			if (err)				break;			if (sk->type == SOCK_STREAM) {				struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)				if (sk->family == PF_INET ||				    (!((1<<sk->state)&(TCPF_LISTEN|TCPF_CLOSE))				     && sk->daddr != LOOPBACK4_IPV6)) {#endif					if (opt)						tp->ext_header_len = opt->optlen;					tcp_sync_mss(sk, tp->pmtu_cookie);#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)				}#endif			}			opt = xchg(&sk->protinfo.af_inet.opt, opt);			if (opt)				kfree(opt);			break;		}		case IP_PKTINFO:			if (val)				sk->protinfo.af_inet.cmsg_flags |= IP_CMSG_PKTINFO;			else				sk->protinfo.af_inet.cmsg_flags &= ~IP_CMSG_PKTINFO;			break;		case IP_RECVTTL:			if (val)				sk->protinfo.af_inet.cmsg_flags |=  IP_CMSG_TTL;			else				sk->protinfo.af_inet.cmsg_flags &= ~IP_CMSG_TTL;			break;		case IP_RECVTOS:			if (val)				sk->protinfo.af_inet.cmsg_flags |=  IP_CMSG_TOS;			else				sk->protinfo.af_inet.cmsg_flags &= ~IP_CMSG_TOS;			break;		case IP_RECVOPTS:			if (val)				sk->protinfo.af_inet.cmsg_flags |=  IP_CMSG_RECVOPTS;			else				sk->protinfo.af_inet.cmsg_flags &= ~IP_CMSG_RECVOPTS;			break;		case IP_RETOPTS:			if (val)				sk->protinfo.af_inet.cmsg_flags |= IP_CMSG_RETOPTS;			else				sk->protinfo.af_inet.cmsg_flags &= ~IP_CMSG_RETOPTS;			break;		case IP_TOS:	/* This sets both TOS and Precedence */			if (sk->type == SOCK_STREAM) {				val &= ~3;				val |= sk->protinfo.af_inet.tos & 3;			}			if (IPTOS_PREC(val) >= IPTOS_PREC_CRITIC_ECP && 			    !capable(CAP_NET_ADMIN)) {				err = -EPERM;				break;			}			if (sk->protinfo.af_inet.tos != val) {				sk->protinfo.af_inet.tos=val;				sk->priority = rt_tos2priority(val);				sk_dst_reset(sk); 			}			break;		case IP_TTL:			if (optlen<1)				goto e_inval;			if(val==-1)				val = sysctl_ip_default_ttl;			if(val<1||val>255)				goto e_inval;			sk->protinfo.af_inet.ttl=val;			break;		case IP_HDRINCL:			if(sk->type!=SOCK_RAW) {				err = -ENOPROTOOPT;				break;			}			sk->protinfo.af_inet.hdrincl=val?1:0;			break;		case IP_MTU_DISCOVER:			if (val<0 || val>2)				goto e_inval;			sk->protinfo.af_inet.pmtudisc = val;			break;		case IP_RECVERR:			sk->protinfo.af_inet.recverr = !!val;			if (!val)				skb_queue_purge(&sk->error_queue);			break;		case IP_MULTICAST_TTL:			if (sk->type == SOCK_STREAM)				goto e_inval;			if (optlen<1)				goto e_inval;			if (val==-1)				val = 1;			if (val < 0 || val > 255)				goto e_inval;			sk->protinfo.af_inet.mc_ttl=val;	                break;		case IP_MULTICAST_LOOP: 			if (optlen<1)				goto e_inval;			sk->protinfo.af_inet.mc_loop = val ? 1 : 0;	                break;		case IP_MULTICAST_IF: 		{			struct ip_mreqn mreq;			struct net_device *dev = NULL;			if (sk->type == SOCK_STREAM)				goto e_inval;			/*			 *	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) {					sk->protinfo.af_inet.mc_index = 0;					sk->protinfo.af_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->bound_dev_if && mreq.imr_ifindex != sk->bound_dev_if)				break;			sk->protinfo.af_inet.mc_index = mreq.imr_ifindex;			sk->protinfo.af_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_ROUTER_ALERT:				err = ip_ra_control(sk, val ? 1 : 0, NULL);			break;		case IP_FREEBIND:			if (optlen<1)				goto e_inval;			sk->protinfo.af_inet.freebind = !!val; 	                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 *optval, int *optlen){	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 (sk->protinfo.af_inet.opt)					memcpy(optbuf, sk->protinfo.af_inet.opt,					       sizeof(struct ip_options)+					       sk->protinfo.af_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 = (sk->protinfo.af_inet.cmsg_flags & IP_CMSG_PKTINFO) != 0;			break;		case IP_RECVTTL:			val = (sk->protinfo.af_inet.cmsg_flags & IP_CMSG_TTL) != 0;			break;		case IP_RECVTOS:			val = (sk->protinfo.af_inet.cmsg_flags & IP_CMSG_TOS) != 0;			break;		case IP_RECVOPTS:			val = (sk->protinfo.af_inet.cmsg_flags & IP_CMSG_RECVOPTS) != 0;			break;		case IP_RETOPTS:			val = (sk->protinfo.af_inet.cmsg_flags & IP_CMSG_RETOPTS) != 0;			break;		case IP_TOS:			val=sk->protinfo.af_inet.tos;			break;		case IP_TTL:			val=sk->protinfo.af_inet.ttl;			break;		case IP_HDRINCL:			val=sk->protinfo.af_inet.hdrincl;			break;		case IP_MTU_DISCOVER:			val=sk->protinfo.af_inet.pmtudisc;			break;		case IP_MTU:		{			struct dst_entry *dst;			val = 0;			dst = sk_dst_get(sk);			if (dst) {				val = dst->pmtu;				dst_release(dst);			}			if (!val) {				release_sock(sk);				return -ENOTCONN;			}			break;		}		case IP_RECVERR:			val=sk->protinfo.af_inet.recverr;			break;		case IP_MULTICAST_TTL:			val=sk->protinfo.af_inet.mc_ttl;			break;		case IP_MULTICAST_LOOP:			val=sk->protinfo.af_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 = sk->protinfo.af_inet.mc_addr;			release_sock(sk);  			if(put_user(len, optlen))  				return -EFAULT;			if(copy_to_user((void *)optval, &addr, len))				return -EFAULT;			return 0;		}		case IP_PKTOPTIONS:				{			struct msghdr msg;			release_sock(sk);			if (sk->type != SOCK_STREAM)				return -ENOPROTOOPT;			msg.msg_control = optval;			msg.msg_controllen = len;			msg.msg_flags = 0;			if (sk->protinfo.af_inet.cmsg_flags&IP_CMSG_PKTINFO) {				struct in_pktinfo info;				info.ipi_addr.s_addr = sk->rcv_saddr;				info.ipi_spec_dst.s_addr = sk->rcv_saddr;				info.ipi_ifindex = sk->protinfo.af_inet.mc_index;				put_cmsg(&msg, SOL_IP, IP_PKTINFO, sizeof(info), &info);			}			if (sk->protinfo.af_inet.cmsg_flags&IP_CMSG_TTL) {				int hlim = sk->protinfo.af_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 = sk->protinfo.af_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;}

⌨️ 快捷键说明

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