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

          Line data    Source code
       1             : /*-
       2             :  * Copyright (c) 2001-2008, 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/sctputil.c 280439 2015-03-24 14:51:46Z 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_sysctl.h>
      43             : #ifdef INET6
      44             : #if defined(__Userspace__) || defined(__FreeBSD__)
      45             : #include <netinet6/sctp6_var.h>
      46             : #endif
      47             : #endif
      48             : #include <netinet/sctp_header.h>
      49             : #include <netinet/sctp_output.h>
      50             : #include <netinet/sctp_uio.h>
      51             : #include <netinet/sctp_timer.h>
      52             : #include <netinet/sctp_indata.h>/* for sctp_deliver_data() */
      53             : #include <netinet/sctp_auth.h>
      54             : #include <netinet/sctp_asconf.h>
      55             : #include <netinet/sctp_bsd_addr.h>
      56             : #if defined(__Userspace__)
      57             : #include <netinet/sctp_constants.h>
      58             : #endif
      59             : #if defined(__FreeBSD__)
      60             : #include <netinet/udp.h>
      61             : #include <netinet/udp_var.h>
      62             : #include <sys/proc.h>
      63             : #endif
      64             : 
      65             : #if defined(__APPLE__)
      66             : #define APPLE_FILE_NO 8
      67             : #endif
      68             : 
      69             : #if defined(__Windows__)
      70             : #if !defined(SCTP_LOCAL_TRACE_BUF)
      71             : #include "eventrace_netinet.h"
      72             : #include "sctputil.tmh" /* this is the file that will be auto generated */
      73             : #endif
      74             : #else
      75             : #ifndef KTR_SCTP
      76             : #define KTR_SCTP KTR_SUBSYS
      77             : #endif
      78             : #endif
      79             : 
      80             : extern struct sctp_cc_functions sctp_cc_functions[];
      81             : extern struct sctp_ss_functions sctp_ss_functions[];
      82             : 
      83             : void
      84           0 : sctp_sblog(struct sockbuf *sb, struct sctp_tcb *stcb, int from, int incr)
      85             : {
      86             : #if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
      87             :         struct sctp_cwnd_log sctp_clog;
      88             : 
      89             :         sctp_clog.x.sb.stcb = stcb;
      90             :         sctp_clog.x.sb.so_sbcc = sb->sb_cc;
      91             :         if (stcb)
      92             :                 sctp_clog.x.sb.stcb_sbcc = stcb->asoc.sb_cc;
      93             :         else
      94             :                 sctp_clog.x.sb.stcb_sbcc = 0;
      95             :         sctp_clog.x.sb.incr = incr;
      96             :         SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
      97             :              SCTP_LOG_EVENT_SB,
      98             :              from,
      99             :              sctp_clog.x.misc.log1,
     100             :              sctp_clog.x.misc.log2,
     101             :              sctp_clog.x.misc.log3,
     102             :              sctp_clog.x.misc.log4);
     103             : #endif
     104           0 : }
     105             : 
     106             : void
     107           0 : sctp_log_closing(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int16_t loc)
     108             : {
     109             : #if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
     110             :         struct sctp_cwnd_log sctp_clog;
     111             : 
     112             :         sctp_clog.x.close.inp = (void *)inp;
     113             :         sctp_clog.x.close.sctp_flags = inp->sctp_flags;
     114             :         if (stcb) {
     115             :                 sctp_clog.x.close.stcb = (void *)stcb;
     116             :                 sctp_clog.x.close.state = (uint16_t)stcb->asoc.state;
     117             :         } else {
     118             :                 sctp_clog.x.close.stcb = 0;
     119             :                 sctp_clog.x.close.state = 0;
     120             :         }
     121             :         sctp_clog.x.close.loc = loc;
     122             :         SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
     123             :              SCTP_LOG_EVENT_CLOSE,
     124             :              0,
     125             :              sctp_clog.x.misc.log1,
     126             :              sctp_clog.x.misc.log2,
     127             :              sctp_clog.x.misc.log3,
     128             :              sctp_clog.x.misc.log4);
     129             : #endif
     130           0 : }
     131             : 
     132             : void
     133           0 : rto_logging(struct sctp_nets *net, int from)
     134             : {
     135             : #if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
     136             :         struct sctp_cwnd_log sctp_clog;
     137             : 
     138             :         memset(&sctp_clog, 0, sizeof(sctp_clog));
     139             :         sctp_clog.x.rto.net = (void *) net;
     140             :         sctp_clog.x.rto.rtt = net->rtt / 1000;
     141             :         SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
     142             :              SCTP_LOG_EVENT_RTT,
     143             :              from,
     144             :              sctp_clog.x.misc.log1,
     145             :              sctp_clog.x.misc.log2,
     146             :              sctp_clog.x.misc.log3,
     147             :              sctp_clog.x.misc.log4);
     148             : #endif
     149           0 : }
     150             : 
     151             : void
     152           0 : sctp_log_strm_del_alt(struct sctp_tcb *stcb, uint32_t tsn, uint16_t sseq, uint16_t stream, int from)
     153             : {
     154             : #if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
     155             :         struct sctp_cwnd_log sctp_clog;
     156             : 
     157             :         sctp_clog.x.strlog.stcb = stcb;
     158             :         sctp_clog.x.strlog.n_tsn = tsn;
     159             :         sctp_clog.x.strlog.n_sseq = sseq;
     160             :         sctp_clog.x.strlog.e_tsn = 0;
     161             :         sctp_clog.x.strlog.e_sseq = 0;
     162             :         sctp_clog.x.strlog.strm = stream;
     163             :         SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
     164             :              SCTP_LOG_EVENT_STRM,
     165             :              from,
     166             :              sctp_clog.x.misc.log1,
     167             :              sctp_clog.x.misc.log2,
     168             :              sctp_clog.x.misc.log3,
     169             :              sctp_clog.x.misc.log4);
     170             : #endif
     171           0 : }
     172             : 
     173             : void
     174           0 : sctp_log_nagle_event(struct sctp_tcb *stcb, int action)
     175             : {
     176             : #if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
     177             :         struct sctp_cwnd_log sctp_clog;
     178             : 
     179             :         sctp_clog.x.nagle.stcb = (void *)stcb;
     180             :         sctp_clog.x.nagle.total_flight = stcb->asoc.total_flight;
     181             :         sctp_clog.x.nagle.total_in_queue = stcb->asoc.total_output_queue_size;
     182             :         sctp_clog.x.nagle.count_in_queue = stcb->asoc.chunks_on_out_queue;
     183             :         sctp_clog.x.nagle.count_in_flight = stcb->asoc.total_flight_count;
     184             :         SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
     185             :              SCTP_LOG_EVENT_NAGLE,
     186             :              action,
     187             :              sctp_clog.x.misc.log1,
     188             :              sctp_clog.x.misc.log2,
     189             :              sctp_clog.x.misc.log3,
     190             :              sctp_clog.x.misc.log4);
     191             : #endif
     192           0 : }
     193             : 
     194             : void
     195           0 : sctp_log_sack(uint32_t old_cumack, uint32_t cumack, uint32_t tsn, uint16_t gaps, uint16_t dups, int from)
     196             : {
     197             : #if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
     198             :         struct sctp_cwnd_log sctp_clog;
     199             : 
     200             :         sctp_clog.x.sack.cumack = cumack;
     201             :         sctp_clog.x.sack.oldcumack = old_cumack;
     202             :         sctp_clog.x.sack.tsn = tsn;
     203             :         sctp_clog.x.sack.numGaps = gaps;
     204             :         sctp_clog.x.sack.numDups = dups;
     205             :         SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
     206             :              SCTP_LOG_EVENT_SACK,
     207             :              from,
     208             :              sctp_clog.x.misc.log1,
     209             :              sctp_clog.x.misc.log2,
     210             :              sctp_clog.x.misc.log3,
     211             :              sctp_clog.x.misc.log4);
     212             : #endif
     213           0 : }
     214             : 
     215             : void
     216           0 : sctp_log_map(uint32_t map, uint32_t cum, uint32_t high, int from)
     217             : {
     218             : #if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
     219             :         struct sctp_cwnd_log sctp_clog;
     220             : 
     221             :         memset(&sctp_clog, 0, sizeof(sctp_clog));
     222             :         sctp_clog.x.map.base = map;
     223             :         sctp_clog.x.map.cum = cum;
     224             :         sctp_clog.x.map.high = high;
     225             :         SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
     226             :              SCTP_LOG_EVENT_MAP,
     227             :              from,
     228             :              sctp_clog.x.misc.log1,
     229             :              sctp_clog.x.misc.log2,
     230             :              sctp_clog.x.misc.log3,
     231             :              sctp_clog.x.misc.log4);
     232             : #endif
     233           0 : }
     234             : 
     235             : void
     236           0 : sctp_log_fr(uint32_t biggest_tsn, uint32_t biggest_new_tsn, uint32_t tsn, int from)
     237             : {
     238             : #if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
     239             :         struct sctp_cwnd_log sctp_clog;
     240             : 
     241             :         memset(&sctp_clog, 0, sizeof(sctp_clog));
     242             :         sctp_clog.x.fr.largest_tsn = biggest_tsn;
     243             :         sctp_clog.x.fr.largest_new_tsn = biggest_new_tsn;
     244             :         sctp_clog.x.fr.tsn = tsn;
     245             :         SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
     246             :              SCTP_LOG_EVENT_FR,
     247             :              from,
     248             :              sctp_clog.x.misc.log1,
     249             :              sctp_clog.x.misc.log2,
     250             :              sctp_clog.x.misc.log3,
     251             :              sctp_clog.x.misc.log4);
     252             : #endif
     253           0 : }
     254             : 
     255             : #ifdef SCTP_MBUF_LOGGING
     256             : void
     257             : sctp_log_mb(struct mbuf *m, int from)
     258             : {
     259             : #if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
     260             :         struct sctp_cwnd_log sctp_clog;
     261             : 
     262             :         sctp_clog.x.mb.mp = m;
     263             :         sctp_clog.x.mb.mbuf_flags = (uint8_t)(SCTP_BUF_GET_FLAGS(m));
     264             :         sctp_clog.x.mb.size = (uint16_t)(SCTP_BUF_LEN(m));
     265             :         sctp_clog.x.mb.data = SCTP_BUF_AT(m, 0);
     266             :         if (SCTP_BUF_IS_EXTENDED(m)) {
     267             :                 sctp_clog.x.mb.ext = SCTP_BUF_EXTEND_BASE(m);
     268             : #if defined(__APPLE__)
     269             :                 /* APPLE does not use a ref_cnt, but a forward/backward ref queue */
     270             : #else
     271             :                 sctp_clog.x.mb.refcnt = (uint8_t)(SCTP_BUF_EXTEND_REFCNT(m));
     272             : #endif
     273             :         } else {
     274             :                 sctp_clog.x.mb.ext = 0;
     275             :                 sctp_clog.x.mb.refcnt = 0;
     276             :         }
     277             :         SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
     278             :              SCTP_LOG_EVENT_MBUF,
     279             :              from,
     280             :              sctp_clog.x.misc.log1,
     281             :              sctp_clog.x.misc.log2,
     282             :              sctp_clog.x.misc.log3,
     283             :              sctp_clog.x.misc.log4);
     284             : #endif
     285             : }
     286             : 
     287             : void
     288             : sctp_log_mbc(struct mbuf *m, int from)
     289             : {
     290             :         struct mbuf *mat;
     291             : 
     292             :         for (mat = m; mat; mat = SCTP_BUF_NEXT(mat)) {
     293             :                 sctp_log_mb(mat, from);
     294             :         }
     295             : }
     296             : #endif
     297             : 
     298             : void
     299           0 : sctp_log_strm_del(struct sctp_queued_to_read *control, struct sctp_queued_to_read *poschk, int from)
     300             : {
     301             : #if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
     302             :         struct sctp_cwnd_log sctp_clog;
     303             : 
     304             :         if (control == NULL) {
     305             :                 SCTP_PRINTF("Gak log of NULL?\n");
     306             :                 return;
     307             :         }
     308             :         sctp_clog.x.strlog.stcb = control->stcb;
     309             :         sctp_clog.x.strlog.n_tsn = control->sinfo_tsn;
     310             :         sctp_clog.x.strlog.n_sseq = control->sinfo_ssn;
     311             :         sctp_clog.x.strlog.strm = control->sinfo_stream;
     312             :         if (poschk != NULL) {
     313             :                 sctp_clog.x.strlog.e_tsn = poschk->sinfo_tsn;
     314             :                 sctp_clog.x.strlog.e_sseq = poschk->sinfo_ssn;
     315             :         } else {
     316             :                 sctp_clog.x.strlog.e_tsn = 0;
     317             :                 sctp_clog.x.strlog.e_sseq = 0;
     318             :         }
     319             :         SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
     320             :              SCTP_LOG_EVENT_STRM,
     321             :              from,
     322             :              sctp_clog.x.misc.log1,
     323             :              sctp_clog.x.misc.log2,
     324             :              sctp_clog.x.misc.log3,
     325             :              sctp_clog.x.misc.log4);
     326             : #endif
     327           0 : }
     328             : 
     329             : void
     330           0 : sctp_log_cwnd(struct sctp_tcb *stcb, struct sctp_nets *net, int augment, uint8_t from)
     331             : {
     332             : #if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
     333             :         struct sctp_cwnd_log sctp_clog;
     334             : 
     335             :         sctp_clog.x.cwnd.net = net;
     336             :         if (stcb->asoc.send_queue_cnt > 255)
     337             :                 sctp_clog.x.cwnd.cnt_in_send = 255;
     338             :         else
     339             :                 sctp_clog.x.cwnd.cnt_in_send = stcb->asoc.send_queue_cnt;
     340             :         if (stcb->asoc.stream_queue_cnt > 255)
     341             :                 sctp_clog.x.cwnd.cnt_in_str = 255;
     342             :         else
     343             :                 sctp_clog.x.cwnd.cnt_in_str = stcb->asoc.stream_queue_cnt;
     344             : 
     345             :         if (net) {
     346             :                 sctp_clog.x.cwnd.cwnd_new_value = net->cwnd;
     347             :                 sctp_clog.x.cwnd.inflight = net->flight_size;
     348             :                 sctp_clog.x.cwnd.pseudo_cumack = net->pseudo_cumack;
     349             :                 sctp_clog.x.cwnd.meets_pseudo_cumack = net->new_pseudo_cumack;
     350             :                 sctp_clog.x.cwnd.need_new_pseudo_cumack = net->find_pseudo_cumack;
     351             :         }
     352             :         if (SCTP_CWNDLOG_PRESEND == from) {
     353             :                 sctp_clog.x.cwnd.meets_pseudo_cumack = stcb->asoc.peers_rwnd;
     354             :         }
     355             :         sctp_clog.x.cwnd.cwnd_augment = augment;
     356             :         SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
     357             :              SCTP_LOG_EVENT_CWND,
     358             :              from,
     359             :              sctp_clog.x.misc.log1,
     360             :              sctp_clog.x.misc.log2,
     361             :              sctp_clog.x.misc.log3,
     362             :              sctp_clog.x.misc.log4);
     363             : #endif
     364           0 : }
     365             : 
     366             : #ifndef __APPLE__
     367             : void
     368           0 : sctp_log_lock(struct sctp_inpcb *inp, struct sctp_tcb *stcb, uint8_t from)
     369             : {
     370             : #if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
     371             :         struct sctp_cwnd_log sctp_clog;
     372             : 
     373             :         memset(&sctp_clog, 0, sizeof(sctp_clog));
     374             :         if (inp) {
     375             :                 sctp_clog.x.lock.sock = (void *) inp->sctp_socket;
     376             : 
     377             :         } else {
     378             :                 sctp_clog.x.lock.sock = (void *) NULL;
     379             :         }
     380             :         sctp_clog.x.lock.inp = (void *) inp;
     381             : #if (defined(__FreeBSD__) && __FreeBSD_version >= 503000) || (defined(__APPLE__))
     382             :         if (stcb) {
     383             :                 sctp_clog.x.lock.tcb_lock = mtx_owned(&stcb->tcb_mtx);
     384             :         } else {
     385             :                 sctp_clog.x.lock.tcb_lock = SCTP_LOCK_UNKNOWN;
     386             :         }
     387             :         if (inp) {
     388             :                 sctp_clog.x.lock.inp_lock = mtx_owned(&inp->inp_mtx);
     389             :                 sctp_clog.x.lock.create_lock = mtx_owned(&inp->inp_create_mtx);
     390             :         } else {
     391             :                 sctp_clog.x.lock.inp_lock = SCTP_LOCK_UNKNOWN;
     392             :                 sctp_clog.x.lock.create_lock = SCTP_LOCK_UNKNOWN;
     393             :         }
     394             : #if (defined(__FreeBSD__) && __FreeBSD_version <= 602000)
     395             :         sctp_clog.x.lock.info_lock = mtx_owned(&SCTP_BASE_INFO(ipi_ep_mtx));
     396             : #else
     397             :         sctp_clog.x.lock.info_lock = rw_wowned(&SCTP_BASE_INFO(ipi_ep_mtx));
     398             : #endif
     399             :         if (inp && (inp->sctp_socket)) {
     400             :                 sctp_clog.x.lock.sock_lock = mtx_owned(&(inp->sctp_socket->so_rcv.sb_mtx));
     401             :                 sctp_clog.x.lock.sockrcvbuf_lock = mtx_owned(&(inp->sctp_socket->so_rcv.sb_mtx));
     402             :                 sctp_clog.x.lock.socksndbuf_lock = mtx_owned(&(inp->sctp_socket->so_snd.sb_mtx));
     403             :         } else {
     404             :                 sctp_clog.x.lock.sock_lock = SCTP_LOCK_UNKNOWN;
     405             :                 sctp_clog.x.lock.sockrcvbuf_lock = SCTP_LOCK_UNKNOWN;
     406             :                 sctp_clog.x.lock.socksndbuf_lock = SCTP_LOCK_UNKNOWN;
     407             :         }
     408             : #endif
     409             :         SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
     410             :              SCTP_LOG_LOCK_EVENT,
     411             :              from,
     412             :              sctp_clog.x.misc.log1,
     413             :              sctp_clog.x.misc.log2,
     414             :              sctp_clog.x.misc.log3,
     415             :              sctp_clog.x.misc.log4);
     416             : #endif
     417           0 : }
     418             : #endif
     419             : 
     420             : void
     421           0 : sctp_log_maxburst(struct sctp_tcb *stcb, struct sctp_nets *net, int error, int burst, uint8_t from)
     422             : {
     423             : #if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
     424             :         struct sctp_cwnd_log sctp_clog;
     425             : 
     426             :         memset(&sctp_clog, 0, sizeof(sctp_clog));
     427             :         sctp_clog.x.cwnd.net = net;
     428             :         sctp_clog.x.cwnd.cwnd_new_value = error;
     429             :         sctp_clog.x.cwnd.inflight = net->flight_size;
     430             :         sctp_clog.x.cwnd.cwnd_augment = burst;
     431             :         if (stcb->asoc.send_queue_cnt > 255)
     432             :                 sctp_clog.x.cwnd.cnt_in_send = 255;
     433             :         else
     434             :                 sctp_clog.x.cwnd.cnt_in_send = stcb->asoc.send_queue_cnt;
     435             :         if (stcb->asoc.stream_queue_cnt > 255)
     436             :                 sctp_clog.x.cwnd.cnt_in_str = 255;
     437             :         else
     438             :                 sctp_clog.x.cwnd.cnt_in_str = stcb->asoc.stream_queue_cnt;
     439             :         SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
     440             :              SCTP_LOG_EVENT_MAXBURST,
     441             :              from,
     442             :              sctp_clog.x.misc.log1,
     443             :              sctp_clog.x.misc.log2,
     444             :              sctp_clog.x.misc.log3,
     445             :              sctp_clog.x.misc.log4);
     446             : #endif
     447           0 : }
     448             : 
     449             : void
     450           0 : sctp_log_rwnd(uint8_t from, uint32_t peers_rwnd, uint32_t snd_size, uint32_t overhead)
     451             : {
     452             : #if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
     453             :         struct sctp_cwnd_log sctp_clog;
     454             : 
     455             :         sctp_clog.x.rwnd.rwnd = peers_rwnd;
     456             :         sctp_clog.x.rwnd.send_size = snd_size;
     457             :         sctp_clog.x.rwnd.overhead = overhead;
     458             :         sctp_clog.x.rwnd.new_rwnd = 0;
     459             :         SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
     460             :              SCTP_LOG_EVENT_RWND,
     461             :              from,
     462             :              sctp_clog.x.misc.log1,
     463             :              sctp_clog.x.misc.log2,
     464             :              sctp_clog.x.misc.log3,
     465             :              sctp_clog.x.misc.log4);
     466             : #endif
     467           0 : }
     468             : 
     469             : void
     470           0 : sctp_log_rwnd_set(uint8_t from, uint32_t peers_rwnd, uint32_t flight_size, uint32_t overhead, uint32_t a_rwndval)
     471             : {
     472             : #if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
     473             :         struct sctp_cwnd_log sctp_clog;
     474             : 
     475             :         sctp_clog.x.rwnd.rwnd = peers_rwnd;
     476             :         sctp_clog.x.rwnd.send_size = flight_size;
     477             :         sctp_clog.x.rwnd.overhead = overhead;
     478             :         sctp_clog.x.rwnd.new_rwnd = a_rwndval;
     479             :         SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
     480             :              SCTP_LOG_EVENT_RWND,
     481             :              from,
     482             :              sctp_clog.x.misc.log1,
     483             :              sctp_clog.x.misc.log2,
     484             :              sctp_clog.x.misc.log3,
     485             :              sctp_clog.x.misc.log4);
     486             : #endif
     487           0 : }
     488             : 
     489             : #ifdef SCTP_MBCNT_LOGGING
     490             : static void
     491             : sctp_log_mbcnt(uint8_t from, uint32_t total_oq, uint32_t book, uint32_t total_mbcnt_q, uint32_t mbcnt)
     492             : {
     493             : #if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
     494             :         struct sctp_cwnd_log sctp_clog;
     495             : 
     496             :         sctp_clog.x.mbcnt.total_queue_size = total_oq;
     497             :         sctp_clog.x.mbcnt.size_change = book;
     498             :         sctp_clog.x.mbcnt.total_queue_mb_size = total_mbcnt_q;
     499             :         sctp_clog.x.mbcnt.mbcnt_change = mbcnt;
     500             :         SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
     501             :              SCTP_LOG_EVENT_MBCNT,
     502             :              from,
     503             :              sctp_clog.x.misc.log1,
     504             :              sctp_clog.x.misc.log2,
     505             :              sctp_clog.x.misc.log3,
     506             :              sctp_clog.x.misc.log4);
     507             : #endif
     508             : }
     509             : #endif
     510             : 
     511             : void
     512           0 : sctp_misc_ints(uint8_t from, uint32_t a, uint32_t b, uint32_t c, uint32_t d)
     513             : {
     514             : #if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
     515             :         SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
     516             :              SCTP_LOG_MISC_EVENT,
     517             :              from,
     518             :              a, b, c, d);
     519             : #endif
     520           0 : }
     521             : 
     522             : void
     523           0 : sctp_wakeup_log(struct sctp_tcb *stcb, uint32_t wake_cnt, int from)
     524             : {
     525             : #if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
     526             :         struct sctp_cwnd_log sctp_clog;
     527             : 
     528             :         sctp_clog.x.wake.stcb = (void *)stcb;
     529             :         sctp_clog.x.wake.wake_cnt = wake_cnt;
     530             :         sctp_clog.x.wake.flight = stcb->asoc.total_flight_count;
     531             :         sctp_clog.x.wake.send_q = stcb->asoc.send_queue_cnt;
     532             :         sctp_clog.x.wake.sent_q = stcb->asoc.sent_queue_cnt;
     533             : 
     534             :         if (stcb->asoc.stream_queue_cnt < 0xff)
     535             :                 sctp_clog.x.wake.stream_qcnt = (uint8_t) stcb->asoc.stream_queue_cnt;
     536             :         else
     537             :                 sctp_clog.x.wake.stream_qcnt = 0xff;
     538             : 
     539             :         if (stcb->asoc.chunks_on_out_queue < 0xff)
     540             :                 sctp_clog.x.wake.chunks_on_oque = (uint8_t) stcb->asoc.chunks_on_out_queue;
     541             :         else
     542             :                 sctp_clog.x.wake.chunks_on_oque = 0xff;
     543             : 
     544             :         sctp_clog.x.wake.sctpflags = 0;
     545             :         /* set in the defered mode stuff */
     546             :         if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_DONT_WAKE)
     547             :                 sctp_clog.x.wake.sctpflags |= 1;
     548             :         if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_WAKEOUTPUT)
     549             :                 sctp_clog.x.wake.sctpflags |= 2;
     550             :         if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_WAKEINPUT)
     551             :                 sctp_clog.x.wake.sctpflags |= 4;
     552             :         /* what about the sb */
     553             :         if (stcb->sctp_socket) {
     554             :                 struct socket *so = stcb->sctp_socket;
     555             : 
     556             :                 sctp_clog.x.wake.sbflags = (uint8_t)((so->so_snd.sb_flags & 0x00ff));
     557             :         } else {
     558             :                 sctp_clog.x.wake.sbflags = 0xff;
     559             :         }
     560             :         SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
     561             :              SCTP_LOG_EVENT_WAKE,
     562             :              from,
     563             :              sctp_clog.x.misc.log1,
     564             :              sctp_clog.x.misc.log2,
     565             :              sctp_clog.x.misc.log3,
     566             :              sctp_clog.x.misc.log4);
     567             : #endif
     568           0 : }
     569             : 
     570             : void
     571           0 : sctp_log_block(uint8_t from, struct sctp_association *asoc, int sendlen)
     572             : {
     573             : #if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
     574             :         struct sctp_cwnd_log sctp_clog;
     575             : 
     576             :         sctp_clog.x.blk.onsb = asoc->total_output_queue_size;
     577             :         sctp_clog.x.blk.send_sent_qcnt = (uint16_t) (asoc->send_queue_cnt + asoc->sent_queue_cnt);
     578             :         sctp_clog.x.blk.peer_rwnd = asoc->peers_rwnd;
     579             :         sctp_clog.x.blk.stream_qcnt = (uint16_t) asoc->stream_queue_cnt;
     580             :         sctp_clog.x.blk.chunks_on_oque = (uint16_t) asoc->chunks_on_out_queue;
     581             :         sctp_clog.x.blk.flight_size = (uint16_t) (asoc->total_flight/1024);
     582             :         sctp_clog.x.blk.sndlen = sendlen;
     583             :         SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
     584             :              SCTP_LOG_EVENT_BLOCK,
     585             :              from,
     586             :              sctp_clog.x.misc.log1,
     587             :              sctp_clog.x.misc.log2,
     588             :              sctp_clog.x.misc.log3,
     589             :              sctp_clog.x.misc.log4);
     590             : #endif
     591           0 : }
     592             : 
     593             : int
     594           0 : sctp_fill_stat_log(void *optval SCTP_UNUSED, size_t *optsize SCTP_UNUSED)
     595             : {
     596             :         /* May need to fix this if ktrdump does not work */
     597           0 :         return (0);
     598             : }
     599             : 
     600             : #ifdef SCTP_AUDITING_ENABLED
     601             : uint8_t sctp_audit_data[SCTP_AUDIT_SIZE][2];
     602             : static int sctp_audit_indx = 0;
     603             : 
     604             : static
     605             : void
     606             : sctp_print_audit_report(void)
     607             : {
     608             :         int i;
     609             :         int cnt;
     610             : 
     611             :         cnt = 0;
     612             :         for (i = sctp_audit_indx; i < SCTP_AUDIT_SIZE; i++) {
     613             :                 if ((sctp_audit_data[i][0] == 0xe0) &&
     614             :                     (sctp_audit_data[i][1] == 0x01)) {
     615             :                         cnt = 0;
     616             :                         SCTP_PRINTF("\n");
     617             :                 } else if (sctp_audit_data[i][0] == 0xf0) {
     618             :                         cnt = 0;
     619             :                         SCTP_PRINTF("\n");
     620             :                 } else if ((sctp_audit_data[i][0] == 0xc0) &&
     621             :                     (sctp_audit_data[i][1] == 0x01)) {
     622             :                         SCTP_PRINTF("\n");
     623             :                         cnt = 0;
     624             :                 }
     625             :                 SCTP_PRINTF("%2.2x%2.2x ", (uint32_t) sctp_audit_data[i][0],
     626             :                             (uint32_t) sctp_audit_data[i][1]);
     627             :                 cnt++;
     628             :                 if ((cnt % 14) == 0)
     629             :                         SCTP_PRINTF("\n");
     630             :         }
     631             :         for (i = 0; i < sctp_audit_indx; i++) {
     632             :                 if ((sctp_audit_data[i][0] == 0xe0) &&
     633             :                     (sctp_audit_data[i][1] == 0x01)) {
     634             :                         cnt = 0;
     635             :                         SCTP_PRINTF("\n");
     636             :                 } else if (sctp_audit_data[i][0] == 0xf0) {
     637             :                         cnt = 0;
     638             :                         SCTP_PRINTF("\n");
     639             :                 } else if ((sctp_audit_data[i][0] == 0xc0) &&
     640             :                     (sctp_audit_data[i][1] == 0x01)) {
     641             :                         SCTP_PRINTF("\n");
     642             :                         cnt = 0;
     643             :                 }
     644             :                 SCTP_PRINTF("%2.2x%2.2x ", (uint32_t) sctp_audit_data[i][0],
     645             :                             (uint32_t) sctp_audit_data[i][1]);
     646             :                 cnt++;
     647             :                 if ((cnt % 14) == 0)
     648             :                         SCTP_PRINTF("\n");
     649             :         }
     650             :         SCTP_PRINTF("\n");
     651             : }
     652             : 
     653             : void
     654             : sctp_auditing(int from, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
     655             :     struct sctp_nets *net)
     656             : {
     657             :         int resend_cnt, tot_out, rep, tot_book_cnt;
     658             :         struct sctp_nets *lnet;
     659             :         struct sctp_tmit_chunk *chk;
     660             : 
     661             :         sctp_audit_data[sctp_audit_indx][0] = 0xAA;
     662             :         sctp_audit_data[sctp_audit_indx][1] = 0x000000ff & from;
     663             :         sctp_audit_indx++;
     664             :         if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
     665             :                 sctp_audit_indx = 0;
     666             :         }
     667             :         if (inp == NULL) {
     668             :                 sctp_audit_data[sctp_audit_indx][0] = 0xAF;
     669             :                 sctp_audit_data[sctp_audit_indx][1] = 0x01;
     670             :                 sctp_audit_indx++;
     671             :                 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
     672             :                         sctp_audit_indx = 0;
     673             :                 }
     674             :                 return;
     675             :         }
     676             :         if (stcb == NULL) {
     677             :                 sctp_audit_data[sctp_audit_indx][0] = 0xAF;
     678             :                 sctp_audit_data[sctp_audit_indx][1] = 0x02;
     679             :                 sctp_audit_indx++;
     680             :                 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
     681             :                         sctp_audit_indx = 0;
     682             :                 }
     683             :                 return;
     684             :         }
     685             :         sctp_audit_data[sctp_audit_indx][0] = 0xA1;
     686             :         sctp_audit_data[sctp_audit_indx][1] =
     687             :             (0x000000ff & stcb->asoc.sent_queue_retran_cnt);
     688             :         sctp_audit_indx++;
     689             :         if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
     690             :                 sctp_audit_indx = 0;
     691             :         }
     692             :         rep = 0;
     693             :         tot_book_cnt = 0;
     694             :         resend_cnt = tot_out = 0;
     695             :         TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
     696             :                 if (chk->sent == SCTP_DATAGRAM_RESEND) {
     697             :                         resend_cnt++;
     698             :                 } else if (chk->sent < SCTP_DATAGRAM_RESEND) {
     699             :                         tot_out += chk->book_size;
     700             :                         tot_book_cnt++;
     701             :                 }
     702             :         }
     703             :         if (resend_cnt != stcb->asoc.sent_queue_retran_cnt) {
     704             :                 sctp_audit_data[sctp_audit_indx][0] = 0xAF;
     705             :                 sctp_audit_data[sctp_audit_indx][1] = 0xA1;
     706             :                 sctp_audit_indx++;
     707             :                 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
     708             :                         sctp_audit_indx = 0;
     709             :                 }
     710             :                 SCTP_PRINTF("resend_cnt:%d asoc-tot:%d\n",
     711             :                             resend_cnt, stcb->asoc.sent_queue_retran_cnt);
     712             :                 rep = 1;
     713             :                 stcb->asoc.sent_queue_retran_cnt = resend_cnt;
     714             :                 sctp_audit_data[sctp_audit_indx][0] = 0xA2;
     715             :                 sctp_audit_data[sctp_audit_indx][1] =
     716             :                     (0x000000ff & stcb->asoc.sent_queue_retran_cnt);
     717             :                 sctp_audit_indx++;
     718             :                 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
     719             :                         sctp_audit_indx = 0;
     720             :                 }
     721             :         }
     722             :         if (tot_out != stcb->asoc.total_flight) {
     723             :                 sctp_audit_data[sctp_audit_indx][0] = 0xAF;
     724             :                 sctp_audit_data[sctp_audit_indx][1] = 0xA2;
     725             :                 sctp_audit_indx++;
     726             :                 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
     727             :                         sctp_audit_indx = 0;
     728             :                 }
     729             :                 rep = 1;
     730             :                 SCTP_PRINTF("tot_flt:%d asoc_tot:%d\n", tot_out,
     731             :                             (int)stcb->asoc.total_flight);
     732             :                 stcb->asoc.total_flight = tot_out;
     733             :         }
     734             :         if (tot_book_cnt != stcb->asoc.total_flight_count) {
     735             :                 sctp_audit_data[sctp_audit_indx][0] = 0xAF;
     736             :                 sctp_audit_data[sctp_audit_indx][1] = 0xA5;
     737             :                 sctp_audit_indx++;
     738             :                 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
     739             :                         sctp_audit_indx = 0;
     740             :                 }
     741             :                 rep = 1;
     742             :                 SCTP_PRINTF("tot_flt_book:%d\n", tot_book_cnt);
     743             : 
     744             :                 stcb->asoc.total_flight_count = tot_book_cnt;
     745             :         }
     746             :         tot_out = 0;
     747             :         TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
     748             :                 tot_out += lnet->flight_size;
     749             :         }
     750             :         if (tot_out != stcb->asoc.total_flight) {
     751             :                 sctp_audit_data[sctp_audit_indx][0] = 0xAF;
     752             :                 sctp_audit_data[sctp_audit_indx][1] = 0xA3;
     753             :                 sctp_audit_indx++;
     754             :                 if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
     755             :                         sctp_audit_indx = 0;
     756             :                 }
     757             :                 rep = 1;
     758             :                 SCTP_PRINTF("real flight:%d net total was %d\n",
     759             :                             stcb->asoc.total_flight, tot_out);
     760             :                 /* now corrective action */
     761             :                 TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
     762             : 
     763             :                         tot_out = 0;
     764             :                         TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
     765             :                                 if ((chk->whoTo == lnet) &&
     766             :                                     (chk->sent < SCTP_DATAGRAM_RESEND)) {
     767             :                                         tot_out += chk->book_size;
     768             :                                 }
     769             :                         }
     770             :                         if (lnet->flight_size != tot_out) {
     771             :                                 SCTP_PRINTF("net:%p flight was %d corrected to %d\n",
     772             :                                             (void *)lnet, lnet->flight_size,
     773             :                                             tot_out);
     774             :                                 lnet->flight_size = tot_out;
     775             :                         }
     776             :                 }
     777             :         }
     778             :         if (rep) {
     779             :                 sctp_print_audit_report();
     780             :         }
     781             : }
     782             : 
     783             : void
     784             : sctp_audit_log(uint8_t ev, uint8_t fd)
     785             : {
     786             : 
     787             :         sctp_audit_data[sctp_audit_indx][0] = ev;
     788             :         sctp_audit_data[sctp_audit_indx][1] = fd;
     789             :         sctp_audit_indx++;
     790             :         if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
     791             :                 sctp_audit_indx = 0;
     792             :         }
     793             : }
     794             : 
     795             : #endif
     796             : 
     797             : /*
     798             :  * sctp_stop_timers_for_shutdown() should be called
     799             :  * when entering the SHUTDOWN_SENT or SHUTDOWN_ACK_SENT
     800             :  * state to make sure that all timers are stopped.
     801             :  */
     802             : void
     803           0 : sctp_stop_timers_for_shutdown(struct sctp_tcb *stcb)
     804             : {
     805             :         struct sctp_association *asoc;
     806             :         struct sctp_nets *net;
     807             : 
     808           0 :         asoc = &stcb->asoc;
     809             : 
     810           0 :         (void)SCTP_OS_TIMER_STOP(&asoc->dack_timer.timer);
     811           0 :         (void)SCTP_OS_TIMER_STOP(&asoc->strreset_timer.timer);
     812           0 :         (void)SCTP_OS_TIMER_STOP(&asoc->asconf_timer.timer);
     813           0 :         (void)SCTP_OS_TIMER_STOP(&asoc->autoclose_timer.timer);
     814           0 :         (void)SCTP_OS_TIMER_STOP(&asoc->delayed_event_timer.timer);
     815           0 :         TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
     816           0 :                 (void)SCTP_OS_TIMER_STOP(&net->pmtu_timer.timer);
     817           0 :                 (void)SCTP_OS_TIMER_STOP(&net->hb_timer.timer);
     818             :         }
     819           0 : }
     820             : 
     821             : /*
     822             :  * a list of sizes based on typical mtu's, used only if next hop size not
     823             :  * returned.
     824             :  */
     825             : static uint32_t sctp_mtu_sizes[] = {
     826             :         68,
     827             :         296,
     828             :         508,
     829             :         512,
     830             :         544,
     831             :         576,
     832             :         1006,
     833             :         1492,
     834             :         1500,
     835             :         1536,
     836             :         2002,
     837             :         2048,
     838             :         4352,
     839             :         4464,
     840             :         8166,
     841             :         17914,
     842             :         32000,
     843             :         65535
     844             : };
     845             : 
     846             : /*
     847             :  * Return the largest MTU smaller than val. If there is no
     848             :  * entry, just return val.
     849             :  */
     850             : uint32_t
     851           0 : sctp_get_prev_mtu(uint32_t val)
     852             : {
     853             :         uint32_t i;
     854             : 
     855           0 :         if (val <= sctp_mtu_sizes[0]) {
     856           0 :                 return (val);
     857             :         }
     858           0 :         for (i = 1; i < (sizeof(sctp_mtu_sizes) / sizeof(uint32_t)); i++) {
     859           0 :                 if (val <= sctp_mtu_sizes[i]) {
     860           0 :                         break;
     861             :                 }
     862             :         }
     863           0 :         return (sctp_mtu_sizes[i - 1]);
     864             : }
     865             : 
     866             : /*
     867             :  * Return the smallest MTU larger than val. If there is no
     868             :  * entry, just return val.
     869             :  */
     870             : uint32_t
     871           0 : sctp_get_next_mtu(uint32_t val)
     872             : {
     873             :         /* select another MTU that is just bigger than this one */
     874             :         uint32_t i;
     875             : 
     876           0 :         for (i = 0; i < (sizeof(sctp_mtu_sizes) / sizeof(uint32_t)); i++) {
     877           0 :                 if (val < sctp_mtu_sizes[i]) {
     878           0 :                         return (sctp_mtu_sizes[i]);
     879             :                 }
     880             :         }
     881           0 :         return (val);
     882             : }
     883             : 
     884             : void
     885           0 : sctp_fill_random_store(struct sctp_pcb *m)
     886             : {
     887             :         /*
     888             :          * Here we use the MD5/SHA-1 to hash with our good randomNumbers and
     889             :          * our counter. The result becomes our good random numbers and we
     890             :          * then setup to give these out. Note that we do no locking to
     891             :          * protect this. This is ok, since if competing folks call this we
     892             :          * will get more gobbled gook in the random store which is what we
     893             :          * want. There is a danger that two guys will use the same random
     894             :          * numbers, but thats ok too since that is random as well :->
     895             :          */
     896           0 :         m->store_at = 0;
     897           0 :         (void)sctp_hmac(SCTP_HMAC, (uint8_t *)m->random_numbers,
     898           0 :             sizeof(m->random_numbers), (uint8_t *)&m->random_counter,
     899           0 :             sizeof(m->random_counter), (uint8_t *)m->random_store);
     900           0 :         m->random_counter++;
     901           0 : }
     902             : 
     903             : uint32_t
     904           0 : sctp_select_initial_TSN(struct sctp_pcb *inp)
     905             : {
     906             :         /*
     907             :          * A true implementation should use random selection process to get
     908             :          * the initial stream sequence number, using RFC1750 as a good
     909             :          * guideline
     910             :          */
     911             :         uint32_t x, *xp;
     912             :         uint8_t *p;
     913             :         int store_at, new_store;
     914             : 
     915           0 :         if (inp->initial_sequence_debug != 0) {
     916             :                 uint32_t ret;
     917             : 
     918           0 :                 ret = inp->initial_sequence_debug;
     919           0 :                 inp->initial_sequence_debug++;
     920           0 :                 return (ret);
     921             :         }
     922             :  retry:
     923           0 :         store_at = inp->store_at;
     924           0 :         new_store = store_at + sizeof(uint32_t);
     925           0 :         if (new_store >= (SCTP_SIGNATURE_SIZE-3)) {
     926           0 :                 new_store = 0;
     927             :         }
     928           0 :         if (!atomic_cmpset_int(&inp->store_at, store_at, new_store)) {
     929           0 :                 goto retry;
     930             :         }
     931           0 :         if (new_store == 0) {
     932             :                 /* Refill the random store */
     933           0 :                 sctp_fill_random_store(inp);
     934             :         }
     935           0 :         p = &inp->random_store[store_at];
     936           0 :         xp = (uint32_t *)p;
     937           0 :         x = *xp;
     938           0 :         return (x);
     939             : }
     940             : 
     941             : uint32_t
     942           0 : sctp_select_a_tag(struct sctp_inpcb *inp, uint16_t lport, uint16_t rport, int check)
     943             : {
     944             :         uint32_t x;
     945             :         struct timeval now;
     946             : 
     947           0 :         if (check) {
     948           0 :                 (void)SCTP_GETTIME_TIMEVAL(&now);
     949             :         }
     950             :         for (;;) {
     951           0 :                 x = sctp_select_initial_TSN(&inp->sctp_ep);
     952           0 :                 if (x == 0) {
     953             :                         /* we never use 0 */
     954           0 :                         continue;
     955             :                 }
     956           0 :                 if (!check || sctp_is_vtag_good(x, lport, rport, &now)) {
     957             :                         break;
     958             :                 }
     959             :         }
     960           0 :         return (x);
     961             : }
     962             : 
     963             : int
     964           0 : sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
     965             :                uint32_t override_tag, uint32_t vrf_id)
     966             : {
     967             :         struct sctp_association *asoc;
     968             :         /*
     969             :          * Anything set to zero is taken care of by the allocation routine's
     970             :          * bzero
     971             :          */
     972             : 
     973             :         /*
     974             :          * Up front select what scoping to apply on addresses I tell my peer
     975             :          * Not sure what to do with these right now, we will need to come up
     976             :          * with a way to set them. We may need to pass them through from the
     977             :          * caller in the sctp_aloc_assoc() function.
     978             :          */
     979             :         int i;
     980             : #if defined(SCTP_DETAILED_STR_STATS)
     981             :         int j;
     982             : #endif
     983             : 
     984           0 :         asoc = &stcb->asoc;
     985             :         /* init all variables to a known value. */
     986           0 :         SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_INUSE);
     987           0 :         asoc->max_burst = inp->sctp_ep.max_burst;
     988           0 :         asoc->fr_max_burst = inp->sctp_ep.fr_max_burst;
     989           0 :         asoc->heart_beat_delay = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]);
     990           0 :         asoc->cookie_life = inp->sctp_ep.def_cookie_life;
     991           0 :         asoc->sctp_cmt_on_off = inp->sctp_cmt_on_off;
     992           0 :         asoc->ecn_supported = inp->ecn_supported;
     993           0 :         asoc->prsctp_supported = inp->prsctp_supported;
     994           0 :         asoc->auth_supported = inp->auth_supported;
     995           0 :         asoc->asconf_supported = inp->asconf_supported;
     996           0 :         asoc->reconfig_supported = inp->reconfig_supported;
     997           0 :         asoc->nrsack_supported = inp->nrsack_supported;
     998           0 :         asoc->pktdrop_supported = inp->pktdrop_supported;
     999           0 :         asoc->sctp_cmt_pf = (uint8_t)0;
    1000           0 :         asoc->sctp_frag_point = inp->sctp_frag_point;
    1001           0 :         asoc->sctp_features = inp->sctp_features;
    1002           0 :         asoc->default_dscp = inp->sctp_ep.default_dscp;
    1003           0 :         asoc->max_cwnd = inp->max_cwnd;
    1004             : #ifdef INET6
    1005             :         if (inp->sctp_ep.default_flowlabel) {
    1006             :                 asoc->default_flowlabel = inp->sctp_ep.default_flowlabel;
    1007             :         } else {
    1008             :                 if (inp->ip_inp.inp.inp_flags & IN6P_AUTOFLOWLABEL) {
    1009             :                         asoc->default_flowlabel = sctp_select_initial_TSN(&inp->sctp_ep);
    1010             :                         asoc->default_flowlabel &= 0x000fffff;
    1011             :                         asoc->default_flowlabel |= 0x80000000;
    1012             :                 } else {
    1013             :                         asoc->default_flowlabel = 0;
    1014             :                 }
    1015             :         }
    1016             : #endif
    1017           0 :         asoc->sb_send_resv = 0;
    1018           0 :         if (override_tag) {
    1019           0 :                 asoc->my_vtag = override_tag;
    1020             :         } else {
    1021           0 :                 asoc->my_vtag = sctp_select_a_tag(inp, stcb->sctp_ep->sctp_lport, stcb->rport,  1);
    1022             :         }
    1023             :         /* Get the nonce tags */
    1024           0 :         asoc->my_vtag_nonce = sctp_select_a_tag(inp, stcb->sctp_ep->sctp_lport, stcb->rport, 0);
    1025           0 :         asoc->peer_vtag_nonce = sctp_select_a_tag(inp, stcb->sctp_ep->sctp_lport, stcb->rport, 0);
    1026           0 :         asoc->vrf_id = vrf_id;
    1027             : 
    1028             : #ifdef SCTP_ASOCLOG_OF_TSNS
    1029             :         asoc->tsn_in_at = 0;
    1030             :         asoc->tsn_out_at = 0;
    1031             :         asoc->tsn_in_wrapped = 0;
    1032             :         asoc->tsn_out_wrapped = 0;
    1033             :         asoc->cumack_log_at = 0;
    1034             :         asoc->cumack_log_atsnt = 0;
    1035             : #endif
    1036             : #ifdef SCTP_FS_SPEC_LOG
    1037             :         asoc->fs_index = 0;
    1038             : #endif
    1039           0 :         asoc->refcnt = 0;
    1040           0 :         asoc->assoc_up_sent = 0;
    1041           0 :         asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number = asoc->sending_seq =
    1042           0 :             sctp_select_initial_TSN(&inp->sctp_ep);
    1043           0 :         asoc->asconf_seq_out_acked = asoc->asconf_seq_out - 1;
    1044             :         /* we are optimisitic here */
    1045           0 :         asoc->peer_supports_nat = 0;
    1046           0 :         asoc->sent_queue_retran_cnt = 0;
    1047             : 
    1048             :         /* for CMT */
    1049           0 :         asoc->last_net_cmt_send_started = NULL;
    1050             : 
    1051             :         /* This will need to be adjusted */
    1052           0 :         asoc->last_acked_seq = asoc->init_seq_number - 1;
    1053           0 :         asoc->advanced_peer_ack_point = asoc->last_acked_seq;
    1054           0 :         asoc->asconf_seq_in = asoc->last_acked_seq;
    1055             : 
    1056             :         /* here we are different, we hold the next one we expect */
    1057           0 :         asoc->str_reset_seq_in = asoc->last_acked_seq + 1;
    1058             : 
    1059           0 :         asoc->initial_init_rto_max = inp->sctp_ep.initial_init_rto_max;
    1060           0 :         asoc->initial_rto = inp->sctp_ep.initial_rto;
    1061             : 
    1062           0 :         asoc->max_init_times = inp->sctp_ep.max_init_times;
    1063           0 :         asoc->max_send_times = inp->sctp_ep.max_send_times;
    1064           0 :         asoc->def_net_failure = inp->sctp_ep.def_net_failure;
    1065           0 :         asoc->def_net_pf_threshold = inp->sctp_ep.def_net_pf_threshold;
    1066           0 :         asoc->free_chunk_cnt = 0;
    1067             : 
    1068           0 :         asoc->iam_blocking = 0;
    1069           0 :         asoc->context = inp->sctp_context;
    1070           0 :         asoc->local_strreset_support = inp->local_strreset_support;
    1071           0 :         asoc->def_send = inp->def_send;
    1072           0 :         asoc->delayed_ack = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]);
    1073           0 :         asoc->sack_freq = inp->sctp_ep.sctp_sack_freq;
    1074           0 :         asoc->pr_sctp_cnt = 0;
    1075           0 :         asoc->total_output_queue_size = 0;
    1076             : 
    1077           0 :         if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
    1078           0 :                 asoc->scope.ipv6_addr_legal = 1;
    1079           0 :                 if (SCTP_IPV6_V6ONLY(inp) == 0) {
    1080           0 :                         asoc->scope.ipv4_addr_legal = 1;
    1081             :                 } else {
    1082           0 :                         asoc->scope.ipv4_addr_legal = 0;
    1083             :                 }
    1084             : #if defined(__Userspace__)
    1085           0 :                         asoc->scope.conn_addr_legal = 0;
    1086             : #endif
    1087             :         } else {
    1088           0 :                 asoc->scope.ipv6_addr_legal = 0;
    1089             : #if defined(__Userspace__)
    1090           0 :                 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_CONN) {
    1091           0 :                         asoc->scope.conn_addr_legal = 1;
    1092           0 :                         asoc->scope.ipv4_addr_legal = 0;
    1093             :                 } else {
    1094           0 :                         asoc->scope.conn_addr_legal = 0;
    1095           0 :                         asoc->scope.ipv4_addr_legal = 1;
    1096             :                 }
    1097             : #else
    1098             :                 asoc->scope.ipv4_addr_legal = 1;
    1099             : #endif
    1100             :         }
    1101             : 
    1102           0 :         asoc->my_rwnd = max(SCTP_SB_LIMIT_RCV(inp->sctp_socket), SCTP_MINIMAL_RWND);
    1103           0 :         asoc->peers_rwnd = SCTP_SB_LIMIT_RCV(inp->sctp_socket);
    1104             : 
    1105           0 :         asoc->smallest_mtu = inp->sctp_frag_point;
    1106           0 :         asoc->minrto = inp->sctp_ep.sctp_minrto;
    1107           0 :         asoc->maxrto = inp->sctp_ep.sctp_maxrto;
    1108             : 
    1109           0 :         asoc->locked_on_sending = NULL;
    1110           0 :         asoc->stream_locked_on = 0;
    1111           0 :         asoc->ecn_echo_cnt_onq = 0;
    1112           0 :         asoc->stream_locked = 0;
    1113             : 
    1114           0 :         asoc->send_sack = 1;
    1115             : 
    1116           0 :         LIST_INIT(&asoc->sctp_restricted_addrs);
    1117             : 
    1118           0 :         TAILQ_INIT(&asoc->nets);
    1119           0 :         TAILQ_INIT(&asoc->pending_reply_queue);
    1120           0 :         TAILQ_INIT(&asoc->asconf_ack_sent);
    1121             :         /* Setup to fill the hb random cache at first HB */
    1122           0 :         asoc->hb_random_idx = 4;
    1123             : 
    1124           0 :         asoc->sctp_autoclose_ticks = inp->sctp_ep.auto_close_time;
    1125             : 
    1126           0 :         stcb->asoc.congestion_control_module = inp->sctp_ep.sctp_default_cc_module;
    1127           0 :         stcb->asoc.cc_functions = sctp_cc_functions[inp->sctp_ep.sctp_default_cc_module];
    1128             : 
    1129           0 :         stcb->asoc.stream_scheduling_module = inp->sctp_ep.sctp_default_ss_module;
    1130           0 :         stcb->asoc.ss_functions = sctp_ss_functions[inp->sctp_ep.sctp_default_ss_module];
    1131             : 
    1132             :         /*
    1133             :          * Now the stream parameters, here we allocate space for all streams
    1134             :          * that we request by default.
    1135             :          */
    1136           0 :         asoc->strm_realoutsize = asoc->streamoutcnt = asoc->pre_open_streams =
    1137           0 :             inp->sctp_ep.pre_open_stream_count;
    1138           0 :         SCTP_MALLOC(asoc->strmout, struct sctp_stream_out *,
    1139             :                     asoc->streamoutcnt * sizeof(struct sctp_stream_out),
    1140             :                     SCTP_M_STRMO);
    1141           0 :         if (asoc->strmout == NULL) {
    1142             :                 /* big trouble no memory */
    1143             :                 SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOMEM);
    1144           0 :                 return (ENOMEM);
    1145             :         }
    1146           0 :         for (i = 0; i < asoc->streamoutcnt; i++) {
    1147             :                 /*
    1148             :                  * inbound side must be set to 0xffff, also NOTE when we get
    1149             :                  * the INIT-ACK back (for INIT sender) we MUST reduce the
    1150             :                  * count (streamoutcnt) but first check if we sent to any of
    1151             :                  * the upper streams that were dropped (if some were). Those
    1152             :                  * that were dropped must be notified to the upper layer as
    1153             :                  * failed to send.
    1154             :                  */
    1155           0 :                 asoc->strmout[i].next_sequence_send = 0x0;
    1156           0 :                 TAILQ_INIT(&asoc->strmout[i].outqueue);
    1157           0 :                 asoc->strmout[i].chunks_on_queues = 0;
    1158             : #if defined(SCTP_DETAILED_STR_STATS)
    1159             :                 for (j = 0; j < SCTP_PR_SCTP_MAX + 1; j++) {
    1160             :                         asoc->strmout[i].abandoned_sent[j] = 0;
    1161             :                         asoc->strmout[i].abandoned_unsent[j] = 0;
    1162             :                 }
    1163             : #else
    1164           0 :                 asoc->strmout[i].abandoned_sent[0] = 0;
    1165           0 :                 asoc->strmout[i].abandoned_unsent[0] = 0;
    1166             : #endif
    1167           0 :                 asoc->strmout[i].stream_no = i;
    1168           0 :                 asoc->strmout[i].last_msg_incomplete = 0;
    1169           0 :                 asoc->ss_functions.sctp_ss_init_stream(&asoc->strmout[i], NULL);
    1170             :         }
    1171           0 :         asoc->ss_functions.sctp_ss_init(stcb, asoc, 0);
    1172             : 
    1173             :         /* Now the mapping array */
    1174           0 :         asoc->mapping_array_size = SCTP_INITIAL_MAPPING_ARRAY;
    1175           0 :         SCTP_MALLOC(asoc->mapping_array, uint8_t *, asoc->mapping_array_size,
    1176             :                     SCTP_M_MAP);
    1177           0 :         if (asoc->mapping_array == NULL) {
    1178           0 :                 SCTP_FREE(asoc->strmout, SCTP_M_STRMO);
    1179             :                 SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOMEM);
    1180           0 :                 return (ENOMEM);
    1181             :         }
    1182           0 :         memset(asoc->mapping_array, 0, asoc->mapping_array_size);
    1183           0 :         SCTP_MALLOC(asoc->nr_mapping_array, uint8_t *, asoc->mapping_array_size,
    1184             :             SCTP_M_MAP);
    1185           0 :         if (asoc->nr_mapping_array == NULL) {
    1186           0 :                 SCTP_FREE(asoc->strmout, SCTP_M_STRMO);
    1187           0 :                 SCTP_FREE(asoc->mapping_array, SCTP_M_MAP);
    1188             :                 SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOMEM);
    1189           0 :                 return (ENOMEM);
    1190             :         }
    1191           0 :         memset(asoc->nr_mapping_array, 0, asoc->mapping_array_size);
    1192             : 
    1193             :         /* Now the init of the other outqueues */
    1194           0 :         TAILQ_INIT(&asoc->free_chunks);
    1195           0 :         TAILQ_INIT(&asoc->control_send_queue);
    1196           0 :         TAILQ_INIT(&asoc->asconf_send_queue);
    1197           0 :         TAILQ_INIT(&asoc->send_queue);
    1198           0 :         TAILQ_INIT(&asoc->sent_queue);
    1199           0 :         TAILQ_INIT(&asoc->reasmqueue);
    1200           0 :         TAILQ_INIT(&asoc->resetHead);
    1201           0 :         asoc->max_inbound_streams = inp->sctp_ep.max_open_streams_intome;
    1202           0 :         TAILQ_INIT(&asoc->asconf_queue);
    1203             :         /* authentication fields */
    1204           0 :         asoc->authinfo.random = NULL;
    1205           0 :         asoc->authinfo.active_keyid = 0;
    1206           0 :         asoc->authinfo.assoc_key = NULL;
    1207           0 :         asoc->authinfo.assoc_keyid = 0;
    1208           0 :         asoc->authinfo.recv_key = NULL;
    1209           0 :         asoc->authinfo.recv_keyid = 0;
    1210           0 :         LIST_INIT(&asoc->shared_keys);
    1211           0 :         asoc->marked_retrans = 0;
    1212           0 :         asoc->port = inp->sctp_ep.port;
    1213           0 :         asoc->timoinit = 0;
    1214           0 :         asoc->timodata = 0;
    1215           0 :         asoc->timosack = 0;
    1216           0 :         asoc->timoshutdown = 0;
    1217           0 :         asoc->timoheartbeat = 0;
    1218           0 :         asoc->timocookie = 0;
    1219           0 :         asoc->timoshutdownack = 0;
    1220           0 :         (void)SCTP_GETTIME_TIMEVAL(&asoc->start_time);
    1221           0 :         asoc->discontinuity_time = asoc->start_time;
    1222           0 :         for (i = 0; i < SCTP_PR_SCTP_MAX + 1; i++) {
    1223           0 :                 asoc->abandoned_unsent[i] = 0;
    1224           0 :                 asoc->abandoned_sent[i] = 0;
    1225             :         }
    1226             :         /* sa_ignore MEMLEAK {memory is put in the assoc mapping array and freed later when
    1227             :          * the association is freed.
    1228             :          */
    1229           0 :         return (0);
    1230             : }
    1231             : 
    1232             : void
    1233           0 : sctp_print_mapping_array(struct sctp_association *asoc)
    1234             : {
    1235             :         unsigned int i, limit;
    1236             : 
    1237           0 :         SCTP_PRINTF("Mapping array size: %d, baseTSN: %8.8x, cumAck: %8.8x, highestTSN: (%8.8x, %8.8x).\n",
    1238             :                     asoc->mapping_array_size,
    1239             :                     asoc->mapping_array_base_tsn,
    1240             :                     asoc->cumulative_tsn,
    1241             :                     asoc->highest_tsn_inside_map,
    1242             :                     asoc->highest_tsn_inside_nr_map);
    1243           0 :         for (limit = asoc->mapping_array_size; limit > 1; limit--) {
    1244           0 :                 if (asoc->mapping_array[limit - 1] != 0) {
    1245           0 :                         break;
    1246             :                 }
    1247             :         }
    1248           0 :         SCTP_PRINTF("Renegable mapping array (last %d entries are zero):\n", asoc->mapping_array_size - limit);
    1249           0 :         for (i = 0; i < limit; i++) {
    1250           0 :                 SCTP_PRINTF("%2.2x%c", asoc->mapping_array[i], ((i + 1) % 16) ? ' ' : '\n');
    1251             :         }
    1252           0 :         if (limit % 16)
    1253           0 :                 SCTP_PRINTF("\n");
    1254           0 :         for (limit = asoc->mapping_array_size; limit > 1; limit--) {
    1255           0 :                 if (asoc->nr_mapping_array[limit - 1]) {
    1256           0 :                         break;
    1257             :                 }
    1258             :         }
    1259           0 :         SCTP_PRINTF("Non renegable mapping array (last %d entries are zero):\n", asoc->mapping_array_size - limit);
    1260           0 :         for (i = 0; i < limit; i++) {
    1261           0 :                 SCTP_PRINTF("%2.2x%c", asoc->nr_mapping_array[i], ((i + 1) % 16) ? ' ': '\n');
    1262             :         }
    1263           0 :         if (limit % 16)
    1264           0 :                 SCTP_PRINTF("\n");
    1265           0 : }
    1266             : 
    1267             : int
    1268           0 : sctp_expand_mapping_array(struct sctp_association *asoc, uint32_t needed)
    1269             : {
    1270             :         /* mapping array needs to grow */
    1271             :         uint8_t *new_array1, *new_array2;
    1272             :         uint32_t new_size;
    1273             : 
    1274           0 :         new_size = asoc->mapping_array_size + ((needed+7)/8 + SCTP_MAPPING_ARRAY_INCR);
    1275           0 :         SCTP_MALLOC(new_array1, uint8_t *, new_size, SCTP_M_MAP);
    1276           0 :         SCTP_MALLOC(new_array2, uint8_t *, new_size, SCTP_M_MAP);
    1277           0 :         if ((new_array1 == NULL) || (new_array2 == NULL)) {
    1278             :                 /* can't get more, forget it */
    1279           0 :                 SCTP_PRINTF("No memory for expansion of SCTP mapping array %d\n", new_size);
    1280           0 :                 if (new_array1) {
    1281           0 :                         SCTP_FREE(new_array1, SCTP_M_MAP);
    1282             :                 }
    1283           0 :                 if (new_array2) {
    1284           0 :                         SCTP_FREE(new_array2, SCTP_M_MAP);
    1285             :                 }
    1286           0 :                 return (-1);
    1287             :         }
    1288           0 :         memset(new_array1, 0, new_size);
    1289           0 :         memset(new_array2, 0, new_size);
    1290           0 :         memcpy(new_array1, asoc->mapping_array, asoc->mapping_array_size);
    1291           0 :         memcpy(new_array2, asoc->nr_mapping_array, asoc->mapping_array_size);
    1292           0 :         SCTP_FREE(asoc->mapping_array, SCTP_M_MAP);
    1293           0 :         SCTP_FREE(asoc->nr_mapping_array, SCTP_M_MAP);
    1294           0 :         asoc->mapping_array = new_array1;
    1295           0 :         asoc->nr_mapping_array = new_array2;
    1296           0 :         asoc->mapping_array_size = new_size;
    1297           0 :         return (0);
    1298             : }
    1299             : 
    1300             : 
    1301             : static void
    1302           0 : sctp_iterator_work(struct sctp_iterator *it)
    1303             : {
    1304           0 :         int iteration_count = 0;
    1305           0 :         int inp_skip = 0;
    1306           0 :         int first_in = 1;
    1307             :         struct sctp_inpcb *tinp;
    1308             : 
    1309           0 :         SCTP_INP_INFO_RLOCK();
    1310           0 :         SCTP_ITERATOR_LOCK();
    1311           0 :         sctp_it_ctl.cur_it = it;
    1312           0 :         if (it->inp) {
    1313           0 :                 SCTP_INP_RLOCK(it->inp);
    1314           0 :                 SCTP_INP_DECR_REF(it->inp);
    1315             :         }
    1316           0 :         if (it->inp == NULL) {
    1317             :                 /* iterator is complete */
    1318             : done_with_iterator:
    1319           0 :                 sctp_it_ctl.cur_it = NULL;
    1320           0 :                 SCTP_ITERATOR_UNLOCK();
    1321           0 :                 SCTP_INP_INFO_RUNLOCK();
    1322           0 :                 if (it->function_atend != NULL) {
    1323           0 :                         (*it->function_atend) (it->pointer, it->val);
    1324             :                 }
    1325           0 :                 SCTP_FREE(it, SCTP_M_ITER);
    1326           0 :                 return;
    1327             :         }
    1328             : select_a_new_ep:
    1329           0 :         if (first_in) {
    1330           0 :                 first_in = 0;
    1331             :         } else {
    1332           0 :                 SCTP_INP_RLOCK(it->inp);
    1333             :         }
    1334           0 :         while (((it->pcb_flags) &&
    1335           0 :                 ((it->inp->sctp_flags & it->pcb_flags) != it->pcb_flags)) ||
    1336           0 :                ((it->pcb_features) &&
    1337           0 :                 ((it->inp->sctp_features & it->pcb_features) != it->pcb_features))) {
    1338             :                 /* endpoint flags or features don't match, so keep looking */
    1339           0 :                 if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) {
    1340           0 :                         SCTP_INP_RUNLOCK(it->inp);
    1341           0 :                         goto done_with_iterator;
    1342             :                 }
    1343           0 :                 tinp = it->inp;
    1344           0 :                 it->inp = LIST_NEXT(it->inp, sctp_list);
    1345           0 :                 SCTP_INP_RUNLOCK(tinp);
    1346           0 :                 if (it->inp == NULL) {
    1347           0 :                         goto done_with_iterator;
    1348             :                 }
    1349           0 :                 SCTP_INP_RLOCK(it->inp);
    1350             :         }
    1351             :         /* now go through each assoc which is in the desired state */
    1352           0 :         if (it->done_current_ep == 0) {
    1353           0 :                 if (it->function_inp != NULL)
    1354           0 :                         inp_skip = (*it->function_inp)(it->inp, it->pointer, it->val);
    1355           0 :                 it->done_current_ep = 1;
    1356             :         }
    1357           0 :         if (it->stcb == NULL) {
    1358             :                 /* run the per instance function */
    1359           0 :                 it->stcb = LIST_FIRST(&it->inp->sctp_asoc_list);
    1360             :         }
    1361           0 :         if ((inp_skip) || it->stcb == NULL) {
    1362           0 :                 if (it->function_inp_end != NULL) {
    1363           0 :                         inp_skip = (*it->function_inp_end)(it->inp,
    1364             :                                                            it->pointer,
    1365             :                                                            it->val);
    1366             :                 }
    1367           0 :                 SCTP_INP_RUNLOCK(it->inp);
    1368           0 :                 goto no_stcb;
    1369             :         }
    1370           0 :         while (it->stcb) {
    1371           0 :                 SCTP_TCB_LOCK(it->stcb);
    1372           0 :                 if (it->asoc_state && ((it->stcb->asoc.state & it->asoc_state) != it->asoc_state)) {
    1373             :                         /* not in the right state... keep looking */
    1374           0 :                         SCTP_TCB_UNLOCK(it->stcb);
    1375           0 :                         goto next_assoc;
    1376             :                 }
    1377             :                 /* see if we have limited out the iterator loop */
    1378           0 :                 iteration_count++;
    1379           0 :                 if (iteration_count > SCTP_ITERATOR_MAX_AT_ONCE) {
    1380             :                         /* Pause to let others grab the lock */
    1381           0 :                         atomic_add_int(&it->stcb->asoc.refcnt, 1);
    1382           0 :                         SCTP_TCB_UNLOCK(it->stcb);
    1383           0 :                         SCTP_INP_INCR_REF(it->inp);
    1384           0 :                         SCTP_INP_RUNLOCK(it->inp);
    1385           0 :                         SCTP_ITERATOR_UNLOCK();
    1386           0 :                         SCTP_INP_INFO_RUNLOCK();
    1387           0 :                         SCTP_INP_INFO_RLOCK();
    1388           0 :                         SCTP_ITERATOR_LOCK();
    1389           0 :                         if (sctp_it_ctl.iterator_flags) {
    1390             :                                 /* We won't be staying here */
    1391           0 :                                 SCTP_INP_DECR_REF(it->inp);
    1392           0 :                                 atomic_add_int(&it->stcb->asoc.refcnt, -1);
    1393             : #if !defined(__FreeBSD__)
    1394           0 :                                 if (sctp_it_ctl.iterator_flags &
    1395             :                                    SCTP_ITERATOR_MUST_EXIT) {
    1396           0 :                                         goto done_with_iterator;
    1397             :                                 }
    1398             : #endif
    1399           0 :                                 if (sctp_it_ctl.iterator_flags &
    1400             :                                    SCTP_ITERATOR_STOP_CUR_IT) {
    1401           0 :                                         sctp_it_ctl.iterator_flags &= ~SCTP_ITERATOR_STOP_CUR_IT;
    1402           0 :                                         goto done_with_iterator;
    1403             :                                 }
    1404           0 :                                 if (sctp_it_ctl.iterator_flags &
    1405             :                                    SCTP_ITERATOR_STOP_CUR_INP) {
    1406           0 :                                         sctp_it_ctl.iterator_flags &= ~SCTP_ITERATOR_STOP_CUR_INP;
    1407           0 :                                         goto no_stcb;
    1408             :                                 }
    1409             :                                 /* If we reach here huh? */
    1410           0 :                                 SCTP_PRINTF("Unknown it ctl flag %x\n",
    1411             :                                             sctp_it_ctl.iterator_flags);
    1412           0 :                                 sctp_it_ctl.iterator_flags = 0;
    1413             :                         }
    1414           0 :                         SCTP_INP_RLOCK(it->inp);
    1415           0 :                         SCTP_INP_DECR_REF(it->inp);
    1416           0 :                         SCTP_TCB_LOCK(it->stcb);
    1417           0 :                         atomic_add_int(&it->stcb->asoc.refcnt, -1);
    1418           0 :                         iteration_count = 0;
    1419             :                 }
    1420             : 
    1421             :                 /* run function on this one */
    1422           0 :                 (*it->function_assoc)(it->inp, it->stcb, it->pointer, it->val);
    1423             : 
    1424             :                 /*
    1425             :                  * we lie here, it really needs to have its own type but
    1426             :                  * first I must verify that this won't effect things :-0
    1427             :                  */
    1428           0 :                 if (it->no_chunk_output == 0)
    1429           0 :                         sctp_chunk_output(it->inp, it->stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED);
    1430             : 
    1431           0 :                 SCTP_TCB_UNLOCK(it->stcb);
    1432             :         next_assoc:
    1433           0 :                 it->stcb = LIST_NEXT(it->stcb, sctp_tcblist);
    1434           0 :                 if (it->stcb == NULL) {
    1435             :                         /* Run last function */
    1436           0 :                         if (it->function_inp_end != NULL) {
    1437           0 :                                 inp_skip = (*it->function_inp_end)(it->inp,
    1438             :                                                                    it->pointer,
    1439             :                                                                    it->val);
    1440             :                         }
    1441             :                 }
    1442             :         }
    1443           0 :         SCTP_INP_RUNLOCK(it->inp);
    1444             :  no_stcb:
    1445             :         /* done with all assocs on this endpoint, move on to next endpoint */
    1446           0 :         it->done_current_ep = 0;
    1447           0 :         if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) {
    1448           0 :                 it->inp = NULL;
    1449             :         } else {
    1450           0 :                 it->inp = LIST_NEXT(it->inp, sctp_list);
    1451             :         }
    1452           0 :         if (it->inp == NULL) {
    1453           0 :                 goto done_with_iterator;
    1454             :         }
    1455           0 :         goto select_a_new_ep;
    1456             : }
    1457             : 
    1458             : void
    1459           0 : sctp_iterator_worker(void)
    1460             : {
    1461             :         struct sctp_iterator *it, *nit;
    1462             : 
    1463             :         /* This function is called with the WQ lock in place */
    1464             : 
    1465           0 :         sctp_it_ctl.iterator_running = 1;
    1466           0 :         TAILQ_FOREACH_SAFE(it, &sctp_it_ctl.iteratorhead, sctp_nxt_itr, nit) {
    1467             :                 /* now lets work on this one */
    1468           0 :                 TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, it, sctp_nxt_itr);
    1469           0 :                 SCTP_IPI_ITERATOR_WQ_UNLOCK();
    1470             : #if defined(__FreeBSD__) && __FreeBSD_version >= 801000
    1471             :                 CURVNET_SET(it->vn);
    1472             : #endif
    1473           0 :                 sctp_iterator_work(it);
    1474             : #if defined(__FreeBSD__) && __FreeBSD_version >= 801000
    1475             :                 CURVNET_RESTORE();
    1476             : #endif
    1477           0 :                 SCTP_IPI_ITERATOR_WQ_LOCK();
    1478             : #if !defined(__FreeBSD__)
    1479           0 :                 if (sctp_it_ctl.iterator_flags & SCTP_ITERATOR_MUST_EXIT) {
    1480           0 :                         break;
    1481             :                 }
    1482             : #endif
    1483             :                 /*sa_ignore FREED_MEMORY*/
    1484             :         }
    1485           0 :         sctp_it_ctl.iterator_running = 0;
    1486           0 :         return;
    1487             : }
    1488             : 
    1489             : 
    1490             : static void
    1491           0 : sctp_handle_addr_wq(void)
    1492             : {
    1493             :         /* deal with the ADDR wq from the rtsock calls */
    1494             :         struct sctp_laddr *wi, *nwi;
    1495             :         struct sctp_asconf_iterator *asc;
    1496             : 
    1497           0 :         SCTP_MALLOC(asc, struct sctp_asconf_iterator *,
    1498             :                     sizeof(struct sctp_asconf_iterator), SCTP_M_ASC_IT);
    1499           0 :         if (asc == NULL) {
    1500             :                 /* Try later, no memory */
    1501           0 :                 sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ,
    1502             :                                  (struct sctp_inpcb *)NULL,
    1503             :                                  (struct sctp_tcb *)NULL,
    1504             :                                  (struct sctp_nets *)NULL);
    1505           0 :                 return;
    1506             :         }
    1507           0 :         LIST_INIT(&asc->list_of_work);
    1508           0 :         asc->cnt = 0;
    1509             : 
    1510           0 :         SCTP_WQ_ADDR_LOCK();
    1511           0 :         LIST_FOREACH_SAFE(wi, &SCTP_BASE_INFO(addr_wq), sctp_nxt_addr, nwi) {
    1512           0 :                 LIST_REMOVE(wi, sctp_nxt_addr);
    1513           0 :                 LIST_INSERT_HEAD(&asc->list_of_work, wi, sctp_nxt_addr);
    1514           0 :                 asc->cnt++;
    1515             :         }
    1516           0 :         SCTP_WQ_ADDR_UNLOCK();
    1517             : 
    1518           0 :         if (asc->cnt == 0) {
    1519           0 :                 SCTP_FREE(asc, SCTP_M_ASC_IT);
    1520             :         } else {
    1521           0 :                 (void)sctp_initiate_iterator(sctp_asconf_iterator_ep,
    1522             :                                              sctp_asconf_iterator_stcb,
    1523             :                                              NULL, /* No ep end for boundall */
    1524             :                                              SCTP_PCB_FLAGS_BOUNDALL,
    1525             :                                              SCTP_PCB_ANY_FEATURES,
    1526             :                                              SCTP_ASOC_ANY_STATE,
    1527             :                                              (void *)asc, 0,
    1528             :                                              sctp_asconf_iterator_end, NULL, 0);
    1529             :         }
    1530             : }
    1531             : 
    1532             : void
    1533           0 : sctp_timeout_handler(void *t)
    1534             : {
    1535             :         struct sctp_inpcb *inp;
    1536             :         struct sctp_tcb *stcb;
    1537             :         struct sctp_nets *net;
    1538             :         struct sctp_timer *tmr;
    1539             : #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
    1540             :         struct socket *so;
    1541             : #endif
    1542             :         int did_output, type;
    1543             : 
    1544           0 :         tmr = (struct sctp_timer *)t;
    1545           0 :         inp = (struct sctp_inpcb *)tmr->ep;
    1546           0 :         stcb = (struct sctp_tcb *)tmr->tcb;
    1547           0 :         net = (struct sctp_nets *)tmr->net;
    1548             : #if defined(__FreeBSD__) && __FreeBSD_version >= 801000
    1549             :         CURVNET_SET((struct vnet *)tmr->vnet);
    1550             : #endif
    1551           0 :         did_output = 1;
    1552             : 
    1553             : #ifdef SCTP_AUDITING_ENABLED
    1554             :         sctp_audit_log(0xF0, (uint8_t) tmr->type);
    1555             :         sctp_auditing(3, inp, stcb, net);
    1556             : #endif
    1557             : 
    1558             :         /* sanity checks... */
    1559           0 :         if (tmr->self != (void *)tmr) {
    1560             :                 /*
    1561             :                  * SCTP_PRINTF("Stale SCTP timer fired (%p), ignoring...\n",
    1562             :                  *             (void *)tmr);
    1563             :                  */
    1564             : #if defined(__FreeBSD__) && __FreeBSD_version >= 801000
    1565             :                 CURVNET_RESTORE();
    1566             : #endif
    1567           0 :                 return;
    1568             :         }
    1569           0 :         tmr->stopped_from = 0xa001;
    1570           0 :         if (!SCTP_IS_TIMER_TYPE_VALID(tmr->type)) {
    1571             :                 /*
    1572             :                  * SCTP_PRINTF("SCTP timer fired with invalid type: 0x%x\n",
    1573             :                  * tmr->type);
    1574             :                  */
    1575             : #if defined(__FreeBSD__) && __FreeBSD_version >= 801000
    1576             :                 CURVNET_RESTORE();
    1577             : #endif
    1578           0 :                 return;
    1579             :         }
    1580           0 :         tmr->stopped_from = 0xa002;
    1581           0 :         if ((tmr->type != SCTP_TIMER_TYPE_ADDR_WQ) && (inp == NULL)) {
    1582             : #if defined(__FreeBSD__) && __FreeBSD_version >= 801000
    1583             :                 CURVNET_RESTORE();
    1584             : #endif
    1585           0 :                 return;
    1586             :         }
    1587             :         /* if this is an iterator timeout, get the struct and clear inp */
    1588           0 :         tmr->stopped_from = 0xa003;
    1589           0 :         type = tmr->type;
    1590           0 :         if (inp) {
    1591           0 :                 SCTP_INP_INCR_REF(inp);
    1592           0 :                 if ((inp->sctp_socket == NULL) &&
    1593           0 :                     ((tmr->type != SCTP_TIMER_TYPE_INPKILL) &&
    1594           0 :                      (tmr->type != SCTP_TIMER_TYPE_INIT) &&
    1595           0 :                      (tmr->type != SCTP_TIMER_TYPE_SEND) &&
    1596           0 :                      (tmr->type != SCTP_TIMER_TYPE_RECV) &&
    1597           0 :                      (tmr->type != SCTP_TIMER_TYPE_HEARTBEAT) &&
    1598           0 :                      (tmr->type != SCTP_TIMER_TYPE_SHUTDOWN) &&
    1599           0 :                      (tmr->type != SCTP_TIMER_TYPE_SHUTDOWNACK) &&
    1600           0 :                      (tmr->type != SCTP_TIMER_TYPE_SHUTDOWNGUARD) &&
    1601           0 :                      (tmr->type != SCTP_TIMER_TYPE_ASOCKILL))
    1602             :                         ) {
    1603           0 :                         SCTP_INP_DECR_REF(inp);
    1604             : #if defined(__FreeBSD__) && __FreeBSD_version >= 801000
    1605             :                         CURVNET_RESTORE();
    1606             : #endif
    1607           0 :                         return;
    1608             :                 }
    1609             :         }
    1610           0 :         tmr->stopped_from = 0xa004;
    1611           0 :         if (stcb) {
    1612           0 :                 atomic_add_int(&stcb->asoc.refcnt, 1);
    1613           0 :                 if (stcb->asoc.state == 0) {
    1614           0 :                         atomic_add_int(&stcb->asoc.refcnt, -1);
    1615           0 :                         if (inp) {
    1616           0 :                                 SCTP_INP_DECR_REF(inp);
    1617             :                         }
    1618             : #if defined(__FreeBSD__) && __FreeBSD_version >= 801000
    1619             :                         CURVNET_RESTORE();
    1620             : #endif
    1621           0 :                         return;
    1622             :                 }
    1623             :         }
    1624           0 :         tmr->stopped_from = 0xa005;
    1625           0 :         SCTPDBG(SCTP_DEBUG_TIMER1, "Timer type %d goes off\n", tmr->type);
    1626           0 :         if (!SCTP_OS_TIMER_ACTIVE(&tmr->timer)) {
    1627           0 :                 if (inp) {
    1628           0 :                         SCTP_INP_DECR_REF(inp);
    1629             :                 }
    1630           0 :                 if (stcb) {
    1631           0 :                         atomic_add_int(&stcb->asoc.refcnt, -1);
    1632             :                 }
    1633             : #if defined(__FreeBSD__) && __FreeBSD_version >= 801000
    1634             :                 CURVNET_RESTORE();
    1635             : #endif
    1636           0 :                 return;
    1637             :         }
    1638           0 :         tmr->stopped_from = 0xa006;
    1639             : 
    1640           0 :         if (stcb) {
    1641           0 :                 SCTP_TCB_LOCK(stcb);
    1642           0 :                 atomic_add_int(&stcb->asoc.refcnt, -1);
    1643           0 :                 if ((tmr->type != SCTP_TIMER_TYPE_ASOCKILL) &&
    1644           0 :                     ((stcb->asoc.state == 0) ||
    1645           0 :                      (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED))) {
    1646           0 :                         SCTP_TCB_UNLOCK(stcb);
    1647           0 :                         if (inp) {
    1648           0 :                                 SCTP_INP_DECR_REF(inp);
    1649             :                         }
    1650             : #if defined(__FreeBSD__) && __FreeBSD_version >= 801000
    1651             :                         CURVNET_RESTORE();
    1652             : #endif
    1653           0 :                         return;
    1654             :                 }
    1655             :         }
    1656             :         /* record in stopped what t-o occured */
    1657           0 :         tmr->stopped_from = tmr->type;
    1658             : 
    1659             :         /* mark as being serviced now */
    1660           0 :         if (SCTP_OS_TIMER_PENDING(&tmr->timer)) {
    1661             :                 /*
    1662             :                  * Callout has been rescheduled.
    1663             :                  */
    1664           0 :                 goto get_out;
    1665             :         }
    1666           0 :         if (!SCTP_OS_TIMER_ACTIVE(&tmr->timer)) {
    1667             :                 /*
    1668             :                  * Not active, so no action.
    1669             :                  */
    1670           0 :                 goto get_out;
    1671             :         }
    1672           0 :         SCTP_OS_TIMER_DEACTIVATE(&tmr->timer);
    1673             : 
    1674             :         /* call the handler for the appropriate timer type */
    1675           0 :         switch (tmr->type) {
    1676             :         case SCTP_TIMER_TYPE_ZERO_COPY:
    1677           0 :                 if (inp == NULL) {
    1678           0 :                         break;
    1679             :                 }
    1680           0 :                 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) {
    1681             :                         SCTP_ZERO_COPY_EVENT(inp, inp->sctp_socket);
    1682             :                 }
    1683           0 :                 break;
    1684             :         case SCTP_TIMER_TYPE_ZCOPY_SENDQ:
    1685           0 :                 if (inp == NULL) {
    1686           0 :                         break;
    1687             :                 }
    1688           0 :                 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) {
    1689             :                     SCTP_ZERO_COPY_SENDQ_EVENT(inp, inp->sctp_socket);
    1690             :                 }
    1691           0 :                 break;
    1692             :         case SCTP_TIMER_TYPE_ADDR_WQ:
    1693           0 :                 sctp_handle_addr_wq();
    1694           0 :                 break;
    1695             :         case SCTP_TIMER_TYPE_SEND:
    1696           0 :                 if ((stcb == NULL) || (inp == NULL)) {
    1697             :                         break;
    1698             :                 }
    1699           0 :                 SCTP_STAT_INCR(sctps_timodata);
    1700           0 :                 stcb->asoc.timodata++;
    1701           0 :                 stcb->asoc.num_send_timers_up--;
    1702           0 :                 if (stcb->asoc.num_send_timers_up < 0) {
    1703           0 :                         stcb->asoc.num_send_timers_up = 0;
    1704             :                 }
    1705             :                 SCTP_TCB_LOCK_ASSERT(stcb);
    1706           0 :                 if (sctp_t3rxt_timer(inp, stcb, net)) {
    1707             :                         /* no need to unlock on tcb its gone */
    1708             : 
    1709           0 :                         goto out_decr;
    1710             :                 }
    1711             :                 SCTP_TCB_LOCK_ASSERT(stcb);
    1712             : #ifdef SCTP_AUDITING_ENABLED
    1713             :                 sctp_auditing(4, inp, stcb, net);
    1714             : #endif
    1715           0 :                 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED);
    1716           0 :                 if ((stcb->asoc.num_send_timers_up == 0) &&
    1717           0 :                     (stcb->asoc.sent_queue_cnt > 0)) {
    1718             :                         struct sctp_tmit_chunk *chk;
    1719             : 
    1720             :                         /*
    1721             :                          * safeguard. If there on some on the sent queue
    1722             :                          * somewhere but no timers running something is
    1723             :                          * wrong... so we start a timer on the first chunk
    1724             :                          * on the send queue on whatever net it is sent to.
    1725             :                          */
    1726           0 :                         chk = TAILQ_FIRST(&stcb->asoc.sent_queue);
    1727           0 :                         sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb,
    1728             :                             chk->whoTo);
    1729             :                 }
    1730           0 :                 break;
    1731             :         case SCTP_TIMER_TYPE_INIT:
    1732           0 :                 if ((stcb == NULL) || (inp == NULL)) {
    1733             :                         break;
    1734             :                 }
    1735           0 :                 SCTP_STAT_INCR(sctps_timoinit);
    1736           0 :                 stcb->asoc.timoinit++;
    1737           0 :                 if (sctp_t1init_timer(inp, stcb, net)) {
    1738             :                         /* no need to unlock on tcb its gone */
    1739           0 :                         goto out_decr;
    1740             :                 }
    1741             :                 /* We do output but not here */
    1742           0 :                 did_output = 0;
    1743           0 :                 break;
    1744             :         case SCTP_TIMER_TYPE_RECV:
    1745           0 :                 if ((stcb == NULL) || (inp == NULL)) {
    1746             :                         break;
    1747             :                 }
    1748           0 :                 SCTP_STAT_INCR(sctps_timosack);
    1749           0 :                 stcb->asoc.timosack++;
    1750           0 :                 sctp_send_sack(stcb, SCTP_SO_NOT_LOCKED);
    1751             : #ifdef SCTP_AUDITING_ENABLED
    1752             :                 sctp_auditing(4, inp, stcb, net);
    1753             : #endif
    1754           0 :                 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SACK_TMR, SCTP_SO_NOT_LOCKED);
    1755           0 :                 break;
    1756             :         case SCTP_TIMER_TYPE_SHUTDOWN:
    1757           0 :                 if ((stcb == NULL) || (inp == NULL)) {
    1758             :                         break;
    1759             :                 }
    1760           0 :                 if (sctp_shutdown_timer(inp, stcb, net)) {
    1761             :                         /* no need to unlock on tcb its gone */
    1762           0 :                         goto out_decr;
    1763             :                 }
    1764           0 :                 SCTP_STAT_INCR(sctps_timoshutdown);
    1765           0 :                 stcb->asoc.timoshutdown++;
    1766             : #ifdef SCTP_AUDITING_ENABLED
    1767             :                 sctp_auditing(4, inp, stcb, net);
    1768             : #endif
    1769           0 :                 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SHUT_TMR, SCTP_SO_NOT_LOCKED);
    1770           0 :                 break;
    1771             :         case SCTP_TIMER_TYPE_HEARTBEAT:
    1772           0 :                 if ((stcb == NULL) || (inp == NULL) || (net == NULL)) {
    1773             :                         break;
    1774             :                 }
    1775           0 :                 SCTP_STAT_INCR(sctps_timoheartbeat);
    1776           0 :                 stcb->asoc.timoheartbeat++;
    1777           0 :                 if (sctp_heartbeat_timer(inp, stcb, net)) {
    1778             :                         /* no need to unlock on tcb its gone */
    1779           0 :                         goto out_decr;
    1780             :                 }
    1781             : #ifdef SCTP_AUDITING_ENABLED
    1782             :                 sctp_auditing(4, inp, stcb, net);
    1783             : #endif
    1784           0 :                 if (!(net->dest_state & SCTP_ADDR_NOHB)) {
    1785           0 :                         sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
    1786           0 :                         sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_HB_TMR, SCTP_SO_NOT_LOCKED);
    1787             :                 }
    1788           0 :                 break;
    1789             :         case SCTP_TIMER_TYPE_COOKIE:
    1790           0 :                 if ((stcb == NULL) || (inp == NULL)) {
    1791             :                         break;
    1792             :                 }
    1793             : 
    1794           0 :                 if (sctp_cookie_timer(inp, stcb, net)) {
    1795             :                         /* no need to unlock on tcb its gone */
    1796           0 :                         goto out_decr;
    1797             :                 }
    1798           0 :                 SCTP_STAT_INCR(sctps_timocookie);
    1799           0 :                 stcb->asoc.timocookie++;
    1800             : #ifdef SCTP_AUDITING_ENABLED
    1801             :                 sctp_auditing(4, inp, stcb, net);
    1802             : #endif
    1803             :                 /*
    1804             :                  * We consider T3 and Cookie timer pretty much the same with
    1805             :                  * respect to where from in chunk_output.
    1806             :                  */
    1807           0 :                 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED);
    1808           0 :                 break;
    1809             :         case SCTP_TIMER_TYPE_NEWCOOKIE:
    1810             :                 {
    1811             :                         struct timeval tv;
    1812             :                         int i, secret;
    1813           0 :                         if (inp == NULL) {
    1814           0 :                                 break;
    1815             :                         }
    1816           0 :                         SCTP_STAT_INCR(sctps_timosecret);
    1817           0 :                         (void)SCTP_GETTIME_TIMEVAL(&tv);
    1818           0 :                         SCTP_INP_WLOCK(inp);
    1819           0 :                         inp->sctp_ep.time_of_secret_change = tv.tv_sec;
    1820           0 :                         inp->sctp_ep.last_secret_number =
    1821           0 :                             inp->sctp_ep.current_secret_number;
    1822           0 :                         inp->sctp_ep.current_secret_number++;
    1823           0 :                         if (inp->sctp_ep.current_secret_number >=
    1824             :                             SCTP_HOW_MANY_SECRETS) {
    1825           0 :                                 inp->sctp_ep.current_secret_number = 0;
    1826             :                         }
    1827           0 :                         secret = (int)inp->sctp_ep.current_secret_number;
    1828           0 :                         for (i = 0; i < SCTP_NUMBER_OF_SECRETS; i++) {
    1829           0 :                                 inp->sctp_ep.secret_key[secret][i] =
    1830           0 :                                     sctp_select_initial_TSN(&inp->sctp_ep);
    1831             :                         }
    1832           0 :                         SCTP_INP_WUNLOCK(inp);
    1833           0 :                         sctp_timer_start(SCTP_TIMER_TYPE_NEWCOOKIE, inp, stcb, net);
    1834             :                 }
    1835           0 :                 did_output = 0;
    1836           0 :                 break;
    1837             :         case SCTP_TIMER_TYPE_PATHMTURAISE:
    1838           0 :                 if ((stcb == NULL) || (inp == NULL)) {
    1839             :                         break;
    1840             :                 }
    1841           0 :                 SCTP_STAT_INCR(sctps_timopathmtu);
    1842           0 :                 sctp_pathmtu_timer(inp, stcb, net);
    1843           0 :                 did_output = 0;
    1844           0 :                 break;
    1845             :         case SCTP_TIMER_TYPE_SHUTDOWNACK:
    1846           0 :                 if ((stcb == NULL) || (inp == NULL)) {
    1847             :                         break;
    1848             :                 }
    1849           0 :                 if (sctp_shutdownack_timer(inp, stcb, net)) {
    1850             :                         /* no need to unlock on tcb its gone */
    1851           0 :                         goto out_decr;
    1852             :                 }
    1853           0 :                 SCTP_STAT_INCR(sctps_timoshutdownack);
    1854           0 :                 stcb->asoc.timoshutdownack++;
    1855             : #ifdef SCTP_AUDITING_ENABLED
    1856             :                 sctp_auditing(4, inp, stcb, net);
    1857             : #endif
    1858           0 :                 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SHUT_ACK_TMR, SCTP_SO_NOT_LOCKED);
    1859           0 :                 break;
    1860             :         case SCTP_TIMER_TYPE_SHUTDOWNGUARD:
    1861           0 :                 if ((stcb == NULL) || (inp == NULL)) {
    1862             :                         break;
    1863             :                 }
    1864           0 :                 SCTP_STAT_INCR(sctps_timoshutdownguard);
    1865           0 :                 sctp_abort_an_association(inp, stcb, NULL, SCTP_SO_NOT_LOCKED);
    1866             :                 /* no need to unlock on tcb its gone */
    1867           0 :                 goto out_decr;
    1868             : 
    1869             :         case SCTP_TIMER_TYPE_STRRESET:
    1870           0 :                 if ((stcb == NULL) || (inp == NULL)) {
    1871             :                         break;
    1872             :                 }
    1873           0 :                 if (sctp_strreset_timer(inp, stcb, net)) {
    1874             :                         /* no need to unlock on tcb its gone */
    1875           0 :                         goto out_decr;
    1876             :                 }
    1877           0 :                 SCTP_STAT_INCR(sctps_timostrmrst);
    1878           0 :                 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_TMR, SCTP_SO_NOT_LOCKED);
    1879           0 :                 break;
    1880             :         case SCTP_TIMER_TYPE_ASCONF:
    1881           0 :                 if ((stcb == NULL) || (inp == NULL)) {
    1882             :                         break;
    1883             :                 }
    1884           0 :                 if (sctp_asconf_timer(inp, stcb, net)) {
    1885             :                         /* no need to unlock on tcb its gone */
    1886           0 :                         goto out_decr;
    1887             :                 }
    1888           0 :                 SCTP_STAT_INCR(sctps_timoasconf);
    1889             : #ifdef SCTP_AUDITING_ENABLED
    1890             :                 sctp_auditing(4, inp, stcb, net);
    1891             : #endif
    1892           0 :                 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_ASCONF_TMR, SCTP_SO_NOT_LOCKED);
    1893           0 :                 break;
    1894             :         case SCTP_TIMER_TYPE_PRIM_DELETED:
    1895           0 :                 if ((stcb == NULL) || (inp == NULL)) {
    1896             :                         break;
    1897             :                 }
    1898           0 :                 sctp_delete_prim_timer(inp, stcb, net);
    1899           0 :                 SCTP_STAT_INCR(sctps_timodelprim);
    1900           0 :                 break;
    1901             : 
    1902             :         case SCTP_TIMER_TYPE_AUTOCLOSE:
    1903           0 :                 if ((stcb == NULL) || (inp == NULL)) {
    1904             :                         break;
    1905             :                 }
    1906           0 :                 SCTP_STAT_INCR(sctps_timoautoclose);
    1907           0 :                 sctp_autoclose_timer(inp, stcb, net);
    1908           0 :                 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_AUTOCLOSE_TMR, SCTP_SO_NOT_LOCKED);
    1909           0 :                 did_output = 0;
    1910           0 :                 break;
    1911             :         case SCTP_TIMER_TYPE_ASOCKILL:
    1912           0 :                 if ((stcb == NULL) || (inp == NULL)) {
    1913             :                         break;
    1914             :                 }
    1915           0 :                 SCTP_STAT_INCR(sctps_timoassockill);
    1916             :                 /* Can we free it yet? */
    1917           0 :                 SCTP_INP_DECR_REF(inp);
    1918           0 :                 sctp_timer_stop(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL, SCTP_FROM_SCTPUTIL+SCTP_LOC_1);
    1919             : #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
    1920             :                 so = SCTP_INP_SO(inp);
    1921             :                 atomic_add_int(&stcb->asoc.refcnt, 1);
    1922             :                 SCTP_TCB_UNLOCK(stcb);
    1923             :                 SCTP_SOCKET_LOCK(so, 1);
    1924             :                 SCTP_TCB_LOCK(stcb);
    1925             :                 atomic_subtract_int(&stcb->asoc.refcnt, 1);
    1926             : #endif
    1927           0 :                 (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL+SCTP_LOC_2);
    1928             : #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
    1929             :                 SCTP_SOCKET_UNLOCK(so, 1);
    1930             : #endif
    1931             :                 /*
    1932             :                  * free asoc, always unlocks (or destroy's) so prevent
    1933             :                  * duplicate unlock or unlock of a free mtx :-0
    1934             :                  */
    1935           0 :                 stcb = NULL;
    1936           0 :                 goto out_no_decr;
    1937             :         case SCTP_TIMER_TYPE_INPKILL:
    1938           0 :                 SCTP_STAT_INCR(sctps_timoinpkill);
    1939           0 :                 if (inp == NULL) {
    1940           0 :                         break;
    1941             :                 }
    1942             :                 /*
    1943             :                  * special case, take away our increment since WE are the
    1944             :                  * killer
    1945             :                  */
    1946           0 :                 SCTP_INP_DECR_REF(inp);
    1947           0 :                 sctp_timer_stop(SCTP_TIMER_TYPE_INPKILL, inp, NULL, NULL, SCTP_FROM_SCTPUTIL+SCTP_LOC_3);
    1948             : #if defined(__APPLE__)
    1949             :                 SCTP_SOCKET_LOCK(SCTP_INP_SO(inp), 1);
    1950             : #endif
    1951           0 :                 sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
    1952             :                                 SCTP_CALLED_FROM_INPKILL_TIMER);
    1953             : #if defined(__APPLE__)
    1954             :                 SCTP_SOCKET_UNLOCK(SCTP_INP_SO(inp), 1);
    1955             : #endif
    1956           0 :                 inp = NULL;
    1957           0 :                 goto out_no_decr;
    1958             :         default:
    1959           0 :                 SCTPDBG(SCTP_DEBUG_TIMER1, "sctp_timeout_handler:unknown timer %d\n",
    1960             :                         tmr->type);
    1961           0 :                 break;
    1962             :         }
    1963             : #ifdef SCTP_AUDITING_ENABLED
    1964             :         sctp_audit_log(0xF1, (uint8_t) tmr->type);
    1965             :         if (inp)
    1966             :                 sctp_auditing(5, inp, stcb, net);
    1967             : #endif
    1968           0 :         if ((did_output) && stcb) {
    1969             :                 /*
    1970             :                  * Now we need to clean up the control chunk chain if an
    1971             :                  * ECNE is on it. It must be marked as UNSENT again so next
    1972             :                  * call will continue to send it until such time that we get
    1973             :                  * a CWR, to remove it. It is, however, less likely that we
    1974             :                  * will find a ecn echo on the chain though.
    1975             :                  */
    1976           0 :                 sctp_fix_ecn_echo(&stcb->asoc);
    1977             :         }
    1978             : get_out:
    1979           0 :         if (stcb) {
    1980           0 :                 SCTP_TCB_UNLOCK(stcb);
    1981             :         }
    1982             : 
    1983             : out_decr:
    1984           0 :         if (inp) {
    1985           0 :                 SCTP_INP_DECR_REF(inp);
    1986             :         }
    1987             : 
    1988             : out_no_decr:
    1989           0 :         SCTPDBG(SCTP_DEBUG_TIMER1, "Timer now complete (type %d)\n",
    1990             :                           type);
    1991             : #if defined(__FreeBSD__) && __FreeBSD_version >= 801000
    1992             :         CURVNET_RESTORE();
    1993             : #endif
    1994             : }
    1995             : 
    1996             : void
    1997           0 : sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
    1998             :     struct sctp_nets *net)
    1999             : {
    2000             :         uint32_t to_ticks;
    2001             :         struct sctp_timer *tmr;
    2002             : 
    2003           0 :         if ((t_type != SCTP_TIMER_TYPE_ADDR_WQ) && (inp == NULL))
    2004           0 :                 return;
    2005             : 
    2006           0 :         tmr = NULL;
    2007             :         if (stcb) {
    2008             :                 SCTP_TCB_LOCK_ASSERT(stcb);
    2009             :         }
    2010           0 :         switch (t_type) {
    2011             :         case SCTP_TIMER_TYPE_ZERO_COPY:
    2012           0 :                 tmr = &inp->sctp_ep.zero_copy_timer;
    2013           0 :                 to_ticks = SCTP_ZERO_COPY_TICK_DELAY;
    2014           0 :                 break;
    2015             :         case SCTP_TIMER_TYPE_ZCOPY_SENDQ:
    2016           0 :                 tmr = &inp->sctp_ep.zero_copy_sendq_timer;
    2017           0 :                 to_ticks = SCTP_ZERO_COPY_SENDQ_TICK_DELAY;
    2018           0 :                 break;
    2019             :         case SCTP_TIMER_TYPE_ADDR_WQ:
    2020             :                 /* Only 1 tick away :-) */
    2021           0 :                 tmr = &SCTP_BASE_INFO(addr_wq_timer);
    2022           0 :                 to_ticks = SCTP_ADDRESS_TICK_DELAY;
    2023           0 :                 break;
    2024             :         case SCTP_TIMER_TYPE_SEND:
    2025             :                 /* Here we use the RTO timer */
    2026             :                 {
    2027             :                         int rto_val;
    2028             : 
    2029           0 :                         if ((stcb == NULL) || (net == NULL)) {
    2030           0 :                                 return;
    2031             :                         }
    2032           0 :                         tmr = &net->rxt_timer;
    2033           0 :                         if (net->RTO == 0) {
    2034           0 :                                 rto_val = stcb->asoc.initial_rto;
    2035             :                         } else {
    2036           0 :                                 rto_val = net->RTO;
    2037             :                         }
    2038           0 :                         to_ticks = MSEC_TO_TICKS(rto_val);
    2039             :                 }
    2040           0 :                 break;
    2041             :         case SCTP_TIMER_TYPE_INIT:
    2042             :                 /*
    2043             :                  * Here we use the INIT timer default usually about 1
    2044             :                  * minute.
    2045             :                  */
    2046           0 :                 if ((stcb == NULL) || (net == NULL)) {
    2047           0 :                         return;
    2048             :                 }
    2049           0 :                 tmr = &net->rxt_timer;
    2050           0 :                 if (net->RTO == 0) {
    2051           0 :                         to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
    2052             :                 } else {
    2053           0 :                         to_ticks = MSEC_TO_TICKS(net->RTO);
    2054             :                 }
    2055           0 :                 break;
    2056             :         case SCTP_TIMER_TYPE_RECV:
    2057             :                 /*
    2058             :                  * Here we use the Delayed-Ack timer value from the inp
    2059             :                  * ususually about 200ms.
    2060             :                  */
    2061           0 :                 if (stcb == NULL) {
    2062           0 :                         return;
    2063             :                 }
    2064           0 :                 tmr = &stcb->asoc.dack_timer;
    2065           0 :                 to_ticks = MSEC_TO_TICKS(stcb->asoc.delayed_ack);
    2066           0 :                 break;
    2067             :         case SCTP_TIMER_TYPE_SHUTDOWN:
    2068             :                 /* Here we use the RTO of the destination. */
    2069           0 :                 if ((stcb == NULL) || (net == NULL)) {
    2070           0 :                         return;
    2071             :                 }
    2072           0 :                 if (net->RTO == 0) {
    2073           0 :                         to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
    2074             :                 } else {
    2075           0 :                         to_ticks = MSEC_TO_TICKS(net->RTO);
    2076             :                 }
    2077           0 :                 tmr = &net->rxt_timer;
    2078           0 :                 break;
    2079             :         case SCTP_TIMER_TYPE_HEARTBEAT:
    2080             :                 /*
    2081             :                  * the net is used here so that we can add in the RTO. Even
    2082             :                  * though we use a different timer. We also add the HB timer
    2083             :                  * PLUS a random jitter.
    2084             :                  */
    2085           0 :                 if ((stcb == NULL) || (net == NULL)) {
    2086           0 :                         return;
    2087             :                 } else {
    2088             :                         uint32_t rndval;
    2089             :                         uint32_t jitter;
    2090             : 
    2091           0 :                         if ((net->dest_state & SCTP_ADDR_NOHB) &&
    2092           0 :                             !(net->dest_state & SCTP_ADDR_UNCONFIRMED)) {
    2093           0 :                                 return;
    2094             :                         }
    2095           0 :                         if (net->RTO == 0) {
    2096           0 :                                 to_ticks = stcb->asoc.initial_rto;
    2097             :                         } else {
    2098           0 :                                 to_ticks = net->RTO;
    2099             :                         }
    2100           0 :                         rndval = sctp_select_initial_TSN(&inp->sctp_ep);
    2101           0 :                         jitter = rndval % to_ticks;
    2102           0 :                         if (jitter >= (to_ticks >> 1)) {
    2103           0 :                                 to_ticks = to_ticks + (jitter - (to_ticks >> 1));
    2104             :                         } else {
    2105           0 :                                 to_ticks = to_ticks - jitter;
    2106             :                         }
    2107           0 :                         if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED) &&
    2108           0 :                             !(net->dest_state & SCTP_ADDR_PF)) {
    2109           0 :                                 to_ticks += net->heart_beat_delay;
    2110             :                         }
    2111             :                         /*
    2112             :                          * Now we must convert the to_ticks that are now in
    2113             :                          * ms to ticks.
    2114             :                          */
    2115           0 :                         to_ticks = MSEC_TO_TICKS(to_ticks);
    2116           0 :                         tmr = &net->hb_timer;
    2117             :                 }
    2118           0 :                 break;
    2119             :         case SCTP_TIMER_TYPE_COOKIE:
    2120             :                 /*
    2121             :                  * Here we can use the RTO timer from the network since one
    2122             :                  * RTT was compelete. If a retran happened then we will be
    2123             :                  * using the RTO initial value.
    2124             :                  */
    2125           0 :                 if ((stcb == NULL) || (net == NULL)) {
    2126           0 :                         return;
    2127             :                 }
    2128           0 :                 if (net->RTO == 0) {
    2129           0 :                         to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
    2130             :                 } else {
    2131           0 :                         to_ticks = MSEC_TO_TICKS(net->RTO);
    2132             :                 }
    2133           0 :                 tmr = &net->rxt_timer;
    2134           0 :                 break;
    2135             :         case SCTP_TIMER_TYPE_NEWCOOKIE:
    2136             :                 /*
    2137             :                  * nothing needed but the endpoint here ususually about 60
    2138             :                  * minutes.
    2139             :                  */
    2140           0 :                 tmr = &inp->sctp_ep.signature_change;
    2141           0 :                 to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_SIGNATURE];
    2142           0 :                 break;
    2143             :         case SCTP_TIMER_TYPE_ASOCKILL:
    2144           0 :                 if (stcb == NULL) {
    2145           0 :                         return;
    2146             :                 }
    2147           0 :                 tmr = &stcb->asoc.strreset_timer;
    2148           0 :                 to_ticks = MSEC_TO_TICKS(SCTP_ASOC_KILL_TIMEOUT);
    2149           0 :                 break;
    2150             :         case SCTP_TIMER_TYPE_INPKILL:
    2151             :                 /*
    2152             :                  * The inp is setup to die. We re-use the signature_chage
    2153             :                  * timer since that has stopped and we are in the GONE
    2154             :                  * state.
    2155             :                  */
    2156           0 :                 tmr = &inp->sctp_ep.signature_change;
    2157           0 :                 to_ticks = MSEC_TO_TICKS(SCTP_INP_KILL_TIMEOUT);
    2158           0 :                 break;
    2159             :         case SCTP_TIMER_TYPE_PATHMTURAISE:
    2160             :                 /*
    2161             :                  * Here we use the value found in the EP for PMTU ususually
    2162             :                  * about 10 minutes.
    2163             :                  */
    2164           0 :                 if ((stcb == NULL) || (net == NULL)) {
    2165           0 :                         return;
    2166             :                 }
    2167           0 :                 if (net->dest_state & SCTP_ADDR_NO_PMTUD) {
    2168           0 :                         return;
    2169             :                 }
    2170           0 :                 to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_PMTU];
    2171           0 :                 tmr = &net->pmtu_timer;
    2172           0 :                 break;
    2173             :         case SCTP_TIMER_TYPE_SHUTDOWNACK:
    2174             :                 /* Here we use the RTO of the destination */
    2175           0 :                 if ((stcb == NULL) || (net == NULL)) {
    2176           0 :                         return;
    2177             :                 }
    2178           0 :                 if (net->RTO == 0) {
    2179           0 :                         to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
    2180             :                 } else {
    2181           0 :                         to_ticks = MSEC_TO_TICKS(net->RTO);
    2182             :                 }
    2183           0 :                 tmr = &net->rxt_timer;
    2184           0 :                 break;
    2185             :         case SCTP_TIMER_TYPE_SHUTDOWNGUARD:
    2186             :                 /*
    2187             :                  * Here we use the endpoints shutdown guard timer usually
    2188             :                  * about 3 minutes.
    2189             :                  */
    2190           0 :                 if (stcb == NULL) {
    2191           0 :                         return;
    2192             :                 }
    2193           0 :                 to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_MAXSHUTDOWN];
    2194           0 :                 tmr = &stcb->asoc.shut_guard_timer;
    2195           0 :                 break;
    2196             :         case SCTP_TIMER_TYPE_STRRESET:
    2197             :                 /*
    2198             :                  * Here the timer comes from the stcb but its value is from
    2199             :                  * the net's RTO.
    2200             :                  */
    2201           0 :                 if ((stcb == NULL) || (net == NULL)) {
    2202           0 :                         return;
    2203             :                 }
    2204           0 :                 if (net->RTO == 0) {
    2205           0 :                         to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
    2206             :                 } else {
    2207           0 :                         to_ticks = MSEC_TO_TICKS(net->RTO);
    2208             :                 }
    2209           0 :                 tmr = &stcb->asoc.strreset_timer;
    2210           0 :                 break;
    2211             :         case SCTP_TIMER_TYPE_ASCONF:
    2212             :                 /*
    2213             :                  * Here the timer comes from the stcb but its value is from
    2214             :                  * the net's RTO.
    2215             :                  */
    2216           0 :                 if ((stcb == NULL) || (net == NULL)) {
    2217           0 :                         return;
    2218             :                 }
    2219           0 :                 if (net->RTO == 0) {
    2220           0 :                         to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
    2221             :                 } else {
    2222           0 :                         to_ticks = MSEC_TO_TICKS(net->RTO);
    2223             :                 }
    2224           0 :                 tmr = &stcb->asoc.asconf_timer;
    2225           0 :                 break;
    2226             :         case SCTP_TIMER_TYPE_PRIM_DELETED:
    2227           0 :                 if ((stcb == NULL) || (net != NULL)) {
    2228           0 :                         return;
    2229             :                 }
    2230           0 :                 to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
    2231           0 :                 tmr = &stcb->asoc.delete_prim_timer;
    2232           0 :                 break;
    2233             :         case SCTP_TIMER_TYPE_AUTOCLOSE:
    2234           0 :                 if (stcb == NULL) {
    2235           0 :                         return;
    2236             :                 }
    2237           0 :                 if (stcb->asoc.sctp_autoclose_ticks == 0) {
    2238             :                         /*
    2239             :                          * Really an error since stcb is NOT set to
    2240             :                          * autoclose
    2241             :                          */
    2242           0 :                         return;
    2243             :                 }
    2244           0 :                 to_ticks = stcb->asoc.sctp_autoclose_ticks;
    2245           0 :                 tmr = &stcb->asoc.autoclose_timer;
    2246           0 :                 break;
    2247             :         default:
    2248           0 :                 SCTPDBG(SCTP_DEBUG_TIMER1, "%s: Unknown timer type %d\n",
    2249             :                         __FUNCTION__, t_type);
    2250           0 :                 return;
    2251             :                 break;
    2252             :         }
    2253           0 :         if ((to_ticks <= 0) || (tmr == NULL)) {
    2254           0 :                 SCTPDBG(SCTP_DEBUG_TIMER1, "%s: %d:software error to_ticks:%d tmr:%p not set ??\n",
    2255             :                         __FUNCTION__, t_type, to_ticks, (void *)tmr);
    2256           0 :                 return;
    2257             :         }
    2258           0 :         if (SCTP_OS_TIMER_PENDING(&tmr->timer)) {
    2259             :                 /*
    2260             :                  * we do NOT allow you to have it already running. if it is
    2261             :                  * we leave the current one up unchanged
    2262             :                  */
    2263           0 :                 return;
    2264             :         }
    2265             :         /* At this point we can proceed */
    2266           0 :         if (t_type == SCTP_TIMER_TYPE_SEND) {
    2267           0 :                 stcb->asoc.num_send_timers_up++;
    2268             :         }
    2269           0 :         tmr->stopped_from = 0;
    2270           0 :         tmr->type = t_type;
    2271           0 :         tmr->ep = (void *)inp;
    2272           0 :         tmr->tcb = (void *)stcb;
    2273           0 :         tmr->net = (void *)net;
    2274           0 :         tmr->self = (void *)tmr;
    2275             : #if defined(__FreeBSD__) && __FreeBSD_version >= 800000
    2276             :         tmr->vnet = (void *)curvnet;
    2277             : #endif
    2278             : #ifndef __Panda__
    2279           0 :         tmr->ticks = sctp_get_tick_count();
    2280             : #endif
    2281           0 :         (void)SCTP_OS_TIMER_START(&tmr->timer, to_ticks, sctp_timeout_handler, tmr);
    2282           0 :         return;
    2283             : }
    2284             : 
    2285             : void
    2286           0 : sctp_timer_stop(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
    2287             :     struct sctp_nets *net, uint32_t from)
    2288             : {
    2289             :         struct sctp_timer *tmr;
    2290             : 
    2291           0 :         if ((t_type != SCTP_TIMER_TYPE_ADDR_WQ) &&
    2292             :             (inp == NULL))
    2293           0 :                 return;
    2294             : 
    2295           0 :         tmr = NULL;
    2296             :         if (stcb) {
    2297             :                 SCTP_TCB_LOCK_ASSERT(stcb);
    2298             :         }
    2299           0 :         switch (t_type) {
    2300             :         case SCTP_TIMER_TYPE_ZERO_COPY:
    2301           0 :                 tmr = &inp->sctp_ep.zero_copy_timer;
    2302           0 :                 break;
    2303             :         case SCTP_TIMER_TYPE_ZCOPY_SENDQ:
    2304           0 :                 tmr = &inp->sctp_ep.zero_copy_sendq_timer;
    2305           0 :                 break;
    2306             :         case SCTP_TIMER_TYPE_ADDR_WQ:
    2307           0 :                 tmr = &SCTP_BASE_INFO(addr_wq_timer);
    2308           0 :                 break;
    2309             :         case SCTP_TIMER_TYPE_SEND:
    2310           0 :                 if ((stcb == NULL) || (net == NULL)) {
    2311           0 :                         return;
    2312             :                 }
    2313           0 :                 tmr = &net->rxt_timer;
    2314           0 :                 break;
    2315             :         case SCTP_TIMER_TYPE_INIT:
    2316           0 :                 if ((stcb == NULL) || (net == NULL)) {
    2317           0 :                         return;
    2318             :                 }
    2319           0 :                 tmr = &net->rxt_timer;
    2320           0 :                 break;
    2321             :         case SCTP_TIMER_TYPE_RECV:
    2322           0 :                 if (stcb == NULL) {
    2323           0 :                         return;
    2324             :                 }
    2325           0 :                 tmr = &stcb->asoc.dack_timer;
    2326           0 :                 break;
    2327             :         case SCTP_TIMER_TYPE_SHUTDOWN:
    2328           0 :                 if ((stcb == NULL) || (net == NULL)) {
    2329           0 :                         return;
    2330             :                 }
    2331           0 :                 tmr = &net->rxt_timer;
    2332           0 :                 break;
    2333             :         case SCTP_TIMER_TYPE_HEARTBEAT:
    2334           0 :                 if ((stcb == NULL) || (net == NULL)) {
    2335           0 :                         return;
    2336             :                 }
    2337           0 :                 tmr = &net->hb_timer;
    2338           0 :                 break;
    2339             :         case SCTP_TIMER_TYPE_COOKIE:
    2340           0 :                 if ((stcb == NULL) || (net == NULL)) {
    2341           0 :                         return;
    2342             :                 }
    2343           0 :                 tmr = &net->rxt_timer;
    2344           0 :                 break;
    2345             :         case SCTP_TIMER_TYPE_NEWCOOKIE:
    2346             :                 /* nothing needed but the endpoint here */
    2347           0 :                 tmr = &inp->sctp_ep.signature_change;
    2348             :                 /*
    2349             :                  * We re-use the newcookie timer for the INP kill timer. We
    2350             :                  * must assure that we do not kill it by accident.
    2351             :                  */
    2352           0 :                 break;
    2353             :         case SCTP_TIMER_TYPE_ASOCKILL:
    2354             :                 /*
    2355             :                  * Stop the asoc kill timer.
    2356             :                  */
    2357           0 :                 if (stcb == NULL) {
    2358           0 :                         return;
    2359             :                 }
    2360           0 :                 tmr = &stcb->asoc.strreset_timer;
    2361           0 :                 break;
    2362             : 
    2363             :         case SCTP_TIMER_TYPE_INPKILL:
    2364             :                 /*
    2365             :                  * The inp is setup to die. We re-use the signature_chage
    2366             :                  * timer since that has stopped and we are in the GONE
    2367             :                  * state.
    2368             :                  */
    2369           0 :                 tmr = &inp->sctp_ep.signature_change;
    2370           0 :                 break;
    2371             :         case SCTP_TIMER_TYPE_PATHMTURAISE:
    2372           0 :                 if ((stcb == NULL) || (net == NULL)) {
    2373           0 :                         return;
    2374             :                 }
    2375           0 :                 tmr = &net->pmtu_timer;
    2376           0 :                 break;
    2377             :         case SCTP_TIMER_TYPE_SHUTDOWNACK:
    2378           0 :                 if ((stcb == NULL) || (net == NULL)) {
    2379           0 :                         return;
    2380             :                 }
    2381           0 :                 tmr = &net->rxt_timer;
    2382           0 :                 break;
    2383             :         case SCTP_TIMER_TYPE_SHUTDOWNGUARD:
    2384           0 :                 if (stcb == NULL) {
    2385           0 :                         return;
    2386             :                 }
    2387           0 :                 tmr = &stcb->asoc.shut_guard_timer;
    2388           0 :                 break;
    2389             :         case SCTP_TIMER_TYPE_STRRESET:
    2390           0 :                 if (stcb == NULL) {
    2391           0 :                         return;
    2392             :                 }
    2393           0 :                 tmr = &stcb->asoc.strreset_timer;
    2394           0 :                 break;
    2395             :         case SCTP_TIMER_TYPE_ASCONF:
    2396           0 :                 if (stcb == NULL) {
    2397           0 :                         return;
    2398             :                 }
    2399           0 :                 tmr = &stcb->asoc.asconf_timer;
    2400           0 :                 break;
    2401             :         case SCTP_TIMER_TYPE_PRIM_DELETED:
    2402           0 :                 if (stcb == NULL) {
    2403           0 :                         return;
    2404             :                 }
    2405           0 :                 tmr = &stcb->asoc.delete_prim_timer;
    2406           0 :                 break;
    2407             :         case SCTP_TIMER_TYPE_AUTOCLOSE:
    2408           0 :                 if (stcb == NULL) {
    2409           0 :                         return;
    2410             :                 }
    2411           0 :                 tmr = &stcb->asoc.autoclose_timer;
    2412           0 :                 break;
    2413             :         default:
    2414           0 :                 SCTPDBG(SCTP_DEBUG_TIMER1, "%s: Unknown timer type %d\n",
    2415             :                         __FUNCTION__, t_type);
    2416           0 :                 break;
    2417             :         }
    2418           0 :         if (tmr == NULL) {
    2419           0 :                 return;
    2420             :         }
    2421           0 :         if ((tmr->type != t_type) && tmr->type) {
    2422             :                 /*
    2423             :                  * Ok we have a timer that is under joint use. Cookie timer
    2424             :                  * per chance with the SEND timer. We therefore are NOT
    2425             :                  * running the timer that the caller wants stopped.  So just
    2426             :                  * return.
    2427             :                  */
    2428           0 :                 return;
    2429             :         }
    2430           0 :         if ((t_type == SCTP_TIMER_TYPE_SEND) && (stcb != NULL)) {
    2431           0 :                 stcb->asoc.num_send_timers_up--;
    2432           0 :                 if (stcb->asoc.num_send_timers_up < 0) {
    2433           0 :                         stcb->asoc.num_send_timers_up = 0;
    2434             :                 }
    2435             :         }
    2436           0 :         tmr->self = NULL;
    2437           0 :         tmr->stopped_from = from;
    2438           0 :         (void)SCTP_OS_TIMER_STOP(&tmr->timer);
    2439           0 :         return;
    2440             : }
    2441             : 
    2442             : uint32_t
    2443           0 : sctp_calculate_len(struct mbuf *m)
    2444             : {
    2445           0 :         uint32_t tlen = 0;
    2446             :         struct mbuf *at;
    2447             : 
    2448           0 :         at = m;
    2449           0 :         while (at) {
    2450           0 :                 tlen += SCTP_BUF_LEN(at);
    2451           0 :                 at = SCTP_BUF_NEXT(at);
    2452             :         }
    2453           0 :         return (tlen);
    2454             : }
    2455             : 
    2456             : void
    2457           0 : sctp_mtu_size_reset(struct sctp_inpcb *inp,
    2458             :     struct sctp_association *asoc, uint32_t mtu)
    2459             : {
    2460             :         /*
    2461             :          * Reset the P-MTU size on this association, this involves changing
    2462             :          * the asoc MTU, going through ANY chunk+overhead larger than mtu to
    2463             :          * allow the DF flag to be cleared.
    2464             :          */
    2465             :         struct sctp_tmit_chunk *chk;
    2466             :         unsigned int eff_mtu, ovh;
    2467             : 
    2468           0 :         asoc->smallest_mtu = mtu;
    2469           0 :         if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
    2470           0 :                 ovh = SCTP_MIN_OVERHEAD;
    2471             :         } else {
    2472           0 :                 ovh = SCTP_MIN_V4_OVERHEAD;
    2473             :         }
    2474           0 :         eff_mtu = mtu - ovh;
    2475           0 :         TAILQ_FOREACH(chk, &asoc->send_queue, sctp_next) {
    2476           0 :                 if (chk->send_size > eff_mtu) {
    2477           0 :                         chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
    2478             :                 }
    2479             :         }
    2480           0 :         TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) {
    2481           0 :                 if (chk->send_size > eff_mtu) {
    2482           0 :                         chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
    2483             :                 }
    2484             :         }
    2485           0 : }
    2486             : 
    2487             : 
    2488             : /*
    2489             :  * given an association and starting time of the current RTT period return
    2490             :  * RTO in number of msecs net should point to the current network
    2491             :  */
    2492             : 
    2493             : uint32_t
    2494           0 : sctp_calculate_rto(struct sctp_tcb *stcb,
    2495             :                    struct sctp_association *asoc,
    2496             :                    struct sctp_nets *net,
    2497             :                    struct timeval *told,
    2498             :                    int safe, int rtt_from_sack)
    2499             : {
    2500             :         /*-
    2501             :          * given an association and the starting time of the current RTT
    2502             :          * period (in value1/value2) return RTO in number of msecs.
    2503             :          */
    2504             :         int32_t rtt; /* RTT in ms */
    2505             :         uint32_t new_rto;
    2506           0 :         int first_measure = 0;
    2507             :         struct timeval now, then, *old;
    2508             : 
    2509             :         /* Copy it out for sparc64 */
    2510           0 :         if (safe == sctp_align_unsafe_makecopy) {
    2511           0 :                 old = &then;
    2512           0 :                 memcpy(&then, told, sizeof(struct timeval));
    2513           0 :         } else if (safe == sctp_align_safe_nocopy) {
    2514           0 :                 old = told;
    2515             :         } else {
    2516             :                 /* error */
    2517           0 :                 SCTP_PRINTF("Huh, bad rto calc call\n");
    2518           0 :                 return (0);
    2519             :         }
    2520             :         /************************/
    2521             :         /* 1. calculate new RTT */
    2522             :         /************************/
    2523             :         /* get the current time */
    2524           0 :         if (stcb->asoc.use_precise_time) {
    2525           0 :                 (void)SCTP_GETPTIME_TIMEVAL(&now);
    2526             :         } else {
    2527           0 :                 (void)SCTP_GETTIME_TIMEVAL(&now);
    2528             :         }
    2529           0 :         timevalsub(&now, old);
    2530             :         /* store the current RTT in us */
    2531           0 :         net->rtt = (uint64_t)1000000 * (uint64_t)now.tv_sec +
    2532           0 :                    (uint64_t)now.tv_usec;
    2533             :         /* compute rtt in ms */
    2534           0 :         rtt = (int32_t)(net->rtt / 1000);
    2535           0 :         if ((asoc->cc_functions.sctp_rtt_calculated) && (rtt_from_sack == SCTP_RTT_FROM_DATA)) {
    2536             :                 /* Tell the CC module that a new update has just occurred from a sack */
    2537           0 :                 (*asoc->cc_functions.sctp_rtt_calculated)(stcb, net, &now);
    2538             :         }
    2539             :         /* Do we need to determine the lan? We do this only
    2540             :          * on sacks i.e. RTT being determined from data not
    2541             :          * non-data (HB/INIT->INITACK).
    2542             :          */
    2543           0 :         if ((rtt_from_sack == SCTP_RTT_FROM_DATA) &&
    2544           0 :             (net->lan_type == SCTP_LAN_UNKNOWN)) {
    2545           0 :                 if (net->rtt > SCTP_LOCAL_LAN_RTT) {
    2546           0 :                         net->lan_type = SCTP_LAN_INTERNET;
    2547             :                 } else {
    2548           0 :                         net->lan_type = SCTP_LAN_LOCAL;
    2549             :                 }
    2550             :         }
    2551             : 
    2552             :         /***************************/
    2553             :         /* 2. update RTTVAR & SRTT */
    2554             :         /***************************/
    2555             :         /*-
    2556             :          * Compute the scaled average lastsa and the
    2557             :          * scaled variance lastsv as described in van Jacobson
    2558             :          * Paper "Congestion Avoidance and Control", Annex A.
    2559             :          *
    2560             :          * (net->lastsa >> SCTP_RTT_SHIFT) is the srtt
    2561             :          * (net->lastsa >> SCTP_RTT_VAR_SHIFT) is the rttvar
    2562             :          */
    2563           0 :         if (net->RTO_measured) {
    2564           0 :                 rtt -= (net->lastsa >> SCTP_RTT_SHIFT);
    2565           0 :                 net->lastsa += rtt;
    2566           0 :                 if (rtt < 0) {
    2567           0 :                         rtt = -rtt;
    2568             :                 }
    2569           0 :                 rtt -= (net->lastsv >> SCTP_RTT_VAR_SHIFT);
    2570           0 :                 net->lastsv += rtt;
    2571           0 :                 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_RTTVAR_LOGGING_ENABLE) {
    2572           0 :                         rto_logging(net, SCTP_LOG_RTTVAR);
    2573             :                 }
    2574             :         } else {
    2575             :                 /* First RTO measurment */
    2576           0 :                 net->RTO_measured = 1;
    2577           0 :                 first_measure = 1;
    2578           0 :                 net->lastsa = rtt << SCTP_RTT_SHIFT;
    2579           0 :                 net->lastsv = (rtt / 2) << SCTP_RTT_VAR_SHIFT;
    2580           0 :                 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_RTTVAR_LOGGING_ENABLE) {
    2581           0 :                         rto_logging(net, SCTP_LOG_INITIAL_RTT);
    2582             :                 }
    2583             :         }
    2584           0 :         if (net->lastsv == 0) {
    2585           0 :                 net->lastsv = SCTP_CLOCK_GRANULARITY;
    2586             :         }
    2587           0 :         new_rto = (net->lastsa >> SCTP_RTT_SHIFT) + net->lastsv;
    2588           0 :         if ((new_rto > SCTP_SAT_NETWORK_MIN) &&
    2589           0 :             (stcb->asoc.sat_network_lockout == 0)) {
    2590           0 :                 stcb->asoc.sat_network = 1;
    2591           0 :         } else if ((!first_measure) && stcb->asoc.sat_network) {
    2592           0 :                 stcb->asoc.sat_network = 0;
    2593           0 :                 stcb->asoc.sat_network_lockout = 1;
    2594             :         }
    2595             :         /* bound it, per C6/C7 in Section 5.3.1 */
    2596           0 :         if (new_rto < stcb->asoc.minrto) {
    2597           0 :                 new_rto = stcb->asoc.minrto;
    2598             :         }
    2599           0 :         if (new_rto > stcb->asoc.maxrto) {
    2600           0 :                 new_rto = stcb->asoc.maxrto;
    2601             :         }
    2602             :         /* we are now returning the RTO */
    2603           0 :         return (new_rto);
    2604             : }
    2605             : 
    2606             : /*
    2607             :  * return a pointer to a contiguous piece of data from the given mbuf chain
    2608             :  * starting at 'off' for 'len' bytes.  If the desired piece spans more than
    2609             :  * one mbuf, a copy is made at 'ptr'. caller must ensure that the buffer size
    2610             :  * is >= 'len' returns NULL if there there isn't 'len' bytes in the chain.
    2611             :  */
    2612             : caddr_t
    2613           0 : sctp_m_getptr(struct mbuf *m, int off, int len, uint8_t * in_ptr)
    2614             : {
    2615             :         uint32_t count;
    2616             :         uint8_t *ptr;
    2617             : 
    2618           0 :         ptr = in_ptr;
    2619           0 :         if ((off < 0) || (len <= 0))
    2620           0 :                 return (NULL);
    2621             : 
    2622             :         /* find the desired start location */
    2623           0 :         while ((m != NULL) && (off > 0)) {
    2624           0 :                 if (off < SCTP_BUF_LEN(m))
    2625           0 :                         break;
    2626           0 :                 off -= SCTP_BUF_LEN(m);
    2627           0 :                 m = SCTP_BUF_NEXT(m);
    2628             :         }
    2629           0 :         if (m == NULL)
    2630           0 :                 return (NULL);
    2631             : 
    2632             :         /* is the current mbuf large enough (eg. contiguous)? */
    2633           0 :         if ((SCTP_BUF_LEN(m) - off) >= len) {
    2634           0 :                 return (mtod(m, caddr_t) + off);
    2635             :         } else {
    2636             :                 /* else, it spans more than one mbuf, so save a temp copy... */
    2637           0 :                 while ((m != NULL) && (len > 0)) {
    2638           0 :                         count = min(SCTP_BUF_LEN(m) - off, len);
    2639           0 :                         bcopy(mtod(m, caddr_t) + off, ptr, count);
    2640           0 :                         len -= count;
    2641           0 :                         ptr += count;
    2642           0 :                         off = 0;
    2643           0 :                         m = SCTP_BUF_NEXT(m);
    2644             :                 }
    2645           0 :                 if ((m == NULL) && (len > 0))
    2646           0 :                         return (NULL);
    2647             :                 else
    2648           0 :                         return ((caddr_t)in_ptr);
    2649             :         }
    2650             : }
    2651             : 
    2652             : 
    2653             : 
    2654             : struct sctp_paramhdr *
    2655           0 : sctp_get_next_param(struct mbuf *m,
    2656             :     int offset,
    2657             :     struct sctp_paramhdr *pull,
    2658             :     int pull_limit)
    2659             : {
    2660             :         /* This just provides a typed signature to Peter's Pull routine */
    2661           0 :         return ((struct sctp_paramhdr *)sctp_m_getptr(m, offset, pull_limit,
    2662             :             (uint8_t *) pull));
    2663             : }
    2664             : 
    2665             : 
    2666             : struct mbuf *
    2667           0 : sctp_add_pad_tombuf(struct mbuf *m, int padlen)
    2668             : {
    2669             :         struct mbuf *m_last;
    2670             :         caddr_t dp;
    2671             : 
    2672           0 :         if (padlen > 3) {
    2673           0 :                 return (NULL);
    2674             :         }
    2675           0 :         if (padlen <= M_TRAILINGSPACE(m)) {
    2676             :                 /*
    2677             :                  * The easy way. We hope the majority of the time we hit
    2678             :                  * here :)
    2679             :                  */
    2680           0 :                 m_last = m;
    2681             :         } else {
    2682             :                 /* Hard way we must grow the mbuf chain */
    2683           0 :                 m_last = sctp_get_mbuf_for_msg(padlen, 0, M_NOWAIT, 1, MT_DATA);
    2684           0 :                 if (m_last == NULL) {
    2685           0 :                         return (NULL);
    2686             :                 }
    2687           0 :                 SCTP_BUF_LEN(m_last) = 0;
    2688           0 :                 SCTP_BUF_NEXT(m_last) = NULL;
    2689           0 :                 SCTP_BUF_NEXT(m) = m_last;
    2690             :         }
    2691           0 :         dp = mtod(m_last, caddr_t) + SCTP_BUF_LEN(m_last);
    2692           0 :         SCTP_BUF_LEN(m_last) += padlen;
    2693           0 :         memset(dp, 0, padlen);
    2694           0 :         return (m_last);
    2695             : }
    2696             : 
    2697             : struct mbuf *
    2698           0 : sctp_pad_lastmbuf(struct mbuf *m, int padval, struct mbuf *last_mbuf)
    2699             : {
    2700             :         /* find the last mbuf in chain and pad it */
    2701             :         struct mbuf *m_at;
    2702             : 
    2703           0 :         if (last_mbuf != NULL) {
    2704           0 :                 return (sctp_add_pad_tombuf(last_mbuf, padval));
    2705             :         } else {
    2706           0 :                 for (m_at = m; m_at; m_at = SCTP_BUF_NEXT(m_at)) {
    2707           0 :                         if (SCTP_BUF_NEXT(m_at) == NULL) {
    2708           0 :                                 return (sctp_add_pad_tombuf(m_at, padval));
    2709             :                         }
    2710             :                 }
    2711             :         }
    2712           0 :         return (NULL);
    2713             : }
    2714             : 
    2715             : static void
    2716           0 : sctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb,
    2717             :     uint16_t error, struct sctp_abort_chunk *abort, uint8_t from_peer, int so_locked
    2718             : #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
    2719             :     SCTP_UNUSED
    2720             : #endif
    2721             :     )
    2722             : {
    2723             :         struct mbuf *m_notify;
    2724             :         struct sctp_assoc_change *sac;
    2725             :         struct sctp_queued_to_read *control;
    2726             :         size_t notif_len, abort_len;
    2727             :         unsigned int i;
    2728             : #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
    2729             :         struct socket *so;
    2730             : #endif
    2731             : 
    2732           0 :         if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT)) {
    2733           0 :                 notif_len = sizeof(struct sctp_assoc_change);
    2734           0 :                 if (abort != NULL) {
    2735           0 :                         abort_len = ntohs(abort->ch.chunk_length);
    2736             :                 } else {
    2737           0 :                         abort_len = 0;
    2738             :                 }
    2739           0 :                 if ((state == SCTP_COMM_UP) || (state == SCTP_RESTART)) {
    2740           0 :                         notif_len += SCTP_ASSOC_SUPPORTS_MAX;
    2741           0 :                 } else if ((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC)) {
    2742           0 :                         notif_len += abort_len;
    2743             :                 }
    2744           0 :                 m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_NOWAIT, 1, MT_DATA);
    2745           0 :                 if (m_notify == NULL) {
    2746             :                         /* Retry with smaller value. */
    2747           0 :                         notif_len = sizeof(struct sctp_assoc_change);
    2748           0 :                         m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_NOWAIT, 1, MT_DATA);
    2749           0 :                         if (m_notify == NULL) {
    2750           0 :                                 goto set_error;
    2751             :                         }
    2752             :                 }
    2753           0 :                 SCTP_BUF_NEXT(m_notify) = NULL;
    2754           0 :                 sac = mtod(m_notify, struct sctp_assoc_change *);
    2755           0 :                 memset(sac, 0, notif_len);
    2756           0 :                 sac->sac_type = SCTP_ASSOC_CHANGE;
    2757           0 :                 sac->sac_flags = 0;
    2758           0 :                 sac->sac_length = sizeof(struct sctp_assoc_change);
    2759           0 :                 sac->sac_state = state;
    2760           0 :                 sac->sac_error = error;
    2761             :                 /* XXX verify these stream counts */
    2762           0 :                 sac->sac_outbound_streams = stcb->asoc.streamoutcnt;
    2763           0 :                 sac->sac_inbound_streams = stcb->asoc.streamincnt;
    2764           0 :                 sac->sac_assoc_id = sctp_get_associd(stcb);
    2765           0 :                 if (notif_len > sizeof(struct sctp_assoc_change)) {
    2766           0 :                         if ((state == SCTP_COMM_UP) || (state == SCTP_RESTART)) {
    2767           0 :                                 i = 0;
    2768           0 :                                 if (stcb->asoc.prsctp_supported == 1) {
    2769           0 :                                         sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_PR;
    2770             :                                 }
    2771           0 :                                 if (stcb->asoc.auth_supported == 1) {
    2772           0 :                                         sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_AUTH;
    2773             :                                 }
    2774           0 :                                 if (stcb->asoc.asconf_supported == 1) {
    2775           0 :                                         sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_ASCONF;
    2776             :                                 }
    2777           0 :                                 sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_MULTIBUF;
    2778           0 :                                 if (stcb->asoc.reconfig_supported == 1) {
    2779           0 :                                         sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_RE_CONFIG;
    2780             :                                 }
    2781           0 :                                 sac->sac_length += i;
    2782           0 :                         } else if ((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC)) {
    2783           0 :                                 memcpy(sac->sac_info, abort, abort_len);
    2784           0 :                                 sac->sac_length += abort_len;
    2785             :                         }
    2786             :                 }
    2787           0 :                 SCTP_BUF_LEN(m_notify) = sac->sac_length;
    2788           0 :                 control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
    2789             :                                                  0, 0, stcb->asoc.context, 0, 0, 0,
    2790             :                                                  m_notify);
    2791           0 :                 if (control != NULL) {
    2792           0 :                         control->length = SCTP_BUF_LEN(m_notify);
    2793             :                         /* not that we need this */
    2794           0 :                         control->tail_mbuf = m_notify;
    2795           0 :                         control->spec_flags = M_NOTIFICATION;
    2796           0 :                         sctp_add_to_readq(stcb->sctp_ep, stcb,
    2797             :                                           control,
    2798           0 :                                           &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD,
    2799             :                                           so_locked);
    2800             :                 } else {
    2801           0 :                         sctp_m_freem(m_notify);
    2802             :                 }
    2803             :         }
    2804             :         /*
    2805             :          * For 1-to-1 style sockets, we send up and error when an ABORT
    2806             :          * comes in.
    2807             :          */
    2808             : set_error:
    2809           0 :         if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
    2810           0 :              (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
    2811           0 :             ((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC))) {
    2812           0 :                 SOCK_LOCK(stcb->sctp_socket);
    2813           0 :                 if (from_peer) {
    2814           0 :                         if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) {
    2815             :                                 SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ECONNREFUSED);
    2816           0 :                                 stcb->sctp_socket->so_error = ECONNREFUSED;
    2817             :                         } else {
    2818             :                                 SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ECONNRESET);
    2819           0 :                                 stcb->sctp_socket->so_error = ECONNRESET;
    2820             :                         }
    2821             :                 } else {
    2822           0 :                         if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) ||
    2823           0 :                             (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED)) {
    2824             :                                 SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ETIMEDOUT);
    2825           0 :                                 stcb->sctp_socket->so_error = ETIMEDOUT;
    2826             :                         } else {
    2827             :                                 SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ECONNABORTED);
    2828           0 :                                 stcb->sctp_socket->so_error = ECONNABORTED;
    2829             :                         }
    2830             :                 }
    2831             :         }
    2832             :         /* Wake ANY sleepers */
    2833             : #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
    2834             :         so = SCTP_INP_SO(stcb->sctp_ep);
    2835             :         if (!so_locked) {
    2836             :                 atomic_add_int(&stcb->asoc.refcnt, 1);
    2837             :                 SCTP_TCB_UNLOCK(stcb);
    2838             :                 SCTP_SOCKET_LOCK(so, 1);
    2839             :                 SCTP_TCB_LOCK(stcb);
    2840             :                 atomic_subtract_int(&stcb->asoc.refcnt, 1);
    2841             :                 if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
    2842             :                         SCTP_SOCKET_UNLOCK(so, 1);
    2843             :                         return;
    2844             :                 }
    2845             :         }
    2846             : #endif
    2847           0 :         if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
    2848           0 :              (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
    2849           0 :             ((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC))) {
    2850             : #if defined(__APPLE__)
    2851             :                 socantrcvmore(stcb->sctp_socket);
    2852             : #else
    2853           0 :                 socantrcvmore_locked(stcb->sctp_socket);
    2854             : #endif
    2855             :         }
    2856           0 :         sorwakeup(stcb->sctp_socket);
    2857           0 :         sowwakeup(stcb->sctp_socket);
    2858             : #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
    2859             :         if (!so_locked) {
    2860             :                 SCTP_SOCKET_UNLOCK(so, 1);
    2861             :         }
    2862             : #endif
    2863           0 : }
    2864             : 
    2865             : static void
    2866           0 : sctp_notify_peer_addr_change(struct sctp_tcb *stcb, uint32_t state,
    2867             :     struct sockaddr *sa, uint32_t error, int so_locked
    2868             : #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
    2869             :     SCTP_UNUSED
    2870             : #endif
    2871             : )
    2872             : {
    2873             :         struct mbuf *m_notify;
    2874             :         struct sctp_paddr_change *spc;
    2875             :         struct sctp_queued_to_read *control;
    2876             : 
    2877           0 :         if ((stcb == NULL) ||
    2878           0 :             sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT)) {
    2879             :                 /* event not enabled */
    2880           0 :                 return;
    2881             :         }
    2882           0 :         m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_paddr_change), 0, M_NOWAIT, 1, MT_DATA);
    2883           0 :         if (m_notify == NULL)
    2884           0 :                 return;
    2885           0 :         SCTP_BUF_LEN(m_notify) = 0;
    2886           0 :         spc = mtod(m_notify, struct sctp_paddr_change *);
    2887           0 :         memset(spc, 0, sizeof(struct sctp_paddr_change));
    2888           0 :         spc->spc_type = SCTP_PEER_ADDR_CHANGE;
    2889           0 :         spc->spc_flags = 0;
    2890           0 :         spc->spc_length = sizeof(struct sctp_paddr_change);
    2891           0 :         switch (sa->sa_family) {
    2892             : #ifdef INET
    2893             :         case AF_INET:
    2894             : #ifdef INET6
    2895             :                 if (sctp_is_feature_on(stcb->sctp_ep, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
    2896             :                         in6_sin_2_v4mapsin6((struct sockaddr_in *)sa,
    2897             :                                             (struct sockaddr_in6 *)&spc->spc_aaddr);
    2898             :                 } else {
    2899             :                         memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in));
    2900             :                 }
    2901             : #else
    2902             :                 memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in));
    2903             : #endif
    2904             :                 break;
    2905             : #endif
    2906             : #ifdef INET6
    2907             :         case AF_INET6:
    2908             :         {
    2909             : #ifdef SCTP_EMBEDDED_V6_SCOPE
    2910             :                 struct sockaddr_in6 *sin6;
    2911             : #endif /* SCTP_EMBEDDED_V6_SCOPE */
    2912             :                 memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in6));
    2913             : 
    2914             : #ifdef SCTP_EMBEDDED_V6_SCOPE
    2915             :                 sin6 = (struct sockaddr_in6 *)&spc->spc_aaddr;
    2916             :                 if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) {
    2917             :                         if (sin6->sin6_scope_id == 0) {
    2918             :                                 /* recover scope_id for user */
    2919             : #ifdef SCTP_KAME
    2920             :                                 (void)sa6_recoverscope(sin6);
    2921             : #else
    2922             :                                 (void)in6_recoverscope(sin6, &sin6->sin6_addr,
    2923             :                                                        NULL);
    2924             : #endif
    2925             :                         } else {
    2926             :                                 /* clear embedded scope_id for user */
    2927             :                                 in6_clearscope(&sin6->sin6_addr);
    2928             :                         }
    2929             :                 }
    2930             : #endif /* SCTP_EMBEDDED_V6_SCOPE */
    2931             :                 break;
    2932             :         }
    2933             : #endif
    2934             : #if defined(__Userspace__)
    2935             :         case AF_CONN:
    2936           0 :                 memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_conn));
    2937           0 :                 break;
    2938             : #endif
    2939             :         default:
    2940             :                 /* TSNH */
    2941           0 :                 break;
    2942             :         }
    2943           0 :         spc->spc_state = state;
    2944           0 :         spc->spc_error = error;
    2945           0 :         spc->spc_assoc_id = sctp_get_associd(stcb);
    2946             : 
    2947           0 :         SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_paddr_change);
    2948           0 :         SCTP_BUF_NEXT(m_notify) = NULL;
    2949             : 
    2950             :         /* append to socket */
    2951           0 :         control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
    2952             :                                          0, 0, stcb->asoc.context, 0, 0, 0,
    2953             :                                          m_notify);
    2954           0 :         if (control == NULL) {
    2955             :                 /* no memory */
    2956           0 :                 sctp_m_freem(m_notify);
    2957           0 :                 return;
    2958             :         }
    2959           0 :         control->length = SCTP_BUF_LEN(m_notify);
    2960           0 :         control->spec_flags = M_NOTIFICATION;
    2961             :         /* not that we need this */
    2962           0 :         control->tail_mbuf = m_notify;
    2963           0 :         sctp_add_to_readq(stcb->sctp_ep, stcb,
    2964             :                           control,
    2965           0 :                           &stcb->sctp_socket->so_rcv, 1,
    2966             :                           SCTP_READ_LOCK_NOT_HELD,
    2967             :                           so_locked);
    2968             : }
    2969             : 
    2970             : 
    2971             : static void
    2972           0 : sctp_notify_send_failed(struct sctp_tcb *stcb, uint8_t sent, uint32_t error,
    2973             :     struct sctp_tmit_chunk *chk, int so_locked
    2974             : #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
    2975             :     SCTP_UNUSED
    2976             : #endif
    2977             :     )
    2978             : {
    2979             :         struct mbuf *m_notify;
    2980             :         struct sctp_send_failed *ssf;
    2981             :         struct sctp_send_failed_event *ssfe;
    2982             :         struct sctp_queued_to_read *control;
    2983             :         int length;
    2984             : 
    2985           0 :         if ((stcb == NULL) ||
    2986           0 :             (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT) &&
    2987           0 :              sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT))) {
    2988             :                 /* event not enabled */
    2989           0 :                 return;
    2990             :         }
    2991             : 
    2992           0 :         if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) {
    2993           0 :                 length = sizeof(struct sctp_send_failed_event);
    2994             :         } else {
    2995           0 :                 length = sizeof(struct sctp_send_failed);
    2996             :         }
    2997           0 :         m_notify = sctp_get_mbuf_for_msg(length, 0, M_NOWAIT, 1, MT_DATA);
    2998           0 :         if (m_notify == NULL)
    2999             :                 /* no space left */
    3000           0 :                 return;
    3001           0 :         SCTP_BUF_LEN(m_notify) = 0;
    3002           0 :         if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) {
    3003           0 :                 ssfe = mtod(m_notify, struct sctp_send_failed_event *);
    3004           0 :                 memset(ssfe, 0, length);
    3005           0 :                 ssfe->ssfe_type = SCTP_SEND_FAILED_EVENT;
    3006           0 :                 if (sent) {
    3007           0 :                         ssfe->ssfe_flags = SCTP_DATA_SENT;
    3008             :                 } else {
    3009           0 :                         ssfe->ssfe_flags = SCTP_DATA_UNSENT;
    3010             :                 }
    3011           0 :                 length += chk->send_size;
    3012           0 :                 length -= sizeof(struct sctp_data_chunk);
    3013           0 :                 ssfe->ssfe_length = length;
    3014           0 :                 ssfe->ssfe_error = error;
    3015             :                 /* not exactly what the user sent in, but should be close :) */
    3016           0 :                 ssfe->ssfe_info.snd_sid = chk->rec.data.stream_number;
    3017           0 :                 ssfe->ssfe_info.snd_flags = chk->rec.data.rcv_flags;
    3018           0 :                 ssfe->ssfe_info.snd_ppid = chk->rec.data.payloadtype;
    3019           0 :                 ssfe->ssfe_info.snd_context = chk->rec.data.context;
    3020           0 :                 ssfe->ssfe_info.snd_assoc_id = sctp_get_associd(stcb);
    3021           0 :                 ssfe->ssfe_assoc_id = sctp_get_associd(stcb);
    3022           0 :                 SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed_event);
    3023             :         } else {
    3024           0 :                 ssf = mtod(m_notify, struct sctp_send_failed *);
    3025           0 :                 memset(ssf, 0, length);
    3026           0 :                 ssf->ssf_type = SCTP_SEND_FAILED;
    3027           0 :                 if (sent) {
    3028           0 :                         ssf->ssf_flags = SCTP_DATA_SENT;
    3029             :                 } else {
    3030           0 :                         ssf->ssf_flags = SCTP_DATA_UNSENT;
    3031             :                 }
    3032           0 :                 length += chk->send_size;
    3033           0 :                 length -= sizeof(struct sctp_data_chunk);
    3034           0 :                 ssf->ssf_length = length;
    3035           0 :                 ssf->ssf_error = error;
    3036             :                 /* not exactly what the user sent in, but should be close :) */
    3037           0 :                 bzero(&ssf->ssf_info, sizeof(ssf->ssf_info));
    3038           0 :                 ssf->ssf_info.sinfo_stream = chk->rec.data.stream_number;
    3039           0 :                 ssf->ssf_info.sinfo_ssn = chk->rec.data.stream_seq;
    3040           0 :                 ssf->ssf_info.sinfo_flags = chk->rec.data.rcv_flags;
    3041           0 :                 ssf->ssf_info.sinfo_ppid = chk->rec.data.payloadtype;
    3042           0 :                 ssf->ssf_info.sinfo_context = chk->rec.data.context;
    3043           0 :                 ssf->ssf_info.sinfo_assoc_id = sctp_get_associd(stcb);
    3044           0 :                 ssf->ssf_assoc_id = sctp_get_associd(stcb);
    3045           0 :                 SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed);
    3046             :         }
    3047           0 :         if (chk->data) {
    3048             :                 /*
    3049             :                  * trim off the sctp chunk header(it should
    3050             :                  * be there)
    3051             :                  */
    3052           0 :                 if (chk->send_size >= sizeof(struct sctp_data_chunk)) {
    3053           0 :                         m_adj(chk->data, sizeof(struct sctp_data_chunk));
    3054           0 :                         sctp_mbuf_crush(chk->data);
    3055           0 :                         chk->send_size -= sizeof(struct sctp_data_chunk);
    3056             :                 }
    3057             :         }
    3058           0 :         SCTP_BUF_NEXT(m_notify) = chk->data;
    3059             :         /* Steal off the mbuf */
    3060           0 :         chk->data = NULL;
    3061             :         /*
    3062             :          * For this case, we check the actual socket buffer, since the assoc
    3063             :          * is going away we don't want to overfill the socket buffer for a
    3064             :          * non-reader
    3065             :          */
    3066           0 :         if (sctp_sbspace_failedmsgs(&stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) {
    3067           0 :                 sctp_m_freem(m_notify);
    3068           0 :                 return;
    3069             :         }
    3070             :         /* append to socket */
    3071           0 :         control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
    3072             :                                          0, 0, stcb->asoc.context, 0, 0, 0,
    3073             :                                          m_notify);
    3074           0 :         if (control == NULL) {
    3075             :                 /* no memory */
    3076           0 :                 sctp_m_freem(m_notify);
    3077           0 :                 return;
    3078             :         }
    3079           0 :         control->spec_flags = M_NOTIFICATION;
    3080           0 :         sctp_add_to_readq(stcb->sctp_ep, stcb,
    3081             :                           control,
    3082           0 :                           &stcb->sctp_socket->so_rcv, 1,
    3083             :                           SCTP_READ_LOCK_NOT_HELD,
    3084             :                           so_locked);
    3085             : }
    3086             : 
    3087             : 
    3088             : static void
    3089           0 : sctp_notify_send_failed2(struct sctp_tcb *stcb, uint32_t error,
    3090             :                          struct sctp_stream_queue_pending *sp, int so_locked
    3091             : #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
    3092             :                          SCTP_UNUSED
    3093             : #endif
    3094             :                          )
    3095             : {
    3096             :         struct mbuf *m_notify;
    3097             :         struct sctp_send_failed *ssf;
    3098             :         struct sctp_send_failed_event *ssfe;
    3099             :         struct sctp_queued_to_read *control;
    3100             :         int length;
    3101             : 
    3102           0 :         if ((stcb == NULL) ||
    3103           0 :             (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT) &&
    3104           0 :              sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT))) {
    3105             :                 /* event not enabled */
    3106           0 :                 return;
    3107             :         }
    3108           0 :         if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) {
    3109           0 :                 length = sizeof(struct sctp_send_failed_event);
    3110             :         } else {
    3111           0 :                 length = sizeof(struct sctp_send_failed);
    3112             :         }
    3113           0 :         m_notify = sctp_get_mbuf_for_msg(length, 0, M_NOWAIT, 1, MT_DATA);
    3114           0 :         if (m_notify == NULL) {
    3115             :                 /* no space left */
    3116           0 :                 return;
    3117             :         }
    3118           0 :         SCTP_BUF_LEN(m_notify) = 0;
    3119           0 :         if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) {
    3120           0 :                 ssfe = mtod(m_notify, struct sctp_send_failed_event *);
    3121           0 :                 memset(ssfe, 0, length);
    3122           0 :                 ssfe->ssfe_type = SCTP_SEND_FAILED_EVENT;
    3123           0 :                 ssfe->ssfe_flags = SCTP_DATA_UNSENT;
    3124           0 :                 length += sp->length;
    3125           0 :                 ssfe->ssfe_length = length;
    3126           0 :                 ssfe->ssfe_error = error;
    3127             :                 /* not exactly what the user sent in, but should be close :) */
    3128           0 :                 ssfe->ssfe_info.snd_sid = sp->stream;
    3129           0 :                 if (sp->some_taken) {
    3130           0 :                         ssfe->ssfe_info.snd_flags = SCTP_DATA_LAST_FRAG;
    3131             :                 } else {
    3132           0 :                         ssfe->ssfe_info.snd_flags = SCTP_DATA_NOT_FRAG;
    3133             :                 }
    3134           0 :                 ssfe->ssfe_info.snd_ppid = sp->ppid;
    3135           0 :                 ssfe->ssfe_info.snd_context = sp->context;
    3136           0 :                 ssfe->ssfe_info.snd_assoc_id = sctp_get_associd(stcb);
    3137           0 :                 ssfe->ssfe_assoc_id = sctp_get_associd(stcb);
    3138           0 :                 SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed_event);
    3139             :         } else {
    3140           0 :                 ssf = mtod(m_notify, struct sctp_send_failed *);
    3141           0 :                 memset(ssf, 0, length);
    3142           0 :                 ssf->ssf_type = SCTP_SEND_FAILED;
    3143           0 :                 ssf->ssf_flags = SCTP_DATA_UNSENT;
    3144           0 :                 length += sp->length;
    3145           0 :                 ssf->ssf_length = length;
    3146           0 :                 ssf->ssf_error = error;
    3147             :                 /* not exactly what the user sent in, but should be close :) */
    3148           0 :                 ssf->ssf_info.sinfo_stream = sp->stream;
    3149           0 :                 ssf->ssf_info.sinfo_ssn = 0;
    3150           0 :                 if (sp->some_taken) {
    3151           0 :                         ssf->ssf_info.sinfo_flags = SCTP_DATA_LAST_FRAG;
    3152             :                 } else {
    3153           0 :                         ssf->ssf_info.sinfo_flags = SCTP_DATA_NOT_FRAG;
    3154             :                 }
    3155           0 :                 ssf->ssf_info.sinfo_ppid = sp->ppid;
    3156           0 :                 ssf->ssf_info.sinfo_context = sp->context;
    3157           0 :                 ssf->ssf_info.sinfo_assoc_id = sctp_get_associd(stcb);
    3158           0 :                 ssf->ssf_assoc_id = sctp_get_associd(stcb);
    3159           0 :                 SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed);
    3160             :         }
    3161           0 :         SCTP_BUF_NEXT(m_notify) = sp->data;
    3162             : 
    3163             :         /* Steal off the mbuf */
    3164           0 :         sp->data = NULL;
    3165             :         /*
    3166             :          * For this case, we check the actual socket buffer, since the assoc
    3167             :          * is going away we don't want to overfill the socket buffer for a
    3168             :          * non-reader
    3169             :          */
    3170           0 :         if (sctp_sbspace_failedmsgs(&stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) {
    3171           0 :                 sctp_m_freem(m_notify);
    3172           0 :                 return;
    3173             :         }
    3174             :         /* append to socket */
    3175           0 :         control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
    3176             :                                          0, 0, stcb->asoc.context, 0, 0, 0,
    3177             :                                          m_notify);
    3178           0 :         if (control == NULL) {
    3179             :                 /* no memory */
    3180           0 :                 sctp_m_freem(m_notify);
    3181           0 :                 return;
    3182             :         }
    3183           0 :         control->spec_flags = M_NOTIFICATION;
    3184           0 :         sctp_add_to_readq(stcb->sctp_ep, stcb,
    3185             :             control,
    3186           0 :             &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, so_locked);
    3187             : }
    3188             : 
    3189             : 
    3190             : 
    3191             : static void
    3192           0 : sctp_notify_adaptation_layer(struct sctp_tcb *stcb)
    3193             : {
    3194             :         struct mbuf *m_notify;
    3195             :         struct sctp_adaptation_event *sai;
    3196             :         struct sctp_queued_to_read *control;
    3197             : 
    3198           0 :         if ((stcb == NULL) ||
    3199           0 :             sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT)) {
    3200             :                 /* event not enabled */
    3201           0 :                 return;
    3202             :         }
    3203             : 
    3204           0 :         m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_adaption_event), 0, M_NOWAIT, 1, MT_DATA);
    3205           0 :         if (m_notify == NULL)
    3206             :                 /* no space left */
    3207           0 :                 return;
    3208           0 :         SCTP_BUF_LEN(m_notify) = 0;
    3209           0 :         sai = mtod(m_notify, struct sctp_adaptation_event *);
    3210           0 :         memset(sai, 0, sizeof(struct sctp_adaptation_event));
    3211           0 :         sai->sai_type = SCTP_ADAPTATION_INDICATION;
    3212           0 :         sai->sai_flags = 0;
    3213           0 :         sai->sai_length = sizeof(struct sctp_adaptation_event);
    3214           0 :         sai->sai_adaptation_ind = stcb->asoc.peers_adaptation;
    3215           0 :         sai->sai_assoc_id = sctp_get_associd(stcb);
    3216             : 
    3217           0 :         SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_adaptation_event);
    3218           0 :         SCTP_BUF_NEXT(m_notify) = NULL;
    3219             : 
    3220             :         /* append to socket */
    3221           0 :         control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
    3222             :                                          0, 0, stcb->asoc.context, 0, 0, 0,
    3223             :                                          m_notify);
    3224           0 :         if (control == NULL) {
    3225             :                 /* no memory */
    3226           0 :                 sctp_m_freem(m_notify);
    3227           0 :                 return;
    3228             :         }
    3229           0 :         control->length = SCTP_BUF_LEN(m_notify);
    3230           0 :         control->spec_flags = M_NOTIFICATION;
    3231             :         /* not that we need this */
    3232           0 :         control->tail_mbuf = m_notify;
    3233           0 :         sctp_add_to_readq(stcb->sctp_ep, stcb,
    3234             :             control,
    3235           0 :             &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
    3236             : }
    3237             : 
    3238             : /* This always must be called with the read-queue LOCKED in the INP */
    3239             : static void
    3240           0 : sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb, uint32_t error,
    3241             :                                         uint32_t val, int so_locked
    3242             : #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
    3243             :                              SCTP_UNUSED
    3244             : #endif
    3245             :                                         )
    3246             : {
    3247             :         struct mbuf *m_notify;
    3248             :         struct sctp_pdapi_event *pdapi;
    3249             :         struct sctp_queued_to_read *control;
    3250             :         struct sockbuf *sb;
    3251             : 
    3252           0 :         if ((stcb == NULL) ||
    3253           0 :             sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_PDAPIEVNT)) {
    3254             :                 /* event not enabled */
    3255           0 :                 return;
    3256             :         }
    3257           0 :         if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_CANT_READ) {
    3258           0 :                 return;
    3259             :         }
    3260             : 
    3261           0 :         m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_pdapi_event), 0, M_NOWAIT, 1, MT_DATA);
    3262           0 :         if (m_notify == NULL)
    3263             :                 /* no space left */
    3264           0 :                 return;
    3265           0 :         SCTP_BUF_LEN(m_notify) = 0;
    3266           0 :         pdapi = mtod(m_notify, struct sctp_pdapi_event *);
    3267           0 :         memset(pdapi, 0, sizeof(struct sctp_pdapi_event));
    3268           0 :         pdapi->pdapi_type = SCTP_PARTIAL_DELIVERY_EVENT;
    3269           0 :         pdapi->pdapi_flags = 0;
    3270           0 :         pdapi->pdapi_length = sizeof(struct sctp_pdapi_event);
    3271           0 :         pdapi->pdapi_indication = error;
    3272           0 :         pdapi->pdapi_stream = (val >> 16);
    3273           0 :         pdapi->pdapi_seq = (val & 0x0000ffff);
    3274           0 :         pdapi->pdapi_assoc_id = sctp_get_associd(stcb);
    3275             : 
    3276           0 :         SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_pdapi_event);
    3277           0 :         SCTP_BUF_NEXT(m_notify) = NULL;
    3278           0 :         control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
    3279             :                                          0, 0, stcb->asoc.context, 0, 0, 0,
    3280             :                                          m_notify);
    3281           0 :         if (control == NULL) {
    3282             :                 /* no memory */
    3283           0 :                 sctp_m_freem(m_notify);
    3284           0 :                 return;
    3285             :         }
    3286           0 :         control->spec_flags = M_NOTIFICATION;
    3287           0 :         control->length = SCTP_BUF_LEN(m_notify);
    3288             :         /* not that we need this */
    3289           0 :         control->tail_mbuf = m_notify;
    3290           0 :         control->held_length = 0;
    3291           0 :         control->length = 0;
    3292           0 :         sb = &stcb->sctp_socket->so_rcv;
    3293           0 :         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
    3294           0 :                 sctp_sblog(sb, control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBALLOC, SCTP_BUF_LEN(m_notify));
    3295             :         }
    3296           0 :         sctp_sballoc(stcb, sb, m_notify);
    3297           0 :         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
    3298           0 :                 sctp_sblog(sb, control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBRESULT, 0);
    3299             :         }
    3300           0 :         atomic_add_int(&control->length, SCTP_BUF_LEN(m_notify));
    3301           0 :         control->end_added = 1;
    3302           0 :         if (stcb->asoc.control_pdapi)
    3303           0 :                 TAILQ_INSERT_AFTER(&stcb->sctp_ep->read_queue, stcb->asoc.control_pdapi,  control, next);
    3304             :         else {
    3305             :                 /* we really should not see this case */
    3306           0 :                 TAILQ_INSERT_TAIL(&stcb->sctp_ep->read_queue, control, next);
    3307             :         }
    3308           0 :         if (stcb->sctp_ep && stcb->sctp_socket) {
    3309             :                 /* This should always be the case */
    3310             : #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
    3311             :                 struct socket *so;
    3312             : 
    3313             :                 so = SCTP_INP_SO(stcb->sctp_ep);
    3314             :                 if (!so_locked) {
    3315             :                         atomic_add_int(&stcb->asoc.refcnt, 1);
    3316             :                         SCTP_TCB_UNLOCK(stcb);
    3317             :                         SCTP_SOCKET_LOCK(so, 1);
    3318             :                         SCTP_TCB_LOCK(stcb);
    3319             :                         atomic_subtract_int(&stcb->asoc.refcnt, 1);
    3320             :                         if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
    3321             :                                 SCTP_SOCKET_UNLOCK(so, 1);
    3322             :                                 return;
    3323             :                         }
    3324             :                 }
    3325             : #endif
    3326           0 :                 sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
    3327             : #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
    3328             :                 if (!so_locked) {
    3329             :                         SCTP_SOCKET_UNLOCK(so, 1);
    3330             :                 }
    3331             : #endif
    3332             :         }
    3333             : }
    3334             : 
    3335             : static void
    3336           0 : sctp_notify_shutdown_event(struct sctp_tcb *stcb)
    3337             : {
    3338             :         struct mbuf *m_notify;
    3339             :         struct sctp_shutdown_event *sse;
    3340             :         struct sctp_queued_to_read *control;
    3341             : 
    3342             :         /*
    3343             :          * For TCP model AND UDP connected sockets we will send an error up
    3344             :          * when an SHUTDOWN completes
    3345             :          */
    3346           0 :         if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
    3347           0 :             (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
    3348             :                 /* mark socket closed for read/write and wakeup! */
    3349             : #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
    3350             :                 struct socket *so;
    3351             : 
    3352             :                 so = SCTP_INP_SO(stcb->sctp_ep);
    3353             :                 atomic_add_int(&stcb->asoc.refcnt, 1);
    3354             :                 SCTP_TCB_UNLOCK(stcb);
    3355             :                 SCTP_SOCKET_LOCK(so, 1);
    3356             :                 SCTP_TCB_LOCK(stcb);
    3357             :                 atomic_subtract_int(&stcb->asoc.refcnt, 1);
    3358             :                 if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
    3359             :                         SCTP_SOCKET_UNLOCK(so, 1);
    3360             :                         return;
    3361             :                 }
    3362             : #endif
    3363           0 :                 socantsendmore(stcb->sctp_socket);
    3364             : #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
    3365             :                 SCTP_SOCKET_UNLOCK(so, 1);
    3366             : #endif
    3367             :         }
    3368           0 :         if (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT)) {
    3369             :                 /* event not enabled */
    3370           0 :                 return;
    3371             :         }
    3372             : 
    3373           0 :         m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_shutdown_event), 0, M_NOWAIT, 1, MT_DATA);
    3374           0 :         if (m_notify == NULL)
    3375             :                 /* no space left */
    3376           0 :                 return;
    3377           0 :         sse = mtod(m_notify, struct sctp_shutdown_event *);
    3378           0 :         memset(sse, 0, sizeof(struct sctp_shutdown_event));
    3379           0 :         sse->sse_type = SCTP_SHUTDOWN_EVENT;
    3380           0 :         sse->sse_flags = 0;
    3381           0 :         sse->sse_length = sizeof(struct sctp_shutdown_event);
    3382           0 :         sse->sse_assoc_id = sctp_get_associd(stcb);
    3383             : 
    3384           0 :         SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_shutdown_event);
    3385           0 :         SCTP_BUF_NEXT(m_notify) = NULL;
    3386             : 
    3387             :         /* append to socket */
    3388           0 :         control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
    3389             :                                          0, 0, stcb->asoc.context, 0, 0, 0,
    3390             :                                          m_notify);
    3391           0 :         if (control == NULL) {
    3392             :                 /* no memory */
    3393           0 :                 sctp_m_freem(m_notify);
    3394           0 :                 return;
    3395             :         }
    3396           0 :         control->spec_flags = M_NOTIFICATION;
    3397           0 :         control->length = SCTP_BUF_LEN(m_notify);
    3398             :         /* not that we need this */
    3399           0 :         control->tail_mbuf = m_notify;
    3400           0 :         sctp_add_to_readq(stcb->sctp_ep, stcb,
    3401             :             control,
    3402           0 :             &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
    3403             : }
    3404             : 
    3405             : static void
    3406           0 : sctp_notify_sender_dry_event(struct sctp_tcb *stcb,
    3407             :                              int so_locked
    3408             : #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
    3409             :                              SCTP_UNUSED
    3410             : #endif
    3411             :                              )
    3412             : {
    3413             :         struct mbuf *m_notify;
    3414             :         struct sctp_sender_dry_event *event;
    3415             :         struct sctp_queued_to_read *control;
    3416             : 
    3417           0 :         if ((stcb == NULL) ||
    3418           0 :             sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_DRYEVNT)) {
    3419             :                 /* event not enabled */
    3420           0 :                 return;
    3421             :         }
    3422             : 
    3423           0 :         m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_sender_dry_event), 0, M_NOWAIT, 1, MT_DATA);
    3424           0 :         if (m_notify == NULL) {
    3425             :                 /* no space left */
    3426           0 :                 return;
    3427             :         }
    3428           0 :         SCTP_BUF_LEN(m_notify) = 0;
    3429           0 :         event = mtod(m_notify, struct sctp_sender_dry_event *);
    3430           0 :         memset(event, 0, sizeof(struct sctp_sender_dry_event));
    3431           0 :         event->sender_dry_type = SCTP_SENDER_DRY_EVENT;
    3432           0 :         event->sender_dry_flags = 0;
    3433           0 :         event->sender_dry_length = sizeof(struct sctp_sender_dry_event);
    3434           0 :         event->sender_dry_assoc_id = sctp_get_associd(stcb);
    3435             : 
    3436           0 :         SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_sender_dry_event);
    3437           0 :         SCTP_BUF_NEXT(m_notify) = NULL;
    3438             : 
    3439             :         /* append to socket */
    3440           0 :         control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
    3441             :                                          0, 0, stcb->asoc.context, 0, 0, 0,
    3442             :                                          m_notify);
    3443           0 :         if (control == NULL) {
    3444             :                 /* no memory */
    3445           0 :                 sctp_m_freem(m_notify);
    3446           0 :                 return;
    3447             :         }
    3448           0 :         control->length = SCTP_BUF_LEN(m_notify);
    3449           0 :         control->spec_flags = M_NOTIFICATION;
    3450             :         /* not that we need this */
    3451           0 :         control->tail_mbuf = m_notify;
    3452           0 :         sctp_add_to_readq(stcb->sctp_ep, stcb, control,
    3453           0 :                           &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, so_locked);
    3454             : }
    3455             : 
    3456             : 
    3457             : void
    3458           0 : sctp_notify_stream_reset_add(struct sctp_tcb *stcb, uint16_t numberin, uint16_t numberout, int flag)
    3459             : {
    3460             :         struct mbuf *m_notify;
    3461             :         struct sctp_queued_to_read *control;
    3462             :         struct sctp_stream_change_event *stradd;
    3463             : 
    3464           0 :         if ((stcb == NULL) ||
    3465           0 :             (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_STREAM_CHANGEEVNT))) {
    3466             :                 /* event not enabled */
    3467           0 :                 return;
    3468             :         }
    3469           0 :         if ((stcb->asoc.peer_req_out) && flag) {
    3470             :                 /* Peer made the request, don't tell the local user */
    3471           0 :                 stcb->asoc.peer_req_out = 0;
    3472           0 :                 return;
    3473             :         }
    3474           0 :         stcb->asoc.peer_req_out = 0;
    3475           0 :         m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_stream_change_event), 0, M_NOWAIT, 1, MT_DATA);
    3476           0 :         if (m_notify == NULL)
    3477             :                 /* no space left */
    3478           0 :                 return;
    3479           0 :         SCTP_BUF_LEN(m_notify) = 0;
    3480           0 :         stradd = mtod(m_notify, struct sctp_stream_change_event *);
    3481           0 :         memset(stradd, 0, sizeof(struct sctp_stream_change_event));
    3482           0 :         stradd->strchange_type = SCTP_STREAM_CHANGE_EVENT;
    3483           0 :         stradd->strchange_flags = flag;
    3484           0 :         stradd->strchange_length = sizeof(struct sctp_stream_change_event);
    3485           0 :         stradd->strchange_assoc_id = sctp_get_associd(stcb);
    3486           0 :         stradd->strchange_instrms = numberin;
    3487           0 :         stradd->strchange_outstrms = numberout;
    3488           0 :         SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_stream_change_event);
    3489           0 :         SCTP_BUF_NEXT(m_notify) = NULL;
    3490           0 :         if (sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) {
    3491             :                 /* no space */
    3492           0 :                 sctp_m_freem(m_notify);
    3493           0 :                 return;
    3494             :         }
    3495             :         /* append to socket */
    3496           0 :         control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
    3497             :                                          0, 0, stcb->asoc.context, 0, 0, 0,
    3498             :                                          m_notify);
    3499           0 :         if (control == NULL) {
    3500             :                 /* no memory */
    3501           0 :                 sctp_m_freem(m_notify);
    3502           0 :                 return;
    3503             :         }
    3504           0 :         control->spec_flags = M_NOTIFICATION;
    3505           0 :         control->length = SCTP_BUF_LEN(m_notify);
    3506             :         /* not that we need this */
    3507           0 :         control->tail_mbuf = m_notify;
    3508           0 :         sctp_add_to_readq(stcb->sctp_ep, stcb,
    3509             :             control,
    3510           0 :             &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
    3511             : }
    3512             : 
    3513             : void
    3514           0 : sctp_notify_stream_reset_tsn(struct sctp_tcb *stcb, uint32_t sending_tsn, uint32_t recv_tsn, int flag)
    3515             : {
    3516             :         struct mbuf *m_notify;
    3517             :         struct sctp_queued_to_read *control;
    3518             :         struct sctp_assoc_reset_event *strasoc;
    3519             : 
    3520           0 :         if ((stcb == NULL) ||
    3521           0 :             (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_ASSOC_RESETEVNT))) {
    3522             :                 /* event not enabled */
    3523           0 :                 return;
    3524             :         }
    3525           0 :         m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_assoc_reset_event), 0, M_NOWAIT, 1, MT_DATA);
    3526           0 :         if (m_notify == NULL)
    3527             :                 /* no space left */
    3528           0 :                 return;
    3529           0 :         SCTP_BUF_LEN(m_notify) = 0;
    3530           0 :         strasoc = mtod(m_notify, struct sctp_assoc_reset_event  *);
    3531           0 :         memset(strasoc, 0, sizeof(struct sctp_assoc_reset_event));
    3532           0 :         strasoc->assocreset_type = SCTP_ASSOC_RESET_EVENT;
    3533           0 :         strasoc->assocreset_flags = flag;
    3534           0 :         strasoc->assocreset_length = sizeof(struct sctp_assoc_reset_event);
    3535           0 :         strasoc->assocreset_assoc_id= sctp_get_associd(stcb);
    3536           0 :         strasoc->assocreset_local_tsn = sending_tsn;
    3537           0 :         strasoc->assocreset_remote_tsn = recv_tsn;
    3538           0 :         SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_assoc_reset_event);
    3539           0 :         SCTP_BUF_NEXT(m_notify) = NULL;
    3540           0 :         if (sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) {
    3541             :                 /* no space */
    3542           0 :                 sctp_m_freem(m_notify);
    3543           0 :                 return;
    3544             :         }
    3545             :         /* append to socket */
    3546           0 :         control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
    3547             :                                          0, 0, stcb->asoc.context, 0, 0, 0,
    3548             :                                          m_notify);
    3549           0 :         if (control == NULL) {
    3550             :                 /* no memory */
    3551           0 :                 sctp_m_freem(m_notify);
    3552           0 :                 return;
    3553             :         }
    3554           0 :         control->spec_flags = M_NOTIFICATION;
    3555           0 :         control->length = SCTP_BUF_LEN(m_notify);
    3556             :         /* not that we need this */
    3557           0 :         control->tail_mbuf = m_notify;
    3558           0 :         sctp_add_to_readq(stcb->sctp_ep, stcb,
    3559             :             control,
    3560           0 :             &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
    3561             : }
    3562             : 
    3563             : 
    3564             : 
    3565             : static void
    3566           0 : sctp_notify_stream_reset(struct sctp_tcb *stcb,
    3567             :     int number_entries, uint16_t * list, int flag)
    3568             : {
    3569             :         struct mbuf *m_notify;
    3570             :         struct sctp_queued_to_read *control;
    3571             :         struct sctp_stream_reset_event *strreset;
    3572             :         int len;
    3573             : 
    3574           0 :         if ((stcb == NULL) ||
    3575           0 :             (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT))) {
    3576             :                 /* event not enabled */
    3577           0 :                 return;
    3578             :         }
    3579             : 
    3580           0 :         m_notify = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA);
    3581           0 :         if (m_notify == NULL)
    3582             :                 /* no space left */
    3583           0 :                 return;
    3584           0 :         SCTP_BUF_LEN(m_notify) = 0;
    3585           0 :         len = sizeof(struct sctp_stream_reset_event) + (number_entries * sizeof(uint16_t));
    3586           0 :         if (len > M_TRAILINGSPACE(m_notify)) {
    3587             :                 /* never enough room */
    3588           0 :                 sctp_m_freem(m_notify);
    3589           0 :                 return;
    3590             :         }
    3591           0 :         strreset = mtod(m_notify, struct sctp_stream_reset_event *);
    3592           0 :         memset(strreset, 0, len);
    3593           0 :         strreset->strreset_type = SCTP_STREAM_RESET_EVENT;
    3594           0 :         strreset->strreset_flags = flag;
    3595           0 :         strreset->strreset_length = len;
    3596           0 :         strreset->strreset_assoc_id = sctp_get_associd(stcb);
    3597           0 :         if (number_entries) {
    3598             :                 int i;
    3599             : 
    3600           0 :                 for (i = 0; i < number_entries; i++) {
    3601           0 :                         strreset->strreset_stream_list[i] = ntohs(list[i]);
    3602             :                 }
    3603             :         }
    3604           0 :         SCTP_BUF_LEN(m_notify) = len;
    3605           0 :         SCTP_BUF_NEXT(m_notify) = NULL;
    3606           0 :         if (sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) {
    3607             :                 /* no space */
    3608           0 :                 sctp_m_freem(m_notify);
    3609           0 :                 return;
    3610             :         }
    3611             :         /* append to socket */
    3612           0 :         control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
    3613             :                                          0, 0, stcb->asoc.context, 0, 0, 0,
    3614             :                                          m_notify);
    3615           0 :         if (control == NULL) {
    3616             :                 /* no memory */
    3617           0 :                 sctp_m_freem(m_notify);
    3618           0 :                 return;
    3619             :         }
    3620           0 :         control->spec_flags = M_NOTIFICATION;
    3621           0 :         control->length = SCTP_BUF_LEN(m_notify);
    3622             :         /* not that we need this */
    3623           0 :         control->tail_mbuf = m_notify;
    3624           0 :         sctp_add_to_readq(stcb->sctp_ep, stcb,
    3625             :                           control,
    3626           0 :                           &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
    3627             : }
    3628             : 
    3629             : 
    3630             : static void
    3631           0 : sctp_notify_remote_error(struct sctp_tcb *stcb, uint16_t error, struct sctp_error_chunk *chunk)
    3632             : {
    3633             :         struct mbuf *m_notify;
    3634             :         struct sctp_remote_error *sre;
    3635             :         struct sctp_queued_to_read *control;
    3636             :         size_t notif_len, chunk_len;
    3637             : 
    3638           0 :         if ((stcb == NULL) ||
    3639           0 :             sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVPEERERR)) {
    3640           0 :                 return;
    3641             :         }
    3642           0 :         if (chunk != NULL) {
    3643           0 :                 chunk_len = ntohs(chunk->ch.chunk_length);
    3644             :         } else {
    3645           0 :                 chunk_len = 0;
    3646             :         }
    3647           0 :         notif_len = sizeof(struct sctp_remote_error) + chunk_len;
    3648           0 :         m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_NOWAIT, 1, MT_DATA);
    3649           0 :         if (m_notify == NULL) {
    3650             :                 /* Retry with smaller value. */
    3651           0 :                 notif_len = sizeof(struct sctp_remote_error);
    3652           0 :                 m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_NOWAIT, 1, MT_DATA);
    3653           0 :                 if (m_notify == NULL) {
    3654           0 :                         return;
    3655             :                 }
    3656             :         }
    3657           0 :         SCTP_BUF_NEXT(m_notify) = NULL;
    3658           0 :         sre = mtod(m_notify, struct sctp_remote_error *);
    3659           0 :         memset(sre, 0, notif_len);
    3660           0 :         sre->sre_type = SCTP_REMOTE_ERROR;
    3661           0 :         sre->sre_flags = 0;
    3662           0 :         sre->sre_length = sizeof(struct sctp_remote_error);
    3663           0 :         sre->sre_error = error;
    3664           0 :         sre->sre_assoc_id = sctp_get_associd(stcb);
    3665           0 :         if (notif_len > sizeof(struct sctp_remote_error)) {
    3666           0 :                 memcpy(sre->sre_data, chunk, chunk_len);
    3667           0 :                 sre->sre_length += chunk_len;
    3668             :         }
    3669           0 :         SCTP_BUF_LEN(m_notify) = sre->sre_length;
    3670           0 :         control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
    3671             :                                          0, 0, stcb->asoc.context, 0, 0, 0,
    3672             :                                          m_notify);
    3673           0 :         if (control != NULL) {
    3674           0 :                 control->length = SCTP_BUF_LEN(m_notify);
    3675             :                 /* not that we need this */
    3676           0 :                 control->tail_mbuf = m_notify;
    3677           0 :                 control->spec_flags = M_NOTIFICATION;
    3678           0 :                 sctp_add_to_readq(stcb->sctp_ep, stcb,
    3679             :                                   control,
    3680           0 :                                   &stcb->sctp_socket->so_rcv, 1,
    3681             :                                   SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
    3682             :         } else {
    3683           0 :                 sctp_m_freem(m_notify);
    3684             :         }
    3685             : }
    3686             : 
    3687             : 
    3688             : void
    3689           0 : sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
    3690             :     uint32_t error, void *data, int so_locked
    3691             : #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
    3692             :     SCTP_UNUSED
    3693             : #endif
    3694             :     )
    3695             : {
    3696           0 :         if ((stcb == NULL) ||
    3697           0 :             (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
    3698           0 :             (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
    3699           0 :             (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) {
    3700             :                 /* If the socket is gone we are out of here */
    3701           0 :                 return;
    3702             :         }
    3703             : #if (defined(__FreeBSD__) && __FreeBSD_version > 500000) || defined(__Windows__)
    3704             :         if (stcb->sctp_socket->so_rcv.sb_state & SBS_CANTRCVMORE) {
    3705             : #else
    3706           0 :         if (stcb->sctp_socket->so_state & SS_CANTRCVMORE) {
    3707             : #endif
    3708           0 :                 return;
    3709             :         }
    3710             : #if defined(__APPLE__)
    3711             :         if (so_locked) {
    3712             :                 sctp_lock_assert(SCTP_INP_SO(stcb->sctp_ep));
    3713             :         } else {
    3714             :                 sctp_unlock_assert(SCTP_INP_SO(stcb->sctp_ep));
    3715             :         }
    3716             : #endif
    3717           0 :         if ((stcb->asoc.state & SCTP_STATE_COOKIE_WAIT) ||
    3718           0 :             (stcb->asoc.state &  SCTP_STATE_COOKIE_ECHOED)) {
    3719           0 :                 if ((notification == SCTP_NOTIFY_INTERFACE_DOWN) ||
    3720           0 :                     (notification == SCTP_NOTIFY_INTERFACE_UP) ||
    3721             :                     (notification == SCTP_NOTIFY_INTERFACE_CONFIRMED)) {
    3722             :                         /* Don't report these in front states */
    3723           0 :                         return;
    3724             :                 }
    3725             :         }
    3726           0 :         switch (notification) {
    3727             :         case SCTP_NOTIFY_ASSOC_UP:
    3728           0 :                 if (stcb->asoc.assoc_up_sent == 0) {
    3729           0 :                         sctp_notify_assoc_change(SCTP_COMM_UP, stcb, error, NULL, 0, so_locked);
    3730           0 :                         stcb->asoc.assoc_up_sent = 1;
    3731             :                 }
    3732           0 :                 if (stcb->asoc.adaptation_needed && (stcb->asoc.adaptation_sent == 0)) {
    3733           0 :                         sctp_notify_adaptation_layer(stcb);
    3734             :                 }
    3735           0 :                 if (stcb->asoc.auth_supported == 0) {
    3736           0 :                         sctp_ulp_notify(SCTP_NOTIFY_NO_PEER_AUTH, stcb, 0,
    3737             :                                         NULL, so_locked);
    3738             :                 }
    3739           0 :                 break;
    3740             :         case SCTP_NOTIFY_ASSOC_DOWN:
    3741           0 :                 sctp_notify_assoc_change(SCTP_SHUTDOWN_COMP, stcb, error, NULL, 0, so_locked);
    3742             : #if defined(__Userspace__)
    3743           0 :                 if (stcb->sctp_ep->recv_callback) {
    3744           0 :                         if (stcb->sctp_socket) {
    3745             :                                 union sctp_sockstore addr;
    3746             :                                 struct sctp_rcvinfo rcv;
    3747             : 
    3748           0 :                                 memset(&addr, 0, sizeof(union sctp_sockstore));
    3749           0 :                                 memset(&rcv, 0, sizeof(struct sctp_rcvinfo));
    3750           0 :                                 atomic_add_int(&stcb->asoc.refcnt, 1);
    3751           0 :                                 SCTP_TCB_UNLOCK(stcb);
    3752           0 :                                 stcb->sctp_ep->recv_callback(stcb->sctp_socket, addr, NULL, 0, rcv, 0, stcb->sctp_ep->ulp_info);
    3753           0 :                                 SCTP_TCB_LOCK(stcb);
    3754           0 :                                 atomic_subtract_int(&stcb->asoc.refcnt, 1);
    3755             :                         }
    3756             :                 }
    3757             : #endif
    3758           0 :                 break;
    3759             :         case SCTP_NOTIFY_INTERFACE_DOWN:
    3760             :                 {
    3761             :                         struct sctp_nets *net;
    3762             : 
    3763           0 :                         net = (struct sctp_nets *)data;
    3764           0 :                         sctp_notify_peer_addr_change(stcb, SCTP_ADDR_UNREACHABLE,
    3765           0 :                             (struct sockaddr *)&net->ro._l_addr, error, so_locked);
    3766           0 :                         break;
    3767             :                 }
    3768             :         case SCTP_NOTIFY_INTERFACE_UP:
    3769             :                 {
    3770             :                         struct sctp_nets *net;
    3771             : 
    3772           0 :                         net = (struct sctp_nets *)data;
    3773           0 :                         sctp_notify_peer_addr_change(stcb, SCTP_ADDR_AVAILABLE,
    3774           0 :                             (struct sockaddr *)&net->ro._l_addr, error, so_locked);
    3775           0 :                         break;
    3776             :                 }
    3777             :         case SCTP_NOTIFY_INTERFACE_CONFIRMED:
    3778             :                 {
    3779             :                         struct sctp_nets *net;
    3780             : 
    3781           0 :                         net = (struct sctp_nets *)data;
    3782           0 :                         sctp_notify_peer_addr_change(stcb, SCTP_ADDR_CONFIRMED,
    3783           0 :                             (struct sockaddr *)&net->ro._l_addr, error, so_locked);
    3784           0 :                         break;
    3785             :                 }
    3786             :         case SCTP_NOTIFY_SPECIAL_SP_FAIL:
    3787           0 :                 sctp_notify_send_failed2(stcb, error,
    3788             :                                          (struct sctp_stream_queue_pending *)data, so_locked);
    3789           0 :                 break;
    3790             :         case SCTP_NOTIFY_SENT_DG_FAIL:
    3791           0 :                 sctp_notify_send_failed(stcb, 1, error,
    3792             :                     (struct sctp_tmit_chunk *)data, so_locked);
    3793           0 :                 break;
    3794             :         case SCTP_NOTIFY_UNSENT_DG_FAIL:
    3795           0 :                 sctp_notify_send_failed(stcb, 0, error,
    3796             :                                         (struct sctp_tmit_chunk *)data, so_locked);
    3797           0 :                 break;
    3798             :         case SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION:
    3799             :                 {
    3800             :                         uint32_t val;
    3801           0 :                         val = *((uint32_t *)data);
    3802             : 
    3803           0 :                         sctp_notify_partial_delivery_indication(stcb, error, val, so_locked);
    3804           0 :                 break;
    3805             :                 }
    3806             :         case SCTP_NOTIFY_ASSOC_LOC_ABORTED:
    3807           0 :                 if (((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_WAIT) ||
    3808           0 :                     ((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_ECHOED)) {
    3809           0 :                         sctp_notify_assoc_change(SCTP_CANT_STR_ASSOC, stcb, error, data, 0, so_locked);
    3810             :                 } else {
    3811           0 :                         sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error, data, 0, so_locked);
    3812             :                 }
    3813           0 :                 break;
    3814             :         case SCTP_NOTIFY_ASSOC_REM_ABORTED:
    3815           0 :                 if (((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_WAIT) ||
    3816           0 :                     ((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_ECHOED)) {
    3817           0 :                         sctp_notify_assoc_change(SCTP_CANT_STR_ASSOC, stcb, error, data, 1, so_locked);
    3818             :                 } else {
    3819           0 :                         sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error, data, 1, so_locked);
    3820             :                 }
    3821           0 :                 break;
    3822             :         case SCTP_NOTIFY_ASSOC_RESTART:
    3823           0 :                 sctp_notify_assoc_change(SCTP_RESTART, stcb, error, NULL, 0, so_locked);
    3824           0 :                 if (stcb->asoc.auth_supported == 0) {
    3825           0 :                         sctp_ulp_notify(SCTP_NOTIFY_NO_PEER_AUTH, stcb, 0,
    3826             :                                         NULL, so_locked);
    3827             :                 }
    3828           0 :                 break;
    3829             :         case SCTP_NOTIFY_STR_RESET_SEND:
    3830           0 :                 sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), SCTP_STREAM_RESET_OUTGOING_SSN);
    3831           0 :                 break;
    3832             :         case SCTP_NOTIFY_STR_RESET_RECV:
    3833           0 :                 sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), SCTP_STREAM_RESET_INCOMING);
    3834           0 :                 break;
    3835             :         case SCTP_NOTIFY_STR_RESET_FAILED_OUT:
    3836           0 :                 sctp_notify_stream_reset(stcb, error, ((uint16_t *) data),
    3837             :                                          (SCTP_STREAM_RESET_OUTGOING_SSN|SCTP_STREAM_RESET_FAILED));
    3838           0 :                 break;
    3839             :         case SCTP_NOTIFY_STR_RESET_DENIED_OUT:
    3840           0 :                 sctp_notify_stream_reset(stcb, error, ((uint16_t *) data),
    3841             :                                          (SCTP_STREAM_RESET_OUTGOING_SSN|SCTP_STREAM_RESET_DENIED));
    3842           0 :                 break;
    3843             :         case SCTP_NOTIFY_STR_RESET_FAILED_IN:
    3844           0 :                 sctp_notify_stream_reset(stcb, error, ((uint16_t *) data),
    3845             :                                          (SCTP_STREAM_RESET_INCOMING|SCTP_STREAM_RESET_FAILED));
    3846           0 :                 break;
    3847             :         case SCTP_NOTIFY_STR_RESET_DENIED_IN:
    3848           0 :                 sctp_notify_stream_reset(stcb, error, ((uint16_t *) data),
    3849             :                                          (SCTP_STREAM_RESET_INCOMING|SCTP_STREAM_RESET_DENIED));
    3850           0 :                 break;
    3851             :         case SCTP_NOTIFY_ASCONF_ADD_IP:
    3852           0 :                 sctp_notify_peer_addr_change(stcb, SCTP_ADDR_ADDED, data,
    3853             :                     error, so_locked);
    3854           0 :                 break;
    3855             :         case SCTP_NOTIFY_ASCONF_DELETE_IP:
    3856           0 :                 sctp_notify_peer_addr_change(stcb, SCTP_ADDR_REMOVED, data,
    3857             :                                              error, so_locked);
    3858           0 :                 break;
    3859             :         case SCTP_NOTIFY_ASCONF_SET_PRIMARY:
    3860           0 :                 sctp_notify_peer_addr_change(stcb, SCTP_ADDR_MADE_PRIM, data,
    3861             :                                              error, so_locked);
    3862           0 :                 break;
    3863             :         case SCTP_NOTIFY_PEER_SHUTDOWN:
    3864           0 :                 sctp_notify_shutdown_event(stcb);
    3865           0 :                 break;
    3866             :         case SCTP_NOTIFY_AUTH_NEW_KEY:
    3867           0 :                 sctp_notify_authentication(stcb, SCTP_AUTH_NEW_KEY, error,
    3868           0 :                                            (uint16_t)(uintptr_t)data,
    3869             :                                            so_locked);
    3870           0 :                 break;
    3871             :         case SCTP_NOTIFY_AUTH_FREE_KEY:
    3872           0 :                 sctp_notify_authentication(stcb, SCTP_AUTH_FREE_KEY, error,
    3873           0 :                                            (uint16_t)(uintptr_t)data,
    3874             :                                            so_locked);
    3875           0 :                 break;
    3876             :         case SCTP_NOTIFY_NO_PEER_AUTH:
    3877           0 :                 sctp_notify_authentication(stcb, SCTP_AUTH_NO_AUTH, error,
    3878           0 :                                            (uint16_t)(uintptr_t)data,
    3879             :                                            so_locked);
    3880           0 :                 break;
    3881             :         case SCTP_NOTIFY_SENDER_DRY:
    3882           0 :                 sctp_notify_sender_dry_event(stcb, so_locked);
    3883           0 :                 break;
    3884             :         case SCTP_NOTIFY_REMOTE_ERROR:
    3885           0 :                 sctp_notify_remote_error(stcb, error, data);
    3886           0 :                 break;
    3887             :         default:
    3888           0 :                 SCTPDBG(SCTP_DEBUG_UTIL1, "%s: unknown notification %xh (%u)\n",
    3889             :                         __FUNCTION__, notification, notification);
    3890           0 :                 break;
    3891             :         }                       /* end switch */
    3892             : }
    3893             : 
    3894             : void
    3895           0 : sctp_report_all_outbound(struct sctp_tcb *stcb, uint16_t error, int holds_lock, int so_locked
    3896             : #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
    3897             :     SCTP_UNUSED
    3898             : #endif
    3899             :     )
    3900             : {
    3901             :         struct sctp_association *asoc;
    3902             :         struct sctp_stream_out *outs;
    3903             :         struct sctp_tmit_chunk *chk, *nchk;
    3904             :         struct sctp_stream_queue_pending *sp, *nsp;
    3905             :         int i;
    3906             : 
    3907           0 :         if (stcb == NULL) {
    3908           0 :                 return;
    3909             :         }
    3910           0 :         asoc = &stcb->asoc;
    3911           0 :         if (asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) {
    3912             :                 /* already being freed */
    3913           0 :                 return;
    3914             :         }
    3915             : #if defined(__APPLE__)
    3916             :         if (so_locked) {
    3917             :                 sctp_lock_assert(SCTP_INP_SO(stcb->sctp_ep));
    3918             :         } else {
    3919             :                 sctp_unlock_assert(SCTP_INP_SO(stcb->sctp_ep));
    3920             :         }
    3921             : #endif
    3922           0 :         if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
    3923           0 :             (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
    3924           0 :             (asoc->state & SCTP_STATE_CLOSED_SOCKET)) {
    3925           0 :                 return;
    3926             :         }
    3927             :         /* now through all the gunk freeing chunks */
    3928           0 :         if (holds_lock == 0) {
    3929           0 :                 SCTP_TCB_SEND_LOCK(stcb);
    3930             :         }
    3931             :         /* sent queue SHOULD be empty */
    3932           0 :         TAILQ_FOREACH_SAFE(chk, &asoc->sent_queue, sctp_next, nchk) {
    3933           0 :                 TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next);
    3934           0 :                 asoc->sent_queue_cnt--;
    3935           0 :                 if (chk->sent != SCTP_DATAGRAM_NR_ACKED) {
    3936           0 :                         if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) {
    3937           0 :                                 asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--;
    3938             : #ifdef INVARIANTS
    3939             :                         } else {
    3940             :                                 panic("No chunks on the queues for sid %u.", chk->rec.data.stream_number);
    3941             : #endif
    3942             :                         }
    3943             :                 }
    3944           0 :                 if (chk->data != NULL) {
    3945           0 :                         sctp_free_bufspace(stcb, asoc, chk, 1);
    3946           0 :                         sctp_ulp_notify(SCTP_NOTIFY_SENT_DG_FAIL, stcb,
    3947             :                                         error, chk, so_locked);
    3948           0 :                         if (chk->data) {
    3949           0 :                                 sctp_m_freem(chk->data);
    3950           0 :                                 chk->data = NULL;
    3951             :                         }
    3952             :                 }
    3953           0 :                 sctp_free_a_chunk(stcb, chk, so_locked);
    3954             :                 /*sa_ignore FREED_MEMORY*/
    3955             :         }
    3956             :         /* pending send queue SHOULD be empty */
    3957           0 :         TAILQ_FOREACH_SAFE(chk, &asoc->send_queue, sctp_next, nchk) {
    3958           0 :                 TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next);
    3959           0 :                 asoc->send_queue_cnt--;
    3960           0 :                 if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) {
    3961           0 :                         asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--;
    3962             : #ifdef INVARIANTS
    3963             :                 } else {
    3964             :                         panic("No chunks on the queues for sid %u.", chk->rec.data.stream_number);
    3965             : #endif
    3966             :                 }
    3967           0 :                 if (chk->data != NULL) {
    3968           0 :                         sctp_free_bufspace(stcb, asoc, chk, 1);
    3969           0 :                         sctp_ulp_notify(SCTP_NOTIFY_UNSENT_DG_FAIL, stcb,
    3970             :                                         error, chk, so_locked);
    3971           0 :                         if (chk->data) {
    3972           0 :                                 sctp_m_freem(chk->data);
    3973           0 :                                 chk->data = NULL;
    3974             :                         }
    3975             :                 }
    3976           0 :                 sctp_free_a_chunk(stcb, chk, so_locked);
    3977             :                 /*sa_ignore FREED_MEMORY*/
    3978             :         }
    3979           0 :         for (i = 0; i < asoc->streamoutcnt; i++) {
    3980             :                 /* For each stream */
    3981           0 :                 outs = &asoc->strmout[i];
    3982             :                 /* clean up any sends there */
    3983           0 :                 asoc->locked_on_sending = NULL;
    3984           0 :                 TAILQ_FOREACH_SAFE(sp, &outs->outqueue, next, nsp) {
    3985           0 :                         asoc->stream_queue_cnt--;
    3986           0 :                         TAILQ_REMOVE(&outs->outqueue, sp, next);
    3987           0 :                         sctp_free_spbufspace(stcb, asoc, sp);
    3988           0 :                         if (sp->data) {
    3989           0 :                                 sctp_ulp_notify(SCTP_NOTIFY_SPECIAL_SP_FAIL, stcb,
    3990             :                                                 error, (void *)sp, so_locked);
    3991           0 :                                 if (sp->data) {
    3992           0 :                                         sctp_m_freem(sp->data);
    3993           0 :                                         sp->data = NULL;
    3994           0 :                                         sp->tail_mbuf = NULL;
    3995           0 :                                         sp->length = 0;
    3996             :                                 }
    3997             :                         }
    3998           0 :                         if (sp->net) {
    3999           0 :                                 sctp_free_remote_addr(sp->net);
    4000           0 :                                 sp->net = NULL;
    4001             :                         }
    4002             :                         /* Free the chunk */
    4003           0 :                         sctp_free_a_strmoq(stcb, sp, so_locked);
    4004             :                         /*sa_ignore FREED_MEMORY*/
    4005             :                 }
    4006             :         }
    4007             : 
    4008           0 :         if (holds_lock == 0) {
    4009           0 :                 SCTP_TCB_SEND_UNLOCK(stcb);
    4010             :         }
    4011             : }
    4012             : 
    4013             : void
    4014           0 : sctp_abort_notification(struct sctp_tcb *stcb, uint8_t from_peer, uint16_t error,
    4015             :                         struct sctp_abort_chunk *abort, int so_locked
    4016             : #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
    4017             :     SCTP_UNUSED
    4018             : #endif
    4019             :     )
    4020             : {
    4021           0 :         if (stcb == NULL) {
    4022           0 :                 return;
    4023             :         }
    4024             : #if defined(__APPLE__)
    4025             :         if (so_locked) {
    4026             :                 sctp_lock_assert(SCTP_INP_SO(stcb->sctp_ep));
    4027             :         } else {
    4028             :                 sctp_unlock_assert(SCTP_INP_SO(stcb->sctp_ep));
    4029             :         }
    4030             : #endif
    4031           0 :         if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
    4032           0 :             ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
    4033           0 :              (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED))) {
    4034           0 :                 stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_WAS_ABORTED;
    4035             :         }
    4036           0 :         if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
    4037           0 :             (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
    4038           0 :             (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) {
    4039           0 :                 return;
    4040             :         }
    4041             :         /* Tell them we lost the asoc */
    4042           0 :         sctp_report_all_outbound(stcb, error, 1, so_locked);
    4043           0 :         if (from_peer) {
    4044           0 :                 sctp_ulp_notify(SCTP_NOTIFY_ASSOC_REM_ABORTED, stcb, error, abort, so_locked);
    4045             :         } else {
    4046           0 :                 sctp_ulp_notify(SCTP_NOTIFY_ASSOC_LOC_ABORTED, stcb, error, abort, so_locked);
    4047             :         }
    4048             : }
    4049             : 
    4050             : void
    4051           0 : sctp_abort_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
    4052             :                        struct mbuf *m, int iphlen,
    4053             :                        struct sockaddr *src, struct sockaddr *dst,
    4054             :                        struct sctphdr *sh, struct mbuf *op_err,
    4055             : #if defined(__FreeBSD__)
    4056             :                        uint8_t mflowtype, uint32_t mflowid,
    4057             : #endif
    4058             :                        uint32_t vrf_id, uint16_t port)
    4059             : {
    4060             :         uint32_t vtag;
    4061             : #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
    4062             :         struct socket *so;
    4063             : #endif
    4064             : 
    4065           0 :         vtag = 0;
    4066           0 :         if (stcb != NULL) {
    4067           0 :                 vtag = stcb->asoc.peer_vtag;
    4068           0 :                 vrf_id = stcb->asoc.vrf_id;
    4069             :         }
    4070           0 :         sctp_send_abort(m, iphlen, src, dst, sh, vtag, op_err,
    4071             : #if defined(__FreeBSD__)
    4072             :                         mflowtype, mflowid,
    4073             : #endif
    4074             :                         vrf_id, port);
    4075           0 :         if (stcb != NULL) {
    4076             :                 /* We have a TCB to abort, send notification too */
    4077           0 :                 sctp_abort_notification(stcb, 0, 0, NULL, SCTP_SO_NOT_LOCKED);
    4078           0 :                 stcb->asoc.state |= SCTP_STATE_WAS_ABORTED;
    4079             :                 /* Ok, now lets free it */
    4080             : #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
    4081             :                 so = SCTP_INP_SO(inp);
    4082             :                 atomic_add_int(&stcb->asoc.refcnt, 1);
    4083             :                 SCTP_TCB_UNLOCK(stcb);
    4084             :                 SCTP_SOCKET_LOCK(so, 1);
    4085             :                 SCTP_TCB_LOCK(stcb);
    4086             :                 atomic_subtract_int(&stcb->asoc.refcnt, 1);
    4087             : #endif
    4088           0 :                 SCTP_STAT_INCR_COUNTER32(sctps_aborted);
    4089           0 :                 if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
    4090           0 :                     (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
    4091           0 :                         SCTP_STAT_DECR_GAUGE32(sctps_currestab);
    4092             :                 }
    4093           0 :                 (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL+SCTP_LOC_4);
    4094             : #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
    4095             :                 SCTP_SOCKET_UNLOCK(so, 1);
    4096             : #endif
    4097             :         }
    4098           0 : }
    4099             : #ifdef SCTP_ASOCLOG_OF_TSNS
    4100             : void
    4101             : sctp_print_out_track_log(struct sctp_tcb *stcb)
    4102             : {
    4103             : #ifdef NOSIY_PRINTS
    4104             :         int i;
    4105             :         SCTP_PRINTF("Last ep reason:%x\n", stcb->sctp_ep->last_abort_code);
    4106             :         SCTP_PRINTF("IN bound TSN log-aaa\n");
    4107             :         if ((stcb->asoc.tsn_in_at == 0) && (stcb->asoc.tsn_in_wrapped == 0)) {
    4108             :                 SCTP_PRINTF("None rcvd\n");
    4109             :                 goto none_in;
    4110             :         }
    4111             :         if (stcb->asoc.tsn_in_wrapped) {
    4112             :                 for (i = stcb->asoc.tsn_in_at; i < SCTP_TSN_LOG_SIZE; i++) {
    4113             :                         SCTP_PRINTF("TSN:%x strm:%d seq:%d flags:%x sz:%d\n",
    4114             :                                     stcb->asoc.in_tsnlog[i].tsn,
    4115             :                                     stcb->asoc.in_tsnlog[i].strm,
    4116             :                                     stcb->asoc.in_tsnlog[i].seq,
    4117             :                                     stcb->asoc.in_tsnlog[i].flgs,
    4118             :                                     stcb->asoc.in_tsnlog[i].sz);
    4119             :                 }
    4120             :         }
    4121             :         if (stcb->asoc.tsn_in_at) {
    4122             :                 for (i = 0; i < stcb->asoc.tsn_in_at; i++) {
    4123             :                         SCTP_PRINTF("TSN:%x strm:%d seq:%d flags:%x sz:%d\n",
    4124             :                                     stcb->asoc.in_tsnlog[i].tsn,
    4125             :                                     stcb->asoc.in_tsnlog[i].strm,
    4126             :                                     stcb->asoc.in_tsnlog[i].seq,
    4127             :                                     stcb->asoc.in_tsnlog[i].flgs,
    4128             :                                     stcb->asoc.in_tsnlog[i].sz);
    4129             :                 }
    4130             :         }
    4131             :  none_in:
    4132             :         SCTP_PRINTF("OUT bound TSN log-aaa\n");
    4133             :         if ((stcb->asoc.tsn_out_at == 0) &&
    4134             :             (stcb->asoc.tsn_out_wrapped == 0)) {
    4135             :                 SCTP_PRINTF("None sent\n");
    4136             :         }
    4137             :         if (stcb->asoc.tsn_out_wrapped) {
    4138             :                 for (i = stcb->asoc.tsn_out_at; i < SCTP_TSN_LOG_SIZE; i++) {
    4139             :                         SCTP_PRINTF("TSN:%x strm:%d seq:%d flags:%x sz:%d\n",
    4140             :                                     stcb->asoc.out_tsnlog[i].tsn,
    4141             :                                     stcb->asoc.out_tsnlog[i].strm,
    4142             :                                     stcb->asoc.out_tsnlog[i].seq,
    4143             :                                     stcb->asoc.out_tsnlog[i].flgs,
    4144             :                                     stcb->asoc.out_tsnlog[i].sz);
    4145             :                 }
    4146             :         }
    4147             :         if (stcb->asoc.tsn_out_at) {
    4148             :                 for (i = 0; i < stcb->asoc.tsn_out_at; i++) {
    4149             :                         SCTP_PRINTF("TSN:%x strm:%d seq:%d flags:%x sz:%d\n",
    4150             :                                     stcb->asoc.out_tsnlog[i].tsn,
    4151             :                                     stcb->asoc.out_tsnlog[i].strm,
    4152             :                                     stcb->asoc.out_tsnlog[i].seq,
    4153             :                                     stcb->asoc.out_tsnlog[i].flgs,
    4154             :                                     stcb->asoc.out_tsnlog[i].sz);
    4155             :                 }
    4156             :         }
    4157             : #endif
    4158             : }
    4159             : #endif
    4160             : 
    4161             : void
    4162           0 : sctp_abort_an_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
    4163             :                           struct mbuf *op_err,
    4164             :                           int so_locked
    4165             : #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
    4166             :                           SCTP_UNUSED
    4167             : #endif
    4168             : )
    4169             : {
    4170             : #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
    4171             :         struct socket *so;
    4172             : #endif
    4173             : 
    4174             : #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
    4175             :         so = SCTP_INP_SO(inp);
    4176             : #endif
    4177             : #if defined(__APPLE__)
    4178             :         if (so_locked) {
    4179             :                 sctp_lock_assert(SCTP_INP_SO(inp));
    4180             :         } else {
    4181             :                 sctp_unlock_assert(SCTP_INP_SO(inp));
    4182             :         }
    4183             : #endif
    4184           0 :         if (stcb == NULL) {
    4185             :                 /* Got to have a TCB */
    4186           0 :                 if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
    4187           0 :                         if (LIST_EMPTY(&inp->sctp_asoc_list)) {
    4188             : #if defined(__APPLE__)
    4189             :                                 if (!so_locked) {
    4190             :                                         SCTP_SOCKET_LOCK(so, 1);
    4191             :                                 }
    4192             : #endif
    4193           0 :                                 sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
    4194             :                                                 SCTP_CALLED_DIRECTLY_NOCMPSET);
    4195             : #if defined(__APPLE__)
    4196             :                                 if (!so_locked) {
    4197             :                                         SCTP_SOCKET_UNLOCK(so, 1);
    4198             :                                 }
    4199             : #endif
    4200             :                         }
    4201             :                 }
    4202           0 :                 return;
    4203             :         } else {
    4204           0 :                 stcb->asoc.state |= SCTP_STATE_WAS_ABORTED;
    4205             :         }
    4206             :         /* notify the peer */
    4207           0 :         sctp_send_abort_tcb(stcb, op_err, so_locked);
    4208           0 :         SCTP_STAT_INCR_COUNTER32(sctps_aborted);
    4209           0 :         if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
    4210           0 :             (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
    4211           0 :                 SCTP_STAT_DECR_GAUGE32(sctps_currestab);
    4212             :         }
    4213             :         /* notify the ulp */
    4214           0 :         if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
    4215           0 :                 sctp_abort_notification(stcb, 0, 0, NULL, so_locked);
    4216             :         }
    4217             :         /* now free the asoc */
    4218             : #ifdef SCTP_ASOCLOG_OF_TSNS
    4219             :         sctp_print_out_track_log(stcb);
    4220             : #endif
    4221             : #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
    4222             :         if (!so_locked) {
    4223             :                 atomic_add_int(&stcb->asoc.refcnt, 1);
    4224             :                 SCTP_TCB_UNLOCK(stcb);
    4225             :                 SCTP_SOCKET_LOCK(so, 1);
    4226             :                 SCTP_TCB_LOCK(stcb);
    4227             :                 atomic_subtract_int(&stcb->asoc.refcnt, 1);
    4228             :         }
    4229             : #endif
    4230           0 :         (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL+SCTP_LOC_5);
    4231             : #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
    4232             :         if (!so_locked) {
    4233             :                 SCTP_SOCKET_UNLOCK(so, 1);
    4234             :         }
    4235             : #endif
    4236             : }
    4237             : 
    4238             : void
    4239           0 : sctp_handle_ootb(struct mbuf *m, int iphlen, int offset,
    4240             :                  struct sockaddr *src, struct sockaddr *dst,
    4241             :                  struct sctphdr *sh, struct sctp_inpcb *inp,
    4242             :                  struct mbuf *cause,
    4243             : #if defined(__FreeBSD__)
    4244             :                  uint8_t mflowtype, uint32_t mflowid,
    4245             : #endif
    4246             :                  uint32_t vrf_id, uint16_t port)
    4247             : {
    4248             :         struct sctp_chunkhdr *ch, chunk_buf;
    4249             :         unsigned int chk_length;
    4250             :         int contains_init_chunk;
    4251             : 
    4252           0 :         SCTP_STAT_INCR_COUNTER32(sctps_outoftheblue);
    4253             :         /* Generate a TO address for future reference */
    4254           0 :         if (inp && (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
    4255           0 :                 if (LIST_EMPTY(&inp->sctp_asoc_list)) {
    4256             : #if defined(__APPLE__)
    4257             :                         SCTP_SOCKET_LOCK(SCTP_INP_SO(inp), 1);
    4258             : #endif
    4259           0 :                         sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
    4260             :                                         SCTP_CALLED_DIRECTLY_NOCMPSET);
    4261             : #if defined(__APPLE__)
    4262             :                         SCTP_SOCKET_UNLOCK(SCTP_INP_SO(inp), 1);
    4263             : #endif
    4264             :                 }
    4265             :         }
    4266           0 :         contains_init_chunk = 0;
    4267           0 :         ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset,
    4268             :             sizeof(*ch), (uint8_t *) & chunk_buf);
    4269           0 :         while (ch != NULL) {
    4270           0 :                 chk_length = ntohs(ch->chunk_length);
    4271           0 :                 if (chk_length < sizeof(*ch)) {
    4272             :                         /* break to abort land */
    4273           0 :                         break;
    4274             :                 }
    4275           0 :                 switch (ch->chunk_type) {
    4276             :                 case SCTP_INIT:
    4277           0 :                         contains_init_chunk = 1;
    4278           0 :                         break;
    4279             :                 case SCTP_PACKET_DROPPED:
    4280             :                         /* we don't respond to pkt-dropped */
    4281           0 :                         return;
    4282             :                 case SCTP_ABORT_ASSOCIATION:
    4283             :                         /* we don't respond with an ABORT to an ABORT */
    4284           0 :                         return;
    4285             :                 case SCTP_SHUTDOWN_COMPLETE:
    4286             :                         /*
    4287             :                          * we ignore it since we are not waiting for it and
    4288             :                          * peer is gone
    4289             :                          */
    4290           0 :                         return;
    4291             :                 case SCTP_SHUTDOWN_ACK:
    4292           0 :                         sctp_send_shutdown_complete2(src, dst, sh,
    4293             : #if defined(__FreeBSD__)
    4294             :                                                      mflowtype, mflowid,
    4295             : #endif
    4296             :                                                      vrf_id, port);
    4297           0 :                         return;
    4298             :                 default:
    4299           0 :                         break;
    4300             :                 }
    4301           0 :                 offset += SCTP_SIZE32(chk_length);
    4302           0 :                 ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset,
    4303             :                     sizeof(*ch), (uint8_t *) & chunk_buf);
    4304             :         }
    4305           0 :         if ((SCTP_BASE_SYSCTL(sctp_blackhole) == 0) ||
    4306           0 :             ((SCTP_BASE_SYSCTL(sctp_blackhole) == 1) &&
    4307             :              (contains_init_chunk == 0))) {
    4308           0 :                 sctp_send_abort(m, iphlen, src, dst, sh, 0, cause,
    4309             : #if defined(__FreeBSD__)
    4310             :                                 mflowtype, mflowid,
    4311             : #endif
    4312             :                                 vrf_id, port);
    4313             :         }
    4314             : }
    4315             : 
    4316             : /*
    4317             :  * check the inbound datagram to make sure there is not an abort inside it,
    4318             :  * if there is return 1, else return 0.
    4319             :  */
    4320             : int
    4321           0 : sctp_is_there_an_abort_here(struct mbuf *m, int iphlen, uint32_t * vtagfill)
    4322             : {
    4323             :         struct sctp_chunkhdr *ch;
    4324             :         struct sctp_init_chunk *init_chk, chunk_buf;
    4325             :         int offset;
    4326             :         unsigned int chk_length;
    4327             : 
    4328           0 :         offset = iphlen + sizeof(struct sctphdr);
    4329           0 :         ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset, sizeof(*ch),
    4330             :             (uint8_t *) & chunk_buf);
    4331           0 :         while (ch != NULL) {
    4332           0 :                 chk_length = ntohs(ch->chunk_length);
    4333           0 :                 if (chk_length < sizeof(*ch)) {
    4334             :                         /* packet is probably corrupt */
    4335           0 :                         break;
    4336             :                 }
    4337             :                 /* we seem to be ok, is it an abort? */
    4338           0 :                 if (ch->chunk_type == SCTP_ABORT_ASSOCIATION) {
    4339             :                         /* yep, tell them */
    4340           0 :                         return (1);
    4341             :                 }
    4342           0 :                 if (ch->chunk_type == SCTP_INITIATION) {
    4343             :                         /* need to update the Vtag */
    4344           0 :                         init_chk = (struct sctp_init_chunk *)sctp_m_getptr(m,
    4345             :                             offset, sizeof(*init_chk), (uint8_t *) & chunk_buf);
    4346           0 :                         if (init_chk != NULL) {
    4347           0 :                                 *vtagfill = ntohl(init_chk->init.initiate_tag);
    4348             :                         }
    4349             :                 }
    4350             :                 /* Nope, move to the next chunk */
    4351           0 :                 offset += SCTP_SIZE32(chk_length);
    4352           0 :                 ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset,
    4353             :                     sizeof(*ch), (uint8_t *) & chunk_buf);
    4354             :         }
    4355           0 :         return (0);
    4356             : }
    4357             : 
    4358             : /*
    4359             :  * currently (2/02), ifa_addr embeds scope_id's and don't have sin6_scope_id
    4360             :  * set (i.e. it's 0) so, create this function to compare link local scopes
    4361             :  */
    4362             : #ifdef INET6
    4363             : uint32_t
    4364             : sctp_is_same_scope(struct sockaddr_in6 *addr1, struct sockaddr_in6 *addr2)
    4365             : {
    4366             : #if defined(__Userspace__)
    4367             :     /*__Userspace__ Returning 1 here always */
    4368             : #endif
    4369             : #if defined(SCTP_EMBEDDED_V6_SCOPE)
    4370             :         struct sockaddr_in6 a, b;
    4371             : 
    4372             :         /* save copies */
    4373             :         a = *addr1;
    4374             :         b = *addr2;
    4375             : 
    4376             :         if (a.sin6_scope_id == 0)
    4377             : #ifdef SCTP_KAME
    4378             :                 if (sa6_recoverscope(&a)) {
    4379             : #else
    4380             :                 if (in6_recoverscope(&a, &a.sin6_addr, NULL)) {
    4381             : #endif                          /* SCTP_KAME */
    4382             :                         /* can't get scope, so can't match */
    4383             :                         return (0);
    4384             :                 }
    4385             :         if (b.sin6_scope_id == 0)
    4386             : #ifdef SCTP_KAME
    4387             :                 if (sa6_recoverscope(&b)) {
    4388             : #else
    4389             :                 if (in6_recoverscope(&b, &b.sin6_addr, NULL)) {
    4390             : #endif                          /* SCTP_KAME */
    4391             :                         /* can't get scope, so can't match */
    4392             :                         return (0);
    4393             :                 }
    4394             :         if (a.sin6_scope_id != b.sin6_scope_id)
    4395             :                 return (0);
    4396             : #else
    4397             :         if (addr1->sin6_scope_id != addr2->sin6_scope_id)
    4398             :                 return (0);
    4399             : #endif /* SCTP_EMBEDDED_V6_SCOPE */
    4400             : 
    4401             :         return (1);
    4402             : }
    4403             : 
    4404             : #if defined(SCTP_EMBEDDED_V6_SCOPE)
    4405             : /*
    4406             :  * returns a sockaddr_in6 with embedded scope recovered and removed
    4407             :  */
    4408             : struct sockaddr_in6 *
    4409             : sctp_recover_scope(struct sockaddr_in6 *addr, struct sockaddr_in6 *store)
    4410             : {
    4411             :         /* check and strip embedded scope junk */
    4412             :         if (addr->sin6_family == AF_INET6) {
    4413             :                 if (IN6_IS_SCOPE_LINKLOCAL(&addr->sin6_addr)) {
    4414             :                         if (addr->sin6_scope_id == 0) {
    4415             :                                 *store = *addr;
    4416             : #ifdef SCTP_KAME
    4417             :                                 if (!sa6_recoverscope(store)) {
    4418             : #else
    4419             :                                 if (!in6_recoverscope(store, &store->sin6_addr,
    4420             :                                     NULL)) {
    4421             : #endif /* SCTP_KAME */
    4422             :                                         /* use the recovered scope */
    4423             :                                         addr = store;
    4424             :                                 }
    4425             :                         } else {
    4426             :                                 /* else, return the original "to" addr */
    4427             :                                 in6_clearscope(&addr->sin6_addr);
    4428             :                         }
    4429             :                 }
    4430             :         }
    4431             :         return (addr);
    4432             : }
    4433             : #endif /* SCTP_EMBEDDED_V6_SCOPE */
    4434             : #endif
    4435             : 
    4436             : /*
    4437             :  * are the two addresses the same?  currently a "scopeless" check returns: 1
    4438             :  * if same, 0 if not
    4439             :  */
    4440             : int
    4441           0 : sctp_cmpaddr(struct sockaddr *sa1, struct sockaddr *sa2)
    4442             : {
    4443             : 
    4444             :         /* must be valid */
    4445           0 :         if (sa1 == NULL || sa2 == NULL)
    4446           0 :                 return (0);
    4447             : 
    4448             :         /* must be the same family */
    4449           0 :         if (sa1->sa_family != sa2->sa_family)
    4450           0 :                 return (0);
    4451             : 
    4452           0 :         switch (sa1->sa_family) {
    4453             : #ifdef INET6
    4454             :         case AF_INET6:
    4455             :         {
    4456             :                 /* IPv6 addresses */
    4457             :                 struct sockaddr_in6 *sin6_1, *sin6_2;
    4458             : 
    4459             :                 sin6_1 = (struct sockaddr_in6 *)sa1;
    4460             :                 sin6_2 = (struct sockaddr_in6 *)sa2;
    4461             :                 return (SCTP6_ARE_ADDR_EQUAL(sin6_1,
    4462             :                     sin6_2));
    4463             :         }
    4464             : #endif
    4465             : #ifdef INET
    4466             :         case AF_INET:
    4467             :         {
    4468             :                 /* IPv4 addresses */
    4469             :                 struct sockaddr_in *sin_1, *sin_2;
    4470             : 
    4471             :                 sin_1 = (struct sockaddr_in *)sa1;
    4472             :                 sin_2 = (struct sockaddr_in *)sa2;
    4473             :                 return (sin_1->sin_addr.s_addr == sin_2->sin_addr.s_addr);
    4474             :         }
    4475             : #endif
    4476             : #if defined(__Userspace__)
    4477             :         case AF_CONN:
    4478             :         {
    4479             :                 struct sockaddr_conn *sconn_1, *sconn_2;
    4480             : 
    4481           0 :                 sconn_1 = (struct sockaddr_conn *)sa1;
    4482           0 :                 sconn_2 = (struct sockaddr_conn *)sa2;
    4483           0 :                 return (sconn_1->sconn_addr == sconn_2->sconn_addr);
    4484             :         }
    4485             : #endif
    4486             :         default:
    4487             :                 /* we don't do these... */
    4488           0 :                 return (0);
    4489             :         }
    4490             : }
    4491             : 
    4492             : void
    4493           0 : sctp_print_address(struct sockaddr *sa)
    4494             : {
    4495             : #ifdef INET6
    4496             : #if defined(__FreeBSD__) && __FreeBSD_version >= 700000
    4497             :         char ip6buf[INET6_ADDRSTRLEN];
    4498             : #endif
    4499             : #endif
    4500             : 
    4501           0 :         switch (sa->sa_family) {
    4502             : #ifdef INET6
    4503             :         case AF_INET6:
    4504             :         {
    4505             :                 struct sockaddr_in6 *sin6;
    4506             : 
    4507             :                 sin6 = (struct sockaddr_in6 *)sa;
    4508             : #if defined(__Userspace__)
    4509             :                 SCTP_PRINTF("IPv6 address: %x:%x:%x:%x:%x:%x:%x:%x:port:%d scope:%u\n",
    4510             :                             ntohs(sin6->sin6_addr.s6_addr16[0]),
    4511             :                             ntohs(sin6->sin6_addr.s6_addr16[1]),
    4512             :                             ntohs(sin6->sin6_addr.s6_addr16[2]),
    4513             :                             ntohs(sin6->sin6_addr.s6_addr16[3]),
    4514             :                             ntohs(sin6->sin6_addr.s6_addr16[4]),
    4515             :                             ntohs(sin6->sin6_addr.s6_addr16[5]),
    4516             :                             ntohs(sin6->sin6_addr.s6_addr16[6]),
    4517             :                             ntohs(sin6->sin6_addr.s6_addr16[7]),
    4518             :                             ntohs(sin6->sin6_port),
    4519             :                             sin6->sin6_scope_id);
    4520             : #else
    4521             : #if defined(__FreeBSD__) && __FreeBSD_version >= 700000
    4522             :                 SCTP_PRINTF("IPv6 address: %s:port:%d scope:%u\n",
    4523             :                             ip6_sprintf(ip6buf, &sin6->sin6_addr),
    4524             :                             ntohs(sin6->sin6_port),
    4525             :                             sin6->sin6_scope_id);
    4526             : #else
    4527             :                 SCTP_PRINTF("IPv6 address: %s:port:%d scope:%u\n",
    4528             :                             ip6_sprintf(&sin6->sin6_addr),
    4529             :                             ntohs(sin6->sin6_port),
    4530             :                             sin6->sin6_scope_id);
    4531             : #endif
    4532             : #endif
    4533             :                 break;
    4534             :         }
    4535             : #endif
    4536             : #ifdef INET
    4537             :         case AF_INET:
    4538             :         {
    4539             :                 struct sockaddr_in *sin;
    4540             :                 unsigned char *p;
    4541             : 
    4542             :                 sin = (struct sockaddr_in *)sa;
    4543             :                 p = (unsigned char *)&sin->sin_addr;
    4544             :                 SCTP_PRINTF("IPv4 address: %u.%u.%u.%u:%d\n",
    4545             :                             p[0], p[1], p[2], p[3], ntohs(sin->sin_port));
    4546             :                 break;
    4547             :         }
    4548             : #endif
    4549             : #if defined(__Userspace__)
    4550             :         case AF_CONN:
    4551             :         {
    4552             :                 struct sockaddr_conn *sconn;
    4553             : 
    4554           0 :                 sconn = (struct sockaddr_conn *)sa;
    4555           0 :                 SCTP_PRINTF("AF_CONN address: %p\n", sconn->sconn_addr);
    4556           0 :                 break;
    4557             :         }
    4558             : #endif
    4559             :         default:
    4560           0 :                 SCTP_PRINTF("?\n");
    4561           0 :                 break;
    4562             :         }
    4563           0 : }
    4564             : 
    4565             : void
    4566           0 : sctp_pull_off_control_to_new_inp(struct sctp_inpcb *old_inp,
    4567             :     struct sctp_inpcb *new_inp,
    4568             :     struct sctp_tcb *stcb,
    4569             :     int waitflags)
    4570             : {
    4571             :         /*
    4572             :          * go through our old INP and pull off any control structures that
    4573             :          * belong to stcb and move then to the new inp.
    4574             :          */
    4575             :         struct socket *old_so, *new_so;
    4576             :         struct sctp_queued_to_read *control, *nctl;
    4577             :         struct sctp_readhead tmp_queue;
    4578             :         struct mbuf *m;
    4579           0 :         int error = 0;
    4580             : 
    4581           0 :         old_so = old_inp->sctp_socket;
    4582           0 :         new_so = new_inp->sctp_socket;
    4583           0 :         TAILQ_INIT(&tmp_queue);
    4584             : #if defined(__FreeBSD__) && __FreeBSD_version < 700000
    4585             :         SOCKBUF_LOCK(&(old_so->so_rcv));
    4586             : #endif
    4587             : #if defined(__FreeBSD__) || defined(__APPLE__)
    4588             :         error = sblock(&old_so->so_rcv, waitflags);
    4589             : #endif
    4590             : #if defined(__FreeBSD__) && __FreeBSD_version < 700000
    4591             :         SOCKBUF_UNLOCK(&(old_so->so_rcv));
    4592             : #endif
    4593           0 :         if (error) {
    4594             :                 /* Gak, can't get sblock, we have a problem.
    4595             :                  * data will be left stranded.. and we
    4596             :                  * don't dare look at it since the
    4597             :                  * other thread may be reading something.
    4598             :                  * Oh well, its a screwed up app that does
    4599             :                  * a peeloff OR a accept while reading
    4600             :                  * from the main socket... actually its
    4601             :                  * only the peeloff() case, since I think
    4602             :                  * read will fail on a listening socket..
    4603             :                  */
    4604           0 :                 return;
    4605             :         }
    4606             :         /* lock the socket buffers */
    4607           0 :         SCTP_INP_READ_LOCK(old_inp);
    4608           0 :         TAILQ_FOREACH_SAFE(control, &old_inp->read_queue, next, nctl) {
    4609             :                 /* Pull off all for out target stcb */
    4610           0 :                 if (control->stcb == stcb) {
    4611             :                         /* remove it we want it */
    4612           0 :                         TAILQ_REMOVE(&old_inp->read_queue, control, next);
    4613           0 :                         TAILQ_INSERT_TAIL(&tmp_queue, control, next);
    4614           0 :                         m = control->data;
    4615           0 :                         while (m) {
    4616           0 :                                 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
    4617           0 :                                         sctp_sblog(&old_so->so_rcv, control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBFREE,SCTP_BUF_LEN(m));
    4618             :                                 }
    4619           0 :                                 sctp_sbfree(control, stcb, &old_so->so_rcv, m);
    4620           0 :                                 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
    4621           0 :                                         sctp_sblog(&old_so->so_rcv, control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBRESULT, 0);
    4622             :                                 }
    4623           0 :                                 m = SCTP_BUF_NEXT(m);
    4624             :                         }
    4625             :                 }
    4626             :         }
    4627           0 :         SCTP_INP_READ_UNLOCK(old_inp);
    4628             :         /* Remove the sb-lock on the old socket */
    4629             : #if defined(__FreeBSD__) && __FreeBSD_version < 700000
    4630             :         SOCKBUF_LOCK(&(old_so->so_rcv));
    4631             : #endif
    4632             : #if defined(__APPLE__)
    4633             :         sbunlock(&old_so->so_rcv, 1);
    4634             : #endif
    4635             : 
    4636             : #if defined(__FreeBSD__)
    4637             :         sbunlock(&old_so->so_rcv);
    4638             : #endif
    4639             : #if defined(__FreeBSD__) && __FreeBSD_version < 700000
    4640             :         SOCKBUF_UNLOCK(&(old_so->so_rcv));
    4641             : #endif
    4642             :         /* Now we move them over to the new socket buffer */
    4643           0 :         SCTP_INP_READ_LOCK(new_inp);
    4644           0 :         TAILQ_FOREACH_SAFE(control, &tmp_queue, next, nctl) {
    4645           0 :                 TAILQ_INSERT_TAIL(&new_inp->read_queue, control, next);
    4646           0 :                 m = control->data;
    4647           0 :                 while (m) {
    4648           0 :                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
    4649           0 :                                 sctp_sblog(&new_so->so_rcv, control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBALLOC, SCTP_BUF_LEN(m));
    4650             :                         }
    4651           0 :                         sctp_sballoc(stcb, &new_so->so_rcv, m);
    4652           0 :                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
    4653           0 :                                 sctp_sblog(&new_so->so_rcv, control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBRESULT, 0);
    4654             :                         }
    4655           0 :                         m = SCTP_BUF_NEXT(m);
    4656             :                 }
    4657             :         }
    4658           0 :         SCTP_INP_READ_UNLOCK(new_inp);
    4659             : }
    4660             : 
    4661             : void
    4662           0 : sctp_add_to_readq(struct sctp_inpcb *inp,
    4663             :     struct sctp_tcb *stcb,
    4664             :     struct sctp_queued_to_read *control,
    4665             :     struct sockbuf *sb,
    4666             :     int end,
    4667             :     int inp_read_lock_held,
    4668             :     int so_locked
    4669             : #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
    4670             :     SCTP_UNUSED
    4671             : #endif
    4672             :     )
    4673             : {
    4674             :         /*
    4675             :          * Here we must place the control on the end of the socket read
    4676             :          * queue AND increment sb_cc so that select will work properly on
    4677             :          * read.
    4678             :          */
    4679           0 :         struct mbuf *m, *prev = NULL;
    4680             : 
    4681           0 :         if (inp == NULL) {
    4682             :                 /* Gak, TSNH!! */
    4683             : #ifdef INVARIANTS
    4684             :                 panic("Gak, inp NULL on add_to_readq");
    4685             : #endif
    4686           0 :                 return;
    4687             :         }
    4688             : #if defined(__APPLE__)
    4689             :         if (so_locked) {
    4690             :                 sctp_lock_assert(SCTP_INP_SO(inp));
    4691             :         } else {
    4692             :                 sctp_unlock_assert(SCTP_INP_SO(inp));
    4693             :         }
    4694             : #endif
    4695           0 :         if (inp_read_lock_held == 0)
    4696           0 :                 SCTP_INP_READ_LOCK(inp);
    4697           0 :         if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_CANT_READ) {
    4698           0 :                 sctp_free_remote_addr(control->whoFrom);
    4699           0 :                 if (control->data) {
    4700           0 :                         sctp_m_freem(control->data);
    4701           0 :                         control->data = NULL;
    4702             :                 }
    4703           0 :                 SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), control);
    4704           0 :                 if (inp_read_lock_held == 0)
    4705           0 :                         SCTP_INP_READ_UNLOCK(inp);
    4706           0 :                 return;
    4707             :         }
    4708           0 :         if (!(control->spec_flags & M_NOTIFICATION)) {
    4709           0 :                 atomic_add_int(&inp->total_recvs, 1);
    4710           0 :                 if (!control->do_not_ref_stcb) {
    4711           0 :                         atomic_add_int(&stcb->total_recvs, 1);
    4712             :                 }
    4713             :         }
    4714           0 :         m = control->data;
    4715           0 :         control->held_length = 0;
    4716           0 :         control->length = 0;
    4717           0 :         while (m) {
    4718           0 :                 if (SCTP_BUF_LEN(m) == 0) {
    4719             :                         /* Skip mbufs with NO length */
    4720           0 :                         if (prev == NULL) {
    4721             :                                 /* First one */
    4722           0 :                                 control->data = sctp_m_free(m);
    4723           0 :                                 m = control->data;
    4724             :                         } else {
    4725           0 :                                 SCTP_BUF_NEXT(prev) = sctp_m_free(m);
    4726           0 :                                 m = SCTP_BUF_NEXT(prev);
    4727             :                         }
    4728           0 :                         if (m == NULL) {
    4729           0 :                                 control->tail_mbuf = prev;
    4730             :                         }
    4731           0 :                         continue;
    4732             :                 }
    4733           0 :                 prev = m;
    4734           0 :                 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
    4735           0 :                         sctp_sblog(sb, control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBALLOC, SCTP_BUF_LEN(m));
    4736             :                 }
    4737           0 :                 sctp_sballoc(stcb, sb, m);
    4738           0 :                 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
    4739           0 :                         sctp_sblog(sb, control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBRESULT, 0);
    4740             :                 }
    4741           0 :                 atomic_add_int(&control->length, SCTP_BUF_LEN(m));
    4742           0 :                 m = SCTP_BUF_NEXT(m);
    4743             :         }
    4744           0 :         if (prev != NULL) {
    4745           0 :                 control->tail_mbuf = prev;
    4746             :         } else {
    4747             :                 /* Everything got collapsed out?? */
    4748           0 :                 sctp_free_remote_addr(control->whoFrom);
    4749           0 :                 SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), control);
    4750           0 :                 if (inp_read_lock_held == 0)
    4751           0 :                         SCTP_INP_READ_UNLOCK(inp);
    4752           0 :                 return;
    4753             :         }
    4754           0 :         if (end) {
    4755           0 :                 control->end_added = 1;
    4756             :         }
    4757             : #if defined(__Userspace__)
    4758           0 :         if (inp->recv_callback) {
    4759           0 :                 if (inp_read_lock_held == 0)
    4760           0 :                         SCTP_INP_READ_UNLOCK(inp);
    4761           0 :                 if (control->end_added == 1) {
    4762             :                         struct socket *so;
    4763             :                         struct mbuf *m;
    4764             :                         char *buffer;
    4765             :                         struct sctp_rcvinfo rcv;
    4766             :                         union sctp_sockstore addr;
    4767             :                         int flags;
    4768             : 
    4769           0 :                         if ((buffer = malloc(control->length)) == NULL) {
    4770           0 :                                 return;
    4771             :                         }
    4772           0 :                         so = stcb->sctp_socket;
    4773           0 :                         for (m = control->data; m; m = SCTP_BUF_NEXT(m)) {
    4774           0 :                                 sctp_sbfree(control, control->stcb, &so->so_rcv, m);
    4775             :                         }
    4776           0 :                         atomic_add_int(&stcb->asoc.refcnt, 1);
    4777           0 :                         SCTP_TCB_UNLOCK(stcb);
    4778           0 :                         m_copydata(control->data, 0, control->length, buffer);
    4779           0 :                         memset(&rcv, 0, sizeof(struct sctp_rcvinfo));
    4780           0 :                         rcv.rcv_sid = control->sinfo_stream;
    4781           0 :                         rcv.rcv_ssn = control->sinfo_ssn;
    4782           0 :                         rcv.rcv_flags = control->sinfo_flags;
    4783           0 :                         rcv.rcv_ppid = control->sinfo_ppid;
    4784           0 :                         rcv.rcv_tsn = control->sinfo_tsn;
    4785           0 :                         rcv.rcv_cumtsn = control->sinfo_cumtsn;
    4786           0 :                         rcv.rcv_context = control->sinfo_context;
    4787           0 :                         rcv.rcv_assoc_id = control->sinfo_assoc_id;
    4788           0 :                         memset(&addr, 0, sizeof(union sctp_sockstore));
    4789           0 :                         switch (control->whoFrom->ro._l_addr.sa.sa_family) {
    4790             : #ifdef INET
    4791             :                         case AF_INET:
    4792             :                                 addr.sin = control->whoFrom->ro._l_addr.sin;
    4793             :                                 break;
    4794             : #endif
    4795             : #ifdef INET6
    4796             :                         case AF_INET6:
    4797             :                                 addr.sin6 = control->whoFrom->ro._l_addr.sin6;
    4798             :                                 break;
    4799             : #endif
    4800             :                         case AF_CONN:
    4801           0 :                                 addr.sconn = control->whoFrom->ro._l_addr.sconn;
    4802           0 :                                 break;
    4803             :                         default:
    4804           0 :                                 addr.sa = control->whoFrom->ro._l_addr.sa;
    4805           0 :                                 break;
    4806             :                         }
    4807           0 :                         flags = MSG_EOR;
    4808           0 :                         if (control->spec_flags & M_NOTIFICATION) {
    4809           0 :                                 flags |= MSG_NOTIFICATION;
    4810             :                         }
    4811           0 :                         inp->recv_callback(so, addr, buffer, control->length, rcv, flags, inp->ulp_info);
    4812           0 :                         SCTP_TCB_LOCK(stcb);
    4813           0 :                         atomic_subtract_int(&stcb->asoc.refcnt, 1);
    4814           0 :                         sctp_free_remote_addr(control->whoFrom);
    4815           0 :                         control->whoFrom = NULL;
    4816           0 :                         sctp_m_freem(control->data);
    4817           0 :                         control->data = NULL;
    4818           0 :                         control->length = 0;
    4819           0 :                         sctp_free_a_readq(stcb, control);
    4820             :                 }
    4821           0 :                 return;
    4822             :         }
    4823             : #endif
    4824           0 :         TAILQ_INSERT_TAIL(&inp->read_queue, control, next);
    4825           0 :         if (inp_read_lock_held == 0)
    4826           0 :                 SCTP_INP_READ_UNLOCK(inp);
    4827           0 :         if (inp && inp->sctp_socket) {
    4828           0 :                 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) {
    4829             :                         SCTP_ZERO_COPY_EVENT(inp, inp->sctp_socket);
    4830             :                 } else {
    4831             : #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
    4832             :                         struct socket *so;
    4833             : 
    4834             :                         so = SCTP_INP_SO(inp);
    4835             :                         if (!so_locked) {
    4836             :                                 if (stcb) {
    4837             :                                         atomic_add_int(&stcb->asoc.refcnt, 1);
    4838             :                                         SCTP_TCB_UNLOCK(stcb);
    4839             :                                 }
    4840             :                                 SCTP_SOCKET_LOCK(so, 1);
    4841             :                                 if (stcb) {
    4842             :                                         SCTP_TCB_LOCK(stcb);
    4843             :                                         atomic_subtract_int(&stcb->asoc.refcnt, 1);
    4844             :                                 }
    4845             :                                 if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
    4846             :                                         SCTP_SOCKET_UNLOCK(so, 1);
    4847             :                                         return;
    4848             :                                 }
    4849             :                         }
    4850             : #endif
    4851           0 :                         sctp_sorwakeup(inp, inp->sctp_socket);
    4852             : #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
    4853             :                         if (!so_locked) {
    4854             :                                 SCTP_SOCKET_UNLOCK(so, 1);
    4855             :                         }
    4856             : #endif
    4857             :                 }
    4858             :         }
    4859             : }
    4860             : 
    4861             : 
    4862             : int
    4863           0 : sctp_append_to_readq(struct sctp_inpcb *inp,
    4864             :     struct sctp_tcb *stcb,
    4865             :     struct sctp_queued_to_read *control,
    4866             :     struct mbuf *m,
    4867             :     int end,
    4868             :     int ctls_cumack,
    4869             :     struct sockbuf *sb)
    4870             : {
    4871             :         /*
    4872             :          * A partial delivery API event is underway. OR we are appending on
    4873             :          * the reassembly queue.
    4874             :          *
    4875             :          * If PDAPI this means we need to add m to the end of the data.
    4876             :          * Increase the length in the control AND increment the sb_cc.
    4877             :          * Otherwise sb is NULL and all we need to do is put it at the end
    4878             :          * of the mbuf chain.
    4879             :          */
    4880           0 :         int len = 0;
    4881           0 :         struct mbuf *mm, *tail = NULL, *prev = NULL;
    4882             : 
    4883           0 :         if (inp) {
    4884           0 :                 SCTP_INP_READ_LOCK(inp);
    4885             :         }
    4886           0 :         if (control == NULL) {
    4887             :         get_out:
    4888           0 :                 if (inp) {
    4889           0 :                         SCTP_INP_READ_UNLOCK(inp);
    4890             :                 }
    4891           0 :                 return (-1);
    4892             :         }
    4893           0 :         if (inp && (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_CANT_READ)) {
    4894           0 :                 SCTP_INP_READ_UNLOCK(inp);
    4895           0 :                 return (0);
    4896             :         }
    4897           0 :         if (control->end_added) {
    4898             :                 /* huh this one is complete? */
    4899           0 :                 goto get_out;
    4900             :         }
    4901           0 :         mm = m;
    4902           0 :         if (mm == NULL) {
    4903           0 :                 goto get_out;
    4904             :         }
    4905             : 
    4906           0 :         while (mm) {
    4907           0 :                 if (SCTP_BUF_LEN(mm) == 0) {
    4908             :                         /* Skip mbufs with NO lenght */
    4909           0 :                         if (prev == NULL) {
    4910             :                                 /* First one */
    4911           0 :                                 m = sctp_m_free(mm);
    4912           0 :                                 mm = m;
    4913             :                         } else {
    4914           0 :                                 SCTP_BUF_NEXT(prev) = sctp_m_free(mm);
    4915           0 :                                 mm = SCTP_BUF_NEXT(prev);
    4916             :                         }
    4917           0 :                         continue;
    4918             :                 }
    4919           0 :                 prev = mm;
    4920           0 :                 len += SCTP_BUF_LEN(mm);
    4921           0 :                 if (sb) {
    4922           0 :                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
    4923           0 :                                 sctp_sblog(sb, control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBALLOC, SCTP_BUF_LEN(mm));
    4924             :                         }
    4925           0 :                         sctp_sballoc(stcb, sb, mm);
    4926           0 :                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
    4927           0 :                                 sctp_sblog(sb, control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBRESULT, 0);
    4928             :                         }
    4929             :                 }
    4930           0 :                 mm = SCTP_BUF_NEXT(mm);
    4931             :         }
    4932           0 :         if (prev) {
    4933           0 :                 tail = prev;
    4934             :         } else {
    4935             :                 /* Really there should always be a prev */
    4936           0 :                 if (m == NULL) {
    4937             :                         /* Huh nothing left? */
    4938             : #ifdef INVARIANTS
    4939             :                         panic("Nothing left to add?");
    4940             : #else
    4941           0 :                         goto get_out;
    4942             : #endif
    4943             :                 }
    4944           0 :                 tail = m;
    4945             :         }
    4946           0 :         if (control->tail_mbuf) {
    4947             :                 /* append */
    4948           0 :                 SCTP_BUF_NEXT(control->tail_mbuf) = m;
    4949           0 :                 control->tail_mbuf = tail;
    4950             :         } else {
    4951             :                 /* nothing there */
    4952             : #ifdef INVARIANTS
    4953             :                 if (control->data != NULL) {
    4954             :                         panic("This should NOT happen");
    4955             :                 }
    4956             : #endif
    4957           0 :                 control->data = m;
    4958           0 :                 control->tail_mbuf = tail;
    4959             :         }
    4960           0 :         atomic_add_int(&control->length, len);
    4961           0 :         if (end) {
    4962             :                 /* message is complete */
    4963           0 :                 if (stcb && (control == stcb->asoc.control_pdapi)) {
    4964           0 :                         stcb->asoc.control_pdapi = NULL;
    4965             :                 }
    4966           0 :                 control->held_length = 0;
    4967           0 :                 control->end_added = 1;
    4968             :         }
    4969           0 :         if (stcb == NULL) {
    4970           0 :                 control->do_not_ref_stcb = 1;
    4971             :         }
    4972             :         /*
    4973             :          * When we are appending in partial delivery, the cum-ack is used
    4974             :          * for the actual pd-api highest tsn on this mbuf. The true cum-ack
    4975             :          * is populated in the outbound sinfo structure from the true cumack
    4976             :          * if the association exists...
    4977             :          */
    4978           0 :         control->sinfo_tsn = control->sinfo_cumtsn = ctls_cumack;
    4979             : #if defined(__Userspace__)
    4980           0 :         if (inp->recv_callback) {
    4981             :                 uint32_t pd_point, length;
    4982             : 
    4983           0 :                 length = control->length;
    4984           0 :                 if (stcb != NULL && stcb->sctp_socket != NULL) {
    4985           0 :                         pd_point = min(SCTP_SB_LIMIT_RCV(stcb->sctp_socket) >> SCTP_PARTIAL_DELIVERY_SHIFT,
    4986             :                                        stcb->sctp_ep->partial_delivery_point);
    4987             :                 } else {
    4988           0 :                         pd_point = inp->partial_delivery_point;
    4989             :                 }
    4990           0 :                 if ((control->end_added == 1) || (length >= pd_point)) {
    4991             :                         struct socket *so;
    4992             :                         char *buffer;
    4993             :                         struct sctp_rcvinfo rcv;
    4994             :                         union sctp_sockstore addr;
    4995             :                         int flags;
    4996             : 
    4997           0 :                         if ((buffer = malloc(control->length)) == NULL) {
    4998           0 :                                 return (-1);
    4999             :                         }
    5000           0 :                         so = stcb->sctp_socket;
    5001           0 :                         for (m = control->data; m; m = SCTP_BUF_NEXT(m)) {
    5002           0 :                                 sctp_sbfree(control, control->stcb, &so->so_rcv, m);
    5003             :                         }
    5004           0 :                         m_copydata(control->data, 0, control->length, buffer);
    5005           0 :                         memset(&rcv, 0, sizeof(struct sctp_rcvinfo));
    5006           0 :                         rcv.rcv_sid = control->sinfo_stream;
    5007           0 :                         rcv.rcv_ssn = control->sinfo_ssn;
    5008           0 :                         rcv.rcv_flags = control->sinfo_flags;
    5009           0 :                         rcv.rcv_ppid = control->sinfo_ppid;
    5010           0 :                         rcv.rcv_tsn = control->sinfo_tsn;
    5011           0 :                         rcv.rcv_cumtsn = control->sinfo_cumtsn;
    5012           0 :                         rcv.rcv_context = control->sinfo_context;
    5013           0 :                         rcv.rcv_assoc_id = control->sinfo_assoc_id;
    5014           0 :                         memset(&addr, 0, sizeof(union sctp_sockstore));
    5015           0 :                         switch (control->whoFrom->ro._l_addr.sa.sa_family) {
    5016             : #ifdef INET
    5017             :                         case AF_INET:
    5018             :                                 addr.sin = control->whoFrom->ro._l_addr.sin;
    5019             :                                 break;
    5020             : #endif
    5021             : #ifdef INET6
    5022             :                         case AF_INET6:
    5023             :                                 addr.sin6 = control->whoFrom->ro._l_addr.sin6;
    5024             :                                 break;
    5025             : #endif
    5026             :                         case AF_CONN:
    5027           0 :                                 addr.sconn = control->whoFrom->ro._l_addr.sconn;
    5028           0 :                                 break;
    5029             :                         default:
    5030           0 :                                 addr.sa = control->whoFrom->ro._l_addr.sa;
    5031           0 :                                 break;
    5032             :                         }
    5033           0 :                         flags = 0;
    5034           0 :                         if (control->end_added == 1) {
    5035           0 :                                 flags |= MSG_EOR;
    5036             :                         }
    5037           0 :                         if (control->spec_flags & M_NOTIFICATION) {
    5038           0 :                                 flags |= MSG_NOTIFICATION;
    5039             :                         }
    5040           0 :                         sctp_m_freem(control->data);
    5041           0 :                         control->data = NULL;
    5042           0 :                         control->tail_mbuf = NULL;
    5043           0 :                         control->length = 0;
    5044           0 :                         if (control->end_added) {
    5045           0 :                                 sctp_free_remote_addr(control->whoFrom);
    5046           0 :                                 control->whoFrom = NULL;
    5047           0 :                                 sctp_free_a_readq(stcb, control);
    5048             :                         } else {
    5049           0 :                                 control->some_taken = 1;
    5050             :                         }
    5051           0 :                         atomic_add_int(&stcb->asoc.refcnt, 1);
    5052           0 :                         SCTP_TCB_UNLOCK(stcb);
    5053           0 :                         inp->recv_callback(so, addr, buffer, length, rcv, flags, inp->ulp_info);
    5054           0 :                         SCTP_TCB_LOCK(stcb);
    5055           0 :                         atomic_subtract_int(&stcb->asoc.refcnt, 1);
    5056             :                 }
    5057           0 :                 if (inp)
    5058           0 :                         SCTP_INP_READ_UNLOCK(inp);
    5059           0 :                 return (0);
    5060             :         }
    5061             : #endif
    5062           0 :         if (inp) {
    5063           0 :                 SCTP_INP_READ_UNLOCK(inp);
    5064             :         }
    5065           0 :         if (inp && inp->sctp_socket) {
    5066           0 :                 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) {
    5067             :                         SCTP_ZERO_COPY_EVENT(inp, inp->sctp_socket);
    5068             :                 } else {
    5069             : #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
    5070             :                         struct socket *so;
    5071             : 
    5072             :                         so = SCTP_INP_SO(inp);
    5073             :                         if (stcb) {
    5074             :                                 atomic_add_int(&stcb->asoc.refcnt, 1);
    5075             :                                 SCTP_TCB_UNLOCK(stcb);
    5076             :                         }
    5077             :                         SCTP_SOCKET_LOCK(so, 1);
    5078             :                         if (stcb) {
    5079             :                                 SCTP_TCB_LOCK(stcb);
    5080             :                                 atomic_subtract_int(&stcb->asoc.refcnt, 1);
    5081             :                         }
    5082             :                         if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
    5083             :                                 SCTP_SOCKET_UNLOCK(so, 1);
    5084             :                                 return (0);
    5085             :                         }
    5086             : #endif
    5087           0 :                         sctp_sorwakeup(inp, inp->sctp_socket);
    5088             : #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
    5089             :                         SCTP_SOCKET_UNLOCK(so, 1);
    5090             : #endif
    5091             :                 }
    5092             :         }
    5093           0 :         return (0);
    5094             : }
    5095             : 
    5096             : 
    5097             : 
    5098             : /*************HOLD THIS COMMENT FOR PATCH FILE OF
    5099             :  *************ALTERNATE ROUTING CODE
    5100             :  */
    5101             : 
    5102             : /*************HOLD THIS COMMENT FOR END OF PATCH FILE OF
    5103             :  *************ALTERNATE ROUTING CODE
    5104             :  */
    5105             : 
    5106             : struct mbuf *
    5107           0 : sctp_generate_cause(uint16_t code, char *info)
    5108             : {
    5109             :         struct mbuf *m;
    5110             :         struct sctp_gen_error_cause *cause;
    5111             :         size_t info_len, len;
    5112             : 
    5113           0 :         if ((code == 0) || (info == NULL)) {
    5114           0 :                 return (NULL);
    5115             :         }
    5116           0 :         info_len = strlen(info);
    5117           0 :         len = sizeof(struct sctp_paramhdr) + info_len;
    5118           0 :         m = sctp_get_mbuf_for_msg(len, 0, M_NOWAIT, 1, MT_DATA);
    5119           0 :         if (m != NULL) {
    5120           0 :                 SCTP_BUF_LEN(m) = len;
    5121           0 :                 cause = mtod(m, struct sctp_gen_error_cause *);
    5122           0 :                 cause->code = htons(code);
    5123           0 :                 cause->length = htons((uint16_t)len);
    5124           0 :                 memcpy(cause->info, info, info_len);
    5125             :         }
    5126           0 :         return (m);
    5127             : }
    5128             : 
    5129             : struct mbuf *
    5130           0 : sctp_generate_no_user_data_cause(uint32_t tsn)
    5131             : {
    5132             :         struct mbuf *m;
    5133             :         struct sctp_error_no_user_data *no_user_data_cause;
    5134             :         size_t len;
    5135             : 
    5136           0 :         len = sizeof(struct sctp_error_no_user_data);
    5137           0 :         m = sctp_get_mbuf_for_msg(len, 0, M_NOWAIT, 1, MT_DATA);
    5138           0 :         if (m != NULL) {
    5139           0 :                 SCTP_BUF_LEN(m) = len;
    5140           0 :                 no_user_data_cause = mtod(m, struct sctp_error_no_user_data *);
    5141           0 :                 no_user_data_cause->cause.code = htons(SCTP_CAUSE_NO_USER_DATA);
    5142           0 :                 no_user_data_cause->cause.length = htons((uint16_t)len);
    5143           0 :                 no_user_data_cause->tsn = tsn; /* tsn is passed in as NBO */
    5144             :         }
    5145           0 :         return (m);
    5146             : }
    5147             : 
    5148             : #ifdef SCTP_MBCNT_LOGGING
    5149             : void
    5150             : sctp_free_bufspace(struct sctp_tcb *stcb, struct sctp_association *asoc,
    5151             :     struct sctp_tmit_chunk *tp1, int chk_cnt)
    5152             : {
    5153             :         if (tp1->data == NULL) {
    5154             :                 return;
    5155             :         }
    5156             :         asoc->chunks_on_out_queue -= chk_cnt;
    5157             :         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBCNT_LOGGING_ENABLE) {
    5158             :                 sctp_log_mbcnt(SCTP_LOG_MBCNT_DECREASE,
    5159             :                                asoc->total_output_queue_size,
    5160             :                                tp1->book_size,
    5161             :                                0,
    5162             :                                tp1->mbcnt);
    5163             :         }
    5164             :         if (asoc->total_output_queue_size >= tp1->book_size) {
    5165             :                 atomic_add_int(&asoc->total_output_queue_size, -tp1->book_size);
    5166             :         } else {
    5167             :                 asoc->total_output_queue_size = 0;
    5168             :         }
    5169             : 
    5170             :         if (stcb->sctp_socket && (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) ||
    5171             :                                   ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE)))) {
    5172             :                 if (stcb->sctp_socket->so_snd.sb_cc >= tp1->book_size) {
    5173             :                         stcb->sctp_socket->so_snd.sb_cc -= tp1->book_size;
    5174             :                 } else {
    5175             :                         stcb->sctp_socket->so_snd.sb_cc = 0;
    5176             : 
    5177             :                 }
    5178             :         }
    5179             : }
    5180             : 
    5181             : #endif
    5182             : 
    5183             : int
    5184           0 : sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
    5185             :                            uint8_t sent, int so_locked
    5186             : #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
    5187             :                            SCTP_UNUSED
    5188             : #endif
    5189             :         )
    5190             : {
    5191             :         struct sctp_stream_out *strq;
    5192           0 :         struct sctp_tmit_chunk *chk = NULL, *tp2;
    5193             :         struct sctp_stream_queue_pending *sp;
    5194           0 :         uint16_t stream = 0, seq = 0;
    5195           0 :         uint8_t foundeom = 0;
    5196           0 :         int ret_sz = 0;
    5197             :         int notdone;
    5198           0 :         int do_wakeup_routine = 0;
    5199             : 
    5200             : #if defined(__APPLE__)
    5201             :         if (so_locked) {
    5202             :                 sctp_lock_assert(SCTP_INP_SO(stcb->sctp_ep));
    5203             :         } else {
    5204             :                 sctp_unlock_assert(SCTP_INP_SO(stcb->sctp_ep));
    5205             :         }
    5206             : #endif
    5207           0 :         stream = tp1->rec.data.stream_number;
    5208           0 :         seq = tp1->rec.data.stream_seq;
    5209           0 :         if (sent || !(tp1->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG)) {
    5210           0 :                 stcb->asoc.abandoned_sent[0]++;
    5211           0 :                 stcb->asoc.abandoned_sent[PR_SCTP_POLICY(tp1->flags)]++;
    5212           0 :                 stcb->asoc.strmout[stream].abandoned_sent[0]++;
    5213             : #if defined(SCTP_DETAILED_STR_STATS)
    5214             :                 stcb->asoc.strmout[stream].abandoned_sent[PR_SCTP_POLICY(tp1->flags)]++;
    5215             : #endif
    5216             :         } else {
    5217           0 :                 stcb->asoc.abandoned_unsent[0]++;
    5218           0 :                 stcb->asoc.abandoned_unsent[PR_SCTP_POLICY(tp1->flags)]++;
    5219           0 :                 stcb->asoc.strmout[stream].abandoned_unsent[0]++;
    5220             : #if defined(SCTP_DETAILED_STR_STATS)
    5221             :                 stcb->asoc.strmout[stream].abandoned_unsent[PR_SCTP_POLICY(tp1->flags)]++;
    5222             : #endif
    5223             :         }
    5224             :         do {
    5225           0 :                 ret_sz += tp1->book_size;
    5226           0 :                 if (tp1->data != NULL) {
    5227           0 :                         if (tp1->sent < SCTP_DATAGRAM_RESEND) {
    5228           0 :                                 sctp_flight_size_decrease(tp1);
    5229           0 :                                 sctp_total_flight_decrease(stcb, tp1);
    5230             :                         }
    5231           0 :                         sctp_free_bufspace(stcb, &stcb->asoc, tp1, 1);
    5232           0 :                         stcb->asoc.peers_rwnd += tp1->send_size;
    5233           0 :                         stcb->asoc.peers_rwnd += SCTP_BASE_SYSCTL(sctp_peer_chunk_oh);
    5234           0 :                         if (sent) {
    5235           0 :                                 sctp_ulp_notify(SCTP_NOTIFY_SENT_DG_FAIL, stcb, 0, tp1, so_locked);
    5236             :                         } else {
    5237           0 :                                 sctp_ulp_notify(SCTP_NOTIFY_UNSENT_DG_FAIL, stcb, 0, tp1, so_locked);
    5238             :                         }
    5239           0 :                         if (tp1->data) {
    5240           0 :                                 sctp_m_freem(tp1->data);
    5241           0 :                                 tp1->data = NULL;
    5242             :                         }
    5243           0 :                         do_wakeup_routine = 1;
    5244           0 :                         if (PR_SCTP_BUF_ENABLED(tp1->flags)) {
    5245           0 :                                 stcb->asoc.sent_queue_cnt_removeable--;
    5246             :                         }
    5247             :                 }
    5248           0 :                 tp1->sent = SCTP_FORWARD_TSN_SKIP;
    5249           0 :                 if ((tp1->rec.data.rcv_flags & SCTP_DATA_NOT_FRAG) ==
    5250             :                     SCTP_DATA_NOT_FRAG) {
    5251             :                         /* not frag'ed we ae done   */
    5252           0 :                         notdone = 0;
    5253           0 :                         foundeom = 1;
    5254           0 :                 } else if (tp1->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) {
    5255             :                         /* end of frag, we are done */
    5256           0 :                         notdone = 0;
    5257           0 :                         foundeom = 1;
    5258             :                 } else {
    5259             :                         /*
    5260             :                          * Its a begin or middle piece, we must mark all of
    5261             :                          * it
    5262             :                          */
    5263           0 :                         notdone = 1;
    5264           0 :                         tp1 = TAILQ_NEXT(tp1, sctp_next);
    5265             :                 }
    5266           0 :         } while (tp1 && notdone);
    5267           0 :         if (foundeom == 0) {
    5268             :                 /*
    5269             :                  * The multi-part message was scattered across the send and
    5270             :                  * sent queue.
    5271             :                  */
    5272           0 :                 TAILQ_FOREACH_SAFE(tp1, &stcb->asoc.send_queue, sctp_next, tp2) {
    5273           0 :                         if ((tp1->rec.data.stream_number != stream) ||
    5274           0 :                             (tp1->rec.data.stream_seq != seq)) {
    5275             :                                 break;
    5276             :                         }
    5277             :                         /* save to chk in case we have some on stream out
    5278             :                          * queue. If so and we have an un-transmitted one
    5279             :                          * we don't have to fudge the TSN.
    5280             :                          */
    5281           0 :                         chk = tp1;
    5282           0 :                         ret_sz += tp1->book_size;
    5283           0 :                         sctp_free_bufspace(stcb, &stcb->asoc, tp1, 1);
    5284           0 :                         if (sent) {
    5285           0 :                                 sctp_ulp_notify(SCTP_NOTIFY_SENT_DG_FAIL, stcb, 0, tp1, so_locked);
    5286             :                         } else {
    5287           0 :                                 sctp_ulp_notify(SCTP_NOTIFY_UNSENT_DG_FAIL, stcb, 0, tp1, so_locked);
    5288             :                         }
    5289           0 :                         if (tp1->data) {
    5290           0 :                                 sctp_m_freem(tp1->data);
    5291           0 :                                 tp1->data = NULL;
    5292             :                         }
    5293             :                         /* No flight involved here book the size to 0 */
    5294           0 :                         tp1->book_size = 0;
    5295           0 :                         if (tp1->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) {
    5296           0 :                                 foundeom = 1;
    5297             :                         }
    5298           0 :                         do_wakeup_routine = 1;
    5299           0 :                         tp1->sent = SCTP_FORWARD_TSN_SKIP;
    5300           0 :                         TAILQ_REMOVE(&stcb->asoc.send_queue, tp1, sctp_next);
    5301             :                         /* on to the sent queue so we can wait for it to be passed by. */
    5302           0 :                         TAILQ_INSERT_TAIL(&stcb->asoc.sent_queue, tp1,
    5303             :                                           sctp_next);
    5304           0 :                         stcb->asoc.send_queue_cnt--;
    5305           0 :                         stcb->asoc.sent_queue_cnt++;
    5306             :                 }
    5307             :         }
    5308           0 :         if (foundeom == 0) {
    5309             :                 /*
    5310             :                  * Still no eom found. That means there
    5311             :                  * is stuff left on the stream out queue.. yuck.
    5312             :                  */
    5313           0 :                 SCTP_TCB_SEND_LOCK(stcb);
    5314           0 :                 strq = &stcb->asoc.strmout[stream];
    5315           0 :                 sp = TAILQ_FIRST(&strq->outqueue);
    5316           0 :                 if (sp != NULL) {
    5317           0 :                         sp->discard_rest = 1;
    5318             :                         /*
    5319             :                          * We may need to put a chunk on the
    5320             :                          * queue that holds the TSN that
    5321             :                          * would have been sent with the LAST
    5322             :                          * bit.
    5323             :                          */
    5324           0 :                         if (chk == NULL) {
    5325             :                                 /* Yep, we have to */
    5326           0 :                                 sctp_alloc_a_chunk(stcb, chk);
    5327           0 :                                 if (chk == NULL) {
    5328             :                                         /* we are hosed. All we can
    5329             :                                          * do is nothing.. which will
    5330             :                                          * cause an abort if the peer is
    5331             :                                          * paying attention.
    5332             :                                          */
    5333           0 :                                         goto oh_well;
    5334             :                                 }
    5335           0 :                                 memset(chk, 0, sizeof(*chk));
    5336           0 :                                 chk->rec.data.rcv_flags = SCTP_DATA_LAST_FRAG;
    5337           0 :                                 chk->sent = SCTP_FORWARD_TSN_SKIP;
    5338           0 :                                 chk->asoc = &stcb->asoc;
    5339           0 :                                 chk->rec.data.stream_seq = strq->next_sequence_send;
    5340           0 :                                 chk->rec.data.stream_number = sp->stream;
    5341           0 :                                 chk->rec.data.payloadtype = sp->ppid;
    5342           0 :                                 chk->rec.data.context = sp->context;
    5343           0 :                                 chk->flags = sp->act_flags;
    5344           0 :                                 chk->whoTo = NULL;
    5345             : #if defined(__FreeBSD__) || defined(__Panda__)
    5346             :                                 chk->rec.data.TSN_seq = atomic_fetchadd_int(&stcb->asoc.sending_seq, 1);
    5347             : #else
    5348           0 :                                 chk->rec.data.TSN_seq = stcb->asoc.sending_seq++;
    5349             : #endif
    5350           0 :                                 strq->chunks_on_queues++;
    5351           0 :                                 TAILQ_INSERT_TAIL(&stcb->asoc.sent_queue, chk, sctp_next);
    5352           0 :                                 stcb->asoc.sent_queue_cnt++;
    5353           0 :                                 stcb->asoc.pr_sctp_cnt++;
    5354             :                         } else {
    5355           0 :                                 chk->rec.data.rcv_flags |= SCTP_DATA_LAST_FRAG;
    5356             :                         }
    5357           0 :                         strq->next_sequence_send++;
    5358             :                 oh_well:
    5359           0 :                         if (sp->data) {
    5360             :                                 /* Pull any data to free up the SB and
    5361             :                                  * allow sender to "add more" while we
    5362             :                                  * will throw away :-)
    5363             :                                  */
    5364           0 :                                 sctp_free_spbufspace(stcb, &stcb->asoc, sp);
    5365           0 :                                 ret_sz += sp->length;
    5366           0 :                                 do_wakeup_routine = 1;
    5367           0 :                                 sp->some_taken = 1;
    5368           0 :                                 sctp_m_freem(sp->data);
    5369           0 :                                 sp->data = NULL;
    5370           0 :                                 sp->tail_mbuf = NULL;
    5371           0 :                                 sp->length = 0;
    5372             :                         }
    5373             :                 }
    5374           0 :                 SCTP_TCB_SEND_UNLOCK(stcb);
    5375             :         }
    5376           0 :         if (do_wakeup_routine) {
    5377             : #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
    5378             :                 struct socket *so;
    5379             : 
    5380             :                 so = SCTP_INP_SO(stcb->sctp_ep);
    5381             :                 if (!so_locked) {
    5382             :                         atomic_add_int(&stcb->asoc.refcnt, 1);
    5383             :                         SCTP_TCB_UNLOCK(stcb);
    5384             :                         SCTP_SOCKET_LOCK(so, 1);
    5385             :                         SCTP_TCB_LOCK(stcb);
    5386             :                         atomic_subtract_int(&stcb->asoc.refcnt, 1);
    5387             :                         if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
    5388             :                                 /* assoc was freed while we were unlocked */
    5389             :                                 SCTP_SOCKET_UNLOCK(so, 1);
    5390             :                                 return (ret_sz);
    5391             :                         }
    5392             :                 }
    5393             : #endif
    5394           0 :                 sctp_sowwakeup(stcb->sctp_ep, stcb->sctp_socket);
    5395             : #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
    5396             :                 if (!so_locked) {
    5397             :                         SCTP_SOCKET_UNLOCK(so, 1);
    5398             :                 }
    5399             : #endif
    5400             :         }
    5401           0 :         return (ret_sz);
    5402             : }
    5403             : 
    5404             : /*
    5405             :  * checks to see if the given address, sa, is one that is currently known by
    5406             :  * the kernel note: can't distinguish the same address on multiple interfaces
    5407             :  * and doesn't handle multiple addresses with different zone/scope id's note:
    5408             :  * ifa_ifwithaddr() compares the entire sockaddr struct
    5409             :  */
    5410             : struct sctp_ifa *
    5411           0 : sctp_find_ifa_in_ep(struct sctp_inpcb *inp, struct sockaddr *addr,
    5412             :                     int holds_lock)
    5413             : {
    5414             :         struct sctp_laddr *laddr;
    5415             : 
    5416           0 :         if (holds_lock == 0) {
    5417           0 :                 SCTP_INP_RLOCK(inp);
    5418             :         }
    5419             : 
    5420           0 :         LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
    5421           0 :                 if (laddr->ifa == NULL)
    5422           0 :                         continue;
    5423           0 :                 if (addr->sa_family != laddr->ifa->address.sa.sa_family)
    5424           0 :                         continue;
    5425             : #ifdef INET
    5426             :                 if (addr->sa_family == AF_INET) {
    5427             :                         if (((struct sockaddr_in *)addr)->sin_addr.s_addr ==
    5428             :                             laddr->ifa->address.sin.sin_addr.s_addr) {
    5429             :                                 /* found him. */
    5430             :                                 if (holds_lock == 0) {
    5431             :                                         SCTP_INP_RUNLOCK(inp);
    5432             :                                 }
    5433             :                                 return (laddr->ifa);
    5434             :                                 break;
    5435             :                         }
    5436             :                 }
    5437             : #endif
    5438             : #ifdef INET6
    5439             :                 if (addr->sa_family == AF_INET6) {
    5440             :                         if (SCTP6_ARE_ADDR_EQUAL((struct sockaddr_in6 *)addr,
    5441             :                                                  &laddr->ifa->address.sin6)) {
    5442             :                                 /* found him. */
    5443             :                                 if (holds_lock == 0) {
    5444             :                                         SCTP_INP_RUNLOCK(inp);
    5445             :                                 }
    5446             :                                 return (laddr->ifa);
    5447             :                                 break;
    5448             :                         }
    5449             :                 }
    5450             : #endif
    5451             : #if defined(__Userspace__)
    5452           0 :                 if (addr->sa_family == AF_CONN) {
    5453           0 :                         if (((struct sockaddr_conn *)addr)->sconn_addr == laddr->ifa->address.sconn.sconn_addr) {
    5454             :                                 /* found him. */
    5455           0 :                                 if (holds_lock == 0) {
    5456           0 :                                         SCTP_INP_RUNLOCK(inp);
    5457             :                                 }
    5458           0 :                                 return (laddr->ifa);
    5459             :                                 break;
    5460             :                         }
    5461             :                 }
    5462             : #endif
    5463             :         }
    5464           0 :         if (holds_lock == 0) {
    5465           0 :                 SCTP_INP_RUNLOCK(inp);
    5466             :         }
    5467           0 :         return (NULL);
    5468             : }
    5469             : 
    5470             : uint32_t
    5471           0 : sctp_get_ifa_hash_val(struct sockaddr *addr)
    5472             : {
    5473           0 :         switch (addr->sa_family) {
    5474             : #ifdef INET
    5475             :         case AF_INET:
    5476             :         {
    5477             :                 struct sockaddr_in *sin;
    5478             : 
    5479             :                 sin = (struct sockaddr_in *)addr;
    5480             :                 return (sin->sin_addr.s_addr ^ (sin->sin_addr.s_addr >> 16));
    5481             :         }
    5482             : #endif
    5483             : #ifdef INET6
    5484             :         case AF_INET6:
    5485             :         {
    5486             :                 struct sockaddr_in6 *sin6;
    5487             :                 uint32_t hash_of_addr;
    5488             : 
    5489             :                 sin6 = (struct sockaddr_in6 *)addr;
    5490             : #if !defined(__Windows__) && !defined(__Userspace_os_FreeBSD) && !defined(__Userspace_os_Darwin) && !defined(__Userspace_os_Windows)
    5491             :                 hash_of_addr = (sin6->sin6_addr.s6_addr32[0] +
    5492             :                                 sin6->sin6_addr.s6_addr32[1] +
    5493             :                                 sin6->sin6_addr.s6_addr32[2] +
    5494             :                                 sin6->sin6_addr.s6_addr32[3]);
    5495             : #else
    5496             :                 hash_of_addr = (((uint32_t *)&sin6->sin6_addr)[0] +
    5497             :                                 ((uint32_t *)&sin6->sin6_addr)[1] +
    5498             :                                 ((uint32_t *)&sin6->sin6_addr)[2] +
    5499             :                                 ((uint32_t *)&sin6->sin6_addr)[3]);
    5500             : #endif
    5501             :                 hash_of_addr = (hash_of_addr ^ (hash_of_addr >> 16));
    5502             :                 return (hash_of_addr);
    5503             :         }
    5504             : #endif
    5505             : #if defined(__Userspace__)
    5506             :         case AF_CONN:
    5507             :         {
    5508             :                 struct sockaddr_conn *sconn;
    5509             :                 uintptr_t temp;
    5510             : 
    5511           0 :                 sconn = (struct sockaddr_conn *)addr;
    5512           0 :                 temp = (uintptr_t)sconn->sconn_addr;
    5513           0 :                 return ((uint32_t)(temp ^ (temp >> 16)));
    5514             :         }
    5515             : #endif
    5516             :         default:
    5517           0 :                 break;
    5518             :         }
    5519           0 :         return (0);
    5520             : }
    5521             : 
    5522             : struct sctp_ifa *
    5523           0 : sctp_find_ifa_by_addr(struct sockaddr *addr, uint32_t vrf_id, int holds_lock)
    5524             : {
    5525             :         struct sctp_ifa *sctp_ifap;
    5526             :         struct sctp_vrf *vrf;
    5527             :         struct sctp_ifalist *hash_head;
    5528             :         uint32_t hash_of_addr;
    5529             : 
    5530           0 :         if (holds_lock == 0)
    5531           0 :                 SCTP_IPI_ADDR_RLOCK();
    5532             : 
    5533           0 :         vrf = sctp_find_vrf(vrf_id);
    5534           0 :         if (vrf == NULL) {
    5535           0 :                 if (holds_lock == 0)
    5536           0 :                         SCTP_IPI_ADDR_RUNLOCK();
    5537           0 :                 return (NULL);
    5538             :         }
    5539             : 
    5540           0 :         hash_of_addr = sctp_get_ifa_hash_val(addr);
    5541             : 
    5542           0 :         hash_head = &vrf->vrf_addr_hash[(hash_of_addr & vrf->vrf_addr_hashmark)];
    5543           0 :         if (hash_head == NULL) {
    5544           0 :                 SCTP_PRINTF("hash_of_addr:%x mask:%x table:%x - ",
    5545             :                             hash_of_addr, (uint32_t)vrf->vrf_addr_hashmark,
    5546             :                             (uint32_t)(hash_of_addr & vrf->vrf_addr_hashmark));
    5547           0 :                 sctp_print_address(addr);
    5548           0 :                 SCTP_PRINTF("No such bucket for address\n");
    5549           0 :                 if (holds_lock == 0)
    5550           0 :                         SCTP_IPI_ADDR_RUNLOCK();
    5551             : 
    5552           0 :                 return (NULL);
    5553             :         }
    5554           0 :         LIST_FOREACH(sctp_ifap, hash_head, next_bucket) {
    5555           0 :                 if (addr->sa_family != sctp_ifap->address.sa.sa_family)
    5556           0 :                         continue;
    5557             : #ifdef INET
    5558             :                 if (addr->sa_family == AF_INET) {
    5559             :                         if (((struct sockaddr_in *)addr)->sin_addr.s_addr ==
    5560             :                             sctp_ifap->address.sin.sin_addr.s_addr) {
    5561             :                                 /* found him. */
    5562             :                                 if (holds_lock == 0)
    5563             :                                         SCTP_IPI_ADDR_RUNLOCK();
    5564             :                                 return (sctp_ifap);
    5565             :                                 break;
    5566             :                         }
    5567             :                 }
    5568             : #endif
    5569             : #ifdef INET6
    5570             :                 if (addr->sa_family == AF_INET6) {
    5571             :                         if (SCTP6_ARE_ADDR_EQUAL((struct sockaddr_in6 *)addr,
    5572             :                                                  &sctp_ifap->address.sin6)) {
    5573             :                                 /* found him. */
    5574             :                                 if (holds_lock == 0)
    5575             :                                         SCTP_IPI_ADDR_RUNLOCK();
    5576             :                                 return (sctp_ifap);
    5577             :                                 break;
    5578             :                         }
    5579             :                 }
    5580             : #endif
    5581             : #if defined(__Userspace__)
    5582           0 :                 if (addr->sa_family == AF_CONN) {
    5583           0 :                         if (((struct sockaddr_conn *)addr)->sconn_addr == sctp_ifap->address.sconn.sconn_addr) {
    5584             :                                 /* found him. */
    5585           0 :                                 if (holds_lock == 0)
    5586           0 :                                         SCTP_IPI_ADDR_RUNLOCK();
    5587           0 :                                 return (sctp_ifap);
    5588             :                                 break;
    5589             :                         }
    5590             :                 }
    5591             : #endif
    5592             :         }
    5593           0 :         if (holds_lock == 0)
    5594           0 :                 SCTP_IPI_ADDR_RUNLOCK();
    5595           0 :         return (NULL);
    5596             : }
    5597             : 
    5598             : static void
    5599           0 : sctp_user_rcvd(struct sctp_tcb *stcb, uint32_t *freed_so_far, int hold_rlock,
    5600             :                uint32_t rwnd_req)
    5601             : {
    5602             :         /* User pulled some data, do we need a rwnd update? */
    5603           0 :         int r_unlocked = 0;
    5604             :         uint32_t dif, rwnd;
    5605           0 :         struct socket *so = NULL;
    5606             : 
    5607           0 :         if (stcb == NULL)
    5608           0 :                 return;
    5609             : 
    5610           0 :         atomic_add_int(&stcb->asoc.refcnt, 1);
    5611             : 
    5612           0 :         if (stcb->asoc.state & (SCTP_STATE_ABOUT_TO_BE_FREED |
    5613             :                                 SCTP_STATE_SHUTDOWN_RECEIVED |
    5614             :                                 SCTP_STATE_SHUTDOWN_ACK_SENT)) {
    5615             :                 /* Pre-check If we are freeing no update */
    5616           0 :                 goto no_lock;
    5617             :         }
    5618           0 :         SCTP_INP_INCR_REF(stcb->sctp_ep);
    5619           0 :         if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
    5620           0 :             (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE)) {
    5621             :                 goto out;
    5622             :         }
    5623           0 :         so = stcb->sctp_socket;
    5624           0 :         if (so == NULL) {
    5625           0 :                 goto out;
    5626             :         }
    5627           0 :         atomic_add_int(&stcb->freed_by_sorcv_sincelast, *freed_so_far);
    5628             :         /* Have you have freed enough to look */
    5629           0 :         *freed_so_far = 0;
    5630             :         /* Yep, its worth a look and the lock overhead */
    5631             : 
    5632             :         /* Figure out what the rwnd would be */
    5633           0 :         rwnd = sctp_calc_rwnd(stcb, &stcb->asoc);
    5634           0 :         if (rwnd >= stcb->asoc.my_last_reported_rwnd) {
    5635           0 :                 dif = rwnd - stcb->asoc.my_last_reported_rwnd;
    5636             :         } else {
    5637           0 :                 dif = 0;
    5638             :         }
    5639           0 :         if (dif >= rwnd_req) {
    5640           0 :                 if (hold_rlock) {
    5641           0 :                         SCTP_INP_READ_UNLOCK(stcb->sctp_ep);
    5642           0 :                         r_unlocked = 1;
    5643             :                 }
    5644           0 :                 if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
    5645             :                         /*
    5646             :                          * One last check before we allow the guy possibly
    5647             :                          * to get in. There is a race, where the guy has not
    5648             :                          * reached the gate. In that case
    5649             :                          */
    5650           0 :                         goto out;
    5651             :                 }
    5652           0 :                 SCTP_TCB_LOCK(stcb);
    5653           0 :                 if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
    5654             :                         /* No reports here */
    5655           0 :                         SCTP_TCB_UNLOCK(stcb);
    5656           0 :                         goto out;
    5657             :                 }
    5658           0 :                 SCTP_STAT_INCR(sctps_wu_sacks_sent);
    5659           0 :                 sctp_send_sack(stcb, SCTP_SO_LOCKED);
    5660             : 
    5661           0 :                 sctp_chunk_output(stcb->sctp_ep, stcb,
    5662             :                                   SCTP_OUTPUT_FROM_USR_RCVD, SCTP_SO_LOCKED);
    5663             :                 /* make sure no timer is running */
    5664           0 :                 sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTPUTIL+SCTP_LOC_6);
    5665           0 :                 SCTP_TCB_UNLOCK(stcb);
    5666             :         } else {
    5667             :                 /* Update how much we have pending */
    5668           0 :                 stcb->freed_by_sorcv_sincelast = dif;
    5669             :         }
    5670             :  out:
    5671           0 :         if (so && r_unlocked && hold_rlock) {
    5672           0 :                 SCTP_INP_READ_LOCK(stcb->sctp_ep);
    5673             :         }
    5674             : 
    5675           0 :         SCTP_INP_DECR_REF(stcb->sctp_ep);
    5676             :  no_lock:
    5677           0 :         atomic_add_int(&stcb->asoc.refcnt, -1);
    5678           0 :         return;
    5679             : }
    5680             : 
    5681             : int
    5682           0 : sctp_sorecvmsg(struct socket *so,
    5683             :     struct uio *uio,
    5684             :     struct mbuf **mp,
    5685             :     struct sockaddr *from,
    5686             :     int fromlen,
    5687             :     int *msg_flags,
    5688             :     struct sctp_sndrcvinfo *sinfo,
    5689             :     int filling_sinfo)
    5690             : {
    5691             :         /*
    5692             :          * MSG flags we will look at MSG_DONTWAIT - non-blocking IO.
    5693             :          * MSG_PEEK - Look don't touch :-D (only valid with OUT mbuf copy
    5694             :          * mp=NULL thus uio is the copy method to userland) MSG_WAITALL - ??
    5695             :          * On the way out we may send out any combination of:
    5696             :          * MSG_NOTIFICATION MSG_EOR
    5697             :          *
    5698             :          */
    5699           0 :         struct sctp_inpcb *inp = NULL;
    5700           0 :         int my_len = 0;
    5701           0 :         int cp_len = 0, error = 0;
    5702           0 :         struct sctp_queued_to_read *control = NULL, *ctl = NULL, *nxt = NULL;
    5703           0 :         struct mbuf *m = NULL;
    5704           0 :         struct sctp_tcb *stcb = NULL;
    5705           0 :         int wakeup_read_socket = 0;
    5706           0 :         int freecnt_applied = 0;
    5707           0 :         int out_flags = 0, in_flags = 0;
    5708           0 :         int block_allowed = 1;
    5709           0 :         uint32_t freed_so_far = 0;
    5710           0 :         uint32_t copied_so_far = 0;
    5711           0 :         int in_eeor_mode = 0;
    5712           0 :         int no_rcv_needed = 0;
    5713           0 :         uint32_t rwnd_req = 0;
    5714           0 :         int hold_sblock = 0;
    5715           0 :         int hold_rlock = 0;
    5716           0 :         int slen = 0;
    5717           0 :         uint32_t held_length = 0;
    5718             : #if defined(__FreeBSD__) && __FreeBSD_version >= 700000
    5719             :         int sockbuf_lock = 0;
    5720             : #endif
    5721             : 
    5722           0 :         if (uio == NULL) {
    5723             :                 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
    5724           0 :                 return (EINVAL);
    5725             :         }
    5726             : 
    5727           0 :         if (msg_flags) {
    5728           0 :                 in_flags = *msg_flags;
    5729           0 :                 if (in_flags & MSG_PEEK)
    5730           0 :                         SCTP_STAT_INCR(sctps_read_peeks);
    5731             :         } else {
    5732           0 :                 in_flags = 0;
    5733             :         }
    5734             : #if defined(__APPLE__)
    5735             : #if defined(APPLE_LEOPARD)
    5736             :         slen = uio->uio_resid;
    5737             : #else
    5738             :         slen = uio_resid(uio);
    5739             : #endif
    5740             : #else
    5741           0 :         slen = uio->uio_resid;
    5742             : #endif
    5743             : 
    5744             :         /* Pull in and set up our int flags */
    5745           0 :         if (in_flags & MSG_OOB) {
    5746             :                 /* Out of band's NOT supported */
    5747           0 :                 return (EOPNOTSUPP);
    5748             :         }
    5749           0 :         if ((in_flags & MSG_PEEK) && (mp != NULL)) {
    5750             :                 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
    5751           0 :                 return (EINVAL);
    5752             :         }
    5753           0 :         if ((in_flags & (MSG_DONTWAIT
    5754             : #if defined(__FreeBSD__) && __FreeBSD_version > 500000
    5755             :                          | MSG_NBIO
    5756             : #endif
    5757           0 :                      )) ||
    5758           0 :             SCTP_SO_IS_NBIO(so)) {
    5759           0 :                 block_allowed = 0;
    5760             :         }
    5761             :         /* setup the endpoint */
    5762           0 :         inp = (struct sctp_inpcb *)so->so_pcb;
    5763           0 :         if (inp == NULL) {
    5764             :                 SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, EFAULT);
    5765           0 :                 return (EFAULT);
    5766             :         }
    5767           0 :         rwnd_req = (SCTP_SB_LIMIT_RCV(so) >> SCTP_RWND_HIWAT_SHIFT);
    5768             :         /* Must be at least a MTU's worth */
    5769           0 :         if (rwnd_req < SCTP_MIN_RWND)
    5770           0 :                 rwnd_req = SCTP_MIN_RWND;
    5771           0 :         in_eeor_mode = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR);
    5772           0 :         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_RECV_RWND_LOGGING_ENABLE) {
    5773             : #if defined(__APPLE__)
    5774             : #if defined(APPLE_LEOPARD)
    5775             :                 sctp_misc_ints(SCTP_SORECV_ENTER,
    5776             :                                rwnd_req, in_eeor_mode, so->so_rcv.sb_cc, uio->uio_resid);
    5777             : #else
    5778             :                 sctp_misc_ints(SCTP_SORECV_ENTER,
    5779             :                                rwnd_req, in_eeor_mode, so->so_rcv.sb_cc, uio_resid(uio));
    5780             : #endif
    5781             : #else
    5782           0 :                 sctp_misc_ints(SCTP_SORECV_ENTER,
    5783           0 :                                rwnd_req, in_eeor_mode, so->so_rcv.sb_cc, uio->uio_resid);
    5784             : #endif
    5785             :         }
    5786             : #if (defined(__FreeBSD__) && __FreeBSD_version < 700000) || defined(__Userspace__)
    5787           0 :         SOCKBUF_LOCK(&so->so_rcv);
    5788           0 :         hold_sblock = 1;
    5789             : #endif
    5790           0 :         if (SCTP_BASE_SYSCTL(sctp_logging_level) &SCTP_RECV_RWND_LOGGING_ENABLE) {
    5791             : #if defined(__APPLE__)
    5792             : #if defined(APPLE_LEOPARD)
    5793             :                 sctp_misc_ints(SCTP_SORECV_ENTERPL,
    5794             :                                rwnd_req, block_allowed, so->so_rcv.sb_cc, uio->uio_resid);
    5795             : #else
    5796             :                 sctp_misc_ints(SCTP_SORECV_ENTERPL,
    5797             :                                rwnd_req, block_allowed, so->so_rcv.sb_cc, uio_resid(uio));
    5798             : #endif
    5799             : #else
    5800           0 :                 sctp_misc_ints(SCTP_SORECV_ENTERPL,
    5801           0 :                                rwnd_req, block_allowed, so->so_rcv.sb_cc, uio->uio_resid);
    5802             : #endif
    5803             :         }
    5804             : 
    5805             : #if defined(__APPLE__)
    5806             :         error = sblock(&so->so_rcv, SBLOCKWAIT(in_flags));
    5807             : #endif
    5808             : 
    5809             : #if defined(__FreeBSD__)
    5810             :         error = sblock(&so->so_rcv, (block_allowed ? SBL_WAIT : 0));
    5811             : #endif
    5812           0 :         if (error) {
    5813           0 :                 goto release_unlocked;
    5814             :         }
    5815             : #if defined(__FreeBSD__) && __FreeBSD_version >= 700000
    5816             :         sockbuf_lock = 1;
    5817             : #endif
    5818             :  restart:
    5819             : #if (defined(__FreeBSD__) && __FreeBSD_version < 700000) || defined(__Userspace__)
    5820           0 :         if (hold_sblock == 0) {
    5821           0 :                 SOCKBUF_LOCK(&so->so_rcv);
    5822           0 :                 hold_sblock = 1;
    5823             :         }
    5824             : #endif
    5825             : #if defined(__APPLE__)
    5826             :         sbunlock(&so->so_rcv, 1);
    5827             : #endif
    5828             : 
    5829             : #if defined(__FreeBSD__) && __FreeBSD_version < 700000
    5830             :         sbunlock(&so->so_rcv);
    5831             : #endif
    5832             : 
    5833             :  restart_nosblocks:
    5834           0 :         if (hold_sblock == 0) {
    5835           0 :                 SOCKBUF_LOCK(&so->so_rcv);
    5836           0 :                 hold_sblock = 1;
    5837             :         }
    5838           0 :         if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
    5839           0 :             (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE)) {
    5840             :                 goto out;
    5841             :         }
    5842             : #if (defined(__FreeBSD__) && __FreeBSD_version > 500000) || defined(__Windows__)
    5843             :         if ((so->so_rcv.sb_state & SBS_CANTRCVMORE) && (so->so_rcv.sb_cc == 0)) {
    5844             : #else
    5845           0 :         if ((so->so_state & SS_CANTRCVMORE) && (so->so_rcv.sb_cc == 0)) {
    5846             : #endif
    5847           0 :                 if (so->so_error) {
    5848           0 :                         error = so->so_error;
    5849           0 :                         if ((in_flags & MSG_PEEK) == 0)
    5850           0 :                                 so->so_error = 0;
    5851           0 :                         goto out;
    5852             :                 } else {
    5853           0 :                         if (so->so_rcv.sb_cc == 0) {
    5854             :                                 /* indicate EOF */
    5855           0 :                                 error = 0;
    5856           0 :                                 goto out;
    5857             :                         }
    5858             :                 }
    5859             :         }
    5860           0 :         if ((so->so_rcv.sb_cc <= held_length) && block_allowed) {
    5861             :                 /* we need to wait for data */
    5862           0 :                 if ((so->so_rcv.sb_cc == 0) &&
    5863           0 :                     ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
    5864           0 :                      (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))) {
    5865           0 :                         if ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0) {
    5866             :                                 /* For active open side clear flags for re-use
    5867             :                                  * passive open is blocked by connect.
    5868             :                                  */
    5869           0 :                                 if (inp->sctp_flags & SCTP_PCB_FLAGS_WAS_ABORTED) {
    5870             :                                         /* You were aborted, passive side always hits here */
    5871             :                                         SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ECONNRESET);
    5872           0 :                                         error = ECONNRESET;
    5873             :                                 }
    5874           0 :                                 so->so_state &= ~(SS_ISCONNECTING |
    5875             :                                                   SS_ISDISCONNECTING |
    5876             :                                                   SS_ISCONFIRMING |
    5877             :                                                   SS_ISCONNECTED);
    5878           0 :                                 if (error == 0) {
    5879           0 :                                         if ((inp->sctp_flags & SCTP_PCB_FLAGS_WAS_CONNECTED) == 0) {
    5880             :                                                 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOTCONN);
    5881           0 :                                                 error = ENOTCONN;
    5882             :                                         }
    5883             :                                 }
    5884           0 :                                 goto out;
    5885             :                         }
    5886             :                 }
    5887           0 :                 error = sbwait(&so->so_rcv);
    5888           0 :                 if (error) {
    5889           0 :                         goto out;
    5890             :                 }
    5891           0 :                 held_length = 0;
    5892           0 :                 goto restart_nosblocks;
    5893           0 :         } else if (so->so_rcv.sb_cc == 0) {
    5894           0 :                 if (so->so_error) {
    5895           0 :                         error = so->so_error;
    5896           0 :                         if ((in_flags & MSG_PEEK) == 0)
    5897           0 :                                 so->so_error = 0;
    5898             :                 } else {
    5899           0 :                         if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
    5900           0 :                             (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
    5901           0 :                                 if ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0) {
    5902             :                                         /* For active open side clear flags for re-use
    5903             :                                          * passive open is blocked by connect.
    5904             :                                          */
    5905           0 :                                         if (inp->sctp_flags & SCTP_PCB_FLAGS_WAS_ABORTED) {
    5906             :                                                 /* You were aborted, passive side always hits here */
    5907             :                                                 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ECONNRESET);
    5908           0 :                                                 error = ECONNRESET;
    5909             :                                         }
    5910           0 :                                         so->so_state &= ~(SS_ISCONNECTING |
    5911             :                                                           SS_ISDISCONNECTING |
    5912             :                                                           SS_ISCONFIRMING |
    5913             :                                                           SS_ISCONNECTED);
    5914           0 :                                         if (error == 0) {
    5915           0 :                                                 if ((inp->sctp_flags & SCTP_PCB_FLAGS_WAS_CONNECTED) == 0) {
    5916             :                                                         SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOTCONN);
    5917           0 :                                                         error = ENOTCONN;
    5918             :                                                 }
    5919             :                                         }
    5920           0 :                                         goto out;
    5921             :                                 }
    5922             :                         }
    5923             :                         SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EWOULDBLOCK);
    5924           0 :                         error = EWOULDBLOCK;
    5925             :                 }
    5926           0 :                 goto out;
    5927             :         }
    5928           0 :         if (hold_sblock == 1) {
    5929           0 :                 SOCKBUF_UNLOCK(&so->so_rcv);
    5930           0 :                 hold_sblock = 0;
    5931             :         }
    5932             : #if defined(__APPLE__)
    5933             :         error = sblock(&so->so_rcv, SBLOCKWAIT(in_flags));
    5934             : #endif
    5935             : #if defined(__FreeBSD__) && __FreeBSD_version < 700000
    5936             :         error = sblock(&so->so_rcv, (block_allowed ? M_WAITOK : 0));
    5937             : #endif
    5938             :         /* we possibly have data we can read */
    5939             :         /*sa_ignore FREED_MEMORY*/
    5940           0 :         control = TAILQ_FIRST(&inp->read_queue);
    5941           0 :         if (control == NULL) {
    5942             :                 /* This could be happening since
    5943             :                  * the appender did the increment but as not
    5944             :                  * yet did the tailq insert onto the read_queue
    5945             :                  */
    5946           0 :                 if (hold_rlock == 0) {
    5947           0 :                         SCTP_INP_READ_LOCK(inp);
    5948             :                 }
    5949           0 :                 control = TAILQ_FIRST(&inp->read_queue);
    5950           0 :                 if ((control == NULL) && (so->so_rcv.sb_cc != 0)) {
    5951             : #ifdef INVARIANTS
    5952             :                         panic("Huh, its non zero and nothing on control?");
    5953             : #endif
    5954           0 :                         so->so_rcv.sb_cc = 0;
    5955             :                 }
    5956           0 :                 SCTP_INP_READ_UNLOCK(inp);
    5957           0 :                 hold_rlock = 0;
    5958           0 :                 goto restart;
    5959             :         }
    5960             : 
    5961           0 :         if ((control->length == 0) &&
    5962           0 :             (control->do_not_ref_stcb)) {
    5963             :                 /* Clean up code for freeing assoc that left behind a pdapi..
    5964             :                  * maybe a peer in EEOR that just closed after sending and
    5965             :                  * never indicated a EOR.
    5966             :                  */
    5967           0 :                 if (hold_rlock == 0) {
    5968           0 :                         hold_rlock = 1;
    5969           0 :                         SCTP_INP_READ_LOCK(inp);
    5970             :                 }
    5971           0 :                 control->held_length = 0;
    5972           0 :                 if (control->data) {
    5973             :                         /* Hmm there is data here .. fix */
    5974             :                         struct mbuf *m_tmp;
    5975           0 :                         int cnt = 0;
    5976           0 :                         m_tmp = control->data;
    5977           0 :                         while (m_tmp) {
    5978           0 :                                 cnt += SCTP_BUF_LEN(m_tmp);
    5979           0 :                                 if (SCTP_BUF_NEXT(m_tmp) == NULL) {
    5980           0 :                                         control->tail_mbuf = m_tmp;
    5981           0 :                                         control->end_added = 1;
    5982             :                                 }
    5983           0 :                                 m_tmp = SCTP_BUF_NEXT(m_tmp);
    5984             :                         }
    5985           0 :                         control->length = cnt;
    5986             :                 } else {
    5987             :                         /* remove it */
    5988           0 :                         TAILQ_REMOVE(&inp->read_queue, control, next);
    5989             :                         /* Add back any hiddend data */
    5990           0 :                         sctp_free_remote_addr(control->whoFrom);
    5991           0 :                         sctp_free_a_readq(stcb, control);
    5992             :                 }
    5993           0 :                 if (hold_rlock) {
    5994           0 :                         hold_rlock = 0;
    5995           0 :                         SCTP_INP_READ_UNLOCK(inp);
    5996             :                 }
    5997           0 :                 goto restart;
    5998             :         }
    5999           0 :         if ((control->length == 0) &&
    6000           0 :             (control->end_added == 1)) {
    6001             :                 /* Do we also need to check for (control->pdapi_aborted == 1)? */
    6002           0 :                 if (hold_rlock == 0) {
    6003           0 :                         hold_rlock = 1;
    6004           0 :                         SCTP_INP_READ_LOCK(inp);
    6005             :                 }
    6006           0 :                 TAILQ_REMOVE(&inp->read_queue, control, next);
    6007           0 :                 if (control->data) {
    6008             : #ifdef INVARIANTS
    6009             :                         panic("control->data not null but control->length == 0");
    6010             : #else
    6011           0 :                         SCTP_PRINTF("Strange, data left in the control buffer. Cleaning up.\n");
    6012           0 :                         sctp_m_freem(control->data);
    6013           0 :                         control->data = NULL;
    6014             : #endif
    6015             :                 }
    6016           0 :                 if (control->aux_data) {
    6017           0 :                         sctp_m_free (control->aux_data);
    6018           0 :                         control->aux_data = NULL;
    6019             :                 }
    6020           0 :                 sctp_free_remote_addr(control->whoFrom);
    6021           0 :                 sctp_free_a_readq(stcb, control);
    6022           0 :                 if (hold_rlock) {
    6023           0 :                         hold_rlock = 0;
    6024           0 :                         SCTP_INP_READ_UNLOCK(inp);
    6025             :                 }
    6026           0 :                 goto restart;
    6027             :         }
    6028           0 :         if (control->length == 0) {
    6029           0 :                 if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE)) &&
    6030             :                     (filling_sinfo)) {
    6031             :                         /* find a more suitable one then this */
    6032           0 :                         ctl = TAILQ_NEXT(control, next);
    6033           0 :                         while (ctl) {
    6034           0 :                                 if ((ctl->stcb != control->stcb) && (ctl->length) &&
    6035           0 :                                     (ctl->some_taken ||
    6036           0 :                                      (ctl->spec_flags & M_NOTIFICATION) ||
    6037           0 :                                      ((ctl->do_not_ref_stcb == 0) &&
    6038           0 :                                       (ctl->stcb->asoc.strmin[ctl->sinfo_stream].delivery_started == 0)))
    6039             :                                         ) {
    6040             :                                         /*-
    6041             :                                          * If we have a different TCB next, and there is data
    6042             :                                          * present. If we have already taken some (pdapi), OR we can
    6043             :                                          * ref the tcb and no delivery as started on this stream, we
    6044             :                                          * take it. Note we allow a notification on a different
    6045             :                                          * assoc to be delivered..
    6046             :                                          */
    6047           0 :                                         control = ctl;
    6048           0 :                                         goto found_one;
    6049           0 :                                 } else if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS)) &&
    6050           0 :                                            (ctl->length) &&
    6051           0 :                                            ((ctl->some_taken) ||
    6052           0 :                                             ((ctl->do_not_ref_stcb == 0) &&
    6053           0 :                                              ((ctl->spec_flags & M_NOTIFICATION) == 0) &&
    6054           0 :                                              (ctl->stcb->asoc.strmin[ctl->sinfo_stream].delivery_started == 0)))) {
    6055             :                                         /*-
    6056             :                                          * If we have the same tcb, and there is data present, and we
    6057             :                                          * have the strm interleave feature present. Then if we have
    6058             :                                          * taken some (pdapi) or we can refer to tht tcb AND we have
    6059             :                                          * not started a delivery for this stream, we can take it.
    6060             :                                          * Note we do NOT allow a notificaiton on the same assoc to
    6061             :                                          * be delivered.
    6062             :                                          */
    6063           0 :                                         control = ctl;
    6064           0 :                                         goto found_one;
    6065             :                                 }
    6066           0 :                                 ctl = TAILQ_NEXT(ctl, next);
    6067             :                         }
    6068             :                 }
    6069             :                 /*
    6070             :                  * if we reach here, not suitable replacement is available
    6071             :                  * <or> fragment interleave is NOT on. So stuff the sb_cc
    6072             :                  * into the our held count, and its time to sleep again.
    6073             :                  */
    6074           0 :                 held_length = so->so_rcv.sb_cc;
    6075           0 :                 control->held_length = so->so_rcv.sb_cc;
    6076           0 :                 goto restart;
    6077             :         }
    6078             :         /* Clear the held length since there is something to read */
    6079           0 :         control->held_length = 0;
    6080           0 :         if (hold_rlock) {
    6081           0 :                 SCTP_INP_READ_UNLOCK(inp);
    6082           0 :                 hold_rlock = 0;
    6083             :         }
    6084             :  found_one:
    6085             :         /*
    6086             :          * If we reach here, control has a some data for us to read off.
    6087             :          * Note that stcb COULD be NULL.
    6088             :          */
    6089           0 :         control->some_taken++;
    6090           0 :         if (hold_sblock) {
    6091           0 :                 SOCKBUF_UNLOCK(&so->so_rcv);
    6092           0 :                 hold_sblock = 0;
    6093             :         }
    6094           0 :         stcb = control->stcb;
    6095           0 :         if (stcb) {
    6096           0 :                 if ((control->do_not_ref_stcb == 0) &&
    6097           0 :                     (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED)) {
    6098           0 :                         if (freecnt_applied == 0)
    6099           0 :                                 stcb = NULL;
    6100           0 :                 } else if (control->do_not_ref_stcb == 0) {
    6101             :                         /* you can't free it on me please */
    6102             :                         /*
    6103             :                          * The lock on the socket buffer protects us so the
    6104             :                          * free code will stop. But since we used the socketbuf
    6105             :                          * lock and the sender uses the tcb_lock to increment,
    6106             :                          * we need to use the atomic add to the refcnt
    6107             :                          */
    6108           0 :                         if (freecnt_applied) {
    6109             : #ifdef INVARIANTS
    6110             :                                 panic("refcnt already incremented");
    6111             : #else
    6112           0 :                                 SCTP_PRINTF("refcnt already incremented?\n");
    6113             : #endif
    6114             :                         } else {
    6115           0 :                                 atomic_add_int(&stcb->asoc.refcnt, 1);
    6116           0 :                                 freecnt_applied = 1;
    6117             :                         }
    6118             :                         /*
    6119             :                          * Setup to remember how much we have not yet told
    6120             :                          * the peer our rwnd has opened up. Note we grab
    6121             :                          * the value from the tcb from last time.
    6122             :                          * Note too that sack sending clears this when a sack
    6123             :                          * is sent, which is fine. Once we hit the rwnd_req,
    6124             :                          * we then will go to the sctp_user_rcvd() that will
    6125             :                          * not lock until it KNOWs it MUST send a WUP-SACK.
    6126             :                          */
    6127           0 :                         freed_so_far = stcb->freed_by_sorcv_sincelast;
    6128           0 :                         stcb->freed_by_sorcv_sincelast = 0;
    6129             :                 }
    6130             :         }
    6131           0 :         if (stcb &&
    6132           0 :             ((control->spec_flags & M_NOTIFICATION) == 0) &&
    6133           0 :             control->do_not_ref_stcb == 0) {
    6134           0 :                 stcb->asoc.strmin[control->sinfo_stream].delivery_started = 1;
    6135             :         }
    6136             : 
    6137             :         /* First lets get off the sinfo and sockaddr info */
    6138           0 :         if ((sinfo) && filling_sinfo) {
    6139           0 :                 memcpy(sinfo, control, sizeof(struct sctp_nonpad_sndrcvinfo));
    6140           0 :                 nxt = TAILQ_NEXT(control, next);
    6141           0 :                 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO) ||
    6142           0 :                     sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO)) {
    6143             :                         struct sctp_extrcvinfo *s_extra;
    6144           0 :                         s_extra = (struct sctp_extrcvinfo *)sinfo;
    6145           0 :                         if ((nxt) &&
    6146           0 :                             (nxt->length)) {
    6147           0 :                                 s_extra->sreinfo_next_flags = SCTP_NEXT_MSG_AVAIL;
    6148           0 :                                 if (nxt->sinfo_flags & SCTP_UNORDERED) {
    6149           0 :                                         s_extra->sreinfo_next_flags |= SCTP_NEXT_MSG_IS_UNORDERED;
    6150             :                                 }
    6151           0 :                                 if (nxt->spec_flags & M_NOTIFICATION) {
    6152           0 :                                         s_extra->sreinfo_next_flags |= SCTP_NEXT_MSG_IS_NOTIFICATION;
    6153             :                                 }
    6154           0 :                                 s_extra->sreinfo_next_aid = nxt->sinfo_assoc_id;
    6155           0 :                                 s_extra->sreinfo_next_length = nxt->length;
    6156           0 :                                 s_extra->sreinfo_next_ppid = nxt->sinfo_ppid;
    6157           0 :                                 s_extra->sreinfo_next_stream = nxt->sinfo_stream;
    6158           0 :                                 if (nxt->tail_mbuf != NULL) {
    6159           0 :                                         if (nxt->end_added) {
    6160           0 :                                                 s_extra->sreinfo_next_flags |= SCTP_NEXT_MSG_ISCOMPLETE;
    6161             :                                         }
    6162             :                                 }
    6163             :                         } else {
    6164             :                                 /* we explicitly 0 this, since the memcpy got
    6165             :                                  * some other things beyond the older sinfo_
    6166             :                                  * that is on the control's structure :-D
    6167             :                                  */
    6168           0 :                                 nxt = NULL;
    6169           0 :                                 s_extra->sreinfo_next_flags = SCTP_NO_NEXT_MSG;
    6170           0 :                                 s_extra->sreinfo_next_aid = 0;
    6171           0 :                                 s_extra->sreinfo_next_length = 0;
    6172           0 :                                 s_extra->sreinfo_next_ppid = 0;
    6173           0 :                                 s_extra->sreinfo_next_stream = 0;
    6174             :                         }
    6175             :                 }
    6176             :                 /*
    6177             :                  * update off the real current cum-ack, if we have an stcb.
    6178             :                  */
    6179           0 :                 if ((control->do_not_ref_stcb == 0) && stcb)
    6180           0 :                         sinfo->sinfo_cumtsn = stcb->asoc.cumulative_tsn;
    6181             :                 /*
    6182             :                  * mask off the high bits, we keep the actual chunk bits in
    6183             :                  * there.
    6184             :                  */
    6185           0 :                 sinfo->sinfo_flags &= 0x00ff;
    6186           0 :                 if ((control->sinfo_flags >> 8) & SCTP_DATA_UNORDERED) {
    6187           0 :                         sinfo->sinfo_flags |= SCTP_UNORDERED;
    6188             :                 }
    6189             :         }
    6190             : #ifdef SCTP_ASOCLOG_OF_TSNS
    6191             :         {
    6192             :                 int index, newindex;
    6193             :                 struct sctp_pcbtsn_rlog *entry;
    6194             :                 do {
    6195             :                         index = inp->readlog_index;
    6196             :                         newindex = index + 1;
    6197             :                         if (newindex >= SCTP_READ_LOG_SIZE) {
    6198             :                                 newindex = 0;
    6199             :                         }
    6200             :                 } while (atomic_cmpset_int(&inp->readlog_index, index, newindex) == 0);
    6201             :                 entry = &inp->readlog[index];
    6202             :                 entry->vtag = control->sinfo_assoc_id;
    6203             :                 entry->strm = control->sinfo_stream;
    6204             :                 entry->seq = control->sinfo_ssn;
    6205             :                 entry->sz = control->length;
    6206             :                 entry->flgs = control->sinfo_flags;
    6207             :         }
    6208             : #endif
    6209           0 :         if ((fromlen > 0) && (from != NULL)) {
    6210             :                 union sctp_sockstore store;
    6211             :                 size_t len;
    6212             : 
    6213           0 :                 switch (control->whoFrom->ro._l_addr.sa.sa_family) {
    6214             : #ifdef INET6
    6215             :                         case AF_INET6:
    6216             :                                 len = sizeof(struct sockaddr_in6);
    6217             :                                 store.sin6 = control->whoFrom->ro._l_addr.sin6;
    6218             :                                 store.sin6.sin6_port = control->port_from;
    6219             :                                 break;
    6220             : #endif
    6221             : #ifdef INET
    6222             :                         case AF_INET:
    6223             : #ifdef INET6
    6224             :                                 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
    6225             :                                         len = sizeof(struct sockaddr_in6);
    6226             :                                         in6_sin_2_v4mapsin6(&control->whoFrom->ro._l_addr.sin,
    6227             :                                                             &store.sin6);
    6228             :                                         store.sin6.sin6_port = control->port_from;
    6229             :                                 } else {
    6230             :                                         len = sizeof(struct sockaddr_in);
    6231             :                                         store.sin = control->whoFrom->ro._l_addr.sin;
    6232             :                                         store.sin.sin_port = control->port_from;
    6233             :                                 }
    6234             : #else
    6235             :                                 len = sizeof(struct sockaddr_in);
    6236             :                                 store.sin = control->whoFrom->ro._l_addr.sin;
    6237             :                                 store.sin.sin_port = control->port_from;
    6238             : #endif
    6239             :                                 break;
    6240             : #endif
    6241             : #if defined(__Userspace__)
    6242             :                         case AF_CONN:
    6243           0 :                                 len = sizeof(struct sockaddr_conn);
    6244           0 :                                 store.sconn = control->whoFrom->ro._l_addr.sconn;
    6245           0 :                                 store.sconn.sconn_port = control->port_from;
    6246           0 :                                 break;
    6247             : #endif
    6248             :                         default:
    6249           0 :                                 len = 0;
    6250           0 :                                 break;
    6251             :                 }
    6252           0 :                 memcpy(from, &store, min((size_t)fromlen, len));
    6253             : #if defined(SCTP_EMBEDDED_V6_SCOPE)
    6254             : #ifdef INET6
    6255             :                 {
    6256             :                         struct sockaddr_in6 lsa6, *from6;
    6257             : 
    6258             :                         from6 = (struct sockaddr_in6 *)from;
    6259             :                         sctp_recover_scope_mac(from6, (&lsa6));
    6260             :                 }
    6261             : #endif
    6262             : #endif
    6263             :         }
    6264             :         /* now copy out what data we can */
    6265           0 :         if (mp == NULL) {
    6266             :                 /* copy out each mbuf in the chain up to length */
    6267             :         get_more_data:
    6268           0 :                 m = control->data;
    6269           0 :                 while (m) {
    6270             :                         /* Move out all we can */
    6271             : #if defined(__APPLE__)
    6272             : #if defined(APPLE_LEOPARD)
    6273             :                         cp_len = (int)uio->uio_resid;
    6274             : #else
    6275             :                         cp_len = (int)uio_resid(uio);
    6276             : #endif
    6277             : #else
    6278           0 :                         cp_len = (int)uio->uio_resid;
    6279             : #endif
    6280           0 :                         my_len = (int)SCTP_BUF_LEN(m);
    6281           0 :                         if (cp_len > my_len) {
    6282             :                                 /* not enough in this buf */
    6283           0 :                                 cp_len = my_len;
    6284             :                         }
    6285           0 :                         if (hold_rlock) {
    6286           0 :                                 SCTP_INP_READ_UNLOCK(inp);
    6287           0 :                                 hold_rlock = 0;
    6288             :                         }
    6289             : #if defined(__APPLE__)
    6290             :                         SCTP_SOCKET_UNLOCK(so, 0);
    6291             : #endif
    6292           0 :                         if (cp_len > 0)
    6293           0 :                                 error = uiomove(mtod(m, char *), cp_len, uio);
    6294             : #if defined(__APPLE__)
    6295             :                         SCTP_SOCKET_LOCK(so, 0);
    6296             : #endif
    6297             :                         /* re-read */
    6298           0 :                         if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
    6299           0 :                                 goto release;
    6300             :                         }
    6301             : 
    6302           0 :                         if ((control->do_not_ref_stcb == 0) && stcb &&
    6303           0 :                             stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
    6304           0 :                                 no_rcv_needed = 1;
    6305             :                         }
    6306           0 :                         if (error) {
    6307             :                                 /* error we are out of here */
    6308           0 :                                 goto release;
    6309             :                         }
    6310           0 :                         if ((SCTP_BUF_NEXT(m) == NULL) &&
    6311           0 :                             (cp_len >= SCTP_BUF_LEN(m)) &&
    6312           0 :                             ((control->end_added == 0) ||
    6313           0 :                              (control->end_added &&
    6314           0 :                               (TAILQ_NEXT(control, next) == NULL)))
    6315             :                                 ) {
    6316           0 :                                 SCTP_INP_READ_LOCK(inp);
    6317           0 :                                 hold_rlock = 1;
    6318             :                         }
    6319           0 :                         if (cp_len == SCTP_BUF_LEN(m)) {
    6320           0 :                                 if ((SCTP_BUF_NEXT(m)== NULL) &&
    6321           0 :                                     (control->end_added)) {
    6322           0 :                                         out_flags |= MSG_EOR;
    6323           0 :                                         if ((control->do_not_ref_stcb == 0)  &&
    6324           0 :                                             (control->stcb != NULL) &&
    6325           0 :                                             ((control->spec_flags & M_NOTIFICATION) == 0))
    6326           0 :                                                 control->stcb->asoc.strmin[control->sinfo_stream].delivery_started = 0;
    6327             :                                 }
    6328           0 :                                 if (control->spec_flags & M_NOTIFICATION) {
    6329           0 :                                         out_flags |= MSG_NOTIFICATION;
    6330             :                                 }
    6331             :                                 /* we ate up the mbuf */
    6332           0 :                                 if (in_flags & MSG_PEEK) {
    6333             :                                         /* just looking */
    6334           0 :                                         m = SCTP_BUF_NEXT(m);
    6335           0 :                                         copied_so_far += cp_len;
    6336             :                                 } else {
    6337             :                                         /* dispose of the mbuf */
    6338           0 :                                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
    6339           0 :                                                 sctp_sblog(&so->so_rcv,
    6340           0 :                                                    control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBFREE, SCTP_BUF_LEN(m));
    6341             :                                         }
    6342           0 :                                         sctp_sbfree(control, stcb, &so->so_rcv, m);
    6343           0 :                                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
    6344           0 :                                                 sctp_sblog(&so->so_rcv,
    6345           0 :                                                    control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBRESULT, 0);
    6346             :                                         }
    6347           0 :                                         copied_so_far += cp_len;
    6348           0 :                                         freed_so_far += cp_len;
    6349           0 :                                         freed_so_far += MSIZE;
    6350           0 :                                         atomic_subtract_int(&control->length, cp_len);
    6351           0 :                                         control->data = sctp_m_free(m);
    6352           0 :                                         m = control->data;
    6353             :                                         /* been through it all, must hold sb lock ok to null tail */
    6354           0 :                                         if (control->data == NULL) {
    6355             : #ifdef INVARIANTS
    6356             : #if !defined(__APPLE__)
    6357             :                                                 if ((control->end_added == 0) ||
    6358             :                                                     (TAILQ_NEXT(control, next) == NULL)) {
    6359             :                                                         /* If the end is not added, OR the
    6360             :                                                          * next is NOT null we MUST have the lock.
    6361             :                                                          */
    6362             :                                                         if (mtx_owned(&inp->inp_rdata_mtx) == 0) {
    6363             :                                                                 panic("Hmm we don't own the lock?");
    6364             :                                                         }
    6365             :                                                 }
    6366             : #endif
    6367             : #endif
    6368           0 :                                                 control->tail_mbuf = NULL;
    6369             : #ifdef INVARIANTS
    6370             :                                                 if ((control->end_added) && ((out_flags & MSG_EOR) == 0)) {
    6371             :                                                         panic("end_added, nothing left and no MSG_EOR");
    6372             :                                                 }
    6373             : #endif
    6374             :                                         }
    6375             :                                 }
    6376             :                         } else {
    6377             :                                 /* Do we need to trim the mbuf? */
    6378           0 :                                 if (control->spec_flags & M_NOTIFICATION) {
    6379           0 :                                         out_flags |= MSG_NOTIFICATION;
    6380             :                                 }
    6381           0 :                                 if ((in_flags & MSG_PEEK) == 0) {
    6382           0 :                                         SCTP_BUF_RESV_UF(m, cp_len);
    6383           0 :                                         SCTP_BUF_LEN(m) -= cp_len;
    6384           0 :                                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
    6385           0 :                                                 sctp_sblog(&so->so_rcv, control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBFREE, cp_len);
    6386             :                                         }
    6387           0 :                                         atomic_subtract_int(&so->so_rcv.sb_cc, cp_len);
    6388           0 :                                         if ((control->do_not_ref_stcb == 0) &&
    6389             :                                             stcb) {
    6390           0 :                                                 atomic_subtract_int(&stcb->asoc.sb_cc, cp_len);
    6391             :                                         }
    6392           0 :                                         copied_so_far += cp_len;
    6393           0 :                                         freed_so_far += cp_len;
    6394           0 :                                         freed_so_far += MSIZE;
    6395           0 :                                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
    6396           0 :                                                 sctp_sblog(&so->so_rcv, control->do_not_ref_stcb?NULL:stcb,
    6397             :                                                            SCTP_LOG_SBRESULT, 0);
    6398             :                                         }
    6399           0 :                                         atomic_subtract_int(&control->length, cp_len);
    6400             :                                 } else {
    6401           0 :                                         copied_so_far += cp_len;
    6402             :                                 }
    6403             :                         }
    6404             : #if defined(__APPLE__)
    6405             : #if defined(APPLE_LEOPARD)
    6406             :                         if ((out_flags & MSG_EOR) || (uio->uio_resid == 0)) {
    6407             : #else
    6408             :                         if ((out_flags & MSG_EOR) || (uio_resid(uio) == 0)) {
    6409             : #endif
    6410             : #else
    6411           0 :                         if ((out_flags & MSG_EOR) || (uio->uio_resid == 0)) {
    6412             : #endif
    6413             :                                 break;
    6414             :                         }
    6415           0 :                         if (((stcb) && (in_flags & MSG_PEEK) == 0) &&
    6416           0 :                             (control->do_not_ref_stcb == 0) &&
    6417           0 :                             (freed_so_far >= rwnd_req)) {
    6418           0 :                                 sctp_user_rcvd(stcb, &freed_so_far, hold_rlock, rwnd_req);
    6419             :                         }
    6420             :                 } /* end while(m) */
    6421             :                 /*
    6422             :                  * At this point we have looked at it all and we either have
    6423             :                  * a MSG_EOR/or read all the user wants... <OR>
    6424             :                  * control->length == 0.
    6425             :                  */
    6426           0 :                 if ((out_flags & MSG_EOR) && ((in_flags & MSG_PEEK) == 0)) {
    6427             :                         /* we are done with this control */
    6428           0 :                         if (control->length == 0) {
    6429           0 :                                 if (control->data) {
    6430             : #ifdef INVARIANTS
    6431             :                                         panic("control->data not null at read eor?");
    6432             : #else
    6433           0 :                                         SCTP_PRINTF("Strange, data left in the control buffer .. invarients would panic?\n");
    6434           0 :                                         sctp_m_freem(control->data);
    6435           0 :                                         control->data = NULL;
    6436             : #endif
    6437             :                                 }
    6438             :                         done_with_control:
    6439           0 :                                 if (TAILQ_NEXT(control, next) == NULL) {
    6440             :                                         /* If we don't have a next we need a
    6441             :                                          * lock, if there is a next interrupt
    6442             :                                          * is filling ahead of us and we don't
    6443             :                                          * need a lock to remove this guy
    6444             :                                          * (which is the head of the queue).
    6445             :                                          */
    6446           0 :                                         if (hold_rlock == 0) {
    6447           0 :                                                 SCTP_INP_READ_LOCK(inp);
    6448           0 :                                                 hold_rlock = 1;
    6449             :                                         }
    6450             :                                 }
    6451           0 :                                 TAILQ_REMOVE(&inp->read_queue, control, next);
    6452             :                                 /* Add back any hiddend data */
    6453           0 :                                 if (control->held_length) {
    6454           0 :                                         held_length = 0;
    6455           0 :                                         control->held_length = 0;
    6456           0 :                                         wakeup_read_socket = 1;
    6457             :                                 }
    6458           0 :                                 if (control->aux_data) {
    6459           0 :                                         sctp_m_free (control->aux_data);
    6460           0 :                                         control->aux_data = NULL;
    6461             :                                 }
    6462           0 :                                 no_rcv_needed = control->do_not_ref_stcb;
    6463           0 :                                 sctp_free_remote_addr(control->whoFrom);
    6464           0 :                                 control->data = NULL;
    6465           0 :                                 sctp_free_a_readq(stcb, control);
    6466           0 :                                 control = NULL;
    6467           0 :                                 if ((freed_so_far >= rwnd_req) &&
    6468             :                                     (no_rcv_needed == 0))
    6469           0 :                                         sctp_user_rcvd(stcb, &freed_so_far, hold_rlock, rwnd_req);
    6470             : 
    6471             :                         } else {
    6472             :                                 /*
    6473             :                                  * The user did not read all of this
    6474             :                                  * message, turn off the returned MSG_EOR
    6475             :                                  * since we are leaving more behind on the
    6476             :                                  * control to read.
    6477             :                                  */
    6478             : #ifdef INVARIANTS
    6479             :                                 if (control->end_added &&
    6480             :                                     (control->data == NULL) &&
    6481             :                                     (control->tail_mbuf == NULL)) {
    6482             :                                         panic("Gak, control->length is corrupt?");
    6483             :                                 }
    6484             : #endif
    6485           0 :                                 no_rcv_needed = control->do_not_ref_stcb;
    6486           0 :                                 out_flags &= ~MSG_EOR;
    6487             :                         }
    6488             :                 }
    6489           0 :                 if (out_flags & MSG_EOR) {
    6490           0 :                         goto release;
    6491             :                 }
    6492             : #if defined(__APPLE__)
    6493             : #if defined(APPLE_LEOPARD)
    6494             :                 if ((uio->uio_resid == 0) ||
    6495             : #else
    6496             :                 if ((uio_resid(uio) == 0) ||
    6497             : #endif
    6498             : #else
    6499           0 :                 if ((uio->uio_resid == 0) ||
    6500             : #endif
    6501           0 :                     ((in_eeor_mode) &&
    6502           0 :                      (copied_so_far >= (uint32_t)max(so->so_rcv.sb_lowat, 1)))) {
    6503             :                         goto release;
    6504             :                 }
    6505             :                 /*
    6506             :                  * If I hit here the receiver wants more and this message is
    6507             :                  * NOT done (pd-api). So two questions. Can we block? if not
    6508             :                  * we are done. Did the user NOT set MSG_WAITALL?
    6509             :                  */
    6510           0 :                 if (block_allowed == 0) {
    6511           0 :                         goto release;
    6512             :                 }
    6513             :                 /*
    6514             :                  * We need to wait for more data a few things: - We don't
    6515             :                  * sbunlock() so we don't get someone else reading. - We
    6516             :                  * must be sure to account for the case where what is added
    6517             :                  * is NOT to our control when we wakeup.
    6518             :                  */
    6519             : 
    6520             :                 /* Do we need to tell the transport a rwnd update might be
    6521             :                  * needed before we go to sleep?
    6522             :                  */
    6523           0 :                 if (((stcb) && (in_flags & MSG_PEEK) == 0) &&
    6524           0 :                     ((freed_so_far >= rwnd_req) &&
    6525           0 :                      (control->do_not_ref_stcb == 0) &&
    6526             :                      (no_rcv_needed == 0))) {
    6527           0 :                         sctp_user_rcvd(stcb, &freed_so_far, hold_rlock, rwnd_req);
    6528             :                 }
    6529             :         wait_some_more:
    6530             : #if (defined(__FreeBSD__) && __FreeBSD_version > 500000) || defined(__Windows__)
    6531             :                 if (so->so_rcv.sb_state & SBS_CANTRCVMORE) {
    6532             :                         goto release;
    6533             :                 }
    6534             : #else
    6535           0 :                 if (so->so_state & SS_CANTRCVMORE) {
    6536           0 :                         goto release;
    6537             :                 }
    6538             : #endif
    6539             : 
    6540           0 :                 if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)
    6541           0 :                         goto release;
    6542             : 
    6543           0 :                 if (hold_rlock == 1) {
    6544           0 :                         SCTP_INP_READ_UNLOCK(inp);
    6545           0 :                         hold_rlock = 0;
    6546             :                 }
    6547           0 :                 if (hold_sblock == 0) {
    6548           0 :                         SOCKBUF_LOCK(&so->so_rcv);
    6549           0 :                         hold_sblock = 1;
    6550             :                 }
    6551           0 :                 if ((copied_so_far) && (control->length == 0) &&
    6552           0 :                     (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE))) {
    6553           0 :                         goto release;
    6554             :                 }
    6555             : #if defined(__APPLE__)
    6556             :                 sbunlock(&so->so_rcv, 1);
    6557             : #endif
    6558           0 :                 if (so->so_rcv.sb_cc <= control->held_length) {
    6559           0 :                         error = sbwait(&so->so_rcv);
    6560           0 :                         if (error) {
    6561             : #if defined(__FreeBSD__)
    6562             :                                 goto release;
    6563             : #else
    6564           0 :                                 goto release_unlocked;
    6565             : #endif
    6566             :                         }
    6567           0 :                         control->held_length = 0;
    6568             :                 }
    6569             : #if defined(__APPLE__)
    6570             :                 error = sblock(&so->so_rcv, SBLOCKWAIT(in_flags));
    6571             : #endif
    6572           0 :                 if (hold_sblock) {
    6573           0 :                         SOCKBUF_UNLOCK(&so->so_rcv);
    6574           0 :                         hold_sblock = 0;
    6575             :                 }
    6576           0 :                 if (control->length == 0) {
    6577             :                         /* still nothing here */
    6578           0 :                         if (control->end_added == 1) {
    6579             :                                 /* he aborted, or is done i.e.did a shutdown */
    6580           0 :                                 out_flags |= MSG_EOR;
    6581           0 :                                 if (control->pdapi_aborted) {
    6582           0 :                                         if ((control->do_not_ref_stcb == 0) && ((control->spec_flags & M_NOTIFICATION) == 0))
    6583           0 :                                                 control->stcb->asoc.strmin[control->sinfo_stream].delivery_started = 0;
    6584             : 
    6585           0 :                                         out_flags |= MSG_TRUNC;
    6586             :                                 } else {
    6587           0 :                                         if ((control->do_not_ref_stcb == 0) && ((control->spec_flags & M_NOTIFICATION) == 0))
    6588           0 :                                                 control->stcb->asoc.strmin[control->sinfo_stream].delivery_started = 0;
    6589             :                                 }
    6590           0 :                                 goto done_with_control;
    6591             :                         }
    6592           0 :                         if (so->so_rcv.sb_cc > held_length) {
    6593           0 :                                 control->held_length = so->so_rcv.sb_cc;
    6594           0 :                                 held_length = 0;
    6595             :                         }
    6596           0 :                         goto wait_some_more;
    6597           0 :                 } else if (control->data == NULL) {
    6598             :                         /* we must re-sync since data
    6599             :                          * is probably being added
    6600             :                          */
    6601           0 :                         SCTP_INP_READ_LOCK(inp);
    6602           0 :                         if ((control->length > 0) && (control->data == NULL)) {
    6603             :                                 /* big trouble.. we have the lock and its corrupt? */
    6604             : #ifdef INVARIANTS
    6605             :                                 panic ("Impossible data==NULL length !=0");
    6606             : #endif
    6607           0 :                                 out_flags |= MSG_EOR;
    6608           0 :                                 out_flags |= MSG_TRUNC;
    6609           0 :                                 control->length = 0;
    6610           0 :                                 SCTP_INP_READ_UNLOCK(inp);
    6611           0 :                                 goto done_with_control;
    6612             :                         }
    6613           0 :                         SCTP_INP_READ_UNLOCK(inp);
    6614             :                         /* We will fall around to get more data */
    6615             :                 }
    6616           0 :                 goto get_more_data;
    6617             :         } else {
    6618             :                 /*-
    6619             :                  * Give caller back the mbuf chain,
    6620             :                  * store in uio_resid the length
    6621             :                  */
    6622           0 :                 wakeup_read_socket = 0;
    6623           0 :                 if ((control->end_added == 0) ||
    6624           0 :                     (TAILQ_NEXT(control, next) == NULL)) {
    6625             :                         /* Need to get rlock */
    6626           0 :                         if (hold_rlock == 0) {
    6627           0 :                                 SCTP_INP_READ_LOCK(inp);
    6628           0 :                                 hold_rlock = 1;
    6629             :                         }
    6630             :                 }
    6631           0 :                 if (control->end_added) {
    6632           0 :                         out_flags |= MSG_EOR;
    6633           0 :                         if ((control->do_not_ref_stcb == 0) &&
    6634           0 :                             (control->stcb != NULL) &&
    6635           0 :                             ((control->spec_flags & M_NOTIFICATION) == 0))
    6636           0 :                                 control->stcb->asoc.strmin[control->sinfo_stream].delivery_started = 0;
    6637             :                 }
    6638           0 :                 if (control->spec_flags & M_NOTIFICATION) {
    6639           0 :                         out_flags |= MSG_NOTIFICATION;
    6640             :                 }
    6641             : #if defined(__APPLE__)
    6642             : #if defined(APPLE_LEOPARD)
    6643             :                 uio->uio_resid = control->length;
    6644             : #else
    6645             :                 uio_setresid(uio, control->length);
    6646             : #endif
    6647             : #else
    6648           0 :                 uio->uio_resid = control->length;
    6649             : #endif
    6650           0 :                 *mp = control->data;
    6651           0 :                 m = control->data;
    6652           0 :                 while (m) {
    6653           0 :                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
    6654           0 :                                 sctp_sblog(&so->so_rcv,
    6655           0 :                                    control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBFREE, SCTP_BUF_LEN(m));
    6656             :                         }
    6657           0 :                         sctp_sbfree(control, stcb, &so->so_rcv, m);
    6658           0 :                         freed_so_far += SCTP_BUF_LEN(m);
    6659           0 :                         freed_so_far += MSIZE;
    6660           0 :                         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
    6661           0 :                                 sctp_sblog(&so->so_rcv,
    6662           0 :                                    control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBRESULT, 0);
    6663             :                         }
    6664           0 :                         m = SCTP_BUF_NEXT(m);
    6665             :                 }
    6666           0 :                 control->data = control->tail_mbuf = NULL;
    6667           0 :                 control->length = 0;
    6668           0 :                 if (out_flags & MSG_EOR) {
    6669             :                         /* Done with this control */
    6670           0 :                         goto done_with_control;
    6671             :                 }
    6672             :         }
    6673             :  release:
    6674           0 :         if (hold_rlock == 1) {
    6675           0 :                 SCTP_INP_READ_UNLOCK(inp);
    6676           0 :                 hold_rlock = 0;
    6677             :         }
    6678             : #if (defined(__FreeBSD__) && __FreeBSD_version < 700000) || defined(__Userspace__)
    6679           0 :         if (hold_sblock == 0) {
    6680           0 :                 SOCKBUF_LOCK(&so->so_rcv);
    6681           0 :                 hold_sblock = 1;
    6682             :         }
    6683             : #else
    6684             :         if (hold_sblock == 1) {
    6685             :                 SOCKBUF_UNLOCK(&so->so_rcv);
    6686             :                 hold_sblock = 0;
    6687             :         }
    6688             : #endif
    6689             : #if defined(__APPLE__)
    6690             :         sbunlock(&so->so_rcv, 1);
    6691             : #endif
    6692             : 
    6693             : #if defined(__FreeBSD__)
    6694             :         sbunlock(&so->so_rcv);
    6695             : #if defined(__FreeBSD__) && __FreeBSD_version >= 700000
    6696             :         sockbuf_lock = 0;
    6697             : #endif
    6698             : #endif
    6699             : 
    6700             :  release_unlocked:
    6701           0 :         if (hold_sblock) {
    6702           0 :                 SOCKBUF_UNLOCK(&so->so_rcv);
    6703           0 :                 hold_sblock = 0;
    6704             :         }
    6705           0 :         if ((stcb) && (in_flags & MSG_PEEK) == 0) {
    6706           0 :                 if ((freed_so_far >= rwnd_req) &&
    6707           0 :                     (control && (control->do_not_ref_stcb == 0)) &&
    6708             :                     (no_rcv_needed == 0))
    6709           0 :                         sctp_user_rcvd(stcb, &freed_so_far, hold_rlock, rwnd_req);
    6710             :         }
    6711             :  out:
    6712           0 :         if (msg_flags) {
    6713           0 :                 *msg_flags = out_flags;
    6714             :         }
    6715           0 :         if (((out_flags & MSG_EOR) == 0) &&
    6716           0 :             ((in_flags & MSG_PEEK) == 0) &&
    6717           0 :             (sinfo) &&
    6718           0 :             (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO) ||
    6719           0 :              sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO))) {
    6720             :                 struct sctp_extrcvinfo *s_extra;
    6721           0 :                 s_extra = (struct sctp_extrcvinfo *)sinfo;
    6722           0 :                 s_extra->sreinfo_next_flags = SCTP_NO_NEXT_MSG;
    6723             :         }
    6724           0 :         if (hold_rlock == 1) {
    6725           0 :                 SCTP_INP_READ_UNLOCK(inp);
    6726             :         }
    6727           0 :         if (hold_sblock) {
    6728           0 :                 SOCKBUF_UNLOCK(&so->so_rcv);
    6729             :         }
    6730             : #if defined(__FreeBSD__) && __FreeBSD_version >= 700000
    6731             :         if (sockbuf_lock) {
    6732             :                 sbunlock(&so->so_rcv);
    6733             :         }
    6734             : #endif
    6735             : 
    6736           0 :         if (freecnt_applied) {
    6737             :                 /*
    6738             :                  * The lock on the socket buffer protects us so the free
    6739             :                  * code will stop. But since we used the socketbuf lock and
    6740             :                  * the sender uses the tcb_lock to increment, we need to use
    6741             :                  * the atomic add to the refcnt.
    6742             :                  */
    6743           0 :                 if (stcb == NULL) {
    6744             : #ifdef INVARIANTS
    6745             :                         panic("stcb for refcnt has gone NULL?");
    6746             :                         goto stage_left;
    6747             : #else
    6748           0 :                         goto stage_left;
    6749             : #endif
    6750             :                 }
    6751           0 :                 atomic_add_int(&stcb->asoc.refcnt, -1);
    6752             :                 /* Save the value back for next time */
    6753           0 :                 stcb->freed_by_sorcv_sincelast = freed_so_far;
    6754             :         }
    6755           0 :         if (SCTP_BASE_SYSCTL(sctp_logging_level) &SCTP_RECV_RWND_LOGGING_ENABLE) {
    6756           0 :                 if (stcb) {
    6757           0 :                         sctp_misc_ints(SCTP_SORECV_DONE,
    6758             :                                        freed_so_far,
    6759             : #if defined(__APPLE__)
    6760             : #if defined(APPLE_LEOPARD)
    6761             :                                        ((uio) ? (slen - uio->uio_resid) : slen),
    6762             : #else
    6763             :                                        ((uio) ? (slen - uio_resid(uio)) : slen),
    6764             : #endif
    6765             : #else
    6766           0 :                                        ((uio) ? (slen - uio->uio_resid) : slen),
    6767             : #endif
    6768             :                                        stcb->asoc.my_rwnd,
    6769             :                                        so->so_rcv.sb_cc);
    6770             :                 } else {
    6771           0 :                         sctp_misc_ints(SCTP_SORECV_DONE,
    6772             :                                        freed_so_far,
    6773             : #if defined(__APPLE__)
    6774             : #if defined(APPLE_LEOPARD)
    6775             :                                        ((uio) ? (slen - uio->uio_resid) : slen),
    6776             : #else
    6777             :                                        ((uio) ? (slen - uio_resid(uio)) : slen),
    6778             : #endif
    6779             : #else
    6780           0 :                                        ((uio) ? (slen - uio->uio_resid) : slen),
    6781             : #endif
    6782             :                                        0,
    6783             :                                        so->so_rcv.sb_cc);
    6784             :                 }
    6785             :         }
    6786             :  stage_left:
    6787           0 :         if (wakeup_read_socket) {
    6788           0 :                 sctp_sorwakeup(inp, so);
    6789             :         }
    6790           0 :         return (error);
    6791             : }
    6792             : 
    6793             : 
    6794             : #ifdef SCTP_MBUF_LOGGING
    6795             : struct mbuf *
    6796             : sctp_m_free(struct mbuf *m)
    6797             : {
    6798             :         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
    6799             :                 sctp_log_mb(m, SCTP_MBUF_IFREE);
    6800             :         }
    6801             :         return (m_free(m));
    6802             : }
    6803             : 
    6804             : void sctp_m_freem(struct mbuf *mb)
    6805             : {
    6806             :         while (mb != NULL)
    6807             :                 mb = sctp_m_free(mb);
    6808             : }
    6809             : 
    6810             : #endif
    6811             : 
    6812             : int
    6813           0 : sctp_dynamic_set_primary(struct sockaddr *sa, uint32_t vrf_id)
    6814             : {
    6815             :         /* Given a local address. For all associations
    6816             :          * that holds the address, request a peer-set-primary.
    6817             :          */
    6818             :         struct sctp_ifa *ifa;
    6819             :         struct sctp_laddr *wi;
    6820             : 
    6821           0 :         ifa = sctp_find_ifa_by_addr(sa, vrf_id, 0);
    6822           0 :         if (ifa == NULL) {
    6823             :                 SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, EADDRNOTAVAIL);
    6824           0 :                 return (EADDRNOTAVAIL);
    6825             :         }
    6826             :         /* Now that we have the ifa we must awaken the
    6827             :          * iterator with this message.
    6828             :          */
    6829           0 :         wi = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_laddr), struct sctp_laddr);
    6830           0 :         if (wi == NULL) {
    6831             :                 SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOMEM);
    6832           0 :                 return (ENOMEM);
    6833             :         }
    6834             :         /* Now incr the count and int wi structure */
    6835           0 :         SCTP_INCR_LADDR_COUNT();
    6836           0 :         bzero(wi, sizeof(*wi));
    6837           0 :         (void)SCTP_GETTIME_TIMEVAL(&wi->start_time);
    6838           0 :         wi->ifa = ifa;
    6839           0 :         wi->action = SCTP_SET_PRIM_ADDR;
    6840           0 :         atomic_add_int(&ifa->refcount, 1);
    6841             : 
    6842             :         /* Now add it to the work queue */
    6843           0 :         SCTP_WQ_ADDR_LOCK();
    6844             :         /*
    6845             :          * Should this really be a tailq? As it is we will process the
    6846             :          * newest first :-0
    6847             :          */
    6848           0 :         LIST_INSERT_HEAD(&SCTP_BASE_INFO(addr_wq), wi, sctp_nxt_addr);
    6849           0 :         SCTP_WQ_ADDR_UNLOCK();
    6850           0 :         sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ,
    6851             :                          (struct sctp_inpcb *)NULL,
    6852             :                          (struct sctp_tcb *)NULL,
    6853             :                          (struct sctp_nets *)NULL);
    6854           0 :         return (0);
    6855             : }
    6856             : 
    6857             : #if defined(__Userspace__)
    6858             : /* no sctp_soreceive for __Userspace__ now */
    6859             : #endif
    6860             : 
    6861             : #if !defined(__Userspace__)
    6862             : int
    6863             : sctp_soreceive( struct socket *so,
    6864             :                 struct sockaddr **psa,
    6865             :                 struct uio *uio,
    6866             :                 struct mbuf **mp0,
    6867             :                 struct mbuf **controlp,
    6868             :                 int *flagsp)
    6869             : {
    6870             :         int error, fromlen;
    6871             :         uint8_t sockbuf[256];
    6872             :         struct sockaddr *from;
    6873             :         struct sctp_extrcvinfo sinfo;
    6874             :         int filling_sinfo = 1;
    6875             :         struct sctp_inpcb *inp;
    6876             : 
    6877             :         inp = (struct sctp_inpcb *)so->so_pcb;
    6878             :         /* pickup the assoc we are reading from */
    6879             :         if (inp == NULL) {
    6880             :                 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
    6881             :                 return (EINVAL);
    6882             :         }
    6883             :         if ((sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT) &&
    6884             :              sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVRCVINFO) &&
    6885             :              sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVNXTINFO)) ||
    6886             :             (controlp == NULL)) {
    6887             :                 /* user does not want the sndrcv ctl */
    6888             :                 filling_sinfo = 0;
    6889             :         }
    6890             :         if (psa) {
    6891             :                 from = (struct sockaddr *)sockbuf;
    6892             :                 fromlen = sizeof(sockbuf);
    6893             : #ifdef HAVE_SA_LEN
    6894             :                 from->sa_len = 0;
    6895             : #endif
    6896             :         } else {
    6897             :                 from = NULL;
    6898             :                 fromlen = 0;
    6899             :         }
    6900             : 
    6901             : #if defined(__APPLE__)
    6902             :         SCTP_SOCKET_LOCK(so, 1);
    6903             : #endif
    6904             :         if (filling_sinfo) {
    6905             :                 memset(&sinfo, 0, sizeof(struct sctp_extrcvinfo));
    6906             :         }
    6907             :         error = sctp_sorecvmsg(so, uio, mp0, from, fromlen, flagsp,
    6908             :             (struct sctp_sndrcvinfo *)&sinfo, filling_sinfo);
    6909             :         if (controlp != NULL) {
    6910             :                 /* copy back the sinfo in a CMSG format */
    6911             :                 if (filling_sinfo)
    6912             :                         *controlp = sctp_build_ctl_nchunk(inp,
    6913             :                                                           (struct sctp_sndrcvinfo *)&sinfo);
    6914             :                 else
    6915             :                         *controlp = NULL;
    6916             :         }
    6917             :         if (psa) {
    6918             :                 /* copy back the address info */
    6919             : #ifdef HAVE_SA_LEN
    6920             :                 if (from && from->sa_len) {
    6921             : #else
    6922             :                 if (from) {
    6923             : #endif
    6924             : #if (defined(__FreeBSD__) && __FreeBSD_version > 500000) || defined(__Windows__)
    6925             :                         *psa = sodupsockaddr(from, M_NOWAIT);
    6926             : #else
    6927             :                         *psa = dup_sockaddr(from, mp0 == 0);
    6928             : #endif
    6929             :                 } else {
    6930             :                         *psa = NULL;
    6931             :                 }
    6932             :         }
    6933             : #if defined(__APPLE__)
    6934             :         SCTP_SOCKET_UNLOCK(so, 1);
    6935             : #endif
    6936             :         return (error);
    6937             : }
    6938             : 
    6939             : 
    6940             : #if (defined(__FreeBSD__) && __FreeBSD_version < 603000) || defined(__Windows__)
    6941             : /*
    6942             :  * General routine to allocate a hash table with control of memory flags.
    6943             :  * is in 7.0 and beyond for sure :-)
    6944             :  */
    6945             : void *
    6946             : sctp_hashinit_flags(int elements, struct malloc_type *type,
    6947             :                     u_long *hashmask, int flags)
    6948             : {
    6949             :         long hashsize;
    6950             :         LIST_HEAD(generic, generic) *hashtbl;
    6951             :         int i;
    6952             : 
    6953             : 
    6954             :         if (elements <= 0) {
    6955             : #ifdef INVARIANTS
    6956             :                 panic("hashinit: bad elements");
    6957             : #else
    6958             :                 SCTP_PRINTF("hashinit: bad elements?");
    6959             :                 elements = 1;
    6960             : #endif
    6961             :         }
    6962             :         for (hashsize = 1; hashsize <= elements; hashsize <<= 1)
    6963             :                 continue;
    6964             :         hashsize >>= 1;
    6965             :         if (flags & HASH_WAITOK)
    6966             :                 hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, M_WAITOK);
    6967             :         else if (flags & HASH_NOWAIT)
    6968             :                 hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, M_NOWAIT);
    6969             :         else {
    6970             : #ifdef INVARIANTS
    6971             :                 panic("flag incorrect in hashinit_flags");
    6972             : #else
    6973             :                 return (NULL);
    6974             : #endif
    6975             :         }
    6976             : 
    6977             :         /* no memory? */
    6978             :         if (hashtbl == NULL)
    6979             :                 return (NULL);
    6980             : 
    6981             :         for (i = 0; i < hashsize; i++)
    6982             :                 LIST_INIT(&hashtbl[i]);
    6983             :         *hashmask = hashsize - 1;
    6984             :         return (hashtbl);
    6985             : }
    6986             : #endif
    6987             : 
    6988             : #else /*  __Userspace__ ifdef above sctp_soreceive */
    6989             : /*
    6990             :  * __Userspace__ Defining sctp_hashinit_flags() and sctp_hashdestroy() for userland.
    6991             :  * NOTE: We don't want multiple definitions here. So sctp_hashinit_flags() above for
    6992             :  *__FreeBSD__ must be excluded.
    6993             :  *
    6994             :  */
    6995             : 
    6996             : void *
    6997           0 : sctp_hashinit_flags(int elements, struct malloc_type *type,
    6998             :                     u_long *hashmask, int flags)
    6999             : {
    7000             :         long hashsize;
    7001             :         LIST_HEAD(generic, generic) *hashtbl;
    7002             :         int i;
    7003             : 
    7004           0 :         if (elements <= 0) {
    7005           0 :                 SCTP_PRINTF("hashinit: bad elements?");
    7006             : #ifdef INVARIANTS
    7007             :                 return (NULL);
    7008             : #else
    7009           0 :                 elements = 1;
    7010             : #endif
    7011             :         }
    7012           0 :         for (hashsize = 1; hashsize <= elements; hashsize <<= 1)
    7013           0 :                 continue;
    7014           0 :         hashsize >>= 1;
    7015             :         /*cannot use MALLOC here because it has to be declared or defined
    7016             :           using MALLOC_DECLARE or MALLOC_DEFINE first. */
    7017           0 :         if (flags & HASH_WAITOK)
    7018           0 :                 hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl));
    7019           0 :         else if (flags & HASH_NOWAIT)
    7020           0 :                 hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl));
    7021             :         else {
    7022             : #ifdef INVARIANTS
    7023             :                 SCTP_PRINTF("flag incorrect in hashinit_flags.\n");
    7024             : #endif
    7025           0 :                 return (NULL);
    7026             :         }
    7027             : 
    7028             :         /* no memory? */
    7029           0 :         if (hashtbl == NULL)
    7030           0 :                 return (NULL);
    7031             : 
    7032           0 :         for (i = 0; i < hashsize; i++)
    7033           0 :                 LIST_INIT(&hashtbl[i]);
    7034           0 :         *hashmask = hashsize - 1;
    7035           0 :         return (hashtbl);
    7036             : }
    7037             : 
    7038             : 
    7039             : void
    7040           0 : sctp_hashdestroy(void *vhashtbl, struct malloc_type *type, u_long hashmask)
    7041             : {
    7042             :         LIST_HEAD(generic, generic) *hashtbl, *hp;
    7043             : 
    7044           0 :         hashtbl = vhashtbl;
    7045           0 :         for (hp = hashtbl; hp <= &hashtbl[hashmask]; hp++)
    7046           0 :                 if (!LIST_EMPTY(hp)) {
    7047           0 :                         SCTP_PRINTF("hashdestroy: hash not empty.\n");
    7048           0 :                         return;
    7049             :                 }
    7050           0 :         FREE(hashtbl, type);
    7051             : }
    7052             : 
    7053             : 
    7054             : void
    7055           0 : sctp_hashfreedestroy(void *vhashtbl, struct malloc_type *type, u_long hashmask)
    7056             : {
    7057             :         LIST_HEAD(generic, generic) *hashtbl/*, *hp*/;
    7058             :         /*
    7059             :         LIST_ENTRY(type) *start, *temp;
    7060             :          */
    7061           0 :         hashtbl = vhashtbl;
    7062             :         /* Apparently temp is not dynamically allocated, so attempts to
    7063             :            free it results in error.
    7064             :         for (hp = hashtbl; hp <= &hashtbl[hashmask]; hp++)
    7065             :                 if (!LIST_EMPTY(hp)) {
    7066             :                         start = LIST_FIRST(hp);
    7067             :                         while (start != NULL) {
    7068             :                                 temp = start;
    7069             :                                 start = start->le_next;
    7070             :                                 SCTP_PRINTF("%s: %p \n", __func__, (void *)temp);
    7071             :                                 FREE(temp, type);
    7072             :                         }
    7073             :                 }
    7074             :          */
    7075           0 :         FREE(hashtbl, type);
    7076           0 : }
    7077             : 
    7078             : 
    7079             : #endif
    7080             : 
    7081             : 
    7082             : int
    7083           0 : sctp_connectx_helper_add(struct sctp_tcb *stcb, struct sockaddr *addr,
    7084             :                          int totaddr, int *error)
    7085             : {
    7086           0 :         int added = 0;
    7087             :         int i;
    7088             :         struct sctp_inpcb *inp;
    7089             :         struct sockaddr *sa;
    7090           0 :         size_t incr = 0;
    7091             : #ifdef INET
    7092             :         struct sockaddr_in *sin;
    7093             : #endif
    7094             : #ifdef INET6
    7095             :         struct sockaddr_in6 *sin6;
    7096             : #endif
    7097             : 
    7098           0 :         sa = addr;
    7099           0 :         inp = stcb->sctp_ep;
    7100           0 :         *error = 0;
    7101           0 :         for (i = 0; i < totaddr; i++) {
    7102           0 :                 switch (sa->sa_family) {
    7103             : #ifdef INET
    7104             :                 case AF_INET:
    7105             :                         incr = sizeof(struct sockaddr_in);
    7106             :                         sin = (struct sockaddr_in *)sa;
    7107             :                         if ((sin->sin_addr.s_addr == INADDR_ANY) ||
    7108             :                             (sin->sin_addr.s_addr == INADDR_BROADCAST) ||
    7109             :                             IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
    7110             :                                 SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
    7111             :                                 (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_7);
    7112             :                                 *error = EINVAL;
    7113             :                                 goto out_now;
    7114             :                         }
    7115             :                         if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
    7116             :                                 /* assoc gone no un-lock */
    7117             :                                 SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS);
    7118             :                                 (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_7);
    7119             :                                 *error = ENOBUFS;
    7120             :                                 goto out_now;
    7121             :                         }
    7122             :                         added++;
    7123             :                         break;
    7124             : #endif
    7125             : #ifdef INET6
    7126             :                 case AF_INET6:
    7127             :                         incr = sizeof(struct sockaddr_in6);
    7128             :                         sin6 = (struct sockaddr_in6 *)sa;
    7129             :                         if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
    7130             :                             IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
    7131             :                                 SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
    7132             :                                 (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_8);
    7133             :                                 *error = EINVAL;
    7134             :                                 goto out_now;
    7135             :                         }
    7136             :                         if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
    7137             :                                 /* assoc gone no un-lock */
    7138             :                                 SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS);
    7139             :                                 (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_8);
    7140             :                                 *error = ENOBUFS;
    7141             :                                 goto out_now;
    7142             :                         }
    7143             :                         added++;
    7144             :                         break;
    7145             : #endif
    7146             : #if defined(__Userspace__)
    7147             :                 case AF_CONN:
    7148           0 :                         incr = sizeof(struct sockaddr_in6);
    7149           0 :                         if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
    7150             :                                 /* assoc gone no un-lock */
    7151             :                                 SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS);
    7152           0 :                                 (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_8);
    7153           0 :                                 *error = ENOBUFS;
    7154           0 :                                 goto out_now;
    7155             :                         }
    7156           0 :                         added++;
    7157           0 :                         break;
    7158             : #endif
    7159             :                 default:
    7160           0 :                         break;
    7161             :                 }
    7162           0 :                 sa = (struct sockaddr *)((caddr_t)sa + incr);
    7163             :         }
    7164             :  out_now:
    7165           0 :         return (added);
    7166             : }
    7167             : 
    7168             : struct sctp_tcb *
    7169           0 : sctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr,
    7170             :                           int *totaddr, int *num_v4, int *num_v6, int *error,
    7171             :                           int limit, int *bad_addr)
    7172             : {
    7173             :         struct sockaddr *sa;
    7174           0 :         struct sctp_tcb *stcb = NULL;
    7175             :         size_t incr, at, i;
    7176           0 :         at = incr = 0;
    7177           0 :         sa = addr;
    7178             : 
    7179           0 :         *error = *num_v6 = *num_v4 = 0;
    7180             :         /* account and validate addresses */
    7181           0 :         for (i = 0; i < (size_t)*totaddr; i++) {
    7182           0 :                 switch (sa->sa_family) {
    7183             : #ifdef INET
    7184             :                 case AF_INET:
    7185             :                         (*num_v4) += 1;
    7186             :                         incr = sizeof(struct sockaddr_in);
    7187             : #ifdef HAVE_SA_LEN
    7188             :                         if (sa->sa_len != incr) {
    7189             :                                 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
    7190             :                                 *error = EINVAL;
    7191             :                                 *bad_addr = 1;
    7192             :                                 return (NULL);
    7193             :                         }
    7194             : #endif
    7195             :                         break;
    7196             : #endif
    7197             : #ifdef INET6
    7198             :                 case AF_INET6:
    7199             :                 {
    7200             :                         struct sockaddr_in6 *sin6;
    7201             : 
    7202             :                         sin6 = (struct sockaddr_in6 *)sa;
    7203             :                         if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
    7204             :                                 /* Must be non-mapped for connectx */
    7205             :                                 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
    7206             :                                 *error = EINVAL;
    7207             :                                 *bad_addr = 1;
    7208             :                                 return (NULL);
    7209             :                         }
    7210             :                         (*num_v6) += 1;
    7211             :                         incr = sizeof(struct sockaddr_in6);
    7212             : #ifdef HAVE_SA_LEN
    7213             :                         if (sa->sa_len != incr) {
    7214             :                                 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
    7215             :                                 *error = EINVAL;
    7216             :                                 *bad_addr = 1;
    7217             :                                 return (NULL);
    7218             :                         }
    7219             : #endif
    7220             :                         break;
    7221             :                 }
    7222             : #endif
    7223             :                 default:
    7224           0 :                         *totaddr = i;
    7225             :                         /* we are done */
    7226           0 :                         break;
    7227             :                 }
    7228           0 :                 if (i == (size_t)*totaddr) {
    7229           0 :                         break;
    7230             :                 }
    7231           0 :                 SCTP_INP_INCR_REF(inp);
    7232           0 :                 stcb = sctp_findassociation_ep_addr(&inp, sa, NULL, NULL, NULL);
    7233           0 :                 if (stcb != NULL) {
    7234             :                         /* Already have or am bring up an association */
    7235           0 :                         return (stcb);
    7236             :                 } else {
    7237           0 :                         SCTP_INP_DECR_REF(inp);
    7238             :                 }
    7239           0 :                 if ((at + incr) > (size_t)limit) {
    7240           0 :                         *totaddr = i;
    7241           0 :                         break;
    7242             :                 }
    7243           0 :                 sa = (struct sockaddr *)((caddr_t)sa + incr);
    7244             :         }
    7245           0 :         return ((struct sctp_tcb *)NULL);
    7246             : }
    7247             : 
    7248             : /*
    7249             :  * sctp_bindx(ADD) for one address.
    7250             :  * assumes all arguments are valid/checked by caller.
    7251             :  */
    7252             : void
    7253           0 : sctp_bindx_add_address(struct socket *so, struct sctp_inpcb *inp,
    7254             :                        struct sockaddr *sa, sctp_assoc_t assoc_id,
    7255             :                        uint32_t vrf_id, int *error, void *p)
    7256             : {
    7257             :         struct sockaddr *addr_touse;
    7258             : #if defined(INET) && defined(INET6)
    7259             :         struct sockaddr_in sin;
    7260             : #endif
    7261             : #ifdef SCTP_MVRF
    7262             :         int i, fnd = 0;
    7263             : #endif
    7264             : 
    7265             :         /* see if we're bound all already! */
    7266           0 :         if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
    7267             :                 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
    7268           0 :                 *error = EINVAL;
    7269           0 :                 return;
    7270             :         }
    7271             : #ifdef SCTP_MVRF
    7272             :         /* Is the VRF one we have */
    7273             :         for (i = 0; i < inp->num_vrfs; i++) {
    7274             :                 if (vrf_id == inp->m_vrf_ids[i]) {
    7275             :                         fnd = 1;
    7276             :                         break;
    7277             :                 }
    7278             :         }
    7279             :         if (!fnd) {
    7280             :                 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
    7281             :                 *error = EINVAL;
    7282             :                 return;
    7283             :         }
    7284             : #endif
    7285           0 :         addr_touse = sa;
    7286             : #ifdef INET6
    7287             :         if (sa->sa_family == AF_INET6) {
    7288             : #ifdef INET
    7289             :                 struct sockaddr_in6 *sin6;
    7290             : 
    7291             : #endif
    7292             : #ifdef HAVE_SA_LEN
    7293             :                 if (sa->sa_len != sizeof(struct sockaddr_in6)) {
    7294             :                         SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
    7295             :                         *error = EINVAL;
    7296             :                         return;
    7297             :                 }
    7298             : #endif
    7299             :                 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
    7300             :                         /* can only bind v6 on PF_INET6 sockets */
    7301             :                         SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
    7302             :                         *error = EINVAL;
    7303             :                         return;
    7304             :                 }
    7305             : #ifdef INET
    7306             :                 sin6 = (struct sockaddr_in6 *)addr_touse;
    7307             :                 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
    7308             :                         if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
    7309             :                             SCTP_IPV6_V6ONLY(inp)) {
    7310             :                                 /* can't bind v4-mapped on PF_INET sockets */
    7311             :                                 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
    7312             :                                 *error = EINVAL;
    7313             :                                 return;
    7314             :                         }
    7315             :                         in6_sin6_2_sin(&sin, sin6);
    7316             :                         addr_touse = (struct sockaddr *)&sin;
    7317             :                 }
    7318             : #endif
    7319             :         }
    7320             : #endif
    7321             : #ifdef INET
    7322             :         if (sa->sa_family == AF_INET) {
    7323             : #ifdef HAVE_SA_LEN
    7324             :                 if (sa->sa_len != sizeof(struct sockaddr_in)) {
    7325             :                         SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
    7326             :                         *error = EINVAL;
    7327             :                         return;
    7328             :                 }
    7329             : #endif
    7330             :                 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
    7331             :                     SCTP_IPV6_V6ONLY(inp)) {
    7332             :                         /* can't bind v4 on PF_INET sockets */
    7333             :                         SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
    7334             :                         *error = EINVAL;
    7335             :                         return;
    7336             :                 }
    7337             :         }
    7338             : #endif
    7339           0 :         if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
    7340             : #if !(defined(__Panda__) || defined(__Windows__))
    7341           0 :                 if (p == NULL) {
    7342             :                         /* Can't get proc for Net/Open BSD */
    7343             :                         SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
    7344           0 :                         *error = EINVAL;
    7345           0 :                         return;
    7346             :                 }
    7347             : #endif
    7348           0 :                 *error = sctp_inpcb_bind(so, addr_touse, NULL, p);
    7349           0 :                 return;
    7350             :         }
    7351             :         /*
    7352             :          * No locks required here since bind and mgmt_ep_sa
    7353             :          * all do their own locking. If we do something for
    7354             :          * the FIX: below we may need to lock in that case.
    7355             :          */
    7356           0 :         if (assoc_id == 0) {
    7357             :                 /* add the address */
    7358             :                 struct sctp_inpcb *lep;
    7359           0 :                 struct sockaddr_in *lsin = (struct sockaddr_in *)addr_touse;
    7360             : 
    7361             :                 /* validate the incoming port */
    7362           0 :                 if ((lsin->sin_port != 0) &&
    7363           0 :                     (lsin->sin_port != inp->sctp_lport)) {
    7364             :                         SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
    7365           0 :                         *error = EINVAL;
    7366           0 :                         return;
    7367             :                 } else {
    7368             :                         /* user specified 0 port, set it to existing port */
    7369           0 :                         lsin->sin_port = inp->sctp_lport;
    7370             :                 }
    7371             : 
    7372           0 :                 lep = sctp_pcb_findep(addr_touse, 1, 0, vrf_id);
    7373           0 :                 if (lep != NULL) {
    7374             :                         /*
    7375             :                          * We must decrement the refcount
    7376             :                          * since we have the ep already and
    7377             :                          * are binding. No remove going on
    7378             :                          * here.
    7379             :                          */
    7380           0 :                         SCTP_INP_DECR_REF(lep);
    7381             :                 }
    7382           0 :                 if (lep == inp) {
    7383             :                         /* already bound to it.. ok */
    7384           0 :                         return;
    7385           0 :                 } else if (lep == NULL) {
    7386           0 :                         ((struct sockaddr_in *)addr_touse)->sin_port = 0;
    7387           0 :                         *error = sctp_addr_mgmt_ep_sa(inp, addr_touse,
    7388             :                                                       SCTP_ADD_IP_ADDRESS,
    7389             :                                                       vrf_id, NULL);
    7390             :                 } else {
    7391           0 :                         *error = EADDRINUSE;
    7392             :                 }
    7393           0 :                 if (*error)
    7394           0 :                         return;
    7395             :         } else {
    7396             :                 /*
    7397             :                  * FIX: decide whether we allow assoc based
    7398             :                  * bindx
    7399             :                  */
    7400             :         }
    7401             : }
    7402             : 
    7403             : /*
    7404             :  * sctp_bindx(DELETE) for one address.
    7405             :  * assumes all arguments are valid/checked by caller.
    7406             :  */
    7407             : void
    7408           0 : sctp_bindx_delete_address(struct sctp_inpcb *inp,
    7409             :                           struct sockaddr *sa, sctp_assoc_t assoc_id,
    7410             :                           uint32_t vrf_id, int *error)
    7411             : {
    7412             :         struct sockaddr *addr_touse;
    7413             : #if defined(INET) && defined(INET6)
    7414             :         struct sockaddr_in sin;
    7415             : #endif
    7416             : #ifdef SCTP_MVRF
    7417             :         int i, fnd = 0;
    7418             : #endif
    7419             : 
    7420             :         /* see if we're bound all already! */
    7421           0 :         if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
    7422             :                 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
    7423           0 :                 *error = EINVAL;
    7424           0 :                 return;
    7425             :         }
    7426             : #ifdef SCTP_MVRF
    7427             :         /* Is the VRF one we have */
    7428             :         for (i = 0; i < inp->num_vrfs; i++) {
    7429             :                 if (vrf_id == inp->m_vrf_ids[i]) {
    7430             :                         fnd = 1;
    7431             :                         break;
    7432             :                 }
    7433             :         }
    7434             :         if (!fnd) {
    7435             :                 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
    7436             :                 *error = EINVAL;
    7437             :                 return;
    7438             :         }
    7439             : #endif
    7440           0 :         addr_touse = sa;
    7441             : #ifdef INET6
    7442             :         if (sa->sa_family == AF_INET6) {
    7443             : #ifdef INET
    7444             :                 struct sockaddr_in6 *sin6;
    7445             : #endif
    7446             : 
    7447             : #ifdef HAVE_SA_LEN
    7448             :                 if (sa->sa_len != sizeof(struct sockaddr_in6)) {
    7449             :                         SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
    7450             :                         *error = EINVAL;
    7451             :                         return;
    7452             :                 }
    7453             : #endif
    7454             :                 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
    7455             :                         /* can only bind v6 on PF_INET6 sockets */
    7456             :                         SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
    7457             :                         *error = EINVAL;
    7458             :                         return;
    7459             :                 }
    7460             : #ifdef INET
    7461             :                 sin6 = (struct sockaddr_in6 *)addr_touse;
    7462             :                 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
    7463             :                         if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
    7464             :                             SCTP_IPV6_V6ONLY(inp)) {
    7465             :                                 /* can't bind mapped-v4 on PF_INET sockets */
    7466             :                                 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
    7467             :                                 *error = EINVAL;
    7468             :                                 return;
    7469             :                         }
    7470             :                         in6_sin6_2_sin(&sin, sin6);
    7471             :                         addr_touse = (struct sockaddr *)&sin;
    7472             :                 }
    7473             : #endif
    7474             :         }
    7475             : #endif
    7476             : #ifdef INET
    7477             :         if (sa->sa_family == AF_INET) {
    7478             : #ifdef HAVE_SA_LEN
    7479             :                 if (sa->sa_len != sizeof(struct sockaddr_in)) {
    7480             :                         SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
    7481             :                         *error = EINVAL;
    7482             :                         return;
    7483             :                 }
    7484             : #endif
    7485             :                 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
    7486             :                     SCTP_IPV6_V6ONLY(inp)) {
    7487             :                         /* can't bind v4 on PF_INET sockets */
    7488             :                         SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
    7489             :                         *error = EINVAL;
    7490             :                         return;
    7491             :                 }
    7492             :         }
    7493             : #endif
    7494             :         /*
    7495             :          * No lock required mgmt_ep_sa does its own locking.
    7496             :          * If the FIX: below is ever changed we may need to
    7497             :          * lock before calling association level binding.
    7498             :          */
    7499           0 :         if (assoc_id == 0) {
    7500             :                 /* delete the address */
    7501           0 :                 *error = sctp_addr_mgmt_ep_sa(inp, addr_touse,
    7502             :                                               SCTP_DEL_IP_ADDRESS,
    7503             :                                               vrf_id, NULL);
    7504             :         } else {
    7505             :                 /*
    7506             :                  * FIX: decide whether we allow assoc based
    7507             :                  * bindx
    7508             :                  */
    7509             :         }
    7510             : }
    7511             : 
    7512             : /*
    7513             :  * returns the valid local address count for an assoc, taking into account
    7514             :  * all scoping rules
    7515             :  */
    7516             : int
    7517           0 : sctp_local_addr_count(struct sctp_tcb *stcb)
    7518             : {
    7519             :         int loopback_scope;
    7520             : #if defined(INET)
    7521             :         int ipv4_local_scope, ipv4_addr_legal;
    7522             : #endif
    7523             : #if defined (INET6)
    7524             :         int local_scope, site_scope, ipv6_addr_legal;
    7525             : #endif
    7526             : #if defined(__Userspace__)
    7527             :         int conn_addr_legal;
    7528             : #endif
    7529             :         struct sctp_vrf *vrf;
    7530             :         struct sctp_ifn *sctp_ifn;
    7531             :         struct sctp_ifa *sctp_ifa;
    7532           0 :         int count = 0;
    7533             : 
    7534             :         /* Turn on all the appropriate scopes */
    7535           0 :         loopback_scope = stcb->asoc.scope.loopback_scope;
    7536             : #if defined(INET)
    7537             :         ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope;
    7538             :         ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal;
    7539             : #endif
    7540             : #if defined(INET6)
    7541             :         local_scope = stcb->asoc.scope.local_scope;
    7542             :         site_scope = stcb->asoc.scope.site_scope;
    7543             :         ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal;
    7544             : #endif
    7545             : #if defined(__Userspace__)
    7546           0 :         conn_addr_legal = stcb->asoc.scope.conn_addr_legal;
    7547             : #endif
    7548           0 :         SCTP_IPI_ADDR_RLOCK();
    7549           0 :         vrf = sctp_find_vrf(stcb->asoc.vrf_id);
    7550           0 :         if (vrf == NULL) {
    7551             :                 /* no vrf, no addresses */
    7552           0 :                 SCTP_IPI_ADDR_RUNLOCK();
    7553           0 :                 return (0);
    7554             :         }
    7555             : 
    7556           0 :         if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
    7557             :                 /*
    7558             :                  * bound all case: go through all ifns on the vrf
    7559             :                  */
    7560           0 :                 LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
    7561           0 :                         if ((loopback_scope == 0) &&
    7562           0 :                             SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
    7563           0 :                                 continue;
    7564             :                         }
    7565           0 :                         LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
    7566           0 :                                 if (sctp_is_addr_restricted(stcb, sctp_ifa))
    7567           0 :                                         continue;
    7568           0 :                                 switch (sctp_ifa->address.sa.sa_family) {
    7569             : #ifdef INET
    7570             :                                 case AF_INET:
    7571             :                                         if (ipv4_addr_legal) {
    7572             :                                                 struct sockaddr_in *sin;
    7573             : 
    7574             :                                                 sin = &sctp_ifa->address.sin;
    7575             :                                                 if (sin->sin_addr.s_addr == 0) {
    7576             :                                                         /* skip unspecified addrs */
    7577             :                                                         continue;
    7578             :                                                 }
    7579             : #if defined(__FreeBSD__)
    7580             :                                                 if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred,
    7581             :                                                                      &sin->sin_addr) != 0) {
    7582             :                                                         continue;
    7583             :                                                 }
    7584             : #endif
    7585             :                                                 if ((ipv4_local_scope == 0) &&
    7586             :                                                     (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) {
    7587             :                                                         continue;
    7588             :                                                 }
    7589             :                                                 /* count this one */
    7590             :                                                 count++;
    7591             :                                         } else {
    7592             :                                                 continue;
    7593             :                                         }
    7594             :                                         break;
    7595             : #endif
    7596             : #ifdef INET6
    7597             :                                 case AF_INET6:
    7598             :                                         if (ipv6_addr_legal) {
    7599             :                                                 struct sockaddr_in6 *sin6;
    7600             : 
    7601             : #if defined(SCTP_EMBEDDED_V6_SCOPE) && !defined(SCTP_KAME)
    7602             :                                                 struct sockaddr_in6 lsa6;
    7603             : #endif
    7604             :                                                 sin6 = &sctp_ifa->address.sin6;
    7605             :                                                 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
    7606             :                                                         continue;
    7607             :                                                 }
    7608             : #if defined(__FreeBSD__)
    7609             :                                                 if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred,
    7610             :                                                                      &sin6->sin6_addr) != 0) {
    7611             :                                                         continue;
    7612             :                                                 }
    7613             : #endif
    7614             :                                                 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
    7615             :                                                         if (local_scope == 0)
    7616             :                                                                 continue;
    7617             : #if defined(SCTP_EMBEDDED_V6_SCOPE)
    7618             :                                                         if (sin6->sin6_scope_id == 0) {
    7619             : #ifdef SCTP_KAME
    7620             :                                                                 if (sa6_recoverscope(sin6) != 0)
    7621             :                                                                         /*
    7622             :                                                                          * bad link
    7623             :                                                                          * local
    7624             :                                                                          * address
    7625             :                                                                          */
    7626             :                                                                         continue;
    7627             : #else
    7628             :                                                                 lsa6 = *sin6;
    7629             :                                                                 if (in6_recoverscope(&lsa6,
    7630             :                                                                                      &lsa6.sin6_addr,
    7631             :                                                                                      NULL))
    7632             :                                                                         /*
    7633             :                                                                          * bad link
    7634             :                                                                          * local
    7635             :                                                                          * address
    7636             :                                                                          */
    7637             :                                                                         continue;
    7638             :                                                                 sin6 = &lsa6;
    7639             : #endif /* SCTP_KAME */
    7640             :                                                         }
    7641             : #endif /* SCTP_EMBEDDED_V6_SCOPE */
    7642             :                                                 }
    7643             :                                                 if ((site_scope == 0) &&
    7644             :                                                     (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) {
    7645             :                                                         continue;
    7646             :                                                 }
    7647             :                                                 /* count this one */
    7648             :                                                 count++;
    7649             :                                         }
    7650             :                                         break;
    7651             : #endif
    7652             : #if defined(__Userspace__)
    7653             :                                 case AF_CONN:
    7654           0 :                                         if (conn_addr_legal) {
    7655           0 :                                                 count++;
    7656             :                                         }
    7657           0 :                                         break;
    7658             : #endif
    7659             :                                 default:
    7660             :                                         /* TSNH */
    7661           0 :                                         break;
    7662             :                                 }
    7663             :                         }
    7664             :                 }
    7665             :         } else {
    7666             :                 /*
    7667             :                  * subset bound case
    7668             :                  */
    7669             :                 struct sctp_laddr *laddr;
    7670           0 :                 LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list,
    7671             :                              sctp_nxt_addr) {
    7672           0 :                         if (sctp_is_addr_restricted(stcb, laddr->ifa)) {
    7673           0 :                                 continue;
    7674             :                         }
    7675             :                         /* count this one */
    7676           0 :                         count++;
    7677             :                 }
    7678             :         }
    7679           0 :         SCTP_IPI_ADDR_RUNLOCK();
    7680           0 :         return (count);
    7681             : }
    7682             : 
    7683             : #if defined(SCTP_LOCAL_TRACE_BUF)
    7684             : 
    7685             : void
    7686             : sctp_log_trace(uint32_t subsys, const char *str SCTP_UNUSED, uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t e, uint32_t f)
    7687             : {
    7688             :         uint32_t saveindex, newindex;
    7689             : 
    7690             : #if defined(__Windows__)
    7691             :         if (SCTP_BASE_SYSCTL(sctp_log) == NULL) {
    7692             :                 return;
    7693             :         }
    7694             :         do {
    7695             :                 saveindex = SCTP_BASE_SYSCTL(sctp_log)->index;
    7696             :                 if (saveindex >= SCTP_MAX_LOGGING_SIZE) {
    7697             :                         newindex = 1;
    7698             :                 } else {
    7699             :                         newindex = saveindex + 1;
    7700             :                 }
    7701             :         } while (atomic_cmpset_int(&SCTP_BASE_SYSCTL(sctp_log)->index, saveindex, newindex) == 0);
    7702             :         if (saveindex >= SCTP_MAX_LOGGING_SIZE) {
    7703             :                 saveindex = 0;
    7704             :         }
    7705             :         SCTP_BASE_SYSCTL(sctp_log)->entry[saveindex].timestamp = SCTP_GET_CYCLECOUNT;
    7706             :         SCTP_BASE_SYSCTL(sctp_log)->entry[saveindex].subsys = subsys;
    7707             :         SCTP_BASE_SYSCTL(sctp_log)->entry[saveindex].params[0] = a;
    7708             :         SCTP_BASE_SYSCTL(sctp_log)->entry[saveindex].params[1] = b;
    7709             :         SCTP_BASE_SYSCTL(sctp_log)->entry[saveindex].params[2] = c;
    7710             :         SCTP_BASE_SYSCTL(sctp_log)->entry[saveindex].params[3] = d;
    7711             :         SCTP_BASE_SYSCTL(sctp_log)->entry[saveindex].params[4] = e;
    7712             :         SCTP_BASE_SYSCTL(sctp_log)->entry[saveindex].params[5] = f;
    7713             : #else
    7714             :         do {
    7715             :                 saveindex = SCTP_BASE_SYSCTL(sctp_log).index;
    7716             :                 if (saveindex >= SCTP_MAX_LOGGING_SIZE) {
    7717             :                         newindex = 1;
    7718             :                 } else {
    7719             :                         newindex = saveindex + 1;
    7720             :                 }
    7721             :         } while (atomic_cmpset_int(&SCTP_BASE_SYSCTL(sctp_log).index, saveindex, newindex) == 0);
    7722             :         if (saveindex >= SCTP_MAX_LOGGING_SIZE) {
    7723             :                 saveindex = 0;
    7724             :         }
    7725             :         SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].timestamp = SCTP_GET_CYCLECOUNT;
    7726             :         SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].subsys = subsys;
    7727             :         SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[0] = a;
    7728             :         SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[1] = b;
    7729             :         SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[2] = c;
    7730             :         SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[3] = d;
    7731             :         SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[4] = e;
    7732             :         SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[5] = f;
    7733             : #endif
    7734             : }
    7735             : 
    7736             : #endif
    7737             : #if defined(__FreeBSD__)
    7738             : #if __FreeBSD_version >= 800044
    7739             : static void
    7740             : sctp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *ignored,
    7741             :     const struct sockaddr *sa SCTP_UNUSED, void *ctx SCTP_UNUSED)
    7742             : {
    7743             :         struct ip *iph;
    7744             : #ifdef INET6
    7745             :         struct ip6_hdr *ip6;
    7746             : #endif
    7747             :         struct mbuf *sp, *last;
    7748             :         struct udphdr *uhdr;
    7749             :         uint16_t port;
    7750             : 
    7751             :         if ((m->m_flags & M_PKTHDR) == 0) {
    7752             :                 /* Can't handle one that is not a pkt hdr */
    7753             :                 goto out;
    7754             :         }
    7755             :         /* Pull the src port */
    7756             :         iph = mtod(m, struct ip *);
    7757             :         uhdr = (struct udphdr *)((caddr_t)iph + off);
    7758             :         port = uhdr->uh_sport;
    7759             :         /* Split out the mbuf chain. Leave the
    7760             :          * IP header in m, place the
    7761             :          * rest in the sp.
    7762             :          */
    7763             :         sp = m_split(m, off, M_NOWAIT);
    7764             :         if (sp == NULL) {
    7765             :                 /* Gak, drop packet, we can't do a split */
    7766             :                 goto out;
    7767             :         }
    7768             :         if (sp->m_pkthdr.len < sizeof(struct udphdr) + sizeof(struct sctphdr)) {
    7769             :                 /* Gak, packet can't have an SCTP header in it - too small */
    7770             :                 m_freem(sp);
    7771             :                 goto out;
    7772             :         }
    7773             :         /* Now pull up the UDP header and SCTP header together */
    7774             :         sp = m_pullup(sp, sizeof(struct udphdr) + sizeof(struct sctphdr));
    7775             :         if (sp == NULL) {
    7776             :                 /* Gak pullup failed */
    7777             :                 goto out;
    7778             :         }
    7779             :         /* Trim out the UDP header */
    7780             :         m_adj(sp, sizeof(struct udphdr));
    7781             : 
    7782             :         /* Now reconstruct the mbuf chain */
    7783             :         for (last = m; last->m_next; last = last->m_next);
    7784             :         last->m_next = sp;
    7785             :         m->m_pkthdr.len += sp->m_pkthdr.len;
    7786             :         iph = mtod(m, struct ip *);
    7787             :         switch (iph->ip_v) {
    7788             : #ifdef INET
    7789             :         case IPVERSION:
    7790             : #if __FreeBSD_version >= 1000000
    7791             :                 iph->ip_len = htons(ntohs(iph->ip_len) - sizeof(struct udphdr));
    7792             : #else
    7793             :                 iph->ip_len -= sizeof(struct udphdr);
    7794             : #endif
    7795             :                 sctp_input_with_port(m, off, port);
    7796             :                 break;
    7797             : #endif
    7798             : #ifdef INET6
    7799             :         case IPV6_VERSION >> 4:
    7800             :                 ip6 = mtod(m, struct ip6_hdr *);
    7801             :                 ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - sizeof(struct udphdr));
    7802             :                 sctp6_input_with_port(&m, &off, port);
    7803             :                 break;
    7804             : #endif
    7805             :         default:
    7806             :                 goto out;
    7807             :                 break;
    7808             :         }
    7809             :         return;
    7810             :  out:
    7811             :         m_freem(m);
    7812             : }
    7813             : #endif
    7814             : 
    7815             : void
    7816             : sctp_over_udp_stop(void)
    7817             : {
    7818             :         /*
    7819             :          * This function assumes sysctl caller holds sctp_sysctl_info_lock() for writting!
    7820             :          */
    7821             : #ifdef INET
    7822             :         if (SCTP_BASE_INFO(udp4_tun_socket) != NULL) {
    7823             :                 soclose(SCTP_BASE_INFO(udp4_tun_socket));
    7824             :                 SCTP_BASE_INFO(udp4_tun_socket) = NULL;
    7825             :         }
    7826             : #endif
    7827             : #ifdef INET6
    7828             :         if (SCTP_BASE_INFO(udp6_tun_socket) != NULL) {
    7829             :                 soclose(SCTP_BASE_INFO(udp6_tun_socket));
    7830             :                 SCTP_BASE_INFO(udp6_tun_socket) = NULL;
    7831             :         }
    7832             : #endif
    7833             : }
    7834             : 
    7835             : int
    7836             : sctp_over_udp_start(void)
    7837             : {
    7838             : #if __FreeBSD_version >= 800044
    7839             :         uint16_t port;
    7840             :         int ret;
    7841             : #ifdef INET
    7842             :         struct sockaddr_in sin;
    7843             : #endif
    7844             : #ifdef INET6
    7845             :         struct sockaddr_in6 sin6;
    7846             : #endif
    7847             :         /*
    7848             :          * This function assumes sysctl caller holds sctp_sysctl_info_lock() for writting!
    7849             :          */
    7850             :         port = SCTP_BASE_SYSCTL(sctp_udp_tunneling_port);
    7851             :         if (ntohs(port) == 0) {
    7852             :                 /* Must have a port set */
    7853             :                 return (EINVAL);
    7854             :         }
    7855             : #ifdef INET
    7856             :         if (SCTP_BASE_INFO(udp4_tun_socket) != NULL) {
    7857             :                 /* Already running -- must stop first */
    7858             :                 return (EALREADY);
    7859             :         }
    7860             : #endif
    7861             : #ifdef INET6
    7862             :         if (SCTP_BASE_INFO(udp6_tun_socket) != NULL) {
    7863             :                 /* Already running -- must stop first */
    7864             :                 return (EALREADY);
    7865             :         }
    7866             : #endif
    7867             : #ifdef INET
    7868             :         if ((ret = socreate(PF_INET, &SCTP_BASE_INFO(udp4_tun_socket),
    7869             :                             SOCK_DGRAM, IPPROTO_UDP,
    7870             :                             curthread->td_ucred, curthread))) {
    7871             :                 sctp_over_udp_stop();
    7872             :                 return (ret);
    7873             :         }
    7874             :         /* Call the special UDP hook. */
    7875             :         if ((ret = udp_set_kernel_tunneling(SCTP_BASE_INFO(udp4_tun_socket),
    7876             :                                             sctp_recv_udp_tunneled_packet, NULL))) {
    7877             :                 sctp_over_udp_stop();
    7878             :                 return (ret);
    7879             :         }
    7880             :         /* Ok, we have a socket, bind it to the port. */
    7881             :         memset(&sin, 0, sizeof(struct sockaddr_in));
    7882             :         sin.sin_len = sizeof(struct sockaddr_in);
    7883             :         sin.sin_family = AF_INET;
    7884             :         sin.sin_port = htons(port);
    7885             :         if ((ret = sobind(SCTP_BASE_INFO(udp4_tun_socket),
    7886             :                           (struct sockaddr *)&sin, curthread))) {
    7887             :                 sctp_over_udp_stop();
    7888             :                 return (ret);
    7889             :         }
    7890             : #endif
    7891             : #ifdef INET6
    7892             :         if ((ret = socreate(PF_INET6, &SCTP_BASE_INFO(udp6_tun_socket),
    7893             :                             SOCK_DGRAM, IPPROTO_UDP,
    7894             :                             curthread->td_ucred, curthread))) {
    7895             :                 sctp_over_udp_stop();
    7896             :                 return (ret);
    7897             :         }
    7898             :         /* Call the special UDP hook. */
    7899             :         if ((ret = udp_set_kernel_tunneling(SCTP_BASE_INFO(udp6_tun_socket),
    7900             :                                             sctp_recv_udp_tunneled_packet, NULL))) {
    7901             :                 sctp_over_udp_stop();
    7902             :                 return (ret);
    7903             :         }
    7904             :         /* Ok, we have a socket, bind it to the port. */
    7905             :         memset(&sin6, 0, sizeof(struct sockaddr_in6));
    7906             :         sin6.sin6_len = sizeof(struct sockaddr_in6);
    7907             :         sin6.sin6_family = AF_INET6;
    7908             :         sin6.sin6_port = htons(port);
    7909             :         if ((ret = sobind(SCTP_BASE_INFO(udp6_tun_socket),
    7910             :                           (struct sockaddr *)&sin6, curthread))) {
    7911             :                 sctp_over_udp_stop();
    7912             :                 return (ret);
    7913             :         }
    7914             : #endif
    7915             :         return (0);
    7916             : #else
    7917             :         return (ENOTSUP);
    7918             : #endif
    7919             : }
    7920             : #endif

Generated by: LCOV version 1.13