diff options
-rw-r--r-- | include/linux/ipv6.h | 5 | ||||
-rw-r--r-- | include/net/inet6_hashtables.h | 26 | ||||
-rw-r--r-- | net/ipv4/Kconfig | 3 | ||||
-rw-r--r-- | net/ipv4/tcp_diag.c | 40 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 139 |
5 files changed, 122 insertions, 91 deletions
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index 777339b68464..3c7dbc6a0a70 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h | |||
@@ -193,6 +193,11 @@ struct inet6_skb_parm { | |||
193 | 193 | ||
194 | #define IP6CB(skb) ((struct inet6_skb_parm*)((skb)->cb)) | 194 | #define IP6CB(skb) ((struct inet6_skb_parm*)((skb)->cb)) |
195 | 195 | ||
196 | static inline int inet6_iif(const struct sk_buff *skb) | ||
197 | { | ||
198 | return IP6CB(skb)->iif; | ||
199 | } | ||
200 | |||
196 | struct tcp6_request_sock { | 201 | struct tcp6_request_sock { |
197 | struct tcp_request_sock req; | 202 | struct tcp_request_sock req; |
198 | struct in6_addr loc_addr; | 203 | struct in6_addr loc_addr; |
diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h new file mode 100644 index 000000000000..297c2b16967a --- /dev/null +++ b/include/net/inet6_hashtables.h | |||
@@ -0,0 +1,26 @@ | |||
1 | /* | ||
2 | * INET An implementation of the TCP/IP protocol suite for the LINUX | ||
3 | * operating system. INET is implemented using the BSD Socket | ||
4 | * interface as the means of communication with the user level. | ||
5 | * | ||
6 | * Authors: Lotsa people, from code originally in tcp | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version | ||
11 | * 2 of the License, or (at your option) any later version. | ||
12 | */ | ||
13 | |||
14 | #ifndef _INET6_HASHTABLES_H | ||
15 | #define _INET6_HASHTABLES_H | ||
16 | |||
17 | #include <linux/types.h> | ||
18 | |||
19 | struct in6_addr; | ||
20 | struct inet_hashinfo; | ||
21 | |||
22 | extern struct sock *inet6_lookup(struct inet_hashinfo *hashinfo, | ||
23 | const struct in6_addr *saddr, const u16 sport, | ||
24 | const struct in6_addr *daddr, const u16 dport, | ||
25 | const int dif); | ||
26 | #endif /* _INET6_HASHTABLES_H */ | ||
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index c844954c1ad5..a79b4f9c10c5 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig | |||
@@ -425,9 +425,6 @@ config IP_TCPDIAG | |||
425 | 425 | ||
426 | If unsure, say Y. | 426 | If unsure, say Y. |
427 | 427 | ||
428 | config IP_TCPDIAG_IPV6 | ||
429 | def_bool (IP_TCPDIAG=y && IPV6=y) || (IP_TCPDIAG=m && IPV6) | ||
430 | |||
431 | config IP_TCPDIAG_DCCP | 428 | config IP_TCPDIAG_DCCP |
432 | def_bool (IP_TCPDIAG=y && IP_DCCP=y) || (IP_TCPDIAG=m && IP_DCCP) | 429 | def_bool (IP_TCPDIAG=y && IP_DCCP=y) || (IP_TCPDIAG=m && IP_DCCP) |
433 | 430 | ||
diff --git a/net/ipv4/tcp_diag.c b/net/ipv4/tcp_diag.c index 8bf495c698f8..b812191b2f5c 100644 --- a/net/ipv4/tcp_diag.c +++ b/net/ipv4/tcp_diag.c | |||
@@ -24,6 +24,10 @@ | |||
24 | #include <net/tcp.h> | 24 | #include <net/tcp.h> |
25 | #include <net/ipv6.h> | 25 | #include <net/ipv6.h> |
26 | #include <net/inet_common.h> | 26 | #include <net/inet_common.h> |
27 | #include <net/inet_connection_sock.h> | ||
28 | #include <net/inet_hashtables.h> | ||
29 | #include <net/inet_timewait_sock.h> | ||
30 | #include <net/inet6_hashtables.h> | ||
27 | 31 | ||
28 | #include <linux/inet.h> | 32 | #include <linux/inet.h> |
29 | #include <linux/stddef.h> | 33 | #include <linux/stddef.h> |
@@ -102,7 +106,7 @@ static int tcpdiag_fill(struct sk_buff *skb, struct sock *sk, | |||
102 | r->tcpdiag_wqueue = 0; | 106 | r->tcpdiag_wqueue = 0; |
103 | r->tcpdiag_uid = 0; | 107 | r->tcpdiag_uid = 0; |
104 | r->tcpdiag_inode = 0; | 108 | r->tcpdiag_inode = 0; |
105 | #ifdef CONFIG_IP_TCPDIAG_IPV6 | 109 | #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) |
106 | if (r->tcpdiag_family == AF_INET6) { | 110 | if (r->tcpdiag_family == AF_INET6) { |
107 | const struct tcp6_timewait_sock *tcp6tw = tcp6_twsk(sk); | 111 | const struct tcp6_timewait_sock *tcp6tw = tcp6_twsk(sk); |
108 | 112 | ||
@@ -121,7 +125,7 @@ static int tcpdiag_fill(struct sk_buff *skb, struct sock *sk, | |||
121 | r->id.tcpdiag_src[0] = inet->rcv_saddr; | 125 | r->id.tcpdiag_src[0] = inet->rcv_saddr; |
122 | r->id.tcpdiag_dst[0] = inet->daddr; | 126 | r->id.tcpdiag_dst[0] = inet->daddr; |
123 | 127 | ||
124 | #ifdef CONFIG_IP_TCPDIAG_IPV6 | 128 | #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) |
125 | if (r->tcpdiag_family == AF_INET6) { | 129 | if (r->tcpdiag_family == AF_INET6) { |
126 | struct ipv6_pinfo *np = inet6_sk(sk); | 130 | struct ipv6_pinfo *np = inet6_sk(sk); |
127 | 131 | ||
@@ -196,19 +200,6 @@ nlmsg_failure: | |||
196 | return -1; | 200 | return -1; |
197 | } | 201 | } |
198 | 202 | ||
199 | #ifdef CONFIG_IP_TCPDIAG_IPV6 | ||
200 | extern struct sock *tcp_v6_lookup(struct in6_addr *saddr, u16 sport, | ||
201 | struct in6_addr *daddr, u16 dport, | ||
202 | int dif); | ||
203 | #else | ||
204 | static inline struct sock *tcp_v6_lookup(struct in6_addr *saddr, u16 sport, | ||
205 | struct in6_addr *daddr, u16 dport, | ||
206 | int dif) | ||
207 | { | ||
208 | return NULL; | ||
209 | } | ||
210 | #endif | ||
211 | |||
212 | static int tcpdiag_get_exact(struct sk_buff *in_skb, const struct nlmsghdr *nlh) | 203 | static int tcpdiag_get_exact(struct sk_buff *in_skb, const struct nlmsghdr *nlh) |
213 | { | 204 | { |
214 | int err; | 205 | int err; |
@@ -225,11 +216,14 @@ static int tcpdiag_get_exact(struct sk_buff *in_skb, const struct nlmsghdr *nlh) | |||
225 | req->id.tcpdiag_dport, req->id.tcpdiag_src[0], | 216 | req->id.tcpdiag_dport, req->id.tcpdiag_src[0], |
226 | req->id.tcpdiag_sport, req->id.tcpdiag_if); | 217 | req->id.tcpdiag_sport, req->id.tcpdiag_if); |
227 | } | 218 | } |
228 | #ifdef CONFIG_IP_TCPDIAG_IPV6 | 219 | #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) |
229 | else if (req->tcpdiag_family == AF_INET6) { | 220 | else if (req->tcpdiag_family == AF_INET6) { |
230 | sk = tcp_v6_lookup((struct in6_addr*)req->id.tcpdiag_dst, req->id.tcpdiag_dport, | 221 | sk = inet6_lookup(hashinfo, |
231 | (struct in6_addr*)req->id.tcpdiag_src, req->id.tcpdiag_sport, | 222 | (struct in6_addr*)req->id.tcpdiag_dst, |
232 | req->id.tcpdiag_if); | 223 | req->id.tcpdiag_dport, |
224 | (struct in6_addr*)req->id.tcpdiag_src, | ||
225 | req->id.tcpdiag_sport, | ||
226 | req->id.tcpdiag_if); | ||
233 | } | 227 | } |
234 | #endif | 228 | #endif |
235 | else { | 229 | else { |
@@ -440,7 +434,7 @@ static int tcpdiag_dump_sock(struct sk_buff *skb, struct sock *sk, | |||
440 | struct inet_sock *inet = inet_sk(sk); | 434 | struct inet_sock *inet = inet_sk(sk); |
441 | 435 | ||
442 | entry.family = sk->sk_family; | 436 | entry.family = sk->sk_family; |
443 | #ifdef CONFIG_IP_TCPDIAG_IPV6 | 437 | #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) |
444 | if (entry.family == AF_INET6) { | 438 | if (entry.family == AF_INET6) { |
445 | struct ipv6_pinfo *np = inet6_sk(sk); | 439 | struct ipv6_pinfo *np = inet6_sk(sk); |
446 | 440 | ||
@@ -502,7 +496,7 @@ static int tcpdiag_fill_req(struct sk_buff *skb, struct sock *sk, | |||
502 | r->tcpdiag_wqueue = 0; | 496 | r->tcpdiag_wqueue = 0; |
503 | r->tcpdiag_uid = sock_i_uid(sk); | 497 | r->tcpdiag_uid = sock_i_uid(sk); |
504 | r->tcpdiag_inode = 0; | 498 | r->tcpdiag_inode = 0; |
505 | #ifdef CONFIG_IP_TCPDIAG_IPV6 | 499 | #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) |
506 | if (r->tcpdiag_family == AF_INET6) { | 500 | if (r->tcpdiag_family == AF_INET6) { |
507 | ipv6_addr_copy((struct in6_addr *)r->id.tcpdiag_src, | 501 | ipv6_addr_copy((struct in6_addr *)r->id.tcpdiag_src, |
508 | &tcp6_rsk(req)->loc_addr); | 502 | &tcp6_rsk(req)->loc_addr); |
@@ -567,13 +561,13 @@ static int tcpdiag_dump_reqs(struct sk_buff *skb, struct sock *sk, | |||
567 | 561 | ||
568 | if (bc) { | 562 | if (bc) { |
569 | entry.saddr = | 563 | entry.saddr = |
570 | #ifdef CONFIG_IP_TCPDIAG_IPV6 | 564 | #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) |
571 | (entry.family == AF_INET6) ? | 565 | (entry.family == AF_INET6) ? |
572 | tcp6_rsk(req)->loc_addr.s6_addr32 : | 566 | tcp6_rsk(req)->loc_addr.s6_addr32 : |
573 | #endif | 567 | #endif |
574 | &ireq->loc_addr; | 568 | &ireq->loc_addr; |
575 | entry.daddr = | 569 | entry.daddr = |
576 | #ifdef CONFIG_IP_TCPDIAG_IPV6 | 570 | #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) |
577 | (entry.family == AF_INET6) ? | 571 | (entry.family == AF_INET6) ? |
578 | tcp6_rsk(req)->rmt_addr.s6_addr32 : | 572 | tcp6_rsk(req)->rmt_addr.s6_addr32 : |
579 | #endif | 573 | #endif |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 3312cb8742e2..2bc7fafe7668 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -76,26 +76,27 @@ static struct tcp_func ipv6_mapped; | |||
76 | static struct tcp_func ipv6_specific; | 76 | static struct tcp_func ipv6_specific; |
77 | 77 | ||
78 | /* I have no idea if this is a good hash for v6 or not. -DaveM */ | 78 | /* I have no idea if this is a good hash for v6 or not. -DaveM */ |
79 | static __inline__ int tcp_v6_hashfn(struct in6_addr *laddr, u16 lport, | 79 | static inline int inet6_ehashfn(const struct in6_addr *laddr, const u16 lport, |
80 | struct in6_addr *faddr, u16 fport) | 80 | const struct in6_addr *faddr, const u16 fport, |
81 | const int ehash_size) | ||
81 | { | 82 | { |
82 | int hashent = (lport ^ fport); | 83 | int hashent = (lport ^ fport); |
83 | 84 | ||
84 | hashent ^= (laddr->s6_addr32[3] ^ faddr->s6_addr32[3]); | 85 | hashent ^= (laddr->s6_addr32[3] ^ faddr->s6_addr32[3]); |
85 | hashent ^= hashent>>16; | 86 | hashent ^= hashent>>16; |
86 | hashent ^= hashent>>8; | 87 | hashent ^= hashent>>8; |
87 | return (hashent & (tcp_hashinfo.ehash_size - 1)); | 88 | return (hashent & (ehash_size - 1)); |
88 | } | 89 | } |
89 | 90 | ||
90 | static __inline__ int tcp_v6_sk_hashfn(struct sock *sk) | 91 | static inline int inet6_sk_ehashfn(const struct sock *sk, const int ehash_size) |
91 | { | 92 | { |
92 | struct inet_sock *inet = inet_sk(sk); | 93 | const struct inet_sock *inet = inet_sk(sk); |
93 | struct ipv6_pinfo *np = inet6_sk(sk); | 94 | const struct ipv6_pinfo *np = inet6_sk(sk); |
94 | struct in6_addr *laddr = &np->rcv_saddr; | 95 | const struct in6_addr *laddr = &np->rcv_saddr; |
95 | struct in6_addr *faddr = &np->daddr; | 96 | const struct in6_addr *faddr = &np->daddr; |
96 | __u16 lport = inet->num; | 97 | const __u16 lport = inet->num; |
97 | __u16 fport = inet->dport; | 98 | const __u16 fport = inet->dport; |
98 | return tcp_v6_hashfn(laddr, lport, faddr, fport); | 99 | return inet6_ehashfn(laddr, lport, faddr, fport, ehash_size); |
99 | } | 100 | } |
100 | 101 | ||
101 | static inline int tcp_v6_bind_conflict(const struct sock *sk, | 102 | static inline int tcp_v6_bind_conflict(const struct sock *sk, |
@@ -231,7 +232,7 @@ static __inline__ void __tcp_v6_hash(struct sock *sk) | |||
231 | lock = &tcp_hashinfo.lhash_lock; | 232 | lock = &tcp_hashinfo.lhash_lock; |
232 | inet_listen_wlock(&tcp_hashinfo); | 233 | inet_listen_wlock(&tcp_hashinfo); |
233 | } else { | 234 | } else { |
234 | sk->sk_hashent = tcp_v6_sk_hashfn(sk); | 235 | sk->sk_hashent = inet6_sk_ehashfn(sk, tcp_hashinfo.ehash_size); |
235 | list = &tcp_hashinfo.ehash[sk->sk_hashent].chain; | 236 | list = &tcp_hashinfo.ehash[sk->sk_hashent].chain; |
236 | lock = &tcp_hashinfo.ehash[sk->sk_hashent].lock; | 237 | lock = &tcp_hashinfo.ehash[sk->sk_hashent].lock; |
237 | write_lock(lock); | 238 | write_lock(lock); |
@@ -258,7 +259,10 @@ static void tcp_v6_hash(struct sock *sk) | |||
258 | } | 259 | } |
259 | } | 260 | } |
260 | 261 | ||
261 | static struct sock *tcp_v6_lookup_listener(struct in6_addr *daddr, unsigned short hnum, int dif) | 262 | static struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo, |
263 | const struct in6_addr *daddr, | ||
264 | const unsigned short hnum, | ||
265 | const int dif) | ||
262 | { | 266 | { |
263 | struct sock *sk; | 267 | struct sock *sk; |
264 | struct hlist_node *node; | 268 | struct hlist_node *node; |
@@ -266,8 +270,8 @@ static struct sock *tcp_v6_lookup_listener(struct in6_addr *daddr, unsigned shor | |||
266 | int score, hiscore; | 270 | int score, hiscore; |
267 | 271 | ||
268 | hiscore=0; | 272 | hiscore=0; |
269 | read_lock(&tcp_hashinfo.lhash_lock); | 273 | read_lock(&hashinfo->lhash_lock); |
270 | sk_for_each(sk, node, &tcp_hashinfo.listening_hash[inet_lhashfn(hnum)]) { | 274 | sk_for_each(sk, node, &hashinfo->listening_hash[inet_lhashfn(hnum)]) { |
271 | if (inet_sk(sk)->num == hnum && sk->sk_family == PF_INET6) { | 275 | if (inet_sk(sk)->num == hnum && sk->sk_family == PF_INET6) { |
272 | struct ipv6_pinfo *np = inet6_sk(sk); | 276 | struct ipv6_pinfo *np = inet6_sk(sk); |
273 | 277 | ||
@@ -294,7 +298,7 @@ static struct sock *tcp_v6_lookup_listener(struct in6_addr *daddr, unsigned shor | |||
294 | } | 298 | } |
295 | if (result) | 299 | if (result) |
296 | sock_hold(result); | 300 | sock_hold(result); |
297 | read_unlock(&tcp_hashinfo.lhash_lock); | 301 | read_unlock(&hashinfo->lhash_lock); |
298 | return result; | 302 | return result; |
299 | } | 303 | } |
300 | 304 | ||
@@ -304,9 +308,13 @@ static struct sock *tcp_v6_lookup_listener(struct in6_addr *daddr, unsigned shor | |||
304 | * The sockhash lock must be held as a reader here. | 308 | * The sockhash lock must be held as a reader here. |
305 | */ | 309 | */ |
306 | 310 | ||
307 | static inline struct sock *__tcp_v6_lookup_established(struct in6_addr *saddr, u16 sport, | 311 | static inline struct sock * |
308 | struct in6_addr *daddr, u16 hnum, | 312 | __inet6_lookup_established(struct inet_hashinfo *hashinfo, |
309 | int dif) | 313 | const struct in6_addr *saddr, |
314 | const u16 sport, | ||
315 | const struct in6_addr *daddr, | ||
316 | const u16 hnum, | ||
317 | const int dif) | ||
310 | { | 318 | { |
311 | struct sock *sk; | 319 | struct sock *sk; |
312 | const struct hlist_node *node; | 320 | const struct hlist_node *node; |
@@ -314,8 +322,9 @@ static inline struct sock *__tcp_v6_lookup_established(struct in6_addr *saddr, u | |||
314 | /* Optimize here for direct hit, only listening connections can | 322 | /* Optimize here for direct hit, only listening connections can |
315 | * have wildcards anyways. | 323 | * have wildcards anyways. |
316 | */ | 324 | */ |
317 | const int hash = tcp_v6_hashfn(daddr, hnum, saddr, sport); | 325 | const int hash = inet6_ehashfn(daddr, hnum, saddr, sport, |
318 | struct inet_ehash_bucket *head = &tcp_hashinfo.ehash[hash]; | 326 | hashinfo->ehash_size); |
327 | struct inet_ehash_bucket *head = &hashinfo->ehash[hash]; | ||
319 | 328 | ||
320 | read_lock(&head->lock); | 329 | read_lock(&head->lock); |
321 | sk_for_each(sk, node, &head->chain) { | 330 | sk_for_each(sk, node, &head->chain) { |
@@ -324,7 +333,7 @@ static inline struct sock *__tcp_v6_lookup_established(struct in6_addr *saddr, u | |||
324 | goto hit; /* You sunk my battleship! */ | 333 | goto hit; /* You sunk my battleship! */ |
325 | } | 334 | } |
326 | /* Must check for a TIME_WAIT'er before going to listener hash. */ | 335 | /* Must check for a TIME_WAIT'er before going to listener hash. */ |
327 | sk_for_each(sk, node, &(head + tcp_hashinfo.ehash_size)->chain) { | 336 | sk_for_each(sk, node, &(head + hashinfo->ehash_size)->chain) { |
328 | const struct inet_timewait_sock *tw = inet_twsk(sk); | 337 | const struct inet_timewait_sock *tw = inet_twsk(sk); |
329 | 338 | ||
330 | if(*((__u32 *)&(tw->tw_dport)) == ports && | 339 | if(*((__u32 *)&(tw->tw_dport)) == ports && |
@@ -347,34 +356,36 @@ hit: | |||
347 | } | 356 | } |
348 | 357 | ||
349 | 358 | ||
350 | static inline struct sock *__tcp_v6_lookup(struct in6_addr *saddr, u16 sport, | 359 | static inline struct sock *__inet6_lookup(struct inet_hashinfo *hashinfo, |
351 | struct in6_addr *daddr, u16 hnum, | 360 | const struct in6_addr *saddr, |
352 | int dif) | 361 | const u16 sport, |
362 | const struct in6_addr *daddr, | ||
363 | const u16 hnum, | ||
364 | const int dif) | ||
353 | { | 365 | { |
354 | struct sock *sk; | 366 | struct sock *sk = __inet6_lookup_established(hashinfo, saddr, sport, |
355 | 367 | daddr, hnum, dif); | |
356 | sk = __tcp_v6_lookup_established(saddr, sport, daddr, hnum, dif); | ||
357 | |||
358 | if (sk) | 368 | if (sk) |
359 | return sk; | 369 | return sk; |
360 | 370 | ||
361 | return tcp_v6_lookup_listener(daddr, hnum, dif); | 371 | return inet6_lookup_listener(hashinfo, daddr, hnum, dif); |
362 | } | 372 | } |
363 | 373 | ||
364 | inline struct sock *tcp_v6_lookup(struct in6_addr *saddr, u16 sport, | 374 | inline struct sock *inet6_lookup(struct inet_hashinfo *hashinfo, |
365 | struct in6_addr *daddr, u16 dport, | 375 | const struct in6_addr *saddr, const u16 sport, |
366 | int dif) | 376 | const struct in6_addr *daddr, const u16 dport, |
377 | const int dif) | ||
367 | { | 378 | { |
368 | struct sock *sk; | 379 | struct sock *sk; |
369 | 380 | ||
370 | local_bh_disable(); | 381 | local_bh_disable(); |
371 | sk = __tcp_v6_lookup(saddr, sport, daddr, ntohs(dport), dif); | 382 | sk = __inet6_lookup(hashinfo, saddr, sport, daddr, ntohs(dport), dif); |
372 | local_bh_enable(); | 383 | local_bh_enable(); |
373 | 384 | ||
374 | return sk; | 385 | return sk; |
375 | } | 386 | } |
376 | 387 | ||
377 | EXPORT_SYMBOL_GPL(tcp_v6_lookup); | 388 | EXPORT_SYMBOL_GPL(inet6_lookup); |
378 | 389 | ||
379 | 390 | ||
380 | /* | 391 | /* |
@@ -454,16 +465,17 @@ static __u32 tcp_v6_init_sequence(struct sock *sk, struct sk_buff *skb) | |||
454 | } | 465 | } |
455 | } | 466 | } |
456 | 467 | ||
457 | static int __tcp_v6_check_established(struct sock *sk, __u16 lport, | 468 | static int __tcp_v6_check_established(struct sock *sk, const __u16 lport, |
458 | struct inet_timewait_sock **twp) | 469 | struct inet_timewait_sock **twp) |
459 | { | 470 | { |
460 | struct inet_sock *inet = inet_sk(sk); | 471 | struct inet_sock *inet = inet_sk(sk); |
461 | struct ipv6_pinfo *np = inet6_sk(sk); | 472 | const struct ipv6_pinfo *np = inet6_sk(sk); |
462 | struct in6_addr *daddr = &np->rcv_saddr; | 473 | const struct in6_addr *daddr = &np->rcv_saddr; |
463 | struct in6_addr *saddr = &np->daddr; | 474 | const struct in6_addr *saddr = &np->daddr; |
464 | int dif = sk->sk_bound_dev_if; | 475 | const int dif = sk->sk_bound_dev_if; |
465 | const u32 ports = INET_COMBINED_PORTS(inet->dport, lport); | 476 | const u32 ports = INET_COMBINED_PORTS(inet->dport, lport); |
466 | const int hash = tcp_v6_hashfn(daddr, inet->num, saddr, inet->dport); | 477 | const int hash = inet6_ehashfn(daddr, inet->num, saddr, inet->dport, |
478 | tcp_hashinfo.ehash_size); | ||
467 | struct inet_ehash_bucket *head = &tcp_hashinfo.ehash[hash]; | 479 | struct inet_ehash_bucket *head = &tcp_hashinfo.ehash[hash]; |
468 | struct sock *sk2; | 480 | struct sock *sk2; |
469 | const struct hlist_node *node; | 481 | const struct hlist_node *node; |
@@ -637,11 +649,6 @@ out: | |||
637 | } | 649 | } |
638 | } | 650 | } |
639 | 651 | ||
640 | static __inline__ int tcp_v6_iif(struct sk_buff *skb) | ||
641 | { | ||
642 | return IP6CB(skb)->iif; | ||
643 | } | ||
644 | |||
645 | static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | 652 | static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, |
646 | int addr_len) | 653 | int addr_len) |
647 | { | 654 | { |
@@ -833,14 +840,15 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
833 | int type, int code, int offset, __u32 info) | 840 | int type, int code, int offset, __u32 info) |
834 | { | 841 | { |
835 | struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data; | 842 | struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data; |
836 | struct tcphdr *th = (struct tcphdr *)(skb->data+offset); | 843 | const struct tcphdr *th = (struct tcphdr *)(skb->data+offset); |
837 | struct ipv6_pinfo *np; | 844 | struct ipv6_pinfo *np; |
838 | struct sock *sk; | 845 | struct sock *sk; |
839 | int err; | 846 | int err; |
840 | struct tcp_sock *tp; | 847 | struct tcp_sock *tp; |
841 | __u32 seq; | 848 | __u32 seq; |
842 | 849 | ||
843 | sk = tcp_v6_lookup(&hdr->daddr, th->dest, &hdr->saddr, th->source, skb->dev->ifindex); | 850 | sk = inet6_lookup(&tcp_hashinfo, &hdr->daddr, th->dest, &hdr->saddr, |
851 | th->source, skb->dev->ifindex); | ||
844 | 852 | ||
845 | if (sk == NULL) { | 853 | if (sk == NULL) { |
846 | ICMP6_INC_STATS_BH(__in6_dev_get(skb->dev), ICMP6_MIB_INERRORS); | 854 | 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, | |||
927 | goto out; | 935 | goto out; |
928 | 936 | ||
929 | req = tcp_v6_search_req(sk, &prev, th->dest, &hdr->daddr, | 937 | req = tcp_v6_search_req(sk, &prev, th->dest, &hdr->daddr, |
930 | &hdr->saddr, tcp_v6_iif(skb)); | 938 | &hdr->saddr, inet6_iif(skb)); |
931 | if (!req) | 939 | if (!req) |
932 | goto out; | 940 | goto out; |
933 | 941 | ||
@@ -1138,7 +1146,7 @@ static void tcp_v6_send_reset(struct sk_buff *skb) | |||
1138 | buff->csum); | 1146 | buff->csum); |
1139 | 1147 | ||
1140 | fl.proto = IPPROTO_TCP; | 1148 | fl.proto = IPPROTO_TCP; |
1141 | fl.oif = tcp_v6_iif(skb); | 1149 | fl.oif = inet6_iif(skb); |
1142 | fl.fl_ip_dport = t1->dest; | 1150 | fl.fl_ip_dport = t1->dest; |
1143 | fl.fl_ip_sport = t1->source; | 1151 | fl.fl_ip_sport = t1->source; |
1144 | 1152 | ||
@@ -1207,7 +1215,7 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 | |||
1207 | buff->csum); | 1215 | buff->csum); |
1208 | 1216 | ||
1209 | fl.proto = IPPROTO_TCP; | 1217 | fl.proto = IPPROTO_TCP; |
1210 | fl.oif = tcp_v6_iif(skb); | 1218 | fl.oif = inet6_iif(skb); |
1211 | fl.fl_ip_dport = t1->dest; | 1219 | fl.fl_ip_dport = t1->dest; |
1212 | fl.fl_ip_sport = t1->source; | 1220 | fl.fl_ip_sport = t1->source; |
1213 | 1221 | ||
@@ -1245,20 +1253,18 @@ static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req) | |||
1245 | static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) | 1253 | static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) |
1246 | { | 1254 | { |
1247 | struct request_sock *req, **prev; | 1255 | struct request_sock *req, **prev; |
1248 | struct tcphdr *th = skb->h.th; | 1256 | const struct tcphdr *th = skb->h.th; |
1249 | struct sock *nsk; | 1257 | struct sock *nsk; |
1250 | 1258 | ||
1251 | /* Find possible connection requests. */ | 1259 | /* Find possible connection requests. */ |
1252 | req = tcp_v6_search_req(sk, &prev, th->source, &skb->nh.ipv6h->saddr, | 1260 | req = tcp_v6_search_req(sk, &prev, th->source, &skb->nh.ipv6h->saddr, |
1253 | &skb->nh.ipv6h->daddr, tcp_v6_iif(skb)); | 1261 | &skb->nh.ipv6h->daddr, inet6_iif(skb)); |
1254 | if (req) | 1262 | if (req) |
1255 | return tcp_check_req(sk, skb, req, prev); | 1263 | return tcp_check_req(sk, skb, req, prev); |
1256 | 1264 | ||
1257 | nsk = __tcp_v6_lookup_established(&skb->nh.ipv6h->saddr, | 1265 | nsk = __inet6_lookup_established(&tcp_hashinfo, &skb->nh.ipv6h->saddr, |
1258 | th->source, | 1266 | th->source, &skb->nh.ipv6h->daddr, |
1259 | &skb->nh.ipv6h->daddr, | 1267 | ntohs(th->dest), inet6_iif(skb)); |
1260 | ntohs(th->dest), | ||
1261 | tcp_v6_iif(skb)); | ||
1262 | 1268 | ||
1263 | if (nsk) { | 1269 | if (nsk) { |
1264 | if (nsk->sk_state != TCP_TIME_WAIT) { | 1270 | if (nsk->sk_state != TCP_TIME_WAIT) { |
@@ -1346,7 +1352,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1346 | /* So that link locals have meaning */ | 1352 | /* So that link locals have meaning */ |
1347 | if (!sk->sk_bound_dev_if && | 1353 | if (!sk->sk_bound_dev_if && |
1348 | ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL) | 1354 | ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL) |
1349 | treq->iif = tcp_v6_iif(skb); | 1355 | treq->iif = inet6_iif(skb); |
1350 | 1356 | ||
1351 | if (isn == 0) | 1357 | if (isn == 0) |
1352 | isn = tcp_v6_init_sequence(sk,skb); | 1358 | 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, | |||
1411 | newsk->sk_backlog_rcv = tcp_v4_do_rcv; | 1417 | newsk->sk_backlog_rcv = tcp_v4_do_rcv; |
1412 | newnp->pktoptions = NULL; | 1418 | newnp->pktoptions = NULL; |
1413 | newnp->opt = NULL; | 1419 | newnp->opt = NULL; |
1414 | newnp->mcast_oif = tcp_v6_iif(skb); | 1420 | newnp->mcast_oif = inet6_iif(skb); |
1415 | newnp->mcast_hops = skb->nh.ipv6h->hop_limit; | 1421 | newnp->mcast_hops = skb->nh.ipv6h->hop_limit; |
1416 | 1422 | ||
1417 | /* | 1423 | /* |
@@ -1516,7 +1522,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1516 | skb_set_owner_r(newnp->pktoptions, newsk); | 1522 | skb_set_owner_r(newnp->pktoptions, newsk); |
1517 | } | 1523 | } |
1518 | newnp->opt = NULL; | 1524 | newnp->opt = NULL; |
1519 | newnp->mcast_oif = tcp_v6_iif(skb); | 1525 | newnp->mcast_oif = inet6_iif(skb); |
1520 | newnp->mcast_hops = skb->nh.ipv6h->hop_limit; | 1526 | newnp->mcast_hops = skb->nh.ipv6h->hop_limit; |
1521 | 1527 | ||
1522 | /* Clone native IPv6 options from listening socket (if any) | 1528 | /* Clone native IPv6 options from listening socket (if any) |
@@ -1691,7 +1697,7 @@ ipv6_pktoptions: | |||
1691 | if (TCP_SKB_CB(opt_skb)->end_seq == tp->rcv_nxt && | 1697 | if (TCP_SKB_CB(opt_skb)->end_seq == tp->rcv_nxt && |
1692 | !((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN))) { | 1698 | !((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN))) { |
1693 | if (np->rxopt.bits.rxinfo) | 1699 | if (np->rxopt.bits.rxinfo) |
1694 | np->mcast_oif = tcp_v6_iif(opt_skb); | 1700 | np->mcast_oif = inet6_iif(opt_skb); |
1695 | if (np->rxopt.bits.rxhlim) | 1701 | if (np->rxopt.bits.rxhlim) |
1696 | np->mcast_hops = opt_skb->nh.ipv6h->hop_limit; | 1702 | np->mcast_hops = opt_skb->nh.ipv6h->hop_limit; |
1697 | if (ipv6_opt_accepted(sk, opt_skb)) { | 1703 | if (ipv6_opt_accepted(sk, opt_skb)) { |
@@ -1746,8 +1752,9 @@ static int tcp_v6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) | |||
1746 | TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(skb->nh.ipv6h); | 1752 | TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(skb->nh.ipv6h); |
1747 | TCP_SKB_CB(skb)->sacked = 0; | 1753 | TCP_SKB_CB(skb)->sacked = 0; |
1748 | 1754 | ||
1749 | sk = __tcp_v6_lookup(&skb->nh.ipv6h->saddr, th->source, | 1755 | sk = __inet6_lookup(&tcp_hashinfo, &skb->nh.ipv6h->saddr, th->source, |
1750 | &skb->nh.ipv6h->daddr, ntohs(th->dest), tcp_v6_iif(skb)); | 1756 | &skb->nh.ipv6h->daddr, ntohs(th->dest), |
1757 | inet6_iif(skb)); | ||
1751 | 1758 | ||
1752 | if (!sk) | 1759 | if (!sk) |
1753 | goto no_tcp_socket; | 1760 | goto no_tcp_socket; |
@@ -1818,7 +1825,9 @@ do_time_wait: | |||
1818 | { | 1825 | { |
1819 | struct sock *sk2; | 1826 | struct sock *sk2; |
1820 | 1827 | ||
1821 | sk2 = tcp_v6_lookup_listener(&skb->nh.ipv6h->daddr, ntohs(th->dest), tcp_v6_iif(skb)); | 1828 | sk2 = inet6_lookup_listener(&tcp_hashinfo, |
1829 | &skb->nh.ipv6h->daddr, | ||
1830 | ntohs(th->dest), inet6_iif(skb)); | ||
1822 | if (sk2 != NULL) { | 1831 | if (sk2 != NULL) { |
1823 | struct inet_timewait_sock *tw = inet_twsk(sk); | 1832 | struct inet_timewait_sock *tw = inet_twsk(sk); |
1824 | inet_twsk_deschedule(tw, &tcp_death_row); | 1833 | inet_twsk_deschedule(tw, &tcp_death_row); |