Commit 3111b920 authored by Kazunori Miyazawa's avatar Kazunori Miyazawa Committed by Stephen Hemminger

[IPV6]: Fix authentication error with TCP, with help from Joy Latten (latten@austin.ibm.com).

This patch makes the kernel consider extension header length in a dst.
parent 99c2a902
......@@ -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
......
......@@ -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))
......
......@@ -211,10 +211,6 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
u32 mtu;
int err = 0;
if ((err = xfrm_lookup(&skb->dst, fl, sk, 0)) < 0) {
return err;
}
if (opt) {
int head_room;
......@@ -1141,14 +1137,17 @@ 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;
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,
......@@ -1172,41 +1171,39 @@ int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl)
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;
|| (fl->oif && fl->oif != dst->dev->ifindex)) {
dst = NULL;
} else
dst_hold(*dst);
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),
......
......@@ -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 (dst->error)
goto out;
if (hlimit < 0) {
......
......@@ -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;
......
......@@ -928,8 +928,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 (dst->error)
goto out;
if (hlimit < 0) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment