diff options
| author | Ingo Molnar <mingo@elte.hu> | 2010-10-08 10:46:27 +0200 | 
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2010-10-08 10:46:27 +0200 | 
| commit | 7cd2541cf2395962daf98ec32a141aba3398a9b2 (patch) | |
| tree | 3c8bebb277462ba0de9d44233a970d34056dc45e /net | |
| parent | c62f981f9309486ba5546edbb5925f71e441fa65 (diff) | |
| parent | cb655d0f3d57c23db51b981648e452988c0223f9 (diff) | |
Merge commit 'v2.6.36-rc7' into perf/core
Conflicts:
	arch/x86/kernel/module.c
Merge reason: Resolve the conflict, pick up fixes.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'net')
37 files changed, 221 insertions, 152 deletions
| diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index 01ddb0472f86..0eb96f7e44be 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -24,8 +24,11 @@ int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,  	if (vlan_dev)  		skb->dev = vlan_dev; -	else if (vlan_id) -		goto drop; +	else if (vlan_id) { +		if (!(skb->dev->flags & IFF_PROMISC)) +			goto drop; +		skb->pkt_type = PACKET_OTHERHOST; +	}  	return (polling ? netif_receive_skb(skb) : netif_rx(skb)); @@ -102,8 +105,11 @@ vlan_gro_common(struct napi_struct *napi, struct vlan_group *grp,  	if (vlan_dev)  		skb->dev = vlan_dev; -	else if (vlan_id) -		goto drop; +	else if (vlan_id) { +		if (!(skb->dev->flags & IFF_PROMISC)) +			goto drop; +		skb->pkt_type = PACKET_OTHERHOST; +	}  	for (p = napi->gro_list; p; p = p->next) {  		NAPI_GRO_CB(p)->same_flow = diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c index 0ea20c30466c..17c5ba7551a5 100644 --- a/net/9p/trans_rdma.c +++ b/net/9p/trans_rdma.c @@ -426,8 +426,10 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req)  	/* Allocate an fcall for the reply */  	rpl_context = kmalloc(sizeof *rpl_context, GFP_KERNEL); -	if (!rpl_context) +	if (!rpl_context) { +		err = -ENOMEM;  		goto err_close; +	}  	/*  	 * If the request has a buffer, steal it, otherwise @@ -445,8 +447,8 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req)  	}  	rpl_context->rc = req->rc;  	if (!rpl_context->rc) { -		kfree(rpl_context); -		goto err_close; +		err = -ENOMEM; +		goto err_free2;  	}  	/* @@ -458,11 +460,8 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req)  	 */  	if (atomic_inc_return(&rdma->rq_count) <= rdma->rq_depth) {  		err = post_recv(client, rpl_context); -		if (err) { -			kfree(rpl_context->rc); -			kfree(rpl_context); -			goto err_close; -		} +		if (err) +			goto err_free1;  	} else  		atomic_dec(&rdma->rq_count); @@ -471,8 +470,10 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req)  	/* Post the request */  	c = kmalloc(sizeof *c, GFP_KERNEL); -	if (!c) -		goto err_close; +	if (!c) { +		err = -ENOMEM; +		goto err_free1; +	}  	c->req = req;  	c->busa = ib_dma_map_single(rdma->cm_id->device, @@ -499,9 +500,15 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req)  	return ib_post_send(rdma->qp, &wr, &bad_wr);   error: +	kfree(c); +	kfree(rpl_context->rc); +	kfree(rpl_context);  	P9_DPRINTK(P9_DEBUG_ERROR, "EIO\n");  	return -EIO; - + err_free1: +	kfree(rpl_context->rc); + err_free2: +	kfree(rpl_context);   err_close:  	spin_lock_irqsave(&rdma->req_lock, flags);  	if (rdma->state < P9_RDMA_CLOSING) { diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index dcfbe99ff81c..b88515936e4b 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c @@ -329,7 +329,8 @@ p9_virtio_create(struct p9_client *client, const char *devname, char *args)  	mutex_lock(&virtio_9p_lock);  	list_for_each_entry(chan, &virtio_chan_list, chan_list) { -		if (!strncmp(devname, chan->tag, chan->tag_len)) { +		if (!strncmp(devname, chan->tag, chan->tag_len) && +		    strlen(devname) == chan->tag_len) {  			if (!chan->inuse) {  				chan->inuse = true;  				found = 1; diff --git a/net/atm/br2684.c b/net/atm/br2684.c index 651babdfab38..ad2b232a2055 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c @@ -399,12 +399,6 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb)  			unregister_netdev(net_dev);  			free_netdev(net_dev);  		} -		read_lock_irq(&devs_lock); -		if (list_empty(&br2684_devs)) { -			/* last br2684 device */ -			unregister_atmdevice_notifier(&atm_dev_notifier); -		} -		read_unlock_irq(&devs_lock);  		return;  	} @@ -675,7 +669,6 @@ static int br2684_create(void __user *arg)  	if (list_empty(&br2684_devs)) {  		/* 1st br2684 device */ -		register_atmdevice_notifier(&atm_dev_notifier);  		brdev->number = 1;  	} else  		brdev->number = BRPRIV(list_entry_brdev(br2684_devs.prev))->number + 1; @@ -815,6 +808,7 @@ static int __init br2684_init(void)  		return -ENOMEM;  #endif  	register_atm_ioctl(&br2684_ioctl_ops); +	register_atmdevice_notifier(&atm_dev_notifier);  	return 0;  } @@ -830,9 +824,7 @@ static void __exit br2684_exit(void)  #endif -	/* if not already empty */ -	if (!list_empty(&br2684_devs)) -		unregister_atmdevice_notifier(&atm_dev_notifier); +	unregister_atmdevice_notifier(&atm_dev_notifier);  	while (!list_empty(&br2684_devs)) {  		net_dev = list_entry_brdev(br2684_devs.next); diff --git a/net/core/iovec.c b/net/core/iovec.c index 1cd98df412df..e6b133b77ccb 100644 --- a/net/core/iovec.c +++ b/net/core/iovec.c @@ -35,9 +35,10 @@   *	in any case.   */ -int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, int mode) +long verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, int mode)  { -	int size, err, ct; +	int size, ct; +	long err;  	if (m->msg_namelen) {  		if (mode == VERIFY_READ) { diff --git a/net/core/sock.c b/net/core/sock.c index b05b9b6ddb87..ef30e9d286e7 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1351,9 +1351,9 @@ int sock_i_uid(struct sock *sk)  {  	int uid; -	read_lock(&sk->sk_callback_lock); +	read_lock_bh(&sk->sk_callback_lock);  	uid = sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_uid : 0; -	read_unlock(&sk->sk_callback_lock); +	read_unlock_bh(&sk->sk_callback_lock);  	return uid;  }  EXPORT_SYMBOL(sock_i_uid); @@ -1362,9 +1362,9 @@ unsigned long sock_i_ino(struct sock *sk)  {  	unsigned long ino; -	read_lock(&sk->sk_callback_lock); +	read_lock_bh(&sk->sk_callback_lock);  	ino = sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_ino : 0; -	read_unlock(&sk->sk_callback_lock); +	read_unlock_bh(&sk->sk_callback_lock);  	return ino;  }  EXPORT_SYMBOL(sock_i_ino); diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index 571f8950ed06..72380a30d1c8 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig @@ -217,6 +217,7 @@ config NET_IPIP  config NET_IPGRE  	tristate "IP: GRE tunnels over IP" +	depends on IPV6 || IPV6=n  	help  	  Tunneling means encapsulating data of one protocol type within  	  another protocol and sending it over a channel that understands the diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 945b20a5ad50..35c93e8b6a46 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -45,7 +45,7 @@  #include <net/netns/generic.h>  #include <net/rtnetlink.h> -#ifdef CONFIG_IPV6 +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)  #include <net/ipv6.h>  #include <net/ip6_fib.h>  #include <net/ip6_route.h> @@ -699,7 +699,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev  			if ((dst = rt->rt_gateway) == 0)  				goto tx_error_icmp;  		} -#ifdef CONFIG_IPV6 +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)  		else if (skb->protocol == htons(ETH_P_IPV6)) {  			struct in6_addr *addr6;  			int addr_type; @@ -774,7 +774,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev  			goto tx_error;  		}  	} -#ifdef CONFIG_IPV6 +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)  	else if (skb->protocol == htons(ETH_P_IPV6)) {  		struct rt6_info *rt6 = (struct rt6_info *)skb_dst(skb); @@ -850,7 +850,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev  	if ((iph->ttl = tiph->ttl) == 0) {  		if (skb->protocol == htons(ETH_P_IP))  			iph->ttl = old_iph->ttl; -#ifdef CONFIG_IPV6 +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)  		else if (skb->protocol == htons(ETH_P_IPV6))  			iph->ttl = ((struct ipv6hdr *)old_iph)->hop_limit;  #endif diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 04b69896df5f..7649d7750075 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -488,9 +488,8 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))  	 * we can switch to copy when see the first bad fragment.  	 */  	if (skb_has_frags(skb)) { -		struct sk_buff *frag; +		struct sk_buff *frag, *frag2;  		int first_len = skb_pagelen(skb); -		int truesizes = 0;  		if (first_len - hlen > mtu ||  		    ((first_len - hlen) & 7) || @@ -503,18 +502,18 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))  			if (frag->len > mtu ||  			    ((frag->len & 7) && frag->next) ||  			    skb_headroom(frag) < hlen) -			    goto slow_path; +				goto slow_path_clean;  			/* Partially cloned skb? */  			if (skb_shared(frag)) -				goto slow_path; +				goto slow_path_clean;  			BUG_ON(frag->sk);  			if (skb->sk) {  				frag->sk = skb->sk;  				frag->destructor = sock_wfree;  			} -			truesizes += frag->truesize; +			skb->truesize -= frag->truesize;  		}  		/* Everything is OK. Generate! */ @@ -524,7 +523,6 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))  		frag = skb_shinfo(skb)->frag_list;  		skb_frag_list_init(skb);  		skb->data_len = first_len - skb_headlen(skb); -		skb->truesize -= truesizes;  		skb->len = first_len;  		iph->tot_len = htons(first_len);  		iph->frag_off = htons(IP_MF); @@ -576,6 +574,15 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))  		}  		IP_INC_STATS(dev_net(dev), IPSTATS_MIB_FRAGFAILS);  		return err; + +slow_path_clean: +		skb_walk_frags(skb, frag2) { +			if (frag2 == frag) +				break; +			frag2->sk = NULL; +			frag2->destructor = NULL; +			skb->truesize += frag2->truesize; +		}  	}  slow_path: diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index b254dafaf429..43eec80c0e7c 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c @@ -112,6 +112,7 @@ static void send_reset(struct sk_buff *oldskb, int hook)  	/* ip_route_me_harder expects skb->dst to be set */  	skb_dst_set_noref(nskb, skb_dst(oldskb)); +	nskb->protocol = htons(ETH_P_IP);  	if (ip_route_me_harder(nskb, addr_type))  		goto free_nskb; diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c b/net/ipv4/netfilter/nf_defrag_ipv4.c index eab8de32f200..f3a9b42b16c6 100644 --- a/net/ipv4/netfilter/nf_defrag_ipv4.c +++ b/net/ipv4/netfilter/nf_defrag_ipv4.c @@ -66,9 +66,11 @@ static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,  					  const struct net_device *out,  					  int (*okfn)(struct sk_buff *))  { +	struct sock *sk = skb->sk;  	struct inet_sock *inet = inet_sk(skb->sk); -	if (inet && inet->nodefrag) +	if (sk && (sk->sk_family == PF_INET) && +	    inet->nodefrag)  		return NF_ACCEPT;  #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c index 1679e2c0963d..ee5f419d0a56 100644 --- a/net/ipv4/netfilter/nf_nat_snmp_basic.c +++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c @@ -893,13 +893,15 @@ static void fast_csum(__sum16 *csum,  	unsigned char s[4];  	if (offset & 1) { -		s[0] = s[2] = 0; +		s[0] = ~0;  		s[1] = ~*optr; +		s[2] = 0;  		s[3] = *nptr;  	} else { -		s[1] = s[3] = 0;  		s[0] = ~*optr; +		s[1] = ~0;  		s[2] = *nptr; +		s[3] = 0;  	}  	*csum = csum_fold(csum_partial(s, 4, ~csum_unfold(*csum))); diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 6298f75d5e93..ac6559cb54f9 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1231,7 +1231,7 @@ restart:  			}  			if (net_ratelimit()) -				printk(KERN_WARNING "Neighbour table overflow.\n"); +				printk(KERN_WARNING "ipv4: Neighbour table overflow.\n");  			rt_drop(rt);  			return -ENOBUFS;  		} diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 3fb1428e526e..f115ea68a4ef 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -386,8 +386,6 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait)  	 */  	mask = 0; -	if (sk->sk_err) -		mask = POLLERR;  	/*  	 * POLLHUP is certainly not done right. But poll() doesn't @@ -457,6 +455,11 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait)  		if (tp->urg_data & TCP_URG_VALID)  			mask |= POLLPRI;  	} +	/* This barrier is coupled with smp_wmb() in tcp_reset() */ +	smp_rmb(); +	if (sk->sk_err) +		mask |= POLLERR; +  	return mask;  }  EXPORT_SYMBOL(tcp_poll); @@ -940,7 +943,7 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,  	sg = sk->sk_route_caps & NETIF_F_SG;  	while (--iovlen >= 0) { -		int seglen = iov->iov_len; +		size_t seglen = iov->iov_len;  		unsigned char __user *from = iov->iov_base;  		iov++; diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index e663b78a2ef6..b55f60f6fcbe 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2545,7 +2545,8 @@ static void tcp_mark_head_lost(struct sock *sk, int packets)  			cnt += tcp_skb_pcount(skb);  		if (cnt > packets) { -			if (tcp_is_sack(tp) || (oldcnt >= packets)) +			if ((tcp_is_sack(tp) && !tcp_is_fack(tp)) || +			    (oldcnt >= packets))  				break;  			mss = skb_shinfo(skb)->gso_size; @@ -4048,6 +4049,8 @@ static void tcp_reset(struct sock *sk)  	default:  		sk->sk_err = ECONNRESET;  	} +	/* This barrier is coupled with smp_rmb() in tcp_poll() */ +	smp_wmb();  	if (!sock_flag(sk, SOCK_DEAD))  		sk->sk_error_report(sk); diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index c35b469e851c..74c54b30600f 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -135,13 +135,16 @@ static void tcp_mtu_probing(struct inet_connection_sock *icsk, struct sock *sk)  /* This function calculates a "timeout" which is equivalent to the timeout of a   * TCP connection after "boundary" unsuccessful, exponentially backed-off - * retransmissions with an initial RTO of TCP_RTO_MIN. + * retransmissions with an initial RTO of TCP_RTO_MIN or TCP_TIMEOUT_INIT if + * syn_set flag is set.   */  static bool retransmits_timed_out(struct sock *sk, -				  unsigned int boundary) +				  unsigned int boundary, +				  bool syn_set)  {  	unsigned int timeout, linear_backoff_thresh;  	unsigned int start_ts; +	unsigned int rto_base = syn_set ? TCP_TIMEOUT_INIT : TCP_RTO_MIN;  	if (!inet_csk(sk)->icsk_retransmits)  		return false; @@ -151,12 +154,12 @@ static bool retransmits_timed_out(struct sock *sk,  	else  		start_ts = tcp_sk(sk)->retrans_stamp; -	linear_backoff_thresh = ilog2(TCP_RTO_MAX/TCP_RTO_MIN); +	linear_backoff_thresh = ilog2(TCP_RTO_MAX/rto_base);  	if (boundary <= linear_backoff_thresh) -		timeout = ((2 << boundary) - 1) * TCP_RTO_MIN; +		timeout = ((2 << boundary) - 1) * rto_base;  	else -		timeout = ((2 << linear_backoff_thresh) - 1) * TCP_RTO_MIN + +		timeout = ((2 << linear_backoff_thresh) - 1) * rto_base +  			  (boundary - linear_backoff_thresh) * TCP_RTO_MAX;  	return (tcp_time_stamp - start_ts) >= timeout; @@ -167,14 +170,15 @@ static int tcp_write_timeout(struct sock *sk)  {  	struct inet_connection_sock *icsk = inet_csk(sk);  	int retry_until; -	bool do_reset; +	bool do_reset, syn_set = 0;  	if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) {  		if (icsk->icsk_retransmits)  			dst_negative_advice(sk);  		retry_until = icsk->icsk_syn_retries ? : sysctl_tcp_syn_retries; +		syn_set = 1;  	} else { -		if (retransmits_timed_out(sk, sysctl_tcp_retries1)) { +		if (retransmits_timed_out(sk, sysctl_tcp_retries1, 0)) {  			/* Black hole detection */  			tcp_mtu_probing(icsk, sk); @@ -187,14 +191,14 @@ static int tcp_write_timeout(struct sock *sk)  			retry_until = tcp_orphan_retries(sk, alive);  			do_reset = alive || -				   !retransmits_timed_out(sk, retry_until); +				   !retransmits_timed_out(sk, retry_until, 0);  			if (tcp_out_of_resources(sk, do_reset))  				return 1;  		}  	} -	if (retransmits_timed_out(sk, retry_until)) { +	if (retransmits_timed_out(sk, retry_until, syn_set)) {  		/* Has it gone just too far? */  		tcp_write_err(sk);  		return 1; @@ -436,7 +440,7 @@ out_reset_timer:  		icsk->icsk_rto = min(icsk->icsk_rto << 1, TCP_RTO_MAX);  	}  	inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto, TCP_RTO_MAX); -	if (retransmits_timed_out(sk, sysctl_tcp_retries1 + 1)) +	if (retransmits_timed_out(sk, sysctl_tcp_retries1 + 1, 0))  		__sk_dst_reset(sk);  out:; diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 869078d4eeb9..a580349f0b8a 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c @@ -61,7 +61,7 @@ static int xfrm4_get_saddr(struct net *net,  static int xfrm4_get_tos(struct flowi *fl)  { -	return fl->fl4_tos; +	return IPTOS_RT_MASK & fl->fl4_tos; /* Strip ECN bits */  }  static int xfrm4_init_path(struct xfrm_dst *path, struct dst_entry *dst, diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c index 1ef1366a0a03..47947624eccc 100644 --- a/net/ipv4/xfrm4_state.c +++ b/net/ipv4/xfrm4_state.c @@ -21,21 +21,25 @@ static int xfrm4_init_flags(struct xfrm_state *x)  }  static void -__xfrm4_init_tempsel(struct xfrm_state *x, struct flowi *fl, -		     struct xfrm_tmpl *tmpl, -		     xfrm_address_t *daddr, xfrm_address_t *saddr) +__xfrm4_init_tempsel(struct xfrm_selector *sel, struct flowi *fl) +{ +	sel->daddr.a4 = fl->fl4_dst; +	sel->saddr.a4 = fl->fl4_src; +	sel->dport = xfrm_flowi_dport(fl); +	sel->dport_mask = htons(0xffff); +	sel->sport = xfrm_flowi_sport(fl); +	sel->sport_mask = htons(0xffff); +	sel->family = AF_INET; +	sel->prefixlen_d = 32; +	sel->prefixlen_s = 32; +	sel->proto = fl->proto; +	sel->ifindex = fl->oif; +} + +static void +xfrm4_init_temprop(struct xfrm_state *x, struct xfrm_tmpl *tmpl, +		   xfrm_address_t *daddr, xfrm_address_t *saddr)  { -	x->sel.daddr.a4 = fl->fl4_dst; -	x->sel.saddr.a4 = fl->fl4_src; -	x->sel.dport = xfrm_flowi_dport(fl); -	x->sel.dport_mask = htons(0xffff); -	x->sel.sport = xfrm_flowi_sport(fl); -	x->sel.sport_mask = htons(0xffff); -	x->sel.family = AF_INET; -	x->sel.prefixlen_d = 32; -	x->sel.prefixlen_s = 32; -	x->sel.proto = fl->proto; -	x->sel.ifindex = fl->oif;  	x->id = tmpl->id;  	if (x->id.daddr.a4 == 0)  		x->id.daddr.a4 = daddr->a4; @@ -70,6 +74,7 @@ static struct xfrm_state_afinfo xfrm4_state_afinfo = {  	.owner			= THIS_MODULE,  	.init_flags		= xfrm4_init_flags,  	.init_tempsel		= __xfrm4_init_tempsel, +	.init_temprop		= xfrm4_init_temprop,  	.output			= xfrm4_output,  	.extract_input		= xfrm4_extract_input,  	.extract_output		= xfrm4_extract_output, diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index ab70a3fbcafa..324fac3b6c16 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -4637,10 +4637,12 @@ int __init addrconf_init(void)  	if (err < 0) {  		printk(KERN_CRIT "IPv6 Addrconf:"  		       " cannot initialize default policy table: %d.\n", err); -		return err; +		goto out;  	} -	register_pernet_subsys(&addrconf_ops); +	err = register_pernet_subsys(&addrconf_ops); +	if (err < 0) +		goto out_addrlabel;  	/* The addrconf netdev notifier requires that loopback_dev  	 * has it's ipv6 private information allocated and setup @@ -4692,7 +4694,9 @@ errout:  	unregister_netdevice_notifier(&ipv6_dev_notf);  errlo:  	unregister_pernet_subsys(&addrconf_ops); - +out_addrlabel: +	ipv6_addr_label_cleanup(); +out:  	return err;  } @@ -4703,6 +4707,7 @@ void addrconf_cleanup(void)  	unregister_netdevice_notifier(&ipv6_dev_notf);  	unregister_pernet_subsys(&addrconf_ops); +	ipv6_addr_label_cleanup();  	rtnl_lock(); diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c index f0e774cea386..8175f802651b 100644 --- a/net/ipv6/addrlabel.c +++ b/net/ipv6/addrlabel.c @@ -393,6 +393,11 @@ int __init ipv6_addr_label_init(void)  	return register_pernet_subsys(&ipv6_addr_label_ops);  } +void ipv6_addr_label_cleanup(void) +{ +	unregister_pernet_subsys(&ipv6_addr_label_ops); +} +  static const struct nla_policy ifal_policy[IFAL_MAX+1] = {  	[IFAL_ADDRESS]		= { .len = sizeof(struct in6_addr), },  	[IFAL_LABEL]		= { .len = sizeof(u32), }, diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index d40b330c0ee6..980912ed7a38 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -639,7 +639,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))  	if (skb_has_frags(skb)) {  		int first_len = skb_pagelen(skb); -		int truesizes = 0; +		struct sk_buff *frag2;  		if (first_len - hlen > mtu ||  		    ((first_len - hlen) & 7) || @@ -651,18 +651,18 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))  			if (frag->len > mtu ||  			    ((frag->len & 7) && frag->next) ||  			    skb_headroom(frag) < hlen) -			    goto slow_path; +				goto slow_path_clean;  			/* Partially cloned skb? */  			if (skb_shared(frag)) -				goto slow_path; +				goto slow_path_clean;  			BUG_ON(frag->sk);  			if (skb->sk) {  				frag->sk = skb->sk;  				frag->destructor = sock_wfree; -				truesizes += frag->truesize;  			} +			skb->truesize -= frag->truesize;  		}  		err = 0; @@ -693,7 +693,6 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))  		first_len = skb_pagelen(skb);  		skb->data_len = first_len - skb_headlen(skb); -		skb->truesize -= truesizes;  		skb->len = first_len;  		ipv6_hdr(skb)->payload_len = htons(first_len -  						   sizeof(struct ipv6hdr)); @@ -756,6 +755,15 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))  			      IPSTATS_MIB_FRAGFAILS);  		dst_release(&rt->dst);  		return err; + +slow_path_clean: +		skb_walk_frags(skb, frag2) { +			if (frag2 == frag) +				break; +			frag2->sk = NULL; +			frag2->destructor = NULL; +			skb->truesize += frag2->truesize; +		}  	}  slow_path: diff --git a/net/ipv6/route.c b/net/ipv6/route.c index d126365ac046..8323136bdc54 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -670,7 +670,7 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, struct in6_addr *dad  			if (net_ratelimit())  				printk(KERN_WARNING -				       "Neighbour table overflow.\n"); +				       "ipv6: Neighbour table overflow.\n");  			dst_free(&rt->dst);  			return NULL;  		} diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c index f417b77fa0e1..a67575d472a3 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c @@ -20,23 +20,27 @@  #include <net/addrconf.h>  static void -__xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl, -		     struct xfrm_tmpl *tmpl, -		     xfrm_address_t *daddr, xfrm_address_t *saddr) +__xfrm6_init_tempsel(struct xfrm_selector *sel, struct flowi *fl)  {  	/* Initialize temporary selector matching only  	 * to current session. */ -	ipv6_addr_copy((struct in6_addr *)&x->sel.daddr, &fl->fl6_dst); -	ipv6_addr_copy((struct in6_addr *)&x->sel.saddr, &fl->fl6_src); -	x->sel.dport = xfrm_flowi_dport(fl); -	x->sel.dport_mask = htons(0xffff); -	x->sel.sport = xfrm_flowi_sport(fl); -	x->sel.sport_mask = htons(0xffff); -	x->sel.family = AF_INET6; -	x->sel.prefixlen_d = 128; -	x->sel.prefixlen_s = 128; -	x->sel.proto = fl->proto; -	x->sel.ifindex = fl->oif; +	ipv6_addr_copy((struct in6_addr *)&sel->daddr, &fl->fl6_dst); +	ipv6_addr_copy((struct in6_addr *)&sel->saddr, &fl->fl6_src); +	sel->dport = xfrm_flowi_dport(fl); +	sel->dport_mask = htons(0xffff); +	sel->sport = xfrm_flowi_sport(fl); +	sel->sport_mask = htons(0xffff); +	sel->family = AF_INET6; +	sel->prefixlen_d = 128; +	sel->prefixlen_s = 128; +	sel->proto = fl->proto; +	sel->ifindex = fl->oif; +} + +static void +xfrm6_init_temprop(struct xfrm_state *x, struct xfrm_tmpl *tmpl, +		   xfrm_address_t *daddr, xfrm_address_t *saddr) +{  	x->id = tmpl->id;  	if (ipv6_addr_any((struct in6_addr*)&x->id.daddr))  		memcpy(&x->id.daddr, daddr, sizeof(x->sel.daddr)); @@ -168,6 +172,7 @@ static struct xfrm_state_afinfo xfrm6_state_afinfo = {  	.eth_proto		= htons(ETH_P_IPV6),  	.owner			= THIS_MODULE,  	.init_tempsel		= __xfrm6_init_tempsel, +	.init_temprop		= xfrm6_init_temprop,  	.tmpl_sort		= __xfrm6_tmpl_sort,  	.state_sort		= __xfrm6_state_sort,  	.output			= xfrm6_output, diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index fa0f37e4afe4..28624282c5f3 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2199,9 +2199,6 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,  	struct net_device *prev_dev = NULL;  	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); -	if (status->flag & RX_FLAG_INTERNAL_CMTR) -		goto out_free_skb; -  	if (skb_headroom(skb) < sizeof(*rthdr) &&  	    pskb_expand_head(skb, sizeof(*rthdr), 0, GFP_ATOMIC))  		goto out_free_skb; @@ -2260,7 +2257,6 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,  	} else  		goto out_free_skb; -	status->flag |= RX_FLAG_INTERNAL_CMTR;  	return;   out_free_skb: diff --git a/net/netfilter/nf_conntrack_extend.c b/net/netfilter/nf_conntrack_extend.c index 7dcf7a404190..8d9e4c949b96 100644 --- a/net/netfilter/nf_conntrack_extend.c +++ b/net/netfilter/nf_conntrack_extend.c @@ -48,15 +48,17 @@ nf_ct_ext_create(struct nf_ct_ext **ext, enum nf_ct_ext_id id, gfp_t gfp)  {  	unsigned int off, len;  	struct nf_ct_ext_type *t; +	size_t alloc_size;  	rcu_read_lock();  	t = rcu_dereference(nf_ct_ext_types[id]);  	BUG_ON(t == NULL);  	off = ALIGN(sizeof(struct nf_ct_ext), t->align);  	len = off + t->len; +	alloc_size = t->alloc_size;  	rcu_read_unlock(); -	*ext = kzalloc(t->alloc_size, gfp); +	*ext = kzalloc(alloc_size, gfp);  	if (!*ext)  		return NULL; diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index 53d892210a04..f64de9544866 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c @@ -1376,7 +1376,7 @@ static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff,  	unsigned int msglen, origlen;  	const char *dptr, *end;  	s16 diff, tdiff = 0; -	int ret; +	int ret = NF_ACCEPT;  	typeof(nf_nat_sip_seq_adjust_hook) nf_nat_sip_seq_adjust;  	if (ctinfo != IP_CT_ESTABLISHED && diff --git a/net/netfilter/nf_tproxy_core.c b/net/netfilter/nf_tproxy_core.c index 5490fc37c92d..daab8c4a903c 100644 --- a/net/netfilter/nf_tproxy_core.c +++ b/net/netfilter/nf_tproxy_core.c @@ -70,7 +70,11 @@ nf_tproxy_destructor(struct sk_buff *skb)  int  nf_tproxy_assign_sock(struct sk_buff *skb, struct sock *sk)  { -	if (inet_sk(sk)->transparent) { +	bool transparent = (sk->sk_state == TCP_TIME_WAIT) ? +				inet_twsk(sk)->tw_transparent : +				inet_sk(sk)->transparent; + +	if (transparent) {  		skb_orphan(skb);  		skb->sk = sk;  		skb->destructor = nf_tproxy_destructor; diff --git a/net/phonet/pep.c b/net/phonet/pep.c index b2a3ae6cad78..15003021f4f0 100644 --- a/net/phonet/pep.c +++ b/net/phonet/pep.c @@ -225,12 +225,13 @@ static void pipe_grant_credits(struct sock *sk)  static int pipe_rcv_status(struct sock *sk, struct sk_buff *skb)  {  	struct pep_sock *pn = pep_sk(sk); -	struct pnpipehdr *hdr = pnp_hdr(skb); +	struct pnpipehdr *hdr;  	int wake = 0;  	if (!pskb_may_pull(skb, sizeof(*hdr) + 4))  		return -EINVAL; +	hdr = pnp_hdr(skb);  	if (hdr->data[0] != PN_PEP_TYPE_COMMON) {  		LIMIT_NETDEBUG(KERN_DEBUG"Phonet unknown PEP type: %u\n",  				(unsigned)hdr->data[0]); diff --git a/net/rds/tcp_connect.c b/net/rds/tcp_connect.c index c397524c039c..c519939e8da9 100644 --- a/net/rds/tcp_connect.c +++ b/net/rds/tcp_connect.c @@ -43,7 +43,7 @@ void rds_tcp_state_change(struct sock *sk)  	struct rds_connection *conn;  	struct rds_tcp_connection *tc; -	read_lock(&sk->sk_callback_lock); +	read_lock_bh(&sk->sk_callback_lock);  	conn = sk->sk_user_data;  	if (conn == NULL) {  		state_change = sk->sk_state_change; @@ -68,7 +68,7 @@ void rds_tcp_state_change(struct sock *sk)  			break;  	}  out: -	read_unlock(&sk->sk_callback_lock); +	read_unlock_bh(&sk->sk_callback_lock);  	state_change(sk);  } diff --git a/net/rds/tcp_listen.c b/net/rds/tcp_listen.c index 975183fe6950..27844f231d10 100644 --- a/net/rds/tcp_listen.c +++ b/net/rds/tcp_listen.c @@ -114,7 +114,7 @@ void rds_tcp_listen_data_ready(struct sock *sk, int bytes)  	rdsdebug("listen data ready sk %p\n", sk); -	read_lock(&sk->sk_callback_lock); +	read_lock_bh(&sk->sk_callback_lock);  	ready = sk->sk_user_data;  	if (ready == NULL) { /* check for teardown race */  		ready = sk->sk_data_ready; @@ -131,7 +131,7 @@ void rds_tcp_listen_data_ready(struct sock *sk, int bytes)  		queue_work(rds_wq, &rds_tcp_listen_work);  out: -	read_unlock(&sk->sk_callback_lock); +	read_unlock_bh(&sk->sk_callback_lock);  	ready(sk, bytes);  } diff --git a/net/rds/tcp_recv.c b/net/rds/tcp_recv.c index 1aba6878fa5d..e43797404102 100644 --- a/net/rds/tcp_recv.c +++ b/net/rds/tcp_recv.c @@ -324,7 +324,7 @@ void rds_tcp_data_ready(struct sock *sk, int bytes)  	rdsdebug("data ready sk %p bytes %d\n", sk, bytes); -	read_lock(&sk->sk_callback_lock); +	read_lock_bh(&sk->sk_callback_lock);  	conn = sk->sk_user_data;  	if (conn == NULL) { /* check for teardown race */  		ready = sk->sk_data_ready; @@ -338,7 +338,7 @@ void rds_tcp_data_ready(struct sock *sk, int bytes)  	if (rds_tcp_read_sock(conn, GFP_ATOMIC, KM_SOFTIRQ0) == -ENOMEM)  		queue_delayed_work(rds_wq, &conn->c_recv_w, 0);  out: -	read_unlock(&sk->sk_callback_lock); +	read_unlock_bh(&sk->sk_callback_lock);  	ready(sk, bytes);  } diff --git a/net/rds/tcp_send.c b/net/rds/tcp_send.c index a28b895ff0d1..2f012a07d94d 100644 --- a/net/rds/tcp_send.c +++ b/net/rds/tcp_send.c @@ -224,7 +224,7 @@ void rds_tcp_write_space(struct sock *sk)  	struct rds_connection *conn;  	struct rds_tcp_connection *tc; -	read_lock(&sk->sk_callback_lock); +	read_lock_bh(&sk->sk_callback_lock);  	conn = sk->sk_user_data;  	if (conn == NULL) {  		write_space = sk->sk_write_space; @@ -244,7 +244,7 @@ void rds_tcp_write_space(struct sock *sk)  		queue_delayed_work(rds_wq, &conn->c_send_w, 0);  out: -	read_unlock(&sk->sk_callback_lock); +	read_unlock_bh(&sk->sk_callback_lock);  	/*  	 * write_space is only called when data leaves tcp's send queue if diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 8e45e76a95f5..d952e7eac188 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -679,7 +679,7 @@ static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)  	if (addr_len == sizeof(struct sockaddr_rose) && addr->srose_ndigis > 1)  		return -EINVAL; -	if (addr->srose_ndigis > ROSE_MAX_DIGIS) +	if ((unsigned int) addr->srose_ndigis > ROSE_MAX_DIGIS)  		return -EINVAL;  	if ((dev = rose_dev_get(&addr->srose_addr)) == NULL) { @@ -739,7 +739,7 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le  	if (addr_len == sizeof(struct sockaddr_rose) && addr->srose_ndigis > 1)  		return -EINVAL; -	if (addr->srose_ndigis > ROSE_MAX_DIGIS) +	if ((unsigned int) addr->srose_ndigis > ROSE_MAX_DIGIS)  		return -EINVAL;  	/* Source + Destination digis should not exceed ROSE_MAX_DIGIS */ diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index b6309db56226..fe9306bf10cc 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -800,7 +800,7 @@ static void xs_udp_data_ready(struct sock *sk, int len)  	u32 _xid;  	__be32 *xp; -	read_lock(&sk->sk_callback_lock); +	read_lock_bh(&sk->sk_callback_lock);  	dprintk("RPC:       xs_udp_data_ready...\n");  	if (!(xprt = xprt_from_sock(sk)))  		goto out; @@ -852,7 +852,7 @@ static void xs_udp_data_ready(struct sock *sk, int len)   dropit:  	skb_free_datagram(sk, skb);   out: -	read_unlock(&sk->sk_callback_lock); +	read_unlock_bh(&sk->sk_callback_lock);  }  static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, struct xdr_skb_reader *desc) @@ -1229,7 +1229,7 @@ static void xs_tcp_data_ready(struct sock *sk, int bytes)  	dprintk("RPC:       xs_tcp_data_ready...\n"); -	read_lock(&sk->sk_callback_lock); +	read_lock_bh(&sk->sk_callback_lock);  	if (!(xprt = xprt_from_sock(sk)))  		goto out;  	if (xprt->shutdown) @@ -1248,7 +1248,7 @@ static void xs_tcp_data_ready(struct sock *sk, int bytes)  		read = tcp_read_sock(sk, &rd_desc, xs_tcp_data_recv);  	} while (read > 0);  out: -	read_unlock(&sk->sk_callback_lock); +	read_unlock_bh(&sk->sk_callback_lock);  }  /* @@ -1301,7 +1301,7 @@ static void xs_tcp_state_change(struct sock *sk)  {  	struct rpc_xprt *xprt; -	read_lock(&sk->sk_callback_lock); +	read_lock_bh(&sk->sk_callback_lock);  	if (!(xprt = xprt_from_sock(sk)))  		goto out;  	dprintk("RPC:       xs_tcp_state_change client %p...\n", xprt); @@ -1313,7 +1313,7 @@ static void xs_tcp_state_change(struct sock *sk)  	switch (sk->sk_state) {  	case TCP_ESTABLISHED: -		spin_lock_bh(&xprt->transport_lock); +		spin_lock(&xprt->transport_lock);  		if (!xprt_test_and_set_connected(xprt)) {  			struct sock_xprt *transport = container_of(xprt,  					struct sock_xprt, xprt); @@ -1327,7 +1327,7 @@ static void xs_tcp_state_change(struct sock *sk)  			xprt_wake_pending_tasks(xprt, -EAGAIN);  		} -		spin_unlock_bh(&xprt->transport_lock); +		spin_unlock(&xprt->transport_lock);  		break;  	case TCP_FIN_WAIT1:  		/* The client initiated a shutdown of the socket */ @@ -1365,7 +1365,7 @@ static void xs_tcp_state_change(struct sock *sk)  		xs_sock_mark_closed(xprt);  	}   out: -	read_unlock(&sk->sk_callback_lock); +	read_unlock_bh(&sk->sk_callback_lock);  }  /** @@ -1376,7 +1376,7 @@ static void xs_error_report(struct sock *sk)  {  	struct rpc_xprt *xprt; -	read_lock(&sk->sk_callback_lock); +	read_lock_bh(&sk->sk_callback_lock);  	if (!(xprt = xprt_from_sock(sk)))  		goto out;  	dprintk("RPC:       %s client %p...\n" @@ -1384,7 +1384,7 @@ static void xs_error_report(struct sock *sk)  			__func__, xprt, sk->sk_err);  	xprt_wake_pending_tasks(xprt, -EAGAIN);  out: -	read_unlock(&sk->sk_callback_lock); +	read_unlock_bh(&sk->sk_callback_lock);  }  static void xs_write_space(struct sock *sk) @@ -1416,13 +1416,13 @@ static void xs_write_space(struct sock *sk)   */  static void xs_udp_write_space(struct sock *sk)  { -	read_lock(&sk->sk_callback_lock); +	read_lock_bh(&sk->sk_callback_lock);  	/* from net/core/sock.c:sock_def_write_space */  	if (sock_writeable(sk))  		xs_write_space(sk); -	read_unlock(&sk->sk_callback_lock); +	read_unlock_bh(&sk->sk_callback_lock);  }  /** @@ -1437,13 +1437,13 @@ static void xs_udp_write_space(struct sock *sk)   */  static void xs_tcp_write_space(struct sock *sk)  { -	read_lock(&sk->sk_callback_lock); +	read_lock_bh(&sk->sk_callback_lock);  	/* from net/core/stream.c:sk_stream_write_space */  	if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk))  		xs_write_space(sk); -	read_unlock(&sk->sk_callback_lock); +	read_unlock_bh(&sk->sk_callback_lock);  }  static void xs_udp_do_set_buffer_size(struct rpc_xprt *xprt) diff --git a/net/wireless/wext-priv.c b/net/wireless/wext-priv.c index 3feb28e41c53..674d426a9d24 100644 --- a/net/wireless/wext-priv.c +++ b/net/wireless/wext-priv.c @@ -152,7 +152,7 @@ static int ioctl_private_iw_point(struct iw_point *iwp, unsigned int cmd,  	} else if (!iwp->pointer)  		return -EFAULT; -	extra = kmalloc(extra_size, GFP_KERNEL); +	extra = kzalloc(extra_size, GFP_KERNEL);  	if (!extra)  		return -ENOMEM; diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 2b3ed7ad4933..cbab6e1a8c9c 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -1175,9 +1175,8 @@ xfrm_tmpl_resolve_one(struct xfrm_policy *policy, struct flowi *fl,  		    tmpl->mode == XFRM_MODE_BEET) {  			remote = &tmpl->id.daddr;  			local = &tmpl->saddr; -			family = tmpl->encap_family; -			if (xfrm_addr_any(local, family)) { -				error = xfrm_get_saddr(net, &tmp, remote, family); +			if (xfrm_addr_any(local, tmpl->encap_family)) { +				error = xfrm_get_saddr(net, &tmp, remote, tmpl->encap_family);  				if (error)  					goto fail;  				local = &tmp; diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 5208b12fbfb4..eb96ce52f178 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -656,15 +656,23 @@ void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si)  EXPORT_SYMBOL(xfrm_sad_getinfo);  static int -xfrm_init_tempsel(struct xfrm_state *x, struct flowi *fl, -		  struct xfrm_tmpl *tmpl, -		  xfrm_address_t *daddr, xfrm_address_t *saddr, -		  unsigned short family) +xfrm_init_tempstate(struct xfrm_state *x, struct flowi *fl, +		    struct xfrm_tmpl *tmpl, +		    xfrm_address_t *daddr, xfrm_address_t *saddr, +		    unsigned short family)  {  	struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);  	if (!afinfo)  		return -1; -	afinfo->init_tempsel(x, fl, tmpl, daddr, saddr); +	afinfo->init_tempsel(&x->sel, fl); + +	if (family != tmpl->encap_family) { +		xfrm_state_put_afinfo(afinfo); +		afinfo = xfrm_state_get_afinfo(tmpl->encap_family); +		if (!afinfo) +			return -1; +	} +	afinfo->init_temprop(x, tmpl, daddr, saddr);  	xfrm_state_put_afinfo(afinfo);  	return 0;  } @@ -790,37 +798,38 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,  	int error = 0;  	struct xfrm_state *best = NULL;  	u32 mark = pol->mark.v & pol->mark.m; +	unsigned short encap_family = tmpl->encap_family;  	to_put = NULL;  	spin_lock_bh(&xfrm_state_lock); -	h = xfrm_dst_hash(net, daddr, saddr, tmpl->reqid, family); +	h = xfrm_dst_hash(net, daddr, saddr, tmpl->reqid, encap_family);  	hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { -		if (x->props.family == family && +		if (x->props.family == encap_family &&  		    x->props.reqid == tmpl->reqid &&  		    (mark & x->mark.m) == x->mark.v &&  		    !(x->props.flags & XFRM_STATE_WILDRECV) && -		    xfrm_state_addr_check(x, daddr, saddr, family) && +		    xfrm_state_addr_check(x, daddr, saddr, encap_family) &&  		    tmpl->mode == x->props.mode &&  		    tmpl->id.proto == x->id.proto &&  		    (tmpl->id.spi == x->id.spi || !tmpl->id.spi)) -			xfrm_state_look_at(pol, x, fl, family, daddr, saddr, +			xfrm_state_look_at(pol, x, fl, encap_family, daddr, saddr,  					   &best, &acquire_in_progress, &error);  	}  	if (best)  		goto found; -	h_wildcard = xfrm_dst_hash(net, daddr, &saddr_wildcard, tmpl->reqid, family); +	h_wildcard = xfrm_dst_hash(net, daddr, &saddr_wildcard, tmpl->reqid, encap_family);  	hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h_wildcard, bydst) { -		if (x->props.family == family && +		if (x->props.family == encap_family &&  		    x->props.reqid == tmpl->reqid &&  		    (mark & x->mark.m) == x->mark.v &&  		    !(x->props.flags & XFRM_STATE_WILDRECV) && -		    xfrm_state_addr_check(x, daddr, saddr, family) && +		    xfrm_state_addr_check(x, daddr, saddr, encap_family) &&  		    tmpl->mode == x->props.mode &&  		    tmpl->id.proto == x->id.proto &&  		    (tmpl->id.spi == x->id.spi || !tmpl->id.spi)) -			xfrm_state_look_at(pol, x, fl, family, daddr, saddr, +			xfrm_state_look_at(pol, x, fl, encap_family, daddr, saddr,  					   &best, &acquire_in_progress, &error);  	} @@ -829,7 +838,7 @@ found:  	if (!x && !error && !acquire_in_progress) {  		if (tmpl->id.spi &&  		    (x0 = __xfrm_state_lookup(net, mark, daddr, tmpl->id.spi, -					      tmpl->id.proto, family)) != NULL) { +					      tmpl->id.proto, encap_family)) != NULL) {  			to_put = x0;  			error = -EEXIST;  			goto out; @@ -839,9 +848,9 @@ found:  			error = -ENOMEM;  			goto out;  		} -		/* Initialize temporary selector matching only +		/* Initialize temporary state matching only  		 * to current session. */ -		xfrm_init_tempsel(x, fl, tmpl, daddr, saddr, family); +		xfrm_init_tempstate(x, fl, tmpl, daddr, saddr, family);  		memcpy(&x->mark, &pol->mark, sizeof(x->mark));  		error = security_xfrm_state_alloc_acquire(x, pol->security, fl->secid); @@ -856,10 +865,10 @@ found:  			x->km.state = XFRM_STATE_ACQ;  			list_add(&x->km.all, &net->xfrm.state_all);  			hlist_add_head(&x->bydst, net->xfrm.state_bydst+h); -			h = xfrm_src_hash(net, daddr, saddr, family); +			h = xfrm_src_hash(net, daddr, saddr, encap_family);  			hlist_add_head(&x->bysrc, net->xfrm.state_bysrc+h);  			if (x->id.spi) { -				h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, family); +				h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, encap_family);  				hlist_add_head(&x->byspi, net->xfrm.state_byspi+h);  			}  			x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires; | 
