aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@ghostprotocols.net>2005-08-09 23:10:12 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2005-08-29 18:42:36 -0400
commit87d11ceb9deb7a3f13fdee6e89d9bb6be7d27a71 (patch)
tree3b5f6f15a76e6d58e5088cad707859390757181a /net/ipv4
parentc676270bcd25015b978722ec0352c330dcc87883 (diff)
[SOCK]: Introduce sk_clone
Out of tcp_create_openreq_child, will be used in dccp_create_openreq_child, and is a nice sock function anyway. Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/tcp_minisocks.c70
1 files changed, 3 insertions, 67 deletions
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index 66ce1790a94f..8b6cd8d80662 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -599,67 +599,26 @@ out:
599 */ 599 */
600struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, struct sk_buff *skb) 600struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, struct sk_buff *skb)
601{ 601{
602 /* allocate the newsk from the same slab of the master sock, 602 struct sock *newsk = sk_clone(sk, GFP_ATOMIC);
603 * if not, at sk_free time we'll try to free it from the wrong
604 * slabcache (i.e. is it TCPv4 or v6?), this is handled thru sk->sk_prot -acme */
605 struct sock *newsk = sk_alloc(PF_INET, GFP_ATOMIC, sk->sk_prot, 0);
606 603
607 if(newsk != NULL) { 604 if (newsk != NULL) {
608 struct inet_request_sock *ireq = inet_rsk(req); 605 struct inet_request_sock *ireq = inet_rsk(req);
609 struct tcp_request_sock *treq = tcp_rsk(req); 606 struct tcp_request_sock *treq = tcp_rsk(req);
610 struct inet_sock *newinet = inet_sk(newsk); 607 struct inet_sock *newinet = inet_sk(newsk);
611 struct tcp_sock *newtp; 608 struct tcp_sock *newtp;
612 struct sk_filter *filter;
613 609
614 memcpy(newsk, sk, sizeof(struct tcp_sock));
615 newsk->sk_state = TCP_SYN_RECV; 610 newsk->sk_state = TCP_SYN_RECV;
616
617 /* SANITY */
618 sk_node_init(&newsk->sk_node);
619 newinet->bind_hash = NULL; 611 newinet->bind_hash = NULL;
620 612
621 /* Clone the TCP header template */ 613 /* Clone the TCP header template */
622 newinet->dport = ireq->rmt_port; 614 newinet->dport = ireq->rmt_port;
623
624 sock_lock_init(newsk);
625 bh_lock_sock(newsk);
626
627 rwlock_init(&newsk->sk_dst_lock);
628 newsk->sk_dst_cache = NULL;
629 atomic_set(&newsk->sk_rmem_alloc, 0);
630 skb_queue_head_init(&newsk->sk_receive_queue);
631 atomic_set(&newsk->sk_wmem_alloc, 0);
632 skb_queue_head_init(&newsk->sk_write_queue);
633 atomic_set(&newsk->sk_omem_alloc, 0);
634 newsk->sk_wmem_queued = 0;
635 newsk->sk_forward_alloc = 0;
636
637 sock_reset_flag(newsk, SOCK_DONE);
638 newsk->sk_userlocks = sk->sk_userlocks & ~SOCK_BINDPORT_LOCK;
639 newsk->sk_backlog.head = newsk->sk_backlog.tail = NULL;
640 newsk->sk_send_head = NULL;
641 rwlock_init(&newsk->sk_callback_lock);
642 skb_queue_head_init(&newsk->sk_error_queue);
643 newsk->sk_write_space = sk_stream_write_space; 615 newsk->sk_write_space = sk_stream_write_space;
644 616
645 if ((filter = newsk->sk_filter) != NULL)
646 sk_filter_charge(newsk, filter);
647
648 if (unlikely(xfrm_sk_clone_policy(newsk))) {
649 /* It is still raw copy of parent, so invalidate
650 * destructor and make plain sk_free() */
651 newsk->sk_destruct = NULL;
652 sk_free(newsk);
653 return NULL;
654 }
655
656 /* Now setup tcp_sock */ 617 /* Now setup tcp_sock */
657 newtp = tcp_sk(newsk); 618 newtp = tcp_sk(newsk);
658 newtp->pred_flags = 0; 619 newtp->pred_flags = 0;
659 newtp->rcv_nxt = treq->rcv_isn + 1; 620 newtp->rcv_nxt = treq->rcv_isn + 1;
660 newtp->snd_nxt = treq->snt_isn + 1; 621 newtp->snd_nxt = newtp->snd_una = newtp->snd_sml = treq->snt_isn + 1;
661 newtp->snd_una = treq->snt_isn + 1;
662 newtp->snd_sml = treq->snt_isn + 1;
663 622
664 tcp_prequeue_init(newtp); 623 tcp_prequeue_init(newtp);
665 624
@@ -710,32 +669,9 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,
710 /* Deinitialize accept_queue to trap illegal accesses. */ 669 /* Deinitialize accept_queue to trap illegal accesses. */
711 memset(&newtp->accept_queue, 0, sizeof(newtp->accept_queue)); 670 memset(&newtp->accept_queue, 0, sizeof(newtp->accept_queue));
712 671
713 /* Back to base struct sock members. */
714 newsk->sk_err = 0;
715 newsk->sk_priority = 0;
716 atomic_set(&newsk->sk_refcnt, 2);
717
718 /*
719 * Increment the counter in the same struct proto as the master
720 * sock (sk_refcnt_debug_inc uses newsk->sk_prot->socks, that
721 * is the same as sk->sk_prot->socks, as this field was copied
722 * with memcpy), same rationale as the first comment in this
723 * function.
724 *
725 * This _changes_ the previous behaviour, where
726 * tcp_create_openreq_child always was incrementing the
727 * equivalent to tcp_prot->socks (inet_sock_nr), so this have
728 * to be taken into account in all callers. -acme
729 */
730 sk_refcnt_debug_inc(newsk);
731
732 atomic_inc(&tcp_sockets_allocated);
733
734 if (sock_flag(newsk, SOCK_KEEPOPEN)) 672 if (sock_flag(newsk, SOCK_KEEPOPEN))
735 tcp_reset_keepalive_timer(newsk, 673 tcp_reset_keepalive_timer(newsk,
736 keepalive_time_when(newtp)); 674 keepalive_time_when(newtp));
737 newsk->sk_socket = NULL;
738 newsk->sk_sleep = NULL;
739 675
740 newtp->rx_opt.tstamp_ok = ireq->tstamp_ok; 676 newtp->rx_opt.tstamp_ok = ireq->tstamp_ok;
741 if((newtp->rx_opt.sack_ok = ireq->sack_ok) != 0) { 677 if((newtp->rx_opt.sack_ok = ireq->sack_ok) != 0) {