aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/inet_connection_sock.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/inet_connection_sock.c')
-rw-r--r--net/ipv4/inet_connection_sock.c64
1 files changed, 57 insertions, 7 deletions
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index db0cf17c00f7..f0c5b9c1a957 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -283,7 +283,9 @@ static int inet_csk_wait_for_connect(struct sock *sk, long timeo)
283struct sock *inet_csk_accept(struct sock *sk, int flags, int *err) 283struct sock *inet_csk_accept(struct sock *sk, int flags, int *err)
284{ 284{
285 struct inet_connection_sock *icsk = inet_csk(sk); 285 struct inet_connection_sock *icsk = inet_csk(sk);
286 struct request_sock_queue *queue = &icsk->icsk_accept_queue;
286 struct sock *newsk; 287 struct sock *newsk;
288 struct request_sock *req;
287 int error; 289 int error;
288 290
289 lock_sock(sk); 291 lock_sock(sk);
@@ -296,7 +298,7 @@ struct sock *inet_csk_accept(struct sock *sk, int flags, int *err)
296 goto out_err; 298 goto out_err;
297 299
298 /* Find already established connection */ 300 /* Find already established connection */
299 if (reqsk_queue_empty(&icsk->icsk_accept_queue)) { 301 if (reqsk_queue_empty(queue)) {
300 long timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); 302 long timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
301 303
302 /* If this is a non blocking socket don't sleep */ 304 /* If this is a non blocking socket don't sleep */
@@ -308,14 +310,32 @@ struct sock *inet_csk_accept(struct sock *sk, int flags, int *err)
308 if (error) 310 if (error)
309 goto out_err; 311 goto out_err;
310 } 312 }
311 313 req = reqsk_queue_remove(queue);
312 newsk = reqsk_queue_get_child(&icsk->icsk_accept_queue, sk); 314 newsk = req->sk;
313 WARN_ON(newsk->sk_state == TCP_SYN_RECV); 315
316 sk_acceptq_removed(sk);
317 if (sk->sk_protocol == IPPROTO_TCP && queue->fastopenq != NULL) {
318 spin_lock_bh(&queue->fastopenq->lock);
319 if (tcp_rsk(req)->listener) {
320 /* We are still waiting for the final ACK from 3WHS
321 * so can't free req now. Instead, we set req->sk to
322 * NULL to signify that the child socket is taken
323 * so reqsk_fastopen_remove() will free the req
324 * when 3WHS finishes (or is aborted).
325 */
326 req->sk = NULL;
327 req = NULL;
328 }
329 spin_unlock_bh(&queue->fastopenq->lock);
330 }
314out: 331out:
315 release_sock(sk); 332 release_sock(sk);
333 if (req)
334 __reqsk_free(req);
316 return newsk; 335 return newsk;
317out_err: 336out_err:
318 newsk = NULL; 337 newsk = NULL;
338 req = NULL;
319 *err = error; 339 *err = error;
320 goto out; 340 goto out;
321} 341}
@@ -404,12 +424,15 @@ struct dst_entry *inet_csk_route_child_sock(struct sock *sk,
404{ 424{
405 const struct inet_request_sock *ireq = inet_rsk(req); 425 const struct inet_request_sock *ireq = inet_rsk(req);
406 struct inet_sock *newinet = inet_sk(newsk); 426 struct inet_sock *newinet = inet_sk(newsk);
407 struct ip_options_rcu *opt = ireq->opt; 427 struct ip_options_rcu *opt;
408 struct net *net = sock_net(sk); 428 struct net *net = sock_net(sk);
409 struct flowi4 *fl4; 429 struct flowi4 *fl4;
410 struct rtable *rt; 430 struct rtable *rt;
411 431
412 fl4 = &newinet->cork.fl.u.ip4; 432 fl4 = &newinet->cork.fl.u.ip4;
433
434 rcu_read_lock();
435 opt = rcu_dereference(newinet->inet_opt);
413 flowi4_init_output(fl4, sk->sk_bound_dev_if, sk->sk_mark, 436 flowi4_init_output(fl4, sk->sk_bound_dev_if, sk->sk_mark,
414 RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, 437 RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE,
415 sk->sk_protocol, inet_sk_flowi_flags(sk), 438 sk->sk_protocol, inet_sk_flowi_flags(sk),
@@ -421,11 +444,13 @@ struct dst_entry *inet_csk_route_child_sock(struct sock *sk,
421 goto no_route; 444 goto no_route;
422 if (opt && opt->opt.is_strictroute && rt->rt_gateway) 445 if (opt && opt->opt.is_strictroute && rt->rt_gateway)
423 goto route_err; 446 goto route_err;
447 rcu_read_unlock();
424 return &rt->dst; 448 return &rt->dst;
425 449
426route_err: 450route_err:
427 ip_rt_put(rt); 451 ip_rt_put(rt);
428no_route: 452no_route:
453 rcu_read_unlock();
429 IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES); 454 IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES);
430 return NULL; 455 return NULL;
431} 456}
@@ -715,13 +740,14 @@ EXPORT_SYMBOL_GPL(inet_csk_listen_start);
715void inet_csk_listen_stop(struct sock *sk) 740void inet_csk_listen_stop(struct sock *sk)
716{ 741{
717 struct inet_connection_sock *icsk = inet_csk(sk); 742 struct inet_connection_sock *icsk = inet_csk(sk);
743 struct request_sock_queue *queue = &icsk->icsk_accept_queue;
718 struct request_sock *acc_req; 744 struct request_sock *acc_req;
719 struct request_sock *req; 745 struct request_sock *req;
720 746
721 inet_csk_delete_keepalive_timer(sk); 747 inet_csk_delete_keepalive_timer(sk);
722 748
723 /* make all the listen_opt local to us */ 749 /* make all the listen_opt local to us */
724 acc_req = reqsk_queue_yank_acceptq(&icsk->icsk_accept_queue); 750 acc_req = reqsk_queue_yank_acceptq(queue);
725 751
726 /* Following specs, it would be better either to send FIN 752 /* Following specs, it would be better either to send FIN
727 * (and enter FIN-WAIT-1, it is normal close) 753 * (and enter FIN-WAIT-1, it is normal close)
@@ -731,7 +757,7 @@ void inet_csk_listen_stop(struct sock *sk)
731 * To be honest, we are not able to make either 757 * To be honest, we are not able to make either
732 * of the variants now. --ANK 758 * of the variants now. --ANK
733 */ 759 */
734 reqsk_queue_destroy(&icsk->icsk_accept_queue); 760 reqsk_queue_destroy(queue);
735 761
736 while ((req = acc_req) != NULL) { 762 while ((req = acc_req) != NULL) {
737 struct sock *child = req->sk; 763 struct sock *child = req->sk;
@@ -749,6 +775,19 @@ void inet_csk_listen_stop(struct sock *sk)
749 775
750 percpu_counter_inc(sk->sk_prot->orphan_count); 776 percpu_counter_inc(sk->sk_prot->orphan_count);
751 777
778 if (sk->sk_protocol == IPPROTO_TCP && tcp_rsk(req)->listener) {
779 BUG_ON(tcp_sk(child)->fastopen_rsk != req);
780 BUG_ON(sk != tcp_rsk(req)->listener);
781
782 /* Paranoid, to prevent race condition if
783 * an inbound pkt destined for child is
784 * blocked by sock lock in tcp_v4_rcv().
785 * Also to satisfy an assertion in
786 * tcp_v4_destroy_sock().
787 */
788 tcp_sk(child)->fastopen_rsk = NULL;
789 sock_put(sk);
790 }
752 inet_csk_destroy_sock(child); 791 inet_csk_destroy_sock(child);
753 792
754 bh_unlock_sock(child); 793 bh_unlock_sock(child);
@@ -758,6 +797,17 @@ void inet_csk_listen_stop(struct sock *sk)
758 sk_acceptq_removed(sk); 797 sk_acceptq_removed(sk);
759 __reqsk_free(req); 798 __reqsk_free(req);
760 } 799 }
800 if (queue->fastopenq != NULL) {
801 /* Free all the reqs queued in rskq_rst_head. */
802 spin_lock_bh(&queue->fastopenq->lock);
803 acc_req = queue->fastopenq->rskq_rst_head;
804 queue->fastopenq->rskq_rst_head = NULL;
805 spin_unlock_bh(&queue->fastopenq->lock);
806 while ((req = acc_req) != NULL) {
807 acc_req = req->dl_next;
808 __reqsk_free(req);
809 }
810 }
761 WARN_ON(sk->sk_ack_backlog); 811 WARN_ON(sk->sk_ack_backlog);
762} 812}
763EXPORT_SYMBOL_GPL(inet_csk_listen_stop); 813EXPORT_SYMBOL_GPL(inet_csk_listen_stop);