[IPV6]: Generalise the tcp_v6_lookup routines

In the same way as was done with the v4 counterparts, this will be moved
to inet6_hashtables.c.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Arnaldo Carvalho de Melo 2005-08-12 09:19:38 -03:00 committed by David S. Miller
parent b766b305d3
commit 505cbfc577
5 changed files with 122 additions and 91 deletions

View File

@ -193,6 +193,11 @@ struct inet6_skb_parm {
#define IP6CB(skb) ((struct inet6_skb_parm*)((skb)->cb)) #define IP6CB(skb) ((struct inet6_skb_parm*)((skb)->cb))
static inline int inet6_iif(const struct sk_buff *skb)
{
return IP6CB(skb)->iif;
}
struct tcp6_request_sock { struct tcp6_request_sock {
struct tcp_request_sock req; struct tcp_request_sock req;
struct in6_addr loc_addr; struct in6_addr loc_addr;

View File

@ -0,0 +1,26 @@
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* Authors: Lotsa people, from code originally in tcp
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#ifndef _INET6_HASHTABLES_H
#define _INET6_HASHTABLES_H
#include <linux/types.h>
struct in6_addr;
struct inet_hashinfo;
extern struct sock *inet6_lookup(struct inet_hashinfo *hashinfo,
const struct in6_addr *saddr, const u16 sport,
const struct in6_addr *daddr, const u16 dport,
const int dif);
#endif /* _INET6_HASHTABLES_H */

View File

@ -425,9 +425,6 @@ config IP_TCPDIAG
If unsure, say Y. If unsure, say Y.
config IP_TCPDIAG_IPV6
def_bool (IP_TCPDIAG=y && IPV6=y) || (IP_TCPDIAG=m && IPV6)
config IP_TCPDIAG_DCCP config IP_TCPDIAG_DCCP
def_bool (IP_TCPDIAG=y && IP_DCCP=y) || (IP_TCPDIAG=m && IP_DCCP) def_bool (IP_TCPDIAG=y && IP_DCCP=y) || (IP_TCPDIAG=m && IP_DCCP)

View File

@ -24,6 +24,10 @@
#include <net/tcp.h> #include <net/tcp.h>
#include <net/ipv6.h> #include <net/ipv6.h>
#include <net/inet_common.h> #include <net/inet_common.h>
#include <net/inet_connection_sock.h>
#include <net/inet_hashtables.h>
#include <net/inet_timewait_sock.h>
#include <net/inet6_hashtables.h>
#include <linux/inet.h> #include <linux/inet.h>
#include <linux/stddef.h> #include <linux/stddef.h>
@ -102,7 +106,7 @@ static int tcpdiag_fill(struct sk_buff *skb, struct sock *sk,
r->tcpdiag_wqueue = 0; r->tcpdiag_wqueue = 0;
r->tcpdiag_uid = 0; r->tcpdiag_uid = 0;
r->tcpdiag_inode = 0; r->tcpdiag_inode = 0;
#ifdef CONFIG_IP_TCPDIAG_IPV6 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
if (r->tcpdiag_family == AF_INET6) { if (r->tcpdiag_family == AF_INET6) {
const struct tcp6_timewait_sock *tcp6tw = tcp6_twsk(sk); const struct tcp6_timewait_sock *tcp6tw = tcp6_twsk(sk);
@ -121,7 +125,7 @@ static int tcpdiag_fill(struct sk_buff *skb, struct sock *sk,
r->id.tcpdiag_src[0] = inet->rcv_saddr; r->id.tcpdiag_src[0] = inet->rcv_saddr;
r->id.tcpdiag_dst[0] = inet->daddr; r->id.tcpdiag_dst[0] = inet->daddr;
#ifdef CONFIG_IP_TCPDIAG_IPV6 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
if (r->tcpdiag_family == AF_INET6) { if (r->tcpdiag_family == AF_INET6) {
struct ipv6_pinfo *np = inet6_sk(sk); struct ipv6_pinfo *np = inet6_sk(sk);
@ -196,19 +200,6 @@ nlmsg_failure:
return -1; return -1;
} }
#ifdef CONFIG_IP_TCPDIAG_IPV6
extern struct sock *tcp_v6_lookup(struct in6_addr *saddr, u16 sport,
struct in6_addr *daddr, u16 dport,
int dif);
#else
static inline struct sock *tcp_v6_lookup(struct in6_addr *saddr, u16 sport,
struct in6_addr *daddr, u16 dport,
int dif)
{
return NULL;
}
#endif
static int tcpdiag_get_exact(struct sk_buff *in_skb, const struct nlmsghdr *nlh) static int tcpdiag_get_exact(struct sk_buff *in_skb, const struct nlmsghdr *nlh)
{ {
int err; int err;
@ -225,11 +216,14 @@ static int tcpdiag_get_exact(struct sk_buff *in_skb, const struct nlmsghdr *nlh)
req->id.tcpdiag_dport, req->id.tcpdiag_src[0], req->id.tcpdiag_dport, req->id.tcpdiag_src[0],
req->id.tcpdiag_sport, req->id.tcpdiag_if); req->id.tcpdiag_sport, req->id.tcpdiag_if);
} }
#ifdef CONFIG_IP_TCPDIAG_IPV6 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
else if (req->tcpdiag_family == AF_INET6) { else if (req->tcpdiag_family == AF_INET6) {
sk = tcp_v6_lookup((struct in6_addr*)req->id.tcpdiag_dst, req->id.tcpdiag_dport, sk = inet6_lookup(hashinfo,
(struct in6_addr*)req->id.tcpdiag_src, req->id.tcpdiag_sport, (struct in6_addr*)req->id.tcpdiag_dst,
req->id.tcpdiag_if); req->id.tcpdiag_dport,
(struct in6_addr*)req->id.tcpdiag_src,
req->id.tcpdiag_sport,
req->id.tcpdiag_if);
} }
#endif #endif
else { else {
@ -440,7 +434,7 @@ static int tcpdiag_dump_sock(struct sk_buff *skb, struct sock *sk,
struct inet_sock *inet = inet_sk(sk); struct inet_sock *inet = inet_sk(sk);
entry.family = sk->sk_family; entry.family = sk->sk_family;
#ifdef CONFIG_IP_TCPDIAG_IPV6 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
if (entry.family == AF_INET6) { if (entry.family == AF_INET6) {
struct ipv6_pinfo *np = inet6_sk(sk); struct ipv6_pinfo *np = inet6_sk(sk);
@ -502,7 +496,7 @@ static int tcpdiag_fill_req(struct sk_buff *skb, struct sock *sk,
r->tcpdiag_wqueue = 0; r->tcpdiag_wqueue = 0;
r->tcpdiag_uid = sock_i_uid(sk); r->tcpdiag_uid = sock_i_uid(sk);
r->tcpdiag_inode = 0; r->tcpdiag_inode = 0;
#ifdef CONFIG_IP_TCPDIAG_IPV6 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
if (r->tcpdiag_family == AF_INET6) { if (r->tcpdiag_family == AF_INET6) {
ipv6_addr_copy((struct in6_addr *)r->id.tcpdiag_src, ipv6_addr_copy((struct in6_addr *)r->id.tcpdiag_src,
&tcp6_rsk(req)->loc_addr); &tcp6_rsk(req)->loc_addr);
@ -567,13 +561,13 @@ static int tcpdiag_dump_reqs(struct sk_buff *skb, struct sock *sk,
if (bc) { if (bc) {
entry.saddr = entry.saddr =
#ifdef CONFIG_IP_TCPDIAG_IPV6 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
(entry.family == AF_INET6) ? (entry.family == AF_INET6) ?
tcp6_rsk(req)->loc_addr.s6_addr32 : tcp6_rsk(req)->loc_addr.s6_addr32 :
#endif #endif
&ireq->loc_addr; &ireq->loc_addr;
entry.daddr = entry.daddr =
#ifdef CONFIG_IP_TCPDIAG_IPV6 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
(entry.family == AF_INET6) ? (entry.family == AF_INET6) ?
tcp6_rsk(req)->rmt_addr.s6_addr32 : tcp6_rsk(req)->rmt_addr.s6_addr32 :
#endif #endif

View File

@ -76,26 +76,27 @@ static struct tcp_func ipv6_mapped;
static struct tcp_func ipv6_specific; static struct tcp_func ipv6_specific;
/* I have no idea if this is a good hash for v6 or not. -DaveM */ /* I have no idea if this is a good hash for v6 or not. -DaveM */
static __inline__ int tcp_v6_hashfn(struct in6_addr *laddr, u16 lport, static inline int inet6_ehashfn(const struct in6_addr *laddr, const u16 lport,
struct in6_addr *faddr, u16 fport) const struct in6_addr *faddr, const u16 fport,
const int ehash_size)
{ {
int hashent = (lport ^ fport); int hashent = (lport ^ fport);
hashent ^= (laddr->s6_addr32[3] ^ faddr->s6_addr32[3]); hashent ^= (laddr->s6_addr32[3] ^ faddr->s6_addr32[3]);
hashent ^= hashent>>16; hashent ^= hashent>>16;
hashent ^= hashent>>8; hashent ^= hashent>>8;
return (hashent & (tcp_hashinfo.ehash_size - 1)); return (hashent & (ehash_size - 1));
} }
static __inline__ int tcp_v6_sk_hashfn(struct sock *sk) static inline int inet6_sk_ehashfn(const struct sock *sk, const int ehash_size)
{ {
struct inet_sock *inet = inet_sk(sk); const struct inet_sock *inet = inet_sk(sk);
struct ipv6_pinfo *np = inet6_sk(sk); const struct ipv6_pinfo *np = inet6_sk(sk);
struct in6_addr *laddr = &np->rcv_saddr; const struct in6_addr *laddr = &np->rcv_saddr;
struct in6_addr *faddr = &np->daddr; const struct in6_addr *faddr = &np->daddr;
__u16 lport = inet->num; const __u16 lport = inet->num;
__u16 fport = inet->dport; const __u16 fport = inet->dport;
return tcp_v6_hashfn(laddr, lport, faddr, fport); return inet6_ehashfn(laddr, lport, faddr, fport, ehash_size);
} }
static inline int tcp_v6_bind_conflict(const struct sock *sk, static inline int tcp_v6_bind_conflict(const struct sock *sk,
@ -231,7 +232,7 @@ static __inline__ void __tcp_v6_hash(struct sock *sk)
lock = &tcp_hashinfo.lhash_lock; lock = &tcp_hashinfo.lhash_lock;
inet_listen_wlock(&tcp_hashinfo); inet_listen_wlock(&tcp_hashinfo);
} else { } else {
sk->sk_hashent = tcp_v6_sk_hashfn(sk); sk->sk_hashent = inet6_sk_ehashfn(sk, tcp_hashinfo.ehash_size);
list = &tcp_hashinfo.ehash[sk->sk_hashent].chain; list = &tcp_hashinfo.ehash[sk->sk_hashent].chain;
lock = &tcp_hashinfo.ehash[sk->sk_hashent].lock; lock = &tcp_hashinfo.ehash[sk->sk_hashent].lock;
write_lock(lock); write_lock(lock);
@ -258,7 +259,10 @@ static void tcp_v6_hash(struct sock *sk)
} }
} }
static struct sock *tcp_v6_lookup_listener(struct in6_addr *daddr, unsigned short hnum, int dif) static struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo,
const struct in6_addr *daddr,
const unsigned short hnum,
const int dif)
{ {
struct sock *sk; struct sock *sk;
struct hlist_node *node; struct hlist_node *node;
@ -266,8 +270,8 @@ static struct sock *tcp_v6_lookup_listener(struct in6_addr *daddr, unsigned shor
int score, hiscore; int score, hiscore;
hiscore=0; hiscore=0;
read_lock(&tcp_hashinfo.lhash_lock); read_lock(&hashinfo->lhash_lock);
sk_for_each(sk, node, &tcp_hashinfo.listening_hash[inet_lhashfn(hnum)]) { sk_for_each(sk, node, &hashinfo->listening_hash[inet_lhashfn(hnum)]) {
if (inet_sk(sk)->num == hnum && sk->sk_family == PF_INET6) { if (inet_sk(sk)->num == hnum && sk->sk_family == PF_INET6) {
struct ipv6_pinfo *np = inet6_sk(sk); struct ipv6_pinfo *np = inet6_sk(sk);
@ -294,7 +298,7 @@ static struct sock *tcp_v6_lookup_listener(struct in6_addr *daddr, unsigned shor
} }
if (result) if (result)
sock_hold(result); sock_hold(result);
read_unlock(&tcp_hashinfo.lhash_lock); read_unlock(&hashinfo->lhash_lock);
return result; return result;
} }
@ -304,9 +308,13 @@ static struct sock *tcp_v6_lookup_listener(struct in6_addr *daddr, unsigned shor
* The sockhash lock must be held as a reader here. * The sockhash lock must be held as a reader here.
*/ */
static inline struct sock *__tcp_v6_lookup_established(struct in6_addr *saddr, u16 sport, static inline struct sock *
struct in6_addr *daddr, u16 hnum, __inet6_lookup_established(struct inet_hashinfo *hashinfo,
int dif) const struct in6_addr *saddr,
const u16 sport,
const struct in6_addr *daddr,
const u16 hnum,
const int dif)
{ {
struct sock *sk; struct sock *sk;
const struct hlist_node *node; const struct hlist_node *node;
@ -314,8 +322,9 @@ static inline struct sock *__tcp_v6_lookup_established(struct in6_addr *saddr, u
/* Optimize here for direct hit, only listening connections can /* Optimize here for direct hit, only listening connections can
* have wildcards anyways. * have wildcards anyways.
*/ */
const int hash = tcp_v6_hashfn(daddr, hnum, saddr, sport); const int hash = inet6_ehashfn(daddr, hnum, saddr, sport,
struct inet_ehash_bucket *head = &tcp_hashinfo.ehash[hash]; hashinfo->ehash_size);
struct inet_ehash_bucket *head = &hashinfo->ehash[hash];
read_lock(&head->lock); read_lock(&head->lock);
sk_for_each(sk, node, &head->chain) { sk_for_each(sk, node, &head->chain) {
@ -324,7 +333,7 @@ static inline struct sock *__tcp_v6_lookup_established(struct in6_addr *saddr, u
goto hit; /* You sunk my battleship! */ goto hit; /* You sunk my battleship! */
} }
/* Must check for a TIME_WAIT'er before going to listener hash. */ /* Must check for a TIME_WAIT'er before going to listener hash. */
sk_for_each(sk, node, &(head + tcp_hashinfo.ehash_size)->chain) { sk_for_each(sk, node, &(head + hashinfo->ehash_size)->chain) {
const struct inet_timewait_sock *tw = inet_twsk(sk); const struct inet_timewait_sock *tw = inet_twsk(sk);
if(*((__u32 *)&(tw->tw_dport)) == ports && if(*((__u32 *)&(tw->tw_dport)) == ports &&
@ -347,34 +356,36 @@ hit:
} }
static inline struct sock *__tcp_v6_lookup(struct in6_addr *saddr, u16 sport, static inline struct sock *__inet6_lookup(struct inet_hashinfo *hashinfo,
struct in6_addr *daddr, u16 hnum, const struct in6_addr *saddr,
int dif) const u16 sport,
const struct in6_addr *daddr,
const u16 hnum,
const int dif)
{ {
struct sock *sk; struct sock *sk = __inet6_lookup_established(hashinfo, saddr, sport,
daddr, hnum, dif);
sk = __tcp_v6_lookup_established(saddr, sport, daddr, hnum, dif);
if (sk) if (sk)
return sk; return sk;
return tcp_v6_lookup_listener(daddr, hnum, dif); return inet6_lookup_listener(hashinfo, daddr, hnum, dif);
} }
inline struct sock *tcp_v6_lookup(struct in6_addr *saddr, u16 sport, inline struct sock *inet6_lookup(struct inet_hashinfo *hashinfo,
struct in6_addr *daddr, u16 dport, const struct in6_addr *saddr, const u16 sport,
int dif) const struct in6_addr *daddr, const u16 dport,
const int dif)
{ {
struct sock *sk; struct sock *sk;
local_bh_disable(); local_bh_disable();
sk = __tcp_v6_lookup(saddr, sport, daddr, ntohs(dport), dif); sk = __inet6_lookup(hashinfo, saddr, sport, daddr, ntohs(dport), dif);
local_bh_enable(); local_bh_enable();
return sk; return sk;
} }
EXPORT_SYMBOL_GPL(tcp_v6_lookup); EXPORT_SYMBOL_GPL(inet6_lookup);
/* /*
@ -454,16 +465,17 @@ static __u32 tcp_v6_init_sequence(struct sock *sk, struct sk_buff *skb)
} }
} }
static int __tcp_v6_check_established(struct sock *sk, __u16 lport, static int __tcp_v6_check_established(struct sock *sk, const __u16 lport,
struct inet_timewait_sock **twp) struct inet_timewait_sock **twp)
{ {
struct inet_sock *inet = inet_sk(sk); struct inet_sock *inet = inet_sk(sk);
struct ipv6_pinfo *np = inet6_sk(sk); const struct ipv6_pinfo *np = inet6_sk(sk);
struct in6_addr *daddr = &np->rcv_saddr; const struct in6_addr *daddr = &np->rcv_saddr;
struct in6_addr *saddr = &np->daddr; const struct in6_addr *saddr = &np->daddr;
int dif = sk->sk_bound_dev_if; const int dif = sk->sk_bound_dev_if;
const u32 ports = INET_COMBINED_PORTS(inet->dport, lport); const u32 ports = INET_COMBINED_PORTS(inet->dport, lport);
const int hash = tcp_v6_hashfn(daddr, inet->num, saddr, inet->dport); const int hash = inet6_ehashfn(daddr, inet->num, saddr, inet->dport,
tcp_hashinfo.ehash_size);
struct inet_ehash_bucket *head = &tcp_hashinfo.ehash[hash]; struct inet_ehash_bucket *head = &tcp_hashinfo.ehash[hash];
struct sock *sk2; struct sock *sk2;
const struct hlist_node *node; const struct hlist_node *node;
@ -637,11 +649,6 @@ out:
} }
} }
static __inline__ int tcp_v6_iif(struct sk_buff *skb)
{
return IP6CB(skb)->iif;
}
static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
int addr_len) int addr_len)
{ {
@ -833,14 +840,15 @@ static 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 tcphdr *th = (struct tcphdr *)(skb->data+offset); const struct tcphdr *th = (struct tcphdr *)(skb->data+offset);
struct ipv6_pinfo *np; struct ipv6_pinfo *np;
struct sock *sk; struct sock *sk;
int err; int err;
struct tcp_sock *tp; struct tcp_sock *tp;
__u32 seq; __u32 seq;
sk = tcp_v6_lookup(&hdr->daddr, th->dest, &hdr->saddr, th->source, skb->dev->ifindex); sk = inet6_lookup(&tcp_hashinfo, &hdr->daddr, th->dest, &hdr->saddr,
th->source, skb->dev->ifindex);
if (sk == NULL) { if (sk == NULL) {
ICMP6_INC_STATS_BH(__in6_dev_get(skb->dev), ICMP6_MIB_INERRORS); ICMP6_INC_STATS_BH(__in6_dev_get(skb->dev), ICMP6_MIB_INERRORS);
@ -927,7 +935,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
goto out; goto out;
req = tcp_v6_search_req(sk, &prev, th->dest, &hdr->daddr, req = tcp_v6_search_req(sk, &prev, th->dest, &hdr->daddr,
&hdr->saddr, tcp_v6_iif(skb)); &hdr->saddr, inet6_iif(skb));
if (!req) if (!req)
goto out; goto out;
@ -1138,7 +1146,7 @@ static void tcp_v6_send_reset(struct sk_buff *skb)
buff->csum); buff->csum);
fl.proto = IPPROTO_TCP; fl.proto = IPPROTO_TCP;
fl.oif = tcp_v6_iif(skb); fl.oif = inet6_iif(skb);
fl.fl_ip_dport = t1->dest; fl.fl_ip_dport = t1->dest;
fl.fl_ip_sport = t1->source; fl.fl_ip_sport = t1->source;
@ -1207,7 +1215,7 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32
buff->csum); buff->csum);
fl.proto = IPPROTO_TCP; fl.proto = IPPROTO_TCP;
fl.oif = tcp_v6_iif(skb); fl.oif = inet6_iif(skb);
fl.fl_ip_dport = t1->dest; fl.fl_ip_dport = t1->dest;
fl.fl_ip_sport = t1->source; fl.fl_ip_sport = t1->source;
@ -1245,20 +1253,18 @@ static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req)
static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
{ {
struct request_sock *req, **prev; struct request_sock *req, **prev;
struct tcphdr *th = skb->h.th; const struct tcphdr *th = skb->h.th;
struct sock *nsk; struct sock *nsk;
/* Find possible connection requests. */ /* Find possible connection requests. */
req = tcp_v6_search_req(sk, &prev, th->source, &skb->nh.ipv6h->saddr, req = tcp_v6_search_req(sk, &prev, th->source, &skb->nh.ipv6h->saddr,
&skb->nh.ipv6h->daddr, tcp_v6_iif(skb)); &skb->nh.ipv6h->daddr, inet6_iif(skb));
if (req) if (req)
return tcp_check_req(sk, skb, req, prev); return tcp_check_req(sk, skb, req, prev);
nsk = __tcp_v6_lookup_established(&skb->nh.ipv6h->saddr, nsk = __inet6_lookup_established(&tcp_hashinfo, &skb->nh.ipv6h->saddr,
th->source, th->source, &skb->nh.ipv6h->daddr,
&skb->nh.ipv6h->daddr, ntohs(th->dest), inet6_iif(skb));
ntohs(th->dest),
tcp_v6_iif(skb));
if (nsk) { if (nsk) {
if (nsk->sk_state != TCP_TIME_WAIT) { if (nsk->sk_state != TCP_TIME_WAIT) {
@ -1346,7 +1352,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
/* So that link locals have meaning */ /* So that link locals have meaning */
if (!sk->sk_bound_dev_if && if (!sk->sk_bound_dev_if &&
ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL) ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL)
treq->iif = tcp_v6_iif(skb); treq->iif = inet6_iif(skb);
if (isn == 0) if (isn == 0)
isn = tcp_v6_init_sequence(sk,skb); isn = tcp_v6_init_sequence(sk,skb);
@ -1411,7 +1417,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
newsk->sk_backlog_rcv = tcp_v4_do_rcv; newsk->sk_backlog_rcv = tcp_v4_do_rcv;
newnp->pktoptions = NULL; newnp->pktoptions = NULL;
newnp->opt = NULL; newnp->opt = NULL;
newnp->mcast_oif = tcp_v6_iif(skb); newnp->mcast_oif = inet6_iif(skb);
newnp->mcast_hops = skb->nh.ipv6h->hop_limit; newnp->mcast_hops = skb->nh.ipv6h->hop_limit;
/* /*
@ -1516,7 +1522,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
skb_set_owner_r(newnp->pktoptions, newsk); skb_set_owner_r(newnp->pktoptions, newsk);
} }
newnp->opt = NULL; newnp->opt = NULL;
newnp->mcast_oif = tcp_v6_iif(skb); newnp->mcast_oif = inet6_iif(skb);
newnp->mcast_hops = skb->nh.ipv6h->hop_limit; newnp->mcast_hops = skb->nh.ipv6h->hop_limit;
/* Clone native IPv6 options from listening socket (if any) /* Clone native IPv6 options from listening socket (if any)
@ -1691,7 +1697,7 @@ ipv6_pktoptions:
if (TCP_SKB_CB(opt_skb)->end_seq == tp->rcv_nxt && if (TCP_SKB_CB(opt_skb)->end_seq == tp->rcv_nxt &&
!((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN))) { !((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN))) {
if (np->rxopt.bits.rxinfo) if (np->rxopt.bits.rxinfo)
np->mcast_oif = tcp_v6_iif(opt_skb); np->mcast_oif = inet6_iif(opt_skb);
if (np->rxopt.bits.rxhlim) if (np->rxopt.bits.rxhlim)
np->mcast_hops = opt_skb->nh.ipv6h->hop_limit; np->mcast_hops = opt_skb->nh.ipv6h->hop_limit;
if (ipv6_opt_accepted(sk, opt_skb)) { if (ipv6_opt_accepted(sk, opt_skb)) {
@ -1746,8 +1752,9 @@ static int tcp_v6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(skb->nh.ipv6h); TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(skb->nh.ipv6h);
TCP_SKB_CB(skb)->sacked = 0; TCP_SKB_CB(skb)->sacked = 0;
sk = __tcp_v6_lookup(&skb->nh.ipv6h->saddr, th->source, sk = __inet6_lookup(&tcp_hashinfo, &skb->nh.ipv6h->saddr, th->source,
&skb->nh.ipv6h->daddr, ntohs(th->dest), tcp_v6_iif(skb)); &skb->nh.ipv6h->daddr, ntohs(th->dest),
inet6_iif(skb));
if (!sk) if (!sk)
goto no_tcp_socket; goto no_tcp_socket;
@ -1818,7 +1825,9 @@ do_time_wait:
{ {
struct sock *sk2; struct sock *sk2;
sk2 = tcp_v6_lookup_listener(&skb->nh.ipv6h->daddr, ntohs(th->dest), tcp_v6_iif(skb)); sk2 = inet6_lookup_listener(&tcp_hashinfo,
&skb->nh.ipv6h->daddr,
ntohs(th->dest), inet6_iif(skb));
if (sk2 != NULL) { if (sk2 != NULL) {
struct inet_timewait_sock *tw = inet_twsk(sk); struct inet_timewait_sock *tw = inet_twsk(sk);
inet_twsk_deschedule(tw, &tcp_death_row); inet_twsk_deschedule(tw, &tcp_death_row);