diff options
Diffstat (limited to 'net/ipv6')
| -rw-r--r-- | net/ipv6/addrconf.c | 1 | ||||
| -rw-r--r-- | net/ipv6/datagram.c | 16 | ||||
| -rw-r--r-- | net/ipv6/ip6_flowlabel.c | 4 | ||||
| -rw-r--r-- | net/ipv6/ip6_gre.c | 2 | ||||
| -rw-r--r-- | net/ipv6/ipv6_sockglue.c | 6 | ||||
| -rw-r--r-- | net/ipv6/netfilter/ip6t_NPT.c | 18 | ||||
| -rw-r--r-- | net/ipv6/raw.c | 6 | ||||
| -rw-r--r-- | net/ipv6/route.c | 2 | ||||
| -rw-r--r-- | net/ipv6/tcp_ipv6.c | 6 | ||||
| -rw-r--r-- | net/ipv6/udp.c | 6 | 
10 files changed, 42 insertions, 25 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 420e5632638..1b5d8cb9b12 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -1660,6 +1660,7 @@ static int addrconf_ifid_eui64(u8 *eui, struct net_device *dev)  	if (dev->addr_len != IEEE802154_ADDR_LEN)  		return -1;  	memcpy(eui, dev->dev_addr, 8); +	eui[0] ^= 2;  	return 0;  } diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 8edf2601065..7a778b9a7b8 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c @@ -380,7 +380,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)  		if (skb->protocol == htons(ETH_P_IPV6)) {  			sin->sin6_addr = ipv6_hdr(skb)->saddr;  			if (np->rxopt.all) -				datagram_recv_ctl(sk, msg, skb); +				ip6_datagram_recv_ctl(sk, msg, skb);  			if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL)  				sin->sin6_scope_id = IP6CB(skb)->iif;  		} else { @@ -468,7 +468,8 @@ out:  } -int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) +int ip6_datagram_recv_ctl(struct sock *sk, struct msghdr *msg, +			  struct sk_buff *skb)  {  	struct ipv6_pinfo *np = inet6_sk(sk);  	struct inet6_skb_parm *opt = IP6CB(skb); @@ -597,11 +598,12 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)  	}  	return 0;  } +EXPORT_SYMBOL_GPL(ip6_datagram_recv_ctl); -int datagram_send_ctl(struct net *net, struct sock *sk, -		      struct msghdr *msg, struct flowi6 *fl6, -		      struct ipv6_txoptions *opt, -		      int *hlimit, int *tclass, int *dontfrag) +int ip6_datagram_send_ctl(struct net *net, struct sock *sk, +			  struct msghdr *msg, struct flowi6 *fl6, +			  struct ipv6_txoptions *opt, +			  int *hlimit, int *tclass, int *dontfrag)  {  	struct in6_pktinfo *src_info;  	struct cmsghdr *cmsg; @@ -871,4 +873,4 @@ int datagram_send_ctl(struct net *net, struct sock *sk,  exit_f:  	return err;  } -EXPORT_SYMBOL_GPL(datagram_send_ctl); +EXPORT_SYMBOL_GPL(ip6_datagram_send_ctl); diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index 29124b7a04c..d6de4b44725 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c @@ -365,8 +365,8 @@ fl_create(struct net *net, struct sock *sk, struct in6_flowlabel_req *freq,  		msg.msg_control = (void*)(fl->opt+1);  		memset(&flowi6, 0, sizeof(flowi6)); -		err = datagram_send_ctl(net, sk, &msg, &flowi6, fl->opt, &junk, -					&junk, &junk); +		err = ip6_datagram_send_ctl(net, sk, &msg, &flowi6, fl->opt, +					    &junk, &junk, &junk);  		if (err)  			goto done;  		err = -EINVAL; diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index c727e471275..131dd097736 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c @@ -960,7 +960,7 @@ static netdev_tx_t ip6gre_tunnel_xmit(struct sk_buff *skb,  	int ret;  	if (!ip6_tnl_xmit_ctl(t)) -		return -1; +		goto tx_err;  	switch (skb->protocol) {  	case htons(ETH_P_IP): diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index ee94d31c9d4..d1e2e8ef29c 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -476,8 +476,8 @@ sticky_done:  		msg.msg_controllen = optlen;  		msg.msg_control = (void*)(opt+1); -		retv = datagram_send_ctl(net, sk, &msg, &fl6, opt, &junk, &junk, -					 &junk); +		retv = ip6_datagram_send_ctl(net, sk, &msg, &fl6, opt, &junk, +					     &junk, &junk);  		if (retv)  			goto done;  update: @@ -1002,7 +1002,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,  		release_sock(sk);  		if (skb) { -			int err = datagram_recv_ctl(sk, &msg, skb); +			int err = ip6_datagram_recv_ctl(sk, &msg, skb);  			kfree_skb(skb);  			if (err)  				return err; diff --git a/net/ipv6/netfilter/ip6t_NPT.c b/net/ipv6/netfilter/ip6t_NPT.c index 7302b0b7b64..83acc1405a1 100644 --- a/net/ipv6/netfilter/ip6t_NPT.c +++ b/net/ipv6/netfilter/ip6t_NPT.c @@ -9,6 +9,7 @@  #include <linux/module.h>  #include <linux/skbuff.h>  #include <linux/ipv6.h> +#include <net/ipv6.h>  #include <linux/netfilter.h>  #include <linux/netfilter_ipv6.h>  #include <linux/netfilter_ipv6/ip6t_NPT.h> @@ -18,11 +19,20 @@ static int ip6t_npt_checkentry(const struct xt_tgchk_param *par)  {  	struct ip6t_npt_tginfo *npt = par->targinfo;  	__wsum src_sum = 0, dst_sum = 0; +	struct in6_addr pfx;  	unsigned int i;  	if (npt->src_pfx_len > 64 || npt->dst_pfx_len > 64)  		return -EINVAL; +	/* Ensure that LSB of prefix is zero */ +	ipv6_addr_prefix(&pfx, &npt->src_pfx.in6, npt->src_pfx_len); +	if (!ipv6_addr_equal(&pfx, &npt->src_pfx.in6)) +		return -EINVAL; +	ipv6_addr_prefix(&pfx, &npt->dst_pfx.in6, npt->dst_pfx_len); +	if (!ipv6_addr_equal(&pfx, &npt->dst_pfx.in6)) +		return -EINVAL; +  	for (i = 0; i < ARRAY_SIZE(npt->src_pfx.in6.s6_addr16); i++) {  		src_sum = csum_add(src_sum,  				(__force __wsum)npt->src_pfx.in6.s6_addr16[i]); @@ -30,7 +40,7 @@ static int ip6t_npt_checkentry(const struct xt_tgchk_param *par)  				(__force __wsum)npt->dst_pfx.in6.s6_addr16[i]);  	} -	npt->adjustment = (__force __sum16) csum_sub(src_sum, dst_sum); +	npt->adjustment = ~csum_fold(csum_sub(src_sum, dst_sum));  	return 0;  } @@ -51,7 +61,7 @@ static bool ip6t_npt_map_pfx(const struct ip6t_npt_tginfo *npt,  		idx = i / 32;  		addr->s6_addr32[idx] &= mask; -		addr->s6_addr32[idx] |= npt->dst_pfx.in6.s6_addr32[idx]; +		addr->s6_addr32[idx] |= ~mask & npt->dst_pfx.in6.s6_addr32[idx];  	}  	if (pfx_len <= 48) @@ -66,8 +76,8 @@ static bool ip6t_npt_map_pfx(const struct ip6t_npt_tginfo *npt,  			return false;  	} -	sum = (__force __sum16) csum_add((__force __wsum)addr->s6_addr16[idx], -			 npt->adjustment); +	sum = ~csum_fold(csum_add(csum_unfold((__force __sum16)addr->s6_addr16[idx]), +				  csum_unfold(npt->adjustment)));  	if (sum == CSUM_MANGLED_0)  		sum = 0;  	*(__force __sum16 *)&addr->s6_addr16[idx] = sum; diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 6cd29b1e8b9..70fa8144999 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -507,7 +507,7 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk,  	sock_recv_ts_and_drops(msg, sk, skb);  	if (np->rxopt.all) -		datagram_recv_ctl(sk, msg, skb); +		ip6_datagram_recv_ctl(sk, msg, skb);  	err = copied;  	if (flags & MSG_TRUNC) @@ -822,8 +822,8 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,  		memset(opt, 0, sizeof(struct ipv6_txoptions));  		opt->tot_len = sizeof(struct ipv6_txoptions); -		err = datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt, -					&hlimit, &tclass, &dontfrag); +		err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt, +					    &hlimit, &tclass, &dontfrag);  		if (err < 0) {  			fl6_sock_release(flowlabel);  			return err; diff --git a/net/ipv6/route.c b/net/ipv6/route.c index e229a3bc345..363d8b7772e 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -928,7 +928,7 @@ restart:  	dst_hold(&rt->dst);  	read_unlock_bh(&table->tb6_lock); -	if (!rt->n && !(rt->rt6i_flags & RTF_NONEXTHOP)) +	if (!rt->n && !(rt->rt6i_flags & (RTF_NONEXTHOP | RTF_LOCAL)))  		nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr);  	else if (!(rt->dst.flags & DST_HOST))  		nrt = rt6_alloc_clone(rt, &fl6->daddr); diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 93825dd3a7c..4f43537197e 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -423,6 +423,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,  		}  		inet_csk_reqsk_queue_drop(sk, req, prev); +		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);  		goto out;  	case TCP_SYN_SENT: @@ -958,8 +959,10 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)  			goto drop;  	} -	if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) +	if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) { +		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);  		goto drop; +	}  	req = inet6_reqsk_alloc(&tcp6_request_sock_ops);  	if (req == NULL) @@ -1108,6 +1111,7 @@ drop_and_release:  drop_and_free:  	reqsk_free(req);  drop: +	NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);  	return 0; /* don't send reset */  } diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index dfaa29b8b29..fb083295ff0 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -443,7 +443,7 @@ try_again:  			ip_cmsg_recv(msg, skb);  	} else {  		if (np->rxopt.all) -			datagram_recv_ctl(sk, msg, skb); +			ip6_datagram_recv_ctl(sk, msg, skb);  	}  	err = copied; @@ -1153,8 +1153,8 @@ do_udp_sendmsg:  		memset(opt, 0, sizeof(struct ipv6_txoptions));  		opt->tot_len = sizeof(*opt); -		err = datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt, -					&hlimit, &tclass, &dontfrag); +		err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt, +					    &hlimit, &tclass, &dontfrag);  		if (err < 0) {  			fl6_sock_release(flowlabel);  			return err;  |