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;