if (msf) kfree(msf); if (gsf) kfree(gsf); 
kfree(msf); kfree(gsf); 
int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen){	struct inet_sock *inet = inet_sk(sk);	int val=0,err;	if (level != SOL_IP)		return -ENOPROTOOPT;	if (((1<<optname) & ((1<<IP_PKTINFO) | (1<<IP_RECVTTL) | 			    (1<<IP_RECVOPTS) | (1<<IP_RECVTOS) | 			    (1<<IP_RETOPTS) | (1<<IP_TOS) | 			    (1<<IP_TTL) | (1<<IP_HDRINCL) | 			    (1<<IP_MTU_DISCOVER) | (1<<IP_RECVERR) | 			    (1<<IP_ROUTER_ALERT) | (1<<IP_FREEBIND))) || 				optname == IP_MULTICAST_TTL || 				optname == IP_MULTICAST_LOOP) { 		if (optlen >= sizeof(int)) {			if (get_user(val, (int __user *) optval))				return -EFAULT;		} else if (optlen >= sizeof(char)) {			unsigned char ucval;			if (get_user(ucval, (unsigned char __user *) optval))				return -EFAULT;			val = (int) ucval;		}	}	/* 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_from_user(&opt, optval, optlen);			if (err)				break;			if (sk->sk_type == SOCK_STREAM) {				struct tcp_sock *tp = tcp_sk(sk);#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)				if (sk->sk_family == PF_INET ||				    (!((1 << sk->sk_state) &				       (TCPF_LISTEN | TCPF_CLOSE)) &&				     inet->daddr != LOOPBACK4_IPV6)) {#endif					if (inet->opt)						tp->ext_header_len -= inet->opt->optlen;					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(&inet->opt, opt);			if (opt)				kfree(opt);			break;		}		case IP_PKTINFO:			if (val)				inet->cmsg_flags |= IP_CMSG_PKTINFO;			else				inet->cmsg_flags &= ~IP_CMSG_PKTINFO;			break;		case IP_RECVTTL:			if (val)				inet->cmsg_flags |=  IP_CMSG_TTL;			else				inet->cmsg_flags &= ~IP_CMSG_TTL;			break;		case IP_RECVTOS:			if (val)				inet->cmsg_flags |=  IP_CMSG_TOS;			else				inet->cmsg_flags &= ~IP_CMSG_TOS;			break;		case IP_RECVOPTS:			if (val)				inet->cmsg_flags |=  IP_CMSG_RECVOPTS;			else				inet->cmsg_flags &= ~IP_CMSG_RECVOPTS;			break;		case IP_RETOPTS:			if (val)				inet->cmsg_flags |= IP_CMSG_RETOPTS;			else				inet->cmsg_flags &= ~IP_CMSG_RETOPTS;			break;		case IP_TOS:	/* This sets both TOS and Precedence */			if (sk->sk_type == SOCK_STREAM) {				val &= ~3;				val |= inet->tos & 3;			}			if (IPTOS_PREC(val) >= IPTOS_PREC_CRITIC_ECP && 			    !capable(CAP_NET_ADMIN)) {				err = -EPERM;				break;			}			if (inet->tos != val) {				inet->tos = val;				sk->sk_priority = rt_tos2priority(val);				sk_dst_reset(sk); 			}			break;		case IP_TTL:			if (optlen<1)				goto e_inval;			if (val != -1 && (val < 1 || val>255))				goto e_inval;			inet->uc_ttl = val;			break;		case IP_HDRINCL:			if (sk->sk_type != SOCK_RAW) {				err = -ENOPROTOOPT;				break;			}			inet->hdrincl = val ? 1 : 0;			break;		case IP_MTU_DISCOVER:			if (val<0 || val>2)				goto e_inval;			inet->pmtudisc = val;			break;		case IP_RECVERR:			inet->recverr = !!val;			if (!val)				skb_queue_purge(&sk->sk_error_queue);			break;		case IP_MULTICAST_TTL:			if (sk->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;			inet->mc_ttl = val;	                break;		case IP_MULTICAST_LOOP: 			if (optlen<1)				goto e_inval;			inet->mc_loop = !!val;	                break;		case IP_MULTICAST_IF: 		{			struct ip_mreqn mreq;			struct net_device *dev = NULL;			if (sk->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) {					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_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 && err != -EADDRINUSE)					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 && err != -EADDRINUSE)					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_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 = -EPERM;			if (!capable(CAP_NET_ADMIN))				break;			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;}
4520	/local/tlutelli/issta_data/temp/c/2005_temp/2005/4520/a51482bde22f99c63fbbb57d5d46cc666384e379/ip_sockglue.c/clean/net/ipv4/ip_sockglue.c