summaryrefslogtreecommitdiffstats
path: root/sys/netinet/sctp_usrreq.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet/sctp_usrreq.c')
-rw-r--r--sys/netinet/sctp_usrreq.c909
1 files changed, 235 insertions, 674 deletions
diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c
index 1e0d5b3..550a8b3 100644
--- a/sys/netinet/sctp_usrreq.c
+++ b/sys/netinet/sctp_usrreq.c
@@ -37,92 +37,18 @@ __FBSDID("$FreeBSD$");
#include <netinet/sctp_pcb.h>
#include <netinet/sctp_header.h>
#include <netinet/sctp_var.h>
+#include <netinet/sctp_sysctl.h>
#include <netinet/sctp_output.h>
#include <netinet/sctp_bsd_addr.h>
#include <netinet/sctp_uio.h>
#include <netinet/sctp_asconf.h>
#include <netinet/sctputil.h>
#include <netinet/sctp_indata.h>
-#include <netinet/sctp_asconf.h>
#include <netinet/sctp_timer.h>
#include <netinet/sctp_auth.h>
-/*
- * sysctl tunable variables
- */
-int sctp_sendspace = (128 * 1024);
-int sctp_recvspace = 128 * (1024 +
-#ifdef INET6
- sizeof(struct sockaddr_in6)
-#else
- sizeof(struct sockaddr_in)
-#endif
-);
-int sctp_mbuf_threshold_count = SCTP_DEFAULT_MBUFS_IN_CHAIN;
-int sctp_auto_asconf = SCTP_DEFAULT_AUTO_ASCONF;
-int sctp_ecn_enable = 1;
-int sctp_ecn_nonce = 0;
-int sctp_strict_sacks = 0;
-int sctp_no_csum_on_loopback = 1;
-int sctp_strict_init = 1;
-int sctp_abort_if_one_2_one_hits_limit = 0;
-int sctp_strict_data_order = 0;
-
-int sctp_peer_chunk_oh = sizeof(struct mbuf);
-int sctp_max_burst_default = SCTP_DEF_MAX_BURST;
-int sctp_use_cwnd_based_maxburst = 1;
-int sctp_do_drain = 1;
-int sctp_warm_the_crc32_table = 0;
-
-unsigned int sctp_max_chunks_on_queue = SCTP_ASOC_MAX_CHUNKS_ON_QUEUE;
-unsigned int sctp_delayed_sack_time_default = SCTP_RECV_MSEC;
-unsigned int sctp_heartbeat_interval_default = SCTP_HB_DEFAULT_MSEC;
-unsigned int sctp_pmtu_raise_time_default = SCTP_DEF_PMTU_RAISE_SEC;
-unsigned int sctp_shutdown_guard_time_default = SCTP_DEF_MAX_SHUTDOWN_SEC;
-unsigned int sctp_secret_lifetime_default = SCTP_DEFAULT_SECRET_LIFE_SEC;
-unsigned int sctp_rto_max_default = SCTP_RTO_UPPER_BOUND;
-unsigned int sctp_rto_min_default = SCTP_RTO_LOWER_BOUND;
-unsigned int sctp_rto_initial_default = SCTP_RTO_INITIAL;
-unsigned int sctp_init_rto_max_default = SCTP_RTO_UPPER_BOUND;
-unsigned int sctp_valid_cookie_life_default = SCTP_DEFAULT_COOKIE_LIFE;
-unsigned int sctp_init_rtx_max_default = SCTP_DEF_MAX_INIT;
-unsigned int sctp_assoc_rtx_max_default = SCTP_DEF_MAX_SEND;
-unsigned int sctp_path_rtx_max_default = SCTP_DEF_MAX_PATH_RTX;
-unsigned int sctp_nr_outgoing_streams_default = SCTP_OSTREAM_INITIAL;
-unsigned int sctp_add_more_threshold = SCTP_DEFAULT_ADD_MORE;
-
-uint32_t sctp_asoc_free_resc_limit = SCTP_DEF_ASOC_RESC_LIMIT;
-uint32_t sctp_system_free_resc_limit = SCTP_DEF_SYSTEM_RESC_LIMIT;
-
-int sctp_min_split_point = SCTP_DEFAULT_SPLIT_POINT_MIN;
-int sctp_pcbtblsize = SCTP_PCBHASHSIZE;
-int sctp_hashtblsize = SCTP_TCBHASHSIZE;
-int sctp_chunkscale = SCTP_CHUNKQUEUE_SCALE;
-
-unsigned int sctp_cmt_on_off = 0;
-unsigned int sctp_cmt_sockopt_on_off = 0;
-unsigned int sctp_cmt_use_dac = 0;
-
-int sctp_L2_abc_variable = 1;
-unsigned int sctp_early_fr = 0;
-unsigned int sctp_early_fr_msec = SCTP_MINFR_MSEC_TIMER;
-unsigned int sctp_use_rttvar_cc = 0;
-int sctp_says_check_for_deadlock = 0;
-unsigned int sctp_asconf_auth_nochk = 0;
-unsigned int sctp_nat_friendly = 1;
-unsigned int sctp_auth_disable = 0;
-unsigned int sctp_auth_random_len = SCTP_AUTH_RANDOM_SIZE_DEFAULT;
-unsigned int sctp_auth_hmac_id_default = SCTP_AUTH_HMAC_ID_SHA1;
-struct sctpstat sctpstat;
-
-#ifdef SCTP_DEBUG
-extern uint32_t sctp_debug_on;
-
-#endif /* SCTP_DEBUG */
-
-
void
sctp_init(void)
{
@@ -336,6 +262,11 @@ sctp_notify(struct sctp_inpcb *inp,
if ((errno == EHOSTUNREACH) || (errno == EHOSTDOWN)) {
if (net->dest_state & SCTP_ADDR_REACHABLE) {
/* Ok that destination is NOT reachable */
+ printf("ICMP (thresh %d/%d) takes interface %p down\n",
+ net->error_count,
+ net->failure_threshold,
+ net);
+
net->dest_state &= ~SCTP_ADDR_REACHABLE;
net->dest_state |= SCTP_ADDR_NOT_REACHABLE;
net->error_count = net->failure_threshold + 1;
@@ -384,7 +315,9 @@ sctp_ctlinput(cmd, sa, vip)
{
struct ip *ip = vip;
struct sctphdr *sh;
+ uint32_t vrf_id;
+ vrf_id = SCTP_DEFAULT_VRFID;
if (sa->sa_family != AF_INET ||
((struct sockaddr_in *)sa)->sin_addr.s_addr == INADDR_ANY) {
return;
@@ -417,7 +350,7 @@ sctp_ctlinput(cmd, sa, vip)
*/
stcb = sctp_findassociation_addr_sa((struct sockaddr *)&from,
(struct sockaddr *)&to,
- &inp, &net, 1);
+ &inp, &net, 1, vrf_id);
if (stcb != NULL && inp && (inp->sctp_socket != NULL)) {
if (cmd != PRC_MSGSIZE) {
int cm;
@@ -455,13 +388,16 @@ sctp_getcred(SYSCTL_HANDLER_ARGS)
struct sctp_nets *net;
struct sctp_tcb *stcb;
int error;
+ uint32_t vrf_id;
+ vrf_id = SCTP_DEFAULT_VRFID;
/*
* XXXRW: Other instances of getcred use SUSER_ALLOWJAIL, as socket
* visibility is scoped using cr_canseesocket(), which it is not
* here.
*/
- error = priv_check_cred(req->td->td_ucred, PRIV_NETINET_GETCRED, 0);
+ error = priv_check_cred(req->td->td_ucred, PRIV_NETINET_GETCRED,
+ SUSER_ALLOWJAIL);
if (error)
return (error);
@@ -471,7 +407,7 @@ sctp_getcred(SYSCTL_HANDLER_ARGS)
stcb = sctp_findassociation_addr_sa(sintosa(&addrs[0]),
sintosa(&addrs[1]),
- &inp, &net, 1);
+ &inp, &net, 1, vrf_id);
if (stcb == NULL || inp == NULL || inp->sctp_socket == NULL) {
if ((inp != NULL) && (stcb == NULL)) {
/* reduce ref-count */
@@ -506,416 +442,6 @@ out:
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, getcred, CTLTYPE_OPAQUE | CTLFLAG_RW,
0, 0, sctp_getcred, "S,ucred", "Get the ucred of a SCTP connection");
-static int
-sctp_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 sctp_laddr *laddr;
- struct xsctp_inpcb xinpcb;
- struct xsctp_tcb xstcb;
-
-/* struct xsctp_laddr xladdr; */
- struct xsctp_raddr xraddr;
-
- 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 == USER_ADDR_NULL) {
- LIST_FOREACH(inp, &sctppcbinfo.listhead, sctp_list) {
- SCTP_INP_RLOCK(inp);
- number_of_endpoints++;
- /* FIXME MT */
- LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
- number_of_local_addresses++;
- }
- LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
- number_of_associations++;
- /* FIXME MT */
- LIST_FOREACH(laddr, &stcb->asoc.sctp_local_addr_list, sctp_nxt_addr) {
- number_of_local_addresses++;
- }
- 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 * sizeof(struct xsctp_laddr) +
- number_of_associations * sizeof(struct xsctp_tcb) +
- number_of_remote_addresses * sizeof(struct xsctp_raddr);
-#ifdef SCTP_DEBUG
- printf("inps = %u, stcbs = %u, laddrs = %u, raddrs = %u\n",
- number_of_endpoints, number_of_associations,
- number_of_local_addresses, number_of_remote_addresses);
-#endif
- /* request some more memory than needed */
- req->oldidx = (n + n / 8);
- return 0;
- }
- if (req->newptr != USER_ADDR_NULL) {
- SCTP_INP_INFO_RUNLOCK();
- return EPERM;
- }
- LIST_FOREACH(inp, &sctppcbinfo.listhead, sctp_list) {
- SCTP_INP_RLOCK(inp);
- number_of_local_addresses = 0;
- number_of_associations = 0;
- /*
- * LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr)
- * { number_of_local_addresses++; }
- */
- LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
- number_of_associations++;
- }
- xinpcb.last = 0;
- xinpcb.local_port = ntohs(inp->sctp_lport);
- xinpcb.number_local_addresses = number_of_local_addresses;
- xinpcb.number_associations = number_of_associations;
- 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;
- SCTP_INP_INCR_REF(inp);
- SCTP_INP_RUNLOCK(inp);
- SCTP_INP_INFO_RUNLOCK();
- error = SYSCTL_OUT(req, &xinpcb, sizeof(struct xsctp_inpcb));
- if (error) {
- return error;
- }
- SCTP_INP_INFO_RLOCK();
- SCTP_INP_RLOCK(inp);
- /* FIXME MT */
- /*
- * LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr)
- * { error = SYSCTL_OUT(req, &xladdr, sizeof(struct
- * xsctp_laddr)); if (error) { #if
- * defined(SCTP_PER_SOCKET_LOCKING)
- * SCTP_SOCKET_UNLOCK(SCTP_INP_SO(inp), 1);
- * SCTP_UNLOCK_SHARED(sctppcbinfo.ipi_ep_mtx); #endif
- * SCTP_INP_RUNLOCK(inp); SCTP_INP_INFO_RUNLOCK(); 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);
- number_of_local_addresses = 0;
- number_of_remote_addresses = 0;
- /* FIXME MT */
- /*
- * LIST_FOREACH(laddr,
- * &stcb->asoc.sctp_local_addr_list, sctp_nxt_addr)
- * { number_of_local_addresses++; }
- */
- TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
- number_of_remote_addresses++;
- }
- xstcb.LocalPort = ntohs(inp->sctp_lport);
- xstcb.RemPort = ntohs(stcb->rport);
- if (stcb->asoc.primary_destination != NULL)
- xstcb.RemPrimAddr = stcb->asoc.primary_destination->ro._l_addr;
- xstcb.HeartBeatInterval = stcb->asoc.heart_beat_delay;
- xstcb.State = SCTP_GET_STATE(&stcb->asoc); /* FIXME */
- xstcb.InStreams = stcb->asoc.streamincnt;
- xstcb.OutStreams = stcb->asoc.streamoutcnt;
- xstcb.MaxRetr = stcb->asoc.overall_error_count;
- xstcb.PrimProcess = 0; /* not really supported yet */
- xstcb.T1expireds = stcb->asoc.timoinit + stcb->asoc.timocookie;
- xstcb.T2expireds = stcb->asoc.timoshutdown + stcb->asoc.timoshutdownack;
- xstcb.RtxChunks = stcb->asoc.marked_retrans;
- xstcb.StartTime = stcb->asoc.start_time;
- xstcb.DiscontinuityTime = stcb->asoc.discontinuity_time;
-
- xstcb.number_local_addresses = number_of_local_addresses;
- xstcb.number_remote_addresses = number_of_remote_addresses;
- 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;
- SCTP_INP_RUNLOCK(inp);
- SCTP_INP_INFO_RUNLOCK();
- error = SYSCTL_OUT(req, &xstcb, sizeof(struct xsctp_tcb));
- if (error) {
- atomic_add_int(&stcb->asoc.refcnt, -1);
- return error;
- }
- /* FIXME MT */
- /*
- * LIST_FOREACH(laddr,
- * &stcb->asoc.sctp_local_addr_list, sctp_nxt_addr)
- * { error = SYSCTL_OUT(req, &xladdr, sizeof(struct
- * xsctp_laddr)); if (error) { #if
- * defined(SCTP_PER_SOCKET_LOCKING)
- * SCTP_SOCKET_UNLOCK(SCTP_INP_SO(inp), 1);
- * SCTP_UNLOCK_SHARED(sctppcbinfo.ipi_ep_mtx);
- * #endif SCTP_INP_RUNLOCK(inp);
- * SCTP_INP_INFO_RUNLOCK(); return error; }
- * */
- TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
- xraddr.RemAddr = net->ro._l_addr;
- xraddr.RemAddrActive = ((net->dest_state & SCTP_ADDR_REACHABLE) == SCTP_ADDR_REACHABLE);
- xraddr.RemAddrConfirmed = ((net->dest_state & SCTP_ADDR_UNCONFIRMED) == 0);
- xraddr.RemAddrHBActive = ((net->dest_state & SCTP_ADDR_NOHB) == 0);
- xraddr.RemAddrRTO = net->RTO;
- xraddr.RemAddrMaxPathRtx = net->failure_threshold;
- xraddr.RemAddrRtx = net->marked_retrans;
- xraddr.RemAddrErrorCounter = net->error_count;
- xraddr.RemAddrCwnd = net->cwnd;
- xraddr.RemAddrFlightSize = net->flight_size;
- xraddr.RemAddrStartTime = net->start_time;
- error = SYSCTL_OUT(req, &xraddr, sizeof(struct xsctp_raddr));
- if (error) {
- atomic_add_int(&stcb->asoc.refcnt, -1);
- return error;
- }
- }
- atomic_add_int(&stcb->asoc.refcnt, -1);
- SCTP_INP_INFO_RLOCK();
- SCTP_INP_RLOCK(inp);
- }
- SCTP_INP_DECR_REF(inp);
- SCTP_INP_RUNLOCK(inp);
- }
- SCTP_INP_INFO_RUNLOCK();
-
- xinpcb.last = 1;
- xinpcb.local_port = 0;
- xinpcb.number_local_addresses = 0;
- xinpcb.number_associations = 0;
- xinpcb.flags = 0;
- xinpcb.features = 0;
- error = SYSCTL_OUT(req, &xinpcb, sizeof(struct xsctp_inpcb));
- return error;
-}
-
-/*
- * sysctl definitions
- */
-
-SYSCTL_INT(_net_inet_sctp, OID_AUTO, sendspace, CTLFLAG_RW,
- &sctp_sendspace, 0, "Maximum outgoing SCTP buffer size");
-
-SYSCTL_INT(_net_inet_sctp, OID_AUTO, recvspace, CTLFLAG_RW,
- &sctp_recvspace, 0, "Maximum incoming SCTP buffer size");
-
-SYSCTL_INT(_net_inet_sctp, OID_AUTO, auto_asconf, CTLFLAG_RW,
- &sctp_auto_asconf, 0, "Enable SCTP Auto-ASCONF");
-
-SYSCTL_INT(_net_inet_sctp, OID_AUTO, ecn_enable, CTLFLAG_RW,
- &sctp_ecn_enable, 0, "Enable SCTP ECN");
-
-SYSCTL_INT(_net_inet_sctp, OID_AUTO, ecn_nonce, CTLFLAG_RW,
- &sctp_ecn_nonce, 0, "Enable SCTP ECN Nonce");
-
-SYSCTL_INT(_net_inet_sctp, OID_AUTO, strict_sacks, CTLFLAG_RW,
- &sctp_strict_sacks, 0, "Enable SCTP Strict SACK checking");
-
-SYSCTL_INT(_net_inet_sctp, OID_AUTO, loopback_nocsum, CTLFLAG_RW,
- &sctp_no_csum_on_loopback, 0,
- "Enable NO Csum on packets sent on loopback");
-
-SYSCTL_INT(_net_inet_sctp, OID_AUTO, strict_init, CTLFLAG_RW,
- &sctp_strict_init, 0,
- "Enable strict INIT/INIT-ACK singleton enforcement");
-
-SYSCTL_INT(_net_inet_sctp, OID_AUTO, peer_chkoh, CTLFLAG_RW,
- &sctp_peer_chunk_oh, 0,
- "Amount to debit peers rwnd per chunk sent");
-
-SYSCTL_INT(_net_inet_sctp, OID_AUTO, maxburst, CTLFLAG_RW,
- &sctp_max_burst_default, 0,
- "Default max burst for sctp endpoints");
-
-SYSCTL_INT(_net_inet_sctp, OID_AUTO, maxchunks, CTLFLAG_RW,
- &sctp_max_chunks_on_queue, 0,
- "Default max chunks on queue per asoc");
-
-SYSCTL_INT(_net_inet_sctp, OID_AUTO, tcbhashsize, CTLFLAG_RW,
- &sctp_hashtblsize, 0,
- "Tuneable for Hash table sizes");
-
-SYSCTL_INT(_net_inet_sctp, OID_AUTO, min_split_point, CTLFLAG_RW,
- &sctp_min_split_point, 0,
- "Minimum size when splitting a chunk");
-
-SYSCTL_INT(_net_inet_sctp, OID_AUTO, pcbhashsize, CTLFLAG_RW,
- &sctp_pcbtblsize, 0,
- "Tuneable for PCB Hash table sizes");
-
-SYSCTL_INT(_net_inet_sctp, OID_AUTO, sys_resource, CTLFLAG_RW,
- &sctp_system_free_resc_limit, 0,
- "Max number of cached resources in the system");
-
-SYSCTL_INT(_net_inet_sctp, OID_AUTO, asoc_resource, CTLFLAG_RW,
- &sctp_asoc_free_resc_limit, 0,
- "Max number of cached resources in an asoc");
-
-SYSCTL_INT(_net_inet_sctp, OID_AUTO, chunkscale, CTLFLAG_RW,
- &sctp_chunkscale, 0,
- "Tuneable for Scaling of number of chunks and messages");
-
-SYSCTL_UINT(_net_inet_sctp, OID_AUTO, delayed_sack_time, CTLFLAG_RW,
- &sctp_delayed_sack_time_default, 0,
- "Default delayed SACK timer in msec");
-
-SYSCTL_UINT(_net_inet_sctp, OID_AUTO, heartbeat_interval, CTLFLAG_RW,
- &sctp_heartbeat_interval_default, 0,
- "Default heartbeat interval in msec");
-
-SYSCTL_UINT(_net_inet_sctp, OID_AUTO, pmtu_raise_time, CTLFLAG_RW,
- &sctp_pmtu_raise_time_default, 0,
- "Default PMTU raise timer in sec");
-
-SYSCTL_UINT(_net_inet_sctp, OID_AUTO, shutdown_guard_time, CTLFLAG_RW,
- &sctp_shutdown_guard_time_default, 0,
- "Default shutdown guard timer in sec");
-
-SYSCTL_UINT(_net_inet_sctp, OID_AUTO, secret_lifetime, CTLFLAG_RW,
- &sctp_secret_lifetime_default, 0,
- "Default secret lifetime in sec");
-
-SYSCTL_UINT(_net_inet_sctp, OID_AUTO, rto_max, CTLFLAG_RW,
- &sctp_rto_max_default, 0,
- "Default maximum retransmission timeout in msec");
-
-SYSCTL_UINT(_net_inet_sctp, OID_AUTO, rto_min, CTLFLAG_RW,
- &sctp_rto_min_default, 0,
- "Default minimum retransmission timeout in msec");
-
-SYSCTL_UINT(_net_inet_sctp, OID_AUTO, rto_initial, CTLFLAG_RW,
- &sctp_rto_initial_default, 0,
- "Default initial retransmission timeout in msec");
-
-SYSCTL_UINT(_net_inet_sctp, OID_AUTO, init_rto_max, CTLFLAG_RW,
- &sctp_init_rto_max_default, 0,
- "Default maximum retransmission timeout during association setup in msec");
-
-SYSCTL_UINT(_net_inet_sctp, OID_AUTO, valid_cookie_life, CTLFLAG_RW,
- &sctp_valid_cookie_life_default, 0,
- "Default cookie lifetime in sec");
-
-SYSCTL_UINT(_net_inet_sctp, OID_AUTO, init_rtx_max, CTLFLAG_RW,
- &sctp_init_rtx_max_default, 0,
- "Default maximum number of retransmission for INIT chunks");
-
-SYSCTL_UINT(_net_inet_sctp, OID_AUTO, assoc_rtx_max, CTLFLAG_RW,
- &sctp_assoc_rtx_max_default, 0,
- "Default maximum number of retransmissions per association");
-
-SYSCTL_UINT(_net_inet_sctp, OID_AUTO, path_rtx_max, CTLFLAG_RW,
- &sctp_path_rtx_max_default, 0,
- "Default maximum of retransmissions per path");
-
-SYSCTL_UINT(_net_inet_sctp, OID_AUTO, add_more_on_output, CTLFLAG_RW,
- &sctp_add_more_threshold, 0,
- "When space wise is it worthwhile to try to add more to a socket send buffer");
-
-SYSCTL_UINT(_net_inet_sctp, OID_AUTO, nr_outgoing_streams, CTLFLAG_RW,
- &sctp_nr_outgoing_streams_default, 0,
- "Default number of outgoing streams");
-
-SYSCTL_UINT(_net_inet_sctp, OID_AUTO, cmt_on_off, CTLFLAG_RW,
- &sctp_cmt_on_off, 0,
- "CMT ON/OFF flag");
-
-SYSCTL_UINT(_net_inet_sctp, OID_AUTO, cwnd_maxburst, CTLFLAG_RW,
- &sctp_use_cwnd_based_maxburst, 0,
- "Use a CWND adjusting maxburst");
-
-SYSCTL_UINT(_net_inet_sctp, OID_AUTO, early_fast_retran, CTLFLAG_RW,
- &sctp_early_fr, 0,
- "Early Fast Retransmit with Timer");
-
-SYSCTL_UINT(_net_inet_sctp, OID_AUTO, use_rttvar_congctrl, CTLFLAG_RW,
- &sctp_use_rttvar_cc, 0,
- "Use congestion control via rtt variation");
-
-SYSCTL_UINT(_net_inet_sctp, OID_AUTO, deadlock_detect, CTLFLAG_RW,
- &sctp_says_check_for_deadlock, 0,
- "SMP Deadlock detection on/off");
-
-SYSCTL_UINT(_net_inet_sctp, OID_AUTO, early_fast_retran_msec, CTLFLAG_RW,
- &sctp_early_fr_msec, 0,
- "Early Fast Retransmit minimum timer value");
-
-SYSCTL_UINT(_net_inet_sctp, OID_AUTO, asconf_auth_nochk, CTLFLAG_RW,
- &sctp_asconf_auth_nochk, 0,
- "Disable SCTP ASCONF AUTH requirement");
-
-SYSCTL_UINT(_net_inet_sctp, OID_AUTO, auth_disable, CTLFLAG_RW,
- &sctp_auth_disable, 0,
- "Disable SCTP AUTH chunk requirement/function");
-
-SYSCTL_UINT(_net_inet_sctp, OID_AUTO, auth_random_len, CTLFLAG_RW,
- &sctp_auth_random_len, 0,
- "Length of AUTH RANDOMs");
-
-SYSCTL_UINT(_net_inet_sctp, OID_AUTO, auth_hmac_id, CTLFLAG_RW,
- &sctp_auth_hmac_id_default, 0,
- "Default HMAC Id for SCTP AUTHenthication");
-
-SYSCTL_INT(_net_inet_sctp, OID_AUTO, abc_l_var, CTLFLAG_RW,
- &sctp_L2_abc_variable, 0,
- "SCTP ABC max increase per SACK (L)");
-
-SYSCTL_INT(_net_inet_sctp, OID_AUTO, max_chained_mbufs, CTLFLAG_RW,
- &sctp_mbuf_threshold_count, 0,
- "Default max number of small mbufs on a chain");
-
-SYSCTL_UINT(_net_inet_sctp, OID_AUTO, cmt_use_dac, CTLFLAG_RW,
- &sctp_cmt_use_dac, 0,
- "CMT DAC ON/OFF flag");
-
-SYSCTL_INT(_net_inet_sctp, OID_AUTO, do_sctp_drain, CTLFLAG_RW,
- &sctp_do_drain, 0,
- "Should SCTP respond to the drain calls");
-
-SYSCTL_INT(_net_inet_sctp, OID_AUTO, warm_crc_table, CTLFLAG_RW,
- &sctp_warm_the_crc32_table, 0,
- "Should the CRC32c tables be warmed before checksum?");
-
-SYSCTL_INT(_net_inet_sctp, OID_AUTO, abort_at_limit, CTLFLAG_RW,
- &sctp_abort_if_one_2_one_hits_limit, 0,
- "When one-2-one hits qlimit abort");
-
-SYSCTL_INT(_net_inet_sctp, OID_AUTO, strict_data_order, CTLFLAG_RW,
- &sctp_strict_data_order, 0,
- "Enforce strict data ordering, abort if control inside data");
-
-SYSCTL_STRUCT(_net_inet_sctp, OID_AUTO, stats, CTLFLAG_RW,
- &sctpstat, sctpstat,
- "SCTP statistics (struct sctps_stat, netinet/sctp.h");
-
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, assoclist, CTLFLAG_RD,
- 0, 0, sctp_assoclist,
- "S,xassoc", "List of active SCTP associations");
-
-SYSCTL_UINT(_net_inet_sctp, OID_AUTO, nat_friendly, CTLFLAG_RW,
- &sctp_nat_friendly, 0,
- "SCTP NAT friendly operation");
-
-#ifdef SCTP_DEBUG
-SYSCTL_INT(_net_inet_sctp, OID_AUTO, debug, CTLFLAG_RW,
- &sctp_debug_on, 0, "Configure debug output");
-#endif /* SCTP_DEBUG */
static void
sctp_abort(struct socket *so)
@@ -1501,13 +1027,15 @@ static size_t
sctp_fill_up_addresses(struct sctp_inpcb *inp,
struct sctp_tcb *stcb,
size_t limit,
- struct sockaddr_storage *sas)
+ struct sockaddr_storage *sas,
+ uint32_t vrf_id)
{
- struct ifnet *ifn;
- struct ifaddr *ifa;
+ struct sctp_ifn *sctp_ifn;
+ struct sctp_ifa *sctp_ifa;
int loopback_scope, ipv4_local_scope, local_scope, site_scope;
size_t actual;
int ipv4_addr_legal, ipv6_addr_legal;
+ struct sctp_vrf *vrf;
actual = 0;
if (limit <= 0)
@@ -1533,15 +1061,18 @@ sctp_fill_up_addresses(struct sctp_inpcb *inp,
} else {
ipv4_addr_legal = 1;
}
-
+ vrf = sctp_find_vrf(vrf_id);
+ if (vrf == NULL) {
+ return (0);
+ }
if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
- TAILQ_FOREACH(ifn, &ifnet, if_list) {
+ LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
if ((loopback_scope == 0) &&
- (ifn->if_type == IFT_LOOP)) {
+ SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
/* Skip loopback if loopback_scope not set */
continue;
}
- TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list) {
+ LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
if (stcb) {
/*
* For the BOUND-ALL case, the list
@@ -1552,15 +1083,15 @@ sctp_fill_up_addresses(struct sctp_inpcb *inp,
* is one of those we must skip it.
*/
if (sctp_is_addr_restricted(stcb,
- ifa->ifa_addr)) {
+ sctp_ifa)) {
continue;
}
}
- if ((ifa->ifa_addr->sa_family == AF_INET) &&
+ if ((sctp_ifa->address.sa.sa_family == AF_INET) &&
(ipv4_addr_legal)) {
struct sockaddr_in *sin;
- sin = (struct sockaddr_in *)ifa->ifa_addr;
+ sin = (struct sockaddr_in *)&sctp_ifa->address.sa;
if (sin->sin_addr.s_addr == 0) {
/*
* we skip unspecifed
@@ -1586,11 +1117,11 @@ sctp_fill_up_addresses(struct sctp_inpcb *inp,
if (actual >= limit) {
return (actual);
}
- } else if ((ifa->ifa_addr->sa_family == AF_INET6) &&
+ } else if ((sctp_ifa->address.sa.sa_family == AF_INET6) &&
(ipv6_addr_legal)) {
struct sockaddr_in6 *sin6;
- sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
+ sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa;
if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
/*
* we skip unspecifed
@@ -1628,67 +1159,22 @@ sctp_fill_up_addresses(struct sctp_inpcb *inp,
} else {
struct sctp_laddr *laddr;
- /*
- * If we have a TCB and we do NOT support ASCONF (it's
- * turned off or otherwise) then the list is always the true
- * list of addresses (the else case below). Otherwise the
- * list on the association is a list of addresses that are
- * NOT part of the association.
- */
- if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF)) {
- /* The list is a NEGATIVE list */
- LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
- if (stcb) {
- if (sctp_is_addr_restricted(stcb, laddr->ifa->ifa_addr)) {
- continue;
- }
- }
- if (sctp_fill_user_address(sas, laddr->ifa->ifa_addr))
+ /* The list is a NEGATIVE list */
+ LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
+ if (stcb) {
+ if (sctp_is_addr_restricted(stcb, laddr->ifa)) {
continue;
-
- ((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
- sas = (struct sockaddr_storage *)((caddr_t)sas +
- laddr->ifa->ifa_addr->sa_len);
- actual += laddr->ifa->ifa_addr->sa_len;
- if (actual >= limit) {
- return (actual);
}
}
- } else {
- /* The list is a positive list if present */
- if (stcb) {
- /* Must use the specific association list */
- LIST_FOREACH(laddr, &stcb->asoc.sctp_local_addr_list,
- sctp_nxt_addr) {
- if (sctp_fill_user_address(sas,
- laddr->ifa->ifa_addr))
- continue;
- ((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
- sas = (struct sockaddr_storage *)((caddr_t)sas +
- laddr->ifa->ifa_addr->sa_len);
- actual += laddr->ifa->ifa_addr->sa_len;
- if (actual >= limit) {
- return (actual);
- }
- }
- } else {
- /*
- * No endpoint so use the endpoints
- * individual list
- */
- LIST_FOREACH(laddr, &inp->sctp_addr_list,
- sctp_nxt_addr) {
- if (sctp_fill_user_address(sas,
- laddr->ifa->ifa_addr))
- continue;
- ((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
- sas = (struct sockaddr_storage *)((caddr_t)sas +
- laddr->ifa->ifa_addr->sa_len);
- actual += laddr->ifa->ifa_addr->sa_len;
- if (actual >= limit) {
- return (actual);
- }
- }
+ if (sctp_fill_user_address(sas, &laddr->ifa->address.sa))
+ continue;
+
+ ((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
+ sas = (struct sockaddr_storage *)((caddr_t)sas +
+ laddr->ifa->address.sa.sa_len);
+ actual += laddr->ifa->address.sa.sa_len;
+ if (actual >= limit) {
+ return (actual);
}
}
}
@@ -1696,9 +1182,10 @@ sctp_fill_up_addresses(struct sctp_inpcb *inp,
}
static int
-sctp_count_max_addresses(struct sctp_inpcb *inp)
+sctp_count_max_addresses(struct sctp_inpcb *inp, uint32_t vrf_id)
{
int cnt = 0;
+ struct sctp_vrf *vrf = NULL;
/*
* In both sub-set bound an bound_all cases we return the MAXIMUM
@@ -1707,20 +1194,24 @@ sctp_count_max_addresses(struct sctp_inpcb *inp)
* bound-all case a TCB may NOT include the loopback or other
* addresses as well.
*/
+ vrf = sctp_find_vrf(vrf_id);
+ if (vrf == NULL) {
+ return (0);
+ }
if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
- struct ifnet *ifn;
- struct ifaddr *ifa;
+ struct sctp_ifn *sctp_ifn;
+ struct sctp_ifa *sctp_ifa;
- TAILQ_FOREACH(ifn, &ifnet, if_list) {
- TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list) {
+ LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
+ LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
/* Count them if they are the right type */
- if (ifa->ifa_addr->sa_family == AF_INET) {
+ if (sctp_ifa->address.sa.sa_family == AF_INET) {
if (inp->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)
cnt += sizeof(struct sockaddr_in6);
else
cnt += sizeof(struct sockaddr_in);
- } else if (ifa->ifa_addr->sa_family == AF_INET6)
+ } else if (sctp_ifa->address.sa.sa_family == AF_INET6)
cnt += sizeof(struct sockaddr_in6);
}
}
@@ -1728,13 +1219,13 @@ sctp_count_max_addresses(struct sctp_inpcb *inp)
struct sctp_laddr *laddr;
LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
- if (laddr->ifa->ifa_addr->sa_family == AF_INET) {
+ if (laddr->ifa->address.sa.sa_family == AF_INET) {
if (inp->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)
cnt += sizeof(struct sockaddr_in6);
else
cnt += sizeof(struct sockaddr_in);
- } else if (laddr->ifa->ifa_addr->sa_family == AF_INET6)
+ } else if (laddr->ifa->address.sa.sa_family == AF_INET6)
cnt += sizeof(struct sockaddr_in6);
}
}
@@ -1752,6 +1243,8 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
struct sockaddr *sa;
int num_v6 = 0, num_v4 = 0, *totaddrp, totaddr, i;
size_t incr, at;
+ uint32_t vrf_id;
+ sctp_assoc_t *a_id;
#ifdef SCTP_DEBUG
if (sctp_debug_on & SCTP_DEBUG_PCB1) {
@@ -1856,8 +1349,9 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
SCTP_INP_WUNLOCK(inp);
}
+ vrf_id = SCTP_DEFAULT_VRFID;
/* We are GOOD to go */
- stcb = sctp_aloc_assoc(inp, sa, 1, &error, 0);
+ stcb = sctp_aloc_assoc(inp, sa, 1, &error, 0, vrf_id);
if (stcb == NULL) {
/* Gak! no memory */
goto out_now;
@@ -1889,6 +1383,9 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
sa = (struct sockaddr *)((caddr_t)sa + incr);
}
stcb->asoc.state = SCTP_STATE_COOKIE_WAIT;
+ /* Fill in the return id */
+ a_id = (sctp_assoc_t *) optval;
+ *a_id = sctp_get_associd(stcb);
/* initialize authentication parameters for the assoc */
sctp_initialize_auth_params(inp, stcb);
@@ -1939,13 +1436,13 @@ out_now:
destp = (type *)srcp; \
}
-
static int
sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
void *p)
{
struct sctp_inpcb *inp;
int error, val = 0;
+ uint32_t vrf_id;
struct sctp_tcb *stcb = NULL;
if (optval == NULL) {
@@ -1954,6 +1451,8 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
inp = (struct sctp_inpcb *)so->so_pcb;
if (inp == 0)
return EINVAL;
+ vrf_id = SCTP_DEFAULT_VRFID;
+
error = 0;
switch (optname) {
@@ -2008,6 +1507,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
*optsize = sizeof(val);
}
break;
+
case SCTP_PARTIAL_DELIVERY_POINT:
{
uint32_t *value;
@@ -2052,13 +1552,13 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
error = EINVAL;
-#ifdef AF_INET
+#ifdef INET
if (av->assoc_value == AF_INET) {
av->assoc_value = sizeof(struct sockaddr_in);
error = 0;
}
#endif
-#ifdef AF_INET6
+#ifdef INET6
if (av->assoc_value == AF_INET6) {
av->assoc_value = sizeof(struct sockaddr_in6);
error = 0;
@@ -2130,6 +1630,32 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
*optsize = sizeof(*av);
}
break;
+ case SCTP_VRF_ID:
+ {
+ uint32_t *vrf_id;
+
+ SCTP_CHECK_AND_CAST(vrf_id, optval, uint32_t, *optsize);
+ *vrf_id = inp->def_vrf_id;
+ break;
+ }
+ case SCTP_GET_ASOC_VRF:
+ {
+ struct sctp_assoc_value *id;
+
+ SCTP_CHECK_AND_CAST(id, optval, struct sctp_assoc_value, *optsize);
+ SCTP_FIND_STCB(inp, stcb, id->assoc_id);
+ if (stcb == NULL) {
+ error = EINVAL;
+ break;
+ }
+ id->assoc_value = stcb->asoc.vrf_id;
+ break;
+ }
+ case SCTP_GET_VRF_IDS:
+ {
+ error = EOPNOTSUPP;
+ break;
+ }
case SCTP_GET_NONCE_VALUES:
{
struct sctp_get_nonce_values *gnv;
@@ -2196,38 +1722,37 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
*optsize = sizeof(uint8_t);
}
break;
- /*
- * FIXME MT: Should this be done as the association level by
- * using sctp_get_frag_point?
- */
case SCTP_MAXSEG:
{
- uint32_t *segsize;
+ struct sctp_assoc_value *av;
int ovh;
- SCTP_CHECK_AND_CAST(segsize, optval, uint32_t, *optsize);
+ SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
+ SCTP_FIND_STCB(inp, stcb, av->assoc_id);
- SCTP_INP_RLOCK(inp);
- if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
- ovh = SCTP_MED_OVERHEAD;
+ if (stcb) {
+ av->assoc_value = sctp_get_frag_point(stcb, &stcb->asoc);
+ SCTP_TCB_UNLOCK(stcb);
} else {
- ovh = SCTP_MED_V4_OVERHEAD;
+ SCTP_INP_RLOCK(inp);
+ if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
+ ovh = SCTP_MED_OVERHEAD;
+ } else {
+ ovh = SCTP_MED_V4_OVERHEAD;
+ }
+ av->assoc_value = inp->sctp_frag_point - ovh;
+ SCTP_INP_RUNLOCK(inp);
}
- *segsize = inp->sctp_frag_point - ovh;
- SCTP_INP_RUNLOCK(inp);
- *optsize = sizeof(uint32_t);
+ *optsize = sizeof(struct sctp_assoc_value);
}
break;
-#if 0
- /* FIXME MT: How does this work? */
case SCTP_GET_STAT_LOG:
#ifdef SCTP_STAT_LOGGING
- error = sctp_fill_stat_log(m);
-#else /* SCTP_DEBUG */
+ error = sctp_fill_stat_log(optval, optsize);
+#else
error = EOPNOTSUPP;
#endif
break;
-#endif
case SCTP_EVENTS:
{
struct sctp_event_subscribe *events;
@@ -2298,7 +1823,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
SCTP_INP_RLOCK(inp);
- *value = sctp_count_max_addresses(inp);
+ *value = sctp_count_max_addresses(inp, vrf_id);
SCTP_INP_RUNLOCK(inp);
*optsize = sizeof(uint32_t);
}
@@ -2399,7 +1924,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
sas = (struct sockaddr_storage *)&saddr->addr[0];
limit = *optsize - sizeof(sctp_assoc_t);
- actual = sctp_fill_up_addresses(inp, stcb, limit, sas);
+ actual = sctp_fill_up_addresses(inp, stcb, limit, sas, vrf_id);
if (stcb)
SCTP_TCB_UNLOCK(stcb);
*optsize = sizeof(struct sockaddr_storage) + actual;
@@ -2448,13 +1973,13 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
} else {
paddrp->spp_flags |= SPP_PMTUD_DISABLE;
}
-#ifdef AF_INET
+#ifdef INET
if (net->ro._l_addr.sin.sin_family == AF_INET) {
paddrp->spp_ipv4_tos = net->tos_flowlabel & 0x000000fc;
paddrp->spp_flags |= SPP_IPV4_TOS;
}
#endif
-#ifdef AF_INET6
+#ifdef INET6
if (net->ro._l_addr.sin6.sin6_family == AF_INET6) {
paddrp->spp_ipv6_flowlabel = net->tos_flowlabel;
paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
@@ -2467,11 +1992,11 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
*/
paddrp->spp_pathmaxrxt = stcb->asoc.def_net_failure;
paddrp->spp_pathmtu = sctp_get_frag_point(stcb, &stcb->asoc);
-#ifdef AF_INET
+#ifdef INET
paddrp->spp_ipv4_tos = stcb->asoc.default_tos & 0x000000fc;
paddrp->spp_flags |= SPP_IPV4_TOS;
#endif
-#ifdef AF_INET6
+#ifdef INET6
paddrp->spp_ipv6_flowlabel = stcb->asoc.default_flowlabel;
paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
#endif
@@ -2481,12 +2006,6 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
}
}
paddrp->spp_hbinterval = stcb->asoc.heart_beat_delay;
- paddrp->spp_sackdelay = stcb->asoc.delayed_ack;
- /*
- * Currently we don't support no sack delay
- * aka SPP_SACKDELAY_DISABLE.
- */
- paddrp->spp_flags |= SPP_SACKDELAY_ENABLE;
paddrp->spp_assoc_id = sctp_get_associd(stcb);
SCTP_TCB_UNLOCK(stcb);
} else {
@@ -2494,14 +2013,13 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
SCTP_INP_RLOCK(inp);
paddrp->spp_pathmaxrxt = inp->sctp_ep.def_net_failure;
paddrp->spp_hbinterval = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]);
- paddrp->spp_sackdelay = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]);
paddrp->spp_assoc_id = (sctp_assoc_t) 0;
/* get inp's default */
-#ifdef AF_INET
+#ifdef INET
paddrp->spp_ipv4_tos = inp->ip_inp.inp.inp_ip_tos;
paddrp->spp_flags |= SPP_IPV4_TOS;
#endif
-#ifdef AF_INET6
+#ifdef INET6
if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
paddrp->spp_ipv6_flowlabel = ((struct in6pcb *)inp)->in6p_flowinfo;
paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
@@ -2511,7 +2029,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
paddrp->spp_pathmaxrxt = 0;
paddrp->spp_pathmtu = 0;
/* default behavior, no stcb */
- paddrp->spp_flags = SPP_HB_ENABLE | SPP_SACKDELAY_ENABLE | SPP_PMTUD_ENABLE;
+ paddrp->spp_flags = SPP_HB_ENABLE | SPP_PMTUD_ENABLE;
SCTP_INP_RUNLOCK(inp);
}
@@ -2569,6 +2087,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
*optsize = sizeof(struct sctp_pcbinfo);
}
break;
+
case SCTP_STATUS:
{
struct sctp_nets *net;
@@ -2654,6 +2173,8 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
sasoc->sasoc_peer_rwnd = stcb->asoc.peers_rwnd;
sasoc->sasoc_local_rwnd = stcb->asoc.my_rwnd;
sasoc->sasoc_cookie_life = stcb->asoc.cookie_life;
+ sasoc->sasoc_sack_delay = stcb->asoc.delayed_ack;
+ sasoc->sasoc_sack_freq = stcb->asoc.sack_freq;
SCTP_TCB_UNLOCK(stcb);
} else {
SCTP_INP_RLOCK(inp);
@@ -2662,6 +2183,8 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
sasoc->sasoc_peer_rwnd = 0;
sasoc->sasoc_local_rwnd = sbspace(&inp->sctp_socket->so_rcv);
sasoc->sasoc_cookie_life = inp->sctp_ep.def_cookie_life;
+ sasoc->sasoc_sack_delay = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]);
+ sasoc->sasoc_sack_freq = inp->sctp_ep.sctp_sack_freq;
SCTP_INP_RUNLOCK(inp);
}
*optsize = sizeof(*sasoc);
@@ -2845,7 +2368,6 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
return (error);
}
-
static int
sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
void *p)
@@ -2854,13 +2376,18 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
uint32_t *mopt;
struct sctp_tcb *stcb = NULL;
struct sctp_inpcb *inp;
+ uint32_t vrf_id;
if (optval == NULL) {
+ printf("optval is NULL\n");
return (EINVAL);
}
inp = (struct sctp_inpcb *)so->so_pcb;
- if (inp == 0)
+ if (inp == 0) {
+ printf("inp is NULL?\n");
return EINVAL;
+ }
+ vrf_id = SCTP_DEFAULT_VRFID;
error = 0;
switch (optname) {
@@ -2979,6 +2506,29 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
}
break;
+ case SCTP_VRF_ID:
+ {
+ uint32_t *vrf_id;
+
+ SCTP_CHECK_AND_CAST(vrf_id, optval, uint32_t, optsize);
+ if (*vrf_id > SCTP_MAX_VRF_ID) {
+ error = EINVAL;
+ break;
+ }
+ inp->def_vrf_id = *vrf_id;
+ break;
+ }
+ case SCTP_DEL_VRF_ID:
+ {
+ error = EOPNOTSUPP;
+ break;
+ }
+ case SCTP_ADD_VRF_ID:
+ {
+ error = EOPNOTSUPP;
+ break;
+ }
+
case SCTP_DELAYED_ACK_TIME:
{
struct sctp_assoc_value *tm;
@@ -3313,24 +2863,33 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
break;
case SCTP_MAXSEG:
{
- uint32_t *segsize;
+ struct sctp_assoc_value *av;
int ovh;
- SCTP_CHECK_AND_CAST(segsize, optval, uint32_t, optsize);
+ SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
+ SCTP_FIND_STCB(inp, stcb, av->assoc_id);
- if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
- ovh = SCTP_MED_OVERHEAD;
- } else {
- ovh = SCTP_MED_V4_OVERHEAD;
- }
- SCTP_INP_WLOCK(inp);
- /* FIXME MT: Why is this not allowed? */
- if (*segsize) {
- inp->sctp_frag_point = (*segsize + ovh);
- } else {
+ if (stcb) {
error = EINVAL;
+ SCTP_TCB_UNLOCK(stcb);
+ } else {
+ SCTP_INP_WLOCK(inp);
+ if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
+ ovh = SCTP_MED_OVERHEAD;
+ } else {
+ ovh = SCTP_MED_V4_OVERHEAD;
+ }
+ /*
+ * FIXME MT: I think this is not in tune
+ * with the API ID
+ */
+ if (av->assoc_value) {
+ inp->sctp_frag_point = (av->assoc_value + ovh);
+ } else {
+ error = EINVAL;
+ }
+ SCTP_INP_WUNLOCK(inp);
}
- SCTP_INP_WUNLOCK(inp);
}
break;
case SCTP_EVENTS:
@@ -3477,20 +3036,6 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
if (stcb) {
/************************TCB SPECIFIC SET ******************/
- /* sack delay first */
- if (paddrp->spp_flags & SPP_SACKDELAY_ENABLE) {
- /*
- * we do NOT support turning it off
- * (yet). only setting the delay.
- */
- if (paddrp->spp_sackdelay >= SCTP_CLOCK_GRANULARITY)
- stcb->asoc.delayed_ack = paddrp->spp_sackdelay;
- else
- stcb->asoc.delayed_ack = SCTP_CLOCK_GRANULARITY;
-
- } else if (paddrp->spp_flags & SPP_SACKDELAY_DISABLE) {
- stcb->asoc.delayed_ack = 0;
- }
/*
* do we change the timer for HB, we run
* only one?
@@ -3531,14 +3076,14 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
if (paddrp->spp_pathmaxrxt)
net->failure_threshold = paddrp->spp_pathmaxrxt;
-#ifdef AF_INET
+#ifdef INET
if (paddrp->spp_flags & SPP_IPV4_TOS) {
if (net->ro._l_addr.sin.sin_family == AF_INET) {
net->tos_flowlabel = paddrp->spp_ipv4_tos & 0x000000fc;
}
}
#endif
-#ifdef AF_INET6
+#ifdef INET6
if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
if (net->ro._l_addr.sin6.sin6_family == AF_INET6) {
net->tos_flowlabel = paddrp->spp_ipv6_flowlabel;
@@ -3578,11 +3123,11 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
/* start up the timer. */
sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
}
-#ifdef AF_INET
+#ifdef INET
if (paddrp->spp_flags & SPP_IPV4_TOS)
stcb->asoc.default_tos = paddrp->spp_ipv4_tos & 0x000000fc;
#endif
-#ifdef AF_INET6
+#ifdef INET6
if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL)
stcb->asoc.default_flowlabel = paddrp->spp_ipv6_flowlabel;
#endif
@@ -3605,15 +3150,6 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
} else if (paddrp->spp_flags & SPP_HB_DISABLE) {
sctp_feature_on(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
}
- if (paddrp->spp_flags & SPP_SACKDELAY_ENABLE) {
- if (paddrp->spp_sackdelay > SCTP_CLOCK_GRANULARITY)
- inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV] = MSEC_TO_TICKS(paddrp->spp_sackdelay);
- else
- inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV] = MSEC_TO_TICKS(SCTP_CLOCK_GRANULARITY);
-
- } else if (paddrp->spp_flags & SPP_SACKDELAY_DISABLE) {
- inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV] = 0;
- }
SCTP_INP_WUNLOCK(inp);
}
}
@@ -3627,11 +3163,11 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
if (stcb) {
/* Set in ms we hope :-) */
- if (srto->srto_initial > 10)
+ if (srto->srto_initial)
stcb->asoc.initial_rto = srto->srto_initial;
- if (srto->srto_max > 10)
+ if (srto->srto_max)
stcb->asoc.maxrto = srto->srto_max;
- if (srto->srto_min > 10)
+ if (srto->srto_min)
stcb->asoc.minrto = srto->srto_min;
SCTP_TCB_UNLOCK(stcb);
} else {
@@ -3640,11 +3176,11 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
* If we have a null asoc, its default for
* the endpoint
*/
- if (srto->srto_initial > 10)
+ if (srto->srto_initial)
inp->sctp_ep.initial_rto = srto->srto_initial;
- if (srto->srto_max > 10)
+ if (srto->srto_max)
inp->sctp_ep.sctp_maxrto = srto->srto_max;
- if (srto->srto_min > 10)
+ if (srto->srto_min)
inp->sctp_ep.sctp_minrto = srto->srto_min;
SCTP_INP_WUNLOCK(inp);
}
@@ -3665,6 +3201,10 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
sasoc->sasoc_local_rwnd = 0;
if (stcb->asoc.cookie_life)
stcb->asoc.cookie_life = sasoc->sasoc_cookie_life;
+ stcb->asoc.delayed_ack = sasoc->sasoc_sack_delay;
+ if (sasoc->sasoc_sack_freq) {
+ stcb->asoc.sack_freq = sasoc->sasoc_sack_freq;
+ }
SCTP_TCB_UNLOCK(stcb);
} else {
SCTP_INP_WLOCK(inp);
@@ -3675,6 +3215,10 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
sasoc->sasoc_local_rwnd = 0;
if (sasoc->sasoc_cookie_life)
inp->sctp_ep.def_cookie_life = sasoc->sasoc_cookie_life;
+ inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV] = MSEC_TO_TICKS(sasoc->sasoc_sack_delay);
+ if (sasoc->sasoc_sack_freq) {
+ inp->sctp_ep.sctp_sack_freq = sasoc->sasoc_sack_freq;
+ }
SCTP_INP_WUNLOCK(inp);
}
}
@@ -3694,12 +3238,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
if (sinit->sinit_max_attempts)
inp->sctp_ep.max_init_times = sinit->sinit_max_attempts;
- if (sinit->sinit_max_init_timeo > 10)
- /*
- * We must be at least a 100ms (we set in
- * ticks)
- */
- /* FIXME MT: What is this? */
+ if (sinit->sinit_max_init_timeo)
inp->sctp_ep.initial_init_rto_max = sinit->sinit_max_init_timeo;
SCTP_INP_WUNLOCK(inp);
}
@@ -3752,7 +3291,21 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
}
break;
+ case SCTP_SET_DYNAMIC_PRIMARY:
+ {
+ union sctp_sockstore *ss;
+
+ error = priv_check_cred(curthread->td_ucred,
+ PRIV_NETINET_RESERVEDPORT,
+ SUSER_ALLOWJAIL);
+ if (error)
+ break;
+ SCTP_CHECK_AND_CAST(ss, optval, union sctp_sockstore, optsize);
+ /* SUPER USER CHECK? */
+ error = sctp_dynamic_set_primary(&ss->sa, vrf_id);
+ }
+ break;
case SCTP_SET_PEER_PRIMARY_ADDR:
{
struct sctp_setpeerprim *sspp;
@@ -3783,6 +3336,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
error = EINVAL;
break;
}
+ /* Is the VRF one we have */
addr_touse = addrs->addr;
if (addrs->addr->sa_family == AF_INET6) {
struct sockaddr_in6 *sin6;
@@ -3812,7 +3366,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
struct sctp_inpcb *lep;
((struct sockaddr_in *)addr_touse)->sin_port = inp->sctp_lport;
- lep = sctp_pcb_findep(addr_touse, 1, 0);
+ lep = sctp_pcb_findep(addr_touse, 1, 0, vrf_id);
if (lep != NULL) {
/*
* We must decrement the refcount
@@ -3828,7 +3382,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
} else if (lep == NULL) {
((struct sockaddr_in *)addr_touse)->sin_port = 0;
error = sctp_addr_mgmt_ep_sa(inp, addr_touse,
- SCTP_ADD_IP_ADDRESS);
+ SCTP_ADD_IP_ADDRESS, vrf_id);
} else {
error = EADDRNOTAVAIL;
}
@@ -3873,7 +3427,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
if (addrs->sget_assoc_id == 0) {
/* delete the address */
sctp_addr_mgmt_ep_sa(inp, addr_touse,
- SCTP_DEL_IP_ADDRESS);
+ SCTP_DEL_IP_ADDRESS, vrf_id);
} else {
/*
* FIX: decide whether we allow assoc based
@@ -3890,9 +3444,6 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
-
-extern int sctp_chatty_mbuf;
-
int
sctp_ctloutput(struct socket *so, struct sockopt *sopt)
{
@@ -3953,6 +3504,7 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
{
int error = 0;
int create_lock_on = 0;
+ uint32_t vrf_id;
struct sctp_inpcb *inp;
struct sctp_tcb *stcb = NULL;
@@ -4020,11 +3572,12 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
error = EALREADY;
goto out_now;
}
+ vrf_id = SCTP_DEFAULT_VRFID;
/* We are GOOD to go */
- stcb = sctp_aloc_assoc(inp, addr, 1, &error, 0);
+ stcb = sctp_aloc_assoc(inp, addr, 1, &error, 0, vrf_id);
if (stcb == NULL) {
/* Gak! no memory */
- return (error);
+ goto out_now;
}
if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
@@ -4205,7 +3758,7 @@ int
sctp_ingetaddr(struct socket *so, struct sockaddr **addr)
{
struct sockaddr_in *sin;
-
+ uint32_t vrf_id;
struct sctp_inpcb *inp;
/*
@@ -4220,6 +3773,8 @@ sctp_ingetaddr(struct socket *so, struct sockaddr **addr)
return ECONNRESET;
}
SCTP_INP_RLOCK(inp);
+ struct sctp_ifa *sctp_ifa;
+
sin->sin_port = inp->sctp_lport;
if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
@@ -4251,8 +3806,16 @@ sctp_ingetaddr(struct socket *so, struct sockaddr **addr)
SCTP_TCB_UNLOCK(stcb);
goto notConn;
}
- sin->sin_addr = sctp_ipv4_source_address_selection(inp,
- stcb, (struct route *)&net->ro, net, 0);
+ vrf_id = SCTP_DEFAULT_VRFID;
+
+ sctp_ifa = sctp_source_address_selection(inp,
+ stcb,
+ (struct route *)&net->ro,
+ net, 0, vrf_id);
+ if (sctp_ifa) {
+ sin->sin_addr = sctp_ifa->address.sin.sin_addr;
+ sctp_free_ifa(sctp_ifa);
+ }
SCTP_TCB_UNLOCK(stcb);
} else {
/* For the bound all case you get back 0 */
@@ -4266,10 +3829,10 @@ sctp_ingetaddr(struct socket *so, struct sockaddr **addr)
int fnd = 0;
LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
- if (laddr->ifa->ifa_addr->sa_family == AF_INET) {
+ if (laddr->ifa->address.sa.sa_family == AF_INET) {
struct sockaddr_in *sin_a;
- sin_a = (struct sockaddr_in *)laddr->ifa->ifa_addr;
+ sin_a = (struct sockaddr_in *)&laddr->ifa->address.sa;
sin->sin_addr = sin_a->sin_addr;
fnd = 1;
break;
@@ -4290,14 +3853,12 @@ int
sctp_peeraddr(struct socket *so, struct sockaddr **addr)
{
struct sockaddr_in *sin = (struct sockaddr_in *)*addr;
-
int fnd;
struct sockaddr_in *sin_a;
struct sctp_inpcb *inp;
struct sctp_tcb *stcb;
struct sctp_nets *net;
-
/* Do the malloc first in case it blocks. */
inp = (struct sctp_inpcb *)so->so_pcb;
if ((inp == NULL) ||
OpenPOWER on IntegriCloud