freebsd-skq/sys/netinet/sctp_sysctl.c
hselasky 1d17f744c7 MFC r273733, r273740 and r273773:
The SYSCTL data pointers can come from userspace and must not be
directly accessed. Although this will work on some platforms, it can
throw an exception if the pointer is invalid and then panic the kernel.

Add a missing SYSCTL_IN() of "SCTP_BASE_STATS" structure.

Sponsored by:	Mellanox Technologies
2014-10-30 08:04:48 +00:00

936 lines
37 KiB
C

/*-
* Copyright (c) 2007, 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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <netinet/sctp_os.h>
#include <netinet/sctp.h>
#include <netinet/sctp_constants.h>
#include <netinet/sctp_sysctl.h>
#include <netinet/sctp_pcb.h>
#include <netinet/sctputil.h>
#include <netinet/sctp_output.h>
#include <sys/smp.h>
#include <sys/sysctl.h>
FEATURE(sctp, "Stream Control Transmission Protocol");
/*
* sysctl tunable variables
*/
void
sctp_init_sysctls()
{
SCTP_BASE_SYSCTL(sctp_sendspace) = SCTPCTL_MAXDGRAM_DEFAULT;
SCTP_BASE_SYSCTL(sctp_recvspace) = SCTPCTL_RECVSPACE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_auto_asconf) = SCTPCTL_AUTOASCONF_DEFAULT;
SCTP_BASE_SYSCTL(sctp_multiple_asconfs) = SCTPCTL_MULTIPLEASCONFS_DEFAULT;
SCTP_BASE_SYSCTL(sctp_ecn_enable) = SCTPCTL_ECN_ENABLE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_pr_enable) = SCTPCTL_PR_ENABLE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_auth_disable) = SCTPCTL_AUTH_DISABLE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_asconf_enable) = SCTPCTL_ASCONF_ENABLE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_reconfig_enable) = SCTPCTL_RECONFIG_ENABLE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_nrsack_enable) = SCTPCTL_NRSACK_ENABLE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_pktdrop_enable) = SCTPCTL_PKTDROP_ENABLE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_strict_sacks) = SCTPCTL_STRICT_SACKS_DEFAULT;
SCTP_BASE_SYSCTL(sctp_peer_chunk_oh) = SCTPCTL_PEER_CHKOH_DEFAULT;
SCTP_BASE_SYSCTL(sctp_max_burst_default) = SCTPCTL_MAXBURST_DEFAULT;
SCTP_BASE_SYSCTL(sctp_fr_max_burst_default) = SCTPCTL_FRMAXBURST_DEFAULT;
SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue) = SCTPCTL_MAXCHUNKS_DEFAULT;
SCTP_BASE_SYSCTL(sctp_hashtblsize) = SCTPCTL_TCBHASHSIZE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_pcbtblsize) = SCTPCTL_PCBHASHSIZE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_min_split_point) = SCTPCTL_MIN_SPLIT_POINT_DEFAULT;
SCTP_BASE_SYSCTL(sctp_chunkscale) = SCTPCTL_CHUNKSCALE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_delayed_sack_time_default) = SCTPCTL_DELAYED_SACK_TIME_DEFAULT;
SCTP_BASE_SYSCTL(sctp_sack_freq_default) = SCTPCTL_SACK_FREQ_DEFAULT;
SCTP_BASE_SYSCTL(sctp_system_free_resc_limit) = SCTPCTL_SYS_RESOURCE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_asoc_free_resc_limit) = SCTPCTL_ASOC_RESOURCE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_heartbeat_interval_default) = SCTPCTL_HEARTBEAT_INTERVAL_DEFAULT;
SCTP_BASE_SYSCTL(sctp_pmtu_raise_time_default) = SCTPCTL_PMTU_RAISE_TIME_DEFAULT;
SCTP_BASE_SYSCTL(sctp_shutdown_guard_time_default) = SCTPCTL_SHUTDOWN_GUARD_TIME_DEFAULT;
SCTP_BASE_SYSCTL(sctp_secret_lifetime_default) = SCTPCTL_SECRET_LIFETIME_DEFAULT;
SCTP_BASE_SYSCTL(sctp_rto_max_default) = SCTPCTL_RTO_MAX_DEFAULT;
SCTP_BASE_SYSCTL(sctp_rto_min_default) = SCTPCTL_RTO_MIN_DEFAULT;
SCTP_BASE_SYSCTL(sctp_rto_initial_default) = SCTPCTL_RTO_INITIAL_DEFAULT;
SCTP_BASE_SYSCTL(sctp_init_rto_max_default) = SCTPCTL_INIT_RTO_MAX_DEFAULT;
SCTP_BASE_SYSCTL(sctp_valid_cookie_life_default) = SCTPCTL_VALID_COOKIE_LIFE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_init_rtx_max_default) = SCTPCTL_INIT_RTX_MAX_DEFAULT;
SCTP_BASE_SYSCTL(sctp_assoc_rtx_max_default) = SCTPCTL_ASSOC_RTX_MAX_DEFAULT;
SCTP_BASE_SYSCTL(sctp_path_rtx_max_default) = SCTPCTL_PATH_RTX_MAX_DEFAULT;
SCTP_BASE_SYSCTL(sctp_path_pf_threshold) = SCTPCTL_PATH_PF_THRESHOLD_DEFAULT;
SCTP_BASE_SYSCTL(sctp_add_more_threshold) = SCTPCTL_ADD_MORE_ON_OUTPUT_DEFAULT;
SCTP_BASE_SYSCTL(sctp_nr_incoming_streams_default) = SCTPCTL_INCOMING_STREAMS_DEFAULT;
SCTP_BASE_SYSCTL(sctp_nr_outgoing_streams_default) = SCTPCTL_OUTGOING_STREAMS_DEFAULT;
SCTP_BASE_SYSCTL(sctp_cmt_on_off) = SCTPCTL_CMT_ON_OFF_DEFAULT;
SCTP_BASE_SYSCTL(sctp_cmt_use_dac) = SCTPCTL_CMT_USE_DAC_DEFAULT;
SCTP_BASE_SYSCTL(sctp_use_cwnd_based_maxburst) = SCTPCTL_CWND_MAXBURST_DEFAULT;
SCTP_BASE_SYSCTL(sctp_nat_friendly) = SCTPCTL_NAT_FRIENDLY_DEFAULT;
SCTP_BASE_SYSCTL(sctp_L2_abc_variable) = SCTPCTL_ABC_L_VAR_DEFAULT;
SCTP_BASE_SYSCTL(sctp_mbuf_threshold_count) = SCTPCTL_MAX_CHAINED_MBUFS_DEFAULT;
SCTP_BASE_SYSCTL(sctp_do_drain) = SCTPCTL_DO_SCTP_DRAIN_DEFAULT;
SCTP_BASE_SYSCTL(sctp_hb_maxburst) = SCTPCTL_HB_MAX_BURST_DEFAULT;
SCTP_BASE_SYSCTL(sctp_abort_if_one_2_one_hits_limit) = SCTPCTL_ABORT_AT_LIMIT_DEFAULT;
SCTP_BASE_SYSCTL(sctp_strict_data_order) = SCTPCTL_STRICT_DATA_ORDER_DEFAULT;
SCTP_BASE_SYSCTL(sctp_min_residual) = SCTPCTL_MIN_RESIDUAL_DEFAULT;
SCTP_BASE_SYSCTL(sctp_max_retran_chunk) = SCTPCTL_MAX_RETRAN_CHUNK_DEFAULT;
SCTP_BASE_SYSCTL(sctp_logging_level) = SCTPCTL_LOGGING_LEVEL_DEFAULT;
SCTP_BASE_SYSCTL(sctp_default_cc_module) = SCTPCTL_DEFAULT_CC_MODULE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_default_ss_module) = SCTPCTL_DEFAULT_SS_MODULE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_default_frag_interleave) = SCTPCTL_DEFAULT_FRAG_INTERLEAVE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_mobility_base) = SCTPCTL_MOBILITY_BASE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_mobility_fasthandoff) = SCTPCTL_MOBILITY_FASTHANDOFF_DEFAULT;
SCTP_BASE_SYSCTL(sctp_vtag_time_wait) = SCTPCTL_TIME_WAIT_DEFAULT;
SCTP_BASE_SYSCTL(sctp_buffer_splitting) = SCTPCTL_BUFFER_SPLITTING_DEFAULT;
SCTP_BASE_SYSCTL(sctp_initial_cwnd) = SCTPCTL_INITIAL_CWND_DEFAULT;
SCTP_BASE_SYSCTL(sctp_rttvar_bw) = SCTPCTL_RTTVAR_BW_DEFAULT;
SCTP_BASE_SYSCTL(sctp_rttvar_rtt) = SCTPCTL_RTTVAR_RTT_DEFAULT;
SCTP_BASE_SYSCTL(sctp_rttvar_eqret) = SCTPCTL_RTTVAR_EQRET_DEFAULT;
SCTP_BASE_SYSCTL(sctp_steady_step) = SCTPCTL_RTTVAR_STEADYS_DEFAULT;
SCTP_BASE_SYSCTL(sctp_use_dccc_ecn) = SCTPCTL_RTTVAR_DCCCECN_DEFAULT;
SCTP_BASE_SYSCTL(sctp_blackhole) = SCTPCTL_BLACKHOLE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_diag_info_code) = SCTPCTL_DIAG_INFO_CODE_DEFAULT;
#if defined(SCTP_LOCAL_TRACE_BUF)
memset(&SCTP_BASE_SYSCTL(sctp_log), 0, sizeof(struct sctp_log));
#endif
SCTP_BASE_SYSCTL(sctp_udp_tunneling_port) = SCTPCTL_UDP_TUNNELING_PORT_DEFAULT;
SCTP_BASE_SYSCTL(sctp_enable_sack_immediately) = SCTPCTL_SACK_IMMEDIATELY_ENABLE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_inits_include_nat_friendly) = SCTPCTL_NAT_FRIENDLY_INITS_DEFAULT;
#if defined(SCTP_DEBUG)
SCTP_BASE_SYSCTL(sctp_debug_on) = SCTPCTL_DEBUG_DEFAULT;
#endif
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_BASE_SYSCTL(sctp_output_unlocked) = SCTPCTL_OUTPUT_UNLOCKED_DEFAULT;
#endif
}
/* It returns an upper limit. No filtering is done here */
static unsigned int
sctp_sysctl_number_of_addresses(struct sctp_inpcb *inp)
{
unsigned int cnt;
struct sctp_vrf *vrf;
struct sctp_ifn *sctp_ifn;
struct sctp_ifa *sctp_ifa;
struct sctp_laddr *laddr;
cnt = 0;
/* neither Mac OS X nor FreeBSD support mulitple routing functions */
if ((vrf = sctp_find_vrf(inp->def_vrf_id)) == NULL) {
return (0);
}
if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
switch (sctp_ifa->address.sa.sa_family) {
#ifdef INET
case AF_INET:
#endif
#ifdef INET6
case AF_INET6:
#endif
cnt++;
break;
default:
break;
}
}
}
} else {
LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
switch (laddr->ifa->address.sa.sa_family) {
#ifdef INET
case AF_INET:
#endif
#ifdef INET6
case AF_INET6:
#endif
cnt++;
break;
default:
break;
}
}
}
return (cnt);
}
static int
sctp_sysctl_copy_out_local_addresses(struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct sysctl_req *req)
{
struct sctp_ifn *sctp_ifn;
struct sctp_ifa *sctp_ifa;
int loopback_scope, ipv4_local_scope, local_scope, site_scope;
int ipv4_addr_legal, ipv6_addr_legal;
struct sctp_vrf *vrf;
struct xsctp_laddr xladdr;
struct sctp_laddr *laddr;
int error;
/* Turn on all the appropriate scope */
if (stcb) {
/* use association specific values */
loopback_scope = stcb->asoc.scope.loopback_scope;
ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope;
local_scope = stcb->asoc.scope.local_scope;
site_scope = stcb->asoc.scope.site_scope;
ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal;
ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal;
} else {
/* Use generic values for endpoints. */
loopback_scope = 1;
ipv4_local_scope = 1;
local_scope = 1;
site_scope = 1;
if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
ipv6_addr_legal = 1;
if (SCTP_IPV6_V6ONLY(inp)) {
ipv4_addr_legal = 0;
} else {
ipv4_addr_legal = 1;
}
} else {
ipv6_addr_legal = 0;
ipv4_addr_legal = 1;
}
}
/* neither Mac OS X nor FreeBSD support mulitple routing functions */
if ((vrf = sctp_find_vrf(inp->def_vrf_id)) == NULL) {
SCTP_INP_RUNLOCK(inp);
SCTP_INP_INFO_RUNLOCK();
return (-1);
}
if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
if ((loopback_scope == 0) && SCTP_IFN_IS_IFT_LOOP(sctp_ifn))
/* Skip loopback if loopback_scope not set */
continue;
LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
if (stcb) {
/*
* ignore if blacklisted at
* association level
*/
if (sctp_is_addr_restricted(stcb, sctp_ifa))
continue;
}
switch (sctp_ifa->address.sa.sa_family) {
#ifdef INET
case AF_INET:
if (ipv4_addr_legal) {
struct sockaddr_in *sin;
sin = &sctp_ifa->address.sin;
if (sin->sin_addr.s_addr == 0)
continue;
if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
&sin->sin_addr) != 0) {
continue;
}
if ((ipv4_local_scope == 0) && (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)))
continue;
} else {
continue;
}
break;
#endif
#ifdef INET6
case AF_INET6:
if (ipv6_addr_legal) {
struct sockaddr_in6 *sin6;
sin6 = &sctp_ifa->address.sin6;
if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
continue;
if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
&sin6->sin6_addr) != 0) {
continue;
}
if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
if (local_scope == 0)
continue;
if (sin6->sin6_scope_id == 0) {
/*
* bad link
* local
* address
*/
if (sa6_recoverscope(sin6) != 0)
continue;
}
}
if ((site_scope == 0) && (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)))
continue;
} else {
continue;
}
break;
#endif
default:
continue;
}
memset((void *)&xladdr, 0, sizeof(struct xsctp_laddr));
memcpy((void *)&xladdr.address, (const void *)&sctp_ifa->address, sizeof(union sctp_sockstore));
SCTP_INP_RUNLOCK(inp);
SCTP_INP_INFO_RUNLOCK();
error = SYSCTL_OUT(req, &xladdr, sizeof(struct xsctp_laddr));
if (error) {
return (error);
} else {
SCTP_INP_INFO_RLOCK();
SCTP_INP_RLOCK(inp);
}
}
}
} else {
LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
/* ignore if blacklisted at association level */
if (stcb && sctp_is_addr_restricted(stcb, laddr->ifa))
continue;
memset((void *)&xladdr, 0, sizeof(struct xsctp_laddr));
memcpy((void *)&xladdr.address, (const void *)&laddr->ifa->address, sizeof(union sctp_sockstore));
xladdr.start_time.tv_sec = (uint32_t) laddr->start_time.tv_sec;
xladdr.start_time.tv_usec = (uint32_t) laddr->start_time.tv_usec;
SCTP_INP_RUNLOCK(inp);
SCTP_INP_INFO_RUNLOCK();
error = SYSCTL_OUT(req, &xladdr, sizeof(struct xsctp_laddr));
if (error) {
return (error);
} else {
SCTP_INP_INFO_RLOCK();
SCTP_INP_RLOCK(inp);
}
}
}
memset((void *)&xladdr, 0, sizeof(struct xsctp_laddr));
xladdr.last = 1;
SCTP_INP_RUNLOCK(inp);
SCTP_INP_INFO_RUNLOCK();
error = SYSCTL_OUT(req, &xladdr, sizeof(struct xsctp_laddr));
if (error) {
return (error);
} else {
SCTP_INP_INFO_RLOCK();
SCTP_INP_RLOCK(inp);
return (0);
}
}
/*
* sysctl functions
*/
static int
sctp_sysctl_handle_assoclist(SYSCTL_HANDLER_ARGS)
{
unsigned int number_of_endpoints;
unsigned int number_of_local_addresses;
unsigned int number_of_associations;
unsigned int number_of_remote_addresses;
unsigned int n;
int error;
struct sctp_inpcb *inp;
struct sctp_tcb *stcb;
struct sctp_nets *net;
struct xsctp_inpcb xinpcb;
struct xsctp_tcb xstcb;
struct xsctp_raddr xraddr;
struct socket *so;
number_of_endpoints = 0;
number_of_local_addresses = 0;
number_of_associations = 0;
number_of_remote_addresses = 0;
SCTP_INP_INFO_RLOCK();
if (req->oldptr == NULL) {
LIST_FOREACH(inp, &SCTP_BASE_INFO(listhead), sctp_list) {
SCTP_INP_RLOCK(inp);
number_of_endpoints++;
number_of_local_addresses += sctp_sysctl_number_of_addresses(inp);
LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
number_of_associations++;
number_of_local_addresses += sctp_sysctl_number_of_addresses(inp);
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
number_of_remote_addresses++;
}
}
SCTP_INP_RUNLOCK(inp);
}
SCTP_INP_INFO_RUNLOCK();
n = (number_of_endpoints + 1) * sizeof(struct xsctp_inpcb) +
(number_of_local_addresses + number_of_endpoints + number_of_associations) * sizeof(struct xsctp_laddr) +
(number_of_associations + number_of_endpoints) * sizeof(struct xsctp_tcb) +
(number_of_remote_addresses + number_of_associations) * sizeof(struct xsctp_raddr);
/* request some more memory than needed */
req->oldidx = (n + n / 8);
return (0);
}
if (req->newptr != NULL) {
SCTP_INP_INFO_RUNLOCK();
SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_SYSCTL, EPERM);
return (EPERM);
}
LIST_FOREACH(inp, &SCTP_BASE_INFO(listhead), sctp_list) {
SCTP_INP_RLOCK(inp);
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) {
/* if its allgone it is being freed - skip it */
goto skip;
}
xinpcb.last = 0;
xinpcb.local_port = ntohs(inp->sctp_lport);
xinpcb.flags = inp->sctp_flags;
xinpcb.features = inp->sctp_features;
xinpcb.total_sends = inp->total_sends;
xinpcb.total_recvs = inp->total_recvs;
xinpcb.total_nospaces = inp->total_nospaces;
xinpcb.fragmentation_point = inp->sctp_frag_point;
so = inp->sctp_socket;
if ((so == NULL) ||
(inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
xinpcb.qlen = 0;
xinpcb.maxqlen = 0;
} else {
xinpcb.qlen = so->so_qlen;
xinpcb.maxqlen = so->so_qlimit;
}
SCTP_INP_INCR_REF(inp);
SCTP_INP_RUNLOCK(inp);
SCTP_INP_INFO_RUNLOCK();
error = SYSCTL_OUT(req, &xinpcb, sizeof(struct xsctp_inpcb));
if (error) {
SCTP_INP_DECR_REF(inp);
return (error);
}
SCTP_INP_INFO_RLOCK();
SCTP_INP_RLOCK(inp);
error = sctp_sysctl_copy_out_local_addresses(inp, NULL, req);
if (error) {
SCTP_INP_DECR_REF(inp);
return (error);
}
LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
SCTP_TCB_LOCK(stcb);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
xstcb.last = 0;
xstcb.local_port = ntohs(inp->sctp_lport);
xstcb.remote_port = ntohs(stcb->rport);
if (stcb->asoc.primary_destination != NULL)
xstcb.primary_addr = stcb->asoc.primary_destination->ro._l_addr;
xstcb.heartbeat_interval = stcb->asoc.heart_beat_delay;
xstcb.state = SCTP_GET_STATE(&stcb->asoc); /* FIXME */
/* 7.0 does not support these */
xstcb.assoc_id = sctp_get_associd(stcb);
xstcb.peers_rwnd = stcb->asoc.peers_rwnd;
xstcb.in_streams = stcb->asoc.streamincnt;
xstcb.out_streams = stcb->asoc.streamoutcnt;
xstcb.max_nr_retrans = stcb->asoc.overall_error_count;
xstcb.primary_process = 0; /* not really supported
* yet */
xstcb.T1_expireries = stcb->asoc.timoinit + stcb->asoc.timocookie;
xstcb.T2_expireries = stcb->asoc.timoshutdown + stcb->asoc.timoshutdownack;
xstcb.retransmitted_tsns = stcb->asoc.marked_retrans;
xstcb.start_time.tv_sec = (uint32_t) stcb->asoc.start_time.tv_sec;
xstcb.start_time.tv_usec = (uint32_t) stcb->asoc.start_time.tv_usec;
xstcb.discontinuity_time.tv_sec = (uint32_t) stcb->asoc.discontinuity_time.tv_sec;
xstcb.discontinuity_time.tv_usec = (uint32_t) stcb->asoc.discontinuity_time.tv_usec;
xstcb.total_sends = stcb->total_sends;
xstcb.total_recvs = stcb->total_recvs;
xstcb.local_tag = stcb->asoc.my_vtag;
xstcb.remote_tag = stcb->asoc.peer_vtag;
xstcb.initial_tsn = stcb->asoc.init_seq_number;
xstcb.highest_tsn = stcb->asoc.sending_seq - 1;
xstcb.cumulative_tsn = stcb->asoc.last_acked_seq;
xstcb.cumulative_tsn_ack = stcb->asoc.cumulative_tsn;
xstcb.mtu = stcb->asoc.smallest_mtu;
xstcb.refcnt = stcb->asoc.refcnt;
SCTP_INP_RUNLOCK(inp);
SCTP_INP_INFO_RUNLOCK();
error = SYSCTL_OUT(req, &xstcb, sizeof(struct xsctp_tcb));
if (error) {
SCTP_INP_DECR_REF(inp);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
return (error);
}
SCTP_INP_INFO_RLOCK();
SCTP_INP_RLOCK(inp);
error = sctp_sysctl_copy_out_local_addresses(inp, stcb, req);
if (error) {
SCTP_INP_DECR_REF(inp);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
return (error);
}
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
xraddr.last = 0;
xraddr.address = net->ro._l_addr;
xraddr.active = ((net->dest_state & SCTP_ADDR_REACHABLE) == SCTP_ADDR_REACHABLE);
xraddr.confirmed = ((net->dest_state & SCTP_ADDR_UNCONFIRMED) == 0);
xraddr.heartbeat_enabled = ((net->dest_state & SCTP_ADDR_NOHB) == 0);
xraddr.potentially_failed = ((net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF);
xraddr.rto = net->RTO;
xraddr.max_path_rtx = net->failure_threshold;
xraddr.rtx = net->marked_retrans;
xraddr.error_counter = net->error_count;
xraddr.cwnd = net->cwnd;
xraddr.flight_size = net->flight_size;
xraddr.mtu = net->mtu;
xraddr.rtt = net->rtt / 1000;
xraddr.heartbeat_interval = net->heart_beat_delay;
xraddr.start_time.tv_sec = (uint32_t) net->start_time.tv_sec;
xraddr.start_time.tv_usec = (uint32_t) net->start_time.tv_usec;
SCTP_INP_RUNLOCK(inp);
SCTP_INP_INFO_RUNLOCK();
error = SYSCTL_OUT(req, &xraddr, sizeof(struct xsctp_raddr));
if (error) {
SCTP_INP_DECR_REF(inp);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
return (error);
}
SCTP_INP_INFO_RLOCK();
SCTP_INP_RLOCK(inp);
}
atomic_subtract_int(&stcb->asoc.refcnt, 1);
memset((void *)&xraddr, 0, sizeof(struct xsctp_raddr));
xraddr.last = 1;
SCTP_INP_RUNLOCK(inp);
SCTP_INP_INFO_RUNLOCK();
error = SYSCTL_OUT(req, &xraddr, sizeof(struct xsctp_raddr));
if (error) {
SCTP_INP_DECR_REF(inp);
return (error);
}
SCTP_INP_INFO_RLOCK();
SCTP_INP_RLOCK(inp);
}
SCTP_INP_DECR_REF(inp);
SCTP_INP_RUNLOCK(inp);
SCTP_INP_INFO_RUNLOCK();
memset((void *)&xstcb, 0, sizeof(struct xsctp_tcb));
xstcb.last = 1;
error = SYSCTL_OUT(req, &xstcb, sizeof(struct xsctp_tcb));
if (error) {
return (error);
}
skip:
SCTP_INP_INFO_RLOCK();
}
SCTP_INP_INFO_RUNLOCK();
memset((void *)&xinpcb, 0, sizeof(struct xsctp_inpcb));
xinpcb.last = 1;
error = SYSCTL_OUT(req, &xinpcb, sizeof(struct xsctp_inpcb));
return (error);
}
static int
sctp_sysctl_handle_udp_tunneling(SYSCTL_HANDLER_ARGS)
{
int error;
uint32_t old, new;
SCTP_INP_INFO_RLOCK();
old = SCTP_BASE_SYSCTL(sctp_udp_tunneling_port);
SCTP_INP_INFO_RUNLOCK();
new = old;
error = sysctl_handle_int(oidp, &new, 0, req);
if ((error == 0) &&
(req->newptr != NULL)) {
if ((new < SCTPCTL_UDP_TUNNELING_PORT_MIN) ||
(new > SCTPCTL_UDP_TUNNELING_PORT_MAX)) {
error = EINVAL;
} else {
SCTP_INP_INFO_WLOCK();
SCTP_BASE_SYSCTL(sctp_udp_tunneling_port) = new;
if (old != 0) {
sctp_over_udp_stop();
}
if (new != 0) {
error = sctp_over_udp_start();
}
SCTP_INP_INFO_WUNLOCK();
}
}
return (error);
}
static int
sctp_sysctl_handle_auth(SYSCTL_HANDLER_ARGS)
{
int error;
uint32_t new;
new = SCTP_BASE_SYSCTL(sctp_auth_disable);
error = sysctl_handle_int(oidp, &new, 0, req);
if ((error == 0) &&
(req->newptr != NULL)) {
if ((new < SCTPCTL_AUTH_DISABLE_MIN) ||
(new > SCTPCTL_AUTH_DISABLE_MAX) ||
((new == 1) && (SCTP_BASE_SYSCTL(sctp_asconf_enable) == 1))) {
error = EINVAL;
} else {
SCTP_BASE_SYSCTL(sctp_auth_disable) = new;
}
}
return (error);
}
static int
sctp_sysctl_handle_asconf(SYSCTL_HANDLER_ARGS)
{
int error;
uint32_t new;
new = SCTP_BASE_SYSCTL(sctp_asconf_enable);
error = sysctl_handle_int(oidp, &new, 0, req);
if ((error == 0) &&
(req->newptr != NULL)) {
if ((new < SCTPCTL_ASCONF_ENABLE_MIN) ||
(new > SCTPCTL_ASCONF_ENABLE_MAX) ||
((new == 1) && (SCTP_BASE_SYSCTL(sctp_auth_disable) == 1))) {
error = EINVAL;
} else {
SCTP_BASE_SYSCTL(sctp_asconf_enable) = new;
}
}
return (error);
}
static int
sctp_sysctl_handle_stats(SYSCTL_HANDLER_ARGS)
{
int error;
#if defined(SMP) && defined(SCTP_USE_PERCPU_STAT)
struct sctpstat sb_temp;
struct sctpstat *sarry;
struct sctpstat sb;
int cpu;
#endif
if ((req->newptr != NULL) &&
(req->newlen != sizeof(struct sctpstat))) {
return (EINVAL);
}
#if defined(SMP) && defined(SCTP_USE_PERCPU_STAT)
memset(&sb, 0, sizeof(sb));
memset(&sb_temp, 0, sizeof(sb_temp));
if (req->newptr != NULL) {
error = SYSCTL_IN(req, &sb_temp, sizeof(sb_temp));
if (error != 0)
return (error);
}
for (cpu = 0; cpu < mp_maxid; cpu++) {
sarry = &SCTP_BASE_STATS[cpu];
if (sarry->sctps_discontinuitytime.tv_sec > sb.sctps_discontinuitytime.tv_sec) {
sb.sctps_discontinuitytime.tv_sec = sarry->sctps_discontinuitytime.tv_sec;
sb.sctps_discontinuitytime.tv_usec = sarry->sctps_discontinuitytime.tv_usec;
}
sb.sctps_currestab += sarry->sctps_currestab;
sb.sctps_activeestab += sarry->sctps_activeestab;
sb.sctps_restartestab += sarry->sctps_restartestab;
sb.sctps_collisionestab += sarry->sctps_collisionestab;
sb.sctps_passiveestab += sarry->sctps_passiveestab;
sb.sctps_aborted += sarry->sctps_aborted;
sb.sctps_shutdown += sarry->sctps_shutdown;
sb.sctps_outoftheblue += sarry->sctps_outoftheblue;
sb.sctps_checksumerrors += sarry->sctps_checksumerrors;
sb.sctps_outcontrolchunks += sarry->sctps_outcontrolchunks;
sb.sctps_outorderchunks += sarry->sctps_outorderchunks;
sb.sctps_outunorderchunks += sarry->sctps_outunorderchunks;
sb.sctps_incontrolchunks += sarry->sctps_incontrolchunks;
sb.sctps_inorderchunks += sarry->sctps_inorderchunks;
sb.sctps_inunorderchunks += sarry->sctps_inunorderchunks;
sb.sctps_fragusrmsgs += sarry->sctps_fragusrmsgs;
sb.sctps_reasmusrmsgs += sarry->sctps_reasmusrmsgs;
sb.sctps_outpackets += sarry->sctps_outpackets;
sb.sctps_inpackets += sarry->sctps_inpackets;
sb.sctps_recvpackets += sarry->sctps_recvpackets;
sb.sctps_recvdatagrams += sarry->sctps_recvdatagrams;
sb.sctps_recvpktwithdata += sarry->sctps_recvpktwithdata;
sb.sctps_recvsacks += sarry->sctps_recvsacks;
sb.sctps_recvdata += sarry->sctps_recvdata;
sb.sctps_recvdupdata += sarry->sctps_recvdupdata;
sb.sctps_recvheartbeat += sarry->sctps_recvheartbeat;
sb.sctps_recvheartbeatack += sarry->sctps_recvheartbeatack;
sb.sctps_recvecne += sarry->sctps_recvecne;
sb.sctps_recvauth += sarry->sctps_recvauth;
sb.sctps_recvauthmissing += sarry->sctps_recvauthmissing;
sb.sctps_recvivalhmacid += sarry->sctps_recvivalhmacid;
sb.sctps_recvivalkeyid += sarry->sctps_recvivalkeyid;
sb.sctps_recvauthfailed += sarry->sctps_recvauthfailed;
sb.sctps_recvexpress += sarry->sctps_recvexpress;
sb.sctps_recvexpressm += sarry->sctps_recvexpressm;
sb.sctps_recvnocrc += sarry->sctps_recvnocrc;
sb.sctps_recvswcrc += sarry->sctps_recvswcrc;
sb.sctps_recvhwcrc += sarry->sctps_recvhwcrc;
sb.sctps_sendpackets += sarry->sctps_sendpackets;
sb.sctps_sendsacks += sarry->sctps_sendsacks;
sb.sctps_senddata += sarry->sctps_senddata;
sb.sctps_sendretransdata += sarry->sctps_sendretransdata;
sb.sctps_sendfastretrans += sarry->sctps_sendfastretrans;
sb.sctps_sendmultfastretrans += sarry->sctps_sendmultfastretrans;
sb.sctps_sendheartbeat += sarry->sctps_sendheartbeat;
sb.sctps_sendecne += sarry->sctps_sendecne;
sb.sctps_sendauth += sarry->sctps_sendauth;
sb.sctps_senderrors += sarry->sctps_senderrors;
sb.sctps_sendnocrc += sarry->sctps_sendnocrc;
sb.sctps_sendswcrc += sarry->sctps_sendswcrc;
sb.sctps_sendhwcrc += sarry->sctps_sendhwcrc;
sb.sctps_pdrpfmbox += sarry->sctps_pdrpfmbox;
sb.sctps_pdrpfehos += sarry->sctps_pdrpfehos;
sb.sctps_pdrpmbda += sarry->sctps_pdrpmbda;
sb.sctps_pdrpmbct += sarry->sctps_pdrpmbct;
sb.sctps_pdrpbwrpt += sarry->sctps_pdrpbwrpt;
sb.sctps_pdrpcrupt += sarry->sctps_pdrpcrupt;
sb.sctps_pdrpnedat += sarry->sctps_pdrpnedat;
sb.sctps_pdrppdbrk += sarry->sctps_pdrppdbrk;
sb.sctps_pdrptsnnf += sarry->sctps_pdrptsnnf;
sb.sctps_pdrpdnfnd += sarry->sctps_pdrpdnfnd;
sb.sctps_pdrpdiwnp += sarry->sctps_pdrpdiwnp;
sb.sctps_pdrpdizrw += sarry->sctps_pdrpdizrw;
sb.sctps_pdrpbadd += sarry->sctps_pdrpbadd;
sb.sctps_pdrpmark += sarry->sctps_pdrpmark;
sb.sctps_timoiterator += sarry->sctps_timoiterator;
sb.sctps_timodata += sarry->sctps_timodata;
sb.sctps_timowindowprobe += sarry->sctps_timowindowprobe;
sb.sctps_timoinit += sarry->sctps_timoinit;
sb.sctps_timosack += sarry->sctps_timosack;
sb.sctps_timoshutdown += sarry->sctps_timoshutdown;
sb.sctps_timoheartbeat += sarry->sctps_timoheartbeat;
sb.sctps_timocookie += sarry->sctps_timocookie;
sb.sctps_timosecret += sarry->sctps_timosecret;
sb.sctps_timopathmtu += sarry->sctps_timopathmtu;
sb.sctps_timoshutdownack += sarry->sctps_timoshutdownack;
sb.sctps_timoshutdownguard += sarry->sctps_timoshutdownguard;
sb.sctps_timostrmrst += sarry->sctps_timostrmrst;
sb.sctps_timoearlyfr += sarry->sctps_timoearlyfr;
sb.sctps_timoasconf += sarry->sctps_timoasconf;
sb.sctps_timodelprim += sarry->sctps_timodelprim;
sb.sctps_timoautoclose += sarry->sctps_timoautoclose;
sb.sctps_timoassockill += sarry->sctps_timoassockill;
sb.sctps_timoinpkill += sarry->sctps_timoinpkill;
sb.sctps_hdrops += sarry->sctps_hdrops;
sb.sctps_badsum += sarry->sctps_badsum;
sb.sctps_noport += sarry->sctps_noport;
sb.sctps_badvtag += sarry->sctps_badvtag;
sb.sctps_badsid += sarry->sctps_badsid;
sb.sctps_nomem += sarry->sctps_nomem;
sb.sctps_fastretransinrtt += sarry->sctps_fastretransinrtt;
sb.sctps_markedretrans += sarry->sctps_markedretrans;
sb.sctps_naglesent += sarry->sctps_naglesent;
sb.sctps_naglequeued += sarry->sctps_naglequeued;
sb.sctps_maxburstqueued += sarry->sctps_maxburstqueued;
sb.sctps_ifnomemqueued += sarry->sctps_ifnomemqueued;
sb.sctps_windowprobed += sarry->sctps_windowprobed;
sb.sctps_lowlevelerr += sarry->sctps_lowlevelerr;
sb.sctps_lowlevelerrusr += sarry->sctps_lowlevelerrusr;
sb.sctps_datadropchklmt += sarry->sctps_datadropchklmt;
sb.sctps_datadroprwnd += sarry->sctps_datadroprwnd;
sb.sctps_ecnereducedcwnd += sarry->sctps_ecnereducedcwnd;
sb.sctps_vtagexpress += sarry->sctps_vtagexpress;
sb.sctps_vtagbogus += sarry->sctps_vtagbogus;
sb.sctps_primary_randry += sarry->sctps_primary_randry;
sb.sctps_cmt_randry += sarry->sctps_cmt_randry;
sb.sctps_slowpath_sack += sarry->sctps_slowpath_sack;
sb.sctps_wu_sacks_sent += sarry->sctps_wu_sacks_sent;
sb.sctps_sends_with_flags += sarry->sctps_sends_with_flags;
sb.sctps_sends_with_unord += sarry->sctps_sends_with_unord;
sb.sctps_sends_with_eof += sarry->sctps_sends_with_eof;
sb.sctps_sends_with_abort += sarry->sctps_sends_with_abort;
sb.sctps_protocol_drain_calls += sarry->sctps_protocol_drain_calls;
sb.sctps_protocol_drains_done += sarry->sctps_protocol_drains_done;
sb.sctps_read_peeks += sarry->sctps_read_peeks;
sb.sctps_cached_chk += sarry->sctps_cached_chk;
sb.sctps_cached_strmoq += sarry->sctps_cached_strmoq;
sb.sctps_left_abandon += sarry->sctps_left_abandon;
sb.sctps_send_burst_avoid += sarry->sctps_send_burst_avoid;
sb.sctps_send_cwnd_avoid += sarry->sctps_send_cwnd_avoid;
sb.sctps_fwdtsn_map_over += sarry->sctps_fwdtsn_map_over;
if (req->newptr != NULL)
memcpy(sarry, &sb_temp, sizeof(struct sctpstat));
}
error = SYSCTL_OUT(req, &sb, sizeof(struct sctpstat));
#else
error = SYSCTL_IN(req, &SCTP_BASE_STATS, sizeof(struct sctpstat));
if (error)
return (error);
error = SYSCTL_OUT(req, &SCTP_BASE_STATS, sizeof(struct sctpstat));
#endif
return (error);
}
#if defined(SCTP_LOCAL_TRACE_BUF)
static int
sctp_sysctl_handle_trace_log(SYSCTL_HANDLER_ARGS)
{
int error;
error = SYSCTL_OUT(req, &SCTP_BASE_SYSCTL(sctp_log), sizeof(struct sctp_log));
return (error);
}
static int
sctp_sysctl_handle_trace_log_clear(SYSCTL_HANDLER_ARGS)
{
int error = 0;
memset(&SCTP_BASE_SYSCTL(sctp_log), 0, sizeof(struct sctp_log));
return (error);
}
#endif
#define SCTP_UINT_SYSCTL(mib_name, var_name, prefix) \
static int \
sctp_sysctl_handle_##mib_name(SYSCTL_HANDLER_ARGS) \
{ \
int error; \
uint32_t new; \
\
new = SCTP_BASE_SYSCTL(var_name); \
error = sysctl_handle_int(oidp, &new, 0, req); \
if ((error == 0) && (req->newptr != NULL)) { \
if ((new < prefix##_MIN) || \
(new > prefix##_MAX)) { \
error = EINVAL; \
} else { \
SCTP_BASE_SYSCTL(var_name) = new; \
} \
} \
return (error); \
} \
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, mib_name, \
CTLFLAG_VNET|CTLTYPE_UINT|CTLFLAG_RW, NULL, 0, \
sctp_sysctl_handle_##mib_name, "UI", prefix##_DESC);
/*
* sysctl definitions
*/
SCTP_UINT_SYSCTL(sendspace, sctp_sendspace, SCTPCTL_MAXDGRAM)
SCTP_UINT_SYSCTL(recvspace, sctp_recvspace, SCTPCTL_RECVSPACE)
SCTP_UINT_SYSCTL(auto_asconf, sctp_auto_asconf, SCTPCTL_AUTOASCONF)
SCTP_UINT_SYSCTL(ecn_enable, sctp_ecn_enable, SCTPCTL_ECN_ENABLE)
SCTP_UINT_SYSCTL(pr_enable, sctp_pr_enable, SCTPCTL_PR_ENABLE)
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, auth_disable, CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW,
NULL, 0, sctp_sysctl_handle_auth, "IU", SCTPCTL_AUTH_DISABLE_DESC);
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, asconf_enable, CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW,
NULL, 0, sctp_sysctl_handle_asconf, "IU", SCTPCTL_ASCONF_ENABLE_DESC);
SCTP_UINT_SYSCTL(reconfig_enable, sctp_reconfig_enable, SCTPCTL_RECONFIG_ENABLE)
SCTP_UINT_SYSCTL(nr_sack_on_off, sctp_nrsack_enable, SCTPCTL_NRSACK_ENABLE)
SCTP_UINT_SYSCTL(pktdrop_enable, sctp_pktdrop_enable, SCTPCTL_PKTDROP_ENABLE)
SCTP_UINT_SYSCTL(strict_sacks, sctp_strict_sacks, SCTPCTL_STRICT_SACKS)
SCTP_UINT_SYSCTL(peer_chkoh, sctp_peer_chunk_oh, SCTPCTL_PEER_CHKOH)
SCTP_UINT_SYSCTL(maxburst, sctp_max_burst_default, SCTPCTL_MAXBURST)
SCTP_UINT_SYSCTL(fr_maxburst, sctp_fr_max_burst_default, SCTPCTL_FRMAXBURST)
SCTP_UINT_SYSCTL(maxchunks, sctp_max_chunks_on_queue, SCTPCTL_MAXCHUNKS)
SCTP_UINT_SYSCTL(tcbhashsize, sctp_hashtblsize, SCTPCTL_TCBHASHSIZE)
SCTP_UINT_SYSCTL(pcbhashsize, sctp_pcbtblsize, SCTPCTL_PCBHASHSIZE)
SCTP_UINT_SYSCTL(min_split_point, sctp_min_split_point, SCTPCTL_MIN_SPLIT_POINT)
SCTP_UINT_SYSCTL(chunkscale, sctp_chunkscale, SCTPCTL_CHUNKSCALE)
SCTP_UINT_SYSCTL(delayed_sack_time, sctp_delayed_sack_time_default, SCTPCTL_DELAYED_SACK_TIME)
SCTP_UINT_SYSCTL(sack_freq, sctp_sack_freq_default, SCTPCTL_SACK_FREQ)
SCTP_UINT_SYSCTL(sys_resource, sctp_system_free_resc_limit, SCTPCTL_SYS_RESOURCE)
SCTP_UINT_SYSCTL(asoc_resource, sctp_asoc_free_resc_limit, SCTPCTL_ASOC_RESOURCE)
SCTP_UINT_SYSCTL(heartbeat_interval, sctp_heartbeat_interval_default, SCTPCTL_HEARTBEAT_INTERVAL)
SCTP_UINT_SYSCTL(pmtu_raise_time, sctp_pmtu_raise_time_default, SCTPCTL_PMTU_RAISE_TIME)
SCTP_UINT_SYSCTL(shutdown_guard_time, sctp_shutdown_guard_time_default, SCTPCTL_SHUTDOWN_GUARD_TIME)
SCTP_UINT_SYSCTL(secret_lifetime, sctp_secret_lifetime_default, SCTPCTL_SECRET_LIFETIME)
SCTP_UINT_SYSCTL(rto_max, sctp_rto_max_default, SCTPCTL_RTO_MAX)
SCTP_UINT_SYSCTL(rto_min, sctp_rto_min_default, SCTPCTL_RTO_MIN)
SCTP_UINT_SYSCTL(rto_initial, sctp_rto_initial_default, SCTPCTL_RTO_INITIAL)
SCTP_UINT_SYSCTL(init_rto_max, sctp_init_rto_max_default, SCTPCTL_INIT_RTO_MAX)
SCTP_UINT_SYSCTL(valid_cookie_life, sctp_valid_cookie_life_default, SCTPCTL_VALID_COOKIE_LIFE)
SCTP_UINT_SYSCTL(init_rtx_max, sctp_init_rtx_max_default, SCTPCTL_INIT_RTX_MAX)
SCTP_UINT_SYSCTL(assoc_rtx_max, sctp_assoc_rtx_max_default, SCTPCTL_ASSOC_RTX_MAX)
SCTP_UINT_SYSCTL(path_rtx_max, sctp_path_rtx_max_default, SCTPCTL_PATH_RTX_MAX)
SCTP_UINT_SYSCTL(path_pf_threshold, sctp_path_pf_threshold, SCTPCTL_PATH_PF_THRESHOLD)
SCTP_UINT_SYSCTL(add_more_on_output, sctp_add_more_threshold, SCTPCTL_ADD_MORE_ON_OUTPUT)
SCTP_UINT_SYSCTL(incoming_streams, sctp_nr_incoming_streams_default, SCTPCTL_INCOMING_STREAMS)
SCTP_UINT_SYSCTL(outgoing_streams, sctp_nr_outgoing_streams_default, SCTPCTL_OUTGOING_STREAMS)
SCTP_UINT_SYSCTL(cmt_on_off, sctp_cmt_on_off, SCTPCTL_CMT_ON_OFF)
SCTP_UINT_SYSCTL(cmt_use_dac, sctp_cmt_use_dac, SCTPCTL_CMT_USE_DAC)
SCTP_UINT_SYSCTL(cwnd_maxburst, sctp_use_cwnd_based_maxburst, SCTPCTL_CWND_MAXBURST)
SCTP_UINT_SYSCTL(nat_friendly, sctp_nat_friendly, SCTPCTL_NAT_FRIENDLY)
SCTP_UINT_SYSCTL(abc_l_var, sctp_L2_abc_variable, SCTPCTL_ABC_L_VAR)
SCTP_UINT_SYSCTL(max_chained_mbufs, sctp_mbuf_threshold_count, SCTPCTL_MAX_CHAINED_MBUFS)
SCTP_UINT_SYSCTL(do_sctp_drain, sctp_do_drain, SCTPCTL_DO_SCTP_DRAIN)
SCTP_UINT_SYSCTL(hb_max_burst, sctp_hb_maxburst, SCTPCTL_HB_MAX_BURST)
SCTP_UINT_SYSCTL(abort_at_limit, sctp_abort_if_one_2_one_hits_limit, SCTPCTL_ABORT_AT_LIMIT)
SCTP_UINT_SYSCTL(strict_data_order, sctp_strict_data_order, SCTPCTL_STRICT_DATA_ORDER)
SCTP_UINT_SYSCTL(min_residual, sctp_min_residual, SCTPCTL_MIN_RESIDUAL)
SCTP_UINT_SYSCTL(max_retran_chunk, sctp_max_retran_chunk, SCTPCTL_MAX_RETRAN_CHUNK)
SCTP_UINT_SYSCTL(log_level, sctp_logging_level, SCTPCTL_LOGGING_LEVEL)
SCTP_UINT_SYSCTL(default_cc_module, sctp_default_cc_module, SCTPCTL_DEFAULT_CC_MODULE)
SCTP_UINT_SYSCTL(default_ss_module, sctp_default_ss_module, SCTPCTL_DEFAULT_SS_MODULE)
SCTP_UINT_SYSCTL(default_frag_interleave, sctp_default_frag_interleave, SCTPCTL_DEFAULT_FRAG_INTERLEAVE)
SCTP_UINT_SYSCTL(mobility_base, sctp_mobility_base, SCTPCTL_MOBILITY_BASE)
SCTP_UINT_SYSCTL(mobility_fasthandoff, sctp_mobility_fasthandoff, SCTPCTL_MOBILITY_FASTHANDOFF)
#if defined(SCTP_LOCAL_TRACE_BUF)
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, log, CTLFLAG_VNET | CTLTYPE_STRUCT | CTLFLAG_RD,
NULL, 0, sctp_sysctl_handle_trace_log, "S,sctplog", "SCTP logging (struct sctp_log)");
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, clear_trace, CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW,
NULL, 0, sctp_sysctl_handle_trace_log_clear, "IU", "Clear SCTP Logging buffer");
#endif
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, udp_tunneling_port, CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW,
NULL, 0, sctp_sysctl_handle_udp_tunneling, "IU", SCTPCTL_UDP_TUNNELING_PORT_DESC);
SCTP_UINT_SYSCTL(enable_sack_immediately, sctp_enable_sack_immediately, SCTPCTL_SACK_IMMEDIATELY_ENABLE)
SCTP_UINT_SYSCTL(nat_friendly_init, sctp_inits_include_nat_friendly, SCTPCTL_NAT_FRIENDLY_INITS)
SCTP_UINT_SYSCTL(vtag_time_wait, sctp_vtag_time_wait, SCTPCTL_TIME_WAIT)
SCTP_UINT_SYSCTL(buffer_splitting, sctp_buffer_splitting, SCTPCTL_BUFFER_SPLITTING)
SCTP_UINT_SYSCTL(initial_cwnd, sctp_initial_cwnd, SCTPCTL_INITIAL_CWND)
SCTP_UINT_SYSCTL(rttvar_bw, sctp_rttvar_bw, SCTPCTL_RTTVAR_BW)
SCTP_UINT_SYSCTL(rttvar_rtt, sctp_rttvar_rtt, SCTPCTL_RTTVAR_RTT)
SCTP_UINT_SYSCTL(rttvar_eqret, sctp_rttvar_eqret, SCTPCTL_RTTVAR_EQRET)
SCTP_UINT_SYSCTL(rttvar_steady_step, sctp_steady_step, SCTPCTL_RTTVAR_STEADYS)
SCTP_UINT_SYSCTL(use_dcccecn, sctp_use_dccc_ecn, SCTPCTL_RTTVAR_DCCCECN)
SCTP_UINT_SYSCTL(blackhole, sctp_blackhole, SCTPCTL_BLACKHOLE)
SCTP_UINT_SYSCTL(diag_info_code, sctp_diag_info_code, SCTPCTL_DIAG_INFO_CODE)
#ifdef SCTP_DEBUG
SCTP_UINT_SYSCTL(debug, sctp_debug_on, SCTPCTL_DEBUG)
#endif
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_UINT_SYSCTL(output_unlocked, sctp_output_unlocked, SCTPCTL_OUTPUT_UNLOCKED)
#endif
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, stats, CTLFLAG_VNET | CTLTYPE_STRUCT | CTLFLAG_RW,
NULL, 0, sctp_sysctl_handle_stats, "S,sctpstat", "SCTP statistics (struct sctp_stat)");
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, assoclist, CTLFLAG_VNET | CTLTYPE_OPAQUE | CTLFLAG_RD,
NULL, 0, sctp_sysctl_handle_assoclist, "S,xassoc", "List of active SCTP associations");