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