aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/inet6_hashtables.h2
-rw-r--r--include/net/inet_connection_sock.h8
-rw-r--r--include/net/inet_hashtables.h51
-rw-r--r--include/net/sock.h3
-rw-r--r--net/dccp/dccp.h2
-rw-r--r--net/dccp/ipv4.c18
-rw-r--r--net/dccp/ipv6.c20
-rw-r--r--net/dccp/proto.c18
-rw-r--r--net/ipv4/inet_connection_sock.c8
-rw-r--r--net/ipv4/inet_hashtables.c58
-rw-r--r--net/ipv4/tcp.c2
-rw-r--r--net/ipv4/tcp_ipv4.c31
-rw-r--r--net/ipv6/inet6_hashtables.c4
-rw-r--r--net/ipv6/tcp_ipv6.c19
14 files changed, 103 insertions, 141 deletions
diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h
index fdff630708ce..62a5b691858e 100644
--- a/include/net/inet6_hashtables.h
+++ b/include/net/inet6_hashtables.h
@@ -49,7 +49,7 @@ static inline int inet6_sk_ehashfn(const struct sock *sk)
49 return inet6_ehashfn(laddr, lport, faddr, fport); 49 return inet6_ehashfn(laddr, lport, faddr, fport);
50} 50}
51 51
52extern void __inet6_hash(struct inet_hashinfo *hashinfo, struct sock *sk); 52extern void __inet6_hash(struct sock *sk);
53 53
54/* 54/*
55 * Sockets in TCP_CLOSE state are _always_ taken out of the hash, so 55 * Sockets in TCP_CLOSE state are _always_ taken out of the hash, so
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
index 133cf30d2d79..f00f0573627b 100644
--- a/include/net/inet_connection_sock.h
+++ b/include/net/inet_connection_sock.h
@@ -29,7 +29,6 @@
29#undef INET_CSK_CLEAR_TIMERS 29#undef INET_CSK_CLEAR_TIMERS
30 30
31struct inet_bind_bucket; 31struct inet_bind_bucket;
32struct inet_hashinfo;
33struct tcp_congestion_ops; 32struct tcp_congestion_ops;
34 33
35/* 34/*
@@ -59,6 +58,8 @@ struct inet_connection_sock_af_ops {
59 int level, int optname, 58 int level, int optname,
60 char __user *optval, int __user *optlen); 59 char __user *optval, int __user *optlen);
61 void (*addr2sockaddr)(struct sock *sk, struct sockaddr *); 60 void (*addr2sockaddr)(struct sock *sk, struct sockaddr *);
61 int (*bind_conflict)(const struct sock *sk,
62 const struct inet_bind_bucket *tb);
62}; 63};
63 64
64/** inet_connection_sock - INET connection oriented sock 65/** inet_connection_sock - INET connection oriented sock
@@ -244,10 +245,7 @@ extern struct request_sock *inet_csk_search_req(const struct sock *sk,
244 const __be32 laddr); 245 const __be32 laddr);
245extern int inet_csk_bind_conflict(const struct sock *sk, 246extern int inet_csk_bind_conflict(const struct sock *sk,
246 const struct inet_bind_bucket *tb); 247 const struct inet_bind_bucket *tb);
247extern int inet_csk_get_port(struct inet_hashinfo *hashinfo, 248extern int inet_csk_get_port(struct sock *sk, unsigned short snum);
248 struct sock *sk, unsigned short snum,
249 int (*bind_conflict)(const struct sock *sk,
250 const struct inet_bind_bucket *tb));
251 249
252extern struct dst_entry* inet_csk_route_req(struct sock *sk, 250extern struct dst_entry* inet_csk_route_req(struct sock *sk,
253 const struct request_sock *req); 251 const struct request_sock *req);
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index c23c4ed30724..48ac620cb846 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -221,9 +221,9 @@ static inline int inet_sk_listen_hashfn(const struct sock *sk)
221} 221}
222 222
223/* Caller must disable local BH processing. */ 223/* Caller must disable local BH processing. */
224static inline void __inet_inherit_port(struct inet_hashinfo *table, 224static inline void __inet_inherit_port(struct sock *sk, struct sock *child)
225 struct sock *sk, struct sock *child)
226{ 225{
226 struct inet_hashinfo *table = sk->sk_prot->hashinfo;
227 const int bhash = inet_bhashfn(inet_sk(child)->num, table->bhash_size); 227 const int bhash = inet_bhashfn(inet_sk(child)->num, table->bhash_size);
228 struct inet_bind_hashbucket *head = &table->bhash[bhash]; 228 struct inet_bind_hashbucket *head = &table->bhash[bhash];
229 struct inet_bind_bucket *tb; 229 struct inet_bind_bucket *tb;
@@ -235,15 +235,14 @@ static inline void __inet_inherit_port(struct inet_hashinfo *table,
235 spin_unlock(&head->lock); 235 spin_unlock(&head->lock);
236} 236}
237 237
238static inline void inet_inherit_port(struct inet_hashinfo *table, 238static inline void inet_inherit_port(struct sock *sk, struct sock *child)
239 struct sock *sk, struct sock *child)
240{ 239{
241 local_bh_disable(); 240 local_bh_disable();
242 __inet_inherit_port(table, sk, child); 241 __inet_inherit_port(sk, child);
243 local_bh_enable(); 242 local_bh_enable();
244} 243}
245 244
246extern void inet_put_port(struct inet_hashinfo *table, struct sock *sk); 245extern void inet_put_port(struct sock *sk);
247 246
248extern void inet_listen_wlock(struct inet_hashinfo *hashinfo); 247extern void inet_listen_wlock(struct inet_hashinfo *hashinfo);
249 248
@@ -266,41 +265,9 @@ static inline void inet_listen_unlock(struct inet_hashinfo *hashinfo)
266 wake_up(&hashinfo->lhash_wait); 265 wake_up(&hashinfo->lhash_wait);
267} 266}
268 267
269extern void __inet_hash(struct inet_hashinfo *hashinfo, struct sock *sk); 268extern void __inet_hash_nolisten(struct sock *sk);
270extern void __inet_hash_nolisten(struct inet_hashinfo *hinfo, struct sock *sk); 269extern void inet_hash(struct sock *sk);
271 270extern void inet_unhash(struct sock *sk);
272static inline void inet_hash(struct inet_hashinfo *hashinfo, struct sock *sk)
273{
274 if (sk->sk_state != TCP_CLOSE) {
275 local_bh_disable();
276 __inet_hash(hashinfo, sk);
277 local_bh_enable();
278 }
279}
280
281static inline void inet_unhash(struct inet_hashinfo *hashinfo, struct sock *sk)
282{
283 rwlock_t *lock;
284
285 if (sk_unhashed(sk))
286 goto out;
287
288 if (sk->sk_state == TCP_LISTEN) {
289 local_bh_disable();
290 inet_listen_wlock(hashinfo);
291 lock = &hashinfo->lhash_lock;
292 } else {
293 lock = inet_ehash_lockp(hashinfo, sk->sk_hash);
294 write_lock_bh(lock);
295 }
296
297 if (__sk_del_node_init(sk))
298 sock_prot_inuse_add(sk->sk_prot, -1);
299 write_unlock_bh(lock);
300out:
301 if (sk->sk_state == TCP_LISTEN)
302 wake_up(&hashinfo->lhash_wait);
303}
304 271
305extern struct sock *__inet_lookup_listener(struct net *net, 272extern struct sock *__inet_lookup_listener(struct net *net,
306 struct inet_hashinfo *hashinfo, 273 struct inet_hashinfo *hashinfo,
@@ -425,7 +392,7 @@ extern int __inet_hash_connect(struct inet_timewait_death_row *death_row,
425 struct sock *sk, 392 struct sock *sk,
426 int (*check_established)(struct inet_timewait_death_row *, 393 int (*check_established)(struct inet_timewait_death_row *,
427 struct sock *, __u16, struct inet_timewait_sock **), 394 struct sock *, __u16, struct inet_timewait_sock **),
428 void (*hash)(struct inet_hashinfo *, struct sock *)); 395 void (*hash)(struct sock *sk));
429extern int inet_hash_connect(struct inet_timewait_death_row *death_row, 396extern int inet_hash_connect(struct inet_timewait_death_row *death_row,
430 struct sock *sk); 397 struct sock *sk);
431#endif /* _INET_HASHTABLES_H */ 398#endif /* _INET_HASHTABLES_H */
diff --git a/include/net/sock.h b/include/net/sock.h
index e3fb4c047f4c..8a7889b35810 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -496,6 +496,7 @@ extern int sk_wait_data(struct sock *sk, long *timeo);
496 496
497struct request_sock_ops; 497struct request_sock_ops;
498struct timewait_sock_ops; 498struct timewait_sock_ops;
499struct inet_hashinfo;
499 500
500/* Networking protocol blocks we attach to sockets. 501/* Networking protocol blocks we attach to sockets.
501 * socket layer -> transport layer interface 502 * socket layer -> transport layer interface
@@ -578,6 +579,8 @@ struct proto {
578 struct request_sock_ops *rsk_prot; 579 struct request_sock_ops *rsk_prot;
579 struct timewait_sock_ops *twsk_prot; 580 struct timewait_sock_ops *twsk_prot;
580 581
582 struct inet_hashinfo *hashinfo;
583
581 struct module *owner; 584 struct module *owner;
582 585
583 char name[32]; 586 char name[32];
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index ebe59d98721a..287a62bc2e0f 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -271,8 +271,6 @@ extern struct sk_buff *dccp_make_response(struct sock *sk,
271 271
272extern int dccp_connect(struct sock *sk); 272extern int dccp_connect(struct sock *sk);
273extern int dccp_disconnect(struct sock *sk, int flags); 273extern int dccp_disconnect(struct sock *sk, int flags);
274extern void dccp_hash(struct sock *sk);
275extern void dccp_unhash(struct sock *sk);
276extern int dccp_getsockopt(struct sock *sk, int level, int optname, 274extern int dccp_getsockopt(struct sock *sk, int level, int optname,
277 char __user *optval, int __user *optlen); 275 char __user *optval, int __user *optlen);
278extern int dccp_setsockopt(struct sock *sk, int level, int optname, 276extern int dccp_setsockopt(struct sock *sk, int level, int optname,
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index c982ad88223d..474075adbde4 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -38,12 +38,6 @@
38 */ 38 */
39static struct socket *dccp_v4_ctl_socket; 39static struct socket *dccp_v4_ctl_socket;
40 40
41static int dccp_v4_get_port(struct sock *sk, const unsigned short snum)
42{
43 return inet_csk_get_port(&dccp_hashinfo, sk, snum,
44 inet_csk_bind_conflict);
45}
46
47int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) 41int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
48{ 42{
49 struct inet_sock *inet = inet_sk(sk); 43 struct inet_sock *inet = inet_sk(sk);
@@ -408,8 +402,8 @@ struct sock *dccp_v4_request_recv_sock(struct sock *sk, struct sk_buff *skb,
408 402
409 dccp_sync_mss(newsk, dst_mtu(dst)); 403 dccp_sync_mss(newsk, dst_mtu(dst));
410 404
411 __inet_hash_nolisten(&dccp_hashinfo, newsk); 405 __inet_hash_nolisten(newsk);
412 __inet_inherit_port(&dccp_hashinfo, sk, newsk); 406 __inet_inherit_port(sk, newsk);
413 407
414 return newsk; 408 return newsk;
415 409
@@ -898,6 +892,7 @@ static struct inet_connection_sock_af_ops dccp_ipv4_af_ops = {
898 .getsockopt = ip_getsockopt, 892 .getsockopt = ip_getsockopt,
899 .addr2sockaddr = inet_csk_addr2sockaddr, 893 .addr2sockaddr = inet_csk_addr2sockaddr,
900 .sockaddr_len = sizeof(struct sockaddr_in), 894 .sockaddr_len = sizeof(struct sockaddr_in),
895 .bind_conflict = inet_csk_bind_conflict,
901#ifdef CONFIG_COMPAT 896#ifdef CONFIG_COMPAT
902 .compat_setsockopt = compat_ip_setsockopt, 897 .compat_setsockopt = compat_ip_setsockopt,
903 .compat_getsockopt = compat_ip_getsockopt, 898 .compat_getsockopt = compat_ip_getsockopt,
@@ -937,10 +932,10 @@ static struct proto dccp_v4_prot = {
937 .sendmsg = dccp_sendmsg, 932 .sendmsg = dccp_sendmsg,
938 .recvmsg = dccp_recvmsg, 933 .recvmsg = dccp_recvmsg,
939 .backlog_rcv = dccp_v4_do_rcv, 934 .backlog_rcv = dccp_v4_do_rcv,
940 .hash = dccp_hash, 935 .hash = inet_hash,
941 .unhash = dccp_unhash, 936 .unhash = inet_unhash,
942 .accept = inet_csk_accept, 937 .accept = inet_csk_accept,
943 .get_port = dccp_v4_get_port, 938 .get_port = inet_csk_get_port,
944 .shutdown = dccp_shutdown, 939 .shutdown = dccp_shutdown,
945 .destroy = dccp_destroy_sock, 940 .destroy = dccp_destroy_sock,
946 .orphan_count = &dccp_orphan_count, 941 .orphan_count = &dccp_orphan_count,
@@ -948,6 +943,7 @@ static struct proto dccp_v4_prot = {
948 .obj_size = sizeof(struct dccp_sock), 943 .obj_size = sizeof(struct dccp_sock),
949 .rsk_prot = &dccp_request_sock_ops, 944 .rsk_prot = &dccp_request_sock_ops,
950 .twsk_prot = &dccp_timewait_sock_ops, 945 .twsk_prot = &dccp_timewait_sock_ops,
946 .hashinfo = &dccp_hashinfo,
951#ifdef CONFIG_COMPAT 947#ifdef CONFIG_COMPAT
952 .compat_setsockopt = compat_dccp_setsockopt, 948 .compat_setsockopt = compat_dccp_setsockopt,
953 .compat_getsockopt = compat_dccp_getsockopt, 949 .compat_getsockopt = compat_dccp_getsockopt,
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index ed0a0053a797..490333d47c7b 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -39,21 +39,15 @@ static struct socket *dccp_v6_ctl_socket;
39static struct inet_connection_sock_af_ops dccp_ipv6_mapped; 39static struct inet_connection_sock_af_ops dccp_ipv6_mapped;
40static struct inet_connection_sock_af_ops dccp_ipv6_af_ops; 40static struct inet_connection_sock_af_ops dccp_ipv6_af_ops;
41 41
42static int dccp_v6_get_port(struct sock *sk, unsigned short snum)
43{
44 return inet_csk_get_port(&dccp_hashinfo, sk, snum,
45 inet6_csk_bind_conflict);
46}
47
48static void dccp_v6_hash(struct sock *sk) 42static void dccp_v6_hash(struct sock *sk)
49{ 43{
50 if (sk->sk_state != DCCP_CLOSED) { 44 if (sk->sk_state != DCCP_CLOSED) {
51 if (inet_csk(sk)->icsk_af_ops == &dccp_ipv6_mapped) { 45 if (inet_csk(sk)->icsk_af_ops == &dccp_ipv6_mapped) {
52 dccp_hash(sk); 46 inet_hash(sk);
53 return; 47 return;
54 } 48 }
55 local_bh_disable(); 49 local_bh_disable();
56 __inet6_hash(&dccp_hashinfo, sk); 50 __inet6_hash(sk);
57 local_bh_enable(); 51 local_bh_enable();
58 } 52 }
59} 53}
@@ -630,8 +624,8 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk,
630 624
631 newinet->daddr = newinet->saddr = newinet->rcv_saddr = LOOPBACK4_IPV6; 625 newinet->daddr = newinet->saddr = newinet->rcv_saddr = LOOPBACK4_IPV6;
632 626
633 __inet6_hash(&dccp_hashinfo, newsk); 627 __inet6_hash(newsk);
634 inet_inherit_port(&dccp_hashinfo, sk, newsk); 628 inet_inherit_port(sk, newsk);
635 629
636 return newsk; 630 return newsk;
637 631
@@ -1054,6 +1048,7 @@ static struct inet_connection_sock_af_ops dccp_ipv6_af_ops = {
1054 .getsockopt = ipv6_getsockopt, 1048 .getsockopt = ipv6_getsockopt,
1055 .addr2sockaddr = inet6_csk_addr2sockaddr, 1049 .addr2sockaddr = inet6_csk_addr2sockaddr,
1056 .sockaddr_len = sizeof(struct sockaddr_in6), 1050 .sockaddr_len = sizeof(struct sockaddr_in6),
1051 .bind_conflict = inet6_csk_bind_conflict,
1057#ifdef CONFIG_COMPAT 1052#ifdef CONFIG_COMPAT
1058 .compat_setsockopt = compat_ipv6_setsockopt, 1053 .compat_setsockopt = compat_ipv6_setsockopt,
1059 .compat_getsockopt = compat_ipv6_getsockopt, 1054 .compat_getsockopt = compat_ipv6_getsockopt,
@@ -1123,9 +1118,9 @@ static struct proto dccp_v6_prot = {
1123 .recvmsg = dccp_recvmsg, 1118 .recvmsg = dccp_recvmsg,
1124 .backlog_rcv = dccp_v6_do_rcv, 1119 .backlog_rcv = dccp_v6_do_rcv,
1125 .hash = dccp_v6_hash, 1120 .hash = dccp_v6_hash,
1126 .unhash = dccp_unhash, 1121 .unhash = inet_unhash,
1127 .accept = inet_csk_accept, 1122 .accept = inet_csk_accept,
1128 .get_port = dccp_v6_get_port, 1123 .get_port = inet_csk_get_port,
1129 .shutdown = dccp_shutdown, 1124 .shutdown = dccp_shutdown,
1130 .destroy = dccp_v6_destroy_sock, 1125 .destroy = dccp_v6_destroy_sock,
1131 .orphan_count = &dccp_orphan_count, 1126 .orphan_count = &dccp_orphan_count,
@@ -1133,6 +1128,7 @@ static struct proto dccp_v6_prot = {
1133 .obj_size = sizeof(struct dccp6_sock), 1128 .obj_size = sizeof(struct dccp6_sock),
1134 .rsk_prot = &dccp6_request_sock_ops, 1129 .rsk_prot = &dccp6_request_sock_ops,
1135 .twsk_prot = &dccp6_timewait_sock_ops, 1130 .twsk_prot = &dccp6_timewait_sock_ops,
1131 .hashinfo = &dccp_hashinfo,
1136#ifdef CONFIG_COMPAT 1132#ifdef CONFIG_COMPAT
1137 .compat_setsockopt = compat_dccp_setsockopt, 1133 .compat_setsockopt = compat_dccp_setsockopt,
1138 .compat_getsockopt = compat_dccp_getsockopt, 1134 .compat_getsockopt = compat_dccp_getsockopt,
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 0bed4a6095b7..e3f5d37b84be 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -78,7 +78,7 @@ void dccp_set_state(struct sock *sk, const int state)
78 sk->sk_prot->unhash(sk); 78 sk->sk_prot->unhash(sk);
79 if (inet_csk(sk)->icsk_bind_hash != NULL && 79 if (inet_csk(sk)->icsk_bind_hash != NULL &&
80 !(sk->sk_userlocks & SOCK_BINDPORT_LOCK)) 80 !(sk->sk_userlocks & SOCK_BINDPORT_LOCK))
81 inet_put_port(&dccp_hashinfo, sk); 81 inet_put_port(sk);
82 /* fall through */ 82 /* fall through */
83 default: 83 default:
84 if (oldstate == DCCP_OPEN) 84 if (oldstate == DCCP_OPEN)
@@ -173,20 +173,6 @@ const char *dccp_state_name(const int state)
173 173
174EXPORT_SYMBOL_GPL(dccp_state_name); 174EXPORT_SYMBOL_GPL(dccp_state_name);
175 175
176void dccp_hash(struct sock *sk)
177{
178 inet_hash(&dccp_hashinfo, sk);
179}
180
181EXPORT_SYMBOL_GPL(dccp_hash);
182
183void dccp_unhash(struct sock *sk)
184{
185 inet_unhash(&dccp_hashinfo, sk);
186}
187
188EXPORT_SYMBOL_GPL(dccp_unhash);
189
190int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized) 176int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)
191{ 177{
192 struct dccp_sock *dp = dccp_sk(sk); 178 struct dccp_sock *dp = dccp_sk(sk);
@@ -268,7 +254,7 @@ int dccp_destroy_sock(struct sock *sk)
268 254
269 /* Clean up a referenced DCCP bind bucket. */ 255 /* Clean up a referenced DCCP bind bucket. */
270 if (inet_csk(sk)->icsk_bind_hash != NULL) 256 if (inet_csk(sk)->icsk_bind_hash != NULL)
271 inet_put_port(&dccp_hashinfo, sk); 257 inet_put_port(sk);
272 258
273 kfree(dp->dccps_service_list); 259 kfree(dp->dccps_service_list);
274 dp->dccps_service_list = NULL; 260 dp->dccps_service_list = NULL;
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index de5a41de191a..b189278c7bc1 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -78,11 +78,9 @@ EXPORT_SYMBOL_GPL(inet_csk_bind_conflict);
78/* Obtain a reference to a local port for the given sock, 78/* Obtain a reference to a local port for the given sock,
79 * if snum is zero it means select any available local port. 79 * if snum is zero it means select any available local port.
80 */ 80 */
81int inet_csk_get_port(struct inet_hashinfo *hashinfo, 81int inet_csk_get_port(struct sock *sk, unsigned short snum)
82 struct sock *sk, unsigned short snum,
83 int (*bind_conflict)(const struct sock *sk,
84 const struct inet_bind_bucket *tb))
85{ 82{
83 struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
86 struct inet_bind_hashbucket *head; 84 struct inet_bind_hashbucket *head;
87 struct hlist_node *node; 85 struct hlist_node *node;
88 struct inet_bind_bucket *tb; 86 struct inet_bind_bucket *tb;
@@ -142,7 +140,7 @@ tb_found:
142 goto success; 140 goto success;
143 } else { 141 } else {
144 ret = 1; 142 ret = 1;
145 if (bind_conflict(sk, tb)) 143 if (inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb))
146 goto fail_unlock; 144 goto fail_unlock;
147 } 145 }
148 } 146 }
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index 48d45008f749..90f422c9447b 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -66,8 +66,9 @@ void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb,
66/* 66/*
67 * Get rid of any references to a local port held by the given sock. 67 * Get rid of any references to a local port held by the given sock.
68 */ 68 */
69static void __inet_put_port(struct inet_hashinfo *hashinfo, struct sock *sk) 69static void __inet_put_port(struct sock *sk)
70{ 70{
71 struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
71 const int bhash = inet_bhashfn(inet_sk(sk)->num, hashinfo->bhash_size); 72 const int bhash = inet_bhashfn(inet_sk(sk)->num, hashinfo->bhash_size);
72 struct inet_bind_hashbucket *head = &hashinfo->bhash[bhash]; 73 struct inet_bind_hashbucket *head = &hashinfo->bhash[bhash];
73 struct inet_bind_bucket *tb; 74 struct inet_bind_bucket *tb;
@@ -81,10 +82,10 @@ static void __inet_put_port(struct inet_hashinfo *hashinfo, struct sock *sk)
81 spin_unlock(&head->lock); 82 spin_unlock(&head->lock);
82} 83}
83 84
84void inet_put_port(struct inet_hashinfo *hashinfo, struct sock *sk) 85void inet_put_port(struct sock *sk)
85{ 86{
86 local_bh_disable(); 87 local_bh_disable();
87 __inet_put_port(hashinfo, sk); 88 __inet_put_port(sk);
88 local_bh_enable(); 89 local_bh_enable();
89} 90}
90 91
@@ -317,8 +318,9 @@ static inline u32 inet_sk_port_offset(const struct sock *sk)
317 inet->dport); 318 inet->dport);
318} 319}
319 320
320void __inet_hash_nolisten(struct inet_hashinfo *hashinfo, struct sock *sk) 321void __inet_hash_nolisten(struct sock *sk)
321{ 322{
323 struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
322 struct hlist_head *list; 324 struct hlist_head *list;
323 rwlock_t *lock; 325 rwlock_t *lock;
324 struct inet_ehash_bucket *head; 326 struct inet_ehash_bucket *head;
@@ -337,13 +339,14 @@ void __inet_hash_nolisten(struct inet_hashinfo *hashinfo, struct sock *sk)
337} 339}
338EXPORT_SYMBOL_GPL(__inet_hash_nolisten); 340EXPORT_SYMBOL_GPL(__inet_hash_nolisten);
339 341
340void __inet_hash(struct inet_hashinfo *hashinfo, struct sock *sk) 342static void __inet_hash(struct sock *sk)
341{ 343{
344 struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
342 struct hlist_head *list; 345 struct hlist_head *list;
343 rwlock_t *lock; 346 rwlock_t *lock;
344 347
345 if (sk->sk_state != TCP_LISTEN) { 348 if (sk->sk_state != TCP_LISTEN) {
346 __inet_hash_nolisten(hashinfo, sk); 349 __inet_hash_nolisten(sk);
347 return; 350 return;
348 } 351 }
349 352
@@ -357,13 +360,48 @@ void __inet_hash(struct inet_hashinfo *hashinfo, struct sock *sk)
357 write_unlock(lock); 360 write_unlock(lock);
358 wake_up(&hashinfo->lhash_wait); 361 wake_up(&hashinfo->lhash_wait);
359} 362}
360EXPORT_SYMBOL_GPL(__inet_hash); 363
364void inet_hash(struct sock *sk)
365{
366 if (sk->sk_state != TCP_CLOSE) {
367 local_bh_disable();
368 __inet_hash(sk);
369 local_bh_enable();
370 }
371}
372EXPORT_SYMBOL_GPL(inet_hash);
373
374void inet_unhash(struct sock *sk)
375{
376 rwlock_t *lock;
377 struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
378
379 if (sk_unhashed(sk))
380 goto out;
381
382 if (sk->sk_state == TCP_LISTEN) {
383 local_bh_disable();
384 inet_listen_wlock(hashinfo);
385 lock = &hashinfo->lhash_lock;
386 } else {
387 lock = inet_ehash_lockp(hashinfo, sk->sk_hash);
388 write_lock_bh(lock);
389 }
390
391 if (__sk_del_node_init(sk))
392 sock_prot_inuse_add(sk->sk_prot, -1);
393 write_unlock_bh(lock);
394out:
395 if (sk->sk_state == TCP_LISTEN)
396 wake_up(&hashinfo->lhash_wait);
397}
398EXPORT_SYMBOL_GPL(inet_unhash);
361 399
362int __inet_hash_connect(struct inet_timewait_death_row *death_row, 400int __inet_hash_connect(struct inet_timewait_death_row *death_row,
363 struct sock *sk, 401 struct sock *sk,
364 int (*check_established)(struct inet_timewait_death_row *, 402 int (*check_established)(struct inet_timewait_death_row *,
365 struct sock *, __u16, struct inet_timewait_sock **), 403 struct sock *, __u16, struct inet_timewait_sock **),
366 void (*hash)(struct inet_hashinfo *, struct sock *)) 404 void (*hash)(struct sock *sk))
367{ 405{
368 struct inet_hashinfo *hinfo = death_row->hashinfo; 406 struct inet_hashinfo *hinfo = death_row->hashinfo;
369 const unsigned short snum = inet_sk(sk)->num; 407 const unsigned short snum = inet_sk(sk)->num;
@@ -427,7 +465,7 @@ ok:
427 inet_bind_hash(sk, tb, port); 465 inet_bind_hash(sk, tb, port);
428 if (sk_unhashed(sk)) { 466 if (sk_unhashed(sk)) {
429 inet_sk(sk)->sport = htons(port); 467 inet_sk(sk)->sport = htons(port);
430 hash(hinfo, sk); 468 hash(sk);
431 } 469 }
432 spin_unlock(&head->lock); 470 spin_unlock(&head->lock);
433 471
@@ -444,7 +482,7 @@ ok:
444 tb = inet_csk(sk)->icsk_bind_hash; 482 tb = inet_csk(sk)->icsk_bind_hash;
445 spin_lock_bh(&head->lock); 483 spin_lock_bh(&head->lock);
446 if (sk_head(&tb->owners) == sk && !sk->sk_bind_node.next) { 484 if (sk_head(&tb->owners) == sk && !sk->sk_bind_node.next) {
447 hash(hinfo, sk); 485 hash(sk);
448 spin_unlock_bh(&head->lock); 486 spin_unlock_bh(&head->lock);
449 return 0; 487 return 0;
450 } else { 488 } else {
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index a0d373bd9065..071e83a894ad 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1669,7 +1669,7 @@ void tcp_set_state(struct sock *sk, int state)
1669 sk->sk_prot->unhash(sk); 1669 sk->sk_prot->unhash(sk);
1670 if (inet_csk(sk)->icsk_bind_hash && 1670 if (inet_csk(sk)->icsk_bind_hash &&
1671 !(sk->sk_userlocks & SOCK_BINDPORT_LOCK)) 1671 !(sk->sk_userlocks & SOCK_BINDPORT_LOCK))
1672 inet_put_port(&tcp_hashinfo, sk); 1672 inet_put_port(sk);
1673 /* fall through */ 1673 /* fall through */
1674 default: 1674 default:
1675 if (oldstate==TCP_ESTABLISHED) 1675 if (oldstate==TCP_ESTABLISHED)
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 77c1939a2b0d..63414ea427c5 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -108,22 +108,6 @@ struct inet_hashinfo __cacheline_aligned tcp_hashinfo = {
108 .lhash_wait = __WAIT_QUEUE_HEAD_INITIALIZER(tcp_hashinfo.lhash_wait), 108 .lhash_wait = __WAIT_QUEUE_HEAD_INITIALIZER(tcp_hashinfo.lhash_wait),
109}; 109};
110 110
111static int tcp_v4_get_port(struct sock *sk, unsigned short snum)
112{
113 return inet_csk_get_port(&tcp_hashinfo, sk, snum,
114 inet_csk_bind_conflict);
115}
116
117static void tcp_v4_hash(struct sock *sk)
118{
119 inet_hash(&tcp_hashinfo, sk);
120}
121
122void tcp_unhash(struct sock *sk)
123{
124 inet_unhash(&tcp_hashinfo, sk);
125}
126
127static inline __u32 tcp_v4_init_sequence(struct sk_buff *skb) 111static inline __u32 tcp_v4_init_sequence(struct sk_buff *skb)
128{ 112{
129 return secure_tcp_sequence_number(ip_hdr(skb)->daddr, 113 return secure_tcp_sequence_number(ip_hdr(skb)->daddr,
@@ -1478,8 +1462,8 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
1478 } 1462 }
1479#endif 1463#endif
1480 1464
1481 __inet_hash_nolisten(&tcp_hashinfo, newsk); 1465 __inet_hash_nolisten(newsk);
1482 __inet_inherit_port(&tcp_hashinfo, sk, newsk); 1466 __inet_inherit_port(sk, newsk);
1483 1467
1484 return newsk; 1468 return newsk;
1485 1469
@@ -1827,6 +1811,7 @@ struct inet_connection_sock_af_ops ipv4_specific = {
1827 .getsockopt = ip_getsockopt, 1811 .getsockopt = ip_getsockopt,
1828 .addr2sockaddr = inet_csk_addr2sockaddr, 1812 .addr2sockaddr = inet_csk_addr2sockaddr,
1829 .sockaddr_len = sizeof(struct sockaddr_in), 1813 .sockaddr_len = sizeof(struct sockaddr_in),
1814 .bind_conflict = inet_csk_bind_conflict,
1830#ifdef CONFIG_COMPAT 1815#ifdef CONFIG_COMPAT
1831 .compat_setsockopt = compat_ip_setsockopt, 1816 .compat_setsockopt = compat_ip_setsockopt,
1832 .compat_getsockopt = compat_ip_getsockopt, 1817 .compat_getsockopt = compat_ip_getsockopt,
@@ -1926,7 +1911,7 @@ int tcp_v4_destroy_sock(struct sock *sk)
1926 1911
1927 /* Clean up a referenced TCP bind bucket. */ 1912 /* Clean up a referenced TCP bind bucket. */
1928 if (inet_csk(sk)->icsk_bind_hash) 1913 if (inet_csk(sk)->icsk_bind_hash)
1929 inet_put_port(&tcp_hashinfo, sk); 1914 inet_put_port(sk);
1930 1915
1931 /* 1916 /*
1932 * If sendmsg cached page exists, toss it. 1917 * If sendmsg cached page exists, toss it.
@@ -2435,9 +2420,9 @@ struct proto tcp_prot = {
2435 .getsockopt = tcp_getsockopt, 2420 .getsockopt = tcp_getsockopt,
2436 .recvmsg = tcp_recvmsg, 2421 .recvmsg = tcp_recvmsg,
2437 .backlog_rcv = tcp_v4_do_rcv, 2422 .backlog_rcv = tcp_v4_do_rcv,
2438 .hash = tcp_v4_hash, 2423 .hash = inet_hash,
2439 .unhash = tcp_unhash, 2424 .unhash = inet_unhash,
2440 .get_port = tcp_v4_get_port, 2425 .get_port = inet_csk_get_port,
2441 .enter_memory_pressure = tcp_enter_memory_pressure, 2426 .enter_memory_pressure = tcp_enter_memory_pressure,
2442 .sockets_allocated = &tcp_sockets_allocated, 2427 .sockets_allocated = &tcp_sockets_allocated,
2443 .orphan_count = &tcp_orphan_count, 2428 .orphan_count = &tcp_orphan_count,
@@ -2450,6 +2435,7 @@ struct proto tcp_prot = {
2450 .obj_size = sizeof(struct tcp_sock), 2435 .obj_size = sizeof(struct tcp_sock),
2451 .twsk_prot = &tcp_timewait_sock_ops, 2436 .twsk_prot = &tcp_timewait_sock_ops,
2452 .rsk_prot = &tcp_request_sock_ops, 2437 .rsk_prot = &tcp_request_sock_ops,
2438 .hashinfo = &tcp_hashinfo,
2453#ifdef CONFIG_COMPAT 2439#ifdef CONFIG_COMPAT
2454 .compat_setsockopt = compat_tcp_setsockopt, 2440 .compat_setsockopt = compat_tcp_setsockopt,
2455 .compat_getsockopt = compat_tcp_getsockopt, 2441 .compat_getsockopt = compat_tcp_getsockopt,
@@ -2467,7 +2453,6 @@ void __init tcp_v4_init(struct net_proto_family *ops)
2467EXPORT_SYMBOL(ipv4_specific); 2453EXPORT_SYMBOL(ipv4_specific);
2468EXPORT_SYMBOL(tcp_hashinfo); 2454EXPORT_SYMBOL(tcp_hashinfo);
2469EXPORT_SYMBOL(tcp_prot); 2455EXPORT_SYMBOL(tcp_prot);
2470EXPORT_SYMBOL(tcp_unhash);
2471EXPORT_SYMBOL(tcp_v4_conn_request); 2456EXPORT_SYMBOL(tcp_v4_conn_request);
2472EXPORT_SYMBOL(tcp_v4_connect); 2457EXPORT_SYMBOL(tcp_v4_connect);
2473EXPORT_SYMBOL(tcp_v4_do_rcv); 2458EXPORT_SYMBOL(tcp_v4_do_rcv);
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index d325a9958909..43f3993e1f30 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -22,9 +22,9 @@
22#include <net/inet6_hashtables.h> 22#include <net/inet6_hashtables.h>
23#include <net/ip.h> 23#include <net/ip.h>
24 24
25void __inet6_hash(struct inet_hashinfo *hashinfo, 25void __inet6_hash(struct sock *sk)
26 struct sock *sk)
27{ 26{
27 struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
28 struct hlist_head *list; 28 struct hlist_head *list;
29 rwlock_t *lock; 29 rwlock_t *lock;
30 30
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 59d0029e93a7..12750f2b05ab 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -86,12 +86,6 @@ static struct tcp_sock_af_ops tcp_sock_ipv6_specific;
86static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific; 86static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific;
87#endif 87#endif
88 88
89static int tcp_v6_get_port(struct sock *sk, unsigned short snum)
90{
91 return inet_csk_get_port(&tcp_hashinfo, sk, snum,
92 inet6_csk_bind_conflict);
93}
94
95static void tcp_v6_hash(struct sock *sk) 89static void tcp_v6_hash(struct sock *sk)
96{ 90{
97 if (sk->sk_state != TCP_CLOSE) { 91 if (sk->sk_state != TCP_CLOSE) {
@@ -100,7 +94,7 @@ static void tcp_v6_hash(struct sock *sk)
100 return; 94 return;
101 } 95 }
102 local_bh_disable(); 96 local_bh_disable();
103 __inet6_hash(&tcp_hashinfo, sk); 97 __inet6_hash(sk);
104 local_bh_enable(); 98 local_bh_enable();
105 } 99 }
106} 100}
@@ -1504,8 +1498,8 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
1504 } 1498 }
1505#endif 1499#endif
1506 1500
1507 __inet6_hash(&tcp_hashinfo, newsk); 1501 __inet6_hash(newsk);
1508 inet_inherit_port(&tcp_hashinfo, sk, newsk); 1502 inet_inherit_port(sk, newsk);
1509 1503
1510 return newsk; 1504 return newsk;
1511 1505
@@ -1833,6 +1827,7 @@ static struct inet_connection_sock_af_ops ipv6_specific = {
1833 .getsockopt = ipv6_getsockopt, 1827 .getsockopt = ipv6_getsockopt,
1834 .addr2sockaddr = inet6_csk_addr2sockaddr, 1828 .addr2sockaddr = inet6_csk_addr2sockaddr,
1835 .sockaddr_len = sizeof(struct sockaddr_in6), 1829 .sockaddr_len = sizeof(struct sockaddr_in6),
1830 .bind_conflict = inet6_csk_bind_conflict,
1836#ifdef CONFIG_COMPAT 1831#ifdef CONFIG_COMPAT
1837 .compat_setsockopt = compat_ipv6_setsockopt, 1832 .compat_setsockopt = compat_ipv6_setsockopt,
1838 .compat_getsockopt = compat_ipv6_getsockopt, 1833 .compat_getsockopt = compat_ipv6_getsockopt,
@@ -1864,6 +1859,7 @@ static struct inet_connection_sock_af_ops ipv6_mapped = {
1864 .getsockopt = ipv6_getsockopt, 1859 .getsockopt = ipv6_getsockopt,
1865 .addr2sockaddr = inet6_csk_addr2sockaddr, 1860 .addr2sockaddr = inet6_csk_addr2sockaddr,
1866 .sockaddr_len = sizeof(struct sockaddr_in6), 1861 .sockaddr_len = sizeof(struct sockaddr_in6),
1862 .bind_conflict = inet6_csk_bind_conflict,
1867#ifdef CONFIG_COMPAT 1863#ifdef CONFIG_COMPAT
1868 .compat_setsockopt = compat_ipv6_setsockopt, 1864 .compat_setsockopt = compat_ipv6_setsockopt,
1869 .compat_getsockopt = compat_ipv6_getsockopt, 1865 .compat_getsockopt = compat_ipv6_getsockopt,
@@ -2127,8 +2123,8 @@ struct proto tcpv6_prot = {
2127 .recvmsg = tcp_recvmsg, 2123 .recvmsg = tcp_recvmsg,
2128 .backlog_rcv = tcp_v6_do_rcv, 2124 .backlog_rcv = tcp_v6_do_rcv,
2129 .hash = tcp_v6_hash, 2125 .hash = tcp_v6_hash,
2130 .unhash = tcp_unhash, 2126 .unhash = inet_unhash,
2131 .get_port = tcp_v6_get_port, 2127 .get_port = inet_csk_get_port,
2132 .enter_memory_pressure = tcp_enter_memory_pressure, 2128 .enter_memory_pressure = tcp_enter_memory_pressure,
2133 .sockets_allocated = &tcp_sockets_allocated, 2129 .sockets_allocated = &tcp_sockets_allocated,
2134 .memory_allocated = &tcp_memory_allocated, 2130 .memory_allocated = &tcp_memory_allocated,
@@ -2141,6 +2137,7 @@ struct proto tcpv6_prot = {
2141 .obj_size = sizeof(struct tcp6_sock), 2137 .obj_size = sizeof(struct tcp6_sock),
2142 .twsk_prot = &tcp6_timewait_sock_ops, 2138 .twsk_prot = &tcp6_timewait_sock_ops,
2143 .rsk_prot = &tcp6_request_sock_ops, 2139 .rsk_prot = &tcp6_request_sock_ops,
2140 .hashinfo = &tcp_hashinfo,
2144#ifdef CONFIG_COMPAT 2141#ifdef CONFIG_COMPAT
2145 .compat_setsockopt = compat_tcp_setsockopt, 2142 .compat_setsockopt = compat_tcp_setsockopt,
2146 .compat_getsockopt = compat_tcp_getsockopt, 2143 .compat_getsockopt = compat_tcp_getsockopt,