diff options
Diffstat (limited to 'net/ipv6/raw.c')
| -rw-r--r-- | net/ipv6/raw.c | 53 | 
1 files changed, 24 insertions, 29 deletions
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 58916bbb172..b2dc60b0c76 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -77,20 +77,19 @@ static struct sock *__raw_v6_lookup(struct net *net, struct sock *sk,  	sk_for_each_from(sk)  		if (inet_sk(sk)->inet_num == num) { -			struct ipv6_pinfo *np = inet6_sk(sk);  			if (!net_eq(sock_net(sk), net))  				continue; -			if (!ipv6_addr_any(&np->daddr) && -			    !ipv6_addr_equal(&np->daddr, rmt_addr)) +			if (!ipv6_addr_any(&sk->sk_v6_daddr) && +			    !ipv6_addr_equal(&sk->sk_v6_daddr, rmt_addr))  				continue;  			if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif)  				continue; -			if (!ipv6_addr_any(&np->rcv_saddr)) { -				if (ipv6_addr_equal(&np->rcv_saddr, loc_addr)) +			if (!ipv6_addr_any(&sk->sk_v6_rcv_saddr)) { +				if (ipv6_addr_equal(&sk->sk_v6_rcv_saddr, loc_addr))  					goto found;  				if (is_multicast &&  				    inet6_mc_check(sk, loc_addr, rmt_addr)) @@ -251,6 +250,10 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)  	if (addr_len < SIN6_LEN_RFC2133)  		return -EINVAL; + +	if (addr->sin6_family != AF_INET6) +		return -EINVAL; +  	addr_type = ipv6_addr_type(&addr->sin6_addr);  	/* Raw sockets are IPv6 only */ @@ -302,7 +305,7 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)  	}  	inet->inet_rcv_saddr = inet->inet_saddr = v4addr; -	np->rcv_saddr = addr->sin6_addr; +	sk->sk_v6_rcv_saddr = addr->sin6_addr;  	if (!(addr_type & IPV6_ADDR_MULTICAST))  		np->saddr = addr->sin6_addr;  	err = 0; @@ -335,8 +338,10 @@ static void rawv6_err(struct sock *sk, struct sk_buff *skb,  		ip6_sk_update_pmtu(skb, sk, info);  		harderr = (np->pmtudisc == IPV6_PMTUDISC_DO);  	} -	if (type == NDISC_REDIRECT) +	if (type == NDISC_REDIRECT) {  		ip6_sk_redirect(skb, sk); +		return; +	}  	if (np->recverr) {  		u8 *payload = skb->data;  		if (!inet->hdrincl) @@ -456,7 +461,7 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk,  		  int noblock, int flags, int *addr_len)  {  	struct ipv6_pinfo *np = inet6_sk(sk); -	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)msg->msg_name; +	DECLARE_SOCKADDR(struct sockaddr_in6 *, sin6, msg->msg_name);  	struct sk_buff *skb;  	size_t copied;  	int err; @@ -464,14 +469,11 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk,  	if (flags & MSG_OOB)  		return -EOPNOTSUPP; -	if (addr_len) -		*addr_len=sizeof(*sin6); -  	if (flags & MSG_ERRQUEUE) -		return ipv6_recv_error(sk, msg, len); +		return ipv6_recv_error(sk, msg, len, addr_len);  	if (np->rxpmtu && np->rxopt.bits.rxpmtu) -		return ipv6_recv_rxpmtu(sk, msg, len); +		return ipv6_recv_rxpmtu(sk, msg, len, addr_len);  	skb = skb_recv_datagram(sk, flags, noblock, &err);  	if (!skb) @@ -505,6 +507,7 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk,  		sin6->sin6_flowinfo = 0;  		sin6->sin6_scope_id = ipv6_iface_scope_id(&sin6->sin6_addr,  							  IP6CB(skb)->iif); +		*addr_len = sizeof(*sin6);  	}  	sock_recv_ts_and_drops(msg, sk, skb); @@ -735,7 +738,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,  		   struct msghdr *msg, size_t len)  {  	struct ipv6_txoptions opt_space; -	struct sockaddr_in6 * sin6 = (struct sockaddr_in6 *) msg->msg_name; +	DECLARE_SOCKADDR(struct sockaddr_in6 *, sin6, msg->msg_name);  	struct in6_addr *daddr, *final_p, final;  	struct inet_sock *inet = inet_sk(sk);  	struct ipv6_pinfo *np = inet6_sk(sk); @@ -793,7 +796,6 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,  				flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);  				if (flowlabel == NULL)  					return -EINVAL; -				daddr = &flowlabel->dst;  			}  		} @@ -802,8 +804,8 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,  		 * sk->sk_dst_cache.  		 */  		if (sk->sk_state == TCP_ESTABLISHED && -		    ipv6_addr_equal(daddr, &np->daddr)) -			daddr = &np->daddr; +		    ipv6_addr_equal(daddr, &sk->sk_v6_daddr)) +			daddr = &sk->sk_v6_daddr;  		if (addr_len >= sizeof(struct sockaddr_in6) &&  		    sin6->sin6_scope_id && @@ -814,7 +816,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,  			return -EDESTADDRREQ;  		proto = inet->inet_num; -		daddr = &np->daddr; +		daddr = &sk->sk_v6_daddr;  		fl6.flowlabel = np->flow_label;  	} @@ -866,19 +868,13 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,  		fl6.flowi6_oif = np->ucast_oif;  	security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); -	dst = ip6_dst_lookup_flow(sk, &fl6, final_p, true); +	dst = ip6_dst_lookup_flow(sk, &fl6, final_p);  	if (IS_ERR(dst)) {  		err = PTR_ERR(dst);  		goto out;  	} -	if (hlimit < 0) { -		if (ipv6_addr_is_multicast(&fl6.daddr)) -			hlimit = np->mcast_hops; -		else -			hlimit = np->hop_limit; -		if (hlimit < 0) -			hlimit = ip6_dst_hoplimit(dst); -	} +	if (hlimit < 0) +		hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst);  	if (tclass < 0)  		tclass = np->tclass; @@ -1211,7 +1207,7 @@ struct proto rawv6_prot = {  	.owner		   = THIS_MODULE,  	.close		   = rawv6_close,  	.destroy	   = raw6_destroy, -	.connect	   = ip6_datagram_connect, +	.connect	   = ip6_datagram_connect_v6_only,  	.disconnect	   = udp_disconnect,  	.ioctl		   = rawv6_ioctl,  	.init		   = rawv6_init_sk, @@ -1326,7 +1322,6 @@ static struct inet_protosw rawv6_protosw = {  	.protocol	= IPPROTO_IP,	/* wild card */  	.prot		= &rawv6_prot,  	.ops		= &inet6_sockraw_ops, -	.no_check	= UDP_CSUM_DEFAULT,  	.flags		= INET_PROTOSW_REUSE,  };  | 
