aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/request_sock.h5
-rw-r--r--net/core/request_sock.c26
-rw-r--r--net/ipv4/tcp.c35
3 files changed, 40 insertions, 26 deletions
diff --git a/include/net/request_sock.h b/include/net/request_sock.h
index 72fd6f5e86b1..334717bf9ef6 100644
--- a/include/net/request_sock.h
+++ b/include/net/request_sock.h
@@ -89,6 +89,7 @@ struct listen_sock {
89 int qlen_young; 89 int qlen_young;
90 int clock_hand; 90 int clock_hand;
91 u32 hash_rnd; 91 u32 hash_rnd;
92 u32 nr_table_entries;
92 struct request_sock *syn_table[0]; 93 struct request_sock *syn_table[0];
93}; 94};
94 95
@@ -129,11 +130,13 @@ static inline struct listen_sock *reqsk_queue_yank_listen_sk(struct request_sock
129 return lopt; 130 return lopt;
130} 131}
131 132
132static inline void reqsk_queue_destroy(struct request_sock_queue *queue) 133static inline void __reqsk_queue_destroy(struct request_sock_queue *queue)
133{ 134{
134 kfree(reqsk_queue_yank_listen_sk(queue)); 135 kfree(reqsk_queue_yank_listen_sk(queue));
135} 136}
136 137
138extern void reqsk_queue_destroy(struct request_sock_queue *queue);
139
137static inline struct request_sock * 140static inline struct request_sock *
138 reqsk_queue_yank_acceptq(struct request_sock_queue *queue) 141 reqsk_queue_yank_acceptq(struct request_sock_queue *queue)
139{ 142{
diff --git a/net/core/request_sock.c b/net/core/request_sock.c
index bb55675f0685..4e99ce5c08f2 100644
--- a/net/core/request_sock.c
+++ b/net/core/request_sock.c
@@ -53,6 +53,7 @@ int reqsk_queue_alloc(struct request_sock_queue *queue,
53 get_random_bytes(&lopt->hash_rnd, sizeof(lopt->hash_rnd)); 53 get_random_bytes(&lopt->hash_rnd, sizeof(lopt->hash_rnd));
54 rwlock_init(&queue->syn_wait_lock); 54 rwlock_init(&queue->syn_wait_lock);
55 queue->rskq_accept_head = queue->rskq_accept_head = NULL; 55 queue->rskq_accept_head = queue->rskq_accept_head = NULL;
56 lopt->nr_table_entries = nr_table_entries;
56 57
57 write_lock_bh(&queue->syn_wait_lock); 58 write_lock_bh(&queue->syn_wait_lock);
58 queue->listen_opt = lopt; 59 queue->listen_opt = lopt;
@@ -62,3 +63,28 @@ int reqsk_queue_alloc(struct request_sock_queue *queue,
62} 63}
63 64
64EXPORT_SYMBOL(reqsk_queue_alloc); 65EXPORT_SYMBOL(reqsk_queue_alloc);
66
67void reqsk_queue_destroy(struct request_sock_queue *queue)
68{
69 /* make all the listen_opt local to us */
70 struct listen_sock *lopt = reqsk_queue_yank_listen_sk(queue);
71
72 if (lopt->qlen != 0) {
73 int i;
74
75 for (i = 0; i < lopt->nr_table_entries; i++) {
76 struct request_sock *req;
77
78 while ((req = lopt->syn_table[i]) != NULL) {
79 lopt->syn_table[i] = req->dl_next;
80 lopt->qlen--;
81 reqsk_free(req);
82 }
83 }
84 }
85
86 BUG_TRAP(lopt->qlen == 0);
87 kfree(lopt);
88}
89
90EXPORT_SYMBOL(reqsk_queue_destroy);
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index d2696af46c70..42a2e2ccd430 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -487,7 +487,7 @@ int tcp_listen_start(struct sock *sk)
487 } 487 }
488 488
489 sk->sk_state = TCP_CLOSE; 489 sk->sk_state = TCP_CLOSE;
490 reqsk_queue_destroy(&tp->accept_queue); 490 __reqsk_queue_destroy(&tp->accept_queue);
491 return -EADDRINUSE; 491 return -EADDRINUSE;
492} 492}
493 493
@@ -499,38 +499,23 @@ int tcp_listen_start(struct sock *sk)
499static void tcp_listen_stop (struct sock *sk) 499static void tcp_listen_stop (struct sock *sk)
500{ 500{
501 struct tcp_sock *tp = tcp_sk(sk); 501 struct tcp_sock *tp = tcp_sk(sk);
502 struct listen_sock *lopt;
503 struct request_sock *acc_req; 502 struct request_sock *acc_req;
504 struct request_sock *req; 503 struct request_sock *req;
505 int i;
506 504
507 tcp_delete_keepalive_timer(sk); 505 tcp_delete_keepalive_timer(sk);
508 506
509 /* make all the listen_opt local to us */ 507 /* make all the listen_opt local to us */
510 lopt = reqsk_queue_yank_listen_sk(&tp->accept_queue);
511 acc_req = reqsk_queue_yank_acceptq(&tp->accept_queue); 508 acc_req = reqsk_queue_yank_acceptq(&tp->accept_queue);
512 509
513 if (lopt->qlen) { 510 /* Following specs, it would be better either to send FIN
514 for (i = 0; i < TCP_SYNQ_HSIZE; i++) { 511 * (and enter FIN-WAIT-1, it is normal close)
515 while ((req = lopt->syn_table[i]) != NULL) { 512 * or to send active reset (abort).
516 lopt->syn_table[i] = req->dl_next; 513 * Certainly, it is pretty dangerous while synflood, but it is
517 lopt->qlen--; 514 * bad justification for our negligence 8)
518 reqsk_free(req); 515 * To be honest, we are not able to make either
519 516 * of the variants now. --ANK
520 /* Following specs, it would be better either to send FIN 517 */
521 * (and enter FIN-WAIT-1, it is normal close) 518 reqsk_queue_destroy(&tp->accept_queue);
522 * or to send active reset (abort).
523 * Certainly, it is pretty dangerous while synflood, but it is
524 * bad justification for our negligence 8)
525 * To be honest, we are not able to make either
526 * of the variants now. --ANK
527 */
528 }
529 }
530 }
531 BUG_TRAP(!lopt->qlen);
532
533 kfree(lopt);
534 519
535 while ((req = acc_req) != NULL) { 520 while ((req = acc_req) != NULL) {
536 struct sock *child = req->sk; 521 struct sock *child = req->sk;