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

📄 ip_sockglue.c

📁 GNU Hurd 源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
 * *	We implement IP_TOS (type of service), IP_TTL (time to live). */int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int optlen){	int val=0,err;#if defined(CONFIG_IP_FIREWALL)	char tmp_fw[MAX(sizeof(struct ip_fwtest),sizeof(struct ip_fwnew))];#endif	if(optlen>=sizeof(int)) {		if(get_user(val, (int *) optval))			return -EFAULT;	} else if(optlen>=sizeof(char)) {		unsigned char ucval;		if(get_user(ucval, (unsigned char *) optval))			return -EFAULT;		val = (int)ucval;	}	/* If optlen==0, it is equivalent to val == 0 */		if(level!=SOL_IP)		return -ENOPROTOOPT;#ifdef CONFIG_IP_MROUTE	if(optname>=MRT_BASE && optname <=MRT_BASE+10)	{		return ip_mroute_setsockopt(sk,optname,optval,optlen);	}#endif		switch(optname)	{		case IP_OPTIONS:		{			struct ip_options * opt = NULL;			if (optlen > 40 || optlen < 0)				return -EINVAL;			err = ip_options_get(&opt, optval, optlen, 1);			if (err)				return err;			lock_sock(sk);			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 ||				    ((tcp_connected(sk->state) || sk->state == TCP_SYN_SENT)				     && 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->opt, opt);			release_sock(sk);			if (opt)				kfree_s(opt, sizeof(struct ip_options) + opt->optlen);			return 0;		}		case IP_PKTINFO:			if (val)				sk->ip_cmsg_flags |= IP_CMSG_PKTINFO;			else				sk->ip_cmsg_flags &= ~IP_CMSG_PKTINFO;			return 0;		case IP_RECVTTL:			if (val)				sk->ip_cmsg_flags |=  IP_CMSG_TTL;			else				sk->ip_cmsg_flags &= ~IP_CMSG_TTL;			return 0;		case IP_RECVTOS:			if (val)				sk->ip_cmsg_flags |=  IP_CMSG_TOS;			else				sk->ip_cmsg_flags &= ~IP_CMSG_TOS;			return 0;		case IP_RECVOPTS:			if (val)				sk->ip_cmsg_flags |=  IP_CMSG_RECVOPTS;			else				sk->ip_cmsg_flags &= ~IP_CMSG_RECVOPTS;			return 0;		case IP_RETOPTS:			if (val)				sk->ip_cmsg_flags |= IP_CMSG_RETOPTS;			else				sk->ip_cmsg_flags &= ~IP_CMSG_RETOPTS;			return 0;		case IP_TOS:	/* This sets both TOS and Precedence */			  /* Reject setting of unused bits */			if (val & ~(IPTOS_TOS_MASK|IPTOS_PREC_MASK))				return -EINVAL;			if (IPTOS_PREC(val) >= IPTOS_PREC_CRITIC_ECP && 			    !capable(CAP_NET_ADMIN))				return -EPERM;			if (sk->ip_tos != val) {				lock_sock(sk);				sk->ip_tos=val;				sk->priority = rt_tos2priority(val);				dst_release(xchg(&sk->dst_cache, NULL)); 				release_sock(sk);			}			return 0;		case IP_TTL:			if (optlen<1)				return -EINVAL;			if(val==-1)				val = ip_statistics.IpDefaultTTL;			if(val<1||val>255)				return -EINVAL;			sk->ip_ttl=val;			return 0;		case IP_HDRINCL:			if(sk->type!=SOCK_RAW)				return -ENOPROTOOPT;			sk->ip_hdrincl=val?1:0;			return 0;		case IP_MTU_DISCOVER:			if (val<0 || val>2)				return -EINVAL;			sk->ip_pmtudisc = val;			return 0;		case IP_RECVERR:			sk->ip_recverr = !!val;			if (!val)				skb_queue_purge(&sk->error_queue);			return 0;		case IP_MULTICAST_TTL: 			if (optlen<1)				return -EINVAL;			if (val==-1)				val = 1;			if (val < 0 || val > 255)				return -EINVAL;			sk->ip_mc_ttl=val;	                return 0;		case IP_MULTICAST_LOOP: 			if (optlen<1)				return -EINVAL;			sk->ip_mc_loop = val ? 1 : 0;			return 0;		case IP_MULTICAST_IF: 		{			struct ip_mreqn mreq;			struct device *dev = NULL;						/*			 *	Check the arguments are allowable			 */			if (optlen >= sizeof(struct ip_mreqn)) {				if (copy_from_user(&mreq,optval,sizeof(mreq)))					return -EFAULT;			} else {				memset(&mreq, 0, sizeof(mreq));				if (optlen >= sizeof(struct in_addr) &&				    copy_from_user(&mreq.imr_address,optval,sizeof(struct in_addr)))					return -EFAULT;			}			if (!mreq.imr_ifindex) {				if (mreq.imr_address.s_addr == INADDR_ANY) {					sk->ip_mc_index = 0;					sk->ip_mc_addr  = 0;					return 0;				}				dev = ip_dev_find(mreq.imr_address.s_addr);			} else				dev = dev_get_by_index(mreq.imr_ifindex);			if (!dev)				return -EADDRNOTAVAIL;			if (sk->bound_dev_if && dev->ifindex != sk->bound_dev_if)				return -EINVAL;			sk->ip_mc_index = mreq.imr_ifindex;			sk->ip_mc_addr  = mreq.imr_address.s_addr;			return 0;		}		case IP_ADD_MEMBERSHIP:		case IP_DROP_MEMBERSHIP: 		{			struct ip_mreqn mreq;						if (optlen < sizeof(struct ip_mreq))				return -EINVAL;			if (optlen >= sizeof(struct ip_mreqn)) {				if(copy_from_user(&mreq,optval,sizeof(mreq)))					return -EFAULT;			} else {				memset(&mreq, 0, sizeof(mreq));				if (copy_from_user(&mreq,optval,sizeof(struct ip_mreq)))					return -EFAULT; 			}			if (optname == IP_ADD_MEMBERSHIP)				return ip_mc_join_group(sk,&mreq);			else				return ip_mc_leave_group(sk,&mreq);		}		case IP_ROUTER_ALERT:				return ip_ra_control(sk, val ? 1 : 0, NULL);		#ifdef CONFIG_IP_FIREWALL		case IP_FW_MASQ_TIMEOUTS:		case IP_FW_APPEND:		case IP_FW_REPLACE:		case IP_FW_DELETE:		case IP_FW_DELETE_NUM:		case IP_FW_INSERT:		case IP_FW_FLUSH:		case IP_FW_ZERO:		case IP_FW_CHECK:		case IP_FW_CREATECHAIN:		case IP_FW_DELETECHAIN:		case IP_FW_POLICY:			if(!capable(CAP_NET_ADMIN))				return -EACCES;			if(optlen>sizeof(tmp_fw) || optlen<1)				return -EINVAL;			if(copy_from_user(&tmp_fw,optval,optlen))				return -EFAULT;			err=ip_fw_ctl(optname, &tmp_fw,optlen);			return -err;	/* -0 is 0 after all */#endif /* CONFIG_IP_FIREWALL */#ifdef CONFIG_IP_MASQUERADE		case IP_FW_MASQ_CTL:			if(!capable(CAP_NET_ADMIN))				return -EPERM;			if(optlen<1)				return -EINVAL;			err=ip_masq_uctl(optname, optval ,optlen);			return err;			#endif		default:			return(-ENOPROTOOPT);	}}/* *	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;	switch(optname)	{		case IP_OPTIONS:			{				unsigned char optbuf[sizeof(struct ip_options)+40];				struct ip_options * opt = (struct ip_options*)optbuf;				lock_sock(sk);				opt->optlen = 0;				if (sk->opt)					memcpy(optbuf, sk->opt, sizeof(struct ip_options)+sk->opt->optlen);				release_sock(sk);				if (opt->optlen == 0) 					return put_user(0, optlen);				ip_options_undo(opt);				len=min(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->ip_cmsg_flags & IP_CMSG_PKTINFO) != 0;			break;		case IP_RECVTTL:			val = (sk->ip_cmsg_flags & IP_CMSG_TTL) != 0;			break;		case IP_RECVTOS:			val = (sk->ip_cmsg_flags & IP_CMSG_TOS) != 0;			break;		case IP_RECVOPTS:			val = (sk->ip_cmsg_flags & IP_CMSG_RECVOPTS) != 0;			break;		case IP_RETOPTS:			val = (sk->ip_cmsg_flags & IP_CMSG_RETOPTS) != 0;			break;		case IP_TOS:			val=sk->ip_tos;			break;		case IP_TTL:			val=sk->ip_ttl;			break;		case IP_HDRINCL:			val=sk->ip_hdrincl;			break;		case IP_MTU_DISCOVER:			val=sk->ip_pmtudisc;			break;		case IP_MTU:			val = 0;				lock_sock(sk);			if (sk->dst_cache)						val = sk->dst_cache->pmtu;			release_sock(sk);			if (!val)				return -ENOTCONN;			break;		case IP_RECVERR:			val=sk->ip_recverr;			break;		case IP_MULTICAST_TTL:			val=sk->ip_mc_ttl;			break;		case IP_MULTICAST_LOOP:			val=sk->ip_mc_loop;			break;		case IP_MULTICAST_IF:		{			struct ip_mreqn mreq;			len = min(len,sizeof(struct ip_mreqn));  			if(put_user(len, optlen))  				return -EFAULT;			mreq.imr_ifindex = sk->ip_mc_index;			mreq.imr_address.s_addr = sk->ip_mc_addr;			mreq.imr_multiaddr.s_addr = 0;			if(copy_to_user((void *)optval, &mreq, len))				return -EFAULT;			return 0;		}		default:			return(-ENOPROTOOPT);	}		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(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 + -