Commit 00d67c5a authored by Alexey Kuznetsov's avatar Alexey Kuznetsov Committed by David S. Miller

TCP ipv6 fixes:

- Fix open_request lookup bug that was already fixed in ipv4
parent 75669bcc
...@@ -377,22 +377,22 @@ static __inline__ unsigned tcp_v6_synq_hash(struct in6_addr *raddr, u16 rport) ...@@ -377,22 +377,22 @@ static __inline__ unsigned tcp_v6_synq_hash(struct in6_addr *raddr, u16 rport)
} }
static struct open_request *tcp_v6_search_req(struct tcp_opt *tp, static struct open_request *tcp_v6_search_req(struct tcp_opt *tp,
struct ipv6hdr *ip6h, struct open_request ***prevp,
struct tcphdr *th, __u16 rport,
int iif, struct in6_addr *raddr,
struct open_request ***prevp) struct in6_addr *laddr,
int iif)
{ {
struct tcp_listen_opt *lopt = tp->listen_opt; struct tcp_listen_opt *lopt = tp->listen_opt;
struct open_request *req, **prev; struct open_request *req, **prev;
__u16 rport = th->source;
for (prev = &lopt->syn_table[tcp_v6_synq_hash(&ip6h->saddr, rport)]; for (prev = &lopt->syn_table[tcp_v6_synq_hash(raddr, rport)];
(req = *prev) != NULL; (req = *prev) != NULL;
prev = &req->dl_next) { prev = &req->dl_next) {
if (req->rmt_port == rport && if (req->rmt_port == rport &&
req->class->family == AF_INET6 && req->class->family == AF_INET6 &&
!ipv6_addr_cmp(&req->af.v6_req.rmt_addr, &ip6h->saddr) && !ipv6_addr_cmp(&req->af.v6_req.rmt_addr, raddr) &&
!ipv6_addr_cmp(&req->af.v6_req.loc_addr, &ip6h->daddr) && !ipv6_addr_cmp(&req->af.v6_req.loc_addr, laddr) &&
(!req->af.v6_req.iif || req->af.v6_req.iif == iif)) { (!req->af.v6_req.iif || req->af.v6_req.iif == iif)) {
BUG_TRAP(req->sk == NULL); BUG_TRAP(req->sk == NULL);
*prevp = prev; *prevp = prev;
...@@ -708,8 +708,6 @@ void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, ...@@ -708,8 +708,6 @@ void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
int type, int code, int offset, __u32 info) int type, int code, int offset, __u32 info)
{ {
struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data; struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data;
struct in6_addr *saddr = &hdr->saddr;
struct in6_addr *daddr = &hdr->daddr;
struct tcphdr *th = (struct tcphdr *)(skb->data+offset); struct tcphdr *th = (struct tcphdr *)(skb->data+offset);
struct ipv6_pinfo *np; struct ipv6_pinfo *np;
struct sock *sk; struct sock *sk;
...@@ -717,7 +715,7 @@ void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, ...@@ -717,7 +715,7 @@ void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
struct tcp_opt *tp; struct tcp_opt *tp;
__u32 seq; __u32 seq;
sk = tcp_v6_lookup(daddr, th->dest, saddr, th->source, skb->dev->ifindex); sk = tcp_v6_lookup(&hdr->daddr, th->dest, &hdr->saddr, th->source, skb->dev->ifindex);
if (sk == NULL) { if (sk == NULL) {
ICMP6_INC_STATS_BH(Icmp6InErrors); ICMP6_INC_STATS_BH(Icmp6InErrors);
...@@ -790,15 +788,12 @@ void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, ...@@ -790,15 +788,12 @@ void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
/* Might be for an open_request */ /* Might be for an open_request */
switch (sk->state) { switch (sk->state) {
struct open_request *req, **prev; struct open_request *req, **prev;
struct ipv6hdr hd;
case TCP_LISTEN: case TCP_LISTEN:
if (sk->lock.users) if (sk->lock.users)
goto out; goto out;
/* Grrrr - fix this later. */ req = tcp_v6_search_req(tp, &prev, th->dest, &hdr->daddr,
ipv6_addr_copy(&hd.saddr, saddr); &hdr->saddr, tcp_v6_iif(skb));
ipv6_addr_copy(&hd.daddr, daddr);
req = tcp_v6_search_req(tp, &hd, th, tcp_v6_iif(skb), &prev);
if (!req) if (!req)
goto out; goto out;
...@@ -1107,7 +1102,8 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) ...@@ -1107,7 +1102,8 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
struct sock *nsk; struct sock *nsk;
/* Find possible connection requests. */ /* Find possible connection requests. */
req = tcp_v6_search_req(tp, skb->nh.ipv6h, th, tcp_v6_iif(skb), &prev); req = tcp_v6_search_req(tp, &prev, th->source, &skb->nh.ipv6h->saddr,
&skb->nh.ipv6h->daddr, tcp_v6_iif(skb));
if (req) if (req)
return tcp_check_req(sk, skb, req, prev); return tcp_check_req(sk, skb, req, prev);
......
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