- send call has a reference to uio->uio_resid in

the recent send code, but uio may be NULL on sendfile
  calls. Change to use sndlen variable.
- EMSGSIZE is not being returned in non-blocking mode
  and needs a small tweak to look if the msg would
  ever fit when returning EWOULDBLOCK.
- FWD-TSN has a bug in stream processing which could
  cause a panic. This is a follow on to the codenomicon
  fix.
- PDAPI level 1 and 2 do not work unless the reader
  gets his returned buffer full. Fix so we can break
  out when at level 1 or 2.
- Fix fast-handoff features to copy across properly on
  accepted sockets
- Fix sctp_peeloff() system call when no true system call
  exists to screen arguments for errors. In cases where a
  real system call exists the system call itself does this.
- Fix raddr leak in recent add-ip code change for bundled
  asconfs (even when non-bundled asconfs are received)
- Make sure ipi_addr lock is held when walking global addr
  list. Need to change this lock type to a rwlock().
- Add don't wake flag on both input and output when the
  socket is closing.
- When deleting an address verify the interface is correct
  before allowing the delete to process. This protects panda
  and unnumbered.
- Clean up old sysctl stuff and get rid of the old Open/Net
  BSD structures.
- Add a function to watch the ranges in the sysctl sets.
- When appending in the reassembly queue, validate that
  the assoc has not gone to about to be freed. If so
  (in the middle) abort out. Note this especially effects
  MAC I think due to the lock/unlock they do (or with
  LOCK testing in place).
- Netstat patch to get rid of warnings.
- Make sure that no data gets queued to inactive/unconfirmed
  destinations. This especially effect CMT but also makes a
  impact on regular SCTP as well.
- During init collision when we detect seq number out
  of sync we need to treat it like Case C and discard
  the cookie (no invarient needed here).
- Atomic access to the random store.
- When we declare a vtag good, we need to shove it
  into the time wait hash to prevent further use. When
  the tag is put into the assoc hash, we need to remove it
  from the twait hash (where it will surely be). This prevents
  duplicate tag assignments.
- Move decr-ref count to better protect sysctl out of
  data.
- ltrace error corrections in sctp6_usrreq.c
- Add hook for interface up/down to be sent to us.
- Make sysctl() exported structures independent of processor
  architecture.
- Fix route and src addr cache clearing for delete address case.
- Make sure address marked SCTP_DEL_IP_ADDRESS is never selected
  as src addr.
- in icmp handling fixed so we actually look at the icmp codes
  to figure out what to do.
- Modified mobility code.
  Reception of DELETE IP ADDRESS for a primary destination and
  SET PRIMARY for a new primary destination is used for
  retransmission trigger to the new primary destination.
  Also, in this case, destination of chunks in send_queue are
  changed to the new primary destination.
- Fix so that we disallow sending by mbuf to ever have EEOR
  mode set upon it.

Approved by:	re@freebsd.org (B Mah)
This commit is contained in:
Randall Stewart 2007-09-08 17:48:46 +00:00
parent ceaad40ae7
commit 851b7298b3
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=172091
20 changed files with 1281 additions and 668 deletions

View File

@ -479,7 +479,7 @@ __attribute__((packed));
*/
#define SCTP_MOBILITY_BASE 0x00000001
#define SCTP_MOBILITY_FASTHANDOFF 0x00000002
#define SCTP_MOBILITY_DO_FASTHANDOFF 0x00000004
#define SCTP_MOBILITY_PRIM_DELETED 0x00000004
#define SCTP_SMALLEST_PMTU 512 /* smallest pmtu allowed when disabling PMTU

View File

@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/sctputil.h>
#include <netinet/sctp_output.h>
#include <netinet/sctp_asconf.h>
#include <netinet/sctp_timer.h>
/*
* debug flags:
@ -550,6 +551,42 @@ sctp_process_asconf_set_primary(struct mbuf *m,
if (response_required) {
m_reply = sctp_asconf_success_response(aph->correlation_id);
}
/*
* Mobility adaptation. Ideally, when the reception of SET
* PRIMARY with DELETE IP ADDRESS of the previous primary
* destination, unacknowledged DATA are retransmitted
* immediately to the new primary destination for seamless
* handover. If the destination is UNCONFIRMED and marked
* to REQ_PRIM, The retransmission occur when reception of
* the HEARTBEAT-ACK. (See sctp_handle_heartbeat_ack in
* sctp_input.c) Also, when change of the primary
* destination, it is better that all subsequent new DATA
* containing already queued DATA are transmitted to the new
* primary destination. (by micchie)
*/
if ((sctp_is_mobility_feature_on(stcb->sctp_ep,
SCTP_MOBILITY_BASE) ||
sctp_is_mobility_feature_on(stcb->sctp_ep,
SCTP_MOBILITY_FASTHANDOFF)) &&
sctp_is_mobility_feature_on(stcb->sctp_ep,
SCTP_MOBILITY_PRIM_DELETED) &&
(stcb->asoc.primary_destination->dest_state &
SCTP_ADDR_UNCONFIRMED) == 0) {
sctp_timer_stop(SCTP_TIMER_TYPE_PRIM_DELETED, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_TIMER + SCTP_LOC_7);
if (sctp_is_mobility_feature_on(stcb->sctp_ep,
SCTP_MOBILITY_FASTHANDOFF)) {
sctp_assoc_immediate_retrans(stcb,
stcb->asoc.primary_destination);
}
if (sctp_is_mobility_feature_on(stcb->sctp_ep,
SCTP_MOBILITY_BASE)) {
sctp_move_chunks_from_deleted_prim(stcb,
stcb->asoc.primary_destination);
}
sctp_delete_prim_timer(stcb->sctp_ep, stcb,
stcb->asoc.deleted_primary);
}
} else {
/* couldn't set the requested primary address! */
SCTPDBG(SCTP_DEBUG_ASCONF1,
@ -940,26 +977,138 @@ sctp_asconf_nets_cleanup(struct sctp_tcb *stcb, struct sctp_ifn *ifn)
}
}
void
sctp_move_chunks_from_deleted_prim(struct sctp_tcb *stcb, struct sctp_nets *dst)
{
struct sctp_association *asoc;
struct sctp_stream_out *outs;
struct sctp_tmit_chunk *chk;
struct sctp_stream_queue_pending *sp;
if (dst->dest_state & SCTP_ADDR_UNCONFIRMED) {
SCTPDBG(SCTP_DEBUG_ASCONF1, "move_chunks_from_deleted_prim: specified destination is UNCONFIRMED\n");
return;
}
if (stcb->asoc.deleted_primary == NULL) {
SCTPDBG(SCTP_DEBUG_ASCONF1, "move_chunks_from_deleted_prim: Funny, old primary is not stored\n");
return;
}
asoc = &stcb->asoc;
/*
* now through all the streams checking for chunks sent to our bad
* network.
*/
TAILQ_FOREACH(outs, &asoc->out_wheel, next_spoke) {
/* now clean up any chunks here */
TAILQ_FOREACH(sp, &outs->outqueue, next) {
if (sp->net == asoc->deleted_primary) {
sctp_free_remote_addr(sp->net);
sp->net = dst;
atomic_add_int(&dst->ref_count, 1);
}
}
}
/* Now check the pending queue */
TAILQ_FOREACH(chk, &asoc->send_queue, sctp_next) {
if (chk->whoTo == asoc->deleted_primary) {
sctp_free_remote_addr(chk->whoTo);
chk->whoTo = dst;
atomic_add_int(&dst->ref_count, 1);
}
}
}
extern int cur_oerr;
void
sctp_assoc_immediate_retrans(struct sctp_tcb *stcb, struct sctp_nets *dstnet)
{
int error;
struct sctp_tmit_chunk *chk;
//for debug
if (dstnet->dest_state & SCTP_ADDR_UNCONFIRMED) {
SCTPDBG(SCTP_DEBUG_ASCONF1, "assoc_immediate_retrans: specified destination is UNCONFIRMED\n");
return;
}
if (stcb->asoc.deleted_primary == NULL) {
SCTPDBG(SCTP_DEBUG_ASCONF1, "assoc_immediate_retrans: Funny, old primary is not stored\n");
return;
}
if (!TAILQ_EMPTY(&stcb->asoc.sent_queue)) {
SCTPDBG(SCTP_DEBUG_ASCONF1, "Deleted primary is ");
SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &stcb->asoc.deleted_primary->ro._l_addr.sa);
SCTPDBG(SCTP_DEBUG_ASCONF1, "Current Primary is ");
SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &stcb->asoc.primary_destination->ro._l_addr.sa);
SCTPDBG(SCTP_DEBUG_ASCONF1, "Stopping send timer and calling t3rxt_timer\n");
sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb,
stcb->asoc.deleted_primary,
SCTP_FROM_SCTP_TIMER + SCTP_LOC_8);
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);
cur_oerr = stcb->asoc.overall_error_count;
error = sctp_t3rxt_timer(stcb->sctp_ep, stcb,
stcb->asoc.deleted_primary);
if (error) {
SCTPDBG(SCTP_DEBUG_ASCONF1, "t3rxt_timer error\n");
SCTP_INP_DECR_REF(stcb->sctp_ep);
return;
}
SCTP_TCB_LOCK_ASSERT(stcb);
#ifdef SCTP_AUDITING_ENABLED
sctp_auditing(4, stcb->sctp_ep, stcb->asoc.deleted_primary);
#endif
/* Debug code */
SCTPDBG(SCTP_DEBUG_ASCONF1, "assoc_immediate_retrans: calling chunk_output, retran_cnt is %d\n", stcb->asoc.sent_queue_retran_cnt);
TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
SCTPDBG(SCTP_DEBUG_ASCONF1, "assoc_immediate_retrans: chk->whoTo is ");
SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &chk->whoTo->ro._l_addr.sa);
SCTPDBG(SCTP_DEBUG_ASCONF1, "state is %d\n", chk->sent);
}
/* end Debug code */
sctp_chunk_output(stcb->sctp_ep, 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;
chk = TAILQ_FIRST(&stcb->asoc.sent_queue);
sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
stcb, chk->whoTo);
}
}
return;
}
static int
sctp_asconf_queue_mgmt(struct sctp_tcb *, struct sctp_ifa *, uint16_t);
static void
void
sctp_net_immediate_retrans(struct sctp_tcb *stcb, struct sctp_nets *net)
{
struct sctp_tmit_chunk *chk;
int cnt = 0; /* debug */
SCTPDBG(SCTP_DEBUG_ASCONF2, "net_immediate_retrans()\n");
SCTPDBG(SCTP_DEBUG_ASCONF2, "RTO is %d\n", net->RTO);
SCTPDBG(SCTP_DEBUG_ASCONF1, "net_immediate_retrans:\n");
SCTPDBG(SCTP_DEBUG_ASCONF1, "RTO is %d\n", net->RTO);
sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net,
SCTP_FROM_SCTP_TIMER + SCTP_LOC_5);
stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
net->error_count = 0;
TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
if (chk->whoTo == net) {
chk->sent = SCTP_DATAGRAM_RESEND;
sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
if (chk->sent < SCTP_DATAGRAM_RESEND) {
chk->sent = SCTP_DATAGRAM_RESEND;
sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
cnt++;
}
}
}
SCTPDBG(SCTP_DEBUG_ASCONF1, "%d chunks are marked to RESEND, retran_cnt is %d\n", cnt, stcb->asoc.sent_queue_retran_cnt);
}
static void
@ -1365,7 +1514,7 @@ sctp_asconf_queue_add_sa(struct sctp_tcb *stcb, struct sockaddr *sa,
vrf_id = SCTP_DEFAULT_VRFID;
}
ifa = sctp_find_ifa_by_addr(sa, vrf_id, 0);
ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED);
if (ifa == NULL) {
/* Invalid address */
return (-1);
@ -2061,8 +2210,7 @@ sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
sctp_rtentry_t *rt;
/* delete this address if cached */
if (net->ro._s_addr &&
(net->ro._s_addr->ifa == ifa)) {
if (net->ro._s_addr == ifa) {
sctp_free_ifa(net->ro._s_addr);
net->ro._s_addr = NULL;
net->src_addr_selected = 0;
@ -2223,8 +2371,10 @@ sctp_find_valid_localaddr(struct sctp_tcb *stcb)
struct sctp_ifn *sctp_ifn;
struct sctp_ifa *sctp_ifa;
SCTP_IPI_ADDR_LOCK();
vrf = sctp_find_vrf(stcb->asoc.vrf_id);
if (vrf == NULL) {
SCTP_IPI_ADDR_UNLOCK();
return (NULL);
}
LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
@ -2250,6 +2400,7 @@ sctp_find_valid_localaddr(struct sctp_tcb *stcb)
if (sctp_is_addr_restricted(stcb, sctp_ifa))
continue;
/* found a valid local v4 address to use */
SCTP_IPI_ADDR_UNLOCK();
return (&sctp_ifa->address.sa);
} else if (sctp_ifa->address.sa.sa_family == AF_INET6 &&
stcb->asoc.ipv6_addr_legal) {
@ -2271,11 +2422,13 @@ sctp_find_valid_localaddr(struct sctp_tcb *stcb)
continue;
/* found a valid local v6 address to use */
SCTP_IPI_ADDR_UNLOCK();
return (&sctp_ifa->address.sa);
}
}
}
/* no valid addresses found */
SCTP_IPI_ADDR_UNLOCK();
return (NULL);
}
@ -2566,7 +2719,7 @@ sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m,
vrf_id = SCTP_DEFAULT_VRFID;
}
sctp_ifa = sctp_find_ifa_by_addr(sa, vrf_id, 0);
sctp_ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED);
if (sctp_ifa == NULL) {
/* address doesn't exist anymore */
int status;
@ -2773,8 +2926,10 @@ sctp_check_address_list_all(struct sctp_tcb *stcb, struct mbuf *m, int offset,
} else {
return;
}
SCTP_IPI_ADDR_LOCK();
vrf = sctp_find_vrf(vrf_id);
if (vrf == NULL) {
SCTP_IPI_ADDR_UNLOCK();
return;
}
/* go through all our known interfaces */
@ -2798,6 +2953,7 @@ sctp_check_address_list_all(struct sctp_tcb *stcb, struct mbuf *m, int offset,
}
} /* end foreach ifa */
} /* end foreach ifn */
SCTP_IPI_ADDR_UNLOCK();
}
/*
@ -2850,10 +3006,10 @@ sctp_addr_mgmt_ep_sa(struct sctp_inpcb *inp, struct sockaddr *sa,
ifa = sctp_ifap;
} else if (type == SCTP_ADD_IP_ADDRESS) {
/* For an add the address MUST be on the system */
ifa = sctp_find_ifa_by_addr(sa, vrf_id, 0);
ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED);
} else if (type == SCTP_DEL_IP_ADDRESS) {
/* For a delete we need to find it in the inp */
ifa = sctp_find_ifa_in_ep(inp, sa, 0);
ifa = sctp_find_ifa_in_ep(inp, sa, SCTP_ADDR_NOT_LOCKED);
} else {
ifa = NULL;
}

View File

@ -79,6 +79,13 @@ extern void
sctp_check_address_list(struct sctp_tcb *, struct mbuf *, int, int,
struct sockaddr *, uint16_t, uint16_t, uint16_t, uint16_t);
extern void
sctp_move_chunks_from_deleted_prim(struct sctp_tcb *, struct sctp_nets *);
extern void
sctp_assoc_immediate_retrans(struct sctp_tcb *, struct sctp_nets *);
extern void
sctp_net_immediate_retrans(struct sctp_tcb *, struct sctp_nets *);
#endif /* _KERNEL */
#endif /* !_NETINET_SCTP_ASCONF_H_ */

View File

@ -167,6 +167,7 @@ sctp_is_desired_interface_type(struct ifaddr *ifa)
case IFT_ISDNBASIC:
case IFT_ISDNPRIMARY:
case IFT_PTPSERIAL:
case IFT_OTHER:
case IFT_PPP:
case IFT_LOOP:
case IFT_SLIP:
@ -323,7 +324,10 @@ sctp_addr_change(struct ifaddr *ifa, int cmd)
(void *)ifa, ifa->ifa_addr, ifa_flags, 1);
} else if (cmd == RTM_DELETE) {
sctp_del_addr_from_vrf(SCTP_DEFAULT_VRFID, ifa->ifa_addr, ifa->ifa_ifp->if_index);
sctp_del_addr_from_vrf(SCTP_DEFAULT_VRFID, ifa->ifa_addr,
ifa->ifa_ifp->if_index,
ifa->ifa_ifp->if_xname
);
/*
* We don't bump refcount here so when it completes the
* final delete will happen.

View File

@ -471,11 +471,12 @@ __FBSDID("$FreeBSD$");
#define SCTP_NOTIFY_DATAGRAM_SENT 0x0002
#define SCTP_FAILED_THRESHOLD 0x0004
#define SCTP_HEARTBEAT_SUCCESS 0x0008
#define SCTP_RESPONSE_TO_USER_REQ 0x000f
#define SCTP_INTERNAL_ERROR 0x0010
#define SCTP_SHUTDOWN_GUARD_EXPIRES 0x0020
#define SCTP_RECEIVED_SACK 0x0040
#define SCTP_PEER_FAULTY 0x0080
#define SCTP_RESPONSE_TO_USER_REQ 0x0010
#define SCTP_INTERNAL_ERROR 0x0020
#define SCTP_SHUTDOWN_GUARD_EXPIRES 0x0040
#define SCTP_RECEIVED_SACK 0x0080
#define SCTP_PEER_FAULTY 0x0100
#define SCTP_ICMP_REFUSED 0x0200
/* bits for TOS field */
#define SCTP_ECT0_BIT 0x02
@ -591,8 +592,9 @@ __FBSDID("$FreeBSD$");
#define SCTP_TIMER_TYPE_ADDR_WQ 19
#define SCTP_TIMER_TYPE_ZERO_COPY 20
#define SCTP_TIMER_TYPE_ZCOPY_SENDQ 21
#define SCTP_TIMER_TYPE_PRIM_DELETED 22
/* add new timers here - and increment LAST */
#define SCTP_TIMER_TYPE_LAST 22
#define SCTP_TIMER_TYPE_LAST 23
#define SCTP_IS_TIMER_TYPE_VALID(t) (((t) > SCTP_TIMER_TYPE_NONE) && \
((t) < SCTP_TIMER_TYPE_LAST))
@ -652,6 +654,7 @@ __FBSDID("$FreeBSD$");
*/
#define SCTP_ASOC_MAX_CHUNKS_ON_QUEUE 512
/* The conversion from time to ticks and vice versa is done by rounding
* upwards. This way we can test in the code the time to be positive and
* know that this corresponds to a positive number of ticks.
@ -1036,6 +1039,12 @@ __FBSDID("$FreeBSD$");
#define SCTP_SO_NOT_LOCKED 0
/*-
* For address locks, do we hold the lock?
*/
#define SCTP_ADDR_LOCKED 1
#define SCTP_ADDR_NOT_LOCKED 0
#define IN4_ISPRIVATE_ADDRESS(a) \
((((uint8_t *)&(a)->s_addr)[0] == 10) || \
((((uint8_t *)&(a)->s_addr)[0] == 172) && \

View File

@ -375,8 +375,10 @@ sctp_service_reassembly(struct sctp_tcb *stcb, struct sctp_association *asoc)
cntDel = stream_no = 0;
if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
(stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) ||
(stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) {
/* socket above is long gone */
/* socket above is long gone or going.. */
abandon:
asoc->fragmented_delivery_inprogress = 0;
chk = TAILQ_FIRST(&asoc->reasmqueue);
while (chk) {
@ -449,12 +451,16 @@ sctp_service_reassembly(struct sctp_tcb *stcb, struct sctp_association *asoc)
* is corrupt, or there is a EOM already on
* the mbuf chain.
*/
if ((stcb->asoc.control_pdapi == NULL) || (stcb->asoc.control_pdapi->tail_mbuf == NULL)) {
panic("This should not happen control_pdapi NULL?");
if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
goto abandon;
} else {
if ((stcb->asoc.control_pdapi == NULL) || (stcb->asoc.control_pdapi->tail_mbuf == NULL)) {
panic("This should not happen control_pdapi NULL?");
}
/* if we did not panic, it was a EOM */
panic("Bad chunking ??");
return;
}
/* if we did not panic, it was a EOM */
panic("Bad chunking ??");
return;
}
cntDel++;
}
@ -5542,7 +5548,6 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
num_str = fwd_sz / sizeof(struct sctp_strseq);
for (i = 0; i < num_str; i++) {
uint16_t st;
unsigned char *xx;
stseq = (struct sctp_strseq *)sctp_m_getptr(m, offset,
sizeof(struct sctp_strseq),
@ -5552,22 +5557,21 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
break;
}
/* Convert */
xx = (unsigned char *)&stseq[i];
st = ntohs(stseq[i].stream);
stseq[i].stream = st;
st = ntohs(stseq[i].sequence);
stseq[i].sequence = st;
st = ntohs(stseq->stream);
stseq->stream = st;
st = ntohs(stseq->sequence);
stseq->sequence = st;
/* now process */
if (stseq[i].stream >= asoc->streamincnt) {
if (stseq->stream >= asoc->streamincnt) {
/* screwed up streams, stop! */
break;
}
strm = &asoc->strmin[stseq[i].stream];
if (compare_with_wrap(stseq[i].sequence,
strm = &asoc->strmin[stseq->stream];
if (compare_with_wrap(stseq->sequence,
strm->last_sequence_delivered, MAX_SEQ)) {
/* Update the sequence number */
strm->last_sequence_delivered =
stseq[i].sequence;
stseq->sequence;
}
/* now kick the stream the new way */
sctp_kick_prsctp_reorder_queue(stcb, strm);

View File

@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/sctp_indata.h>
#include <netinet/sctp_asconf.h>
#include <netinet/sctp_bsd_addr.h>
#include <netinet/sctp_timer.h>
@ -548,6 +549,28 @@ sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp,
TAILQ_REMOVE(&stcb->asoc.nets, stcb->asoc.primary_destination, sctp_next);
TAILQ_INSERT_HEAD(&stcb->asoc.nets, stcb->asoc.primary_destination, sctp_next);
}
/* Mobility adaptation */
if ((sctp_is_mobility_feature_on(stcb->sctp_ep,
SCTP_MOBILITY_BASE) ||
sctp_is_mobility_feature_on(stcb->sctp_ep,
SCTP_MOBILITY_FASTHANDOFF)) &&
sctp_is_mobility_feature_on(stcb->sctp_ep,
SCTP_MOBILITY_PRIM_DELETED)) {
sctp_timer_stop(SCTP_TIMER_TYPE_PRIM_DELETED, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_TIMER + SCTP_LOC_7);
if (sctp_is_mobility_feature_on(stcb->sctp_ep,
SCTP_MOBILITY_FASTHANDOFF)) {
sctp_assoc_immediate_retrans(stcb,
stcb->asoc.primary_destination);
}
if (sctp_is_mobility_feature_on(stcb->sctp_ep,
SCTP_MOBILITY_BASE)) {
sctp_move_chunks_from_deleted_prim(stcb,
stcb->asoc.primary_destination);
}
sctp_delete_prim_timer(stcb->sctp_ep, stcb,
stcb->asoc.deleted_primary);
}
}
sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED,
stcb, 0, (void *)r_net, SCTP_SO_NOT_LOCKED);
@ -1255,13 +1278,24 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
* to get into the OPEN state
*/
if (ntohl(initack_cp->init.initial_tsn) != asoc->init_seq_number) {
#ifdef INVARIANTS
panic("Case D and non-match seq?");
#else
SCTP_PRINTF("Case D, seq non-match %x vs %x?\n",
ntohl(initack_cp->init.initial_tsn),
asoc->init_seq_number);
#endif
/*-
* Opps, this means that we somehow generated two vtag's
* the same. I.e. we did:
* Us Peer
* <---INIT(tag=a)------
* ----INIT-ACK(tag=t)-->
* ----INIT(tag=t)------> *1
* <---INIT-ACK(tag=a)---
* <----CE(tag=t)------------- *2
*
* At point *1 we should be generating a different
* tag t'. Which means we would throw away the CE and send
* ours instead. Basically this is case C (throw away side).
*/
if (how_indx < sizeof(asoc->cookie_how))
asoc->cookie_how[how_indx] = 17;
return (NULL);
}
switch SCTP_GET_STATE
(asoc) {
@ -2417,6 +2451,7 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
(SCTP_PCB_COPY_FLAGS & (*inp_p)->sctp_flags) |
SCTP_PCB_FLAGS_DONT_WAKE);
inp->sctp_features = (*inp_p)->sctp_features;
inp->sctp_mobility_features = (*inp_p)->sctp_mobility_features;
inp->sctp_socket = so;
inp->sctp_frag_point = (*inp_p)->sctp_frag_point;
inp->partial_delivery_point = (*inp_p)->partial_delivery_point;
@ -5101,12 +5136,9 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset,
un_sent = (stcb->asoc.total_output_queue_size - stcb->asoc.total_flight);
if (!TAILQ_EMPTY(&stcb->asoc.control_send_queue) ||
/* For retransmission to new primary destination (by micchie) */
sctp_is_mobility_feature_on(inp, SCTP_MOBILITY_DO_FASTHANDOFF) ||
((un_sent) &&
(stcb->asoc.peers_rwnd > 0 ||
(stcb->asoc.peers_rwnd <= 0 && stcb->asoc.total_flight == 0)))) {
sctp_mobility_feature_off(inp, SCTP_MOBILITY_DO_FASTHANDOFF);
SCTPDBG(SCTP_DEBUG_INPUT3, "Calling chunk OUTPUT\n");
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED);
SCTPDBG(SCTP_DEBUG_INPUT3, "chunk OUTPUT returns\n");

View File

@ -2412,6 +2412,10 @@ sctp_choose_boundspecific_inp(struct sctp_inpcb *inp,
/* address has been removed */
continue;
}
if (laddr->action == SCTP_DEL_IP_ADDRESS) {
/* address is being deleted */
continue;
}
sifa = sctp_is_ifa_addr_preferred(laddr->ifa, dest_is_loop,
dest_is_priv, fam);
if (sifa == NULL)
@ -2437,6 +2441,10 @@ sctp_choose_boundspecific_inp(struct sctp_inpcb *inp,
/* address has been removed */
continue;
}
if (laddr->action == SCTP_DEL_IP_ADDRESS) {
/* address is being deleted */
continue;
}
sifa = sctp_is_ifa_addr_acceptable(laddr->ifa, dest_is_loop,
dest_is_priv, fam);
if (sifa == NULL)
@ -2547,6 +2555,10 @@ sctp_choose_boundspecific_stcb(struct sctp_inpcb *inp,
/* address has been removed */
continue;
}
if (laddr->action == SCTP_DEL_IP_ADDRESS) {
/* address is being deleted */
continue;
}
sifa = sctp_is_ifa_addr_preferred(laddr->ifa, dest_is_loop, dest_is_priv, fam);
if (sifa == NULL)
continue;
@ -2558,7 +2570,6 @@ sctp_choose_boundspecific_stcb(struct sctp_inpcb *inp,
stcb->asoc.last_used_address = laddr;
atomic_add_int(&sifa->refcount, 1);
return (sifa);
}
if (start_at_beginning == 0) {
stcb->asoc.last_used_address = NULL;
@ -2579,6 +2590,10 @@ sctp_choose_boundspecific_stcb(struct sctp_inpcb *inp,
/* address has been removed */
continue;
}
if (laddr->action == SCTP_DEL_IP_ADDRESS) {
/* address is being deleted */
continue;
}
sifa = sctp_is_ifa_addr_acceptable(laddr->ifa, dest_is_loop,
dest_is_priv, fam);
if (sifa == NULL)
@ -3396,10 +3411,14 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
/* call the routine to select the src address */
if (net) {
if (net->ro._s_addr && (net->ro._s_addr->localifa_flags & SCTP_BEING_DELETED)) {
if (net->ro._s_addr && (net->ro._s_addr->localifa_flags & (SCTP_BEING_DELETED | SCTP_ADDR_IFA_UNUSEABLE))) {
sctp_free_ifa(net->ro._s_addr);
net->ro._s_addr = NULL;
net->src_addr_selected = 0;
if (ro->ro_rt) {
RTFREE(ro->ro_rt);
ro->ro_rt = NULL;
}
}
if (net->src_addr_selected == 0) {
if (out_of_asoc_ok) {
@ -3671,10 +3690,14 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
lsa6_tmp.sin6_len = sizeof(lsa6_tmp);
lsa6 = &lsa6_tmp;
if (net) {
if (net->ro._s_addr && net->ro._s_addr->localifa_flags & SCTP_BEING_DELETED) {
if (net->ro._s_addr && (net->ro._s_addr->localifa_flags & (SCTP_BEING_DELETED | SCTP_ADDR_IFA_UNUSEABLE))) {
sctp_free_ifa(net->ro._s_addr);
net->ro._s_addr = NULL;
net->src_addr_selected = 0;
if (ro->ro_rt) {
RTFREE(ro->ro_rt);
ro->ro_rt = NULL;
}
}
if (net->src_addr_selected == 0) {
if (out_of_asoc_ok) {
@ -4922,7 +4945,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
initackm_out->msg.init.initiate_tag = htonl(asoc->my_vtag);
initackm_out->msg.init.initial_tsn = htonl(asoc->init_seq_number);
} else {
uint32_t vtag;
uint32_t vtag, itsn;
if (asoc) {
atomic_add_int(&asoc->refcnt, 1);
@ -4930,7 +4953,8 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
vtag = sctp_select_a_tag(inp);
initackm_out->msg.init.initiate_tag = htonl(vtag);
/* get a TSN to use too */
initackm_out->msg.init.initial_tsn = htonl(sctp_select_initial_TSN(&inp->sctp_ep));
itsn = sctp_select_initial_TSN(&inp->sctp_ep);
initackm_out->msg.init.initial_tsn = htonl(itsn);
SCTP_TCB_LOCK(stcb);
atomic_add_int(&asoc->refcnt, -1);
} else {
@ -5978,7 +6002,7 @@ sctp_sendall(struct sctp_inpcb *inp, struct uio *uio, struct mbuf *m,
ca->sndlen += SCTP_BUF_LEN(m);
m = SCTP_BUF_NEXT(m);
}
ca->m = m;
ca->m = mat;
}
ret = sctp_initiate_iterator(NULL, sctp_sendall_iterator, NULL,
SCTP_PCB_ANY_FLAGS, SCTP_PCB_ANY_FEATURES,
@ -6401,6 +6425,7 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb, struct sctp_nets *net,
/* No chunk memory */
out_gu:
if (send_lock_up) {
/* sa_ignore NO_NULL_CHK */
SCTP_TCB_SEND_UNLOCK(stcb);
send_lock_up = 0;
}
@ -6972,6 +6997,14 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
net = TAILQ_FIRST(&asoc->nets);
}
/*
* JRI-TODO: CMT-MPI. Simply set the first
* destination (net) to be optimized for the next
* message to be pulled out of the outwheel. 1. peek
* at outwheel 2. If large message, set net =
* highest_cwnd 3. If small message, set net =
* lowest rtt
*/
} else {
net = asoc->primary_destination;
if (net == NULL) {
@ -6980,12 +7013,27 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
}
}
start_at = net;
one_more_time:
for (; net != NULL; net = TAILQ_NEXT(net, sctp_next)) {
net->window_probe = 0;
if (old_startat && (old_startat == net)) {
break;
}
/*
* JRI: if dest is unreachable or unconfirmed, do
* not send data to it
*/
if ((net->dest_state & SCTP_ADDR_NOT_REACHABLE) || (net->dest_state & SCTP_ADDR_UNCONFIRMED)) {
continue;
}
/*
* JRI: if dest is in PF state, do not send data to
* it
*/
if (sctp_cmt_on_off && sctp_cmt_pf && (net->dest_state & SCTP_ADDR_PF)) {
continue;
}
if ((sctp_cmt_on_off == 0) && (net->ref_count < 2)) {
/* nothing can be in queue for this guy */
continue;
@ -6996,9 +7044,9 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
continue;
}
/*
* @@@ JRI : this for loop we are in takes in each
* net, if its's got space in cwnd and has data sent
* to it (when CMT is off) then it calls
* JRI : this for loop we are in takes in each net,
* if its's got space in cwnd and has data sent to
* it (when CMT is off) then it calls
* sctp_fill_outqueue for the net. This gets data on
* the send queue for that network.
*
@ -7026,6 +7074,7 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
}
skip_the_fill_from_streams:
*cwnd_full = cwnd_full_ind;
/* now service each destination and send out what we can for it */
/* Nothing to send? */
if ((TAILQ_FIRST(&asoc->control_send_queue) == NULL) &&
@ -8082,8 +8131,6 @@ sctp_send_asconf_ack(struct sctp_tcb *stcb)
}
latest_ack->last_sent_to = net;
atomic_add_int(&latest_ack->last_sent_to->ref_count, 1);
TAILQ_FOREACH(ack, &stcb->asoc.asconf_ack_sent, next) {
if (ack->data == NULL) {
continue;
@ -9221,6 +9268,7 @@ sctp_send_sack(struct sctp_tcb *stcb)
a_chk->data = NULL;
}
sctp_free_a_chunk(stcb, a_chk);
/* sa_ignore NO_NULL_CHK */
if (stcb->asoc.delayed_ack) {
sctp_timer_stop(SCTP_TIMER_TYPE_RECV,
stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_6);
@ -9916,6 +9964,7 @@ sctp_send_packet_dropped(struct sctp_tcb *stcb, struct sctp_nets *net,
struct sctp_chunkhdr *ch, chunk_buf;
unsigned int chk_length;
/* sa_ignore NO_NULL_CHK */
asoc = &stcb->asoc;
SCTP_TCB_LOCK_ASSERT(stcb);
if (asoc->peer_supports_pktdrop == 0) {
@ -11131,8 +11180,7 @@ sctp_lower_sosend(struct socket *so,
if ((use_rcvinfo) && (srcv) &&
((srcv->sinfo_flags & SCTP_ABORT) ||
((srcv->sinfo_flags & SCTP_EOF) &&
(uio) &&
(uio->uio_resid == 0)))) {
(sndlen == 0)))) {
/*-
* User asks to abort a non-existant assoc,
* or EOF a non-existant assoc with no data
@ -11282,7 +11330,11 @@ sctp_lower_sosend(struct socket *so,
(stcb->asoc.chunks_on_out_queue >
sctp_max_chunks_on_queue)) {
SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EWOULDBLOCK);
error = EWOULDBLOCK;
if (sndlen > SCTP_SB_LIMIT_SND(so))
error = EMSGSIZE;
else
error = EWOULDBLOCK;
atomic_add_int(&stcb->sctp_ep->total_nospaces, 1);
goto out_unlocked;
}
@ -11402,9 +11454,14 @@ sctp_lower_sosend(struct socket *so,
tot_demand = (tot_out + sizeof(struct sctp_paramhdr));
} else {
/* Must fit in a MTU */
if (uio)
tot_out = uio->uio_resid;
tot_out = sndlen;
tot_demand = (tot_out + sizeof(struct sctp_paramhdr));
if (tot_demand > SCTP_DEFAULT_ADD_MORE) {
/* To big */
SCTP_LTRACE_ERR_RET(NULL, stcb, net, SCTP_FROM_SCTP_OUTPUT, EMSGSIZE);
error = EMSGSIZE;
goto out;
}
mm = sctp_get_mbuf_for_msg(tot_demand, 0, M_WAIT, 1, MT_DATA);
}
if (mm == NULL) {
@ -11491,12 +11548,21 @@ sctp_lower_sosend(struct socket *so,
}
/* Unless E_EOR mode is on, we must make a send FIT in one call. */
if ((user_marks_eor == 0) &&
(uio->uio_resid > (int)SCTP_SB_LIMIT_SND(stcb->sctp_socket))) {
(sndlen > SCTP_SB_LIMIT_SND(stcb->sctp_socket))) {
/* It will NEVER fit */
SCTP_LTRACE_ERR_RET(NULL, stcb, net, SCTP_FROM_SCTP_OUTPUT, EMSGSIZE);
error = EMSGSIZE;
goto out_unlocked;
}
if ((uio == NULL) && user_marks_eor) {
/*-
* We do not support eeor mode for
* sending with mbuf chains (like sendfile).
*/
SCTP_LTRACE_ERR_RET(NULL, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
error = EINVAL;
goto out_unlocked;
}
if (user_marks_eor) {
local_add_more = sctp_add_more_threshold;
} else {
@ -11504,7 +11570,7 @@ sctp_lower_sosend(struct socket *so,
* For non-eeor the whole message must fit in
* the socket send buffer.
*/
local_add_more = uio->uio_resid;
local_add_more = sndlen;
}
len = 0;
if (((max_len < local_add_more) &&
@ -11517,7 +11583,7 @@ sctp_lower_sosend(struct socket *so,
if (sctp_logging_level & SCTP_BLK_LOGGING_ENABLE) {
sctp_log_block(SCTP_BLOCK_LOG_INTO_BLKA,
so, asoc, uio->uio_resid);
so, asoc, sndlen);
}
be.error = 0;
stcb->block_entry = &be;
@ -11557,7 +11623,7 @@ sctp_lower_sosend(struct socket *so,
* sndlen covers for mbuf case uio_resid covers for the non-mbuf
* case NOTE: uio will be null when top/mbuf is passed
*/
if ((sndlen == 0) || ((uio) && (uio->uio_resid == 0))) {
if (sndlen == 0) {
if (srcv->sinfo_flags & SCTP_EOF) {
got_all_of_the_send = 1;
goto dataless_eof;

View File

@ -296,6 +296,110 @@ sctp_delete_ifn(struct sctp_ifn *sctp_ifnp, int hold_addr_lock)
sctp_free_ifn(sctp_ifnp);
}
void
sctp_mark_ifa_addr_down(uint32_t vrf_id, struct sockaddr *addr, const char *if_name, uint32_t ifn_index)
{
struct sctp_vrf *vrf;
struct sctp_ifa *sctp_ifap = NULL;
SCTP_IPI_ADDR_LOCK();
vrf = sctp_find_vrf(vrf_id);
if (vrf == NULL) {
SCTPDBG(SCTP_DEBUG_PCB1, "Can't find vrf_id:%d\n", vrf_id);
goto out;
}
sctp_ifap = sctp_find_ifa_by_addr(addr, vrf->vrf_id, SCTP_ADDR_LOCKED);
if (sctp_ifap == NULL) {
SCTPDBG(SCTP_DEBUG_PCB1, "Can't find sctp_ifap for address\n");
goto out;
}
if (sctp_ifap->ifn_p == NULL) {
SCTPDBG(SCTP_DEBUG_PCB1, "IFA has no IFN - can't mark unuseable\n");
goto out;
}
if (if_name) {
int len1, len2;
len1 = strlen(if_name);
len2 = strlen(sctp_ifap->ifn_p->ifn_name);
if (len1 != len2) {
SCTPDBG(SCTP_DEBUG_PCB1, "IFN of ifa names different lenght %d vs %d - ignored\n",
len1, len2);
goto out;
}
if (strncmp(if_name, sctp_ifap->ifn_p->ifn_name, len1) != 0) {
SCTPDBG(SCTP_DEBUG_PCB1, "IFN %s of IFA not the same as %s\n",
sctp_ifap->ifn_p->ifn_name,
if_name);
goto out;
}
} else {
if (sctp_ifap->ifn_p->ifn_index != ifn_index) {
SCTPDBG(SCTP_DEBUG_PCB1, "IFA owned by ifn_index:%d down command for ifn_index:%d - ignored\n",
sctp_ifap->ifn_p->ifn_index, ifn_index);
goto out;
}
}
sctp_ifap->localifa_flags &= (~SCTP_ADDR_VALID);
sctp_ifap->localifa_flags |= SCTP_ADDR_IFA_UNUSEABLE;
out:
SCTP_IPI_ADDR_UNLOCK();
}
void
sctp_mark_ifa_addr_up(uint32_t vrf_id, struct sockaddr *addr, const char *if_name, uint32_t ifn_index)
{
struct sctp_vrf *vrf;
struct sctp_ifa *sctp_ifap = NULL;
SCTP_IPI_ADDR_LOCK();
vrf = sctp_find_vrf(vrf_id);
if (vrf == NULL) {
SCTPDBG(SCTP_DEBUG_PCB1, "Can't find vrf_id:%d\n", vrf_id);
goto out;
}
sctp_ifap = sctp_find_ifa_by_addr(addr, vrf->vrf_id, SCTP_ADDR_LOCKED);
if (sctp_ifap == NULL) {
SCTPDBG(SCTP_DEBUG_PCB1, "Can't find sctp_ifap for address\n");
goto out;
}
if (sctp_ifap->ifn_p == NULL) {
SCTPDBG(SCTP_DEBUG_PCB1, "IFA has no IFN - can't mark unuseable\n");
goto out;
}
if (if_name) {
int len1, len2;
len1 = strlen(if_name);
len2 = strlen(sctp_ifap->ifn_p->ifn_name);
if (len1 != len2) {
SCTPDBG(SCTP_DEBUG_PCB1, "IFN of ifa names different lenght %d vs %d - ignored\n",
len1, len2);
goto out;
}
if (strncmp(if_name, sctp_ifap->ifn_p->ifn_name, len1) != 0) {
SCTPDBG(SCTP_DEBUG_PCB1, "IFN %s of IFA not the same as %s\n",
sctp_ifap->ifn_p->ifn_name,
if_name);
goto out;
}
} else {
if (sctp_ifap->ifn_p->ifn_index != ifn_index) {
SCTPDBG(SCTP_DEBUG_PCB1, "IFA owned by ifn_index:%d down command for ifn_index:%d - ignored\n",
sctp_ifap->ifn_p->ifn_index, ifn_index);
goto out;
}
}
sctp_ifap->localifa_flags &= (~SCTP_ADDR_IFA_UNUSEABLE);
sctp_ifap->localifa_flags |= SCTP_ADDR_VALID;
out:
SCTP_IPI_ADDR_UNLOCK();
}
struct sctp_ifa *
sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index,
@ -361,7 +465,7 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index,
atomic_add_int(&sctppcbinfo.ipi_count_ifns, 1);
new_ifn_af = 1;
}
sctp_ifap = sctp_find_ifa_by_addr(addr, vrf->vrf_id, 1);
sctp_ifap = sctp_find_ifa_by_addr(addr, vrf->vrf_id, SCTP_ADDR_LOCKED);
if (sctp_ifap) {
/* Hmm, it already exists? */
if ((sctp_ifap->ifn_p) &&
@ -384,15 +488,19 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index,
} else {
if (sctp_ifap->ifn_p) {
/*
* The first IFN gets the address,
* duplicates are ignored.
* The last IFN gets the address, old ones
* are deleted.
*/
if (new_ifn_af) {
/*
* Remove the created one that we
* don't want
*/
sctp_delete_ifn(sctp_ifnp, 1);
sctp_free_ifn(sctp_ifap->ifn_p);
if (sctp_ifap->ifn_p->refcount == 1)
sctp_delete_ifn(sctp_ifap->ifn_p, 1);
sctp_ifap->ifn_p = sctp_ifnp;
atomic_add_int(&sctp_ifap->ifn_p->refcount, 1);
}
goto exit_stage_left;
} else {
@ -488,7 +596,7 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index,
*/
SCTPDBG(SCTP_DEBUG_PCB1, "Lost and address change ???\n");
/* Opps, must decrement the count */
sctp_del_addr_from_vrf(vrf_id, addr, ifn_index);
sctp_del_addr_from_vrf(vrf_id, addr, ifn_index, if_name);
return (NULL);
}
SCTP_INCR_LADDR_COUNT();
@ -516,7 +624,7 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index,
void
sctp_del_addr_from_vrf(uint32_t vrf_id, struct sockaddr *addr,
uint32_t ifn_index)
uint32_t ifn_index, const char *if_name)
{
struct sctp_vrf *vrf;
struct sctp_ifa *sctp_ifap = NULL;
@ -528,8 +636,51 @@ sctp_del_addr_from_vrf(uint32_t vrf_id, struct sockaddr *addr,
SCTP_PRINTF("Can't find vrf_id:%d\n", vrf_id);
goto out_now;
}
sctp_ifap = sctp_find_ifa_by_addr(addr, vrf->vrf_id, 1);
sctp_ifap = sctp_find_ifa_by_addr(addr, vrf->vrf_id, SCTP_ADDR_LOCKED);
if (sctp_ifap) {
/* Validate the delete */
if (sctp_ifap->ifn_p) {
int valid = 0;
/*-
* The name has priority over the ifn_index
* if its given. We do this especially for
* panda who might recycle indexes fast.
*/
if (if_name) {
int len1, len2;
len1 = min(SCTP_IFNAMSIZ, strlen(if_name));
len2 = min(SCTP_IFNAMSIZ, strlen(sctp_ifap->ifn_p->ifn_name));
if (len1 && len2 && (len1 == len2)) {
/* we can compare them */
if (strncmp(if_name, sctp_ifap->ifn_p->ifn_name, len1) == 0) {
/*
* They match its a correct
* delete
*/
valid = 1;
}
}
}
if (!valid) {
/* last ditch check ifn_index */
if (ifn_index == sctp_ifap->ifn_p->ifn_index) {
valid = 1;
}
}
if (!valid) {
#ifdef SCTP_DEBUG
SCTPDBG(SCTP_DEBUG_PCB1, "Deleting address:");
SCTPDBG_ADDR(SCTP_DEBUG_PCB1, addr);
SCTPDBG(SCTP_DEBUG_PCB1, "ifn:%d ifname:%s does not match addresses\n",
ifn_index, ((if_name == NULL) ? "NULL" : if_name));
SCTPDBG(SCTP_DEBUG_PCB1, "ifn:%d ifname:%s - ignoring delete\n",
sctp_ifap->ifn_p->ifn_index, sctp_ifap->ifn_p->ifn_name);
#endif
return;
}
}
sctp_ifap->localifa_flags &= SCTP_ADDR_VALID;
sctp_ifap->localifa_flags |= SCTP_BEING_DELETED;
vrf->total_ifa_count--;
@ -1857,8 +2008,8 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
* unsupported socket type (RAW, etc)- in case we missed it
* in protosw
*/
SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_ep, inp);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EOPNOTSUPP);
SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_ep, inp);
return (EOPNOTSUPP);
}
if (sctp_default_frag_interleave == SCTP_FRAG_LEVEL_1) {
@ -1875,8 +2026,8 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
&inp->sctp_hashmark);
if (inp->sctp_tcbhash == NULL) {
SCTP_PRINTF("Out of SCTP-INPCB->hashinit - no resources\n");
SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_ep, inp);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOBUFS);
SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_ep, inp);
return (ENOBUFS);
}
inp->def_vrf_id = vrf_id;
@ -2086,6 +2237,7 @@ sctp_move_pcb_and_assoc(struct sctp_inpcb *old_inp, struct sctp_inpcb *new_inp,
stcb->asoc.shut_guard_timer.ep = (void *)new_inp;
stcb->asoc.autoclose_timer.ep = (void *)new_inp;
stcb->asoc.delayed_event_timer.ep = (void *)new_inp;
stcb->asoc.delete_prim_timer.ep = (void *)new_inp;
/* now what about the nets? */
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
net->pmtu_timer.ep = (void *)new_inp;
@ -2410,8 +2562,10 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
*/
if (sctp_mobility_base == 0) {
sctp_mobility_feature_off(inp, SCTP_MOBILITY_BASE);
sctp_mobility_feature_off(inp, SCTP_MOBILITY_PRIM_DELETED);
} else {
sctp_mobility_feature_on(inp, SCTP_MOBILITY_BASE);
sctp_mobility_feature_off(inp, SCTP_MOBILITY_PRIM_DELETED);
}
/*
* set the automatic mobility_fasthandoff from kernel flag
@ -2419,10 +2573,10 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
*/
if (sctp_mobility_fasthandoff == 0) {
sctp_mobility_feature_off(inp, SCTP_MOBILITY_FASTHANDOFF);
sctp_mobility_feature_off(inp, SCTP_MOBILITY_DO_FASTHANDOFF);
sctp_mobility_feature_off(inp, SCTP_MOBILITY_PRIM_DELETED);
} else {
sctp_mobility_feature_on(inp, SCTP_MOBILITY_FASTHANDOFF);
sctp_mobility_feature_off(inp, SCTP_MOBILITY_DO_FASTHANDOFF);
sctp_mobility_feature_off(inp, SCTP_MOBILITY_PRIM_DELETED);
}
} else {
/*
@ -2466,7 +2620,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
* (Panda).
*/
ifa = sctp_find_ifa_by_addr((struct sockaddr *)&store_sa,
vrf_id, 0);
vrf_id, SCTP_ADDR_NOT_LOCKED);
}
if (ifa == NULL) {
/* Can't find an interface with that address */
@ -2625,6 +2779,10 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
* via the sockets layer.
*/
inp->sctp_flags &= ~SCTP_PCB_FLAGS_CLOSE_IP;
/* socket is gone, so no more wakeups allowed */
inp->sctp_flags |= SCTP_PCB_FLAGS_DONT_WAKE;
inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEINPUT;
inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEOUTPUT;
}
sctp_timer_stop(SCTP_TIMER_TYPE_NEWCOOKIE, inp, NULL, NULL,
SCTP_FROM_SCTP_PCB + SCTP_LOC_1);
@ -3039,7 +3197,7 @@ sctp_is_address_on_local_host(struct sockaddr *addr, uint32_t vrf_id)
{
struct sctp_ifa *sctp_ifa;
sctp_ifa = sctp_find_ifa_by_addr(addr, vrf_id, 0);
sctp_ifa = sctp_find_ifa_by_addr(addr, vrf_id, SCTP_ADDR_NOT_LOCKED);
if (sctp_ifa) {
return (1);
} else {
@ -3541,6 +3699,8 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
sctppcbinfo.hashasocmark)];
/* put it in the bucket in the vtag hash of assoc's for the system */
LIST_INSERT_HEAD(head, stcb, sctp_asocs);
sctp_delete_from_timewait(stcb->asoc.my_vtag);
SCTP_INP_INFO_WUNLOCK();
if ((err = sctp_add_remote_addr(stcb, firstaddr, SCTP_DO_SETSCOPE, SCTP_ALLOC_ASOC))) {
@ -3570,6 +3730,7 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
SCTP_OS_TIMER_INIT(&asoc->shut_guard_timer.timer);
SCTP_OS_TIMER_INIT(&asoc->autoclose_timer.timer);
SCTP_OS_TIMER_INIT(&asoc->delayed_event_timer.timer);
SCTP_OS_TIMER_INIT(&asoc->delete_prim_timer.timer);
LIST_INSERT_HEAD(&inp->sctp_asoc_list, stcb, sctp_tcblist);
/* now file the port under the hash as well */
@ -3597,6 +3758,26 @@ sctp_remove_net(struct sctp_tcb *stcb, struct sctp_nets *net)
struct sctp_nets *lnet;
lnet = TAILQ_FIRST(&asoc->nets);
/*
* Mobility adaptation Ideally, if deleted destination is
* the primary, it becomes a fast retransmission trigger by
* the subsequent SET PRIMARY. (by micchie)
*/
if (sctp_is_mobility_feature_on(stcb->sctp_ep,
SCTP_MOBILITY_FASTHANDOFF)) {
SCTPDBG(SCTP_DEBUG_ASCONF1, "remove_net: primary dst is deleting\n");
if (asoc->deleted_primary != NULL) {
SCTPDBG(SCTP_DEBUG_ASCONF1, "remove_net: deleted primary may be already stored\n");
goto leave;
}
asoc->deleted_primary = net;
atomic_add_int(&net->ref_count, 1);
sctp_mobility_feature_on(stcb->sctp_ep,
SCTP_MOBILITY_PRIM_DELETED);
sctp_timer_start(SCTP_TIMER_TYPE_PRIM_DELETED,
stcb->sctp_ep, stcb, NULL);
}
leave:
/* Try to find a confirmed primary */
asoc->primary_destination = sctp_find_alternate_net(stcb, lnet, 0);
}
@ -3652,9 +3833,33 @@ sctp_del_remote_addr(struct sctp_tcb *stcb, struct sockaddr *remaddr)
return (-2);
}
void
sctp_delete_from_timewait(uint32_t tag)
{
struct sctpvtaghead *chain;
struct sctp_tagblock *twait_block;
int found = 0;
int i;
chain = &sctppcbinfo.vtag_timewait[(tag % SCTP_STACK_VTAG_HASH_SIZE)];
if (!SCTP_LIST_EMPTY(chain)) {
LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) {
for (i = 0; i < SCTP_NUMBER_IN_VTAG_BLOCK; i++) {
if (twait_block->vtag_block[i].v_tag == tag) {
twait_block->vtag_block[i].tv_sec_at_expire = 0;
twait_block->vtag_block[i].v_tag = 0;
found = 1;
break;
}
}
if (found)
break;
}
}
}
void
sctp_add_vtag_to_timewait(struct sctp_inpcb *inp, uint32_t tag, uint32_t time)
sctp_add_vtag_to_timewait(uint32_t tag, uint32_t time)
{
struct sctpvtaghead *chain;
struct sctp_tagblock *twait_block;
@ -3843,6 +4048,9 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
asoc->shut_guard_timer.self = NULL;
(void)SCTP_OS_TIMER_STOP(&asoc->delayed_event_timer.timer);
asoc->delayed_event_timer.self = NULL;
/* Mobility adaptation */
(void)SCTP_OS_TIMER_STOP(&asoc->delete_prim_timer.timer);
asoc->delete_prim_timer.self = NULL;
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
(void)SCTP_OS_TIMER_STOP(&net->fr_timer.timer);
net->fr_timer.self = NULL;
@ -3999,7 +4207,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
}
/* pull from vtag hash */
LIST_REMOVE(stcb, sctp_asocs);
sctp_add_vtag_to_timewait(inp, asoc->my_vtag, SCTP_TIME_WAIT);
sctp_add_vtag_to_timewait(asoc->my_vtag, SCTP_TIME_WAIT);
/*
* Now restop the timers to be sure - this is paranoia at is finest!
@ -4246,11 +4454,9 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
SCTP_FREE(aparam, SCTP_M_ASC_ADDR);
}
while (!TAILQ_EMPTY(&asoc->asconf_ack_sent)) {
/* sa_ignore FREED_MEMORY */
aack = TAILQ_FIRST(&asoc->asconf_ack_sent);
TAILQ_REMOVE(&asoc->asconf_ack_sent, aack, next);
if (aack->last_sent_to != NULL) {
sctp_free_remote_addr(aack->last_sent_to);
}
if (aack->data != NULL) {
sctp_m_freem(aack->data);
}
@ -4696,6 +4902,7 @@ sctp_pcb_init()
* the sctp_init() funciton.
*/
int i;
struct timeval tv;
if (sctp_pcb_initialized != 0) {
/* error I was called twice */
@ -4704,7 +4911,9 @@ sctp_pcb_init()
sctp_pcb_initialized = 1;
bzero(&sctpstat, sizeof(struct sctpstat));
(void)SCTP_GETTIME_TIMEVAL(&sctpstat.sctps_discontinuitytime);
(void)SCTP_GETTIME_TIMEVAL(&tv);
sctpstat.sctps_discontinuitytime.tv_sec = (uint32_t) tv.tv_sec;
sctpstat.sctps_discontinuitytime.tv_usec = (uint32_t) tv.tv_usec;
/* init the empty list of (All) Endpoints */
LIST_INIT(&sctppcbinfo.listhead);
@ -5542,7 +5751,15 @@ sctp_is_vtag_good(struct sctp_inpcb *inp, uint32_t tag, struct timeval *now)
}
}
}
/* Not found, ok to use the tag */
/*-
* Not found, ok to use the tag, add it to the time wait hash
* as well this will prevent two sucessive cookies from getting
* the same tag or two inits sent quickly on multi-processors.
* We only keep the tag for the life of a cookie and when we
* add this tag to the assoc hash we need to purge it from
* the t-wait hash.
*/
sctp_add_vtag_to_timewait(tag, TICKS_TO_SEC(inp->sctp_ep.def_cookie_life));
SCTP_INP_INFO_WUNLOCK();
return (1);
}

View File

@ -297,7 +297,7 @@ struct sctp_pcb {
int auto_close_time;
uint32_t initial_sequence_debug;
uint32_t adaptation_layer_indicator;
char store_at;
uint32_t store_at;
uint8_t max_burst;
char current_secret_number;
char last_secret_number;
@ -445,6 +445,18 @@ struct sctp_vrf *sctp_allocate_vrf(int vrfid);
struct sctp_vrf *sctp_find_vrf(uint32_t vrfid);
void sctp_free_vrf(struct sctp_vrf *vrf);
/*-
* Change address state, can be used if
* O/S supports telling transports about
* changes to IFA/IFN's (link layer triggers).
* If a ifn goes down, we will do src-addr-selection
* and NOT use that, as a source address. This does
* not stop the routing system from routing out
* that interface, but we won't put it as a source.
*/
void sctp_mark_ifa_addr_down(uint32_t vrf_id, struct sockaddr *addr, const char *if_name, uint32_t ifn_index);
void sctp_mark_ifa_addr_up(uint32_t vrf_id, struct sockaddr *addr, const char *if_name, uint32_t ifn_index);
struct sctp_ifa *
sctp_add_addr_to_vrf(uint32_t vrfid,
void *ifn, uint32_t ifn_index, uint32_t ifn_type,
@ -460,7 +472,7 @@ void sctp_free_ifa(struct sctp_ifa *sctp_ifap);
void
sctp_del_addr_from_vrf(uint32_t vrfid, struct sockaddr *addr,
uint32_t ifn_index);
uint32_t ifn_index, const char *if_name);
@ -516,8 +528,11 @@ sctp_aloc_assoc(struct sctp_inpcb *, struct sockaddr *,
int sctp_free_assoc(struct sctp_inpcb *, struct sctp_tcb *, int, int);
void sctp_delete_from_timewait(uint32_t);
void
sctp_add_vtag_to_timewait(struct sctp_inpcb *, uint32_t, uint32_t);
sctp_add_vtag_to_timewait(uint32_t, uint32_t);
void sctp_add_local_addr_ep(struct sctp_inpcb *, struct sctp_ifa *, uint32_t);

View File

@ -584,12 +584,15 @@ struct sctp_association {
struct sctp_timer shut_guard_timer; /* shutdown guard */
struct sctp_timer autoclose_timer; /* automatic close timer */
struct sctp_timer delayed_event_timer; /* timer for delayed events */
struct sctp_timer delete_prim_timer; /* deleting primary dst */
/* list of restricted local addresses */
struct sctpladdr sctp_restricted_addrs;
/* last local address pending deletion (waiting for an address add) */
struct sctp_ifa *asconf_addr_del_pending;
/* Deleted primary destination (used to stop timer) */
struct sctp_nets *deleted_primary;
struct sctpnetlisthead nets; /* remote address list */

View File

@ -40,86 +40,69 @@ __FBSDID("$FreeBSD$");
/*
* sysctl tunable variables
*/
uint32_t sctp_sendspace = (128 * 1024);
uint32_t sctp_recvspace = 128 * (1024 +
#ifdef INET6
sizeof(struct sockaddr_in6)
#else
sizeof(struct sockaddr_in)
#endif
);
uint32_t sctp_mbuf_threshold_count = SCTP_DEFAULT_MBUFS_IN_CHAIN;
uint32_t sctp_auto_asconf = SCTP_DEFAULT_AUTO_ASCONF;
uint32_t sctp_ecn_enable = 1;
uint32_t sctp_ecn_nonce = 0;
uint32_t sctp_strict_sacks = 0;
uint32_t sctp_no_csum_on_loopback = 1;
uint32_t sctp_strict_init = 1;
uint32_t sctp_abort_if_one_2_one_hits_limit = 0;
uint32_t sctp_strict_data_order = 0;
uint32_t sctp_sendspace = SCTPCTL_MAXDGRAM_DEFAULT;
uint32_t sctp_recvspace = SCTPCTL_RECVSPACE_DEFAULT;
uint32_t sctp_auto_asconf = SCTPCTL_AUTOASCONF_DEFAULT;
uint32_t sctp_ecn_enable = SCTPCTL_ECN_ENABLE_DEFAULT;
uint32_t sctp_ecn_nonce = SCTPCTL_ECN_NONCE_DEFAULT;
uint32_t sctp_strict_sacks = SCTPCTL_STRICT_SACKS_DEFAULT;
uint32_t sctp_no_csum_on_loopback = SCTPCTL_LOOPBACK_NOCSUM_DEFAULT;
uint32_t sctp_strict_init = SCTPCTL_STRICT_INIT_DEFAULT;
uint32_t sctp_peer_chunk_oh = SCTPCTL_PEER_CHKOH_DEFAULT;
uint32_t sctp_max_burst_default = SCTP_DEF_MAX_BURST;
uint32_t sctp_use_cwnd_based_maxburst = 1;
uint32_t sctp_do_drain = 1;
uint32_t sctp_hb_maxburst = SCTP_DEF_MAX_BURST;
uint32_t sctp_logging_level = SCTPCTL_LOGGING_LEVEL_DEFAULT;
uint32_t sctp_max_chunks_on_queue = SCTP_ASOC_MAX_CHUNKS_ON_QUEUE;
uint32_t sctp_delayed_sack_time_default = SCTP_RECV_MSEC;
uint32_t sctp_sack_freq_default = SCTP_DEFAULT_SACK_FREQ;
uint32_t sctp_heartbeat_interval_default = SCTP_HB_DEFAULT_MSEC;
uint32_t sctp_pmtu_raise_time_default = SCTP_DEF_PMTU_RAISE_SEC;
uint32_t sctp_shutdown_guard_time_default = SCTP_DEF_MAX_SHUTDOWN_SEC;
uint32_t sctp_secret_lifetime_default = SCTP_DEFAULT_SECRET_LIFE_SEC;
uint32_t sctp_rto_max_default = SCTP_RTO_UPPER_BOUND;
uint32_t sctp_rto_min_default = SCTP_RTO_LOWER_BOUND;
uint32_t sctp_rto_initial_default = SCTP_RTO_INITIAL;
uint32_t sctp_init_rto_max_default = SCTP_RTO_UPPER_BOUND;
uint32_t sctp_valid_cookie_life_default = SCTP_DEFAULT_COOKIE_LIFE;
uint32_t sctp_init_rtx_max_default = SCTP_DEF_MAX_INIT;
uint32_t sctp_assoc_rtx_max_default = SCTP_DEF_MAX_SEND;
uint32_t sctp_path_rtx_max_default = SCTP_DEF_MAX_PATH_RTX;
uint32_t sctp_nr_outgoing_streams_default = SCTP_OSTREAM_INITIAL;
uint32_t 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;
uint32_t sctp_min_split_point = SCTP_DEFAULT_SPLIT_POINT_MIN;
uint32_t sctp_pcbtblsize = SCTP_PCBHASHSIZE;
uint32_t sctp_hashtblsize = SCTP_TCBHASHSIZE;
uint32_t sctp_chunkscale = SCTP_CHUNKQUEUE_SCALE;
uint32_t sctp_cmt_on_off = 0;
uint32_t sctp_cmt_use_dac = 0;
uint32_t sctp_cmt_pf = 0;
uint32_t sctp_max_burst_default = SCTPCTL_MAXBURST_DEFAULT;
uint32_t sctp_max_chunks_on_queue = SCTPCTL_MAXCHUNKS_DEFAULT;
uint32_t sctp_hashtblsize = SCTPCTL_TCBHASHSIZE_DEFAULT;
uint32_t sctp_pcbtblsize = SCTPCTL_PCBHASHSIZE_DEFAULT;
uint32_t sctp_min_split_point = SCTPCTL_MIN_SPLIT_POINT_DEFAULT;
uint32_t sctp_chunkscale = SCTPCTL_CHUNKSCALE_DEFAULT;
uint32_t sctp_delayed_sack_time_default = SCTPCTL_DELAYED_SACK_TIME_DEFAULT;
uint32_t sctp_sack_freq_default = SCTPCTL_SACK_FREQ_DEFAULT;
uint32_t sctp_system_free_resc_limit = SCTPCTL_SYS_RESOURCE_DEFAULT;
uint32_t sctp_asoc_free_resc_limit = SCTPCTL_ASOC_RESOURCE_DEFAULT;
uint32_t sctp_heartbeat_interval_default = SCTPCTL_HEARTBEAT_INTERVAL_DEFAULT;
uint32_t sctp_pmtu_raise_time_default = SCTPCTL_PMTU_RAISE_TIME_DEFAULT;
uint32_t sctp_shutdown_guard_time_default = SCTPCTL_SHUTDOWN_GUARD_TIME_DEFAULT;
uint32_t sctp_secret_lifetime_default = SCTPCTL_SECRET_LIFETIME_DEFAULT;
uint32_t sctp_rto_max_default = SCTPCTL_RTO_MAX_DEFAULT;
uint32_t sctp_rto_min_default = SCTPCTL_RTO_MIN_DEFAULT;
uint32_t sctp_rto_initial_default = SCTPCTL_RTO_INITIAL_DEFAULT;
uint32_t sctp_init_rto_max_default = SCTPCTL_INIT_RTO_MAX_DEFAULT;
uint32_t sctp_valid_cookie_life_default = SCTPCTL_VALID_COOKIE_LIFE_DEFAULT;
uint32_t sctp_init_rtx_max_default = SCTPCTL_INIT_RTX_MAX_DEFAULT;
uint32_t sctp_assoc_rtx_max_default = SCTPCTL_ASSOC_RTX_MAX_DEFAULT;
uint32_t sctp_path_rtx_max_default = SCTPCTL_PATH_RTX_MAX_DEFAULT;
uint32_t sctp_add_more_threshold = SCTPCTL_ADD_MORE_ON_OUTPUT_DEFAULT;
uint32_t sctp_nr_outgoing_streams_default = SCTPCTL_OUTGOING_STREAMS_DEFAULT;
uint32_t sctp_cmt_on_off = SCTPCTL_CMT_ON_OFF_DEFAULT;
uint32_t sctp_cmt_use_dac = SCTPCTL_CMT_USE_DAC_DEFAULT;
uint32_t sctp_cmt_pf = SCTPCTL_CMT_PF_DEFAULT;
uint32_t sctp_use_cwnd_based_maxburst = SCTPCTL_CWND_MAXBURST_DEFAULT;
uint32_t sctp_early_fr = SCTPCTL_EARLY_FAST_RETRAN_DEFAULT;
uint32_t sctp_early_fr_msec = SCTPCTL_EARLY_FAST_RETRAN_MSEC_DEFAULT;
uint32_t sctp_asconf_auth_nochk = SCTPCTL_ASCONF_AUTH_NOCHK_DEFAULT;
uint32_t sctp_auth_disable = SCTPCTL_AUTH_DISABLE_DEFAULT;
uint32_t sctp_nat_friendly = SCTPCTL_NAT_FRIENDLY_DEFAULT;
uint32_t sctp_L2_abc_variable = SCTPCTL_ABC_L_VAR_DEFAULT;
uint32_t sctp_mbuf_threshold_count = SCTPCTL_MAX_CHAINED_MBUFS_DEFAULT;
uint32_t sctp_do_drain = SCTPCTL_DO_SCTP_DRAIN_DEFAULT;
uint32_t sctp_hb_maxburst = SCTPCTL_HB_MAX_BURST_DEFAULT;
uint32_t sctp_abort_if_one_2_one_hits_limit = SCTPCTL_ABORT_AT_LIMIT_DEFAULT;
uint32_t sctp_strict_data_order = SCTPCTL_STRICT_DATA_ORDER_DEFAULT;
uint32_t sctp_min_residual = SCTPCTL_MIN_RESIDUAL_DEFAULT;
uint32_t sctp_max_retran_chunk = SCTPCTL_MAX_RETRAN_CHUNK_DEFAULT;
uint32_t sctp_mobility_base = SCTP_DEFAULT_MOBILITY_BASE;
uint32_t sctp_mobility_fasthandoff = SCTP_DEFAULT_MOBILITY_FASTHANDOFF;
uint32_t sctp_logging_level = SCTPCTL_LOGGING_LEVEL_DEFAULT;
/* JRS - Variable for default congestion control module */
uint32_t sctp_default_cc_module = SCTPCTL_DEFAULT_CC_MODULE_DEFAULT;
uint32_t sctp_default_frag_interleave = SCTPCTL_DEFAULT_FRAG_INTERLEAVE_DEFAULT;
uint32_t sctp_L2_abc_variable = 1;
uint32_t sctp_early_fr = 0;
uint32_t sctp_early_fr_msec = SCTP_MINFR_MSEC_TIMER;
uint32_t sctp_says_check_for_deadlock = 0;
uint32_t sctp_asconf_auth_nochk = 0;
uint32_t sctp_auth_disable = 0;
uint32_t sctp_nat_friendly = 1;
uint32_t sctp_min_residual = SCTPCTL_MIN_RESIDUAL_DEFAULT;;
struct sctpstat sctpstat;
uint32_t sctp_mobility_base = SCTPCTL_MOBILITY_BASE_DEFAULT;
uint32_t sctp_mobility_fasthandoff = SCTPCTL_MOBILITY_FASTHANDOFF_DEFAULT;
#ifdef SCTP_DEBUG
uint32_t sctp_debug_on = 0;
uint32_t sctp_debug_on = SCTPCTL_DEBUG_DEFAULT;
#endif
struct sctpstat sctpstat;
/* It returns an upper limit. No filtering is done here */
@ -249,15 +232,14 @@ copy_out_local_addresses(struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct s
continue;
} else
continue;
memset((void *)&xladdr, 0, sizeof(union sctp_sockstore));
memset((void *)&xladdr, 0, sizeof(struct xsctp_laddr));
memcpy((void *)&xladdr.address, (const void *)&sctp_ifa->address, sizeof(union sctp_sockstore));
(void)SCTP_GETTIME_TIMEVAL(&xladdr.start_time);
SCTP_INP_RUNLOCK(inp);
SCTP_INP_INFO_RUNLOCK();
error = SYSCTL_OUT(req, &xladdr, sizeof(struct xsctp_laddr));
if (error)
if (error) {
return (error);
else {
} else {
SCTP_INP_INFO_RLOCK();
SCTP_INP_RLOCK(inp);
}
@ -268,30 +250,30 @@ copy_out_local_addresses(struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct s
/* ignore if blacklisted at association level */
if (stcb && sctp_is_addr_restricted(stcb, laddr->ifa))
continue;
memset((void *)&xladdr, 0, sizeof(union sctp_sockstore));
memset((void *)&xladdr, 0, sizeof(struct xsctp_laddr));
memcpy((void *)&xladdr.address, (const void *)&laddr->ifa->address, sizeof(union sctp_sockstore));
xladdr.start_time = laddr->start_time;
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)
if (error) {
return (error);
else {
} else {
SCTP_INP_INFO_RLOCK();
SCTP_INP_RLOCK(inp);
}
}
}
memset((void *)&xladdr, 0, sizeof(union sctp_sockstore));
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)
if (error) {
return (error);
else {
} else {
SCTP_INP_INFO_RLOCK();
SCTP_INP_RLOCK(inp);
return (0);
@ -362,8 +344,14 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS)
xinpcb.total_recvs = inp->total_recvs;
xinpcb.total_nospaces = inp->total_nospaces;
xinpcb.fragmentation_point = inp->sctp_frag_point;
xinpcb.qlen = inp->sctp_socket->so_qlen;
xinpcb.maxqlen = inp->sctp_socket->so_qlimit;
if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
(inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
xinpcb.qlen = 0;
xinpcb.maxqlen = 0;
} else {
xinpcb.qlen = inp->sctp_socket->so_qlen;
xinpcb.maxqlen = inp->sctp_socket->so_qlimit;
}
SCTP_INP_INCR_REF(inp);
SCTP_INP_RUNLOCK(inp);
SCTP_INP_INFO_RUNLOCK();
@ -398,9 +386,10 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS)
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 = stcb->asoc.start_time;
xstcb.discontinuity_time = stcb->asoc.discontinuity_time;
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;
@ -416,7 +405,7 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS)
error = SYSCTL_OUT(req, &xstcb, sizeof(struct xsctp_tcb));
if (error) {
SCTP_INP_DECR_REF(inp);
atomic_add_int(&stcb->asoc.refcnt, -1);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
return error;
}
SCTP_INP_INFO_RLOCK();
@ -424,7 +413,7 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS)
error = copy_out_local_addresses(inp, stcb, req);
if (error) {
SCTP_INP_DECR_REF(inp);
atomic_add_int(&stcb->asoc.refcnt, -1);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
return error;
}
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
@ -440,19 +429,20 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS)
xraddr.cwnd = net->cwnd;
xraddr.flight_size = net->flight_size;
xraddr.mtu = net->mtu;
xraddr.start_time = net->start_time;
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_add_int(&stcb->asoc.refcnt, -1);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
return error;
}
SCTP_INP_INFO_RLOCK();
SCTP_INP_RLOCK(inp);
}
atomic_add_int(&stcb->asoc.refcnt, -1);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
memset((void *)&xraddr, 0, sizeof(struct xsctp_raddr));
xraddr.last = 1;
SCTP_INP_RUNLOCK(inp);
@ -465,6 +455,7 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS)
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));
@ -474,7 +465,6 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS)
return error;
}
SCTP_INP_INFO_RLOCK();
SCTP_INP_DECR_REF(inp);
}
SCTP_INP_INFO_RUNLOCK();
@ -484,211 +474,321 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS)
return error;
}
#define RANGECHK(var, min, max) \
if ((var) < (min)) { (var) = (min); } \
else if ((var) > (max)) { (var) = (max); }
static int
sysctl_sctp_check(SYSCTL_HANDLER_ARGS)
{
int error;
error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
if (error == 0) {
RANGECHK(sctp_sendspace, SCTPCTL_MAXDGRAM_MIN, SCTPCTL_MAXDGRAM_MAX);
RANGECHK(sctp_recvspace, SCTPCTL_RECVSPACE_MIN, SCTPCTL_RECVSPACE_MAX);
#if defined(__FreeBSD__) || defined(SCTP_APPLE_AUTO_ASCONF)
RANGECHK(sctp_auto_asconf, SCTPCTL_AUTOASCONF_MIN, SCTPCTL_AUTOASCONF_MAX);
#endif
RANGECHK(sctp_ecn_enable, SCTPCTL_ECN_ENABLE_MIN, SCTPCTL_ECN_ENABLE_MAX);
RANGECHK(sctp_ecn_nonce, SCTPCTL_ECN_NONCE_MIN, SCTPCTL_ECN_NONCE_MAX);
RANGECHK(sctp_strict_sacks, SCTPCTL_STRICT_SACKS_MIN, SCTPCTL_STRICT_SACKS_MAX);
RANGECHK(sctp_no_csum_on_loopback, SCTPCTL_LOOPBACK_NOCSUM_MIN, SCTPCTL_LOOPBACK_NOCSUM_MAX);
RANGECHK(sctp_strict_init, SCTPCTL_STRICT_INIT_MIN, SCTPCTL_STRICT_INIT_MAX);
RANGECHK(sctp_peer_chunk_oh, SCTPCTL_PEER_CHKOH_MIN, SCTPCTL_PEER_CHKOH_MAX);
RANGECHK(sctp_max_burst_default, SCTPCTL_MAXBURST_MIN, SCTPCTL_MAXBURST_MAX);
RANGECHK(sctp_max_chunks_on_queue, SCTPCTL_MAXCHUNKS_MIN, SCTPCTL_MAXCHUNKS_MAX);
RANGECHK(sctp_hashtblsize, SCTPCTL_TCBHASHSIZE_MIN, SCTPCTL_TCBHASHSIZE_MAX);
RANGECHK(sctp_pcbtblsize, SCTPCTL_PCBHASHSIZE_MIN, SCTPCTL_PCBHASHSIZE_MAX);
RANGECHK(sctp_min_split_point, SCTPCTL_MIN_SPLIT_POINT_MIN, SCTPCTL_MIN_SPLIT_POINT_MAX);
RANGECHK(sctp_chunkscale, SCTPCTL_CHUNKSCALE_MIN, SCTPCTL_CHUNKSCALE_MAX);
RANGECHK(sctp_delayed_sack_time_default, SCTPCTL_DELAYED_SACK_TIME_MIN, SCTPCTL_DELAYED_SACK_TIME_MAX);
RANGECHK(sctp_sack_freq_default, SCTPCTL_SACK_FREQ_MIN, SCTPCTL_SACK_FREQ_MAX);
RANGECHK(sctp_system_free_resc_limit, SCTPCTL_SYS_RESOURCE_MIN, SCTPCTL_SYS_RESOURCE_MAX);
RANGECHK(sctp_asoc_free_resc_limit, SCTPCTL_ASOC_RESOURCE_MIN, SCTPCTL_ASOC_RESOURCE_MAX);
RANGECHK(sctp_heartbeat_interval_default, SCTPCTL_HEARTBEAT_INTERVAL_MIN, SCTPCTL_HEARTBEAT_INTERVAL_MAX);
RANGECHK(sctp_pmtu_raise_time_default, SCTPCTL_PMTU_RAISE_TIME_MIN, SCTPCTL_PMTU_RAISE_TIME_MAX);
RANGECHK(sctp_shutdown_guard_time_default, SCTPCTL_SHUTDOWN_GUARD_TIME_MIN, SCTPCTL_SHUTDOWN_GUARD_TIME_MAX);
RANGECHK(sctp_secret_lifetime_default, SCTPCTL_SECRET_LIFETIME_MIN, SCTPCTL_SECRET_LIFETIME_MAX);
RANGECHK(sctp_rto_max_default, SCTPCTL_RTO_MAX_MIN, SCTPCTL_RTO_MAX_MAX);
RANGECHK(sctp_rto_min_default, SCTPCTL_RTO_MIN_MIN, SCTPCTL_RTO_MIN_MAX);
RANGECHK(sctp_rto_initial_default, SCTPCTL_RTO_INITIAL_MIN, SCTPCTL_RTO_INITIAL_MAX);
RANGECHK(sctp_init_rto_max_default, SCTPCTL_INIT_RTO_MAX_MIN, SCTPCTL_INIT_RTO_MAX_MAX);
RANGECHK(sctp_valid_cookie_life_default, SCTPCTL_VALID_COOKIE_LIFE_MIN, SCTPCTL_VALID_COOKIE_LIFE_MAX);
RANGECHK(sctp_init_rtx_max_default, SCTPCTL_INIT_RTX_MAX_MIN, SCTPCTL_INIT_RTX_MAX_MAX);
RANGECHK(sctp_assoc_rtx_max_default, SCTPCTL_ASSOC_RTX_MAX_MIN, SCTPCTL_ASSOC_RTX_MAX_MAX);
RANGECHK(sctp_path_rtx_max_default, SCTPCTL_PATH_RTX_MAX_MIN, SCTPCTL_PATH_RTX_MAX_MAX);
RANGECHK(sctp_add_more_threshold, SCTPCTL_ADD_MORE_ON_OUTPUT_MIN, SCTPCTL_ADD_MORE_ON_OUTPUT_MAX);
RANGECHK(sctp_nr_outgoing_streams_default, SCTPCTL_OUTGOING_STREAMS_MIN, SCTPCTL_OUTGOING_STREAMS_MAX);
RANGECHK(sctp_cmt_on_off, SCTPCTL_CMT_ON_OFF_MIN, SCTPCTL_CMT_ON_OFF_MAX);
RANGECHK(sctp_cmt_use_dac, SCTPCTL_CMT_USE_DAC_MIN, SCTPCTL_CMT_USE_DAC_MAX);
RANGECHK(sctp_cmt_pf, SCTPCTL_CMT_PF_MIN, SCTPCTL_CMT_PF_MAX);
RANGECHK(sctp_use_cwnd_based_maxburst, SCTPCTL_CWND_MAXBURST_MIN, SCTPCTL_CWND_MAXBURST_MAX);
RANGECHK(sctp_early_fr, SCTPCTL_EARLY_FAST_RETRAN_MIN, SCTPCTL_EARLY_FAST_RETRAN_MAX);
RANGECHK(sctp_early_fr_msec, SCTPCTL_EARLY_FAST_RETRAN_MSEC_MIN, SCTPCTL_EARLY_FAST_RETRAN_MSEC_MAX);
RANGECHK(sctp_asconf_auth_nochk, SCTPCTL_ASCONF_AUTH_NOCHK_MIN, SCTPCTL_ASCONF_AUTH_NOCHK_MAX);
RANGECHK(sctp_auth_disable, SCTPCTL_AUTH_DISABLE_MIN, SCTPCTL_AUTH_DISABLE_MAX);
RANGECHK(sctp_nat_friendly, SCTPCTL_NAT_FRIENDLY_MIN, SCTPCTL_NAT_FRIENDLY_MAX);
RANGECHK(sctp_L2_abc_variable, SCTPCTL_ABC_L_VAR_MIN, SCTPCTL_ABC_L_VAR_MAX);
RANGECHK(sctp_mbuf_threshold_count, SCTPCTL_MAX_CHAINED_MBUFS_MIN, SCTPCTL_MAX_CHAINED_MBUFS_MAX);
RANGECHK(sctp_do_drain, SCTPCTL_DO_SCTP_DRAIN_MIN, SCTPCTL_DO_SCTP_DRAIN_MAX);
RANGECHK(sctp_hb_maxburst, SCTPCTL_HB_MAX_BURST_MIN, SCTPCTL_HB_MAX_BURST_MAX);
RANGECHK(sctp_abort_if_one_2_one_hits_limit, SCTPCTL_ABORT_AT_LIMIT_MIN, SCTPCTL_ABORT_AT_LIMIT_MAX);
RANGECHK(sctp_strict_data_order, SCTPCTL_STRICT_DATA_ORDER_MIN, SCTPCTL_STRICT_DATA_ORDER_MAX);
RANGECHK(sctp_min_residual, SCTPCTL_MIN_RESIDUAL_MIN, SCTPCTL_MIN_RESIDUAL_MAX);
RANGECHK(sctp_max_retran_chunk, SCTPCTL_MAX_RETRAN_CHUNK_MIN, SCTPCTL_MAX_RETRAN_CHUNK_MAX);
RANGECHK(sctp_logging_level, SCTPCTL_LOGGING_LEVEL_MIN, SCTPCTL_LOGGING_LEVEL_MAX);
RANGECHK(sctp_default_cc_module, SCTPCTL_DEFAULT_CC_MODULE_MIN, SCTPCTL_DEFAULT_CC_MODULE_MAX);
RANGECHK(sctp_default_frag_interleave, SCTPCTL_DEFAULT_FRAG_INTERLEAVE_MIN, SCTPCTL_DEFAULT_FRAG_INTERLEAVE_MAX);
#if defined(__FreeBSD__) || defined(SCTP_APPLE_MOBILITY_BASE)
RANGECHK(sctp_mobility_base, SCTPCTL_MOBILITY_BASE_MIN, SCTPCTL_MOBILITY_BASE_MAX);
#endif
#if defined(__FreeBSD__) || defined(SCTP_APPLE_MOBILITY_FASTHANDOFF)
RANGECHK(sctp_mobility_fasthandoff, SCTPCTL_MOBILITY_FASTHANDOFF_MIN, SCTPCTL_MOBILITY_FASTHANDOFF_MAX);
#endif
#ifdef SCTP_DEBUG
RANGECHK(sctp_debug_on, SCTPCTL_DEBUG_MIN, SCTPCTL_DEBUG_MAX);
#endif
}
return (error);
}
/*
* sysctl definitions
*/
SYSCTL_INT(_net_inet_sctp, OID_AUTO, sendspace, CTLFLAG_RW,
&sctp_sendspace, 0, "Maximum outgoing SCTP buffer size");
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, sendspace, CTLTYPE_INT | CTLFLAG_RW,
&sctp_sendspace, 0, sysctl_sctp_check, "IU",
SCTPCTL_MAXDGRAM_DESC);
SYSCTL_INT(_net_inet_sctp, OID_AUTO, recvspace, CTLFLAG_RW,
&sctp_recvspace, 0, "Maximum incoming SCTP buffer size");
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, recvspace, CTLTYPE_INT | CTLFLAG_RW,
&sctp_recvspace, 0, sysctl_sctp_check, "IU",
SCTPCTL_RECVSPACE_DESC);
#if defined(__FreeBSD__) || defined(SCTP_APPLE_AUTO_ASCONF)
SYSCTL_INT(_net_inet_sctp, OID_AUTO, auto_asconf, CTLFLAG_RW,
&sctp_auto_asconf, 0, "Enable SCTP Auto-ASCONF");
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, auto_asconf, CTLTYPE_INT | CTLFLAG_RW,
&sctp_auto_asconf, 0, sysctl_sctp_check, "IU",
SCTPCTL_AUTOASCONF_DESC);
#endif
SYSCTL_INT(_net_inet_sctp, OID_AUTO, ecn_enable, CTLFLAG_RW,
&sctp_ecn_enable, 0, "Enable SCTP ECN");
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, ecn_enable, CTLTYPE_INT | CTLFLAG_RW,
&sctp_ecn_enable, 0, sysctl_sctp_check, "IU",
SCTPCTL_ECN_ENABLE_DESC);
SYSCTL_INT(_net_inet_sctp, OID_AUTO, ecn_nonce, CTLFLAG_RW,
&sctp_ecn_nonce, 0, "Enable SCTP ECN Nonce");
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, ecn_nonce, CTLTYPE_INT | CTLFLAG_RW,
&sctp_ecn_nonce, 0, sysctl_sctp_check, "IU",
SCTPCTL_ECN_NONCE_DESC);
SYSCTL_INT(_net_inet_sctp, OID_AUTO, strict_sacks, CTLFLAG_RW,
&sctp_strict_sacks, 0, "Enable SCTP Strict SACK checking");
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, strict_sacks, CTLTYPE_INT | CTLFLAG_RW,
&sctp_strict_sacks, 0, sysctl_sctp_check, "IU",
SCTPCTL_STRICT_SACKS_DESC);
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_PROC(_net_inet_sctp, OID_AUTO, loopback_nocsum, CTLTYPE_INT | CTLFLAG_RW,
&sctp_no_csum_on_loopback, 0, sysctl_sctp_check, "IU",
SCTPCTL_LOOPBACK_NOCSUM_DESC);
SYSCTL_INT(_net_inet_sctp, OID_AUTO, strict_init, CTLFLAG_RW,
&sctp_strict_init, 0,
"Enable strict INIT/INIT-ACK singleton enforcement");
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, strict_init, CTLTYPE_INT | CTLFLAG_RW,
&sctp_strict_init, 0, sysctl_sctp_check, "IU",
SCTPCTL_STRICT_INIT_DESC);
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_PROC(_net_inet_sctp, OID_AUTO, peer_chkoh, CTLTYPE_INT | CTLFLAG_RW,
&sctp_peer_chunk_oh, 0, sysctl_sctp_check, "IU",
SCTPCTL_PEER_CHKOH_DESC);
SYSCTL_INT(_net_inet_sctp, OID_AUTO, maxburst, CTLFLAG_RW,
&sctp_max_burst_default, 0,
"Default max burst for sctp endpoints");
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, maxburst, CTLTYPE_INT | CTLFLAG_RW,
&sctp_max_burst_default, 0, sysctl_sctp_check, "IU",
SCTPCTL_MAXBURST_DESC);
SYSCTL_INT(_net_inet_sctp, OID_AUTO, maxchunks, CTLFLAG_RW,
&sctp_max_chunks_on_queue, 0,
"Default max chunks on queue per asoc");
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, maxchunks, CTLTYPE_INT | CTLFLAG_RW,
&sctp_max_chunks_on_queue, 0, sysctl_sctp_check, "IU",
SCTPCTL_MAXCHUNKS_DESC);
SYSCTL_INT(_net_inet_sctp, OID_AUTO, tcbhashsize, CTLFLAG_RW,
&sctp_hashtblsize, 0,
"Tuneable for Hash table sizes");
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, tcbhashsize, CTLTYPE_INT | CTLFLAG_RW,
&sctp_hashtblsize, 0, sysctl_sctp_check, "IU",
SCTPCTL_TCBHASHSIZE_DESC);
SYSCTL_INT(_net_inet_sctp, OID_AUTO, min_split_point, CTLFLAG_RW,
&sctp_min_split_point, 0,
"Minimum size when splitting a chunk");
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, pcbhashsize, CTLTYPE_INT | CTLFLAG_RW,
&sctp_pcbtblsize, 0, sysctl_sctp_check, "IU",
SCTPCTL_PCBHASHSIZE_DESC);
SYSCTL_INT(_net_inet_sctp, OID_AUTO, pcbhashsize, CTLFLAG_RW,
&sctp_pcbtblsize, 0,
"Tuneable for PCB Hash table sizes");
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, min_split_point, CTLTYPE_INT | CTLFLAG_RW,
&sctp_min_split_point, 0, sysctl_sctp_check, "IU",
SCTPCTL_MIN_SPLIT_POINT_DESC);
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_PROC(_net_inet_sctp, OID_AUTO, chunkscale, CTLTYPE_INT | CTLFLAG_RW,
&sctp_chunkscale, 0, sysctl_sctp_check, "IU",
SCTPCTL_CHUNKSCALE_DESC);
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_PROC(_net_inet_sctp, OID_AUTO, delayed_sack_time, CTLTYPE_INT | CTLFLAG_RW,
&sctp_delayed_sack_time_default, 0, sysctl_sctp_check, "IU",
SCTPCTL_DELAYED_SACK_TIME_DESC);
SYSCTL_INT(_net_inet_sctp, OID_AUTO, chunkscale, CTLFLAG_RW,
&sctp_chunkscale, 0,
"Tuneable for Scaling of number of chunks and messages");
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, sack_freq, CTLTYPE_INT | CTLFLAG_RW,
&sctp_sack_freq_default, 0, sysctl_sctp_check, "IU",
SCTPCTL_SACK_FREQ_DESC);
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_PROC(_net_inet_sctp, OID_AUTO, sys_resource, CTLTYPE_INT | CTLFLAG_RW,
&sctp_system_free_resc_limit, 0, sysctl_sctp_check, "IU",
SCTPCTL_SYS_RESOURCE_DESC);
SYSCTL_UINT(_net_inet_sctp, OID_AUTO, sack_freq, CTLFLAG_RW,
&sctp_sack_freq_default, 0,
"Default SACK frequency");
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, asoc_resource, CTLTYPE_INT | CTLFLAG_RW,
&sctp_asoc_free_resc_limit, 0, sysctl_sctp_check, "IU",
SCTPCTL_ASOC_RESOURCE_DESC);
SYSCTL_UINT(_net_inet_sctp, OID_AUTO, heartbeat_interval, CTLFLAG_RW,
&sctp_heartbeat_interval_default, 0,
"Default heartbeat interval in msec");
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, heartbeat_interval, CTLTYPE_INT | CTLFLAG_RW,
&sctp_heartbeat_interval_default, 0, sysctl_sctp_check, "IU",
SCTPCTL_HEARTBEAT_INTERVAL_DESC);
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_PROC(_net_inet_sctp, OID_AUTO, pmtu_raise_time, CTLTYPE_INT | CTLFLAG_RW,
&sctp_pmtu_raise_time_default, 0, sysctl_sctp_check, "IU",
SCTPCTL_PMTU_RAISE_TIME_DESC);
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_PROC(_net_inet_sctp, OID_AUTO, shutdown_guard_time, CTLTYPE_INT | CTLFLAG_RW,
&sctp_shutdown_guard_time_default, 0, sysctl_sctp_check, "IU",
SCTPCTL_SHUTDOWN_GUARD_TIME_DESC);
SYSCTL_UINT(_net_inet_sctp, OID_AUTO, secret_lifetime, CTLFLAG_RW,
&sctp_secret_lifetime_default, 0,
"Default secret lifetime in sec");
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, secret_lifetime, CTLTYPE_INT | CTLFLAG_RW,
&sctp_secret_lifetime_default, 0, sysctl_sctp_check, "IU",
SCTPCTL_SECRET_LIFETIME_DESC);
SYSCTL_UINT(_net_inet_sctp, OID_AUTO, rto_max, CTLFLAG_RW,
&sctp_rto_max_default, 0,
"Default maximum retransmission timeout in msec");
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, rto_max, CTLTYPE_INT | CTLFLAG_RW,
&sctp_rto_max_default, 0, sysctl_sctp_check, "IU",
SCTPCTL_RTO_MAX_DESC);
SYSCTL_UINT(_net_inet_sctp, OID_AUTO, rto_min, CTLFLAG_RW,
&sctp_rto_min_default, 0,
"Default minimum retransmission timeout in msec");
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, rto_min, CTLTYPE_INT | CTLFLAG_RW,
&sctp_rto_min_default, 0, sysctl_sctp_check, "IU",
SCTPCTL_RTO_MIN_DESC);
SYSCTL_UINT(_net_inet_sctp, OID_AUTO, rto_initial, CTLFLAG_RW,
&sctp_rto_initial_default, 0,
"Default initial retransmission timeout in msec");
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, rto_initial, CTLTYPE_INT | CTLFLAG_RW,
&sctp_rto_initial_default, 0, sysctl_sctp_check, "IU",
SCTPCTL_RTO_INITIAL_DESC);
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_PROC(_net_inet_sctp, OID_AUTO, init_rto_max, CTLTYPE_INT | CTLFLAG_RW,
&sctp_init_rto_max_default, 0, sysctl_sctp_check, "IU",
SCTPCTL_INIT_RTO_MAX_DESC);
SYSCTL_UINT(_net_inet_sctp, OID_AUTO, valid_cookie_life, CTLFLAG_RW,
&sctp_valid_cookie_life_default, 0,
"Default cookie lifetime in ticks");
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, valid_cookie_life, CTLTYPE_INT | CTLFLAG_RW,
&sctp_valid_cookie_life_default, 0, sysctl_sctp_check, "IU",
SCTPCTL_VALID_COOKIE_LIFE_DESC);
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_PROC(_net_inet_sctp, OID_AUTO, init_rtx_max, CTLTYPE_INT | CTLFLAG_RW,
&sctp_init_rtx_max_default, 0, sysctl_sctp_check, "IU",
SCTPCTL_INIT_RTX_MAX_DESC);
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_PROC(_net_inet_sctp, OID_AUTO, assoc_rtx_max, CTLTYPE_INT | CTLFLAG_RW,
&sctp_assoc_rtx_max_default, 0, sysctl_sctp_check, "IU",
SCTPCTL_ASSOC_RTX_MAX_DESC);
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_PROC(_net_inet_sctp, OID_AUTO, path_rtx_max, CTLTYPE_INT | CTLFLAG_RW,
&sctp_path_rtx_max_default, 0, sysctl_sctp_check, "IU",
SCTPCTL_PATH_RTX_MAX_DESC);
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_PROC(_net_inet_sctp, OID_AUTO, add_more_on_output, CTLTYPE_INT | CTLFLAG_RW,
&sctp_add_more_threshold, 0, sysctl_sctp_check, "IU",
SCTPCTL_ADD_MORE_ON_OUTPUT_DESC);
SYSCTL_UINT(_net_inet_sctp, OID_AUTO, outgoing_streams, CTLFLAG_RW,
&sctp_nr_outgoing_streams_default, 0,
"Default number of outgoing streams");
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, outgoing_streams, CTLTYPE_INT | CTLFLAG_RW,
&sctp_nr_outgoing_streams_default, 0, sysctl_sctp_check, "IU",
SCTPCTL_OUTGOING_STREAMS_DESC);
SYSCTL_UINT(_net_inet_sctp, OID_AUTO, cmt_on_off, CTLFLAG_RW,
&sctp_cmt_on_off, 0,
"CMT ON/OFF flag");
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, cmt_on_off, CTLTYPE_INT | CTLFLAG_RW,
&sctp_cmt_on_off, 0, sysctl_sctp_check, "IU",
SCTPCTL_CMT_ON_OFF_DESC);
SYSCTL_UINT(_net_inet_sctp, OID_AUTO, cmt_pf, CTLFLAG_RW,
&sctp_cmt_pf, 0,
"CMT PF type flag");
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, cmt_use_dac, CTLTYPE_INT | CTLFLAG_RW,
&sctp_cmt_use_dac, 0, sysctl_sctp_check, "IU",
SCTPCTL_CMT_USE_DAC_DESC);
SYSCTL_UINT(_net_inet_sctp, OID_AUTO, default_cc_module, CTLFLAG_RW,
&sctp_default_cc_module, 0,
"Default congestion control module");
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, cmt_pf, CTLTYPE_INT | CTLFLAG_RW,
&sctp_cmt_pf, 0, sysctl_sctp_check, "IU",
SCTPCTL_CMT_PF_DESC);
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, cwnd_maxburst, CTLTYPE_INT | CTLFLAG_RW,
&sctp_use_cwnd_based_maxburst, 0, sysctl_sctp_check, "IU",
SCTPCTL_CWND_MAXBURST_DESC);
SYSCTL_UINT(_net_inet_sctp, OID_AUTO, default_frag_interleave, CTLFLAG_RW,
&sctp_default_frag_interleave, 0,
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, early_fast_retran, CTLTYPE_INT | CTLFLAG_RW,
&sctp_early_fr, 0, sysctl_sctp_check, "IU",
SCTPCTL_EARLY_FAST_RETRAN_DESC);
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, early_fast_retran_msec, CTLTYPE_INT | CTLFLAG_RW,
&sctp_early_fr_msec, 0, sysctl_sctp_check, "IU",
SCTPCTL_EARLY_FAST_RETRAN_MSEC_DESC);
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, asconf_auth_nochk, CTLTYPE_INT | CTLFLAG_RW,
&sctp_asconf_auth_nochk, 0, sysctl_sctp_check, "IU",
SCTPCTL_ASCONF_AUTH_NOCHK_DESC);
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, auth_disable, CTLTYPE_INT | CTLFLAG_RW,
&sctp_auth_disable, 0, sysctl_sctp_check, "IU",
SCTPCTL_AUTH_DISABLE_DESC);
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, nat_friendly, CTLTYPE_INT | CTLFLAG_RW,
&sctp_nat_friendly, 0, sysctl_sctp_check, "IU",
SCTPCTL_NAT_FRIENDLY_DESC);
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, abc_l_var, CTLTYPE_INT | CTLFLAG_RW,
&sctp_L2_abc_variable, 0, sysctl_sctp_check, "IU",
SCTPCTL_ABC_L_VAR_DESC);
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, max_chained_mbufs, CTLTYPE_INT | CTLFLAG_RW,
&sctp_mbuf_threshold_count, 0, sysctl_sctp_check, "IU",
SCTPCTL_MAX_CHAINED_MBUFS_DESC);
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, do_sctp_drain, CTLTYPE_INT | CTLFLAG_RW,
&sctp_do_drain, 0, sysctl_sctp_check, "IU",
SCTPCTL_DO_SCTP_DRAIN_DESC);
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, hb_max_burst, CTLTYPE_INT | CTLFLAG_RW,
&sctp_hb_maxburst, 0, sysctl_sctp_check, "IU",
SCTPCTL_HB_MAX_BURST_DESC);
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, abort_at_limit, CTLTYPE_INT | CTLFLAG_RW,
&sctp_abort_if_one_2_one_hits_limit, 0, sysctl_sctp_check, "IU",
SCTPCTL_ABORT_AT_LIMIT_DESC);
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, strict_data_order, CTLTYPE_INT | CTLFLAG_RW,
&sctp_strict_data_order, 0, sysctl_sctp_check, "IU",
SCTPCTL_STRICT_DATA_ORDER_DESC);
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, min_residual, CTLTYPE_INT | CTLFLAG_RW,
&sctp_min_residual, 0, sysctl_sctp_check, "IU",
SCTPCTL_MIN_RESIDUAL_DESC);
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, max_retran_chunk, CTLTYPE_INT | CTLFLAG_RW,
&sctp_max_retran_chunk, 0, sysctl_sctp_check, "IU",
SCTPCTL_MAX_RETRAN_CHUNK_DESC);
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, logging, CTLTYPE_INT | CTLFLAG_RW,
&sctp_logging_level, 0, sysctl_sctp_check, "IU",
SCTPCTL_LOGGING_LEVEL_DESC);
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, default_cc_module, CTLTYPE_INT | CTLFLAG_RW,
&sctp_default_cc_module, 0, sysctl_sctp_check, "IU",
SCTPCTL_DEFAULT_CC_MODULE_DESC);
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, default_frag_interleave, CTLTYPE_INT | CTLFLAG_RW,
&sctp_default_frag_interleave, 0, sysctl_sctp_check, "IU",
SCTPCTL_DEFAULT_FRAG_INTERLEAVE_DESC);
SYSCTL_UINT(_net_inet_sctp, OID_AUTO, cwnd_maxburst, CTLFLAG_RW,
&sctp_use_cwnd_based_maxburst, 0,
"Use a CWND adjusting maxburst");
#if defined(__FreeBSD__) || defined(SCTP_APPLE_MOBILITY_BASE)
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, mobility_base, CTLTYPE_INT | CTLFLAG_RW,
&sctp_mobility_base, 0, sysctl_sctp_check, "IU",
SCTPCTL_MOBILITY_BASE_DESC);
#endif
SYSCTL_UINT(_net_inet_sctp, OID_AUTO, early_fast_retran, CTLFLAG_RW,
&sctp_early_fr, 0,
"Early Fast Retransmit with timer");
#if defined(__FreeBSD__) || defined(SCTP_APPLE_MOBILITY_FASTHANDOFF)
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, mobility_fasthandoff, CTLTYPE_INT | CTLFLAG_RW,
&sctp_mobility_fasthandoff, 0, sysctl_sctp_check, "IU",
SCTPCTL_MOBILITY_FASTHANDOFF_DESC);
#endif
SYSCTL_UINT(_net_inet_sctp, OID_AUTO, deadlock_detect, CTLFLAG_RW,
&sctp_says_check_for_deadlock, 0,
"SMP Deadlock detection on/off");
#ifdef SCTP_DEBUG
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, debug, CTLTYPE_INT | CTLFLAG_RW,
&sctp_debug_on, 0, sysctl_sctp_check, "IU",
SCTPCTL_DEBUG_DESC);
#endif /* SCTP_DEBUG */
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 function");
SYSCTL_UINT(_net_inet_sctp, OID_AUTO, nat_friendly, CTLFLAG_RW,
&sctp_nat_friendly, 0,
"SCTP NAT friendly operation");
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, hb_max_burst, CTLFLAG_RW,
&sctp_hb_maxburst, 0,
"Confirmation Heartbeat max burst?");
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,
@ -697,31 +797,3 @@ SYSCTL_STRUCT(_net_inet_sctp, OID_AUTO, stats, CTLFLAG_RW,
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, assoclist, CTLFLAG_RD,
0, 0, sctp_assoclist,
"S,xassoc", "List of active SCTP associations");
SYSCTL_INT(_net_inet_sctp, OID_AUTO, min_residual, CTLFLAG_RW,
&sctp_min_residual, 0,
SCTPCTL_MIN_RESIDUAL_DESC);
SYSCTL_INT(_net_inet_sctp, OID_AUTO, max_retran_chunk, CTLFLAG_RW,
&sctp_max_retran_chunk, 0,
SCTPCTL_MAX_RETRAN_CHUNK_DESC);
SYSCTL_INT(_net_inet_sctp, OID_AUTO, sctp_logging, CTLFLAG_RW,
&sctp_logging_level, 0,
SCTPCTL_LOGGING_LEVEL_DESC);
#if defined(__FreeBSD__) || defined(SCTP_APPLE_MOBILITY_BASE)
SYSCTL_INT(_net_inet_sctp, OID_AUTO, mobility_base, CTLFLAG_RW,
&sctp_mobility_base, 0, "Enable SCTP Mobility");
#endif
#if defined(__FreeBSD__) || defined(SCTP_APPLE_MOBILITY_FASTHANDOFF)
SYSCTL_INT(_net_inet_sctp, OID_AUTO, mobility_fasthandoff, CTLFLAG_RW,
&sctp_mobility_fasthandoff, 0, "Enable SCTP fast handoff");
#endif
#ifdef SCTP_DEBUG
SYSCTL_INT(_net_inet_sctp, OID_AUTO, debug, CTLFLAG_RW,
&sctp_debug_on, 0, "Configure debug output");
#endif /* SCTP_DEBUG */

View File

@ -278,78 +278,76 @@ __FBSDID("$FreeBSD$");
#define SCTPCTL_CMT_ON_OFF_MAX 1
#define SCTPCTL_CMT_ON_OFF_DEFAULT 0
/* cmt_use_dac: CMT DAC on/off flag */
#define SCTPCTL_CMT_USE_DAC 35
#define SCTPCTL_CMT_USE_DAC_DESC "CMT DAC on/off flag"
#define SCTPCTL_CMT_USE_DAC_MIN 0
#define SCTPCTL_CMT_USE_DAC_MAX 1
#define SCTPCTL_CMT_USE_DAC_DEFAULT 0
/* JRS 5/2107 - CMT PF type flag */
#define SCTPCTL_CMT_PF 36
#define SCTPCTL_CMT_PF_DESC "CMT PF type flag"
#define SCTPCTL_CMT_PF_MIN 0
#define SCTPCTL_CMT_PF_MAX 2
#define SCTPCTL_CMT_PF_DEFAULT 0
/* cwnd_maxburst: Use a CWND adjusting maxburst */
#define SCTPCTL_CWND_MAXBURST 35
#define SCTPCTL_CWND_MAXBURST 37
#define SCTPCTL_CWND_MAXBURST_DESC "Use a CWND adjusting maxburst"
#define SCTPCTL_CWND_MAXBURST_MIN 0
#define SCTPCTL_CWND_MAXBURST_MAX 1
#define SCTPCTL_CWND_MAXBURST_DEFAULT 1
/* early_fast_retran: Early Fast Retransmit with timer */
#define SCTPCTL_EARLY_FAST_RETRAN 36
#define SCTPCTL_EARLY_FAST_RETRAN 38
#define SCTPCTL_EARLY_FAST_RETRAN_DESC "Early Fast Retransmit with timer"
#define SCTPCTL_EARLY_FAST_RETRAN_MIN 0
#define SCTPCTL_EARLY_FAST_RETRAN_MAX 0xFFFFFFFF
#define SCTPCTL_EARLY_FAST_RETRAN_DEFAULT 0
/* deadlock_detect: SMP Deadlock detection on/off */
#define SCTPCTL_DEADLOCK_DETECT 37
#define SCTPCTL_DEADLOCK_DETECT_DESC "SMP Deadlock detection on/off"
#define SCTPCTL_DEADLOCK_DETECT_MIN 0
#define SCTPCTL_DEADLOCK_DETECT_MAX 1
#define SCTPCTL_DEADLOCK_DETECT_DEFAULT 0
/* early_fast_retran_msec: Early Fast Retransmit minimum timer value */
#define SCTPCTL_EARLY_FAST_RETRAN_MSEC 38
#define SCTPCTL_EARLY_FAST_RETRAN_MSEC 39
#define SCTPCTL_EARLY_FAST_RETRAN_MSEC_DESC "Early Fast Retransmit minimum timer value"
#define SCTPCTL_EARLY_FAST_RETRAN_MSEC_MIN 0
#define SCTPCTL_EARLY_FAST_RETRAN_MSEC_MAX 0xFFFFFFFF
#define SCTPCTL_EARLY_FAST_RETRAN_MSEC_DEFAULT SCTP_MINFR_MSEC_TIMER
/* asconf_auth_nochk: Disable SCTP ASCONF AUTH requirement */
#define SCTPCTL_ASCONF_AUTH_NOCHK 39
#define SCTPCTL_ASCONF_AUTH_NOCHK 40
#define SCTPCTL_ASCONF_AUTH_NOCHK_DESC "Disable SCTP ASCONF AUTH requirement"
#define SCTPCTL_ASCONF_AUTH_NOCHK_MIN 0
#define SCTPCTL_ASCONF_AUTH_NOCHK_MAX 1
#define SCTPCTL_ASCONF_AUTH_NOCHK_DEFAULT 0
/* auth_disable: Disable SCTP AUTH function */
#define SCTPCTL_AUTH_DISABLE 40
#define SCTPCTL_AUTH_DISABLE 41
#define SCTPCTL_AUTH_DISABLE_DESC "Disable SCTP AUTH function"
#define SCTPCTL_AUTH_DISABLE_MIN 0
#define SCTPCTL_AUTH_DISABLE_MAX 1
#define SCTPCTL_AUTH_DISABLE_DEFAULT 0
/* nat_friendly: SCTP NAT friendly operation */
#define SCTPCTL_NAT_FRIENDLY 41
#define SCTPCTL_NAT_FRIENDLY 42
#define SCTPCTL_NAT_FRIENDLY_DESC "SCTP NAT friendly operation"
#define SCTPCTL_NAT_FRIENDLY_MIN 0
#define SCTPCTL_NAT_FRIENDLY_MAX 1
#define SCTPCTL_NAT_FRIENDLY_DEFAULT 1
/* abc_l_var: SCTP ABC max increase per SACK (L) */
#define SCTPCTL_ABC_L_VAR 42
#define SCTPCTL_ABC_L_VAR 43
#define SCTPCTL_ABC_L_VAR_DESC "SCTP ABC max increase per SACK (L)"
#define SCTPCTL_ABC_L_VAR_MIN 0
#define SCTPCTL_ABC_L_VAR_MAX 0xFFFFFFFF
#define SCTPCTL_ABC_L_VAR_DEFAULT 1
/* max_chained_mbufs: Default max number of small mbufs on a chain */
#define SCTPCTL_MAX_CHAINED_MBUFS 43
#define SCTPCTL_MAX_CHAINED_MBUFS 44
#define SCTPCTL_MAX_CHAINED_MBUFS_DESC "Default max number of small mbufs on a chain"
#define SCTPCTL_MAX_CHAINED_MBUFS_MIN 0
#define SCTPCTL_MAX_CHAINED_MBUFS_MAX 0xFFFFFFFF
#define SCTPCTL_MAX_CHAINED_MBUFS_DEFAULT SCTP_DEFAULT_MBUFS_IN_CHAIN
/* cmt_use_dac: CMT DAC on/off flag */
#define SCTPCTL_CMT_USE_DAC 44
#define SCTPCTL_CMT_USE_DAC_DESC "CMT DAC on/off flag"
#define SCTPCTL_CMT_USE_DAC_MIN 0
#define SCTPCTL_CMT_USE_DAC_MAX 1
#define SCTPCTL_CMT_USE_DAC_DEFAULT 0
/* do_sctp_drain: Should SCTP respond to the drain calls */
#define SCTPCTL_DO_SCTP_DRAIN 45
#define SCTPCTL_DO_SCTP_DRAIN_DESC "Should SCTP respond to the drain calls"
@ -359,7 +357,7 @@ __FBSDID("$FreeBSD$");
/* hb_max_burst: Confirmation Heartbeat max burst? */
#define SCTPCTL_HB_MAX_BURST 46
#define SCTPCTL_HB_MAX_BURST_DESC "Confirmation Heartbeat max burst?"
#define SCTPCTL_HB_MAX_BURST_DESC "Confirmation Heartbeat max burst"
#define SCTPCTL_HB_MAX_BURST_MIN 1
#define SCTPCTL_HB_MAX_BURST_MAX 0xFFFFFFFF
#define SCTPCTL_HB_MAX_BURST_DEFAULT SCTP_DEF_MAX_BURST
@ -399,183 +397,43 @@ __FBSDID("$FreeBSD$");
#define SCTPCTL_LOGGING_LEVEL_MAX 0xffffffff
#define SCTPCTL_LOGGING_LEVEL_DEFAULT 0
/* JRS 5/2107 - CMT PF type flag */
#define SCTPCTL_CMT_PF 52
#define SCTPCTL_CMT_PF_DESC "CMT PF type flag"
#define SCTPCTL_CMT_PF_MIN 0
#define SCTPCTL_CMT_PF_MAX 2
#define SCTPCTL_CMT_PF_DEFAULT 0
/* JRS - default congestion control module sysctl */
#define SCTPCTL_DEFAULT_CC_MODULE 53
#define SCTPCTL_DEFAULT_CC_MODULE 52
#define SCTPCTL_DEFAULT_CC_MODULE_DESC "Default congestion control module"
#define SCTPCTL_DEFAULT_CC_MODULE_MIN 0
#define SCTPCTL_DEFAULT_CC_MODULE_MAX 2
#define SCTPCTL_DEFAULT_CC_MODULE_DEFAULT 0
/* RRS - default fragment interleave */
#define SCTPCTL_DEFAULT_FRAG_INTERLEAVE 54
#define SCTPCTL_DEFAULT_FRAG_INTERLEAVE 53
#define SCTPCTL_DEFAULT_FRAG_INTERLEAVE_DESC "Default fragment interleave level"
#define SCTPCTL_DEFAULT_FRAG_INTERLEAVE_MIN 0
#define SCTPCTL_DEFAULT_FRAG_INTERLEAVE_MAX 2
#define SCTPCTL_DEFAULT_FRAG_INTERLEAVE_DEFAULT 1
/* mobility_base: Enable SCTP mobility support */
#define SCTPCTL_MOBILITY_BASE 55
#define SCTPCTL_MOBILITY_BASE 54
#define SCTPCTL_MOBILITY_BASE_DESC "Enable SCTP base mobility"
#define SCTPCTL_MOBILITY_BASE_MIN 0
#define SCTPCTL_MOBILITY_BASE_MAX 1
#define SCTPCTL_MOBILITY_BASE_DEFAULT SCTP_DEFAULT_MOBILITY_BASE
/* mobility_fasthandoff: Enable SCTP fast handoff support */
#define SCTPCTL_MOBILITY_FASTHANDOFF 56
#define SCTPCTL_MOBILITY_FASTHANDOFF 55
#define SCTPCTL_MOBILITY_FASTHANDOFF_DESC "Enable SCTP fast handoff"
#define SCTPCTL_MOBILITY_FASTHANDOFF_MIN 0
#define SCTPCTL_MOBILITY_FASTHANDOFF_MAX 1
#define SCTPCTL_MOBILITY_FASTHANDOFF_DEFAULT SCTP_DEFAULT_MOBILITY_FASTHANDOFF
#ifdef SCTP_DEBUG
#if defined(SCTP_DEBUG)
/* debug: Configure debug output */
#define SCTPCTL_DEBUG 57
#define SCTPCTL_DEBUG 56
#define SCTPCTL_DEBUG_DESC "Configure debug output"
#define SCTPCTL_DEBUG_MIN 0
#define SCTPCTL_DEBUG_MAX 0xFFFFFFFF
#define SCTPCTL_DEBUG_DEFAULT 0
#define SCTPCTL_MAXID 57
#else
#define SCTPCTL_MAXID 58
#endif
/*
* Names for SCTP sysctl objects variables.
* Must match the OIDs above.
*/
#ifdef SCTP_DEBUG
#define SCTPCTL_NAMES { \
{ 0, 0 }, \
{ "sendspace", CTLTYPE_INT }, \
{ "recvspace", CTLTYPE_INT }, \
{ "autoasconf", CTLTYPE_INT }, \
{ "ecn_enable", CTLTYPE_INT }, \
{ "ecn_nonce", CTLTYPE_INT }, \
{ "strict_sack", CTLTYPE_INT }, \
{ "looback_nocsum", CTLTYPE_INT }, \
{ "strict_init", CTLTYPE_INT }, \
{ "peer_chkoh", CTLTYPE_INT }, \
{ "maxburst", CTLTYPE_INT }, \
{ "maxchunks", CTLTYPE_INT }, \
{ "delayed_sack_time", CTLTYPE_INT }, \
{ "sack_freq", CTLTYPE_INT }, \
{ "heartbeat_interval", CTLTYPE_INT }, \
{ "pmtu_raise_time", CTLTYPE_INT }, \
{ "shutdown_guard_time", CTLTYPE_INT }, \
{ "secret_lifetime", CTLTYPE_INT }, \
{ "rto_max", CTLTYPE_INT }, \
{ "rto_min", CTLTYPE_INT }, \
{ "rto_initial", CTLTYPE_INT }, \
{ "init_rto_max", CTLTYPE_INT }, \
{ "valid_cookie_life", CTLTYPE_INT }, \
{ "init_rtx_max", CTLTYPE_INT }, \
{ "assoc_rtx_max", CTLTYPE_INT }, \
{ "path_rtx_max", CTLTYPE_INT }, \
{ "outgoing_streams", CTLTYPE_INT }, \
{ "cmt_on_off", CTLTYPE_INT }, \
{ "cmt_on_pf", CTLTYPE_INT }, \
{ "default_cc_module", CTLTYPE_INT }, \
{ "cwnd_maxburst", CTLTYPE_INT }, \
{ "early_fast_retran", CTLTYPE_INT }, \
{ "deadlock_detect", CTLTYPE_INT }, \
{ "early_fast_retran_msec", CTLTYPE_INT }, \
{ "asconf_auth_nochk", CTLTYPE_INT }, \
{ "auth_disable", CTLTYPE_INT }, \
{ "nat_friendly", CTLTYPE_INT }, \
{ "abc_l_var", CTLTYPE_INT }, \
{ "max_mbuf_chain", CTLTYPE_INT }, \
{ "cmt_use_dac", CTLTYPE_INT }, \
{ "do_sctp_drain", CTLTYPE_INT }, \
{ "warm_crc_table", CTLTYPE_INT }, \
{ "abort_at_limit", CTLTYPE_INT }, \
{ "strict_data_order", CTLTYPE_INT }, \
{ "tcbhashsize", CTLTYPE_INT }, \
{ "pcbhashsize", CTLTYPE_INT }, \
{ "chunkscale", CTLTYPE_INT }, \
{ "min_split_point", CTLTYPE_INT }, \
{ "add_more_on_output", CTLTYPE_INT }, \
{ "sys_resource", CTLTYPE_INT }, \
{ "asoc_resource", CTLTYPE_INT }, \
{ "min_residual", CTLTYPE_INT }, \
{ "max_retran_chunk", CTLTYPE_INT }, \
{ "sctp_logging", CTLTYPE_INT }, \
{ "frag_interleave", CTLTYPE_INT }, \
{ "mobility_base", CTLTYPE_INT }, \
{ "mobility_fasthandoff", CTLTYPE_INT }, \
{ "debug", CTLTYPE_INT }, \
}
#else
#define SCTPCTL_NAMES { \
{ 0, 0 }, \
{ "sendspace", CTLTYPE_INT }, \
{ "recvspace", CTLTYPE_INT }, \
{ "autoasconf", CTLTYPE_INT }, \
{ "ecn_enable", CTLTYPE_INT }, \
{ "ecn_nonce", CTLTYPE_INT }, \
{ "strict_sack", CTLTYPE_INT }, \
{ "looback_nocsum", CTLTYPE_INT }, \
{ "strict_init", CTLTYPE_INT }, \
{ "peer_chkoh", CTLTYPE_INT }, \
{ "maxburst", CTLTYPE_INT }, \
{ "maxchunks", CTLTYPE_INT }, \
{ "delayed_sack_time", CTLTYPE_INT }, \
{ "sack_freq", CTLTYPE_INT }, \
{ "heartbeat_interval", CTLTYPE_INT }, \
{ "pmtu_raise_time", CTLTYPE_INT }, \
{ "shutdown_guard_time", CTLTYPE_INT }, \
{ "secret_lifetime", CTLTYPE_INT }, \
{ "rto_max", CTLTYPE_INT }, \
{ "rto_min", CTLTYPE_INT }, \
{ "rto_initial", CTLTYPE_INT }, \
{ "init_rto_max", CTLTYPE_INT }, \
{ "valid_cookie_life", CTLTYPE_INT }, \
{ "init_rtx_max", CTLTYPE_INT }, \
{ "assoc_rtx_max", CTLTYPE_INT }, \
{ "path_rtx_max", CTLTYPE_INT }, \
{ "outgoing_streams", CTLTYPE_INT }, \
{ "cmt_on_off", CTLTYPE_INT }, \
{ "cmt_on_pf", CTLTYPE_INT }, \
{ "default_cc_module", CTLTYPE_INT }, \
{ "cwnd_maxburst", CTLTYPE_INT }, \
{ "early_fast_retran", CTLTYPE_INT }, \
{ "deadlock_detect", CTLTYPE_INT }, \
{ "early_fast_retran_msec", CTLTYPE_INT }, \
{ "asconf_auth_nochk", CTLTYPE_INT }, \
{ "auth_disable", CTLTYPE_INT }, \
{ "nat_friendly", CTLTYPE_INT }, \
{ "abc_l_var", CTLTYPE_INT }, \
{ "max_mbuf_chain", CTLTYPE_INT }, \
{ "cmt_use_dac", CTLTYPE_INT }, \
{ "do_sctp_drain", CTLTYPE_INT }, \
{ "warm_crc_table", CTLTYPE_INT }, \
{ "abort_at_limit", CTLTYPE_INT }, \
{ "strict_data_order", CTLTYPE_INT }, \
{ "tcbhashsize", CTLTYPE_INT }, \
{ "pcbhashsize", CTLTYPE_INT }, \
{ "chunkscale", CTLTYPE_INT }, \
{ "min_split_point", CTLTYPE_INT }, \
{ "add_more_on_output", CTLTYPE_INT }, \
{ "sys_resource", CTLTYPE_INT }, \
{ "asoc_resource", CTLTYPE_INT }, \
{ "min_residual", CTLTYPE_INT }, \
{ "max_retran_chunk", CTLTYPE_INT }, \
{ "sctp_logging", CTLTYPE_INT }, \
{ "frag_interleave", CTLTYPE_INT }, \
{ "mobility_base", CTLTYPE_INT }, \
{ "mobility_fasthandoff", CTLTYPE_INT }, \
}
#endif
#if defined(_KERNEL)
@ -617,24 +475,18 @@ extern uint32_t sctp_path_rtx_max_default;
extern uint32_t sctp_add_more_threshold;
extern uint32_t sctp_nr_outgoing_streams_default;
extern uint32_t sctp_cmt_on_off;
extern uint32_t sctp_cmt_use_dac;
/* JRS 5/21/07 - CMT PF type flag variables */
extern uint32_t sctp_cmt_pf;
/* JRS - Variable for the default congestion control module */
extern uint32_t sctp_default_cc_module;
extern uint32_t sctp_default_frag_interleave;
extern uint32_t sctp_use_cwnd_based_maxburst;
extern uint32_t sctp_early_fr;
extern uint32_t sctp_use_rttvar_cc;
extern uint32_t sctp_says_check_for_deadlock;
extern uint32_t sctp_early_fr_msec;
extern uint32_t sctp_asconf_auth_nochk;
extern uint32_t sctp_auth_disable;
extern uint32_t sctp_nat_friendly;
extern uint32_t sctp_L2_abc_variable;
extern uint32_t sctp_mbuf_threshold_count;
extern uint32_t sctp_cmt_use_dac;
extern uint32_t sctp_do_drain;
extern uint32_t sctp_hb_maxburst;
extern uint32_t sctp_abort_if_one_2_one_hits_limit;
@ -642,6 +494,10 @@ extern uint32_t sctp_strict_data_order;
extern uint32_t sctp_min_residual;
extern uint32_t sctp_max_retran_chunk;
extern uint32_t sctp_logging_level;
/* JRS - Variable for the default congestion control module */
extern uint32_t sctp_default_cc_module;
extern uint32_t sctp_default_frag_interleave;
extern uint32_t sctp_mobility_base;
extern uint32_t sctp_mobility_fasthandoff;
@ -652,8 +508,7 @@ extern uint32_t sctp_debug_on;
extern struct sctpstat sctpstat;
#ifdef SYSCTL_DECL
#if defined(SYSCTL_DECL)
SYSCTL_DECL(_net_inet_sctp);
#endif

View File

@ -1388,6 +1388,24 @@ sctp_asconf_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
return (0);
}
/* Mobility adaptation */
int
sctp_delete_prim_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
struct sctp_nets *net)
{
if (stcb->asoc.deleted_primary == NULL) {
SCTPDBG(SCTP_DEBUG_ASCONF1, "delete_prim_timer: deleted_primary is not stored...\n");
sctp_mobility_feature_off(inp, SCTP_MOBILITY_PRIM_DELETED);
return (0);
}
SCTPDBG(SCTP_DEBUG_ASCONF1, "delete_prim_timer: finished to keep deleted primary ");
SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &stcb->asoc.deleted_primary->ro._l_addr.sa);
sctp_free_remote_addr(stcb->asoc.deleted_primary);
stcb->asoc.deleted_primary = NULL;
sctp_mobility_feature_off(inp, SCTP_MOBILITY_PRIM_DELETED);
return (0);
}
/*
* For the shutdown and shutdown-ack, we do not keep one around on the
* control queue. This means we must generate a new one and call the general

View File

@ -87,6 +87,10 @@ int
sctp_asconf_timer(struct sctp_inpcb *, struct sctp_tcb *,
struct sctp_nets *);
int
sctp_delete_prim_timer(struct sctp_inpcb *, struct sctp_tcb *,
struct sctp_nets *);
void
sctp_autoclose_timer(struct sctp_inpcb *, struct sctp_tcb *,
struct sctp_nets *net);

View File

@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$");
#endif
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
typedef uint32_t sctp_assoc_t;
@ -743,6 +742,11 @@ struct sctp_cwnd_log_req {
struct sctp_cwnd_log log[0];
};
struct sctp_timeval {
uint32_t tv_sec;
uint32_t tv_usec;
};
struct sctpstat {
/* MIB according to RFC 3873 */
uint32_t sctps_currestab; /* sctpStats 1 (Gauge32) */
@ -845,6 +849,8 @@ struct sctpstat {
* fired */
uint32_t sctps_timoasconf; /* Number of times an asconf timer
* fired */
uint32_t sctps_timodelprim; /* Number of times a prim_deleted
* timer fired */
uint32_t sctps_timoautoclose; /* Number of times auto close timer
* fired */
uint32_t sctps_timoassockill; /* Number of asoc free timers expired */
@ -921,7 +927,8 @@ struct sctpstat {
uint32_t sctps_fwdtsn_map_over; /* number of map array over-runs via
* fwd-tsn's */
struct timeval sctps_discontinuitytime; /* sctpStats 18 (TimeStamp) */
struct sctp_timeval sctps_discontinuitytime; /* sctpStats 18
* (TimeStamp) */
};
#define SCTP_STAT_INCR(_x) SCTP_STAT_INCR_BY(_x,1)
@ -984,14 +991,14 @@ struct xsctp_tcb {
uint32_t refcnt;
uint16_t local_port; /* sctpAssocEntry 3 */
uint16_t remote_port; /* sctpAssocEntry 4 */
struct timeval start_time; /* sctpAssocEntry 16 */
struct timeval discontinuity_time; /* sctpAssocEntry 17 */
struct sctp_timeval start_time; /* sctpAssocEntry 16 */
struct sctp_timeval discontinuity_time; /* sctpAssocEntry 17 */
};
struct xsctp_laddr {
union sctp_sockstore address; /* sctpAssocLocalAddrEntry 1/2 */
uint32_t last;
struct timeval start_time; /* sctpAssocLocalAddrEntry 3 */
struct sctp_timeval start_time; /* sctpAssocLocalAddrEntry 3 */
};
struct xsctp_raddr {
@ -1007,7 +1014,7 @@ struct xsctp_raddr {
uint8_t active; /* sctpAssocLocalRemEntry 3 */
uint8_t confirmed; /* */
uint8_t heartbeat_enabled; /* sctpAssocLocalRemEntry 4 */
struct timeval start_time; /* sctpAssocLocalRemEntry 8 */
struct sctp_timeval start_time; /* sctpAssocLocalRemEntry 8 */
};
/*

View File

@ -223,7 +223,7 @@ sctp_notify_mbuf(struct sctp_inpcb *inp,
void
sctp_notify(struct sctp_inpcb *inp,
int error,
struct ip *ip,
struct sctphdr *sh,
struct sockaddr *to,
struct sctp_tcb *stcb,
@ -234,110 +234,103 @@ sctp_notify(struct sctp_inpcb *inp,
#endif
/* protection */
int reason;
struct icmp *icmph;
if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
(sh == NULL) || (to == NULL)) {
if (stcb)
SCTP_TCB_UNLOCK(stcb);
return;
}
/* First job is to verify the vtag matches what I would send */
if (ntohl(sh->v_tag) != (stcb->asoc.peer_vtag)) {
SCTP_TCB_UNLOCK(stcb);
return;
}
/* FIX ME FIX ME PROTOPT i.e. no SCTP should ALWAYS be an ABORT */
icmph = (struct icmp *)((caddr_t)ip - (sizeof(struct icmp) -
sizeof(struct ip)));
if (icmph->icmp_type != ICMP_UNREACH) {
/* We only care about unreachable */
SCTP_TCB_UNLOCK(stcb);
return;
}
if ((icmph->icmp_code == ICMP_UNREACH_NET) ||
(icmph->icmp_code == ICMP_UNREACH_HOST) ||
(icmph->icmp_code == ICMP_UNREACH_NET_UNKNOWN) ||
(icmph->icmp_code == ICMP_UNREACH_HOST_UNKNOWN) ||
(icmph->icmp_code == ICMP_UNREACH_ISOLATED) ||
(icmph->icmp_code == ICMP_UNREACH_NET_PROHIB) ||
(icmph->icmp_code == ICMP_UNREACH_HOST_PROHIB) ||
(icmph->icmp_code == ICMP_UNREACH_FILTER_PROHIB)) {
if ((error == EHOSTUNREACH) || /* Host is not reachable */
(error == EHOSTDOWN) || /* Host is down */
(error == ECONNREFUSED) || /* Host refused the connection, (not
* an abort?) */
(error == ENOPROTOOPT) /* SCTP is not present on host */
) {
/*
* Hmm reachablity problems we must examine closely. If its
* not reachable, we may have lost a network. Or if there is
* NO protocol at the other end named SCTP. well we consider
* it a OOTB abort.
*/
if ((error == EHOSTUNREACH) || (error == EHOSTDOWN)) {
if (net->dest_state & SCTP_ADDR_REACHABLE) {
/* Ok that destination is NOT reachable */
SCTP_PRINTF("ICMP (thresh %d/%d) takes interface %p down\n",
net->error_count,
net->failure_threshold,
net);
if (net->dest_state & SCTP_ADDR_REACHABLE) {
/* Ok that destination is NOT reachable */
SCTP_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;
/*
* JRS 5/14/07 - If a destination is
* unreachable, the PF bit is turned off.
* This allows an unambiguous use of the PF
* bit for destinations that are reachable
* but potentially failed. If the
* destination is set to the unreachable
* state, also set the destination to the PF
* state.
*/
/*
* Add debug message here if destination is
* not in PF state.
*/
/* Stop any running T3 timers here? */
if (sctp_cmt_on_off && sctp_cmt_pf) {
net->dest_state &= ~SCTP_ADDR_PF;
SCTPDBG(SCTP_DEBUG_TIMER4, "Destination %p moved from PF to unreachable.\n",
net);
}
net->error_count = net->failure_threshold + 1;
sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
stcb, SCTP_FAILED_THRESHOLD,
(void *)net, SCTP_SO_NOT_LOCKED);
}
if (stcb) {
SCTP_TCB_UNLOCK(stcb);
}
} else {
net->dest_state &= ~SCTP_ADDR_REACHABLE;
net->dest_state |= SCTP_ADDR_NOT_REACHABLE;
/*
* Here the peer is either playing tricks on us,
* including an address that belongs to someone who
* does not support SCTP OR was a userland
* implementation that shutdown and now is dead. In
* either case treat it like a OOTB abort with no
* TCB
* JRS 5/14/07 - If a destination is unreachable,
* the PF bit is turned off. This allows an
* unambiguous use of the PF bit for destinations
* that are reachable but potentially failed. If the
* destination is set to the unreachable state, also
* set the destination to the PF state.
*/
sctp_abort_notification(stcb, SCTP_PEER_FAULTY, SCTP_SO_NOT_LOCKED);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(inp);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
#endif
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_2);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
/*
* SCTP_TCB_UNLOCK(stcb); MT: I think this is not
* needed.
* Add debug message here if destination is not in
* PF state.
*/
#endif
/* no need to unlock here, since the TCB is gone */
/* Stop any running T3 timers here? */
if (sctp_cmt_on_off && sctp_cmt_pf) {
net->dest_state &= ~SCTP_ADDR_PF;
SCTPDBG(SCTP_DEBUG_TIMER4, "Destination %p moved from PF to unreachable.\n",
net);
}
net->error_count = net->failure_threshold + 1;
sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
stcb, SCTP_FAILED_THRESHOLD,
(void *)net, SCTP_SO_NOT_LOCKED);
}
SCTP_TCB_UNLOCK(stcb);
} else if ((icmph->icmp_code == ICMP_UNREACH_PROTOCOL) ||
(icmph->icmp_code == ICMP_UNREACH_PORT)) {
/*
* Here the peer is either playing tricks on us, including
* an address that belongs to someone who does not support
* SCTP OR was a userland implementation that shutdown and
* now is dead. In either case treat it like a OOTB abort
* with no TCB
*/
reason = SCTP_PEER_FAULTY;
sctp_abort_notification(stcb, reason, SCTP_SO_NOT_LOCKED);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(inp);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
#endif
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_2);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
/* SCTP_TCB_UNLOCK(stcb); MT: I think this is not needed. */
#endif
/* no need to unlock here, since the TCB is gone */
} else {
/* Send all others to the app */
if (stcb) {
SCTP_TCB_UNLOCK(stcb);
}
if (inp->sctp_socket) {
#ifdef SCTP_LOCK_LOGGING
if (sctp_logging_level & SCTP_LOCK_LOGGING_ENABLE) {
sctp_log_lock(inp, stcb, SCTP_LOG_LOCK_SOCK);
}
#endif
SOCK_LOCK(inp->sctp_socket);
inp->sctp_socket->so_error = error;
sctp_sowwakeup(inp, inp->sctp_socket);
SOCK_UNLOCK(inp->sctp_socket);
}
SCTP_TCB_UNLOCK(stcb);
}
}
@ -388,14 +381,7 @@ sctp_ctlinput(cmd, sa, vip)
&inp, &net, 1, vrf_id);
if (stcb != NULL && inp && (inp->sctp_socket != NULL)) {
if (cmd != PRC_MSGSIZE) {
int cm;
if (cmd == PRC_HOSTDEAD) {
cm = EHOSTUNREACH;
} else {
cm = inetctlerrmap[cmd];
}
sctp_notify(inp, cm, sh,
sctp_notify(inp, ip, sh,
(struct sockaddr *)&to, stcb,
net);
} else {
@ -1070,6 +1056,9 @@ sctp_fill_user_address(struct sockaddr_storage *ss, struct sockaddr *sa)
/*
* NOTE: assumes addr lock is held
*/
static size_t
sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp,
struct sctp_tcb *stcb,
@ -1235,12 +1224,17 @@ sctp_fill_up_addresses(struct sctp_inpcb *inp,
{
size_t size = 0;
SCTP_IPI_ADDR_LOCK();
/* fill up addresses for the endpoint's default vrf */
size = sctp_fill_up_addresses_vrf(inp, stcb, limit, sas,
inp->def_vrf_id);
SCTP_IPI_ADDR_UNLOCK();
return (size);
}
/*
* NOTE: assumes addr lock is held
*/
static int
sctp_count_max_addresses_vrf(struct sctp_inpcb *inp, uint32_t vrf_id)
{
@ -1297,8 +1291,10 @@ sctp_count_max_addresses(struct sctp_inpcb *inp)
{
int cnt = 0;
SCTP_IPI_ADDR_LOCK();
/* count addresses for the endpoint's default VRF */
cnt = sctp_count_max_addresses_vrf(inp, inp->def_vrf_id);
SCTP_IPI_ADDR_UNLOCK();
return (cnt);
}
@ -1655,9 +1651,9 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
error = 0;
}
#endif
if (error)
if (error) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
}
*optsize = sizeof(*av);
}
break;
@ -3785,7 +3781,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
struct sctp_ifa *ifa;
ifa = sctp_find_ifa_by_addr((struct sockaddr *)&sspp->sspp_addr,
stcb->asoc.vrf_id, 0);
stcb->asoc.vrf_id, SCTP_ADDR_NOT_LOCKED);
if (ifa == NULL) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;

View File

@ -307,7 +307,7 @@ void sctp_pcbinfo_cleanup(void);
int sctp_shutdown __P((struct socket *));
void sctp_notify
__P((struct sctp_inpcb *, int, struct sctphdr *,
__P((struct sctp_inpcb *, struct ip *ip, struct sctphdr *,
struct sockaddr *, struct sctp_tcb *,
struct sctp_nets *));

View File

@ -806,7 +806,7 @@ sctp_fill_random_store(struct sctp_pcb *m)
}
uint32_t
sctp_select_initial_TSN(struct sctp_pcb *m)
sctp_select_initial_TSN(struct sctp_pcb *inp)
{
/*
* A true implementation should use random selection process to get
@ -815,27 +815,36 @@ sctp_select_initial_TSN(struct sctp_pcb *m)
*/
uint32_t x, *xp;
uint8_t *p;
int store_at, new_store;
if (m->initial_sequence_debug != 0) {
if (inp->initial_sequence_debug != 0) {
uint32_t ret;
ret = m->initial_sequence_debug;
m->initial_sequence_debug++;
ret = inp->initial_sequence_debug;
inp->initial_sequence_debug++;
return (ret);
}
if ((m->store_at + sizeof(u_long)) > SCTP_SIGNATURE_SIZE) {
/* Refill the random store */
sctp_fill_random_store(m);
retry:
store_at = inp->store_at;
new_store = store_at + sizeof(uint32_t);
if (new_store >= (SCTP_SIGNATURE_SIZE - 3)) {
new_store = 0;
}
p = &m->random_store[(int)m->store_at];
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;
m->store_at += sizeof(uint32_t);
return (x);
}
uint32_t
sctp_select_a_tag(struct sctp_inpcb *m)
sctp_select_a_tag(struct sctp_inpcb *inp)
{
u_long x, not_done;
struct timeval now;
@ -843,12 +852,12 @@ sctp_select_a_tag(struct sctp_inpcb *m)
(void)SCTP_GETTIME_TIMEVAL(&now);
not_done = 1;
while (not_done) {
x = sctp_select_initial_TSN(&m->sctp_ep);
x = sctp_select_initial_TSN(&inp->sctp_ep);
if (x == 0) {
/* we never use 0 */
continue;
}
if (sctp_is_vtag_good(m, x, &now)) {
if (sctp_is_vtag_good(inp, x, &now)) {
not_done = 0;
}
}
@ -1758,6 +1767,15 @@ sctp_timeout_handler(void *t)
#endif
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_ASCONF_TMR, SCTP_SO_NOT_LOCKED);
break;
case SCTP_TIMER_TYPE_PRIM_DELETED:
if ((stcb == NULL) || (inp == NULL)) {
break;
}
if (sctp_delete_prim_timer(inp, stcb, net)) {
goto out_decr;
}
SCTP_STAT_INCR(sctps_timodelprim);
break;
case SCTP_TIMER_TYPE_AUTOCLOSE:
if ((stcb == NULL) || (inp == NULL)) {
@ -2152,6 +2170,13 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
}
tmr = &stcb->asoc.asconf_timer;
break;
case SCTP_TIMER_TYPE_PRIM_DELETED:
if ((stcb == NULL) || (net != NULL)) {
return;
}
to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
tmr = &stcb->asoc.delete_prim_timer;
break;
case SCTP_TIMER_TYPE_AUTOCLOSE:
if (stcb == NULL) {
return;
@ -2330,6 +2355,12 @@ sctp_timer_stop(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
}
tmr = &stcb->asoc.asconf_timer;
break;
case SCTP_TIMER_TYPE_PRIM_DELETED:
if (stcb == NULL) {
return;
}
tmr = &stcb->asoc.delete_prim_timer;
break;
case SCTP_TIMER_TYPE_AUTOCLOSE:
if (stcb == NULL) {
return;
@ -5629,6 +5660,11 @@ sctp_sorecvmsg(struct socket *so,
SOCKBUF_LOCK(&so->so_rcv);
hold_sblock = 1;
}
if ((copied_so_far) && (control->length == 0) &&
(sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE))
) {
goto release;
}
if (so->so_rcv.sb_cc <= control->held_length) {
error = sbwait(&so->so_rcv);
if (error) {
@ -6339,9 +6375,11 @@ sctp_local_addr_count(struct sctp_tcb *stcb)
ipv4_addr_legal = 1;
}
SCTP_IPI_ADDR_LOCK();
vrf = sctp_find_vrf(stcb->asoc.vrf_id);
if (vrf == NULL) {
/* no vrf, no addresses */
SCTP_IPI_ADDR_UNLOCK();
return (0);
}
if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
@ -6417,6 +6455,7 @@ sctp_local_addr_count(struct sctp_tcb *stcb)
count++;
}
}
SCTP_IPI_ADDR_UNLOCK();
return (count);
}

View File

@ -315,13 +315,124 @@ sctp6_notify_mbuf(struct sctp_inpcb *inp, struct icmp6_hdr *icmp6,
}
static void
sctp6_notify(struct sctp_inpcb *inp,
struct icmp6_hdr *icmph,
struct sctphdr *sh,
struct sockaddr *to,
struct sctp_tcb *stcb,
struct sctp_nets *net)
{
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
/* protection */
int reason;
if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
(sh == NULL) || (to == NULL)) {
if (stcb)
SCTP_TCB_UNLOCK(stcb);
return;
}
/* First job is to verify the vtag matches what I would send */
if (ntohl(sh->v_tag) != (stcb->asoc.peer_vtag)) {
SCTP_TCB_UNLOCK(stcb);
return;
}
if (icmph->icmp6_type != ICMP_UNREACH) {
/* We only care about unreachable */
SCTP_TCB_UNLOCK(stcb);
return;
}
if ((icmph->icmp6_code == ICMP_UNREACH_NET) ||
(icmph->icmp6_code == ICMP_UNREACH_HOST) ||
(icmph->icmp6_code == ICMP_UNREACH_NET_UNKNOWN) ||
(icmph->icmp6_code == ICMP_UNREACH_HOST_UNKNOWN) ||
(icmph->icmp6_code == ICMP_UNREACH_ISOLATED) ||
(icmph->icmp6_code == ICMP_UNREACH_NET_PROHIB) ||
(icmph->icmp6_code == ICMP_UNREACH_HOST_PROHIB) ||
(icmph->icmp6_code == ICMP_UNREACH_FILTER_PROHIB)) {
/*
* Hmm reachablity problems we must examine closely. If its
* not reachable, we may have lost a network. Or if there is
* NO protocol at the other end named SCTP. well we consider
* it a OOTB abort.
*/
if (net->dest_state & SCTP_ADDR_REACHABLE) {
/* Ok that destination is NOT reachable */
SCTP_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;
/*
* JRS 5/14/07 - If a destination is unreachable,
* the PF bit is turned off. This allows an
* unambiguous use of the PF bit for destinations
* that are reachable but potentially failed. If the
* destination is set to the unreachable state, also
* set the destination to the PF state.
*/
/*
* Add debug message here if destination is not in
* PF state.
*/
/* Stop any running T3 timers here? */
if (sctp_cmt_on_off && sctp_cmt_pf) {
net->dest_state &= ~SCTP_ADDR_PF;
SCTPDBG(SCTP_DEBUG_TIMER4, "Destination %p moved from PF to unreachable.\n",
net);
}
net->error_count = net->failure_threshold + 1;
sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
stcb, SCTP_FAILED_THRESHOLD,
(void *)net, SCTP_SO_NOT_LOCKED);
}
SCTP_TCB_UNLOCK(stcb);
} else if ((icmph->icmp6_code == ICMP_UNREACH_PROTOCOL) ||
(icmph->icmp6_code == ICMP_UNREACH_PORT)) {
/*
* Here the peer is either playing tricks on us, including
* an address that belongs to someone who does not support
* SCTP OR was a userland implementation that shutdown and
* now is dead. In either case treat it like a OOTB abort
* with no TCB
*/
reason = SCTP_PEER_FAULTY;
sctp_abort_notification(stcb, reason, SCTP_SO_NOT_LOCKED);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(inp);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
#endif
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_2);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
/* SCTP_TCB_UNLOCK(stcb); MT: I think this is not needed. */
#endif
/* no need to unlock here, since the TCB is gone */
} else {
SCTP_TCB_UNLOCK(stcb);
}
}
void
sctp6_ctlinput(int cmd, struct sockaddr *pktdst, void *d)
{
struct sctphdr sh;
struct ip6ctlparam *ip6cp = NULL;
uint32_t vrf_id;
int cm;
vrf_id = SCTP_DEFAULT_VRFID;
@ -381,12 +492,7 @@ sctp6_ctlinput(int cmd, struct sockaddr *pktdst, void *d)
net);
/* inp's ref-count reduced && stcb unlocked */
} else {
if (cmd == PRC_HOSTDEAD) {
cm = EHOSTUNREACH;
} else {
cm = inet6ctlerrmap[cmd];
}
sctp_notify(inp, cm, &sh,
sctp6_notify(inp, ip6cp->ip6c_icmp6, &sh,
(struct sockaddr *)&final,
stcb, net);
/* inp's ref-count reduced && stcb unlocked */
@ -489,8 +595,10 @@ sctp6_abort(struct socket *so)
uint32_t flags;
inp = (struct sctp_inpcb *)so->so_pcb;
if (inp == 0)
if (inp == 0) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return;
}
sctp_must_try_again:
flags = inp->sctp_flags;
#ifdef SCTP_LOG_CLOSING
@ -627,11 +735,12 @@ sctp6_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
sin6_p = (struct sockaddr_in6 *)addr;
if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr))
if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) {
/* can't bind v4-mapped addrs either! */
/* NOTE: we don't support SIIT */
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return EINVAL;
return EINVAL;
}
}
}
error = sctp_inpcb_bind(so, addr, NULL, p);