diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 606d7bf9842d41227f6221db95664086b9e73c42..f022276d7aba19d49e6d387a823fc1420403eaed 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -2073,7 +2073,8 @@ ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound)
 	case CCP_CONFACK:
 		if ((ppp->flags & (SC_CCP_OPEN | SC_CCP_UP)) != SC_CCP_OPEN)
 			break;
-		if (!pskb_may_pull(skb, len = CCP_LENGTH(dp)) + 2)
+		len = CCP_LENGTH(dp);
+		if (!pskb_may_pull(skb, len + 2))
 			return;		/* too short */
 		dp += CCP_HDRLEN;
 		len -= CCP_HDRLEN;
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 470ac0908e585457635dfa5d95fbdd3eaec6fe34..53097e3fa392123ffedf6fc12ec976015aa79dc6 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -605,7 +605,18 @@ int __init tun_init(void)
 
 void tun_cleanup(void)
 {
+	struct net_device *dev, *nxt;
+
 	misc_deregister(&tun_miscdev);  
+
+	rtnl_lock();
+	for (dev = dev_base; dev; dev = nxt) {
+		nxt = dev->next;
+		if (dev->init == tun_net_init) 
+			unregister_netdevice(dev);
+	}
+	rtnl_unlock();
+	
 }
 
 module_init(tun_init);
diff --git a/include/linux/ppp-comp.h b/include/linux/ppp-comp.h
index 82dd01c38920feecd2acdb28e5296ca3d3857540..7227e653b3beacdb7e496196e86b08f821671772 100644
--- a/include/linux/ppp-comp.h
+++ b/include/linux/ppp-comp.h
@@ -185,10 +185,9 @@ struct compressor {
 #define DEFLATE_MIN_SIZE	9
 #define DEFLATE_MAX_SIZE	15
 #define DEFLATE_METHOD_VAL	8
-#define DEFLATE_SIZE(x)		(((x) >> 4) + DEFLATE_MIN_SIZE)
+#define DEFLATE_SIZE(x)		(((x) >> 4) + 8)
 #define DEFLATE_METHOD(x)	((x) & 0x0F)
-#define DEFLATE_MAKE_OPT(w)	((((w) - DEFLATE_MIN_SIZE) << 4) \
-				 + DEFLATE_METHOD_VAL)
+#define DEFLATE_MAKE_OPT(w)	((((w) - 8) << 4) + DEFLATE_METHOD_VAL)
 #define DEFLATE_CHK_SEQUENCE	0
 
 /*
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
index a4dd169d9f6fe4a4854a041a42474dceda8146c5..430370b12d139c32048daf7274ca79ee36cdb8ea 100644
--- a/include/linux/xfrm.h
+++ b/include/linux/xfrm.h
@@ -37,6 +37,7 @@ struct xfrm_selector
 	__u16	dport_mask;
 	__u16	sport;
 	__u16	sport_mask;
+	__u16	family;
 	__u8	prefixlen_d;
 	__u8	prefixlen_s;
 	__u8	proto;
@@ -125,6 +126,7 @@ enum
 
 struct xfrm_user_tmpl {
 	struct xfrm_id		id;
+	__u16			family;
 	xfrm_address_t		saddr;
 	__u32			reqid;
 	__u8			mode;
@@ -189,7 +191,6 @@ struct xfrm_userpolicy_info {
 	struct xfrm_lifetime_cur	curlft;
 	__u32				priority;
 	__u32				index;
-	__u16				family;
 	__u8				dir;
 	__u8				action;
 #define XFRM_POLICY_ALLOW	0
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 8aeb974d8592a0d982f3aeaf23d6e58bd70f9998..9ed62a7db079259c9aace0116fc419d269aaa41e 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -353,9 +353,7 @@ extern int			ip6_push_pending_frames(struct sock *sk);
 
 extern void			ip6_flush_pending_frames(struct sock *sk);
 
-extern int			ip6_dst_lookup(struct sock *sk,
-					       struct dst_entry **dst,
-					       struct flowi *fl);
+extern struct dst_entry *	ip6_dst_lookup(struct sock *sk, struct flowi *fl);
 
 /*
  *	skb processing functions
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index 5ebb565c77d99f263a8738951e0bf235d98041ef..a713530ae557baf5fedc8d564c500b439df6d88f 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -279,6 +279,7 @@ static struct xfrm_state *ipcomp_tunnel_create(struct xfrm_state *x)
 	t->props.family = AF_INET;
 	t->props.mode = 1;
 	t->props.saddr.a4 = x->props.saddr.a4;
+	t->props.flags = x->props.flags;
 	
 	t->type = xfrm_get_type(IPPROTO_IPIP, t->props.family);
 	if (t->type == NULL)
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c
index 2412f939868283cb66ee42a54faeeb8b1f3c9971..9040408dbf81d1118919a5881f9b6bf298935ade 100644
--- a/net/ipv4/xfrm4_input.c
+++ b/net/ipv4/xfrm4_input.c
@@ -27,6 +27,20 @@ static inline void ipip_ecn_decapsulate(struct iphdr *outer_iph, struct sk_buff
 		IP_ECN_set_ce(inner_iph);
 }
 
+static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq)
+{
+	switch (nexthdr) {
+	case IPPROTO_IPIP:
+		if (!pskb_may_pull(skb, sizeof(struct iphdr)))
+			return -EINVAL;
+		*spi = skb->nh.iph->saddr;
+		*seq = 0;
+		return 0;
+	}
+
+	return xfrm_parse_spi(skb, nexthdr, spi, seq);
+}
+
 int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
 {
 	int err;
@@ -36,7 +50,7 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
 	int xfrm_nr = 0;
 	int decaps = 0;
 
-	if ((err = xfrm_parse_spi(skb, skb->nh.iph->protocol, &spi, &seq)) != 0)
+	if ((err = xfrm4_parse_spi(skb, skb->nh.iph->protocol, &spi, &seq)) != 0)
 		goto drop;
 
 	do {
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c
index 1d0d2417893b04a75ffbe2b2a877b21fcbc318be..c4389b6f8d29105e2f842c39f34cbdfc7bd50a31 100644
--- a/net/ipv4/xfrm4_tunnel.c
+++ b/net/ipv4/xfrm4_tunnel.c
@@ -83,31 +83,8 @@ static int ipip_output(struct sk_buff *skb)
 	return err;
 }
 
-static inline void ipip_ecn_decapsulate(struct iphdr *outer_iph, struct sk_buff *skb)
-{
-	struct iphdr *inner_iph = skb->nh.iph;
-
-	if (INET_ECN_is_ce(outer_iph->tos) &&
-	    INET_ECN_is_not_ce(inner_iph->tos))
-		IP_ECN_set_ce(inner_iph);
-}
-
 static int ipip_xfrm_rcv(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
 {
-	struct iphdr *outer_iph = skb->nh.iph;
-
-	if (!pskb_may_pull(skb, sizeof(struct iphdr)))
-		return -EINVAL;
-	skb->mac.raw = skb->nh.raw;
-	skb->nh.raw = skb->data;
-	memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
-	dst_release(skb->dst);
-	skb->dst = NULL;
-	skb->protocol = htons(ETH_P_IP);
-	skb->pkt_type = PACKET_HOST;
-	ipip_ecn_decapsulate(outer_iph, skb);
-	netif_rx(skb);
-
 	return 0;
 }
 
@@ -149,46 +126,12 @@ int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler)
 static int ipip_rcv(struct sk_buff *skb)
 {
 	struct xfrm_tunnel *handler = ipip_handler;
-	struct xfrm_state *x = NULL;
-	int err;
 
 	/* Tunnel devices take precedence.  */
-	if (handler) {
-		err = handler->handler(skb);
-		if (!err)
-			goto out;
-	}
+	if (handler && handler->handler(skb) == 0)
+		return 0;
 
-	x = xfrm_state_lookup((xfrm_address_t *)&skb->nh.iph->daddr,
-			      skb->nh.iph->saddr,
-			      IPPROTO_IPIP, AF_INET);
-
-	if (!x)
-		goto drop;
-
-	spin_lock(&x->lock);
-
-	if (unlikely(x->km.state != XFRM_STATE_VALID))
-		goto drop_unlock;
-
-	err = ipip_xfrm_rcv(x, NULL, skb);
-	if (err)
-		goto drop_unlock;
-
-	x->curlft.bytes += skb->len;
-	x->curlft.packets++;
-	spin_unlock(&x->lock);
-	xfrm_state_put(x);
-out:	
-	return err;
-
-drop_unlock:
-	spin_unlock(&x->lock);
-	xfrm_state_put(x);
-drop:
-	err = NET_RX_DROP;
-	kfree_skb(skb);
-	goto out;
+	return xfrm4_rcv_encap(skb, 0);
 }
 
 static void ipip_err(struct sk_buff *skb, u32 info)
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index 07d92a2e48a3f8a7a532bfbeae297f04419f1bbb..c13efb13eaf9c888f0944f2b4b24b0a76191f251 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -265,13 +265,12 @@ int ah6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_bu
 	 * There is offset of AH before IPv6 header after the process.
 	 */
 
-	struct ipv6hdr *iph = skb->nh.ipv6h;
 	struct ipv6_auth_hdr *ah;
 	struct ah_data *ahp;
 	unsigned char *tmp_hdr = NULL;
-	u16 hdr_len = skb->data - skb->nh.raw;
+	u16 hdr_len;
 	u16 ah_hlen;
-	u16 cleared_hlen = hdr_len;
+	u16 cleared_hlen;
 	u16 nh_offset = 0;
 	u8 nexthdr = 0;
 	u8 *prevhdr;
@@ -279,6 +278,14 @@ int ah6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_bu
 	if (!pskb_may_pull(skb, sizeof(struct ip_auth_hdr)))
 		goto out;
 
+	/* We are going to _remove_ AH header to keep sockets happy,
+	 * so... Later this can change. */
+	if (skb_cloned(skb) &&
+	    pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
+		goto out;
+
+	hdr_len = skb->data - skb->nh.raw;
+	cleared_hlen = hdr_len;
 	ah = (struct ipv6_auth_hdr*)skb->data;
 	ahp = x->data;
 	nexthdr = ah->nexthdr;
@@ -297,27 +304,22 @@ int ah6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_bu
 	if (!pskb_may_pull(skb, ah_hlen))
 		goto out;
 
-	/* We are going to _remove_ AH header to keep sockets happy,
-	 * so... Later this can change. */
-	if (skb_cloned(skb) &&
-	    pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
-		goto out;
-
 	tmp_hdr = kmalloc(cleared_hlen, GFP_ATOMIC);
 	if (!tmp_hdr)
 		goto out;
 	memcpy(tmp_hdr, skb->nh.raw, cleared_hlen);
 	ipv6_clear_mutable_options(skb, &nh_offset, XFRM_POLICY_IN);
-	iph->priority    = 0;
-	iph->flow_lbl[0] = 0;
-	iph->flow_lbl[1] = 0;
-	iph->flow_lbl[2] = 0;
-	iph->hop_limit   = 0;
+	skb->nh.ipv6h->priority    = 0;
+	skb->nh.ipv6h->flow_lbl[0] = 0;
+	skb->nh.ipv6h->flow_lbl[1] = 0;
+	skb->nh.ipv6h->flow_lbl[2] = 0;
+	skb->nh.ipv6h->hop_limit   = 0;
 
         {
 		u8 auth_data[ahp->icv_trunc_len];
 
 		memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len);
+		memset(ah->auth_data, 0, ahp->icv_trunc_len);
 		skb_push(skb, skb->data - skb->nh.raw);
 		ahp->icv(ahp, skb, ah->auth_data);
 		if (memcmp(ah->auth_data, auth_data, ahp->icv_trunc_len)) {
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 727b681325aa76b6a8004e6e60d700f90e1e93d3..cbf54afae93b3d6ebf1ce1be89a98c9847c714f5 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -355,8 +355,8 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
 	if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
 		fl.oif = np->mcast_oif;
 
-	err = ip6_dst_lookup(sk, &dst, &fl);
-	if (err) goto out;
+	dst = ip6_dst_lookup(sk, &fl);
+	if (dst->error) goto out;
 
 	if (hlimit < 0) {
 		if (ipv6_addr_is_multicast(&fl.fl6_dst))
@@ -434,9 +434,9 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
 	if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
 		fl.oif = np->mcast_oif;
 
-	err = ip6_dst_lookup(sk, &dst, &fl);
+	dst = ip6_dst_lookup(sk, &fl);
 
-	if (err) goto out;
+	if (dst->error) goto out;
 
 	if (hlimit < 0) {
 		if (ipv6_addr_is_multicast(&fl.fl6_dst))
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 6a5eaec0c3bdcbb4fc05e7ebc6452a1e2761c25b..840d4117d4198a1acda46e6b66592311ed514e22 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -209,11 +209,6 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
 	int seg_len = skb->len;
 	int hlimit;
 	u32 mtu;
-	int err = 0;
-
-	if ((err = xfrm_lookup(&skb->dst, fl, sk, 0)) < 0) {
-		return err;
-	}
 
 	if (opt) {
 		int head_room;
@@ -1141,72 +1136,73 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
 	return err;
 }
 
-int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl)
+struct dst_entry *ip6_dst_lookup(struct sock *sk, struct flowi *fl)
 {
-	struct ipv6_pinfo *np = inet6_sk(sk);
+	struct dst_entry *dst = NULL;
 	int err = 0;
 
-	*dst = __sk_dst_check(sk, np->dst_cookie);
-	if (*dst) {
-		struct rt6_info *rt = (struct rt6_info*)*dst;
-
-			/* Yes, checking route validity in not connected
-			   case is not very simple. Take into account,
-			   that we do not support routing by source, TOS,
-			   and MSG_DONTROUTE 		--ANK (980726)
-
-			   1. If route was host route, check that
-			      cached destination is current.
-			      If it is network route, we still may
-			      check its validity using saved pointer
-			      to the last used address: daddr_cache.
-			      We do not want to save whole address now,
-			      (because main consumer of this service
-			       is tcp, which has not this problem),
-			      so that the last trick works only on connected
-			      sockets.
-			   2. oif also should be the same.
-			 */
-
-		if (((rt->rt6i_dst.plen != 128 ||
-		      ipv6_addr_cmp(&fl->fl6_dst, &rt->rt6i_dst.addr))
-		     && (np->daddr_cache == NULL ||
-			 ipv6_addr_cmp(&fl->fl6_dst, np->daddr_cache)))
-		    || (fl->oif && fl->oif != (*dst)->dev->ifindex)) {
-			*dst = NULL;
-		} else
-			dst_hold(*dst);
+	if (sk) {
+		struct ipv6_pinfo *np = inet6_sk(sk);
+	
+		dst = __sk_dst_check(sk, np->dst_cookie);
+		if (dst) {
+			struct rt6_info *rt = (struct rt6_info*)dst;
+	
+				/* Yes, checking route validity in not connected
+				   case is not very simple. Take into account,
+				   that we do not support routing by source, TOS,
+				   and MSG_DONTROUTE 		--ANK (980726)
+	
+				   1. If route was host route, check that
+				      cached destination is current.
+				      If it is network route, we still may
+				      check its validity using saved pointer
+				      to the last used address: daddr_cache.
+				      We do not want to save whole address now,
+				      (because main consumer of this service
+				       is tcp, which has not this problem),
+				      so that the last trick works only on connected
+				      sockets.
+				   2. oif also should be the same.
+				 */
+	
+			if (((rt->rt6i_dst.plen != 128 ||
+			      ipv6_addr_cmp(&fl->fl6_dst, &rt->rt6i_dst.addr))
+			     && (np->daddr_cache == NULL ||
+				 ipv6_addr_cmp(&fl->fl6_dst, np->daddr_cache)))
+			    || (fl->oif && fl->oif != dst->dev->ifindex)) {
+				dst = NULL;
+			} else
+				dst_hold(dst);
+		}
 	}
 
-	if (*dst == NULL)
-		*dst = ip6_route_output(sk, fl);
+	if (dst == NULL)
+		dst = ip6_route_output(sk, fl);
 
-	if ((*dst)->error) {
-		IP6_INC_STATS(Ip6OutNoRoutes);
-		dst_release(*dst);
-		return -ENETUNREACH;
-	}
+	if (dst->error)
+		return dst;
 
 	if (ipv6_addr_any(&fl->fl6_src)) {
-		err = ipv6_get_saddr(*dst, &fl->fl6_dst, &fl->fl6_src);
+		err = ipv6_get_saddr(dst, &fl->fl6_dst, &fl->fl6_src);
 
 		if (err) {
 #if IP6_DEBUG >= 2
 			printk(KERN_DEBUG "ip6_build_xmit: "
 			       "no available source address\n");
 #endif
-			return err;
+			dst->error = err;
+			return dst;
 		}
 	}
 
-        if (*dst) {
-		if ((err = xfrm_lookup(dst, fl, sk, 0)) < 0) {
-			dst_release(*dst);	
-			return -ENETUNREACH;
+        if (dst) {
+		if ((err = xfrm_lookup(&dst, fl, sk, 0)) < 0) {
+			dst->error = -ENETUNREACH;
 		}
         }
 
-	return 0;
+	return dst;
 }
 
 int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb),
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 221a1dd22cbcf6867a09c406d253de67aa3ef8af..8aff8d51527eba978fb6c4b583abda28f3943f45 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -621,6 +621,14 @@ merge_options(struct sock *sk, __u8 encap_limit,
 	return opt;
 }
 
+static int 
+ip6ip6_getfrag(void *from, char *to, int offset, int len, int odd, 
+		struct sk_buff *skb)
+{
+	memcpy(to, (char *) from + offset, len);
+	return 0;
+}
+
 /**
  * ip6ip6_tnl_addr_conflict - compare packet addresses to tunnel's own
  *   @t: the outgoing tunnel device
@@ -755,9 +763,9 @@ int ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
 	}
 	if (skb->len > mtu) {
 		icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev);
-		goto tx_err_opt_release;
+		goto tx_err_dst_release;
 	}
-	err = ip6_append_data(sk, ip_generic_getfrag, skb->nh.raw, skb->len, 0,
+	err = ip6_append_data(sk, ip6ip6_getfrag, skb->nh.raw, skb->len, 0,
 			      t->parms.hop_limit, opt, &fl, 
 			      (struct rt6_info *)dst, MSG_DONTWAIT);
 
@@ -785,7 +793,6 @@ int ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
 	return 0;
 tx_err_dst_release:
 	dst_release(dst);
-tx_err_opt_release:
 	if (opt && opt != orig_opt)
 		sock_kfree_s(sk, opt, opt->tot_len);
 tx_err_free_fl_lbl:
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index ac2dbb6d0a0ee97050d0f55b922fead7cb60a4ad..c5d193728e753d2d439cd7bb440ae0d97664db26 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -658,8 +658,8 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg
 	if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
 		fl.oif = np->mcast_oif;
 
-	err = ip6_dst_lookup(sk, &dst, &fl);
-	if (err)
+	dst = ip6_dst_lookup(sk, &fl);
+	if ((err = dst->error))
 		goto out;
 
 	if (hlimit < 0) {
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index e5cd4c3725777559ce25642f8ce58fa5c70f12e3..4d16e99a8e849d7fe73ad45412229ee6a0ea60fe 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -663,7 +663,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
 		ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
 	}
 
-	dst = ip6_route_output(sk, &fl);
+	dst = ip6_dst_lookup(sk, &fl);
 
 	if ((err = dst->error) != 0) {
 		dst_release(dst);
@@ -691,6 +691,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
 	tp->ext_header_len = 0;
 	if (np->opt)
 		tp->ext_header_len = np->opt->opt_flen + np->opt->opt_nflen;
+	tp->ext2_header_len = dst->header_len;
+
 	tp->mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr);
 
 	inet->dport = usin->sin6_port;
@@ -788,7 +790,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 			fl.fl_ip_dport = inet->dport;
 			fl.fl_ip_sport = inet->sport;
 
-			dst = ip6_route_output(sk, &fl);
+			dst = ip6_dst_lookup(sk, &fl);
 		} else
 			dst_hold(dst);
 
@@ -889,7 +891,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct open_request *req,
 			ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
 		}
 
-		dst = ip6_route_output(sk, &fl);
+		dst = ip6_dst_lookup(sk, &fl);
 		if (dst->error)
 			goto done;
 	}
@@ -1018,7 +1020,7 @@ static void tcp_v6_send_reset(struct sk_buff *skb)
 	fl.fl_ip_sport = t1->source;
 
 	/* sk = NULL, but it is safe for now. RST socket required. */
-	buff->dst = ip6_route_output(NULL, &fl);
+	buff->dst = ip6_dst_lookup(NULL, &fl);
 
 	if (buff->dst->error == 0) {
 		ip6_xmit(NULL, buff, &fl, NULL, 0);
@@ -1081,7 +1083,7 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32
 	fl.fl_ip_dport = t1->dest;
 	fl.fl_ip_sport = t1->source;
 
-	buff->dst = ip6_route_output(NULL, &fl);
+	buff->dst = ip6_dst_lookup(NULL, &fl);
 
 	if (buff->dst->error == 0) {
 		ip6_xmit(NULL, buff, &fl, NULL, 0);
@@ -1329,7 +1331,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
 		fl.fl_ip_dport = req->rmt_port;
 		fl.fl_ip_sport = inet_sk(sk)->sport;
 
-		dst = ip6_route_output(sk, &fl);
+		dst = ip6_dst_lookup(sk, &fl);
 	}
 
 	if (dst->error)
@@ -1401,6 +1403,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
 	if (newnp->opt)
 		newtp->ext_header_len = newnp->opt->opt_nflen +
 					newnp->opt->opt_flen;
+	newtp->ext2_header_len = dst->header_len;
 
 	tcp_sync_mss(newsk, dst_pmtu(dst));
 	newtp->advmss = dst_metric(dst, RTAX_ADVMSS);
@@ -1727,7 +1730,7 @@ static int tcp_v6_rebuild_header(struct sock *sk)
 			ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
 		}
 
-		dst = ip6_route_output(sk, &fl);
+		dst = ip6_dst_lookup(sk, &fl);
 
 		if (dst->error) {
 			err = dst->error;
@@ -1770,7 +1773,7 @@ static int tcp_v6_xmit(struct sk_buff *skb, int ipfragok)
 	dst = __sk_dst_check(sk, np->dst_cookie);
 
 	if (dst == NULL) {
-		dst = ip6_route_output(sk, &fl);
+		dst = ip6_dst_lookup(sk, &fl);
 
 		if (dst->error) {
 			sk->sk_err_soft = -dst->error;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 40859abf16008afe17244e023b29e51f0ae4b8b3..699cbc866c77341588ea6774815ede325ea7b82a 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -811,8 +811,10 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg
 		 * The socket lock must be held while it's corked.
 		 */
 		lock_sock(sk);
-		if (likely(up->pending))
+		if (likely(up->pending)) {
+			dst = NULL;
 			goto do_append_data;
+		}
 		release_sock(sk);
 	}
 	ulen += sizeof(struct udphdr);
@@ -928,8 +930,8 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg
 	if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
 		fl.oif = np->mcast_oif;
 
-	err = ip6_dst_lookup(sk, &dst, &fl);
-	if (err)
+	dst = ip6_dst_lookup(sk, &fl);
+	if ((err = dst->error))
 		goto out;
 
 	if (hlimit < 0) {
@@ -968,9 +970,10 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg
 	else if (!corkreq)
 		err = udp_v6_push_pending_frames(sk, up);
 
-	ip6_dst_store(sk, dst,
-		      !ipv6_addr_cmp(&fl.fl6_dst, &np->daddr) ?
-		      &np->daddr : NULL);
+	if (dst)
+		ip6_dst_store(sk, dst,
+			      !ipv6_addr_cmp(&fl.fl6_dst, &np->daddr) ?
+			      &np->daddr : NULL);
 	if (err > 0)
 		err = np->recverr ? net_xmit_errno(err) : 0;
 	release_sock(sk);
diff --git a/net/netsyms.c b/net/netsyms.c
index 78efec6ffb8944c4afab0a76a9fea2fc7b903dcc..9374929b8592dcd65b77cedbd8620c1b99cabc5e 100644
--- a/net/netsyms.c
+++ b/net/netsyms.c
@@ -482,10 +482,8 @@ EXPORT_SYMBOL(sysctl_tcp_tw_recycle);
 EXPORT_SYMBOL(sysctl_max_syn_backlog);
 #endif
 
-#endif
-
-#if defined (CONFIG_IPV6_MODULE) || defined (CONFIG_IP_SCTP_MODULE) || defined (CONFIG_IPV6_TUNNEL_MODULE)
 EXPORT_SYMBOL(ip_generic_getfrag);
+
 #endif
 
 EXPORT_SYMBOL(tcp_read_sock);
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index b1c87c9924f20948ba1efd3404219ab2091d8b0b..049c7c833d955b534dc2b6e43ba81a2b2d02f47a 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -527,7 +527,7 @@ static int verify_newpolicy_info(struct xfrm_userpolicy_info *p)
 		return -EINVAL;
 	};
 
-	switch (p->family) {
+	switch (p->sel.family) {
 	case AF_INET:
 		break;
 
@@ -594,7 +594,7 @@ static void copy_from_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy
 	memcpy(&xp->lft, &p->lft, sizeof(xp->lft));
 	xp->action = p->action;
 	xp->flags = p->flags;
-	xp->family = p->family;
+	xp->family = p->sel.family;
 	/* XXX xp->share = p->share; */
 }
 
@@ -605,7 +605,7 @@ static void copy_to_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy_i
 	memcpy(&p->curlft, &xp->curlft, sizeof(p->curlft));
 	p->priority = xp->priority;
 	p->index = xp->index;
-	p->family = xp->family;
+	p->sel.family = xp->family;
 	p->dir = dir;
 	p->action = xp->action;
 	p->flags = xp->flags;