LCOV - code coverage report
Current view: top level - netwerk/sctp/src/netinet - sctp_peeloff.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 69 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 2 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-
       2             :  * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
       3             :  * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
       4             :  * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
       5             :  *
       6             :  * Redistribution and use in source and binary forms, with or without
       7             :  * modification, are permitted provided that the following conditions are met:
       8             :  *
       9             :  * a) Redistributions of source code must retain the above copyright notice,
      10             :  *    this list of conditions and the following disclaimer.
      11             :  *
      12             :  * b) Redistributions in binary form must reproduce the above copyright
      13             :  *    notice, this list of conditions and the following disclaimer in
      14             :  *    the documentation and/or other materials provided with the distribution.
      15             :  *
      16             :  * c) Neither the name of Cisco Systems, Inc. nor the names of its
      17             :  *    contributors may be used to endorse or promote products derived
      18             :  *    from this software without specific prior written permission.
      19             :  *
      20             :  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      21             :  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
      22             :  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      23             :  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
      24             :  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      25             :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      26             :  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      27             :  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      28             :  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      29             :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
      30             :  * THE POSSIBILITY OF SUCH DAMAGE.
      31             :  */
      32             : 
      33             : #ifdef __FreeBSD__
      34             : #include <sys/cdefs.h>
      35             : __FBSDID("$FreeBSD: head/sys/netinet/sctp_peeloff.c 279859 2015-03-10 19:49:25Z tuexen $");
      36             : #endif
      37             : 
      38             : #include <netinet/sctp_os.h>
      39             : #include <netinet/sctp_pcb.h>
      40             : #include <netinet/sctputil.h>
      41             : #include <netinet/sctp_var.h>
      42             : #include <netinet/sctp_var.h>
      43             : #include <netinet/sctp_sysctl.h>
      44             : #include <netinet/sctp.h>
      45             : #include <netinet/sctp_uio.h>
      46             : #include <netinet/sctp_peeloff.h>
      47             : #include <netinet/sctputil.h>
      48             : #include <netinet/sctp_auth.h>
      49             : 
      50             : #if defined(__APPLE__)
      51             : #define APPLE_FILE_NO 5
      52             : #endif
      53             : 
      54             : int
      55           0 : sctp_can_peel_off(struct socket *head, sctp_assoc_t assoc_id)
      56             : {
      57             :         struct sctp_inpcb *inp;
      58             :         struct sctp_tcb *stcb;
      59             :         uint32_t state;
      60             : 
      61           0 :         if (head == NULL) {
      62             :                 SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, EBADF);
      63           0 :                 return (EBADF);
      64             :         }
      65           0 :         inp = (struct sctp_inpcb *)head->so_pcb;
      66           0 :         if (inp == NULL) {
      67             :                 SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, EFAULT);
      68           0 :                 return (EFAULT);
      69             :         }
      70           0 :         if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
      71           0 :             (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
      72             :                 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, EOPNOTSUPP);
      73           0 :                 return (EOPNOTSUPP);
      74             :         }
      75           0 :         stcb = sctp_findassociation_ep_asocid(inp, assoc_id, 1);
      76           0 :         if (stcb == NULL) {
      77             :                 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_PEELOFF, ENOENT);
      78           0 :                 return (ENOENT);
      79             :         }
      80           0 :         state = SCTP_GET_STATE((&stcb->asoc));
      81           0 :         if ((state == SCTP_STATE_EMPTY) ||
      82             :             (state == SCTP_STATE_INUSE)) {
      83           0 :                 SCTP_TCB_UNLOCK(stcb);
      84             :                 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_PEELOFF, ENOTCONN);
      85           0 :                 return (ENOTCONN);
      86             :         }
      87           0 :         SCTP_TCB_UNLOCK(stcb);
      88             :         /* We are clear to peel this one off */
      89           0 :         return (0);
      90             : }
      91             : 
      92             : int
      93           0 : sctp_do_peeloff(struct socket *head, struct socket *so, sctp_assoc_t assoc_id)
      94             : {
      95             :         struct sctp_inpcb *inp, *n_inp;
      96             :         struct sctp_tcb *stcb;
      97             :         uint32_t state;
      98             : 
      99           0 :         inp = (struct sctp_inpcb *)head->so_pcb;
     100           0 :         if (inp == NULL) {
     101             :                 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, EFAULT);
     102           0 :                 return (EFAULT);
     103             :         }
     104           0 :         stcb = sctp_findassociation_ep_asocid(inp, assoc_id, 1);
     105           0 :         if (stcb == NULL) {
     106             :                 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, ENOTCONN);
     107           0 :                 return (ENOTCONN);
     108             :         }
     109             : 
     110           0 :         state = SCTP_GET_STATE((&stcb->asoc));
     111           0 :         if ((state == SCTP_STATE_EMPTY) ||
     112             :             (state == SCTP_STATE_INUSE)) {
     113           0 :                 SCTP_TCB_UNLOCK(stcb);
     114             :                 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, ENOTCONN);
     115           0 :                 return (ENOTCONN);
     116             :         }
     117             : 
     118           0 :         n_inp = (struct sctp_inpcb *)so->so_pcb;
     119           0 :         n_inp->sctp_flags = (SCTP_PCB_FLAGS_UDPTYPE |
     120             :             SCTP_PCB_FLAGS_CONNECTED |
     121           0 :             SCTP_PCB_FLAGS_IN_TCPPOOL | /* Turn on Blocking IO */
     122           0 :             (SCTP_PCB_COPY_FLAGS & inp->sctp_flags));
     123           0 :         n_inp->sctp_socket = so;
     124           0 :         n_inp->sctp_features = inp->sctp_features;
     125           0 :         n_inp->sctp_mobility_features = inp->sctp_mobility_features;
     126           0 :         n_inp->sctp_frag_point = inp->sctp_frag_point;
     127           0 :         n_inp->sctp_cmt_on_off = inp->sctp_cmt_on_off;
     128           0 :         n_inp->ecn_supported = inp->ecn_supported;
     129           0 :         n_inp->prsctp_supported = inp->prsctp_supported;
     130           0 :         n_inp->auth_supported = inp->auth_supported;
     131           0 :         n_inp->asconf_supported = inp->asconf_supported;
     132           0 :         n_inp->reconfig_supported = inp->reconfig_supported;
     133           0 :         n_inp->nrsack_supported = inp->nrsack_supported;
     134           0 :         n_inp->pktdrop_supported = inp->pktdrop_supported;
     135           0 :         n_inp->partial_delivery_point = inp->partial_delivery_point;
     136           0 :         n_inp->sctp_context = inp->sctp_context;
     137           0 :         n_inp->max_cwnd = inp->max_cwnd;
     138           0 :         n_inp->local_strreset_support = inp->local_strreset_support;
     139           0 :         n_inp->inp_starting_point_for_iterator = NULL;
     140             :         /* copy in the authentication parameters from the original endpoint */
     141           0 :         if (n_inp->sctp_ep.local_hmacs)
     142           0 :                 sctp_free_hmaclist(n_inp->sctp_ep.local_hmacs);
     143           0 :         n_inp->sctp_ep.local_hmacs =
     144           0 :             sctp_copy_hmaclist(inp->sctp_ep.local_hmacs);
     145           0 :         if (n_inp->sctp_ep.local_auth_chunks)
     146           0 :                 sctp_free_chunklist(n_inp->sctp_ep.local_auth_chunks);
     147           0 :         n_inp->sctp_ep.local_auth_chunks =
     148           0 :             sctp_copy_chunklist(inp->sctp_ep.local_auth_chunks);
     149           0 :         (void)sctp_copy_skeylist(&inp->sctp_ep.shared_keys,
     150             :             &n_inp->sctp_ep.shared_keys);
     151             : #if defined(__Userspace__)
     152           0 :         n_inp->ulp_info = inp->ulp_info;
     153           0 :         n_inp->recv_callback = inp->recv_callback;
     154           0 :         n_inp->send_callback = inp->send_callback;
     155           0 :         n_inp->send_sb_threshold = inp->send_sb_threshold;
     156             : #endif
     157             :         /*
     158             :          * Now we must move it from one hash table to another and get the
     159             :          * stcb in the right place.
     160             :          */
     161           0 :         sctp_move_pcb_and_assoc(inp, n_inp, stcb);
     162           0 :         atomic_add_int(&stcb->asoc.refcnt, 1);
     163           0 :         SCTP_TCB_UNLOCK(stcb);
     164             : 
     165             : #if defined(__FreeBSD__)
     166             :         sctp_pull_off_control_to_new_inp(inp, n_inp, stcb, SBL_WAIT);
     167             : #else
     168           0 :         sctp_pull_off_control_to_new_inp(inp, n_inp, stcb, M_WAITOK);
     169             : #endif
     170           0 :         atomic_subtract_int(&stcb->asoc.refcnt, 1);
     171             : 
     172           0 :         return (0);
     173             : }
     174             : 
     175             : #if defined(HAVE_SCTP_PEELOFF_SOCKOPT)
     176             : struct socket *
     177             : sctp_get_peeloff(struct socket *head, sctp_assoc_t assoc_id, int *error)
     178             : {
     179             : #if defined(__Userspace__)
     180             :     /* if __Userspace__ chooses to originally not support peeloff, put it here... */
     181             : #endif
     182             : #if defined(__Panda__)
     183             :         SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, EINVAL);
     184             :         *error = EINVAL;
     185             :         return (NULL);
     186             : #else
     187             :         struct socket *newso;
     188             :         struct sctp_inpcb *inp, *n_inp;
     189             :         struct sctp_tcb *stcb;
     190             : 
     191             :         SCTPDBG(SCTP_DEBUG_PEEL1, "SCTP peel-off called\n");
     192             :         inp = (struct sctp_inpcb *)head->so_pcb;
     193             :         if (inp == NULL) {
     194             :                 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, EFAULT);
     195             :                 *error = EFAULT;
     196             :                 return (NULL);
     197             :         }
     198             :         stcb = sctp_findassociation_ep_asocid(inp, assoc_id, 1);
     199             :         if (stcb == NULL) {
     200             :                 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, ENOTCONN);
     201             :                 *error = ENOTCONN;
     202             :                 return (NULL);
     203             :         }
     204             :         atomic_add_int(&stcb->asoc.refcnt, 1);
     205             :         SCTP_TCB_UNLOCK(stcb);
     206             : #if defined(__FreeBSD__) && __FreeBSD_version >= 801000
     207             :         CURVNET_SET(head->so_vnet);
     208             : #endif
     209             :         newso = sonewconn(head, SS_ISCONNECTED
     210             : #if defined(__APPLE__)
     211             :             , NULL
     212             : #elif defined(__Panda__)
     213             :             /* place this socket in the assoc's vrf id */
     214             :             , NULL, stcb->asoc.vrf_id
     215             : #endif
     216             :                 );
     217             : #if defined(__FreeBSD__) && __FreeBSD_version >= 801000
     218             :         CURVNET_RESTORE();
     219             : #endif
     220             :         if (newso == NULL) {
     221             :                 SCTPDBG(SCTP_DEBUG_PEEL1, "sctp_peeloff:sonewconn failed\n");
     222             :                 SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_PEELOFF, ENOMEM);
     223             :                 *error = ENOMEM;
     224             :                 atomic_subtract_int(&stcb->asoc.refcnt, 1);
     225             :                 return (NULL);
     226             : 
     227             :         }
     228             : #if defined(__APPLE__)
     229             :           else {
     230             :                 SCTP_SOCKET_LOCK(newso, 1);
     231             :         }
     232             : #endif
     233             :         SCTP_TCB_LOCK(stcb);
     234             :         atomic_subtract_int(&stcb->asoc.refcnt, 1);
     235             :         n_inp = (struct sctp_inpcb *)newso->so_pcb;
     236             :         SOCK_LOCK(head);
     237             :         n_inp->sctp_flags = (SCTP_PCB_FLAGS_UDPTYPE |
     238             :             SCTP_PCB_FLAGS_CONNECTED |
     239             :             SCTP_PCB_FLAGS_IN_TCPPOOL | /* Turn on Blocking IO */
     240             :             (SCTP_PCB_COPY_FLAGS & inp->sctp_flags));
     241             :         n_inp->sctp_features = inp->sctp_features;
     242             :         n_inp->sctp_frag_point = inp->sctp_frag_point;
     243             :         n_inp->sctp_cmt_on_off = inp->sctp_cmt_on_off;
     244             :         n_inp->ecn_supported = inp->ecn_supported;
     245             :         n_inp->prsctp_supported = inp->prsctp_supported;
     246             :         n_inp->auth_supported = inp->auth_supported;
     247             :         n_inp->asconf_supported = inp->asconf_supported;
     248             :         n_inp->reconfig_supported = inp->reconfig_supported;
     249             :         n_inp->nrsack_supported = inp->nrsack_supported;
     250             :         n_inp->pktdrop_supported = inp->pktdrop_supported;
     251             :         n_inp->partial_delivery_point = inp->partial_delivery_point;
     252             :         n_inp->sctp_context = inp->sctp_context;
     253             :         n_inp->max_cwnd = inp->max_cwnd;
     254             :         n_inp->local_strreset_support = inp->local_strreset_support;
     255             :         n_inp->inp_starting_point_for_iterator = NULL;
     256             : #if defined(__Userspace__)
     257             :         n_inp->ulp_info = inp->ulp_info;
     258             :         n_inp->recv_callback = inp->recv_callback;
     259             :         n_inp->send_callback = inp->send_callback;
     260             :         n_inp->send_sb_threshold = inp->send_sb_threshold;
     261             : #endif
     262             : 
     263             :         /* copy in the authentication parameters from the original endpoint */
     264             :         if (n_inp->sctp_ep.local_hmacs)
     265             :                 sctp_free_hmaclist(n_inp->sctp_ep.local_hmacs);
     266             :         n_inp->sctp_ep.local_hmacs =
     267             :             sctp_copy_hmaclist(inp->sctp_ep.local_hmacs);
     268             :         if (n_inp->sctp_ep.local_auth_chunks)
     269             :                 sctp_free_chunklist(n_inp->sctp_ep.local_auth_chunks);
     270             :         n_inp->sctp_ep.local_auth_chunks =
     271             :             sctp_copy_chunklist(inp->sctp_ep.local_auth_chunks);
     272             :         (void)sctp_copy_skeylist(&inp->sctp_ep.shared_keys,
     273             :             &n_inp->sctp_ep.shared_keys);
     274             : 
     275             :         n_inp->sctp_socket = newso;
     276             :         if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE)) {
     277             :                 sctp_feature_off(n_inp, SCTP_PCB_FLAGS_AUTOCLOSE);
     278             :                 n_inp->sctp_ep.auto_close_time = 0;
     279             :                 sctp_timer_stop(SCTP_TIMER_TYPE_AUTOCLOSE, n_inp, stcb, NULL,
     280             :                                 SCTP_FROM_SCTP_PEELOFF+SCTP_LOC_1);
     281             :         }
     282             :         /* Turn off any non-blocking semantic. */
     283             :         SCTP_CLEAR_SO_NBIO(newso);
     284             :         newso->so_state |= SS_ISCONNECTED;
     285             :         /* We remove it right away */
     286             : 
     287             : #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
     288             : #ifdef SCTP_LOCK_LOGGING
     289             :         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) {
     290             :                 sctp_log_lock(inp, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_SOCK);
     291             :         }
     292             : #endif
     293             :         TAILQ_REMOVE(&head->so_comp, newso, so_list);
     294             :         head->so_qlen--;
     295             :         SOCK_UNLOCK(head);
     296             : #else
     297             :         newso = TAILQ_FIRST(&head->so_q);
     298             :         if (soqremque(newso, 1) == 0) {
     299             :                 SCTP_PRINTF("soremque failed, peeloff-fails (invarients would panic)\n");
     300             :                 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, ENOTCONN);
     301             :                 *error = ENOTCONN;
     302             :                 return (NULL);
     303             : 
     304             :         }
     305             : #endif
     306             :         /*
     307             :          * Now we must move it from one hash table to another and get the
     308             :          * stcb in the right place.
     309             :          */
     310             :         sctp_move_pcb_and_assoc(inp, n_inp, stcb);
     311             :         atomic_add_int(&stcb->asoc.refcnt, 1);
     312             :         SCTP_TCB_UNLOCK(stcb);
     313             :         /*
     314             :          * And now the final hack. We move data in the pending side i.e.
     315             :          * head to the new socket buffer. Let the GRUBBING begin :-0
     316             :          */
     317             : #if defined(__FreeBSD__)
     318             :         sctp_pull_off_control_to_new_inp(inp, n_inp, stcb, SBL_WAIT);
     319             : #else
     320             :         sctp_pull_off_control_to_new_inp(inp, n_inp, stcb, M_WAITOK);
     321             : #endif
     322             :         atomic_subtract_int(&stcb->asoc.refcnt, 1);
     323             :         return (newso);
     324             : #endif
     325             : }
     326             : #endif

Generated by: LCOV version 1.13