18c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*-
28c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
3ecc6b8c25a7e8d9d2b78889e88224354a1cc3160tuexen * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
4ecc6b8c25a7e8d9d2b78889e88224354a1cc3160tuexen * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
58c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
68c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Redistribution and use in source and binary forms, with or without
78c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * modification, are permitted provided that the following conditions are met:
88c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
98c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * a) Redistributions of source code must retain the above copyright notice,
100ac02f34d6041cd0018437596a5a9a94685e6919tuexen *    this list of conditions and the following disclaimer.
118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * b) Redistributions in binary form must reproduce the above copyright
138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *    notice, this list of conditions and the following disclaimer in
140ac02f34d6041cd0018437596a5a9a94685e6919tuexen *    the documentation and/or other materials provided with the distribution.
158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * c) Neither the name of Cisco Systems, Inc. nor the names of its
178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *    contributors may be used to endorse or promote products derived
188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *    from this software without specific prior written permission.
198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * THE POSSIBILITY OF SUCH DAMAGE.
318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef __FreeBSD__
348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <sys/cdefs.h>
35875d5dae39dd5ba623e1c27212aa2ac953c2317at__FBSDID("$FreeBSD: head/sys/netinet/sctp_peeloff.c 243565 2012-11-26 16:44:03Z tuexen $");
368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
37ecc6b8c25a7e8d9d2b78889e88224354a1cc3160tuexen
388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_os.h>
398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_pcb.h>
408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctputil.h>
418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_var.h>
428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_var.h>
438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_sysctl.h>
448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp.h>
458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_uio.h>
468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_peeloff.h>
478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctputil.h>
488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_auth.h>
498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#define APPLE_FILE_NO 5
528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_can_peel_off(struct socket *head, sctp_assoc_t assoc_id)
568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_inpcb *inp;
588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tcb *stcb;
598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t state;
608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6185e410973e6388d43479e1966f36a4bf532107f0tuexen	if (head == NULL) {
62efe7c710200b27d91ed4fa52900178c9c3a463a7tuexen		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, EBADF);
6332a191a90b5c914a02047389c5b3197e08fc9841tuexen		return (EBADF);
6485e410973e6388d43479e1966f36a4bf532107f0tuexen	}
658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	inp = (struct sctp_inpcb *)head->so_pcb;
668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp == NULL) {
67efe7c710200b27d91ed4fa52900178c9c3a463a7tuexen		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, EFAULT);
688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (EFAULT);
698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
702fbec84cda9df157171087bab7b4a564107161eatuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
712fbec84cda9df157171087bab7b4a564107161eatuexen	    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
722fbec84cda9df157171087bab7b4a564107161eatuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, EOPNOTSUPP);
7332a191a90b5c914a02047389c5b3197e08fc9841tuexen		return (EOPNOTSUPP);
742fbec84cda9df157171087bab7b4a564107161eatuexen	}
758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb = sctp_findassociation_ep_asocid(inp, assoc_id, 1);
768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb == NULL) {
778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_PEELOFF, ENOENT);
788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (ENOENT);
798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	state = SCTP_GET_STATE((&stcb->asoc));
818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((state == SCTP_STATE_EMPTY) ||
82875d5dae39dd5ba623e1c27212aa2ac953c2317at	    (state == SCTP_STATE_INUSE)) {
838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_UNLOCK(stcb);
848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_PEELOFF, ENOTCONN);
858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (ENOTCONN);
868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_TCB_UNLOCK(stcb);
888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* We are clear to peel this one off */
898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_do_peeloff(struct socket *head, struct socket *so, sctp_assoc_t assoc_id)
948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_inpcb *inp, *n_inp;
968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tcb *stcb;
978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t state;
988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	inp = (struct sctp_inpcb *)head->so_pcb;
1008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp == NULL) {
1018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, EFAULT);
1028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (EFAULT);
1038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
1048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb = sctp_findassociation_ep_asocid(inp, assoc_id, 1);
1058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb == NULL) {
1068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, ENOTCONN);
1078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (ENOTCONN);
1088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
1098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	state = SCTP_GET_STATE((&stcb->asoc));
1118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((state == SCTP_STATE_EMPTY) ||
112875d5dae39dd5ba623e1c27212aa2ac953c2317at	    (state == SCTP_STATE_INUSE)) {
1138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_UNLOCK(stcb);
1148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, ENOTCONN);
1158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (ENOTCONN);
1168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
1178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	n_inp = (struct sctp_inpcb *)so->so_pcb;
1198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	n_inp->sctp_flags = (SCTP_PCB_FLAGS_UDPTYPE |
1208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    SCTP_PCB_FLAGS_CONNECTED |
1218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    SCTP_PCB_FLAGS_IN_TCPPOOL |	/* Turn on Blocking IO */
1228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (SCTP_PCB_COPY_FLAGS & inp->sctp_flags));
1238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	n_inp->sctp_socket = so;
1248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	n_inp->sctp_features = inp->sctp_features;
1258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	n_inp->sctp_mobility_features = inp->sctp_mobility_features;
1268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	n_inp->sctp_frag_point = inp->sctp_frag_point;
1278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	n_inp->sctp_cmt_on_off = inp->sctp_cmt_on_off;
1288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	n_inp->sctp_ecn_enable = inp->sctp_ecn_enable;
1298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	n_inp->partial_delivery_point = inp->partial_delivery_point;
1308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	n_inp->sctp_context = inp->sctp_context;
131c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	n_inp->local_strreset_support = inp->local_strreset_support;
1328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	n_inp->inp_starting_point_for_iterator = NULL;
1338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* copy in the authentication parameters from the original endpoint */
1348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (n_inp->sctp_ep.local_hmacs)
1358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_free_hmaclist(n_inp->sctp_ep.local_hmacs);
1368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	n_inp->sctp_ep.local_hmacs =
1378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    sctp_copy_hmaclist(inp->sctp_ep.local_hmacs);
1388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (n_inp->sctp_ep.local_auth_chunks)
1398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_free_chunklist(n_inp->sctp_ep.local_auth_chunks);
1408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	n_inp->sctp_ep.local_auth_chunks =
1418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    sctp_copy_chunklist(inp->sctp_ep.local_auth_chunks);
1428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	(void)sctp_copy_skeylist(&inp->sctp_ep.shared_keys,
1438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    &n_inp->sctp_ep.shared_keys);
14432a191a90b5c914a02047389c5b3197e08fc9841tuexen#if defined(__Userspace__)
145d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen	n_inp->ulp_info = inp->ulp_info;
14632a191a90b5c914a02047389c5b3197e08fc9841tuexen	n_inp->recv_callback = inp->recv_callback;
14732a191a90b5c914a02047389c5b3197e08fc9841tuexen	n_inp->send_callback = inp->send_callback;
14832a191a90b5c914a02047389c5b3197e08fc9841tuexen	n_inp->send_sb_threshold = inp->send_sb_threshold;
14932a191a90b5c914a02047389c5b3197e08fc9841tuexen#endif
1508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
1518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Now we must move it from one hash table to another and get the
1528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * stcb in the right place.
1538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
1548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_move_pcb_and_assoc(inp, n_inp, stcb);
1558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	atomic_add_int(&stcb->asoc.refcnt, 1);
1568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_TCB_UNLOCK(stcb);
1578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__)
1598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_pull_off_control_to_new_inp(inp, n_inp, stcb, SBL_WAIT);
1608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
1618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_pull_off_control_to_new_inp(inp, n_inp, stcb, M_WAITOK);
1628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
1638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	atomic_subtract_int(&stcb->asoc.refcnt, 1);
1648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
1668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
1678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1681252c73fc5c1fd7e181b8b11081cc442dec13858t#if defined(HAVE_SCTP_PEELOFF_SOCKOPT)
1698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct socket *
1708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_get_peeloff(struct socket *head, sctp_assoc_t assoc_id, int *error)
1718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
1728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Userspace__)
1738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    /* if __Userspace__ chooses to originally not support peeloff, put it here... */
1748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
1758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Panda__)
1768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, EINVAL);
1778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	*error = EINVAL;
1788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (NULL);
1798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
1808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct socket *newso;
1818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_inpcb *inp, *n_inp;
1828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tcb *stcb;
1838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTPDBG(SCTP_DEBUG_PEEL1, "SCTP peel-off called\n");
1858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	inp = (struct sctp_inpcb *)head->so_pcb;
1868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp == NULL) {
1878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, EFAULT);
1888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*error = EFAULT;
1898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (NULL);
1908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
1918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb = sctp_findassociation_ep_asocid(inp, assoc_id, 1);
1928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb == NULL) {
1938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, ENOTCONN);
1948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*error = ENOTCONN;
1958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (NULL);
1968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
1978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	atomic_add_int(&stcb->asoc.refcnt, 1);
1988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_TCB_UNLOCK(stcb);
1998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 801000
2008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	CURVNET_SET(head->so_vnet);
2018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
2028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	newso = sonewconn(head, SS_ISCONNECTED
2038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
2048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    , NULL
2058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__Panda__)
2068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    /* place this socket in the assoc's vrf id */
2078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    , NULL, stcb->asoc.vrf_id
2088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
2098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		);
2108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 801000
2118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	CURVNET_RESTORE();
2128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
2138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (newso == NULL) {
2148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_PEEL1, "sctp_peeloff:sonewconn failed\n");
2158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_PEELOFF, ENOMEM);
2168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*error = ENOMEM;
2178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		atomic_subtract_int(&stcb->asoc.refcnt, 1);
2188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (NULL);
2198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
2218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
2228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	  else {
2238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_SOCKET_LOCK(newso, 1);
2248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
2258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
2268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_TCB_LOCK(stcb);
2278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	atomic_subtract_int(&stcb->asoc.refcnt, 1);
2288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	n_inp = (struct sctp_inpcb *)newso->so_pcb;
2298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SOCK_LOCK(head);
2308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	n_inp->sctp_flags = (SCTP_PCB_FLAGS_UDPTYPE |
2318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    SCTP_PCB_FLAGS_CONNECTED |
2328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    SCTP_PCB_FLAGS_IN_TCPPOOL |	/* Turn on Blocking IO */
2338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (SCTP_PCB_COPY_FLAGS & inp->sctp_flags));
2348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	n_inp->sctp_features = inp->sctp_features;
2358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	n_inp->sctp_frag_point = inp->sctp_frag_point;
2368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	n_inp->sctp_cmt_on_off = inp->sctp_cmt_on_off;
2378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	n_inp->sctp_ecn_enable = inp->sctp_ecn_enable;
2388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	n_inp->partial_delivery_point = inp->partial_delivery_point;
2398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	n_inp->sctp_context = inp->sctp_context;
240c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	n_inp->local_strreset_support = inp->local_strreset_support;
2418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	n_inp->inp_starting_point_for_iterator = NULL;
24232a191a90b5c914a02047389c5b3197e08fc9841tuexen#if defined(__Userspace__)
243d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen	n_inp->ulp_info = inp->ulp_info;
24432a191a90b5c914a02047389c5b3197e08fc9841tuexen	n_inp->recv_callback = inp->recv_callback;
24532a191a90b5c914a02047389c5b3197e08fc9841tuexen	n_inp->send_callback = inp->send_callback;
24632a191a90b5c914a02047389c5b3197e08fc9841tuexen	n_inp->send_sb_threshold = inp->send_sb_threshold;
24732a191a90b5c914a02047389c5b3197e08fc9841tuexen#endif
2488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* copy in the authentication parameters from the original endpoint */
2508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (n_inp->sctp_ep.local_hmacs)
2518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_free_hmaclist(n_inp->sctp_ep.local_hmacs);
2528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	n_inp->sctp_ep.local_hmacs =
2538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    sctp_copy_hmaclist(inp->sctp_ep.local_hmacs);
2548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (n_inp->sctp_ep.local_auth_chunks)
2558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_free_chunklist(n_inp->sctp_ep.local_auth_chunks);
2568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	n_inp->sctp_ep.local_auth_chunks =
2578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    sctp_copy_chunklist(inp->sctp_ep.local_auth_chunks);
2588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	(void)sctp_copy_skeylist(&inp->sctp_ep.shared_keys,
2598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    &n_inp->sctp_ep.shared_keys);
2608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	n_inp->sctp_socket = newso;
2628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE)) {
2638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_feature_off(n_inp, SCTP_PCB_FLAGS_AUTOCLOSE);
2648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		n_inp->sctp_ep.auto_close_time = 0;
2658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_timer_stop(SCTP_TIMER_TYPE_AUTOCLOSE, n_inp, stcb, NULL,
2668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_FROM_SCTP_PEELOFF+SCTP_LOC_1);
2678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
2688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Turn off any non-blocking semantic. */
2698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_CLEAR_SO_NBIO(newso);
2708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen        newso->so_state |= SS_ISCONNECTED;
2718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* We remove it right away */
2728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
2748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_LOCK_LOGGING
2758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) {
2768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_log_lock(inp, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_SOCK);
2778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
2788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
2798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_REMOVE(&head->so_comp, newso, so_list);
2808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	head->so_qlen--;
2818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SOCK_UNLOCK(head);
2828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
2838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen        newso = TAILQ_FIRST(&head->so_q);
2848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (soqremque(newso, 1) == 0) {
2858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_PRINTF("soremque failed, peeloff-fails (invarients would panic)\n");
2868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, ENOTCONN);
2878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*error = ENOTCONN;
2888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (NULL);
2898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
2918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
2928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
2938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Now we must move it from one hash table to another and get the
2948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * stcb in the right place.
2958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
2968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen        sctp_move_pcb_and_assoc(inp, n_inp, stcb);
2978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	atomic_add_int(&stcb->asoc.refcnt, 1);
2988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_TCB_UNLOCK(stcb);
2998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
3008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * And now the final hack. We move data in the pending side i.e.
3018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * head to the new socket buffer. Let the GRUBBING begin :-0
3028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
3038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__)
3048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_pull_off_control_to_new_inp(inp, n_inp, stcb, SBL_WAIT);
3058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
3068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_pull_off_control_to_new_inp(inp, n_inp, stcb, M_WAITOK);
3078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
3088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	atomic_subtract_int(&stcb->asoc.refcnt, 1);
3098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (newso);
3108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
3118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
3121252c73fc5c1fd7e181b8b11081cc442dec13858t#endif
313