13f421baaSArnaldo Carvalho de Melo /* 23f421baaSArnaldo Carvalho de Melo * INET An implementation of the TCP/IP protocol suite for the LINUX 33f421baaSArnaldo Carvalho de Melo * operating system. INET is implemented using the BSD Socket 43f421baaSArnaldo Carvalho de Melo * interface as the means of communication with the user level. 53f421baaSArnaldo Carvalho de Melo * 63f421baaSArnaldo Carvalho de Melo * Support for INET connection oriented protocols. 73f421baaSArnaldo Carvalho de Melo * 83f421baaSArnaldo Carvalho de Melo * Authors: See the TCP sources 93f421baaSArnaldo Carvalho de Melo * 103f421baaSArnaldo Carvalho de Melo * This program is free software; you can redistribute it and/or 113f421baaSArnaldo Carvalho de Melo * modify it under the terms of the GNU General Public License 123f421baaSArnaldo Carvalho de Melo * as published by the Free Software Foundation; either version 133f421baaSArnaldo Carvalho de Melo * 2 of the License, or(at your option) any later version. 143f421baaSArnaldo Carvalho de Melo */ 153f421baaSArnaldo Carvalho de Melo 163f421baaSArnaldo Carvalho de Melo #include <linux/config.h> 173f421baaSArnaldo Carvalho de Melo #include <linux/module.h> 183f421baaSArnaldo Carvalho de Melo #include <linux/jhash.h> 193f421baaSArnaldo Carvalho de Melo 203f421baaSArnaldo Carvalho de Melo #include <net/inet_connection_sock.h> 213f421baaSArnaldo Carvalho de Melo #include <net/inet_hashtables.h> 223f421baaSArnaldo Carvalho de Melo #include <net/inet_timewait_sock.h> 233f421baaSArnaldo Carvalho de Melo #include <net/ip.h> 243f421baaSArnaldo Carvalho de Melo #include <net/route.h> 253f421baaSArnaldo Carvalho de Melo #include <net/tcp_states.h> 26a019d6feSArnaldo Carvalho de Melo #include <net/xfrm.h> 273f421baaSArnaldo Carvalho de Melo 283f421baaSArnaldo Carvalho de Melo #ifdef INET_CSK_DEBUG 293f421baaSArnaldo Carvalho de Melo const char inet_csk_timer_bug_msg[] = "inet_csk BUG: unknown timer value\n"; 303f421baaSArnaldo Carvalho de Melo EXPORT_SYMBOL(inet_csk_timer_bug_msg); 313f421baaSArnaldo Carvalho de Melo #endif 323f421baaSArnaldo Carvalho de Melo 333f421baaSArnaldo Carvalho de Melo /* 343f421baaSArnaldo Carvalho de Melo * This array holds the first and last local port number. 353f421baaSArnaldo Carvalho de Melo * For high-usage systems, use sysctl to change this to 363f421baaSArnaldo Carvalho de Melo * 32768-61000 373f421baaSArnaldo Carvalho de Melo */ 383f421baaSArnaldo Carvalho de Melo int sysctl_local_port_range[2] = { 1024, 4999 }; 393f421baaSArnaldo Carvalho de Melo 403f421baaSArnaldo Carvalho de Melo static inline int inet_csk_bind_conflict(struct sock *sk, struct inet_bind_bucket *tb) 413f421baaSArnaldo Carvalho de Melo { 423f421baaSArnaldo Carvalho de Melo const u32 sk_rcv_saddr = inet_rcv_saddr(sk); 433f421baaSArnaldo Carvalho de Melo struct sock *sk2; 443f421baaSArnaldo Carvalho de Melo struct hlist_node *node; 453f421baaSArnaldo Carvalho de Melo int reuse = sk->sk_reuse; 463f421baaSArnaldo Carvalho de Melo 473f421baaSArnaldo Carvalho de Melo sk_for_each_bound(sk2, node, &tb->owners) { 483f421baaSArnaldo Carvalho de Melo if (sk != sk2 && 493f421baaSArnaldo Carvalho de Melo !inet_v6_ipv6only(sk2) && 503f421baaSArnaldo Carvalho de Melo (!sk->sk_bound_dev_if || 513f421baaSArnaldo Carvalho de Melo !sk2->sk_bound_dev_if || 523f421baaSArnaldo Carvalho de Melo sk->sk_bound_dev_if == sk2->sk_bound_dev_if)) { 533f421baaSArnaldo Carvalho de Melo if (!reuse || !sk2->sk_reuse || 543f421baaSArnaldo Carvalho de Melo sk2->sk_state == TCP_LISTEN) { 553f421baaSArnaldo Carvalho de Melo const u32 sk2_rcv_saddr = inet_rcv_saddr(sk2); 563f421baaSArnaldo Carvalho de Melo if (!sk2_rcv_saddr || !sk_rcv_saddr || 573f421baaSArnaldo Carvalho de Melo sk2_rcv_saddr == sk_rcv_saddr) 583f421baaSArnaldo Carvalho de Melo break; 593f421baaSArnaldo Carvalho de Melo } 603f421baaSArnaldo Carvalho de Melo } 613f421baaSArnaldo Carvalho de Melo } 623f421baaSArnaldo Carvalho de Melo return node != NULL; 633f421baaSArnaldo Carvalho de Melo } 643f421baaSArnaldo Carvalho de Melo 653f421baaSArnaldo Carvalho de Melo /* Obtain a reference to a local port for the given sock, 663f421baaSArnaldo Carvalho de Melo * if snum is zero it means select any available local port. 673f421baaSArnaldo Carvalho de Melo */ 683f421baaSArnaldo Carvalho de Melo int inet_csk_get_port(struct inet_hashinfo *hashinfo, 693f421baaSArnaldo Carvalho de Melo struct sock *sk, unsigned short snum) 703f421baaSArnaldo Carvalho de Melo { 713f421baaSArnaldo Carvalho de Melo struct inet_bind_hashbucket *head; 723f421baaSArnaldo Carvalho de Melo struct hlist_node *node; 733f421baaSArnaldo Carvalho de Melo struct inet_bind_bucket *tb; 743f421baaSArnaldo Carvalho de Melo int ret; 753f421baaSArnaldo Carvalho de Melo 763f421baaSArnaldo Carvalho de Melo local_bh_disable(); 773f421baaSArnaldo Carvalho de Melo if (!snum) { 783f421baaSArnaldo Carvalho de Melo int low = sysctl_local_port_range[0]; 793f421baaSArnaldo Carvalho de Melo int high = sysctl_local_port_range[1]; 803f421baaSArnaldo Carvalho de Melo int remaining = (high - low) + 1; 81*6df71634SStephen Hemminger int rover = net_random() % (high - low) + low; 823f421baaSArnaldo Carvalho de Melo 833f421baaSArnaldo Carvalho de Melo do { 843f421baaSArnaldo Carvalho de Melo head = &hashinfo->bhash[inet_bhashfn(rover, hashinfo->bhash_size)]; 853f421baaSArnaldo Carvalho de Melo spin_lock(&head->lock); 863f421baaSArnaldo Carvalho de Melo inet_bind_bucket_for_each(tb, node, &head->chain) 873f421baaSArnaldo Carvalho de Melo if (tb->port == rover) 883f421baaSArnaldo Carvalho de Melo goto next; 893f421baaSArnaldo Carvalho de Melo break; 903f421baaSArnaldo Carvalho de Melo next: 913f421baaSArnaldo Carvalho de Melo spin_unlock(&head->lock); 92*6df71634SStephen Hemminger if (++rover > high) 93*6df71634SStephen Hemminger rover = low; 943f421baaSArnaldo Carvalho de Melo } while (--remaining > 0); 953f421baaSArnaldo Carvalho de Melo 963f421baaSArnaldo Carvalho de Melo /* Exhausted local port range during search? It is not 973f421baaSArnaldo Carvalho de Melo * possible for us to be holding one of the bind hash 983f421baaSArnaldo Carvalho de Melo * locks if this test triggers, because if 'remaining' 993f421baaSArnaldo Carvalho de Melo * drops to zero, we broke out of the do/while loop at 1003f421baaSArnaldo Carvalho de Melo * the top level, not from the 'break;' statement. 1013f421baaSArnaldo Carvalho de Melo */ 1023f421baaSArnaldo Carvalho de Melo ret = 1; 1033f421baaSArnaldo Carvalho de Melo if (remaining <= 0) 1043f421baaSArnaldo Carvalho de Melo goto fail; 1053f421baaSArnaldo Carvalho de Melo 1063f421baaSArnaldo Carvalho de Melo /* OK, here is the one we will use. HEAD is 1073f421baaSArnaldo Carvalho de Melo * non-NULL and we hold it's mutex. 1083f421baaSArnaldo Carvalho de Melo */ 1093f421baaSArnaldo Carvalho de Melo snum = rover; 1103f421baaSArnaldo Carvalho de Melo } else { 1113f421baaSArnaldo Carvalho de Melo head = &hashinfo->bhash[inet_bhashfn(snum, hashinfo->bhash_size)]; 1123f421baaSArnaldo Carvalho de Melo spin_lock(&head->lock); 1133f421baaSArnaldo Carvalho de Melo inet_bind_bucket_for_each(tb, node, &head->chain) 1143f421baaSArnaldo Carvalho de Melo if (tb->port == snum) 1153f421baaSArnaldo Carvalho de Melo goto tb_found; 1163f421baaSArnaldo Carvalho de Melo } 1173f421baaSArnaldo Carvalho de Melo tb = NULL; 1183f421baaSArnaldo Carvalho de Melo goto tb_not_found; 1193f421baaSArnaldo Carvalho de Melo tb_found: 1203f421baaSArnaldo Carvalho de Melo if (!hlist_empty(&tb->owners)) { 1213f421baaSArnaldo Carvalho de Melo if (sk->sk_reuse > 1) 1223f421baaSArnaldo Carvalho de Melo goto success; 1233f421baaSArnaldo Carvalho de Melo if (tb->fastreuse > 0 && 1243f421baaSArnaldo Carvalho de Melo sk->sk_reuse && sk->sk_state != TCP_LISTEN) { 1253f421baaSArnaldo Carvalho de Melo goto success; 1263f421baaSArnaldo Carvalho de Melo } else { 1273f421baaSArnaldo Carvalho de Melo ret = 1; 1283f421baaSArnaldo Carvalho de Melo if (inet_csk_bind_conflict(sk, tb)) 1293f421baaSArnaldo Carvalho de Melo goto fail_unlock; 1303f421baaSArnaldo Carvalho de Melo } 1313f421baaSArnaldo Carvalho de Melo } 1323f421baaSArnaldo Carvalho de Melo tb_not_found: 1333f421baaSArnaldo Carvalho de Melo ret = 1; 1343f421baaSArnaldo Carvalho de Melo if (!tb && (tb = inet_bind_bucket_create(hashinfo->bind_bucket_cachep, head, snum)) == NULL) 1353f421baaSArnaldo Carvalho de Melo goto fail_unlock; 1363f421baaSArnaldo Carvalho de Melo if (hlist_empty(&tb->owners)) { 1373f421baaSArnaldo Carvalho de Melo if (sk->sk_reuse && sk->sk_state != TCP_LISTEN) 1383f421baaSArnaldo Carvalho de Melo tb->fastreuse = 1; 1393f421baaSArnaldo Carvalho de Melo else 1403f421baaSArnaldo Carvalho de Melo tb->fastreuse = 0; 1413f421baaSArnaldo Carvalho de Melo } else if (tb->fastreuse && 1423f421baaSArnaldo Carvalho de Melo (!sk->sk_reuse || sk->sk_state == TCP_LISTEN)) 1433f421baaSArnaldo Carvalho de Melo tb->fastreuse = 0; 1443f421baaSArnaldo Carvalho de Melo success: 1453f421baaSArnaldo Carvalho de Melo if (!inet_csk(sk)->icsk_bind_hash) 1463f421baaSArnaldo Carvalho de Melo inet_bind_hash(sk, tb, snum); 1473f421baaSArnaldo Carvalho de Melo BUG_TRAP(inet_csk(sk)->icsk_bind_hash == tb); 1483f421baaSArnaldo Carvalho de Melo ret = 0; 1493f421baaSArnaldo Carvalho de Melo 1503f421baaSArnaldo Carvalho de Melo fail_unlock: 1513f421baaSArnaldo Carvalho de Melo spin_unlock(&head->lock); 1523f421baaSArnaldo Carvalho de Melo fail: 1533f421baaSArnaldo Carvalho de Melo local_bh_enable(); 1543f421baaSArnaldo Carvalho de Melo return ret; 1553f421baaSArnaldo Carvalho de Melo } 1563f421baaSArnaldo Carvalho de Melo 1573f421baaSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(inet_csk_get_port); 1583f421baaSArnaldo Carvalho de Melo 1593f421baaSArnaldo Carvalho de Melo /* 1603f421baaSArnaldo Carvalho de Melo * Wait for an incoming connection, avoid race conditions. This must be called 1613f421baaSArnaldo Carvalho de Melo * with the socket locked. 1623f421baaSArnaldo Carvalho de Melo */ 1633f421baaSArnaldo Carvalho de Melo static int inet_csk_wait_for_connect(struct sock *sk, long timeo) 1643f421baaSArnaldo Carvalho de Melo { 1653f421baaSArnaldo Carvalho de Melo struct inet_connection_sock *icsk = inet_csk(sk); 1663f421baaSArnaldo Carvalho de Melo DEFINE_WAIT(wait); 1673f421baaSArnaldo Carvalho de Melo int err; 1683f421baaSArnaldo Carvalho de Melo 1693f421baaSArnaldo Carvalho de Melo /* 1703f421baaSArnaldo Carvalho de Melo * True wake-one mechanism for incoming connections: only 1713f421baaSArnaldo Carvalho de Melo * one process gets woken up, not the 'whole herd'. 1723f421baaSArnaldo Carvalho de Melo * Since we do not 'race & poll' for established sockets 1733f421baaSArnaldo Carvalho de Melo * anymore, the common case will execute the loop only once. 1743f421baaSArnaldo Carvalho de Melo * 1753f421baaSArnaldo Carvalho de Melo * Subtle issue: "add_wait_queue_exclusive()" will be added 1763f421baaSArnaldo Carvalho de Melo * after any current non-exclusive waiters, and we know that 1773f421baaSArnaldo Carvalho de Melo * it will always _stay_ after any new non-exclusive waiters 1783f421baaSArnaldo Carvalho de Melo * because all non-exclusive waiters are added at the 1793f421baaSArnaldo Carvalho de Melo * beginning of the wait-queue. As such, it's ok to "drop" 1803f421baaSArnaldo Carvalho de Melo * our exclusiveness temporarily when we get woken up without 1813f421baaSArnaldo Carvalho de Melo * having to remove and re-insert us on the wait queue. 1823f421baaSArnaldo Carvalho de Melo */ 1833f421baaSArnaldo Carvalho de Melo for (;;) { 1843f421baaSArnaldo Carvalho de Melo prepare_to_wait_exclusive(sk->sk_sleep, &wait, 1853f421baaSArnaldo Carvalho de Melo TASK_INTERRUPTIBLE); 1863f421baaSArnaldo Carvalho de Melo release_sock(sk); 1873f421baaSArnaldo Carvalho de Melo if (reqsk_queue_empty(&icsk->icsk_accept_queue)) 1883f421baaSArnaldo Carvalho de Melo timeo = schedule_timeout(timeo); 1893f421baaSArnaldo Carvalho de Melo lock_sock(sk); 1903f421baaSArnaldo Carvalho de Melo err = 0; 1913f421baaSArnaldo Carvalho de Melo if (!reqsk_queue_empty(&icsk->icsk_accept_queue)) 1923f421baaSArnaldo Carvalho de Melo break; 1933f421baaSArnaldo Carvalho de Melo err = -EINVAL; 1943f421baaSArnaldo Carvalho de Melo if (sk->sk_state != TCP_LISTEN) 1953f421baaSArnaldo Carvalho de Melo break; 1963f421baaSArnaldo Carvalho de Melo err = sock_intr_errno(timeo); 1973f421baaSArnaldo Carvalho de Melo if (signal_pending(current)) 1983f421baaSArnaldo Carvalho de Melo break; 1993f421baaSArnaldo Carvalho de Melo err = -EAGAIN; 2003f421baaSArnaldo Carvalho de Melo if (!timeo) 2013f421baaSArnaldo Carvalho de Melo break; 2023f421baaSArnaldo Carvalho de Melo } 2033f421baaSArnaldo Carvalho de Melo finish_wait(sk->sk_sleep, &wait); 2043f421baaSArnaldo Carvalho de Melo return err; 2053f421baaSArnaldo Carvalho de Melo } 2063f421baaSArnaldo Carvalho de Melo 2073f421baaSArnaldo Carvalho de Melo /* 2083f421baaSArnaldo Carvalho de Melo * This will accept the next outstanding connection. 2093f421baaSArnaldo Carvalho de Melo */ 2103f421baaSArnaldo Carvalho de Melo struct sock *inet_csk_accept(struct sock *sk, int flags, int *err) 2113f421baaSArnaldo Carvalho de Melo { 2123f421baaSArnaldo Carvalho de Melo struct inet_connection_sock *icsk = inet_csk(sk); 2133f421baaSArnaldo Carvalho de Melo struct sock *newsk; 2143f421baaSArnaldo Carvalho de Melo int error; 2153f421baaSArnaldo Carvalho de Melo 2163f421baaSArnaldo Carvalho de Melo lock_sock(sk); 2173f421baaSArnaldo Carvalho de Melo 2183f421baaSArnaldo Carvalho de Melo /* We need to make sure that this socket is listening, 2193f421baaSArnaldo Carvalho de Melo * and that it has something pending. 2203f421baaSArnaldo Carvalho de Melo */ 2213f421baaSArnaldo Carvalho de Melo error = -EINVAL; 2223f421baaSArnaldo Carvalho de Melo if (sk->sk_state != TCP_LISTEN) 2233f421baaSArnaldo Carvalho de Melo goto out_err; 2243f421baaSArnaldo Carvalho de Melo 2253f421baaSArnaldo Carvalho de Melo /* Find already established connection */ 2263f421baaSArnaldo Carvalho de Melo if (reqsk_queue_empty(&icsk->icsk_accept_queue)) { 2273f421baaSArnaldo Carvalho de Melo long timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); 2283f421baaSArnaldo Carvalho de Melo 2293f421baaSArnaldo Carvalho de Melo /* If this is a non blocking socket don't sleep */ 2303f421baaSArnaldo Carvalho de Melo error = -EAGAIN; 2313f421baaSArnaldo Carvalho de Melo if (!timeo) 2323f421baaSArnaldo Carvalho de Melo goto out_err; 2333f421baaSArnaldo Carvalho de Melo 2343f421baaSArnaldo Carvalho de Melo error = inet_csk_wait_for_connect(sk, timeo); 2353f421baaSArnaldo Carvalho de Melo if (error) 2363f421baaSArnaldo Carvalho de Melo goto out_err; 2373f421baaSArnaldo Carvalho de Melo } 2383f421baaSArnaldo Carvalho de Melo 2393f421baaSArnaldo Carvalho de Melo newsk = reqsk_queue_get_child(&icsk->icsk_accept_queue, sk); 2403f421baaSArnaldo Carvalho de Melo BUG_TRAP(newsk->sk_state != TCP_SYN_RECV); 2413f421baaSArnaldo Carvalho de Melo out: 2423f421baaSArnaldo Carvalho de Melo release_sock(sk); 2433f421baaSArnaldo Carvalho de Melo return newsk; 2443f421baaSArnaldo Carvalho de Melo out_err: 2453f421baaSArnaldo Carvalho de Melo newsk = NULL; 2463f421baaSArnaldo Carvalho de Melo *err = error; 2473f421baaSArnaldo Carvalho de Melo goto out; 2483f421baaSArnaldo Carvalho de Melo } 2493f421baaSArnaldo Carvalho de Melo 2503f421baaSArnaldo Carvalho de Melo EXPORT_SYMBOL(inet_csk_accept); 2513f421baaSArnaldo Carvalho de Melo 2523f421baaSArnaldo Carvalho de Melo /* 2533f421baaSArnaldo Carvalho de Melo * Using different timers for retransmit, delayed acks and probes 2543f421baaSArnaldo Carvalho de Melo * We may wish use just one timer maintaining a list of expire jiffies 2553f421baaSArnaldo Carvalho de Melo * to optimize. 2563f421baaSArnaldo Carvalho de Melo */ 2573f421baaSArnaldo Carvalho de Melo void inet_csk_init_xmit_timers(struct sock *sk, 2583f421baaSArnaldo Carvalho de Melo void (*retransmit_handler)(unsigned long), 2593f421baaSArnaldo Carvalho de Melo void (*delack_handler)(unsigned long), 2603f421baaSArnaldo Carvalho de Melo void (*keepalive_handler)(unsigned long)) 2613f421baaSArnaldo Carvalho de Melo { 2623f421baaSArnaldo Carvalho de Melo struct inet_connection_sock *icsk = inet_csk(sk); 2633f421baaSArnaldo Carvalho de Melo 2643f421baaSArnaldo Carvalho de Melo init_timer(&icsk->icsk_retransmit_timer); 2653f421baaSArnaldo Carvalho de Melo init_timer(&icsk->icsk_delack_timer); 2663f421baaSArnaldo Carvalho de Melo init_timer(&sk->sk_timer); 2673f421baaSArnaldo Carvalho de Melo 2683f421baaSArnaldo Carvalho de Melo icsk->icsk_retransmit_timer.function = retransmit_handler; 2693f421baaSArnaldo Carvalho de Melo icsk->icsk_delack_timer.function = delack_handler; 2703f421baaSArnaldo Carvalho de Melo sk->sk_timer.function = keepalive_handler; 2713f421baaSArnaldo Carvalho de Melo 2723f421baaSArnaldo Carvalho de Melo icsk->icsk_retransmit_timer.data = 2733f421baaSArnaldo Carvalho de Melo icsk->icsk_delack_timer.data = 2743f421baaSArnaldo Carvalho de Melo sk->sk_timer.data = (unsigned long)sk; 2753f421baaSArnaldo Carvalho de Melo 2763f421baaSArnaldo Carvalho de Melo icsk->icsk_pending = icsk->icsk_ack.pending = 0; 2773f421baaSArnaldo Carvalho de Melo } 2783f421baaSArnaldo Carvalho de Melo 2793f421baaSArnaldo Carvalho de Melo EXPORT_SYMBOL(inet_csk_init_xmit_timers); 2803f421baaSArnaldo Carvalho de Melo 2813f421baaSArnaldo Carvalho de Melo void inet_csk_clear_xmit_timers(struct sock *sk) 2823f421baaSArnaldo Carvalho de Melo { 2833f421baaSArnaldo Carvalho de Melo struct inet_connection_sock *icsk = inet_csk(sk); 2843f421baaSArnaldo Carvalho de Melo 2853f421baaSArnaldo Carvalho de Melo icsk->icsk_pending = icsk->icsk_ack.pending = icsk->icsk_ack.blocked = 0; 2863f421baaSArnaldo Carvalho de Melo 2873f421baaSArnaldo Carvalho de Melo sk_stop_timer(sk, &icsk->icsk_retransmit_timer); 2883f421baaSArnaldo Carvalho de Melo sk_stop_timer(sk, &icsk->icsk_delack_timer); 2893f421baaSArnaldo Carvalho de Melo sk_stop_timer(sk, &sk->sk_timer); 2903f421baaSArnaldo Carvalho de Melo } 2913f421baaSArnaldo Carvalho de Melo 2923f421baaSArnaldo Carvalho de Melo EXPORT_SYMBOL(inet_csk_clear_xmit_timers); 2933f421baaSArnaldo Carvalho de Melo 2943f421baaSArnaldo Carvalho de Melo void inet_csk_delete_keepalive_timer(struct sock *sk) 2953f421baaSArnaldo Carvalho de Melo { 2963f421baaSArnaldo Carvalho de Melo sk_stop_timer(sk, &sk->sk_timer); 2973f421baaSArnaldo Carvalho de Melo } 2983f421baaSArnaldo Carvalho de Melo 2993f421baaSArnaldo Carvalho de Melo EXPORT_SYMBOL(inet_csk_delete_keepalive_timer); 3003f421baaSArnaldo Carvalho de Melo 3013f421baaSArnaldo Carvalho de Melo void inet_csk_reset_keepalive_timer(struct sock *sk, unsigned long len) 3023f421baaSArnaldo Carvalho de Melo { 3033f421baaSArnaldo Carvalho de Melo sk_reset_timer(sk, &sk->sk_timer, jiffies + len); 3043f421baaSArnaldo Carvalho de Melo } 3053f421baaSArnaldo Carvalho de Melo 3063f421baaSArnaldo Carvalho de Melo EXPORT_SYMBOL(inet_csk_reset_keepalive_timer); 3073f421baaSArnaldo Carvalho de Melo 3083f421baaSArnaldo Carvalho de Melo struct dst_entry* inet_csk_route_req(struct sock *sk, 3093f421baaSArnaldo Carvalho de Melo const struct request_sock *req) 3103f421baaSArnaldo Carvalho de Melo { 3113f421baaSArnaldo Carvalho de Melo struct rtable *rt; 3123f421baaSArnaldo Carvalho de Melo const struct inet_request_sock *ireq = inet_rsk(req); 3133f421baaSArnaldo Carvalho de Melo struct ip_options *opt = inet_rsk(req)->opt; 3143f421baaSArnaldo Carvalho de Melo struct flowi fl = { .oif = sk->sk_bound_dev_if, 3153f421baaSArnaldo Carvalho de Melo .nl_u = { .ip4_u = 3163f421baaSArnaldo Carvalho de Melo { .daddr = ((opt && opt->srr) ? 3173f421baaSArnaldo Carvalho de Melo opt->faddr : 3183f421baaSArnaldo Carvalho de Melo ireq->rmt_addr), 3193f421baaSArnaldo Carvalho de Melo .saddr = ireq->loc_addr, 3203f421baaSArnaldo Carvalho de Melo .tos = RT_CONN_FLAGS(sk) } }, 3213f421baaSArnaldo Carvalho de Melo .proto = sk->sk_protocol, 3223f421baaSArnaldo Carvalho de Melo .uli_u = { .ports = 3233f421baaSArnaldo Carvalho de Melo { .sport = inet_sk(sk)->sport, 3243f421baaSArnaldo Carvalho de Melo .dport = ireq->rmt_port } } }; 3253f421baaSArnaldo Carvalho de Melo 3263f421baaSArnaldo Carvalho de Melo if (ip_route_output_flow(&rt, &fl, sk, 0)) { 3273f421baaSArnaldo Carvalho de Melo IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES); 3283f421baaSArnaldo Carvalho de Melo return NULL; 3293f421baaSArnaldo Carvalho de Melo } 3303f421baaSArnaldo Carvalho de Melo if (opt && opt->is_strictroute && rt->rt_dst != rt->rt_gateway) { 3313f421baaSArnaldo Carvalho de Melo ip_rt_put(rt); 3323f421baaSArnaldo Carvalho de Melo IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES); 3333f421baaSArnaldo Carvalho de Melo return NULL; 3343f421baaSArnaldo Carvalho de Melo } 3353f421baaSArnaldo Carvalho de Melo return &rt->u.dst; 3363f421baaSArnaldo Carvalho de Melo } 3373f421baaSArnaldo Carvalho de Melo 3383f421baaSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(inet_csk_route_req); 3393f421baaSArnaldo Carvalho de Melo 3403f421baaSArnaldo Carvalho de Melo static inline u32 inet_synq_hash(const u32 raddr, const u16 rport, 3413f421baaSArnaldo Carvalho de Melo const u32 rnd, const u16 synq_hsize) 3423f421baaSArnaldo Carvalho de Melo { 3433f421baaSArnaldo Carvalho de Melo return jhash_2words(raddr, (u32)rport, rnd) & (synq_hsize - 1); 3443f421baaSArnaldo Carvalho de Melo } 3453f421baaSArnaldo Carvalho de Melo 3463f421baaSArnaldo Carvalho de Melo #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 3473f421baaSArnaldo Carvalho de Melo #define AF_INET_FAMILY(fam) ((fam) == AF_INET) 3483f421baaSArnaldo Carvalho de Melo #else 3493f421baaSArnaldo Carvalho de Melo #define AF_INET_FAMILY(fam) 1 3503f421baaSArnaldo Carvalho de Melo #endif 3513f421baaSArnaldo Carvalho de Melo 3523f421baaSArnaldo Carvalho de Melo struct request_sock *inet_csk_search_req(const struct sock *sk, 3533f421baaSArnaldo Carvalho de Melo struct request_sock ***prevp, 3543f421baaSArnaldo Carvalho de Melo const __u16 rport, const __u32 raddr, 3553f421baaSArnaldo Carvalho de Melo const __u32 laddr) 3563f421baaSArnaldo Carvalho de Melo { 3573f421baaSArnaldo Carvalho de Melo const struct inet_connection_sock *icsk = inet_csk(sk); 3583f421baaSArnaldo Carvalho de Melo struct listen_sock *lopt = icsk->icsk_accept_queue.listen_opt; 3593f421baaSArnaldo Carvalho de Melo struct request_sock *req, **prev; 3603f421baaSArnaldo Carvalho de Melo 3613f421baaSArnaldo Carvalho de Melo for (prev = &lopt->syn_table[inet_synq_hash(raddr, rport, lopt->hash_rnd, 3623f421baaSArnaldo Carvalho de Melo lopt->nr_table_entries)]; 3633f421baaSArnaldo Carvalho de Melo (req = *prev) != NULL; 3643f421baaSArnaldo Carvalho de Melo prev = &req->dl_next) { 3653f421baaSArnaldo Carvalho de Melo const struct inet_request_sock *ireq = inet_rsk(req); 3663f421baaSArnaldo Carvalho de Melo 3673f421baaSArnaldo Carvalho de Melo if (ireq->rmt_port == rport && 3683f421baaSArnaldo Carvalho de Melo ireq->rmt_addr == raddr && 3693f421baaSArnaldo Carvalho de Melo ireq->loc_addr == laddr && 3703f421baaSArnaldo Carvalho de Melo AF_INET_FAMILY(req->rsk_ops->family)) { 3713f421baaSArnaldo Carvalho de Melo BUG_TRAP(!req->sk); 3723f421baaSArnaldo Carvalho de Melo *prevp = prev; 3733f421baaSArnaldo Carvalho de Melo break; 3743f421baaSArnaldo Carvalho de Melo } 3753f421baaSArnaldo Carvalho de Melo } 3763f421baaSArnaldo Carvalho de Melo 3773f421baaSArnaldo Carvalho de Melo return req; 3783f421baaSArnaldo Carvalho de Melo } 3793f421baaSArnaldo Carvalho de Melo 3803f421baaSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(inet_csk_search_req); 3813f421baaSArnaldo Carvalho de Melo 3823f421baaSArnaldo Carvalho de Melo void inet_csk_reqsk_queue_hash_add(struct sock *sk, struct request_sock *req, 3833f421baaSArnaldo Carvalho de Melo const unsigned timeout) 3843f421baaSArnaldo Carvalho de Melo { 3853f421baaSArnaldo Carvalho de Melo struct inet_connection_sock *icsk = inet_csk(sk); 3863f421baaSArnaldo Carvalho de Melo struct listen_sock *lopt = icsk->icsk_accept_queue.listen_opt; 3873f421baaSArnaldo Carvalho de Melo const u32 h = inet_synq_hash(inet_rsk(req)->rmt_addr, inet_rsk(req)->rmt_port, 3883f421baaSArnaldo Carvalho de Melo lopt->hash_rnd, lopt->nr_table_entries); 3893f421baaSArnaldo Carvalho de Melo 3903f421baaSArnaldo Carvalho de Melo reqsk_queue_hash_req(&icsk->icsk_accept_queue, h, req, timeout); 3913f421baaSArnaldo Carvalho de Melo inet_csk_reqsk_queue_added(sk, timeout); 3923f421baaSArnaldo Carvalho de Melo } 3933f421baaSArnaldo Carvalho de Melo 394a019d6feSArnaldo Carvalho de Melo /* Only thing we need from tcp.h */ 395a019d6feSArnaldo Carvalho de Melo extern int sysctl_tcp_synack_retries; 396a019d6feSArnaldo Carvalho de Melo 3973f421baaSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(inet_csk_reqsk_queue_hash_add); 3989f1d2604SArnaldo Carvalho de Melo 399a019d6feSArnaldo Carvalho de Melo void inet_csk_reqsk_queue_prune(struct sock *parent, 400a019d6feSArnaldo Carvalho de Melo const unsigned long interval, 401a019d6feSArnaldo Carvalho de Melo const unsigned long timeout, 402a019d6feSArnaldo Carvalho de Melo const unsigned long max_rto) 403a019d6feSArnaldo Carvalho de Melo { 404a019d6feSArnaldo Carvalho de Melo struct inet_connection_sock *icsk = inet_csk(parent); 405a019d6feSArnaldo Carvalho de Melo struct request_sock_queue *queue = &icsk->icsk_accept_queue; 406a019d6feSArnaldo Carvalho de Melo struct listen_sock *lopt = queue->listen_opt; 407a019d6feSArnaldo Carvalho de Melo int max_retries = icsk->icsk_syn_retries ? : sysctl_tcp_synack_retries; 408a019d6feSArnaldo Carvalho de Melo int thresh = max_retries; 409a019d6feSArnaldo Carvalho de Melo unsigned long now = jiffies; 410a019d6feSArnaldo Carvalho de Melo struct request_sock **reqp, *req; 411a019d6feSArnaldo Carvalho de Melo int i, budget; 412a019d6feSArnaldo Carvalho de Melo 413a019d6feSArnaldo Carvalho de Melo if (lopt == NULL || lopt->qlen == 0) 414a019d6feSArnaldo Carvalho de Melo return; 415a019d6feSArnaldo Carvalho de Melo 416a019d6feSArnaldo Carvalho de Melo /* Normally all the openreqs are young and become mature 417a019d6feSArnaldo Carvalho de Melo * (i.e. converted to established socket) for first timeout. 418a019d6feSArnaldo Carvalho de Melo * If synack was not acknowledged for 3 seconds, it means 419a019d6feSArnaldo Carvalho de Melo * one of the following things: synack was lost, ack was lost, 420a019d6feSArnaldo Carvalho de Melo * rtt is high or nobody planned to ack (i.e. synflood). 421a019d6feSArnaldo Carvalho de Melo * When server is a bit loaded, queue is populated with old 422a019d6feSArnaldo Carvalho de Melo * open requests, reducing effective size of queue. 423a019d6feSArnaldo Carvalho de Melo * When server is well loaded, queue size reduces to zero 424a019d6feSArnaldo Carvalho de Melo * after several minutes of work. It is not synflood, 425a019d6feSArnaldo Carvalho de Melo * it is normal operation. The solution is pruning 426a019d6feSArnaldo Carvalho de Melo * too old entries overriding normal timeout, when 427a019d6feSArnaldo Carvalho de Melo * situation becomes dangerous. 428a019d6feSArnaldo Carvalho de Melo * 429a019d6feSArnaldo Carvalho de Melo * Essentially, we reserve half of room for young 430a019d6feSArnaldo Carvalho de Melo * embrions; and abort old ones without pity, if old 431a019d6feSArnaldo Carvalho de Melo * ones are about to clog our table. 432a019d6feSArnaldo Carvalho de Melo */ 433a019d6feSArnaldo Carvalho de Melo if (lopt->qlen>>(lopt->max_qlen_log-1)) { 434a019d6feSArnaldo Carvalho de Melo int young = (lopt->qlen_young<<1); 435a019d6feSArnaldo Carvalho de Melo 436a019d6feSArnaldo Carvalho de Melo while (thresh > 2) { 437a019d6feSArnaldo Carvalho de Melo if (lopt->qlen < young) 438a019d6feSArnaldo Carvalho de Melo break; 439a019d6feSArnaldo Carvalho de Melo thresh--; 440a019d6feSArnaldo Carvalho de Melo young <<= 1; 441a019d6feSArnaldo Carvalho de Melo } 442a019d6feSArnaldo Carvalho de Melo } 443a019d6feSArnaldo Carvalho de Melo 444a019d6feSArnaldo Carvalho de Melo if (queue->rskq_defer_accept) 445a019d6feSArnaldo Carvalho de Melo max_retries = queue->rskq_defer_accept; 446a019d6feSArnaldo Carvalho de Melo 447a019d6feSArnaldo Carvalho de Melo budget = 2 * (lopt->nr_table_entries / (timeout / interval)); 448a019d6feSArnaldo Carvalho de Melo i = lopt->clock_hand; 449a019d6feSArnaldo Carvalho de Melo 450a019d6feSArnaldo Carvalho de Melo do { 451a019d6feSArnaldo Carvalho de Melo reqp=&lopt->syn_table[i]; 452a019d6feSArnaldo Carvalho de Melo while ((req = *reqp) != NULL) { 453a019d6feSArnaldo Carvalho de Melo if (time_after_eq(now, req->expires)) { 454a019d6feSArnaldo Carvalho de Melo if ((req->retrans < thresh || 455a019d6feSArnaldo Carvalho de Melo (inet_rsk(req)->acked && req->retrans < max_retries)) 456a019d6feSArnaldo Carvalho de Melo && !req->rsk_ops->rtx_syn_ack(parent, req, NULL)) { 457a019d6feSArnaldo Carvalho de Melo unsigned long timeo; 458a019d6feSArnaldo Carvalho de Melo 459a019d6feSArnaldo Carvalho de Melo if (req->retrans++ == 0) 460a019d6feSArnaldo Carvalho de Melo lopt->qlen_young--; 461a019d6feSArnaldo Carvalho de Melo timeo = min((timeout << req->retrans), max_rto); 462a019d6feSArnaldo Carvalho de Melo req->expires = now + timeo; 463a019d6feSArnaldo Carvalho de Melo reqp = &req->dl_next; 464a019d6feSArnaldo Carvalho de Melo continue; 465a019d6feSArnaldo Carvalho de Melo } 466a019d6feSArnaldo Carvalho de Melo 467a019d6feSArnaldo Carvalho de Melo /* Drop this request */ 468a019d6feSArnaldo Carvalho de Melo inet_csk_reqsk_queue_unlink(parent, req, reqp); 469a019d6feSArnaldo Carvalho de Melo reqsk_queue_removed(queue, req); 470a019d6feSArnaldo Carvalho de Melo reqsk_free(req); 471a019d6feSArnaldo Carvalho de Melo continue; 472a019d6feSArnaldo Carvalho de Melo } 473a019d6feSArnaldo Carvalho de Melo reqp = &req->dl_next; 474a019d6feSArnaldo Carvalho de Melo } 475a019d6feSArnaldo Carvalho de Melo 476a019d6feSArnaldo Carvalho de Melo i = (i + 1) & (lopt->nr_table_entries - 1); 477a019d6feSArnaldo Carvalho de Melo 478a019d6feSArnaldo Carvalho de Melo } while (--budget > 0); 479a019d6feSArnaldo Carvalho de Melo 480a019d6feSArnaldo Carvalho de Melo lopt->clock_hand = i; 481a019d6feSArnaldo Carvalho de Melo 482a019d6feSArnaldo Carvalho de Melo if (lopt->qlen) 483a019d6feSArnaldo Carvalho de Melo inet_csk_reset_keepalive_timer(parent, interval); 484a019d6feSArnaldo Carvalho de Melo } 485a019d6feSArnaldo Carvalho de Melo 486a019d6feSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(inet_csk_reqsk_queue_prune); 487a019d6feSArnaldo Carvalho de Melo 4889f1d2604SArnaldo Carvalho de Melo struct sock *inet_csk_clone(struct sock *sk, const struct request_sock *req, 489dd0fc66fSAl Viro const gfp_t priority) 4909f1d2604SArnaldo Carvalho de Melo { 4919f1d2604SArnaldo Carvalho de Melo struct sock *newsk = sk_clone(sk, priority); 4929f1d2604SArnaldo Carvalho de Melo 4939f1d2604SArnaldo Carvalho de Melo if (newsk != NULL) { 4949f1d2604SArnaldo Carvalho de Melo struct inet_connection_sock *newicsk = inet_csk(newsk); 4959f1d2604SArnaldo Carvalho de Melo 4969f1d2604SArnaldo Carvalho de Melo newsk->sk_state = TCP_SYN_RECV; 4979f1d2604SArnaldo Carvalho de Melo newicsk->icsk_bind_hash = NULL; 4989f1d2604SArnaldo Carvalho de Melo 4999f1d2604SArnaldo Carvalho de Melo inet_sk(newsk)->dport = inet_rsk(req)->rmt_port; 5009f1d2604SArnaldo Carvalho de Melo newsk->sk_write_space = sk_stream_write_space; 5019f1d2604SArnaldo Carvalho de Melo 5029f1d2604SArnaldo Carvalho de Melo newicsk->icsk_retransmits = 0; 5039f1d2604SArnaldo Carvalho de Melo newicsk->icsk_backoff = 0; 5046687e988SArnaldo Carvalho de Melo newicsk->icsk_probes_out = 0; 5059f1d2604SArnaldo Carvalho de Melo 5069f1d2604SArnaldo Carvalho de Melo /* Deinitialize accept_queue to trap illegal accesses. */ 5079f1d2604SArnaldo Carvalho de Melo memset(&newicsk->icsk_accept_queue, 0, sizeof(newicsk->icsk_accept_queue)); 5089f1d2604SArnaldo Carvalho de Melo } 5099f1d2604SArnaldo Carvalho de Melo return newsk; 5109f1d2604SArnaldo Carvalho de Melo } 5119f1d2604SArnaldo Carvalho de Melo 5129f1d2604SArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(inet_csk_clone); 513a019d6feSArnaldo Carvalho de Melo 514a019d6feSArnaldo Carvalho de Melo /* 515a019d6feSArnaldo Carvalho de Melo * At this point, there should be no process reference to this 516a019d6feSArnaldo Carvalho de Melo * socket, and thus no user references at all. Therefore we 517a019d6feSArnaldo Carvalho de Melo * can assume the socket waitqueue is inactive and nobody will 518a019d6feSArnaldo Carvalho de Melo * try to jump onto it. 519a019d6feSArnaldo Carvalho de Melo */ 520a019d6feSArnaldo Carvalho de Melo void inet_csk_destroy_sock(struct sock *sk) 521a019d6feSArnaldo Carvalho de Melo { 522a019d6feSArnaldo Carvalho de Melo BUG_TRAP(sk->sk_state == TCP_CLOSE); 523a019d6feSArnaldo Carvalho de Melo BUG_TRAP(sock_flag(sk, SOCK_DEAD)); 524a019d6feSArnaldo Carvalho de Melo 525a019d6feSArnaldo Carvalho de Melo /* It cannot be in hash table! */ 526a019d6feSArnaldo Carvalho de Melo BUG_TRAP(sk_unhashed(sk)); 527a019d6feSArnaldo Carvalho de Melo 528a019d6feSArnaldo Carvalho de Melo /* If it has not 0 inet_sk(sk)->num, it must be bound */ 529a019d6feSArnaldo Carvalho de Melo BUG_TRAP(!inet_sk(sk)->num || inet_csk(sk)->icsk_bind_hash); 530a019d6feSArnaldo Carvalho de Melo 531a019d6feSArnaldo Carvalho de Melo sk->sk_prot->destroy(sk); 532a019d6feSArnaldo Carvalho de Melo 533a019d6feSArnaldo Carvalho de Melo sk_stream_kill_queues(sk); 534a019d6feSArnaldo Carvalho de Melo 535a019d6feSArnaldo Carvalho de Melo xfrm_sk_free_policy(sk); 536a019d6feSArnaldo Carvalho de Melo 537a019d6feSArnaldo Carvalho de Melo sk_refcnt_debug_release(sk); 538a019d6feSArnaldo Carvalho de Melo 539a019d6feSArnaldo Carvalho de Melo atomic_dec(sk->sk_prot->orphan_count); 540a019d6feSArnaldo Carvalho de Melo sock_put(sk); 541a019d6feSArnaldo Carvalho de Melo } 542a019d6feSArnaldo Carvalho de Melo 543a019d6feSArnaldo Carvalho de Melo EXPORT_SYMBOL(inet_csk_destroy_sock); 544a019d6feSArnaldo Carvalho de Melo 545a019d6feSArnaldo Carvalho de Melo int inet_csk_listen_start(struct sock *sk, const int nr_table_entries) 546a019d6feSArnaldo Carvalho de Melo { 547a019d6feSArnaldo Carvalho de Melo struct inet_sock *inet = inet_sk(sk); 548a019d6feSArnaldo Carvalho de Melo struct inet_connection_sock *icsk = inet_csk(sk); 549a019d6feSArnaldo Carvalho de Melo int rc = reqsk_queue_alloc(&icsk->icsk_accept_queue, nr_table_entries); 550a019d6feSArnaldo Carvalho de Melo 551a019d6feSArnaldo Carvalho de Melo if (rc != 0) 552a019d6feSArnaldo Carvalho de Melo return rc; 553a019d6feSArnaldo Carvalho de Melo 554a019d6feSArnaldo Carvalho de Melo sk->sk_max_ack_backlog = 0; 555a019d6feSArnaldo Carvalho de Melo sk->sk_ack_backlog = 0; 556a019d6feSArnaldo Carvalho de Melo inet_csk_delack_init(sk); 557a019d6feSArnaldo Carvalho de Melo 558a019d6feSArnaldo Carvalho de Melo /* There is race window here: we announce ourselves listening, 559a019d6feSArnaldo Carvalho de Melo * but this transition is still not validated by get_port(). 560a019d6feSArnaldo Carvalho de Melo * It is OK, because this socket enters to hash table only 561a019d6feSArnaldo Carvalho de Melo * after validation is complete. 562a019d6feSArnaldo Carvalho de Melo */ 563a019d6feSArnaldo Carvalho de Melo sk->sk_state = TCP_LISTEN; 564a019d6feSArnaldo Carvalho de Melo if (!sk->sk_prot->get_port(sk, inet->num)) { 565a019d6feSArnaldo Carvalho de Melo inet->sport = htons(inet->num); 566a019d6feSArnaldo Carvalho de Melo 567a019d6feSArnaldo Carvalho de Melo sk_dst_reset(sk); 568a019d6feSArnaldo Carvalho de Melo sk->sk_prot->hash(sk); 569a019d6feSArnaldo Carvalho de Melo 570a019d6feSArnaldo Carvalho de Melo return 0; 571a019d6feSArnaldo Carvalho de Melo } 572a019d6feSArnaldo Carvalho de Melo 573a019d6feSArnaldo Carvalho de Melo sk->sk_state = TCP_CLOSE; 574a019d6feSArnaldo Carvalho de Melo __reqsk_queue_destroy(&icsk->icsk_accept_queue); 575a019d6feSArnaldo Carvalho de Melo return -EADDRINUSE; 576a019d6feSArnaldo Carvalho de Melo } 577a019d6feSArnaldo Carvalho de Melo 578a019d6feSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(inet_csk_listen_start); 579a019d6feSArnaldo Carvalho de Melo 580a019d6feSArnaldo Carvalho de Melo /* 581a019d6feSArnaldo Carvalho de Melo * This routine closes sockets which have been at least partially 582a019d6feSArnaldo Carvalho de Melo * opened, but not yet accepted. 583a019d6feSArnaldo Carvalho de Melo */ 584a019d6feSArnaldo Carvalho de Melo void inet_csk_listen_stop(struct sock *sk) 585a019d6feSArnaldo Carvalho de Melo { 586a019d6feSArnaldo Carvalho de Melo struct inet_connection_sock *icsk = inet_csk(sk); 587a019d6feSArnaldo Carvalho de Melo struct request_sock *acc_req; 588a019d6feSArnaldo Carvalho de Melo struct request_sock *req; 589a019d6feSArnaldo Carvalho de Melo 590a019d6feSArnaldo Carvalho de Melo inet_csk_delete_keepalive_timer(sk); 591a019d6feSArnaldo Carvalho de Melo 592a019d6feSArnaldo Carvalho de Melo /* make all the listen_opt local to us */ 593a019d6feSArnaldo Carvalho de Melo acc_req = reqsk_queue_yank_acceptq(&icsk->icsk_accept_queue); 594a019d6feSArnaldo Carvalho de Melo 595a019d6feSArnaldo Carvalho de Melo /* Following specs, it would be better either to send FIN 596a019d6feSArnaldo Carvalho de Melo * (and enter FIN-WAIT-1, it is normal close) 597a019d6feSArnaldo Carvalho de Melo * or to send active reset (abort). 598a019d6feSArnaldo Carvalho de Melo * Certainly, it is pretty dangerous while synflood, but it is 599a019d6feSArnaldo Carvalho de Melo * bad justification for our negligence 8) 600a019d6feSArnaldo Carvalho de Melo * To be honest, we are not able to make either 601a019d6feSArnaldo Carvalho de Melo * of the variants now. --ANK 602a019d6feSArnaldo Carvalho de Melo */ 603a019d6feSArnaldo Carvalho de Melo reqsk_queue_destroy(&icsk->icsk_accept_queue); 604a019d6feSArnaldo Carvalho de Melo 605a019d6feSArnaldo Carvalho de Melo while ((req = acc_req) != NULL) { 606a019d6feSArnaldo Carvalho de Melo struct sock *child = req->sk; 607a019d6feSArnaldo Carvalho de Melo 608a019d6feSArnaldo Carvalho de Melo acc_req = req->dl_next; 609a019d6feSArnaldo Carvalho de Melo 610a019d6feSArnaldo Carvalho de Melo local_bh_disable(); 611a019d6feSArnaldo Carvalho de Melo bh_lock_sock(child); 612a019d6feSArnaldo Carvalho de Melo BUG_TRAP(!sock_owned_by_user(child)); 613a019d6feSArnaldo Carvalho de Melo sock_hold(child); 614a019d6feSArnaldo Carvalho de Melo 615a019d6feSArnaldo Carvalho de Melo sk->sk_prot->disconnect(child, O_NONBLOCK); 616a019d6feSArnaldo Carvalho de Melo 617a019d6feSArnaldo Carvalho de Melo sock_orphan(child); 618a019d6feSArnaldo Carvalho de Melo 619a019d6feSArnaldo Carvalho de Melo atomic_inc(sk->sk_prot->orphan_count); 620a019d6feSArnaldo Carvalho de Melo 621a019d6feSArnaldo Carvalho de Melo inet_csk_destroy_sock(child); 622a019d6feSArnaldo Carvalho de Melo 623a019d6feSArnaldo Carvalho de Melo bh_unlock_sock(child); 624a019d6feSArnaldo Carvalho de Melo local_bh_enable(); 625a019d6feSArnaldo Carvalho de Melo sock_put(child); 626a019d6feSArnaldo Carvalho de Melo 627a019d6feSArnaldo Carvalho de Melo sk_acceptq_removed(sk); 628a019d6feSArnaldo Carvalho de Melo __reqsk_free(req); 629a019d6feSArnaldo Carvalho de Melo } 630a019d6feSArnaldo Carvalho de Melo BUG_TRAP(!sk->sk_ack_backlog); 631a019d6feSArnaldo Carvalho de Melo } 632a019d6feSArnaldo Carvalho de Melo 633a019d6feSArnaldo Carvalho de Melo EXPORT_SYMBOL_GPL(inet_csk_listen_stop); 634