/netinet/sctputil.c
C | 7726 lines | 6422 code | 376 blank | 928 comment | 1694 complexity | 5b1ab6f6258d7e6de6120e6fe7ae9ca4 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- /*-
- * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved.
- * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
- * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * b) Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the distribution.
- *
- * c) Neither the name of Cisco Systems, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
- #ifdef __FreeBSD__
- #include <sys/cdefs.h>
- __FBSDID("$FreeBSD: head/sys/netinet/sctputil.c 235828 2012-05-23 11:26:28Z tuexen $");
- #endif
-
- #include <netinet/sctp_os.h>
- #include <netinet/sctp_pcb.h>
- #include <netinet/sctputil.h>
- #include <netinet/sctp_var.h>
- #include <netinet/sctp_sysctl.h>
- #ifdef INET6
- #if defined(__Userspace__)
- #include <netinet6/sctp6_var.h>
- #endif
- #endif
- #include <netinet/sctp_header.h>
- #include <netinet/sctp_output.h>
- #include <netinet/sctp_uio.h>
- #include <netinet/sctp_timer.h>
- #include <netinet/sctp_indata.h>/* for sctp_deliver_data() */
- #include <netinet/sctp_auth.h>
- #include <netinet/sctp_asconf.h>
- #include <netinet/sctp_windows_addr.h>
- #if defined(__Userspace__)
- #include <netinet/sctp_constants.h>
- #endif
-
- #if defined(__APPLE__)
- #define APPLE_FILE_NO 8
- #endif
-
- #if defined(__Windows__)
- #if !defined(SCTP_LOCAL_TRACE_BUF)
- #include "eventrace_netinet.h"
- #include "sctputil.tmh" /* this is the file that will be auto generated */
- #endif
- #else
- #ifndef KTR_SCTP
- #define KTR_SCTP KTR_SUBSYS
- #endif
- #endif
-
- extern struct sctp_cc_functions sctp_cc_functions[];
- extern struct sctp_ss_functions sctp_ss_functions[];
-
- void
- sctp_sblog(struct sockbuf *sb,
- struct sctp_tcb *stcb, int from, int incr)
- {
- struct sctp_cwnd_log sctp_clog;
-
- sctp_clog.x.sb.stcb = stcb;
- sctp_clog.x.sb.so_sbcc = sb->sb_cc;
- if (stcb)
- sctp_clog.x.sb.stcb_sbcc = stcb->asoc.sb_cc;
- else
- sctp_clog.x.sb.stcb_sbcc = 0;
- sctp_clog.x.sb.incr = incr;
- SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
- SCTP_LOG_EVENT_SB,
- from,
- sctp_clog.x.misc.log1,
- sctp_clog.x.misc.log2,
- sctp_clog.x.misc.log3,
- sctp_clog.x.misc.log4);
- }
-
- void
- sctp_log_closing(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int16_t loc)
- {
- struct sctp_cwnd_log sctp_clog;
-
- sctp_clog.x.close.inp = (void *)inp;
- sctp_clog.x.close.sctp_flags = inp->sctp_flags;
- if (stcb) {
- sctp_clog.x.close.stcb = (void *)stcb;
- sctp_clog.x.close.state = (uint16_t)stcb->asoc.state;
- } else {
- sctp_clog.x.close.stcb = 0;
- sctp_clog.x.close.state = 0;
- }
- sctp_clog.x.close.loc = loc;
- SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
- SCTP_LOG_EVENT_CLOSE,
- 0,
- sctp_clog.x.misc.log1,
- sctp_clog.x.misc.log2,
- sctp_clog.x.misc.log3,
- sctp_clog.x.misc.log4);
- }
-
-
- void
- rto_logging(struct sctp_nets *net, int from)
- {
- struct sctp_cwnd_log sctp_clog;
-
- memset(&sctp_clog, 0, sizeof(sctp_clog));
- sctp_clog.x.rto.net = (void *) net;
- sctp_clog.x.rto.rtt = net->rtt / 1000;
- SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
- SCTP_LOG_EVENT_RTT,
- from,
- sctp_clog.x.misc.log1,
- sctp_clog.x.misc.log2,
- sctp_clog.x.misc.log3,
- sctp_clog.x.misc.log4);
- }
-
- void
- sctp_log_strm_del_alt(struct sctp_tcb *stcb, uint32_t tsn, uint16_t sseq, uint16_t stream, int from)
- {
- struct sctp_cwnd_log sctp_clog;
-
- sctp_clog.x.strlog.stcb = stcb;
- sctp_clog.x.strlog.n_tsn = tsn;
- sctp_clog.x.strlog.n_sseq = sseq;
- sctp_clog.x.strlog.e_tsn = 0;
- sctp_clog.x.strlog.e_sseq = 0;
- sctp_clog.x.strlog.strm = stream;
- SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
- SCTP_LOG_EVENT_STRM,
- from,
- sctp_clog.x.misc.log1,
- sctp_clog.x.misc.log2,
- sctp_clog.x.misc.log3,
- sctp_clog.x.misc.log4);
- }
-
- void
- sctp_log_nagle_event(struct sctp_tcb *stcb, int action)
- {
- struct sctp_cwnd_log sctp_clog;
-
- sctp_clog.x.nagle.stcb = (void *)stcb;
- sctp_clog.x.nagle.total_flight = stcb->asoc.total_flight;
- sctp_clog.x.nagle.total_in_queue = stcb->asoc.total_output_queue_size;
- sctp_clog.x.nagle.count_in_queue = stcb->asoc.chunks_on_out_queue;
- sctp_clog.x.nagle.count_in_flight = stcb->asoc.total_flight_count;
- SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
- SCTP_LOG_EVENT_NAGLE,
- action,
- sctp_clog.x.misc.log1,
- sctp_clog.x.misc.log2,
- sctp_clog.x.misc.log3,
- sctp_clog.x.misc.log4);
- }
-
- void
- sctp_log_sack(uint32_t old_cumack, uint32_t cumack, uint32_t tsn, uint16_t gaps, uint16_t dups, int from)
- {
- struct sctp_cwnd_log sctp_clog;
-
- sctp_clog.x.sack.cumack = cumack;
- sctp_clog.x.sack.oldcumack = old_cumack;
- sctp_clog.x.sack.tsn = tsn;
- sctp_clog.x.sack.numGaps = gaps;
- sctp_clog.x.sack.numDups = dups;
- SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
- SCTP_LOG_EVENT_SACK,
- from,
- sctp_clog.x.misc.log1,
- sctp_clog.x.misc.log2,
- sctp_clog.x.misc.log3,
- sctp_clog.x.misc.log4);
- }
-
- void
- sctp_log_map(uint32_t map, uint32_t cum, uint32_t high, int from)
- {
- struct sctp_cwnd_log sctp_clog;
-
- memset(&sctp_clog, 0, sizeof(sctp_clog));
- sctp_clog.x.map.base = map;
- sctp_clog.x.map.cum = cum;
- sctp_clog.x.map.high = high;
- SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
- SCTP_LOG_EVENT_MAP,
- from,
- sctp_clog.x.misc.log1,
- sctp_clog.x.misc.log2,
- sctp_clog.x.misc.log3,
- sctp_clog.x.misc.log4);
- }
-
- void
- sctp_log_fr(uint32_t biggest_tsn, uint32_t biggest_new_tsn, uint32_t tsn,
- int from)
- {
- struct sctp_cwnd_log sctp_clog;
-
- memset(&sctp_clog, 0, sizeof(sctp_clog));
- sctp_clog.x.fr.largest_tsn = biggest_tsn;
- sctp_clog.x.fr.largest_new_tsn = biggest_new_tsn;
- sctp_clog.x.fr.tsn = tsn;
- SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
- SCTP_LOG_EVENT_FR,
- from,
- sctp_clog.x.misc.log1,
- sctp_clog.x.misc.log2,
- sctp_clog.x.misc.log3,
- sctp_clog.x.misc.log4);
- }
-
- void
- sctp_log_mb(struct mbuf *m, int from)
- {
- struct sctp_cwnd_log sctp_clog;
-
- sctp_clog.x.mb.mp = m;
- sctp_clog.x.mb.mbuf_flags = (uint8_t)(SCTP_BUF_GET_FLAGS(m));
- sctp_clog.x.mb.size = (uint16_t)(SCTP_BUF_LEN(m));
- sctp_clog.x.mb.data = SCTP_BUF_AT(m, 0);
- if (SCTP_BUF_IS_EXTENDED(m)) {
- sctp_clog.x.mb.ext = SCTP_BUF_EXTEND_BASE(m);
- #if defined(__APPLE__)
- /* APPLE does not use a ref_cnt, but a forward/backward ref queue */
- #else
- sctp_clog.x.mb.refcnt = (uint8_t)(SCTP_BUF_EXTEND_REFCNT(m));
- #endif
- } else {
- sctp_clog.x.mb.ext = 0;
- sctp_clog.x.mb.refcnt = 0;
- }
- SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
- SCTP_LOG_EVENT_MBUF,
- from,
- sctp_clog.x.misc.log1,
- sctp_clog.x.misc.log2,
- sctp_clog.x.misc.log3,
- sctp_clog.x.misc.log4);
- }
-
- void
- sctp_log_strm_del(struct sctp_queued_to_read *control, struct sctp_queued_to_read *poschk,
- int from)
- {
- struct sctp_cwnd_log sctp_clog;
-
- if (control == NULL) {
- SCTP_PRINTF("Gak log of NULL?\n");
- return;
- }
- sctp_clog.x.strlog.stcb = control->stcb;
- sctp_clog.x.strlog.n_tsn = control->sinfo_tsn;
- sctp_clog.x.strlog.n_sseq = control->sinfo_ssn;
- sctp_clog.x.strlog.strm = control->sinfo_stream;
- if (poschk != NULL) {
- sctp_clog.x.strlog.e_tsn = poschk->sinfo_tsn;
- sctp_clog.x.strlog.e_sseq = poschk->sinfo_ssn;
- } else {
- sctp_clog.x.strlog.e_tsn = 0;
- sctp_clog.x.strlog.e_sseq = 0;
- }
- SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
- SCTP_LOG_EVENT_STRM,
- from,
- sctp_clog.x.misc.log1,
- sctp_clog.x.misc.log2,
- sctp_clog.x.misc.log3,
- sctp_clog.x.misc.log4);
- }
-
- void
- sctp_log_cwnd(struct sctp_tcb *stcb, struct sctp_nets *net, int augment, uint8_t from)
- {
- struct sctp_cwnd_log sctp_clog;
-
- sctp_clog.x.cwnd.net = net;
- if (stcb->asoc.send_queue_cnt > 255)
- sctp_clog.x.cwnd.cnt_in_send = 255;
- else
- sctp_clog.x.cwnd.cnt_in_send = stcb->asoc.send_queue_cnt;
- if (stcb->asoc.stream_queue_cnt > 255)
- sctp_clog.x.cwnd.cnt_in_str = 255;
- else
- sctp_clog.x.cwnd.cnt_in_str = stcb->asoc.stream_queue_cnt;
-
- if (net) {
- sctp_clog.x.cwnd.cwnd_new_value = net->cwnd;
- sctp_clog.x.cwnd.inflight = net->flight_size;
- sctp_clog.x.cwnd.pseudo_cumack = net->pseudo_cumack;
- sctp_clog.x.cwnd.meets_pseudo_cumack = net->new_pseudo_cumack;
- sctp_clog.x.cwnd.need_new_pseudo_cumack = net->find_pseudo_cumack;
- }
- if (SCTP_CWNDLOG_PRESEND == from) {
- sctp_clog.x.cwnd.meets_pseudo_cumack = stcb->asoc.peers_rwnd;
- }
- sctp_clog.x.cwnd.cwnd_augment = augment;
- SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
- SCTP_LOG_EVENT_CWND,
- from,
- sctp_clog.x.misc.log1,
- sctp_clog.x.misc.log2,
- sctp_clog.x.misc.log3,
- sctp_clog.x.misc.log4);
- }
-
- #ifndef __APPLE__
- void
- sctp_log_lock(struct sctp_inpcb *inp, struct sctp_tcb *stcb, uint8_t from)
- {
- struct sctp_cwnd_log sctp_clog;
-
- memset(&sctp_clog, 0, sizeof(sctp_clog));
- if (inp) {
- sctp_clog.x.lock.sock = (void *) inp->sctp_socket;
-
- } else {
- sctp_clog.x.lock.sock = (void *) NULL;
- }
- sctp_clog.x.lock.inp = (void *) inp;
- #if (defined(__FreeBSD__) && __FreeBSD_version >= 503000) || (defined(__APPLE__))
- if (stcb) {
- sctp_clog.x.lock.tcb_lock = mtx_owned(&stcb->tcb_mtx);
- } else {
- sctp_clog.x.lock.tcb_lock = SCTP_LOCK_UNKNOWN;
- }
- if (inp) {
- sctp_clog.x.lock.inp_lock = mtx_owned(&inp->inp_mtx);
- sctp_clog.x.lock.create_lock = mtx_owned(&inp->inp_create_mtx);
- } else {
- sctp_clog.x.lock.inp_lock = SCTP_LOCK_UNKNOWN;
- sctp_clog.x.lock.create_lock = SCTP_LOCK_UNKNOWN;
- }
- #if (defined(__FreeBSD__) && __FreeBSD_version <= 602000)
- sctp_clog.x.lock.info_lock = mtx_owned(&SCTP_BASE_INFO(ipi_ep_mtx));
- #else
- sctp_clog.x.lock.info_lock = rw_wowned(&SCTP_BASE_INFO(ipi_ep_mtx));
- #endif
- if (inp && (inp->sctp_socket)) {
- sctp_clog.x.lock.sock_lock = mtx_owned(&(inp->sctp_socket->so_rcv.sb_mtx));
- sctp_clog.x.lock.sockrcvbuf_lock = mtx_owned(&(inp->sctp_socket->so_rcv.sb_mtx));
- sctp_clog.x.lock.socksndbuf_lock = mtx_owned(&(inp->sctp_socket->so_snd.sb_mtx));
- } else {
- sctp_clog.x.lock.sock_lock = SCTP_LOCK_UNKNOWN;
- sctp_clog.x.lock.sockrcvbuf_lock = SCTP_LOCK_UNKNOWN;
- sctp_clog.x.lock.socksndbuf_lock = SCTP_LOCK_UNKNOWN;
- }
- #endif
- SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
- SCTP_LOG_LOCK_EVENT,
- from,
- sctp_clog.x.misc.log1,
- sctp_clog.x.misc.log2,
- sctp_clog.x.misc.log3,
- sctp_clog.x.misc.log4);
- }
- #endif
-
- void
- sctp_log_maxburst(struct sctp_tcb *stcb, struct sctp_nets *net, int error, int burst, uint8_t from)
- {
- struct sctp_cwnd_log sctp_clog;
-
- memset(&sctp_clog, 0, sizeof(sctp_clog));
- sctp_clog.x.cwnd.net = net;
- sctp_clog.x.cwnd.cwnd_new_value = error;
- sctp_clog.x.cwnd.inflight = net->flight_size;
- sctp_clog.x.cwnd.cwnd_augment = burst;
- if (stcb->asoc.send_queue_cnt > 255)
- sctp_clog.x.cwnd.cnt_in_send = 255;
- else
- sctp_clog.x.cwnd.cnt_in_send = stcb->asoc.send_queue_cnt;
- if (stcb->asoc.stream_queue_cnt > 255)
- sctp_clog.x.cwnd.cnt_in_str = 255;
- else
- sctp_clog.x.cwnd.cnt_in_str = stcb->asoc.stream_queue_cnt;
- SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
- SCTP_LOG_EVENT_MAXBURST,
- from,
- sctp_clog.x.misc.log1,
- sctp_clog.x.misc.log2,
- sctp_clog.x.misc.log3,
- sctp_clog.x.misc.log4);
- }
-
- void
- sctp_log_rwnd(uint8_t from, uint32_t peers_rwnd, uint32_t snd_size, uint32_t overhead)
- {
- struct sctp_cwnd_log sctp_clog;
-
- sctp_clog.x.rwnd.rwnd = peers_rwnd;
- sctp_clog.x.rwnd.send_size = snd_size;
- sctp_clog.x.rwnd.overhead = overhead;
- sctp_clog.x.rwnd.new_rwnd = 0;
- SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
- SCTP_LOG_EVENT_RWND,
- from,
- sctp_clog.x.misc.log1,
- sctp_clog.x.misc.log2,
- sctp_clog.x.misc.log3,
- sctp_clog.x.misc.log4);
- }
-
- void
- sctp_log_rwnd_set(uint8_t from, uint32_t peers_rwnd, uint32_t flight_size, uint32_t overhead, uint32_t a_rwndval)
- {
- struct sctp_cwnd_log sctp_clog;
-
- sctp_clog.x.rwnd.rwnd = peers_rwnd;
- sctp_clog.x.rwnd.send_size = flight_size;
- sctp_clog.x.rwnd.overhead = overhead;
- sctp_clog.x.rwnd.new_rwnd = a_rwndval;
- SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
- SCTP_LOG_EVENT_RWND,
- from,
- sctp_clog.x.misc.log1,
- sctp_clog.x.misc.log2,
- sctp_clog.x.misc.log3,
- sctp_clog.x.misc.log4);
- }
-
- void
- sctp_log_mbcnt(uint8_t from, uint32_t total_oq, uint32_t book, uint32_t total_mbcnt_q, uint32_t mbcnt)
- {
- struct sctp_cwnd_log sctp_clog;
-
- sctp_clog.x.mbcnt.total_queue_size = total_oq;
- sctp_clog.x.mbcnt.size_change = book;
- sctp_clog.x.mbcnt.total_queue_mb_size = total_mbcnt_q;
- sctp_clog.x.mbcnt.mbcnt_change = mbcnt;
- SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
- SCTP_LOG_EVENT_MBCNT,
- from,
- sctp_clog.x.misc.log1,
- sctp_clog.x.misc.log2,
- sctp_clog.x.misc.log3,
- sctp_clog.x.misc.log4);
- }
-
- void
- sctp_misc_ints(uint8_t from, uint32_t a, uint32_t b, uint32_t c, uint32_t d)
- {
- SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
- SCTP_LOG_MISC_EVENT,
- from,
- a, b, c, d);
- }
-
- void
- sctp_wakeup_log(struct sctp_tcb *stcb, uint32_t wake_cnt, int from)
- {
- struct sctp_cwnd_log sctp_clog;
-
- sctp_clog.x.wake.stcb = (void *)stcb;
- sctp_clog.x.wake.wake_cnt = wake_cnt;
- sctp_clog.x.wake.flight = stcb->asoc.total_flight_count;
- sctp_clog.x.wake.send_q = stcb->asoc.send_queue_cnt;
- sctp_clog.x.wake.sent_q = stcb->asoc.sent_queue_cnt;
-
- if (stcb->asoc.stream_queue_cnt < 0xff)
- sctp_clog.x.wake.stream_qcnt = (uint8_t) stcb->asoc.stream_queue_cnt;
- else
- sctp_clog.x.wake.stream_qcnt = 0xff;
-
- if (stcb->asoc.chunks_on_out_queue < 0xff)
- sctp_clog.x.wake.chunks_on_oque = (uint8_t) stcb->asoc.chunks_on_out_queue;
- else
- sctp_clog.x.wake.chunks_on_oque = 0xff;
-
- sctp_clog.x.wake.sctpflags = 0;
- /* set in the defered mode stuff */
- if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_DONT_WAKE)
- sctp_clog.x.wake.sctpflags |= 1;
- if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_WAKEOUTPUT)
- sctp_clog.x.wake.sctpflags |= 2;
- if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_WAKEINPUT)
- sctp_clog.x.wake.sctpflags |= 4;
- /* what about the sb */
- if (stcb->sctp_socket) {
- struct socket *so = stcb->sctp_socket;
-
- sctp_clog.x.wake.sbflags = (uint8_t)((so->so_snd.sb_flags & 0x00ff));
- } else {
- sctp_clog.x.wake.sbflags = 0xff;
- }
- SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
- SCTP_LOG_EVENT_WAKE,
- from,
- sctp_clog.x.misc.log1,
- sctp_clog.x.misc.log2,
- sctp_clog.x.misc.log3,
- sctp_clog.x.misc.log4);
- }
-
- void
- sctp_log_block(uint8_t from, struct sctp_association *asoc, int sendlen)
- {
- struct sctp_cwnd_log sctp_clog;
-
- sctp_clog.x.blk.onsb = asoc->total_output_queue_size;
- sctp_clog.x.blk.send_sent_qcnt = (uint16_t) (asoc->send_queue_cnt + asoc->sent_queue_cnt);
- sctp_clog.x.blk.peer_rwnd = asoc->peers_rwnd;
- sctp_clog.x.blk.stream_qcnt = (uint16_t) asoc->stream_queue_cnt;
- sctp_clog.x.blk.chunks_on_oque = (uint16_t) asoc->chunks_on_out_queue;
- sctp_clog.x.blk.flight_size = (uint16_t) (asoc->total_flight/1024);
- sctp_clog.x.blk.sndlen = sendlen;
- SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
- SCTP_LOG_EVENT_BLOCK,
- from,
- sctp_clog.x.misc.log1,
- sctp_clog.x.misc.log2,
- sctp_clog.x.misc.log3,
- sctp_clog.x.misc.log4);
- }
-
- int
- sctp_fill_stat_log(void *optval SCTP_UNUSED, size_t *optsize SCTP_UNUSED)
- {
- /* May need to fix this if ktrdump does not work */
- return (0);
- }
-
- #ifdef SCTP_AUDITING_ENABLED
- uint8_t sctp_audit_data[SCTP_AUDIT_SIZE][2];
- static int sctp_audit_indx = 0;
-
- static
- void
- sctp_print_audit_report(void)
- {
- int i;
- int cnt;
-
- cnt = 0;
- for (i = sctp_audit_indx; i < SCTP_AUDIT_SIZE; i++) {
- if ((sctp_audit_data[i][0] == 0xe0) &&
- (sctp_audit_data[i][1] == 0x01)) {
- cnt = 0;
- SCTP_PRINTF("\n");
- } else if (sctp_audit_data[i][0] == 0xf0) {
- cnt = 0;
- SCTP_PRINTF("\n");
- } else if ((sctp_audit_data[i][0] == 0xc0) &&
- (sctp_audit_data[i][1] == 0x01)) {
- SCTP_PRINTF("\n");
- cnt = 0;
- }
- SCTP_PRINTF("%2.2x%2.2x ", (uint32_t) sctp_audit_data[i][0],
- (uint32_t) sctp_audit_data[i][1]);
- cnt++;
- if ((cnt % 14) == 0)
- SCTP_PRINTF("\n");
- }
- for (i = 0; i < sctp_audit_indx; i++) {
- if ((sctp_audit_data[i][0] == 0xe0) &&
- (sctp_audit_data[i][1] == 0x01)) {
- cnt = 0;
- SCTP_PRINTF("\n");
- } else if (sctp_audit_data[i][0] == 0xf0) {
- cnt = 0;
- SCTP_PRINTF("\n");
- } else if ((sctp_audit_data[i][0] == 0xc0) &&
- (sctp_audit_data[i][1] == 0x01)) {
- SCTP_PRINTF("\n");
- cnt = 0;
- }
- SCTP_PRINTF("%2.2x%2.2x ", (uint32_t) sctp_audit_data[i][0],
- (uint32_t) sctp_audit_data[i][1]);
- cnt++;
- if ((cnt % 14) == 0)
- SCTP_PRINTF("\n");
- }
- SCTP_PRINTF("\n");
- }
-
- void
- sctp_auditing(int from, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
- struct sctp_nets *net)
- {
- int resend_cnt, tot_out, rep, tot_book_cnt;
- struct sctp_nets *lnet;
- struct sctp_tmit_chunk *chk;
-
- sctp_audit_data[sctp_audit_indx][0] = 0xAA;
- sctp_audit_data[sctp_audit_indx][1] = 0x000000ff & from;
- sctp_audit_indx++;
- if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
- sctp_audit_indx = 0;
- }
- if (inp == NULL) {
- sctp_audit_data[sctp_audit_indx][0] = 0xAF;
- sctp_audit_data[sctp_audit_indx][1] = 0x01;
- sctp_audit_indx++;
- if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
- sctp_audit_indx = 0;
- }
- return;
- }
- if (stcb == NULL) {
- sctp_audit_data[sctp_audit_indx][0] = 0xAF;
- sctp_audit_data[sctp_audit_indx][1] = 0x02;
- sctp_audit_indx++;
- if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
- sctp_audit_indx = 0;
- }
- return;
- }
- sctp_audit_data[sctp_audit_indx][0] = 0xA1;
- sctp_audit_data[sctp_audit_indx][1] =
- (0x000000ff & stcb->asoc.sent_queue_retran_cnt);
- sctp_audit_indx++;
- if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
- sctp_audit_indx = 0;
- }
- rep = 0;
- tot_book_cnt = 0;
- resend_cnt = tot_out = 0;
- TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
- if (chk->sent == SCTP_DATAGRAM_RESEND) {
- resend_cnt++;
- } else if (chk->sent < SCTP_DATAGRAM_RESEND) {
- tot_out += chk->book_size;
- tot_book_cnt++;
- }
- }
- if (resend_cnt != stcb->asoc.sent_queue_retran_cnt) {
- sctp_audit_data[sctp_audit_indx][0] = 0xAF;
- sctp_audit_data[sctp_audit_indx][1] = 0xA1;
- sctp_audit_indx++;
- if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
- sctp_audit_indx = 0;
- }
- SCTP_PRINTF("resend_cnt:%d asoc-tot:%d\n",
- resend_cnt, stcb->asoc.sent_queue_retran_cnt);
- rep = 1;
- stcb->asoc.sent_queue_retran_cnt = resend_cnt;
- sctp_audit_data[sctp_audit_indx][0] = 0xA2;
- sctp_audit_data[sctp_audit_indx][1] =
- (0x000000ff & stcb->asoc.sent_queue_retran_cnt);
- sctp_audit_indx++;
- if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
- sctp_audit_indx = 0;
- }
- }
- if (tot_out != stcb->asoc.total_flight) {
- sctp_audit_data[sctp_audit_indx][0] = 0xAF;
- sctp_audit_data[sctp_audit_indx][1] = 0xA2;
- sctp_audit_indx++;
- if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
- sctp_audit_indx = 0;
- }
- rep = 1;
- SCTP_PRINTF("tot_flt:%d asoc_tot:%d\n", tot_out,
- (int)stcb->asoc.total_flight);
- stcb->asoc.total_flight = tot_out;
- }
- if (tot_book_cnt != stcb->asoc.total_flight_count) {
- sctp_audit_data[sctp_audit_indx][0] = 0xAF;
- sctp_audit_data[sctp_audit_indx][1] = 0xA5;
- sctp_audit_indx++;
- if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
- sctp_audit_indx = 0;
- }
- rep = 1;
- SCTP_PRINTF("tot_flt_book:%d\n", tot_book_cnt);
-
- stcb->asoc.total_flight_count = tot_book_cnt;
- }
- tot_out = 0;
- TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
- tot_out += lnet->flight_size;
- }
- if (tot_out != stcb->asoc.total_flight) {
- sctp_audit_data[sctp_audit_indx][0] = 0xAF;
- sctp_audit_data[sctp_audit_indx][1] = 0xA3;
- sctp_audit_indx++;
- if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
- sctp_audit_indx = 0;
- }
- rep = 1;
- SCTP_PRINTF("real flight:%d net total was %d\n",
- stcb->asoc.total_flight, tot_out);
- /* now corrective action */
- TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
-
- tot_out = 0;
- TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
- if ((chk->whoTo == lnet) &&
- (chk->sent < SCTP_DATAGRAM_RESEND)) {
- tot_out += chk->book_size;
- }
- }
- if (lnet->flight_size != tot_out) {
- SCTP_PRINTF("net:%p flight was %d corrected to %d\n",
- lnet, lnet->flight_size,
- tot_out);
- lnet->flight_size = tot_out;
- }
- }
- }
- if (rep) {
- sctp_print_audit_report();
- }
- }
-
- void
- sctp_audit_log(uint8_t ev, uint8_t fd)
- {
-
- sctp_audit_data[sctp_audit_indx][0] = ev;
- sctp_audit_data[sctp_audit_indx][1] = fd;
- sctp_audit_indx++;
- if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
- sctp_audit_indx = 0;
- }
- }
-
- #endif
-
- /*
- * sctp_stop_timers_for_shutdown() should be called
- * when entering the SHUTDOWN_SENT or SHUTDOWN_ACK_SENT
- * state to make sure that all timers are stopped.
- */
- void
- sctp_stop_timers_for_shutdown(struct sctp_tcb *stcb)
- {
- struct sctp_association *asoc;
- struct sctp_nets *net;
-
- asoc = &stcb->asoc;
-
- (void)SCTP_OS_TIMER_STOP(&asoc->dack_timer.timer);
- (void)SCTP_OS_TIMER_STOP(&asoc->strreset_timer.timer);
- (void)SCTP_OS_TIMER_STOP(&asoc->asconf_timer.timer);
- (void)SCTP_OS_TIMER_STOP(&asoc->autoclose_timer.timer);
- (void)SCTP_OS_TIMER_STOP(&asoc->delayed_event_timer.timer);
- TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
- (void)SCTP_OS_TIMER_STOP(&net->pmtu_timer.timer);
- (void)SCTP_OS_TIMER_STOP(&net->hb_timer.timer);
- }
- }
-
- /*
- * a list of sizes based on typical mtu's, used only if next hop size not
- * returned.
- */
- static uint32_t sctp_mtu_sizes[] = {
- 68,
- 296,
- 508,
- 512,
- 544,
- 576,
- 1006,
- 1492,
- 1500,
- 1536,
- 2002,
- 2048,
- 4352,
- 4464,
- 8166,
- 17914,
- 32000,
- 65535
- };
-
- /*
- * Return the largest MTU smaller than val. If there is no
- * entry, just return val.
- */
- uint32_t
- sctp_get_prev_mtu(uint32_t val)
- {
- uint32_t i;
-
- if (val <= sctp_mtu_sizes[0]) {
- return (val);
- }
- for (i = 1; i < (sizeof(sctp_mtu_sizes) / sizeof(uint32_t)); i++) {
- if (val <= sctp_mtu_sizes[i]) {
- break;
- }
- }
- return (sctp_mtu_sizes[i - 1]);
- }
-
- /*
- * Return the smallest MTU larger than val. If there is no
- * entry, just return val.
- */
- uint32_t
- sctp_get_next_mtu(uint32_t val)
- {
- /* select another MTU that is just bigger than this one */
- uint32_t i;
-
- for (i = 0; i < (sizeof(sctp_mtu_sizes) / sizeof(uint32_t)); i++) {
- if (val < sctp_mtu_sizes[i]) {
- return (sctp_mtu_sizes[i]);
- }
- }
- return (val);
- }
-
- void
- sctp_fill_random_store(struct sctp_pcb *m)
- {
- /*
- * Here we use the MD5/SHA-1 to hash with our good randomNumbers and
- * our counter. The result becomes our good random numbers and we
- * then setup to give these out. Note that we do no locking to
- * protect this. This is ok, since if competing folks call this we
- * will get more gobbled gook in the random store which is what we
- * want. There is a danger that two guys will use the same random
- * numbers, but thats ok too since that is random as well :->
- */
- m->store_at = 0;
- (void)sctp_hmac(SCTP_HMAC, (uint8_t *)m->random_numbers,
- sizeof(m->random_numbers), (uint8_t *)&m->random_counter,
- sizeof(m->random_counter), (uint8_t *)m->random_store);
- m->random_counter++;
- }
-
- uint32_t
- sctp_select_initial_TSN(struct sctp_pcb *inp)
- {
- /*
- * A true implementation should use random selection process to get
- * the initial stream sequence number, using RFC1750 as a good
- * guideline
- */
- uint32_t x, *xp;
- uint8_t *p;
- int store_at, new_store;
-
- if (inp->initial_sequence_debug != 0) {
- uint32_t ret;
-
- ret = inp->initial_sequence_debug;
- inp->initial_sequence_debug++;
- return (ret);
- }
- retry:
- store_at = inp->store_at;
- new_store = store_at + sizeof(uint32_t);
- if (new_store >= (SCTP_SIGNATURE_SIZE-3)) {
- new_store = 0;
- }
- if (!atomic_cmpset_int(&inp->store_at, store_at, new_store)) {
- goto retry;
- }
- if (new_store == 0) {
- /* Refill the random store */
- sctp_fill_random_store(inp);
- }
- p = &inp->random_store[store_at];
- xp = (uint32_t *)p;
- x = *xp;
- return (x);
- }
-
- uint32_t
- sctp_select_a_tag(struct sctp_inpcb *inp, uint16_t lport, uint16_t rport, int check)
- {
- uint32_t x;
- struct timeval now;
-
- if (check) {
- (void)SCTP_GETTIME_TIMEVAL(&now);
- }
- for (;;) {
- x = sctp_select_initial_TSN(&inp->sctp_ep);
- if (x == 0) {
- /* we never use 0 */
- continue;
- }
- if (!check || sctp_is_vtag_good(x, lport, rport, &now)) {
- break;
- }
- }
- return (x);
- }
-
- int
- sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb,
- uint32_t override_tag, uint32_t vrf_id)
- {
- struct sctp_association *asoc;
- /*
- * Anything set to zero is taken care of by the allocation routine's
- * bzero
- */
-
- /*
- * Up front select what scoping to apply on addresses I tell my peer
- * Not sure what to do with these right now, we will need to come up
- * with a way to set them. We may need to pass them through from the
- * caller in the sctp_aloc_assoc() function.
- */
- int i;
-
- asoc = &stcb->asoc;
- /* init all variables to a known value. */
- SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_INUSE);
- asoc->max_burst = m->sctp_ep.max_burst;
- asoc->fr_max_burst = m->sctp_ep.fr_max_burst;
- asoc->heart_beat_delay = TICKS_TO_MSEC(m->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]);
- asoc->cookie_life = m->sctp_ep.def_cookie_life;
- asoc->sctp_cmt_on_off = m->sctp_cmt_on_off;
- asoc->ecn_allowed = m->sctp_ecn_enable;
- asoc->sctp_nr_sack_on_off = (uint8_t)SCTP_BASE_SYSCTL(sctp_nr_sack_on_off);
- asoc->sctp_cmt_pf = (uint8_t)0;
- asoc->sctp_frag_point = m->sctp_frag_point;
- asoc->sctp_features = m->sctp_features;
- asoc->default_dscp = m->sctp_ep.default_dscp;
- #ifdef INET6
- if (m->sctp_ep.default_flowlabel) {
- asoc->default_flowlabel = m->sctp_ep.default_flowlabel;
- } else {
- if (m->ip_inp.inp.inp_flags & IN6P_AUTOFLOWLABEL) {
- asoc->default_flowlabel = sctp_select_initial_TSN(&m->sctp_ep);
- asoc->default_flowlabel &= 0x000fffff;
- asoc->default_flowlabel |= 0x80000000;
- } else {
- asoc->default_flowlabel = 0;
- }
- }
- #endif
- asoc->sb_send_resv = 0;
- if (override_tag) {
- asoc->my_vtag = override_tag;
- } else {
- asoc->my_vtag = sctp_select_a_tag(m, stcb->sctp_ep->sctp_lport, stcb->rport, 1);
- }
- /* Get the nonce tags */
- asoc->my_vtag_nonce = sctp_select_a_tag(m, stcb->sctp_ep->sctp_lport, stcb->rport, 0);
- asoc->peer_vtag_nonce = sctp_select_a_tag(m, stcb->sctp_ep->sctp_lport, stcb->rport, 0);
- asoc->vrf_id = vrf_id;
-
- #ifdef SCTP_ASOCLOG_OF_TSNS
- asoc->tsn_in_at = 0;
- asoc->tsn_out_at = 0;
- asoc->tsn_in_wrapped = 0;
- asoc->tsn_out_wrapped = 0;
- asoc->cumack_log_at = 0;
- asoc->cumack_log_atsnt = 0;
- #endif
- #ifdef SCTP_FS_SPEC_LOG
- asoc->fs_index = 0;
- #endif
- asoc->refcnt = 0;
- asoc->assoc_up_sent = 0;
- asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number = asoc->sending_seq =
- sctp_select_initial_TSN(&m->sctp_ep);
- asoc->asconf_seq_out_acked = asoc->asconf_seq_out - 1;
- /* we are optimisitic here */
- asoc->peer_supports_pktdrop = 1;
- asoc->peer_supports_nat = 0;
- asoc->sent_queue_retran_cnt = 0;
-
- /* for CMT */
- asoc->last_net_cmt_send_started = NULL;
-
- /* This will need to be adjusted */
- asoc->last_acked_seq = asoc->init_seq_number - 1;
- asoc->advanced_peer_ack_point = asoc->last_acked_seq;
- asoc->asconf_seq_in = asoc->last_acked_seq;
-
- /* here we are different, we hold the next one we expect */
- asoc->str_reset_seq_in = asoc->last_acked_seq + 1;
-
- asoc->initial_init_rto_max = m->sctp_ep.initial_init_rto_max;
- asoc->initial_rto = m->sctp_ep.initial_rto;
-
- asoc->max_init_times = m->sctp_ep.max_init_times;
- asoc->max_send_times = m->sctp_ep.max_send_times;
- asoc->def_net_failure = m->sctp_ep.def_net_failure;
- asoc->def_net_pf_threshold = m->sctp_ep.def_net_pf_threshold;
- asoc->free_chunk_cnt = 0;
-
- asoc->iam_blocking = 0;
- asoc->context = m->sctp_context;
- asoc->local_strreset_support = m->local_strreset_support;
- asoc->def_send = m->def_send;
- asoc->delayed_ack = TICKS_TO_MSEC(m->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]);
- asoc->sack_freq = m->sctp_ep.sctp_sack_freq;
- asoc->pr_sctp_cnt = 0;
- asoc->total_output_queue_size = 0;
-
- if (m->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
- struct in6pcb *inp6;
-
- /* Its a V6 socket */
- inp6 = (struct in6pcb *)m;
- asoc->ipv6_addr_legal = 1;
- /* Now look at the binding flag to see if V4 will be legal */
- if (SCTP_IPV6_V6ONLY(inp6) == 0) {
- asoc->ipv4_addr_legal = 1;
- } else {
- /* V4 addresses are NOT legal on the association */
- asoc->ipv4_addr_legal = 0;
- }
- } else {
- /* Its a V4 socket, no - V6 */
- asoc->ipv4_addr_legal = 1;
- asoc->ipv6_addr_legal = 0;
- }
-
- asoc->my_rwnd = max(SCTP_SB_LIMIT_RCV(m->sctp_socket), SCTP_MINIMAL_RWND);
- asoc->peers_rwnd = SCTP_SB_LIMIT_RCV(m->sctp_socket);
-
- asoc->smallest_mtu = m->sctp_frag_point;
- asoc->minrto = m->sctp_ep.sctp_minrto;
- asoc->maxrto = m->sctp_ep.sctp_maxrto;
-
- asoc->locked_on_sending = NULL;
- asoc->stream_locked_on = 0;
- asoc->ecn_echo_cnt_onq = 0;
- asoc->stream_locked = 0;
-
- asoc->send_sack = 1;
-
- LIST_INIT(&asoc->sctp_restricted_addrs);
-
- TAILQ_INIT(&asoc->nets);
- TAILQ_INIT(&asoc->pending_reply_queue);
- TAILQ_INIT(&asoc->asconf_ack_sent);
- /* Setup to fill the hb random cache at first HB */
- asoc->hb_random_idx = 4;
-
- asoc->sctp_autoclose_ticks = m->sctp_ep.auto_close_time;
-
- stcb->asoc.congestion_control_module = m->sctp_ep.sctp_default_cc_module;
- stcb->asoc.cc_functions = sctp_cc_functions[m->sctp_ep.sctp_default_cc_module];
-
- stcb->asoc.stream_scheduling_module = m->sctp_ep.sctp_default_ss_module;
- stcb->asoc.ss_functions = sctp_ss_functions[m->sctp_ep.sctp_default_ss_module];
-
- /*
- * Now the stream parameters, here we allocate space for all streams
- * that we request by default.
- */
- asoc->strm_realoutsize = asoc->streamoutcnt = asoc->pre_open_streams =
- m->sctp_ep.pre_open_stream_count;
- SCTP_MALLOC(asoc->strmout, struct sctp_stream_out *,
- asoc->streamoutcnt * sizeof(struct sctp_stream_out),
- SCTP_M_STRMO);
- if (asoc->strmout == NULL) {
- /* big trouble no memory */
- SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOMEM);
- return (ENOMEM);
- }
- for (i = 0; i < asoc->streamoutcnt; i++) {
- /*
- * inbound side must be set to 0xffff, also NOTE when we get
- * the INIT-ACK back (for INIT sender) we MUST reduce the
- * count (streamoutcnt) but first check if we sent to any of
- * the upper streams that were dropped (if some were). Those
- * that were dropped must be notified to the upper layer as
- * failed to send.
- */
- asoc->strmout[i].next_sequence_sent = 0x0;
- TAILQ_INIT(&asoc->strmout[i].outqueue);
- asoc->strmout[i].stream_no = i;
- asoc->strmout[i].last_msg_incomplete = 0;
- asoc->ss_functions.sctp_ss_init_stream(&asoc->strmout[i], NULL);
- }
- asoc->ss_functions.sctp_ss_init(stcb, asoc, 0);
-
- /* Now the mapping array */
- asoc->mapping_array_size = SCTP_INITIAL_MAPPING_ARRAY;
- SCTP_MALLOC(asoc->mapping_array, uint8_t *, asoc->mapping_array_size,
- SCTP_M_MAP);
- if (asoc->mapping_array == NULL) {
- SCTP_FREE(asoc->strmout, SCTP_M_STRMO);
- SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOMEM);
- return (ENOMEM);
- }
- memset(asoc->mapping_array, 0, asoc->mapping_array_size);
- SCTP_MALLOC(asoc->nr_mapping_array, uint8_t *, asoc->mapping_array_size,
- SCTP_M_MAP);
- if (asoc->nr_mapping_array == NULL) {
- SCTP_FREE(asoc->strmout, SCTP_M_STRMO);
- SCTP_FREE(asoc->mapping_array, SCTP_M_MAP);
- SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOMEM);
- return (ENOMEM);
- }
- memset(asoc->nr_mapping_array, 0, asoc->mapping_array_size);
-
- /* Now the init of the other outqueues */
- TAILQ_INIT(&asoc->free_chunks);
- TAILQ_INIT(&asoc->control_send_queue);
- TAILQ_INIT(&asoc->asconf_send_queue);
- TAILQ_INIT(&asoc->send_queue);
- TAILQ_INIT(&asoc->sent_queue);
- TAILQ_INIT(&asoc->reasmqueue);
- TAILQ_INIT(&asoc->resetHead);
- asoc->max_inbound_streams = m->sctp_ep.max_open_streams_intome;
- TAILQ_INIT(&asoc->asconf_queue);
- /* authentication fields */
- asoc->authinfo.random = NULL;
- asoc->authinfo.active_keyid = 0;
- asoc->authinfo.assoc_key = NULL;
- asoc->authinfo.assoc_keyid = 0;
- asoc->authinfo.recv_key = NULL;
- asoc->authinfo.recv_keyid = 0;
- LIST_INIT(&asoc->shared_keys);
- asoc->marked_retrans = 0;
- asoc->port = m->sctp_ep.port;
- asoc->timoinit = 0;
- asoc->timodata = 0;
- asoc->timosack = 0;
- asoc->timoshutdown = 0;
- asoc->timoheartbeat = 0;
- asoc->timocookie = 0;
- asoc->timoshutdownack = 0;
- (void)SCTP_GETTIME_TIMEVAL(&asoc->start_time);
- asoc->discontinuity_time = asoc->start_time;
- /* sa_ignore MEMLEAK {memory is put in the assoc mapping array and freed later when
- * the association is freed.
- */
- return (0);
- }
-
- void
- sctp_print_mapping_array(struct sctp_association *asoc)
- {
- unsigned int i, limit;
-
- SCTP_PRINTF("Mapping array size: %d, baseTSN: %8.8x, cumAck: %8.8x, highestTSN: (%8.8x, %8.8x).\n",
- asoc->mapping_array_size,
- asoc->mapping_array_base_tsn,
- asoc->cumulative_tsn,
- asoc->highest_tsn_inside_map,
- asoc->highest_tsn_inside_nr_map);
- for (limit = asoc->mapping_array_size; limit > 1; limit--) {
- if (asoc->mapping_array[limit - 1] != 0) {
- break;
- }
- }
- SCTP_PRINTF("Renegable mapping array (last %d entries are zero):\n", asoc->mapping_array_size - limit);
- for (i = 0; i < limit; i++) {
- SCTP_PRINTF("%2.2x%c", asoc->mapping_array[i], ((i + 1) % 16) ? ' ' : '\n');
- }
- if (limit % 16)
- SCTP_PRINTF("\n");
- for (limit = asoc->mapping_array_size; limit > 1; limit--) {
- if (asoc->nr_mapping_array[limit - 1]) {
- break;
- }
- }
- SCTP_PRINTF("Non renegable mapping array (last %d entries are zero):\n", asoc->mapping_array_size - limit);
- for (i = 0; i < limit; i++) {
- SCTP_PRINTF("%2.2x%c", asoc->nr_mapping_array[i], ((i + 1) % 16) ? ' ': '\n');
- }
- if (limit % 16)
- SCTP_PRINTF("\n");
- }
-
- int
- sctp_expand_mapping_array(struct sctp_association *asoc, uint32_t needed)
- {
- /* mapping array needs to grow */
- uint8_t *new_array1, *new_array2;
- uint32_t new_size;
-
- new_size = asoc->mapping_array_size + ((needed+7)/8 + SCTP_MAPPING_ARRAY_INCR);
- SCTP_MALLOC(new_array1, uint8_t *, new_size, SCTP_M_MAP);
- SCTP_MALLOC(new_array2, uint8_t *, new_size, SCTP_M_MAP);
- if ((new_array1 == NULL) || (new_array2 == NULL)) {
- /* can't get more, forget it */
- SCTP_PRINTF("No memory for expansion of SCTP mapping array %d\n", new_size);
- if (new_array1) {
- SCTP_FREE(new_array1, SCTP_M_MAP);
- }
- if (new_array2) {
- SCTP_FREE(new_array2, SCTP_M_MAP);
- }
- return (-1);
- }
- memset(new_array1, 0, new_size);
- memset(new_array2, 0, new_size);
- memcpy(new_array1, asoc->mapping_array, asoc->mapping_array_size);
- memcpy(new_array2, asoc->nr_mapping_array, asoc->mapping_array_size);
- SCTP_FREE(asoc->mapping_array, SCTP_M_MAP);
- SCTP_FREE(asoc->nr_mapping_array, SCTP_M_MAP);
- asoc->mapping_array = new_array1;
- asoc->nr_mapping_array = new_array2;
- asoc->mapping_array_size = new_size;
- return (0);
- }
-
-
- static void
- sctp_iterator_work(struct sctp_iterator *it)
- {
- int iteration_count = 0;
- int inp_skip = 0;
- int first_in = 1;
- struct sctp_inpcb *tinp;
-
- SCTP_INP_INFO_RLOCK();
- SCTP_ITERATOR_LOCK();
- if (it->inp) {
- SCTP_INP_RLOCK(it->inp);
- SCTP_INP_DECR_REF(it->inp);
- }
- if (it->inp == NULL) {
- /* iterator is complete */
- done_with_iterator:
- SCTP_ITERATOR_UNLOCK();
- SCTP_INP_INFO_RUNLOCK();
- if (it->function_atend != NULL) {
- (*it->function_atend) (it->pointer, it->val);
- }
- SCTP_FREE(it, SCTP_M_ITER);
- return;
- }
- select_a_new_ep:
- if (first_in) {
- first_in = 0;
- } else {
- SCTP_INP_RLOCK(it->inp);
- }
- while (((it->pcb_flags) &&
- ((it->inp->sctp_flags & it->pcb_flags) != it->pcb_flags)) ||
- ((it->pcb_features) &&
- ((it->inp->sctp_features & it->pcb_features) != it->pcb_features))) {
- /* endpoint flags or features don't match, so keep looking */
- if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) {
- SCTP_INP_RUNLOCK(it->inp);
- goto done_with_iterator;
- }
- tinp = it->inp;
- it->inp = LIST_NEXT(it->inp, sctp_list);
- SCTP_INP_RUNLOCK(tinp);
- if (it->inp == NULL) {
- goto done_with_iterator;
- }
- SCTP_INP_RLOCK(it->inp);
- }
- /* now go through each assoc which is in the desired state */
- if (it->done_current_ep == 0) {
- if (it->function_inp != NULL)
- inp_skip = (*it->function_inp)(it->inp, it->pointer, it->val);
- it->done_current_ep = 1;
- }
- if (it->stcb == NULL) {
- /* run the per instance function */
- it->stcb = LIST_FIRST(&it->inp->sctp_asoc_list);
- }
- if ((inp_skip) || it->stcb == NULL) {
- if (it->function_inp_end != NULL) {
- inp_skip = (*it->function_inp_end)(it->inp,
- it->pointer,
- it->val);
- }
- SCTP_INP_RUNLOCK(it->inp);
- goto no_stcb;
- }
- while (it->stcb) {
- SCTP_TCB_LOCK(it->stcb);
- if (it->asoc_state && ((it->stcb->asoc.state & it->asoc_state) != it->asoc_state)) {
- /* not in the right state... keep looking */
- SCTP_TCB_UNLOCK(it->stcb);
- goto next_assoc;
- }
- /* see if we have limited out the iterator loop */
- iteration_count++;
- if (iteration_count > SCTP_ITERATOR_MAX_AT_ONCE) {
- /* Pause to let others grab the lock */
- atomic_add_int(&it->stcb->asoc.refcnt, 1);
- SCTP_TCB_UNLOCK(it->stcb);
- SCTP_INP_INCR_REF(it->inp);
- SCTP_INP_RUNLOCK(it->inp);
- SCTP_ITERATOR_UNLOCK();
- SCTP_INP_INFO_RUNLOCK();
- SCTP_INP_INFO_RLOCK();
- SCTP_ITERATOR_LOCK();
- if (sctp_it_ctl.iterator_flags) {
- /* We won't be staying here */
- SCTP_INP_DECR_REF(it->inp);
- atomic_add_int(&it->stcb->asoc.refcnt, -1);
- #if !defined(__FreeBSD__)
- if (sctp_it_ctl.iterator_flags &
- SCTP_ITERATOR_MUST_EXIT) {
- goto done_with_iterator;
- }
- #endif
- if (sctp_it_ctl.iterator_flags &
- SCTP_ITERATOR_STOP_CUR_IT) {
- sctp_it_ctl.iterator_flags &= ~SCTP_ITERATOR_STOP_CUR_IT;
- goto done_with_iterator;
- }
- if (sctp_it_ctl.iterator_flags &
- SCTP_ITERATOR_STOP_CUR_INP) {
- sctp_it_ctl.iterator_flags &= ~SCTP_ITERATOR_STOP_CUR_INP;
- goto no_stcb;
- }
- /* If we reach here huh? */
- SCTP_PRINTF("Unknown it ctl flag %x\n",
- sctp_it_ctl.iterator_flags);
- sctp_it_ctl.iterator_flags = 0;
- }
- SCTP_INP_RLOCK(it->inp);
- SCTP_INP_DECR_REF(it->inp);
- SCTP_TCB_LOCK(it->stcb);
- atomic_add_int(&it->stcb->asoc.refcnt, -1);
- iteration_count = 0;
- }
-
- /* run function on this one */
- (*it->function_assoc)(it->inp, it->stcb, it->pointer, it->val);
-
- /*
- * we lie here, it really needs to have its own type but
- * first I must verify that this won't effect things :-0
- */
- if (it->no_chunk_output == 0)
- sctp_chunk_output(it->inp, it->stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED);
-
- SCTP_TCB_UNLOCK(it->stcb);
- next_assoc:
- it->stcb = LIST_NEXT(it->stcb, sctp_tcblist);
- if (it->stcb == NULL) {
- /* Run last function */
- if (it->function_inp_end != NULL) {
- inp_skip = (*it->function_inp_end)(it->inp,
- it->pointer,
- it->val);
- }
- }
- }
- SCTP_INP_RUNLOCK(it->inp);
- no_stcb:
- /* done with all assocs on this endpoint, move on to next endpoint */
- it->done_current_ep = 0;
- if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) {
- it->inp = NULL;
- } else {
- it->inp = LIST_NEXT(it->inp, sctp_list);
- }
- if (it->inp == NULL) {
- goto done_with_iterator;
- }
- goto select_a_new_ep;
- }
-
- void
- sctp_iterator_worker(void)
- {
- struct sctp_iterator *it, *nit;
-
- /* This function is called with the WQ lock in place */
-
- sctp_it_ctl.iterator_running = 1;
- TAILQ_FOREACH_SAFE(it, &sctp_it_ctl.iteratorhead, sctp_nxt_itr, nit) {
- sctp_it_ctl.cur_it = it;
- /* now lets work on this one */
- TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, it, sctp_nxt_itr);
- SCTP_IPI_ITERATOR_WQ_UNLOCK();
- #if defined(__FreeBSD__) && __FreeBSD_version >= 801000
- CURVNET_SET(it->vn);
- #endif
- sctp_iterator_work(it);
- sctp_it_ctl.cur_it = NULL;
- #if defined(__FreeBSD__) && __FreeBSD_version >= 801000
- CURVNET_RESTORE();
- #endif
- SCTP_IPI_ITERATOR_WQ_LOCK();
- #if !defined(__FreeBSD__)
- if (sctp_it_ctl.iterator_flags & SCTP_ITERATOR_MUST_EXIT) {
- break;
- }
- #endif
- /*sa_ignore FREED_MEMORY*/
- }
- sctp_it_ctl.iterator_running = 0;
- return;
- }
-
-
- static void
- sctp_handle_addr_wq(void)
- {
- /* deal with the ADDR wq from the rtsock calls */
- struct sctp_laddr *wi, *nwi;
- struct sctp_asconf_iterator *asc;
-
- SCTP_MALLOC(asc, struct sctp_asconf_iterator *,
- sizeof(struct sctp_asconf_iterator), SCTP_M_ASC_IT);
- if (asc == NULL) {
- /* Try later, no memory */
- sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ,
- (struct sctp_inpcb *)NULL,
- (struct sctp_tcb *)NULL,
- (struct sctp_nets *)NULL);
- return;
- }
- LIST_INIT(&asc->list_of_work);
- asc->cnt = 0;
-
- SCTP_WQ_ADDR_LOCK();
- LIST_FOREACH_SAFE(wi, &SCTP_BASE_INFO(addr_wq), sctp_nxt_addr, nwi) {
- LIST_REMOVE(wi, sctp_nxt_addr);
- LIST_INSERT_HEAD(&asc->list_of_work, wi, sctp_nxt_addr);
- asc->cnt++;
- }
- SCTP_WQ_ADDR_UNLOCK();
-
- if (asc->cnt == 0) {
- SCTP_FREE(asc, SCTP_M_ASC_IT);
- } else {
- (void)sctp_initiate_iterator(sctp_asconf_iterator_ep,
- sctp_asconf_iterator_stcb,
- NULL, /* No ep end for boundall */
- SCTP_PCB_FLAGS_BOUNDALL,
- SCTP_PCB_ANY_FEATURES,
- SCTP_ASOC_ANY_STATE,
- (void *)asc, 0,
- sctp_asconf_iterator_end, NULL, 0);
- }
- }
-
- void
- sctp_timeout_handler(void *t)
- {
- struct sctp_inpcb *inp;
- struct sctp_tcb *stcb;
- struct sctp_nets *net;
- struct sctp_timer *tmr;
- #if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
- struct socket *so;
- #endif
- int did_output, type;
-
- tmr = (struct sctp_timer *)t;
- inp = (struct sctp_inpcb *)tmr->ep;
- stcb = (struct sctp_tcb *)tmr->tcb;
- net = (struct sctp_nets *)tmr->net;
- #if defined(__FreeBSD__) && __FreeBSD_version >= 801000
- CURVNET_SET((struct vnet *)tmr->vnet);
- #endif
- did_output = 1;
-
- #ifdef SCTP_AUDITING_ENABLED
- sctp_audit_log(0xF0, (uint8_t) tmr->type);
- sctp_auditing(3, inp, stcb, net);
- #endif
-
- /* sanity checks... */
- if (tmr->self != (void *)tmr) {
- /*
- * SCTP_PRINTF("Stale SCTP timer fired (%p), ignoring...\n",
- * tmr);
- */
- #if defined(__FreeBSD__) && __FreeBSD_version >= 801000
- CURVNET_RESTORE();
- #endif
- return;
- }
- tmr->stopped_from = 0xa001;
- if (!SCTP_IS_TIMER_TYPE_VALID(tmr->type)) {
- /*
- * SCTP_PRINTF("SCTP timer fired with invalid type: 0x%x\n",
- * tmr->type);
- */
- #if defined(__FreeBSD__) && __FreeBSD_version >= 801000
- CURVNET_RESTORE();
- #endif
- return;
- }
- tmr->stopped_from = 0xa002;
- if ((tmr->type != SCTP_TIMER_TYPE_ADDR_WQ) && (inp == NULL)) {
- #if defined(__FreeBSD__) && __FreeBSD_version >= 801000
- CURVNET_RESTORE();
- #endif
- return;
- }
- /* if this is an iterator timeout, get the struct and clear inp */
- tmr->stopped_from = 0xa003;
- type = tmr->type;
- if (inp) {
- SCTP_INP_INCR_REF(inp);
- if ((inp->sctp_socket == NULL) &&
- ((tmr->type != SCTP_TIMER_TYPE_INPKILL) &&
- (tmr->type != SCTP_TIMER_TYPE_INIT) &&
- (tmr->type != SCTP_TIMER_TYPE_SEND) &&
- (tmr->type != SCTP_TIMER_TYPE_RECV) &&
- (tmr->type != SCTP_TIMER_TYPE_HEARTBEAT) &&
- (tmr->type != SCTP_TIMER_TYPE_SHUTDOWN) &&
- (tmr->type != SCTP_TIMER_TYPE_SHUTDOWNACK) &&
- (tmr->type != SCTP_TIMER_TYPE_SHUTDOWNGUARD) &&
- (tmr->type != SCTP_TIMER_TYPE_ASOCKILL))
- ) {
- SCTP_INP_DECR_REF(inp);
- #if defined(__FreeBSD__) && __FreeBSD_version >= 801000
- CURVNET_RESTORE();
- #endif
- return;
- }
- }
- tmr->stopped_from = 0xa004;
- if (stcb) {
- atomic_add_int(&stcb->asoc.refcnt, 1);
- if (stcb->asoc.state == 0) {
- atomic_add_int(&stcb->asoc.refcnt, -1);
- if (inp) {
- SCTP_INP_DECR_REF(inp);
- }
- #if defined(__FreeBSD__) && __FreeBSD_version >= 801000
- CURVNET_RESTORE();
- #endif
- return;
- }
- }
- tmr->stopped_from = 0xa005;
- SCTPDBG(SCTP_DEBUG_TIMER1, "Timer type %d goes off\n", tmr->type);
- if (!SCTP_OS_TIMER_ACTIVE(&tmr->timer)) {
- if (inp) {
- SCTP_INP_DECR_REF(inp);
- }
- if (stcb) {
- atomic_add_int(&stcb->asoc.refcnt, -1);
- }
- #if defined(__FreeBSD__) && __FreeBSD_version >= 801000
- CURVNET_RESTORE();
- #endif
- return;
- }
- tmr->stopped_from = 0xa006;
-
- if (stcb) {
- SCTP_TCB_LOCK(stcb);
- atomic_add_int(&stcb->asoc.refcnt, -1);
- if ((tmr->type != SCTP_TIMER_TYPE_ASOCKILL) &&
- ((stcb->asoc.state == 0) ||
- (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED))) {
- SCTP_TCB_UNLOCK(stcb);
- if (inp) {
- SCTP_INP_DECR_REF(inp);
- }
- #if defined(__FreeBSD__) && __FreeBSD_version >= 801000
- CURVNET_RESTORE();
- #endif
- return;
- }
- }
- /* record in stopped what t-o occured */
- tmr->stopped_from = tmr->type;
-
- /* mark as being serviced now */
- if (SCTP_OS_TIMER_PENDING(&tmr->timer)) {
- /*
- * Callout has been rescheduled.
- */
- goto get_out;
- }
- if (!SCTP_OS_TIMER_ACTIVE(&tmr->timer)) {
- /*
- * Not active, so no action.
- */
- goto get_out;
- }
- SCTP_OS_TIMER_DEACTIVATE(&tmr->timer);
-
- /* call the handler for the appropriate timer type */
- switch (tmr->type) {
- case SCTP_TIMER_TYPE_ZERO_COPY:
- if (inp == NULL) {
- break;
- }
- if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) {
- SCTP_ZERO_COPY_EVENT(inp, inp->sctp_socket);
- }
- break;
- case SCTP_TIMER_TYPE_ZCOPY_SENDQ:
- if (inp == NULL) {
- break;
- }
- if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) {
- SCTP_ZERO_COPY_SENDQ_EVENT(inp, inp->sctp_socket);
- }
- break;
- case SCTP_TIMER_TYPE_ADDR_WQ:
- sctp_handle_addr_wq();
- break;
- case SCTP_TIMER_TYPE_SEND:
- if ((stcb == NULL) || (inp == NULL)) {
- break;
- }
- SCTP_STAT_INCR(sctps_timodata);
- stcb->asoc.timodata++;
- stcb->asoc.num_send_timers_up--;
- if (stcb->asoc.num_send_timers_up < 0) {
- stcb->asoc.num_send_timers_up = 0;
- }
- SCTP_TCB_LOCK_ASSERT(stcb);
- if (sctp_t3rxt_timer(inp, stcb, net)) {
- /* no need to unlock on tcb its gone */
-
- goto out_decr;
- }
- SCTP_TCB_LOCK_ASSERT(stcb);
- #ifdef SCTP_AUDITING_ENABLED
- sctp_auditing(4, inp, stcb, net);
- #endif
- sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED);
- if ((stcb->asoc.num_send_timers_up == 0) &&
- (stcb->asoc.sent_queue_cnt > 0)) {
- struct sctp_tmit_chunk *chk;
-
- /*
- * safeguard. If there on some on the sent queue
- * somewhere but no timers running something is
- * wrong... so we start a timer on the first chunk
- * on the send queue on whatever net it is sent to.
- */
- chk = TAILQ_FIRST(&stcb->asoc.sent_queue);
- sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb,
- chk->whoTo);
- }
- break;
- case SCTP_TIMER_TYPE_INIT:
- if ((stcb == NULL) || (inp == NULL)) {
- break;
- }
- SCTP_STAT_INCR(sctps_timoinit);
- stcb->asoc.timoinit++;
- if (sctp_t1init_timer(inp, stcb, net)) {
- /* no need to unlock on tcb its gone */
- goto out_decr;
- }
- /* We do output but not here */
- did_output = 0;
- break;
- case SCTP_TIMER_TYPE_RECV:
- if ((stcb == NULL) || (inp == NULL)) {
- break;
- }
- SCTP_STAT_INCR(sctps_timosack);
- stcb->asoc.timosack++;
- sctp_send_sack(stcb, SCTP_SO_NOT_LOCKED);
- #ifdef SCTP_AUDITING_ENABLED
- sctp_auditing(4, inp, stcb, net);
- #endif
- sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SACK_TMR, SCTP_SO_NOT_LOCKED);
- break;
- case SCTP_TIMER_TYPE_SHUTDOWN:
- if ((stcb == NULL) || (inp == NULL)) {
- break;
- }
- if (sctp_shutdown_timer(inp, stcb, net)) {
- /* no need to unlock on tcb its gone */
- goto out_decr;
- }
- SCTP_STAT_INCR(sctps_timoshutdown);
- stcb->asoc.timoshutdown++;
- #ifdef SCTP_AUDITING_ENABLED
- sctp_auditing(4, inp, stcb, net);
- #endif
- sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SHUT_TMR, SCTP_SO_NOT_LOCKED);
- break;
- case SCTP_TIMER_TYPE_HEARTBEAT:
- if ((stcb == NULL) || (inp == NULL) || (net == NULL)) {
- break;
- }
- SCTP_STAT_INCR(sctps_timoheartbeat);
- stcb->asoc.timoheartbeat…
Large files files are truncated, but you can click here to view the full file