diff options
| -rw-r--r-- | include/net/request_sock.h | 5 | ||||
| -rw-r--r-- | net/core/request_sock.c | 26 | ||||
| -rw-r--r-- | net/ipv4/tcp.c | 35 |
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 | ||
| 132 | static inline void reqsk_queue_destroy(struct request_sock_queue *queue) | 133 | static 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 | ||
| 138 | extern void reqsk_queue_destroy(struct request_sock_queue *queue); | ||
| 139 | |||
| 137 | static inline struct request_sock * | 140 | static 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 | ||
| 64 | EXPORT_SYMBOL(reqsk_queue_alloc); | 65 | EXPORT_SYMBOL(reqsk_queue_alloc); |
| 66 | |||
| 67 | void 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 | |||
| 90 | EXPORT_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) | |||
| 499 | static void tcp_listen_stop (struct sock *sk) | 499 | static 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; |
