1) Fixes on a number of different collision case LOR's.

2) Fix all "magic numbers" to be constants.
3) A collision case that would generate two associations to
   the same peer due to a missing lock is fixed.
4) Added tracking of where timers are stopped.
Approved by:	gnn
This commit is contained in:
Randall Stewart 2006-12-14 17:02:55 +00:00
parent e0ccd04489
commit a5d547add3
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=165220
17 changed files with 1087 additions and 406 deletions

View File

@ -338,7 +338,8 @@ sctp_process_asconf_add_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph,
#endif /* SCTP_DEBUG */
}
/* add the address */
if (sctp_add_remote_addr(stcb, sa, 0, 6) != 0) {
if (sctp_add_remote_addr(stcb, sa, SCTP_DONOT_SETSCOPE,
SCTP_ADDR_DYNAMIC_ADDED) != 0) {
#ifdef SCTP_DEBUG
if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
printf("process_asconf_add_ip: error adding address\n");
@ -354,7 +355,7 @@ sctp_process_asconf_add_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph,
m_reply =
sctp_asconf_success_response(aph->correlation_id);
}
sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, NULL);
sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_ASCONF + SCTP_LOC_1);
sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, NULL);
}
@ -1024,7 +1025,7 @@ sctp_asconf_cleanup(struct sctp_tcb *stcb, struct sctp_nets *net)
/*
* clear out any existing asconfs going out
*/
sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net);
sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_ASCONF + SCTP_LOC_2);
stcb->asoc.asconf_seq_out++;
/* remove the old ASCONF on our outbound queue */
sctp_toss_old_asconf(stcb);
@ -1500,7 +1501,7 @@ sctp_handle_asconf_ack(struct mbuf *m, int offset,
return;
}
/* stop our timer */
sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net);
sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_ASCONF + SCTP_LOC_3);
/* process the ASCONF-ACK contents */
ack_length = ntohs(cp->ch.chunk_length) -

View File

@ -151,8 +151,9 @@ __FBSDID("$FreeBSD$");
#define SCTP_RANDY_STUFF1 103
#define SCTP_STRMOUT_LOG_ASSIGN 104
#define SCTP_STRMOUT_LOG_SEND 105
#define SCTP_LOG_MAX_TYPES 106
#define SCTP_FLIGHT_LOG_DOWN 106
#define SCTP_FLIGHT_LOG_UP 107
#define SCTP_LOG_MAX_TYPES 108
/*
* To turn on various logging, you must first define SCTP_STAT_LOGGING. Then
* to get something to log you define one of the logging defines i.e.
@ -740,6 +741,77 @@ __FBSDID("$FreeBSD$");
*/
#define SCTP_DEFAULT_SPLIT_POINT_MIN 1452
/* ABORT CODES and other tell-tale location
* codes are generated by adding the below
* to the instance id.
*/
/* File defines */
#define SCTP_FROM_SCTP_INPUT 0x10000000
#define SCTP_FROM_SCTP_PCB 0x20000000
#define SCTP_FROM_SCTP_INDATA 0x30000000
#define SCTP_FROM_SCTP_TIMER 0x40000000
#define SCTP_FROM_SCTP_USRREQ 0x50000000
#define SCTP_FROM_SCTPUTIL 0x60000000
#define SCTP_FROM_SCTP6_USRREQ 0x70000000
#define SCTP_FROM_SCTP_ASCONF 0x80000000
#define SCTP_FROM_SCTP_OUTPUT 0x90000000
#define SCTP_FROM_SCTP_PEELOFF 0xa0000000
/* Location ID's */
#define SCTP_LOC_1 0x00000001
#define SCTP_LOC_2 0x00000002
#define SCTP_LOC_3 0x00000003
#define SCTP_LOC_4 0x00000004
#define SCTP_LOC_5 0x00000005
#define SCTP_LOC_6 0x00000006
#define SCTP_LOC_7 0x00000007
#define SCTP_LOC_8 0x00000008
#define SCTP_LOC_9 0x00000009
#define SCTP_LOC_10 0x0000000a
#define SCTP_LOC_11 0x0000000b
#define SCTP_LOC_12 0x0000000c
#define SCTP_LOC_13 0x0000000d
#define SCTP_LOC_14 0x0000000e
#define SCTP_LOC_15 0x0000000f
#define SCTP_LOC_16 0x00000010
#define SCTP_LOC_17 0x00000011
#define SCTP_LOC_18 0x00000012
#define SCTP_LOC_19 0x00000013
#define SCTP_LOC_20 0x00000014
#define SCTP_LOC_21 0x00000015
#define SCTP_LOC_22 0x00000016
#define SCTP_LOC_23 0x00000017
#define SCTP_LOC_24 0x00000018
#define SCTP_LOC_25 0x00000019
#define SCTP_LOC_26 0x0000001a
#define SCTP_LOC_27 0x0000001b
#define SCTP_LOC_28 0x0000001c
#define SCTP_LOC_29 0x0000001d
#define SCTP_LOC_30 0x0000001e
#define SCTP_LOC_31 0x0000001f
#define SCTP_LOC_32 0x00000020
/* Free assoc codes */
#define SCTP_NORMAL_PROC 0
#define SCTP_PCBFREE_NOFORCE 1
#define SCTP_PCBFREE_FORCE 2
/* From codes for adding addresses */
#define SCTP_ADDR_IS_CONFIRMED 8
#define SCTP_ADDR_DYNAMIC_ADDED 6
#define SCTP_IN_COOKIE_PROC 100
#define SCTP_ALLOC_ASOC 1
#define SCTP_LOAD_ADDR_2 2
#define SCTP_LOAD_ADDR_3 3
#define SCTP_LOAD_ADDR_4 4
#define SCTP_LOAD_ADDR_5 5
#define SCTP_DONOT_SETSCOPE 0
#define SCTP_DO_SETSCOPE 1
/* This value determines the default for when
* we try to add more on the send queue., if
* there is room. This prevents us from cycling

View File

@ -28,7 +28,7 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
/* $kejKAME: sctp_indata.c,v 1.36 2005/03/06 16:04:17 itojun Exp $ */
/* $KAME: sctp_indata.c,v 1.36 2005/03/06 16:04:17 itojun Exp $ */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@ -623,12 +623,13 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb, struct sctp_association *asoc,
ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
ph->param_length = htons(oper->m_len);
ippp = (uint32_t *) (ph + 1);
*ippp = htonl(0x00000001);
*ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_1);
ippp++;
*ippp = control->sinfo_tsn;
ippp++;
*ippp = ((control->sinfo_stream << 16) | control->sinfo_ssn);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_1;
sctp_abort_an_association(stcb->sctp_ep, stcb,
SCTP_PEER_FAULTY, oper);
@ -884,13 +885,14 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
ph->param_length = htons(oper->m_len);
ippp = (uint32_t *) (ph + 1);
*ippp = htonl(0x10000001);
*ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_2);
ippp++;
*ippp = chk->rec.data.TSN_seq;
ippp++;
*ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_2;
sctp_abort_an_association(stcb->sctp_ep, stcb,
SCTP_PEER_FAULTY, oper);
*abort_flag = 1;
@ -920,12 +922,13 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
ph->param_length = htons(oper->m_len);
ippp = (uint32_t *) (ph + 1);
*ippp = htonl(0x10000002);
*ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_3);
ippp++;
*ippp = chk->rec.data.TSN_seq;
ippp++;
*ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_3;
sctp_abort_an_association(stcb->sctp_ep, stcb,
SCTP_PEER_FAULTY, oper);
*abort_flag = 1;
@ -960,12 +963,13 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
ph->param_length =
htons(oper->m_len);
ippp = (uint32_t *) (ph + 1);
*ippp = htonl(0x10000003);
*ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_4);
ippp++;
*ippp = chk->rec.data.TSN_seq;
ippp++;
*ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_4;
sctp_abort_an_association(stcb->sctp_ep,
stcb, SCTP_PEER_FAULTY, oper);
*abort_flag = 1;
@ -997,13 +1001,14 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
ph->param_length =
htons(oper->m_len);
ippp = (uint32_t *) (ph + 1);
*ippp = htonl(0x10000004);
*ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_5);
ippp++;
*ippp = chk->rec.data.TSN_seq;
ippp++;
*ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_5;
sctp_abort_an_association(stcb->sctp_ep,
stcb, SCTP_PEER_FAULTY, oper);
*abort_flag = 1;
@ -1099,13 +1104,14 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
ph->param_length =
htons(oper->m_len);
ippp = (uint32_t *) (ph + 1);
*ippp = htonl(0x10000005);
*ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_6);
ippp++;
*ippp = chk->rec.data.TSN_seq;
ippp++;
*ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_6;
sctp_abort_an_association(stcb->sctp_ep,
stcb, SCTP_PEER_FAULTY, oper);
*abort_flag = 1;
@ -1140,12 +1146,13 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
ph->param_length =
htons(oper->m_len);
ippp = (uint32_t *) (ph + 1);
*ippp = htonl(0x10000006);
*ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_7);
ippp++;
*ippp = chk->rec.data.TSN_seq;
ippp++;
*ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_7;
sctp_abort_an_association(stcb->sctp_ep,
stcb, SCTP_PEER_FAULTY, oper);
@ -1182,12 +1189,13 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
ph->param_length =
htons(oper->m_len);
ippp = (uint32_t *) (ph + 1);
*ippp = htonl(0x10000007);
*ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_8);
ippp++;
*ippp = chk->rec.data.TSN_seq;
ippp++;
*ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_8;
sctp_abort_an_association(stcb->sctp_ep,
stcb, SCTP_PEER_FAULTY, oper);
@ -1220,13 +1228,14 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
ph->param_length =
htons(oper->m_len);
ippp = (uint32_t *) (ph + 1);
*ippp = htonl(0x10000008);
*ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_9);
ippp++;
*ippp = chk->rec.data.TSN_seq;
ippp++;
*ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_9;
sctp_abort_an_association(stcb->sctp_ep,
stcb, SCTP_PEER_FAULTY, oper);
@ -1269,12 +1278,13 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
ph->param_length =
htons(oper->m_len);
ippp = (uint32_t *) (ph + 1);
*ippp = htonl(0x10000009);
*ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_10);
ippp++;
*ippp = chk->rec.data.TSN_seq;
ippp++;
*ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_10;
sctp_abort_an_association(stcb->sctp_ep,
stcb, SCTP_PEER_FAULTY, oper);
@ -1313,13 +1323,14 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
ph->param_length =
htons(oper->m_len);
ippp = (uint32_t *) (ph + 1);
*ippp = htonl(0x1000000a);
*ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_11);
ippp++;
*ippp = chk->rec.data.TSN_seq;
ippp++;
*ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_11;
sctp_abort_an_association(stcb->sctp_ep,
stcb, SCTP_PEER_FAULTY, oper);
@ -1355,13 +1366,14 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
ph->param_length =
htons(oper->m_len);
ippp = (uint32_t *) (ph + 1);
*ippp = htonl(0x1000000b);
*ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_12);
ippp++;
*ippp = chk->rec.data.TSN_seq;
ippp++;
*ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_12;
sctp_abort_an_association(stcb->sctp_ep,
stcb, SCTP_PEER_FAULTY, oper);
@ -1398,12 +1410,13 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
ph->param_length =
htons(oper->m_len);
ippp = (uint32_t *) (ph + 1);
*ippp = htonl(0x1000000c);
*ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_13);
ippp++;
*ippp = chk->rec.data.TSN_seq;
ippp++;
*ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_13;
sctp_abort_an_association(stcb->sctp_ep,
stcb, SCTP_PEER_FAULTY, oper);
@ -1683,13 +1696,14 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
ph->param_length = htons(oper->m_len);
ippp = (uint32_t *) (ph + 1);
*ippp = htonl(0x20000001);
*ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_14);
ippp++;
*ippp = tsn;
ippp++;
*ippp = ((strmno << 16) | strmseq);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_14;
sctp_abort_an_association(stcb->sctp_ep, stcb,
SCTP_PEER_FAULTY, oper);
*abort_flag = 1;
@ -1807,12 +1821,13 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
asoc->last_flags_delivered = ch->ch.chunk_flags;
asoc->last_strm_seq_delivered = strmseq;
asoc->last_strm_no_delivered = strmno;
asoc->tsn_last_delivered = tsn;
if (end) {
/* clean up the flags and such */
asoc->fragmented_delivery_inprogress = 0;
asoc->strmin[strmno].last_sequence_delivered++;
if ((ch->ch.chunk_flags & SCTP_DATA_UNORDERED) == 0) {
asoc->strmin[strmno].last_sequence_delivered++;
}
stcb->asoc.control_pdapi = NULL;
}
control = NULL;
@ -1900,12 +1915,13 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
ph->param_length = htons(oper->m_len);
ippp = (uint32_t *) (ph + 1);
*ippp = htonl(0x20000002);
*ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_15);
ippp++;
*ippp = tsn;
ippp++;
*ippp = ((strmno << 16) | strmseq);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_15;
sctp_abort_an_association(stcb->sctp_ep, stcb,
SCTP_PEER_FAULTY, oper);
@ -1934,12 +1950,13 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
ph->param_length =
htons(oper->m_len);
ippp = (uint32_t *) (ph + 1);
*ippp = htonl(0x20000003);
*ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_16);
ippp++;
*ippp = tsn;
ippp++;
*ippp = ((strmno << 16) | strmseq);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_16;
sctp_abort_an_association(stcb->sctp_ep,
stcb, SCTP_PEER_FAULTY, oper);
@ -1977,12 +1994,13 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
ph->param_length =
htons(oper->m_len);
ippp = (uint32_t *) (ph + 1);
*ippp = htonl(0x20000004);
*ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_17);
ippp++;
*ippp = tsn;
ippp++;
*ippp = ((strmno << 16) | strmseq);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_17;
sctp_abort_an_association(stcb->sctp_ep,
stcb, SCTP_PEER_FAULTY, oper);
@ -2062,6 +2080,11 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
/* Into the re-assembly queue */
sctp_queue_data_for_reasm(stcb, asoc, chk, abort_flag);
if (*abort_flag) {
/*
* the assoc is now gone and chk was put onto the
* reasm queue, which has all been freed.
*/
*m = NULL;
return (0);
}
}
@ -2190,7 +2213,7 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort
if (compare_with_wrap(asoc->cumulative_tsn,
asoc->highest_tsn_inside_map,
MAX_TSN)) {
#ifdef INVARIENTS
#ifdef INVARIANTS
panic("huh, cumack greater than high-tsn in map");
#else
printf("huh, cumack greater than high-tsn in map - should panic?\n");
@ -2346,7 +2369,7 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort
*/
if (callout_pending(&stcb->asoc.dack_timer.timer)) {
sctp_timer_stop(SCTP_TIMER_TYPE_RECV,
stcb->sctp_ep, stcb, NULL);
stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_INDATA + SCTP_LOC_18);
}
sctp_send_shutdown(stcb, stcb->asoc.primary_destination);
sctp_send_sack(stcb);
@ -2585,11 +2608,12 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
ph->param_length = htons(op_err->m_len);
ippp = (uint32_t *) (ph + 1);
*ippp = htonl(0x30000001);
*ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_19);
ippp++;
*ippp = asoc->cumulative_tsn;
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_19;
sctp_abort_association(inp, stcb, m, iphlen, sh,
op_err);
return (2);
@ -2988,73 +3012,47 @@ sctp_handle_segments(struct sctp_tcb *stcb, struct sctp_association *asoc,
frag_end,
SCTP_LOG_TSN_ACKED);
#endif
#ifdef SCTP_FLIGHT_LOGGING
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN,
tp1->whoTo->flight_size,
tp1->book_size,
(uintptr_t) stcb,
tp1->rec.data.TSN_seq);
#endif
if (tp1->whoTo->flight_size >= tp1->book_size)
tp1->whoTo->flight_size -= tp1->book_size;
else
tp1->whoTo->flight_size = 0;
if (asoc->total_flight >= tp1->book_size) {
asoc->total_flight -= tp1->book_size;
if (asoc->total_flight_count > 0)
asoc->total_flight_count--;
} else {
asoc->total_flight = 0;
asoc->total_flight_count = 0;
}
if (tp1->rec.data.chunk_was_revoked == 0) {
tp1->whoTo->net_ack += tp1->send_size;
if (tp1->snd_count < 2) {
/*
* Revoked
* chunks
* don't
* count,
* since we
* previously
* pulled
* them from
* the fs.
*/
if (tp1->whoTo->flight_size >= tp1->book_size)
tp1->whoTo->flight_size -= tp1->book_size;
else
tp1->whoTo->flight_size = 0;
if (asoc->total_flight >= tp1->book_size) {
asoc->total_flight -= tp1->book_size;
if (asoc->total_flight_count > 0)
asoc->total_flight_count--;
} else {
asoc->total_flight = 0;
asoc->total_flight_count = 0;
}
* True
* non-retran
* smited
* chunk */
tp1->whoTo->net_ack2 += tp1->send_size;
tp1->whoTo->net_ack += tp1->send_size;
if (tp1->snd_count < 2) {
/*
* Tru
* e
* no
* n
* -r
* e
* tr
* a
* ns
* m
* it
* e
* d
* ch
* u
* nk
* */
tp1->whoTo->net_ack2 += tp1->send_size;
/*
* upd
*
* ate
*
* RTO
*
* too
* ? */
if (tp1->do_rtt) {
tp1->whoTo->RTO =
sctp_calculate_rto(stcb,
asoc,
tp1->whoTo,
&tp1->sent_rcv_time);
tp1->whoTo->rto_pending = 0;
tp1->do_rtt = 0;
}
/*
* update RTO
* too ? */
if (tp1->do_rtt) {
tp1->whoTo->RTO =
sctp_calculate_rto(stcb,
asoc,
tp1->whoTo,
&tp1->sent_rcv_time);
tp1->whoTo->rto_pending = 0;
tp1->do_rtt = 0;
}
}
}
@ -3117,14 +3115,15 @@ sctp_check_for_revoked(struct sctp_association *asoc, uint32_t cumack,
*/
if (tp1->sent == SCTP_DATAGRAM_ACKED) {
/* it has been revoked */
/*
* We do NOT add back to flight size here
* since it is really NOT in flight. Resend
* (when/if it occurs will add to flight
* size
*/
tp1->sent = SCTP_DATAGRAM_SENT;
tp1->rec.data.chunk_was_revoked = 1;
/*
* We must add this stuff back in to assure
* timers and such get started.
*/
tp1->whoTo->flight_size += tp1->book_size;
asoc->total_flight_count++;
asoc->total_flight += tp1->book_size;
tot_revoked++;
#ifdef SCTP_SACK_LOGGING
sctp_log_sack(asoc->last_acked_seq,
@ -3522,7 +3521,13 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
tp1->do_rtt = 0;
}
/* fix counts and things */
#ifdef SCTP_FLIGHT_LOGGING
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN,
tp1->whoTo->flight_size,
tp1->book_size,
(uintptr_t) stcb,
tp1->rec.data.TSN_seq);
#endif
tp1->whoTo->net_ack++;
if (tp1->whoTo->flight_size >= tp1->book_size)
tp1->whoTo->flight_size -= tp1->book_size;
@ -3895,7 +3900,8 @@ sctp_cwnd_update(struct sctp_tcb *stcb,
*/
if (callout_pending(&net->fr_timer.timer)) {
SCTP_STAT_INCR(sctps_earlyfrstpidsck2);
sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net);
sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net,
SCTP_FROM_SCTP_INDATA + SCTP_LOC_20);
}
SCTP_STAT_INCR(sctps_earlyfrstrid);
sctp_timer_start(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net);
@ -3903,7 +3909,8 @@ sctp_cwnd_update(struct sctp_tcb *stcb,
/* No, stop it if its running */
if (callout_pending(&net->fr_timer.timer)) {
SCTP_STAT_INCR(sctps_earlyfrstpidsck3);
sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net);
sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net,
SCTP_FROM_SCTP_INDATA + SCTP_LOC_21);
}
}
}
@ -4071,6 +4078,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
struct sctp_nets *net;
struct sctp_association *asoc;
struct sctp_tmit_chunk *tp1, *tp2;
int j;
SCTP_TCB_LOCK_ASSERT(stcb);
asoc = &stcb->asoc;
@ -4101,16 +4109,14 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
* now no-longer in flight. Higher
* values may occur during marking
*/
if (tp1->rec.data.chunk_was_revoked == 1) {
/*
* If its been revoked, and
* now ack'd we do NOT take
* away fs etc. since when
* it is retransmitted we
* clear this flag.
*/
goto skip_fs_update;
}
#ifdef SCTP_FLIGHT_LOGGING
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN,
tp1->whoTo->flight_size,
tp1->book_size,
(uintptr_t) stcb,
tp1->rec.data.TSN_seq);
#endif
if (tp1->whoTo->flight_size >= tp1->book_size) {
tp1->whoTo->flight_size -= tp1->book_size;
} else {
@ -4147,7 +4153,6 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
sctp_log_cwnd(stcb, tp1->whoTo, tp1->rec.data.TSN_seq, SCTP_CWND_LOG_FROM_SACK);
#endif
}
skip_fs_update:
if (tp1->sent == SCTP_DATAGRAM_RESEND) {
sctp_ucount_decr(asoc->sent_queue_retran_cnt);
}
@ -4259,6 +4264,8 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
asoc->peers_rwnd = 0;
}
/* Now assure a timer where data is queued at */
again:
j = 0;
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
if (net->flight_size) {
int to_ticks;
@ -4268,22 +4275,48 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
} else {
to_ticks = MSEC_TO_TICKS(net->RTO);
}
j++;
callout_reset(&net->rxt_timer.timer, to_ticks,
sctp_timeout_handler, &net->rxt_timer);
} else {
if (callout_pending(&net->rxt_timer.timer)) {
sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
stcb, net);
stcb, net,
SCTP_FROM_SCTP_INDATA + SCTP_LOC_22);
}
if (sctp_early_fr) {
if (callout_pending(&net->fr_timer.timer)) {
SCTP_STAT_INCR(sctps_earlyfrstpidsck4);
sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net);
sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net,
SCTP_FROM_SCTP_INDATA + SCTP_LOC_23);
}
}
}
}
if ((j == 0) && (!TAILQ_EMPTY(&asoc->sent_queue)) && (asoc->sent_queue_retran_cnt == 0)) {
/* huh, this should not happen */
#ifdef INVARIANTS
panic("Flight size incorrect? fixing??");
#else
printf("Flight size incorrect? fixing\n");
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
net->flight_size = 0;
}
asoc->total_flight = 0;
asoc->total_flight_count = 0;
asoc->sent_queue_retran_cnt = 0;
TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
if (tp1->sent < SCTP_DATAGRAM_RESEND) {
tp1->whoTo->flight_size += tp1->book_size;
asoc->total_flight += tp1->book_size;
asoc->total_flight_count++;
} else if (tp1->sent == SCTP_DATAGRAM_RESEND) {
asoc->sent_queue_retran_cnt++;
}
}
#endif
goto again;
}
/**********************************/
/* Now what about shutdown issues */
/**********************************/
@ -4332,8 +4365,9 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
ph->param_length = htons(oper->m_len);
ippp = (uint32_t *) (ph + 1);
*ippp = htonl(0x30000003);
*ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_24);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_24;
sctp_abort_an_association(stcb->sctp_ep, stcb, SCTP_RESPONSE_TO_USER_REQ, oper);
} else {
asoc->state = SCTP_STATE_SHUTDOWN_SENT;
@ -4502,8 +4536,9 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb,
ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
ph->param_length = htons(oper->m_len);
ippp = (uint32_t *) (ph + 1);
*ippp = htonl(0x30000002);
*ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_25);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_25;
sctp_abort_an_association(stcb->sctp_ep, stcb, SCTP_PEER_FAULTY, oper);
return;
}
@ -4536,11 +4571,12 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb,
/* stop any timers */
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
stcb, net);
stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_26);
if (sctp_early_fr) {
if (callout_pending(&net->fr_timer.timer)) {
SCTP_STAT_INCR(sctps_earlyfrstpidsck1);
sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net);
sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net,
SCTP_FROM_SCTP_INDATA + SCTP_LOC_26);
}
}
net->partial_bytes_acked = 0;
@ -4601,16 +4637,13 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb,
tp1->whoTo->dest_state &=
~SCTP_ADDR_UNCONFIRMED;
}
if (tp1->rec.data.chunk_was_revoked == 1) {
/*
* If its been revoked, and
* now ack'd we do NOT take
* away fs etc. since when
* it is retransmitted we
* clear this flag.
*/
goto skip_fs_update;
}
#ifdef SCTP_FLIGHT_LOGGING
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN,
tp1->whoTo->flight_size,
tp1->book_size,
(uintptr_t) stcb,
tp1->rec.data.TSN_seq);
#endif
if (tp1->whoTo->flight_size >= tp1->book_size) {
tp1->whoTo->flight_size -= tp1->book_size;
} else {
@ -4648,7 +4681,6 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb,
tp1->do_rtt = 0;
}
}
skip_fs_update:
/*
* CMT: CUCv2 algorithm. From the
* cumack'd TSNs, for each TSN being
@ -4746,14 +4778,15 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb,
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
if (net->new_pseudo_cumack)
sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
stcb, net);
stcb, net,
SCTP_FROM_SCTP_INDATA + SCTP_LOC_27);
}
} else {
if (accum_moved) {
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
stcb, net);
stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_28);
}
}
}
@ -4868,6 +4901,10 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb,
if ((tp1->sent > SCTP_DATAGRAM_RESEND) &&
(tp1->sent < SCTP_FORWARD_TSN_SKIP)) {
tp1->sent = SCTP_DATAGRAM_SENT;
tp1->rec.data.chunk_was_revoked = 1;
tp1->whoTo->flight_size += tp1->book_size;
asoc->total_flight_count++;
asoc->total_flight += tp1->book_size;
cnt_revoked++;
}
}
@ -4892,11 +4929,12 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb,
if (sctp_early_fr) {
if (callout_pending(&net->fr_timer.timer)) {
SCTP_STAT_INCR(sctps_earlyfrstpidsck4);
sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net);
sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net,
SCTP_FROM_SCTP_INDATA + SCTP_LOC_29);
}
}
sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
stcb, net);
stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_30);
net->flight_size = 0;
net->partial_bytes_acked = 0;
}
@ -4959,8 +4997,9 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb,
ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
ph->param_length = htons(oper->m_len);
ippp = (uint32_t *) (ph + 1);
*ippp = htonl(0x30000003);
*ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_31);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_31;
sctp_abort_an_association(stcb->sctp_ep, stcb, SCTP_RESPONSE_TO_USER_REQ, oper);
return;
} else {
@ -5116,7 +5155,7 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb,
asoc->nonce_resync_tsn = asoc->fast_recovery_tsn + 1;
sctp_timer_stop(SCTP_TIMER_TYPE_SEND,
stcb->sctp_ep, stcb, net);
stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_32);
sctp_timer_start(SCTP_TIMER_TYPE_SEND,
stcb->sctp_ep, stcb, net);
}
@ -5220,12 +5259,39 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb,
* Now we must setup so we have a timer up for anyone with
* outstanding data.
*/
again:
j = 0;
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
if (net->flight_size) {
j++;
sctp_timer_start(SCTP_TIMER_TYPE_SEND,
stcb->sctp_ep, stcb, net);
}
}
if ((j == 0) && (!TAILQ_EMPTY(&asoc->sent_queue)) && (asoc->sent_queue_retran_cnt == 0)) {
/* huh, this should not happen */
#ifdef INVARIANTS
panic("Flight size incorrect? fixing??");
#else
printf("Flight size incorrect? fixing??\n");
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
net->flight_size = 0;
}
asoc->total_flight = 0;
asoc->total_flight_count = 0;
asoc->sent_queue_retran_cnt = 0;
TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
if (tp1->sent < SCTP_DATAGRAM_RESEND) {
tp1->whoTo->flight_size += tp1->book_size;
asoc->total_flight += tp1->book_size;
asoc->total_flight_count++;
} else if (tp1->sent == SCTP_DATAGRAM_RESEND) {
asoc->sent_queue_retran_cnt++;
}
}
#endif
goto again;
}
#ifdef SCTP_SACK_RWND_LOGGING
sctp_misc_ints(SCTP_SACK_RWND_UPDATE,
a_rwnd,

View File

@ -100,19 +100,34 @@ extern uint32_t sctp_debug_on;
#endif
struct sctp_foo_stuff sctp_logoff[30000];
int sctp_logoff_stuff = 0;
static void
sctp_stop_all_cookie_timers(struct sctp_tcb *stcb)
{
struct sctp_nets *net;
/*
* This now not only stops all cookie timers it also stops any INIT
* timers as well. This will make sure that the timers are stopped
* in all collision cases.
*/
SCTP_TCB_LOCK_ASSERT(stcb);
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
if ((callout_pending(&net->rxt_timer.timer)) &&
(net->rxt_timer.type == SCTP_TIMER_TYPE_COOKIE)) {
if (net->rxt_timer.type == SCTP_TIMER_TYPE_COOKIE) {
sctp_timer_stop(SCTP_TIMER_TYPE_COOKIE,
stcb->sctp_ep,
stcb,
net);
net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_1);
} else if (net->rxt_timer.type == SCTP_TIMER_TYPE_INIT) {
sctp_timer_stop(SCTP_TIMER_TYPE_INIT,
stcb->sctp_ep,
stcb,
net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_2);
}
}
}
@ -372,7 +387,7 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset,
* No sense in further INIT's since we will get the
* same param back
*/
sctp_free_assoc(stcb->sctp_ep, stcb, 0);
sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3);
}
return (-1);
}
@ -415,7 +430,10 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset,
* primary.
*/
sctp_timer_stop(SCTP_TIMER_TYPE_INIT, stcb->sctp_ep, stcb,
asoc->primary_destination);
asoc->primary_destination, SCTP_FROM_SCTP_INPUT + SCTP_LOC_4);
/* calculate the RTO */
net->RTO = sctp_calculate_rto(stcb, asoc, net, &asoc->time_entered);
retval = sctp_send_cookie_echo(m, offset, stcb, net);
if (retval < 0) {
@ -453,9 +471,6 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset,
}
return (retval);
}
/* calculate the RTO */
net->RTO = sctp_calculate_rto(stcb, asoc, net, &asoc->time_entered);
return (0);
}
@ -548,7 +563,7 @@ sctp_handle_abort(struct sctp_abort_chunk *cp,
/* ignore abort for addresses being deleted */
/* stop any receive timers */
sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, net);
sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_5);
/* notify user of the abort and clean up... */
sctp_abort_notification(stcb, 0);
/* free the tcb */
@ -557,7 +572,7 @@ sctp_handle_abort(struct sctp_abort_chunk *cp,
(SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
sctp_free_assoc(stcb->sctp_ep, stcb, 0);
sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_6);
#ifdef SCTP_DEBUG
if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
printf("sctp_handle_abort: finished\n");
@ -579,9 +594,9 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
#endif
if (stcb == NULL)
return;
if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) ||
(SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED)) {
asoc = &stcb->asoc;
if ((SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_WAIT) ||
(SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)) {
return;
}
if (ntohs(cp->ch.chunk_length) != sizeof(struct sctp_shutdown_chunk)) {
@ -590,18 +605,17 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
} else {
sctp_update_acked(stcb, cp, net, abort_flag);
}
asoc = &stcb->asoc;
if (stcb->asoc.control_pdapi) {
if (asoc->control_pdapi) {
/*
* With a normal shutdown we assume the end of last record.
*/
SCTP_INP_READ_LOCK(stcb->sctp_ep);
stcb->asoc.control_pdapi->end_added = 1;
stcb->asoc.control_pdapi->pdapi_aborted = 1;
if (stcb->asoc.control_pdapi->tail_mbuf) {
stcb->asoc.control_pdapi->tail_mbuf->m_flags |= M_EOR;
asoc->control_pdapi->end_added = 1;
asoc->control_pdapi->pdapi_aborted = 1;
if (asoc->control_pdapi->tail_mbuf) {
asoc->control_pdapi->tail_mbuf->m_flags |= M_EOR;
}
stcb->asoc.control_pdapi = NULL;
asoc->control_pdapi = NULL;
SCTP_INP_READ_UNLOCK(stcb->sctp_ep);
sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
}
@ -625,7 +639,7 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
* stop the shutdown timer, since we WILL move to
* SHUTDOWN-ACK-SENT.
*/
sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net);
sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_7);
}
/* Now are we there yet? */
some_on_streamwheel = 0;
@ -683,17 +697,17 @@ sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp,
SCTP_TCB_UNLOCK(stcb);
return;
}
if (stcb->asoc.control_pdapi) {
if (asoc->control_pdapi) {
/*
* With a normal shutdown we assume the end of last record.
*/
SCTP_INP_READ_LOCK(stcb->sctp_ep);
stcb->asoc.control_pdapi->end_added = 1;
stcb->asoc.control_pdapi->pdapi_aborted = 1;
if (stcb->asoc.control_pdapi->tail_mbuf) {
stcb->asoc.control_pdapi->tail_mbuf->m_flags |= M_EOR;
asoc->control_pdapi->end_added = 1;
asoc->control_pdapi->pdapi_aborted = 1;
if (asoc->control_pdapi->tail_mbuf) {
asoc->control_pdapi->tail_mbuf->m_flags |= M_EOR;
}
stcb->asoc.control_pdapi = NULL;
asoc->control_pdapi = NULL;
SCTP_INP_READ_UNLOCK(stcb->sctp_ep);
sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
}
@ -704,7 +718,7 @@ sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp,
sctp_report_all_outbound(stcb, 0);
}
/* stop the timer */
sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net);
sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_8);
/* send SHUTDOWN-COMPLETE */
sctp_send_shutdown_complete(stcb, net);
/* notify upper layer protocol */
@ -718,7 +732,8 @@ sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp,
}
SCTP_STAT_INCR_COUNTER32(sctps_shutdown);
/* free the TCB but first save off the ep */
sctp_free_assoc(stcb->sctp_ep, stcb, 0);
sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC,
SCTP_FROM_SCTP_INPUT + SCTP_LOC_9);
}
/*
@ -861,7 +876,7 @@ sctp_handle_error(struct sctp_chunkhdr *ch,
asoc->max_init_times) {
sctp_abort_notification(stcb, 0);
/* now free the asoc */
sctp_free_assoc(stcb->sctp_ep, stcb, 0);
sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_10);
return (-1);
}
/* blast back to INIT state */
@ -1040,7 +1055,7 @@ sctp_handle_init_ack(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
/*
* collapse the init timer back in case of a exponential
* backoff n
* backoff
*/
sctp_timer_start(SCTP_TIMER_TYPE_COOKIE, stcb->sctp_ep,
stcb, net);
@ -1090,7 +1105,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
struct sctp_init_chunk *init_cp, init_buf;
struct sctp_init_ack_chunk *initack_cp, initack_buf;
int chk_length;
int init_offset, initack_offset;
int init_offset, initack_offset, i;
int retval;
int spec_flag = 0;
@ -1179,9 +1194,8 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
/* Duplicate INIT case */
/* we have already processed the INIT so no problem */
sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb,
net);
sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net);
sctp_stop_all_cookie_timers(stcb);
net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_11);
sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_12);
/* update current state */
if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
asoc->state = SCTP_STATE_OPEN |
@ -1193,6 +1207,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
/* if ok, move to OPEN state */
asoc->state = SCTP_STATE_OPEN;
}
sctp_stop_all_cookie_timers(stcb);
if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
(inp->sctp_socket->so_qlimit == 0)
@ -1228,7 +1243,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
*/
break;
} /* end switch */
sctp_stop_all_cookie_timers(stcb);
/*
* We ignore the return code here.. not sure if we should
* somehow abort.. but we do have an existing asoc. This
@ -1240,6 +1255,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
return (NULL);
}
/* respond with a COOKIE-ACK */
sctp_toss_old_cookies(stcb, asoc);
sctp_send_cookie_ack(stcb);
return (stcb);
} /* end if */
@ -1259,8 +1275,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
* case B in Section 5.2.4 Table 2: MXAA or MOAA my info
* should be ok, re-accept peer info
*/
sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net);
sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_13);
sctp_stop_all_cookie_timers(stcb);
/*
* since we did not send a HB make sure we don't double
@ -1329,6 +1344,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
asoc->state = SCTP_STATE_OPEN;
}
sctp_stop_all_cookie_timers(stcb);
sctp_toss_old_cookies(stcb, asoc);
sctp_send_cookie_ack(stcb);
if (spec_flag) {
/*
@ -1352,17 +1368,27 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
/*
* case A in Section 5.2.4 Table 2: XXMM (peer restarted)
*/
sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net);
sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
/* temp code */
sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_14);
sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_15);
*sac_assoc_id = sctp_get_associd(stcb);
/* notify upper layer */
*notification = SCTP_NOTIFY_ASSOC_RESTART;
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_INP_INFO_WLOCK();
SCTP_INP_WLOCK(stcb->sctp_ep);
SCTP_TCB_LOCK(stcb);
atomic_add_int(&stcb->asoc.refcnt, -1);
/* send up all the data */
SCTP_TCB_SEND_LOCK(stcb);
sctp_report_all_outbound(stcb, 1);
sctp_report_all_outbound(stcb, 1);
for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
stcb->asoc.strmout[i].stream_no = i;
stcb->asoc.strmout[i].next_sequence_sent = 0;
stcb->asoc.strmout[i].last_msg_incomplete = 0;
}
/* process the INIT-ACK info (my info) */
asoc->my_vtag = ntohl(initack_cp->init.initiate_tag);
asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd);
@ -1402,6 +1428,9 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
asoc->mapping_array_size);
/* process the INIT info (peer's info) */
SCTP_TCB_SEND_UNLOCK(stcb);
SCTP_INP_WUNLOCK(stcb->sctp_ep);
SCTP_INP_INFO_WUNLOCK();
retval = sctp_process_init(init_cp, stcb, net);
if (retval < 0) {
return (NULL);
@ -1429,6 +1458,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
}
/* respond with a COOKIE-ACK */
sctp_stop_all_cookie_timers(stcb);
sctp_toss_old_cookies(stcb, asoc);
sctp_send_cookie_ack(stcb);
return (stcb);
@ -1584,14 +1614,14 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
/* process the INIT info (peer's info) */
retval = sctp_process_init(init_cp, stcb, *netp);
if (retval < 0) {
sctp_free_assoc(inp, stcb, 0);
sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_16);
return (NULL);
}
/* load all addresses */
if (sctp_load_addresses_from_init(stcb, m, iphlen,
init_offset + sizeof(struct sctp_init_chunk), initack_offset, sh,
init_src)) {
sctp_free_assoc(inp, stcb, 0);
sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_17);
return (NULL);
}
/*
@ -1612,7 +1642,7 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
if (sctp_debug_on & SCTP_DEBUG_AUTH1)
printf("COOKIE-ECHO: AUTH failed\n");
#endif /* SCTP_DEBUG */
sctp_free_assoc(inp, stcb, 0);
sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_18);
return (NULL);
} else {
/* remaining chunks checked... good to go */
@ -1632,12 +1662,9 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
} else {
asoc->state = SCTP_STATE_OPEN;
}
sctp_stop_all_cookie_timers(stcb);
SCTP_STAT_INCR_COUNTER32(sctps_passiveestab);
SCTP_STAT_INCR_GAUGE32(sctps_currestab);
sctp_stop_all_cookie_timers(stcb);
/* calculate the RTT */
(*netp)->RTO = sctp_calculate_rto(stcb, asoc, *netp,
&cookie->time_entered);
/*
* if we're doing ASCONFs, check to see if we have any new local
@ -1667,7 +1694,7 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
memcpy(&sin6->sin6_addr, cookie->laddress,
sizeof(sin6->sin6_addr));
} else {
sctp_free_assoc(inp, stcb, 0);
sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_19);
return (NULL);
}
@ -1710,6 +1737,9 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, inp, stcb, NULL);
}
/* respond with a COOKIE-ACK */
/* calculate the RTT */
(*netp)->RTO = sctp_calculate_rto(stcb, asoc, *netp,
&cookie->time_entered);
sctp_send_cookie_ack(stcb);
return (stcb);
}
@ -1723,7 +1753,7 @@ static struct mbuf *
sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
struct sctphdr *sh, struct sctp_cookie_echo_chunk *cp,
struct sctp_inpcb **inp_p, struct sctp_tcb **stcb, struct sctp_nets **netp,
int auth_skipped, uint32_t auth_offset, uint32_t auth_len)
int auth_skipped, uint32_t auth_offset, uint32_t auth_len, struct sctp_tcb **locked_tcb)
{
struct sctp_state_cookie *cookie;
struct sockaddr_in6 sin6;
@ -2014,6 +2044,31 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
if (l_inp != *inp_p) {
printf("Bad problem find_ep got a diff inp then special_locate?\n");
}
} else {
if (*locked_tcb == NULL) {
/*
* In this case we found the assoc only
* after we locked the create lock. This
* means we are in a colliding case and we
* must make sure that we unlock the tcb if
* its one of the cases where we throw away
* the incoming packets.
*/
*locked_tcb = *stcb;
/*
* We must also increment the inp ref count
* since the ref_count flags was set when we
* did not find the TCB, now we found it
* which reduces the refcount.. we must
* raise it back out to balance it all :-)
*/
SCTP_INP_INCR_REF((*stcb)->sctp_ep);
if ((*stcb)->sctp_ep != l_inp) {
printf("Huh? ep:%p diff then l_inp:%p?\n",
(*stcb)->sctp_ep, l_inp);
}
}
}
}
cookie_len -= SCTP_SIGNATURE_SIZE;
@ -2046,7 +2101,8 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
/* TSNH! Huh, why do I need to add this address here? */
int ret;
ret = sctp_add_remote_addr(*stcb, to, 0, 100);
ret = sctp_add_remote_addr(*stcb, to, SCTP_DONOT_SETSCOPE,
SCTP_IN_COOKIE_PROC);
netl = sctp_findnet(*stcb, to);
}
if (netl) {
@ -2106,7 +2162,7 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC);
sctp_abort_association(*inp_p, NULL, m, iphlen,
sh, op_err);
sctp_free_assoc(*inp_p, *stcb, 0);
sctp_free_assoc(*inp_p, *stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_20);
return (NULL);
}
inp = (struct sctp_inpcb *)so->so_pcb;
@ -2386,10 +2442,10 @@ sctp_handle_shutdown_complete(struct sctp_shutdown_complete_chunk *cp,
}
}
/* stop the timer */
sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net);
sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_21);
SCTP_STAT_INCR_COUNTER32(sctps_shutdown);
/* free the TCB */
sctp_free_assoc(stcb->sctp_ep, stcb, 0);
sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_22);
return;
}
@ -2499,11 +2555,18 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc,
/* restart the timer */
sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
stcb, tp1->whoTo);
stcb, tp1->whoTo, SCTP_FROM_SCTP_INPUT + SCTP_LOC_23);
sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
stcb, tp1->whoTo);
/* fix counts and things */
#ifdef SCTP_FLIGHT_LOGGING
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN,
tp1->whoTo->flight_size,
tp1->book_size,
(uintptr_t) stcb,
tp1->rec.data.TSN_seq);
#endif
if (tp1->whoTo->flight_size >= tp1->book_size)
tp1->whoTo->flight_size -= tp1->book_size;
else
@ -2569,7 +2632,7 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc,
* this, otherwise we let the timer fire.
*/
sctp_timer_stop(SCTP_TIMER_TYPE_INIT, stcb->sctp_ep,
stcb, net);
stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_24);
sctp_send_initiate(stcb->sctp_ep, stcb);
}
break;
@ -2738,7 +2801,7 @@ sctp_clean_up_stream_reset(struct sctp_tcb *stcb)
if (stcb->asoc.str_reset == NULL) {
return;
}
sctp_timer_stop(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb, chk->whoTo);
sctp_timer_stop(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb, chk->whoTo, SCTP_FROM_SCTP_INPUT + SCTP_LOC_25);
TAILQ_REMOVE(&asoc->control_send_queue,
chk,
sctp_next);
@ -3460,6 +3523,9 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length,
*/
vtag_in = ntohl(sh->v_tag);
if (locked_tcb) {
SCTP_TCB_LOCK_ASSERT(locked_tcb);
}
if (ch->chunk_type == SCTP_INITIATION) {
if (vtag_in != 0) {
/* protocol error- silently discard... */
@ -3754,7 +3820,7 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length,
SCTP_TCB_UNLOCK(locked_tcb);
*offset = length;
if (stcb) {
sctp_free_assoc(inp, stcb, 0);
sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_26);
}
return (NULL);
}
@ -3972,7 +4038,15 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length,
process_cookie_anyway:
{
struct mbuf *ret_buf;
struct sctp_inpcb *linp;
if (stcb)
linp = NULL;
else
linp = inp;
if (linp)
SCTP_ASOC_CREATE_LOCK(linp);
ret_buf =
sctp_handle_cookie_echo(m, iphlen,
*offset, sh,
@ -3980,8 +4054,10 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length,
&inp, &stcb, netp,
auth_skipped,
auth_offset,
auth_len);
auth_len,
&locked_tcb);
if (linp)
SCTP_ASOC_CREATE_UNLOCK(linp);
if (ret_buf == NULL) {
if (locked_tcb) {
SCTP_TCB_UNLOCK(locked_tcb);
@ -4028,7 +4104,7 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length,
if ((stcb) && (stcb->asoc.total_output_queue_size)) {
;
} else {
sctp_free_assoc(inp, stcb, 0);
sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_27);
*offset = length;
return (NULL);
}
@ -4117,7 +4193,7 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length,
*fwd_tsn_seen = 1;
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
/* We are not interested anymore */
sctp_free_assoc(inp, stcb, 0);
sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_28);
*offset = length;
return (NULL);
}
@ -4142,7 +4218,7 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length,
chk_length, chunk_buf);
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
/* We are not interested anymore */
sctp_free_assoc(inp, stcb, 0);
sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_29);
*offset = length;
return (NULL);
}
@ -4431,7 +4507,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset,
* Rest should be DATA only. Check authentication state if AUTH for
* DATA is required.
*/
if ((stcb != NULL) && !sctp_auth_disable &&
if ((length > offset) && (stcb != NULL) && !sctp_auth_disable &&
sctp_auth_is_required_chunk(SCTP_DATA,
stcb->asoc.local_auth_chunks) &&
!stcb->asoc.authenticated) {
@ -4441,8 +4517,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset,
if (sctp_debug_on & SCTP_DEBUG_AUTH1)
printf("Data chunk requires AUTH, skipped\n");
#endif
SCTP_TCB_UNLOCK(stcb);
return (1);
goto trigger_send;
}
if (length > offset) {
int retval;
@ -4526,6 +4601,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset,
}
}
/* trigger send of any chunks in queue... */
trigger_send:
#ifdef SCTP_AUDITING_ENABLED
sctp_audit_log(0xE0, 2);
sctp_auditing(1, inp, stcb, net);
@ -4567,6 +4643,10 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset,
extern int sctp_no_csum_on_loopback;
int sctp_buf_index = 0;
uint8_t sctp_list_of_chunks[30000];
void
sctp_input(m, off)
struct mbuf *m;
@ -4698,6 +4778,16 @@ sctp_input(m, off)
if (mlen < (ip->ip_len - iphlen)) {
SCTP_STAT_INCR(sctps_hdrops);
goto bad;
} {
/* TEMP log the first chunk */
int x;
x = atomic_fetchadd_int(&sctp_buf_index, 1);
if (x > 30000) {
sctp_buf_index = 1;
x = 0;;
}
sctp_list_of_chunks[x] = ch->chunk_type;
}
/*
* Locate pcb and tcb for datagram sctp_findassociation_addr() wants
@ -4736,7 +4826,15 @@ sctp_input(m, off)
if (init_chk != NULL)
sh->v_tag = init_chk->init.initiate_tag;
}
sctp_send_abort(m, iphlen, sh, 0, NULL);
if (ch->chunk_type == SCTP_SHUTDOWN_ACK) {
sctp_send_shutdown_complete2(m, iphlen, sh);
goto bad;
}
if (ch->chunk_type == SCTP_SHUTDOWN_COMPLETE) {
goto bad;
}
if (ch->chunk_type != SCTP_ABORT_ASSOCIATION)
sctp_send_abort(m, iphlen, sh, 0, NULL);
goto bad;
} else if (stcb == NULL) {
refcount_up = 1;

View File

@ -71,6 +71,10 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
extern struct sctp_foo_stuff sctp_logoff[];
extern int sctp_logoff_stuff;
#define SCTP_IPI_COUNT_INIT()
#define SCTP_STATLOG_INIT_LOCK()
@ -87,6 +91,7 @@ __FBSDID("$FreeBSD$");
} \
}
#define SCTP_INP_INFO_LOCK_INIT() \
mtx_init(&sctppcbinfo.ipi_ep_mtx, "sctp-info", "inp_info", MTX_DEF)
@ -185,10 +190,37 @@ __FBSDID("$FreeBSD$");
#define SCTP_TCB_SEND_UNLOCK(_tcb) mtx_unlock(&(_tcb)->tcb_send_mtx)
#ifdef INVARIANTS
#define SCTP_INP_INCR_REF(_inp) { int x; \
atomic_add_int(&((_inp)->refcount), 1); \
x = atomic_fetchadd_int(&sctp_logoff_stuff, 1); \
if(x == 30000) \
sctp_logoff_stuff = x = 0; \
sctp_logoff[x].inp = _inp; \
sctp_logoff[x].ticks = ticks; \
sctp_logoff[x].lineno = __LINE__; \
sctp_logoff[x].updown = 1; \
}
#define SCTP_INP_DECR_REF(_inp) { int x; \
if (atomic_fetchadd_int(&((_inp)->refcount), -1) == 0 ) panic("refcount goes negative"); \
x = atomic_fetchadd_int(&sctp_logoff_stuff, 1); \
if(x == 30000) \
sctp_logoff_stuff = x = 0; \
sctp_logoff[x].inp = _inp; \
sctp_logoff[x].ticks = ticks; \
sctp_logoff[x].lineno = __LINE__; \
sctp_logoff[x].updown = 0; \
}
#else
#define SCTP_INP_INCR_REF(_inp) atomic_add_int(&((_inp)->refcount), 1)
#define SCTP_INP_DECR_REF(_inp) atomic_add_int(&((_inp)->refcount), -1)
#endif
#ifdef SCTP_LOCK_LOGGING
#define SCTP_ASOC_CREATE_LOCK(_inp) \
do { \

View File

@ -43,6 +43,8 @@ __FBSDID("$FreeBSD$");
*/
typedef struct mbuf *sctp_mbuf_t;
#define USER_ADDR_NULL (NULL) /* FIX ME: temp */
/*
* general memory allocation
*/

View File

@ -3617,6 +3617,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
/* place in my tag */
if ((asoc != NULL) &&
((SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_WAIT) ||
(SCTP_GET_STATE(asoc) == SCTP_STATE_INUSE) ||
(SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED))) {
/* re-use the v-tags and init-seq here */
initackm_out->msg.init.initiate_tag = htonl(asoc->my_vtag);
@ -3929,13 +3930,17 @@ sctp_remove_from_wheel(struct sctp_tcb *stcb,
{
/* take off and then setup so we know it is not on the wheel */
SCTP_TCB_SEND_LOCK(stcb);
if (TAILQ_FIRST(&strq->outqueue)) {
/* more was added */
SCTP_TCB_SEND_UNLOCK(stcb);
return;
}
TAILQ_REMOVE(&asoc->out_wheel, strq, next_spoke);
strq->next_spoke.tqe_next = NULL;
strq->next_spoke.tqe_prev = NULL;
SCTP_TCB_SEND_UNLOCK(stcb);
}
static void
sctp_prune_prsctp(struct sctp_tcb *stcb,
struct sctp_association *asoc,
@ -4078,7 +4083,7 @@ sctp_set_prsctp_policy(struct sctp_tcb *stcb,
sp->act_flags |= PR_SCTP_POLICY(sp->sinfo_flags);
sp->pr_sctp_on = 1;
} else {
goto sctp_no_policy;
return;
}
switch (PR_SCTP_POLICY(sp->sinfo_flags)) {
case CHUNK_FLAGS_PR_SCTP_BUF:
@ -4116,13 +4121,8 @@ sctp_set_prsctp_policy(struct sctp_tcb *stcb,
break;
}
}
sctp_no_policy:
if (sp->sinfo_flags & SCTP_UNORDERED)
sp->act_flags |= SCTP_DATA_UNORDERED;
}
static int
sctp_msg_append(struct sctp_tcb *stcb,
struct sctp_nets *net,
@ -4165,7 +4165,6 @@ sctp_msg_append(struct sctp_tcb *stcb,
goto out_now;
}
SCTP_INCR_STRMOQ_COUNT();
sp->act_flags = 0;
sp->sinfo_flags = srcv->sinfo_flags;
sp->timetolive = srcv->sinfo_timetolive;
sp->ppid = srcv->sinfo_ppid;
@ -4217,7 +4216,7 @@ sctp_msg_append(struct sctp_tcb *stcb,
if ((strm->next_spoke.tqe_next == NULL) &&
(strm->next_spoke.tqe_prev == NULL)) {
/* Not on wheel, insert */
sctp_insert_on_wheel(stcb, &stcb->asoc, strm, 0);
sctp_insert_on_wheel(stcb, &stcb->asoc, strm, 1);
}
m = NULL;
SCTP_TCB_SEND_UNLOCK(stcb);
@ -4875,6 +4874,13 @@ sctp_clean_up_datalist(struct sctp_tcb *stcb,
data_list[i]->sent = SCTP_DATAGRAM_SENT;
data_list[i]->snd_count = 1;
data_list[i]->rec.data.chunk_was_revoked = 0;
#ifdef SCTP_FLIGHT_LOGGING
sctp_misc_ints(SCTP_FLIGHT_LOG_UP,
data_list[i]->whoTo->flight_size,
data_list[i]->book_size,
(uintptr_t) stcb,
data_list[i]->rec.data.TSN_seq);
#endif
net->flight_size += data_list[i]->book_size;
asoc->total_flight += data_list[i]->book_size;
asoc->total_flight_count++;
@ -4997,11 +5003,12 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb, struct sctp_nets *net,
struct sctp_data_chunk *dchkh;
int to_move;
uint8_t rcv_flags = 0;
uint8_t some_taken;
uint8_t took_all = 0;
SCTP_TCB_LOCK_ASSERT(stcb);
asoc = &stcb->asoc;
sp = TAILQ_FIRST(&strq->outqueue);
if (sp == NULL) {
*locked = 0;
SCTP_TCB_SEND_LOCK(stcb);
@ -5024,6 +5031,7 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb, struct sctp_nets *net,
/* This should not happen */
panic("sp length is 0?");
}
some_taken = sp->some_taken;
if ((goal_mtu >= sp->length) && (sp->msg_is_complete)) {
/* It all fits and its a complete msg, no brainer */
to_move = min(sp->length, frag_point);
@ -5042,8 +5050,8 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb, struct sctp_nets *net,
sp->some_taken = 1;
}
} else {
to_move = sctp_can_we_split_this(stcb,
sp, goal_mtu, frag_point, eeor_mode);
to_move = sctp_can_we_split_this(stcb, sp, goal_mtu,
frag_point, eeor_mode);
if (to_move) {
if (to_move >= sp->length) {
to_move = sp->length;
@ -5070,11 +5078,17 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb, struct sctp_nets *net,
*giveup = 1;
return (0);
}
/* clear it */
/*
* Setup for unordered if needed by looking at the user sent info
* flags.
*/
if (sp->sinfo_flags & SCTP_UNORDERED) {
rcv_flags |= SCTP_DATA_UNORDERED;
}
/* clear out the chunk before setting up */
memset(chk, sizeof(*chk), 0);
chk->rec.data.rcv_flags = rcv_flags;
SCTP_TCB_SEND_LOCK(stcb);
sctp_snd_sb_alloc(stcb, sizeof(struct sctp_data_chunk));
if (sp->data->m_flags & M_EXT) {
chk->copy_by_ref = 1;
} else {
@ -5086,21 +5100,21 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb, struct sctp_nets *net,
chk->last_mbuf = sp->tail_mbuf;
/* register the stealing */
sp->data = sp->tail_mbuf = NULL;
took_all = 1;
} else {
struct mbuf *m;
chk->data = m_copym(sp->data, 0, to_move, M_DONTWAIT);
chk->last_mbuf = NULL;
if (chk->data == NULL) {
sp->some_taken = some_taken;
sctp_free_a_chunk(stcb, chk);
SCTP_TCB_SEND_UNLOCK(stcb);
goto out_gu;
}
/* Pull off the data */
m_adj(sp->data, to_move);
/*
* Now lets work our way down and compact it
*/
/* Now lets work our way down and compact it */
m = sp->data;
while (m && (m->m_len == 0)) {
sp->data = m->m_next;
@ -5115,8 +5129,9 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb, struct sctp_nets *net,
}
if (to_move > sp->length) {
panic("Huh, how can to_move be larger?");
} else
} else {
sp->length -= to_move;
}
/* Update the new length in */
if (sp->data && (sp->data->m_flags & M_PKTHDR)) {
@ -5129,7 +5144,31 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb, struct sctp_nets *net,
m = sctp_get_mbuf_for_msg(1, 1, M_DONTWAIT, 0, MT_DATA);
if (m == NULL) {
printf("We will Panic maybe, out of mbufs\n");
/*
* we're in trouble here. M_PREPEND below will free
* all the data if there is no leading space, so we
* must put the data back and restore.
*/
if (took_all) {
/* unsteal the data */
sp->data = chk->data;
sp->tail_mbuf = chk->last_mbuf;
} else {
struct mbuf *m;
/* reassemble the data */
m = sp->data;
sp->data = chk->data;
sp->data->m_next = m;
}
sp->some_taken = some_taken;
sp->length += to_move;
if (sp->data && (sp->data->m_flags & M_PKTHDR)) {
sp->data->m_pkthdr.len = sp->length;
}
sctp_free_a_chunk(stcb, chk);
SCTP_TCB_SEND_UNLOCK(stcb);
goto out_gu;
} else {
m->m_len = 0;
m->m_next = chk->data;
@ -5145,7 +5184,9 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb, struct sctp_nets *net,
SCTP_TCB_SEND_UNLOCK(stcb);
goto out_gu;
}
chk->book_size = chk->send_size = (to_move + sizeof(struct sctp_data_chunk));
sctp_snd_sb_alloc(stcb, sizeof(struct sctp_data_chunk));
chk->book_size = chk->send_size = (to_move +
sizeof(struct sctp_data_chunk));
chk->sent = SCTP_DATAGRAM_UNSENT;
/*
@ -5196,9 +5237,7 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb, struct sctp_nets *net,
dchkh->dp.stream_sequence = htons(chk->rec.data.stream_seq);
dchkh->dp.protocol_id = chk->rec.data.payloadtype;
dchkh->ch.chunk_length = htons(chk->send_size);
/*
* Now advance the chk->send_size by the actual pad needed.
*/
/* Now advance the chk->send_size by the actual pad needed. */
if (chk->send_size < SCTP_SIZE32(chk->book_size)) {
/* need a pad */
struct mbuf *lm;
@ -5218,9 +5257,9 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb, struct sctp_nets *net,
chk->send_size += pads;
}
/* We only re-set the policy if it is on */
if (sp->pr_sctp_on)
if (sp->pr_sctp_on) {
sctp_set_prsctp_policy(stcb, sp);
}
if (sp->msg_is_complete && (sp->length == 0)) {
/* All done pull and kill the message */
asoc->stream_queue_cnt--;
@ -5754,7 +5793,7 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
/* turn off the timer */
if (callout_pending(&stcb->asoc.dack_timer.timer)) {
sctp_timer_stop(SCTP_TIMER_TYPE_RECV,
inp, stcb, net);
inp, stcb, net, SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_1);
}
}
ctl_cnt++;
@ -5991,7 +6030,7 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
to_out += chk->send_size;
if (to_out > mx_mtu) {
#ifdef INVARIENT
#ifdef INVARIANTS
panic("gag");
#else
printf("Exceeding mtu of %d out size is %d\n",
@ -6135,7 +6174,8 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
if (net->flight_size < net->cwnd) {
/* start or restart it */
if (callout_pending(&net->fr_timer.timer)) {
sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, inp, stcb, net);
sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, inp, stcb, net,
SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_2);
}
SCTP_STAT_INCR(sctps_earlyfrstrout);
sctp_timer_start(SCTP_TIMER_TYPE_EARLYFR, inp, stcb, net);
@ -6143,7 +6183,8 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
/* stop it if its running */
if (callout_pending(&net->fr_timer.timer)) {
SCTP_STAT_INCR(sctps_earlyfrstpout);
sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, inp, stcb, net);
sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, inp, stcb, net,
SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_3);
}
}
}
@ -7032,6 +7073,13 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp,
if (asoc->sent_queue_retran_cnt < 0) {
asoc->sent_queue_retran_cnt = 0;
}
#ifdef SCTP_FLIGHT_LOGGING
sctp_misc_ints(SCTP_FLIGHT_LOG_UP,
data_list[i]->whoTo->flight_size,
data_list[i]->book_size,
(uintptr_t) stcb,
data_list[i]->rec.data.TSN_seq);
#endif
net->flight_size += data_list[i]->book_size;
asoc->total_flight += data_list[i]->book_size;
if (data_list[i]->book_size_scale) {
@ -7069,7 +7117,8 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp,
* SACK back without a
* t3-expiring.
*/
sctp_timer_stop(SCTP_TIMER_TYPE_SEND, inp, stcb, net);
sctp_timer_stop(SCTP_TIMER_TYPE_SEND, inp, stcb, net,
SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_4);
sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, net);
}
}
@ -7617,7 +7666,7 @@ sctp_send_sack(struct sctp_tcb *stcb)
if (a_chk == NULL) {
/* No memory so we drop the idea, and set a timer */
sctp_timer_stop(SCTP_TIMER_TYPE_RECV,
stcb->sctp_ep, stcb, NULL);
stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_5);
sctp_timer_start(SCTP_TIMER_TYPE_RECV,
stcb->sctp_ep, stcb, NULL);
return;
@ -7686,7 +7735,7 @@ sctp_send_sack(struct sctp_tcb *stcb)
atomic_subtract_int(&a_chk->whoTo->ref_count, 1);
sctp_free_a_chunk(stcb, a_chk);
sctp_timer_stop(SCTP_TIMER_TYPE_RECV,
stcb->sctp_ep, stcb, NULL);
stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_6);
sctp_timer_start(SCTP_TIMER_TYPE_RECV,
stcb->sctp_ep, stcb, NULL);
return;
@ -8234,6 +8283,7 @@ sctp_send_hb(struct sctp_tcb *stcb, int user_req, struct sctp_nets *u_net)
}
/* ok we have a destination that needs a beat */
/* lets do the theshold management Qiaobing style */
if (sctp_threshold_management(stcb->sctp_ep, stcb, net,
stcb->asoc.max_send_times)) {
/*
@ -9324,6 +9374,12 @@ sctp_lower_sosend(struct socket *so,
stcb = NULL;
asoc = NULL;
t_inp = inp = (struct sctp_inpcb *)so->so_pcb;
if (inp == NULL) {
error = EFAULT;
splx(s);
goto out_unlocked;
}
atomic_add_int(&inp->total_sends, 1);
if (uio)
sndlen = uio->uio_resid;
else
@ -9340,6 +9396,9 @@ sctp_lower_sosend(struct socket *so,
goto out_unlocked;
}
if ((use_rcvinfo) && srcv) {
if (srcv->sinfo_flags)
SCTP_STAT_INCR(sctps_sends_with_flags);
if (srcv->sinfo_flags & SCTP_SENDALL) {
/* its a sendall */
error = sctp_sendall(inp, uio, top, srcv);
@ -9414,6 +9473,18 @@ sctp_lower_sosend(struct socket *so,
splx(s);
goto out_unlocked;
}
SCTP_INP_WLOCK(inp);
SCTP_INP_INCR_REF(inp);
SCTP_INP_WUNLOCK(inp);
/* With the lock applied look again */
stcb = sctp_findassociation_ep_addr(&t_inp, addr, &net, NULL, NULL);
if (stcb == NULL) {
SCTP_INP_WLOCK(inp);
SCTP_INP_DECR_REF(inp);
SCTP_INP_WUNLOCK(inp);
} else {
hold_tcblock = 1;
}
}
if (stcb == NULL) {
if (inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
@ -9575,6 +9646,7 @@ sctp_lower_sosend(struct socket *so,
(stcb->asoc.chunks_on_out_queue >
sctp_max_chunks_on_queue)) {
error = EWOULDBLOCK;
atomic_add_int(&stcb->sctp_ep->total_nospaces, 1);
splx(s);
goto out_unlocked;
}
@ -9661,6 +9733,7 @@ sctp_lower_sosend(struct socket *so,
struct mbuf *mm;
int tot_demand, tot_out, max;
SCTP_STAT_INCR(sctps_sends_with_abort);
if ((SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_WAIT) ||
(SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)) {
/* It has to be up before we abort */
@ -9806,6 +9879,7 @@ sctp_lower_sosend(struct socket *so,
if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
goto out_unlocked;
}
atomic_add_int(&stcb->total_sends, 1);
if (top == NULL) {
struct sctp_stream_queue_pending *sp;
struct sctp_stream_out *strm;
@ -9831,6 +9905,7 @@ sctp_lower_sosend(struct socket *so,
strm = &stcb->asoc.strmout[srcv->sinfo_stream];
user_marks_eor = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR);
if (strm->last_msg_incomplete == 0) {
do_a_copy_in:
sp = sctp_copy_it_in(stcb, asoc, srcv, uio, net, max_len, user_marks_eor, &error, non_blocking);
if ((sp == NULL) || (error)) {
goto out;
@ -9860,7 +9935,10 @@ sctp_lower_sosend(struct socket *so,
(uint32_t) ((srcv->sinfo_stream << 16) | sp->strseq), 0);
#endif
strm->next_sequence_sent++;
} else {
SCTP_STAT_INCR(sctps_sends_with_unord);
}
if ((strm->next_spoke.tqe_next == NULL) &&
(strm->next_spoke.tqe_prev == NULL)) {
/* Not on wheel, insert */
@ -9869,6 +9947,17 @@ sctp_lower_sosend(struct socket *so,
SCTP_TCB_SEND_UNLOCK(stcb);
} else {
sp = TAILQ_LAST(&strm->outqueue, sctp_streamhead);
if (sp == NULL) {
/* ???? Huh ??? last msg is gone */
#ifdef INVARIANTS
panic("Warning: Last msg marked incomplete, yet nothing left?");
#else
printf("Warning: Last msg marked incomplete, yet nothing left?\n");
strm->last_msg_incomplete = 0;
#endif
goto do_a_copy_in;
}
}
while (uio->uio_resid > 0) {
/* How much room do we have? */
@ -10019,11 +10108,16 @@ sctp_lower_sosend(struct socket *so,
SCTP_TCB_LOCK(stcb);
hold_tcblock = 1;
}
sctp_send_initiate(inp, stcb);
queue_only_for_init = 0;
queue_only = 1;
SCTP_TCB_UNLOCK(stcb);
hold_tcblock = 0;
if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
/* a collision took us forward? */
queue_only_for_init = 0;
queue_only = 0;
} else {
sctp_send_initiate(inp, stcb);
stcb->asoc.state = SCTP_STATE_COOKIE_WAIT;
queue_only_for_init = 0;
queue_only = 1;
}
}
if ((queue_only == 0) && (nagle_applies == 0)
) {
@ -10126,6 +10220,7 @@ sctp_lower_sosend(struct socket *so,
(got_all_of_the_send == 1) &&
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)
) {
SCTP_STAT_INCR(sctps_sends_with_eof);
error = 0;
if (hold_tcblock == 0) {
SCTP_TCB_LOCK(stcb);
@ -10255,9 +10350,16 @@ sctp_lower_sosend(struct socket *so,
SCTP_TCB_LOCK(stcb);
hold_tcblock = 1;
}
sctp_send_initiate(inp, stcb);
queue_only_for_init = 0;
queue_only = 1;
if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
/* a collision took us forward? */
queue_only_for_init = 0;
queue_only = 0;
} else {
sctp_send_initiate(inp, stcb);
stcb->asoc.state = SCTP_STATE_COOKIE_WAIT;
queue_only_for_init = 0;
queue_only = 1;
}
}
if ((queue_only == 0) && (nagle_applies == 0) && (stcb->asoc.peers_rwnd && un_sent)) {
/* we can attempt to send too. */
@ -10317,7 +10419,7 @@ sctp_lower_sosend(struct socket *so,
if (stcb && free_cnt_applied) {
atomic_add_int(&stcb->asoc.refcnt, -1);
}
#ifdef INVARIENTS
#ifdef INVARIANTS
if (stcb) {
if (mtx_owned(&stcb->tcb_mtx)) {
panic("Leaving with tcb mtx owned?");

View File

@ -408,7 +408,7 @@ sctp_findassociation_ep_addr(struct sctp_inpcb **inp_p, struct sockaddr *remote,
}
/* now look at the list of remote addresses */
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
#ifdef INVARIENTS
#ifdef INVARIANTS
if (net == (TAILQ_NEXT(net, sctp_next))) {
panic("Corrupt net list");
}
@ -481,7 +481,7 @@ sctp_findassociation_ep_addr(struct sctp_inpcb **inp_p, struct sockaddr *remote,
/* now look at the list of remote addresses */
SCTP_TCB_LOCK(stcb);
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
#ifdef INVARIENTS
#ifdef INVARIANTS
if (net == (TAILQ_NEXT(net, sctp_next))) {
panic("Corrupt net list");
}
@ -603,7 +603,7 @@ sctp_findassociation_ep_asocid(struct sctp_inpcb *inp, sctp_assoc_t asoc_id, int
SCTP_INP_RUNLOCK(stcb->sctp_ep);
}
/* Ok if we missed here, lets try the restart hash */
head = &sctppcbinfo.sctp_asochash[SCTP_PCBHASH_ASOC(id, sctppcbinfo.hashrestartmark)];
head = &sctppcbinfo.sctp_restarthash[SCTP_PCBHASH_ASOC(id, sctppcbinfo.hashrestartmark)];
if (head == NULL) {
/* invalid id TSNH */
SCTP_INP_INFO_RUNLOCK();
@ -1456,6 +1456,10 @@ sctp_inpcb_alloc(struct socket *so)
LIST_INIT(&inp->sctp_addr_list);
LIST_INIT(&inp->sctp_asoc_list);
#ifdef SCTP_TRACK_FREED_ASOCS
/* TEMP CODE */
LIST_INIT(&inp->sctp_asoc_free_list);
#endif
/* Init the timer structure for signature change */
callout_init(&inp->sctp_ep.signature_change.timer, 1);
inp->sctp_ep.signature_change.type = SCTP_TIMER_TYPE_NEWCOOKIE;
@ -2103,7 +2107,8 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
*/
inp->sctp_flags &= ~SCTP_PCB_FLAGS_CLOSE_IP;
}
sctp_timer_stop(SCTP_TIMER_TYPE_NEWCOOKIE, inp, NULL, NULL);
sctp_timer_stop(SCTP_TIMER_TYPE_NEWCOOKIE, inp, NULL, NULL,
SCTP_FROM_SCTP_PCB + SCTP_LOC_1);
if (inp->control) {
sctp_m_freem(inp->control);
@ -2134,7 +2139,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
(SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_COOKIE_ECHOED)) {
/* Just abandon things in the front states */
if (asoc->asoc.total_output_queue_size == 0) {
sctp_free_assoc(inp, asoc, 1);
sctp_free_assoc(inp, asoc, SCTP_PCBFREE_NOFORCE, SCTP_FROM_SCTP_PCB + SCTP_LOC_2);
continue;
}
}
@ -2165,15 +2170,16 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
SCTP_CAUSE_USER_INITIATED_ABT);
ph->param_length = htons(op_err->m_len);
ippp = (uint32_t *) (ph + 1);
*ippp = htonl(0x30000004);
*ippp = htonl(SCTP_FROM_SCTP_PCB + SCTP_LOC_3);
}
asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB + SCTP_LOC_3;
sctp_send_abort_tcb(asoc, op_err);
SCTP_STAT_INCR_COUNTER32(sctps_aborted);
if ((SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_OPEN) ||
(SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
sctp_free_assoc(inp, asoc, 1);
sctp_free_assoc(inp, asoc, SCTP_PCBFREE_NOFORCE, SCTP_FROM_SCTP_PCB + SCTP_LOC_4);
continue;
} else if (TAILQ_EMPTY(&asoc->asoc.send_queue) &&
TAILQ_EMPTY(&asoc->asoc.sent_queue) &&
@ -2241,15 +2247,16 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
SCTP_CAUSE_USER_INITIATED_ABT);
ph->param_length = htons(op_err->m_len);
ippp = (uint32_t *) (ph + 1);
*ippp = htonl(0x30000005);
*ippp = htonl(SCTP_FROM_SCTP_PCB + SCTP_LOC_5);
}
asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB + SCTP_LOC_5;
sctp_send_abort_tcb(asoc, op_err);
SCTP_STAT_INCR_COUNTER32(sctps_aborted);
if ((SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_OPEN) ||
(SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
sctp_free_assoc(inp, asoc, 1);
sctp_free_assoc(inp, asoc, SCTP_PCBFREE_NOFORCE, SCTP_FROM_SCTP_PCB + SCTP_LOC_6);
continue;
}
}
@ -2258,23 +2265,6 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
}
/* now is there some left in our SHUTDOWN state? */
if (cnt_in_sd) {
if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) !=
SCTP_PCB_FLAGS_UNBOUND) {
/*
* ok, this guy has been bound. It's port is
* somewhere in the sctppcbinfo hash table.
* Remove it!
*
* Note we are depending on lookup by vtag to
* find associations that are dieing. This
* free's the port so we don't have to block
* its useage. The SCTP_PCB_FLAGS_UNBOUND
* flags will prevent us from doing this
* again.
*/
LIST_REMOVE(inp, sctp_hash);
inp->sctp_flags |= SCTP_PCB_FLAGS_UNBOUND;
}
splx(s);
SCTP_INP_WUNLOCK(inp);
@ -2329,9 +2319,10 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
SCTP_CAUSE_USER_INITIATED_ABT);
ph->param_length = htons(op_err->m_len);
ippp = (uint32_t *) (ph + 1);
*ippp = htonl(0x30000006);
*ippp = htonl(SCTP_FROM_SCTP_PCB + SCTP_LOC_7);
}
asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB + SCTP_LOC_7;
sctp_send_abort_tcb(asoc, op_err);
SCTP_STAT_INCR_COUNTER32(sctps_aborted);
} else if (asoc->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
@ -2343,7 +2334,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
(SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
sctp_free_assoc(inp, asoc, 2);
sctp_free_assoc(inp, asoc, SCTP_PCBFREE_FORCE, SCTP_FROM_SCTP_PCB + SCTP_LOC_8);
}
if (cnt) {
/* Ok we have someone out there that will kill us */
@ -2457,6 +2448,18 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_laddr, laddr);
SCTP_DECR_LADDR_COUNT();
}
#ifdef SCTP_TRACK_FREED_ASOCS
/* TEMP CODE */
for ((asoc = LIST_FIRST(&inp->sctp_asoc_free_list)); asoc != NULL;
asoc = nasoc) {
nasoc = LIST_NEXT(asoc, sctp_tcblist);
LIST_REMOVE(asoc, sctp_tcblist);
SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_asoc, asoc);
SCTP_DECR_ASOC_COUNT();
}
/* *** END TEMP CODE *** */
#endif
/* Now lets see about freeing the EP hash table. */
if (inp->sctp_tcbhash != NULL) {
SCTP_FREE(inp->sctp_tcbhash);
@ -2611,7 +2614,7 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
stcb->asoc.site_scope = 1;
}
} else {
if (from == 8) {
if (from == SCTP_ADDR_IS_CONFIRMED) {
/* From connectx */
if (sctp_is_address_on_local_host(newaddr)) {
stcb->asoc.loopback_scope = 1;
@ -2661,8 +2664,8 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
stcb->asoc.site_scope = 1;
}
} else {
if (from == 8) {
/* From connectx */
if (from == SCTP_ADDR_IS_CONFIRMED) {
/* From connectx so we check for localhost. */
if (sctp_is_address_on_local_host(newaddr)) {
stcb->asoc.loopback_scope = 1;
stcb->asoc.ipv4_local_scope = 1;
@ -2704,8 +2707,8 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
net->dest_state = (SCTP_ADDR_REACHABLE |
SCTP_ADDR_OUT_OF_SCOPE);
} else {
if (from == 8)
/* 8 is passed by connect_x */
if (from == SCTP_ADDR_IS_CONFIRMED)
/* SCTP_ADDR_IS_CONFIRMED is passed by connect_x */
net->dest_state = SCTP_ADDR_REACHABLE;
else
net->dest_state = SCTP_ADDR_REACHABLE |
@ -2747,7 +2750,7 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
if ((net->ro.ro_rt) &&
(net->ro.ro_rt->rt_ifp)) {
net->mtu = net->ro.ro_rt->rt_ifp->if_mtu;
if (from == 1) {
if (from == SCTP_ALLOC_ASOC) {
stcb->asoc.smallest_mtu = net->mtu;
}
/* start things off to match mtu of interface please. */
@ -3001,7 +3004,7 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
LIST_INSERT_HEAD(head, stcb, sctp_asocs);
SCTP_INP_INFO_WUNLOCK();
if ((err = sctp_add_remote_addr(stcb, firstaddr, 1, 1))) {
if ((err = sctp_add_remote_addr(stcb, firstaddr, SCTP_DO_SETSCOPE, SCTP_ALLOC_ASOC))) {
/* failure.. memory error? */
if (asoc->strmout)
SCTP_FREE(asoc->strmout);
@ -3210,7 +3213,7 @@ sctp_iterator_asoc_being_freed(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
* Free the association after un-hashing the remote port.
*/
int
sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfree)
sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfree, int from_location)
{
int i;
struct sctp_association *asoc;
@ -3240,6 +3243,13 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
/* there is no asoc, really TSNH :-0 */
return (1);
}
/* TEMP CODE */
if (stcb->freed_from_where == 0) {
/* Only record the first place free happened from */
stcb->freed_from_where = from_location;
}
/* TEMP CODE */
asoc = &stcb->asoc;
if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
(inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE))
@ -3254,7 +3264,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
* if so we abort early if a reader or writer is still in the way.
*/
if ((stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) &&
(from_inpcbfree == 0)) {
(from_inpcbfree == SCTP_NORMAL_PROC)) {
/*
* is it the timer driving us? if so are the reader/writers
* gone?
@ -3286,6 +3296,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
callout_stop(&net->pmtu_timer.timer);
}
/* Now the read queue needs to be cleaned up (only once) */
cnt = 0;
if ((stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) == 0) {
SCTP_INP_READ_LOCK(inp);
TAILQ_FOREACH(sq, &inp->read_queue, next) {
@ -3322,23 +3333,33 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
}
SCTP_INP_READ_UNLOCK(inp);
if (stcb->block_entry) {
cnt++;
stcb->block_entry->error = ECONNRESET;
stcb->block_entry = NULL;
}
}
stcb->asoc.state |= SCTP_STATE_ABOUT_TO_BE_FREED;
if ((from_inpcbfree != 2) && (stcb->asoc.refcnt)) {
if ((from_inpcbfree != SCTP_PCBFREE_FORCE) && (stcb->asoc.refcnt)) {
/*
* reader or writer in the way, we have hopefully given him
* something to chew on above.
*/
if (so) {
/* Wake any reader/writers */
sctp_sorwakeup(inp, so);
sctp_sowwakeup(inp, so);
}
sctp_timer_start(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL);
SCTP_TCB_UNLOCK(stcb);
if (so) {
SCTP_INP_RLOCK(inp);
if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
(inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE))
/* nothing around */
so = NULL;
if (so) {
/* Wake any reader/writers */
sctp_sorwakeup(inp, so);
sctp_sowwakeup(inp, so);
}
SCTP_INP_RUNLOCK(inp);
}
splx(s);
#ifdef SCTP_LOG_CLOSING
sctp_log_closing(inp, stcb, 9);
@ -3349,9 +3370,32 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
#ifdef SCTP_LOG_CLOSING
sctp_log_closing(inp, stcb, 10);
#endif
if ((from_inpcbfree == 0) && so) {
sctp_sorwakeup(inp, so);
/*
* When I reach here, no others want to kill the assoc yet.. and I
* own the lock. Now its possible an abort comes in when I do the
* lock exchange below to grab all the locks to do the final take
* out. to prevent this we increment the count, which will start a
* timer and blow out above thus assuring us that we hold exclusive
* killing of the asoc. Note that after getting back the TCB lock we
* will go ahead and increment the counter back up and stop any
* timer a passing stranger may have started :-S
*/
if (from_inpcbfree == SCTP_NORMAL_PROC) {
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_ITERATOR_LOCK();
SCTP_INP_INFO_WLOCK();
SCTP_INP_WLOCK(inp);
SCTP_TCB_LOCK(stcb);
}
/* Double check the GONE flag */
if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
(inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE))
/* nothing around */
so = NULL;
if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
(inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
/*
@ -3376,26 +3420,6 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
}
}
}
/*
* When I reach here, no others want to kill the assoc yet.. and I
* own the lock. Now its possible an abort comes in when I do the
* lock exchange below to grab all the locks to do the final take
* out. to prevent this we increment the count, which will start a
* timer and blow out above thus assuring us that we hold exclusive
* killing of the asoc. Note that after getting back the TCB lock we
* will go ahead and increment the counter back up and stop any
* timer a passing stranger may have started :-S
*/
if (from_inpcbfree == 0) {
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_ITERATOR_LOCK();
SCTP_INP_INFO_WLOCK();
SCTP_INP_WLOCK(inp);
SCTP_TCB_LOCK(stcb);
}
/* Stop any timer someone may have started */
callout_stop(&asoc->strreset_timer.timer);
/*
@ -3405,7 +3429,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
asoc->strreset_timer.type = SCTP_TIMER_TYPE_NONE;
sctp_iterator_asoc_being_freed(inp, stcb);
/* re-increment the lock */
if (from_inpcbfree == 0) {
if (from_inpcbfree == SCTP_NORMAL_PROC) {
atomic_add_int(&stcb->asoc.refcnt, -1);
}
/* now restop the timers to be sure - this is paranoia at is finest! */
@ -3431,7 +3455,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
}
/* Now lets remove it from the list of ALL associations in the EP */
LIST_REMOVE(stcb, sctp_tcblist);
if (from_inpcbfree == 0) {
if (from_inpcbfree == SCTP_NORMAL_PROC) {
SCTP_INP_INCR_REF(inp);
SCTP_INP_WUNLOCK(inp);
SCTP_ITERATOR_UNLOCK();
@ -3440,9 +3464,6 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
LIST_REMOVE(stcb, sctp_asocs);
sctp_add_vtag_to_timewait(inp, asoc->my_vtag);
if (from_inpcbfree == 0) {
SCTP_INP_INFO_WUNLOCK();
}
prev = NULL;
/*
* The chunk lists and such SHOULD be empty but we check them just
@ -3651,7 +3672,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
net = TAILQ_FIRST(&asoc->nets);
/* pull from list */
if ((sctppcbinfo.ipi_count_raddr == 0) || (prev == net)) {
#ifdef INVARIENTS
#ifdef INVARIANTS
panic("no net's left alloc'ed, or list points to itself");
#endif
break;
@ -3703,12 +3724,23 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
/* Get rid of LOCK */
SCTP_TCB_LOCK_DESTROY(stcb);
SCTP_TCB_SEND_LOCK_DESTROY(stcb);
/* now clean up the tasoc itself */
if (from_inpcbfree == SCTP_NORMAL_PROC) {
SCTP_INP_INFO_WUNLOCK();
SCTP_INP_RLOCK(inp);
}
#ifdef SCTP_TRACK_FREED_ASOCS
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
/* now clean up the tasoc itself */
SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_asoc, stcb);
SCTP_DECR_ASOC_COUNT();
} else {
LIST_INSERT_HEAD(&inp->sctp_asoc_free_list, stcb, sctp_tcblist);
}
#else
SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_asoc, stcb);
SCTP_DECR_ASOC_COUNT();
if (from_inpcbfree == 0) {
SCTP_INP_RLOCK(inp);
#endif
if (from_inpcbfree == SCTP_NORMAL_PROC) {
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
/*
* If its NOT the inp_free calling us AND sctp_close
@ -3724,12 +3756,16 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
*/
sctp_inpcb_free(inp, 0, 0);
SCTP_INP_DECR_REF(inp);
goto out_of;
} else {
/* The socket is still open. */
SCTP_INP_DECR_REF(inp);
SCTP_INP_RUNLOCK(inp);
}
}
if (from_inpcbfree == SCTP_NORMAL_PROC) {
SCTP_INP_RUNLOCK(inp);
}
out_of:
splx(s);
/* destroyed the asoc */
#ifdef SCTP_LOG_CLOSING
@ -4247,6 +4283,7 @@ sctp_pcb_init()
SCTP_INP_INFO_LOCK_INIT();
SCTP_STATLOG_INIT_LOCK();
SCTP_ITERATOR_LOCK_INIT();
SCTP_IPI_COUNT_INIT();
SCTP_IPI_ADDR_INIT();
LIST_INIT(&sctppcbinfo.addr_wq);
@ -4384,12 +4421,12 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
/* no scope set here since we have a tcb already. */
if ((sa->sa_family == AF_INET) &&
(stcb->asoc.ipv4_addr_legal)) {
if (sctp_add_remote_addr(stcb, sa, 0, 2)) {
if (sctp_add_remote_addr(stcb, sa, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_2)) {
return (-1);
}
} else if ((sa->sa_family == AF_INET6) &&
(stcb->asoc.ipv6_addr_legal)) {
if (sctp_add_remote_addr(stcb, sa, 0, 3)) {
if (sctp_add_remote_addr(stcb, sa, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_3)) {
return (-2);
}
}
@ -4457,7 +4494,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
/* the assoc was freed? */
return (-7);
}
if (sctp_add_remote_addr(stcb, sa, 0, 4)) {
if (sctp_add_remote_addr(stcb, sa, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_4)) {
return (-8);
}
} else if (stcb_tmp == stcb) {
@ -4516,7 +4553,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
* we must add the address, no scope
* set
*/
if (sctp_add_remote_addr(stcb, sa, 0, 5)) {
if (sctp_add_remote_addr(stcb, sa, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_5)) {
return (-17);
}
} else if (stcb_tmp == stcb) {
@ -5039,6 +5076,7 @@ sctp_drain_mbufs(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
/* We look for anything larger than the cum-ack + 1 */
SCTP_STAT_INCR(sctps_protocol_drain_calls);
if (sctp_do_drain == 0) {
return;
}
@ -5047,6 +5085,7 @@ sctp_drain_mbufs(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
/* none we can reneg on. */
return;
}
SCTP_STAT_INCR(sctps_protocol_drains_done);
cumulative_tsn_p1 = asoc->cumulative_tsn + 1;
cnt = 0;
/* First look in the re-assembly queue */

View File

@ -198,6 +198,7 @@ struct sctp_epinfo {
struct mtx ipi_ep_mtx;
struct mtx it_mtx;
struct mtx ipi_addr_mtx;
struct mtx timer_mtx;
uint32_t ipi_count_ep;
/* assoc/tcb zone info */
@ -342,6 +343,9 @@ struct sctp_inpcb {
u_long sctp_hashmark;
/* head of the list of all associations */
struct sctpasochead sctp_asoc_list;
#ifdef SCTP_TRACK_FREED_ASOCS
struct sctpasochead sctp_asoc_free_list;
#endif
struct sctp_iterator *inp_starting_point_for_iterator;
uint32_t sctp_frag_point;
uint32_t partial_delivery_point;
@ -359,6 +363,10 @@ struct sctp_inpcb {
struct mtx inp_create_mtx;
struct mtx inp_rdata_mtx;
int32_t refcount;
uint32_t total_sends;
uint32_t total_recvs;
uint32_t last_abort_code;
uint32_t total_nospaces;
};
struct sctp_tcb {
@ -380,6 +388,9 @@ struct sctp_tcb {
* in the reading of data.
*/
uint32_t freed_by_sorcv_sincelast;
uint32_t total_sends;
uint32_t total_recvs;
int freed_from_where;
uint16_t rport; /* remote port in network format */
uint16_t resv;
struct mtx tcb_mtx;
@ -450,7 +461,7 @@ struct sctp_tcb *
sctp_aloc_assoc(struct sctp_inpcb *, struct sockaddr *,
int, int *, uint32_t);
int sctp_free_assoc(struct sctp_inpcb *, struct sctp_tcb *, int);
int sctp_free_assoc(struct sctp_inpcb *, struct sctp_tcb *, int, int);
int sctp_add_local_addr_ep(struct sctp_inpcb *, struct ifaddr *);

View File

@ -210,7 +210,8 @@ sctp_get_peeloff(struct socket *head, sctp_assoc_t assoc_id, int *error)
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE)) {
sctp_feature_off(n_inp, SCTP_PCB_FLAGS_AUTOCLOSE);
n_inp->sctp_ep.auto_close_time = 0;
sctp_timer_stop(SCTP_TIMER_TYPE_AUTOCLOSE, n_inp, stcb, NULL);
sctp_timer_stop(SCTP_TIMER_TYPE_AUTOCLOSE, n_inp, stcb, NULL,
SCTP_FROM_SCTP_PEELOFF + SCTP_LOC_1);
}
/* Turn off any non-blocking semantic. */
newso->so_state &= ~SS_NBIO;

View File

@ -64,6 +64,7 @@ struct sctp_timer {
/* for sanity checking */
void *self;
uint32_t ticks;
uint32_t stopped_from;
};
struct sctp_nonpad_sndrcvinfo {
@ -78,6 +79,13 @@ struct sctp_nonpad_sndrcvinfo {
sctp_assoc_t sinfo_assoc_id;
};
struct sctp_foo_stuff {
struct sctp_inpcb *inp;
uint32_t lineno;
uint32_t ticks;
int updown;
};
/*
* This is the information we track on each interface that we know about from
@ -284,7 +292,7 @@ struct sctp_data_chunkrec {
struct timeval timetodrop; /* time we drop it from queue */
uint8_t doing_fast_retransmit;
uint8_t rcv_flags; /* flags pulled from data chunk on inbound for
* outbound holds sending flags. */
* outbound holds sending flags for PR-SCTP. */
uint8_t state_flags;
uint8_t chunk_was_revoked;
};
@ -395,12 +403,11 @@ struct sctp_stream_queue_pending {
uint16_t sinfo_flags;
uint16_t stream;
uint16_t strseq;
uint16_t act_flags;
uint8_t msg_is_complete;
uint8_t some_taken;
uint8_t addr_over;
uint8_t act_flags;
uint8_t pr_sctp_on;
uint8_t resv;
};
/*

View File

@ -324,8 +324,9 @@ sctp_threshold_management(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
ph->param_length = htons(oper->m_len);
ippp = (uint32_t *) (ph + 1);
*ippp = htonl(0x40000001);
*ippp = htonl(SCTP_FROM_SCTP_TIMER + SCTP_LOC_1);
}
inp->last_abort_code = SCTP_FROM_SCTP_TIMER + SCTP_LOC_1;
sctp_abort_an_association(inp, stcb, SCTP_FAILED_THRESHOLD, oper);
return (1);
}
@ -681,7 +682,19 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb,
stcb->asoc.total_flight_count--;
chk->sent = SCTP_DATAGRAM_RESEND;
SCTP_STAT_INCR(sctps_markedretrans);
net->flight_size -= chk->book_size;
#ifdef SCTP_FLIGHT_LOGGING
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN,
chk->whoTo->flight_size,
chk->book_size,
(uintptr_t) stcb,
chk->rec.data.TSN_seq);
#endif
if (net->flight_size >= chk->book_size)
net->flight_size -= chk->book_size;
else
net->flight_size = 0;
stcb->asoc.peers_rwnd += chk->send_size;
stcb->asoc.peers_rwnd += sctp_peer_chunk_oh;
@ -747,7 +760,7 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb,
could_be_sent->sent = SCTP_DATAGRAM_RESEND;
}
if (stcb->asoc.sent_queue_retran_cnt != cnt_mk) {
#ifdef INVARIENTS
#ifdef INVARIANTS
printf("Local Audit says there are %d for retran asoc cnt:%d\n",
cnt_mk, stcb->asoc.sent_queue_retran_cnt);
#endif
@ -789,6 +802,13 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb,
}
TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
if (chk->sent < SCTP_DATAGRAM_RESEND) {
#ifdef SCTP_FLIGHT_LOGGING
sctp_misc_ints(SCTP_FLIGHT_LOG_UP,
chk->whoTo->flight_size,
chk->book_size,
(uintptr_t) stcb,
chk->rec.data.TSN_seq);
#endif
stcb->asoc.total_flight += chk->book_size;
chk->whoTo->flight_size += chk->book_size;
stcb->asoc.total_flight_count++;
@ -1077,12 +1097,13 @@ sctp_cookie_timer(struct sctp_inpcb *inp,
ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
ph->param_length = htons(oper->m_len);
ippp = (uint32_t *) (ph + 1);
*ippp = htonl(0x40000002);
*ippp = htonl(SCTP_FROM_SCTP_TIMER + SCTP_LOC_2);
}
inp->last_abort_code = SCTP_FROM_SCTP_TIMER + SCTP_LOC_3;
sctp_abort_an_association(inp, stcb, SCTP_INTERNAL_ERROR,
oper);
} else {
#ifdef INVARIENTS
#ifdef INVARIANTS
panic("Cookie timer expires in wrong state?");
#else
printf("Strange in state %d not cookie-echoed yet c-e timer expires?\n", SCTP_GET_STATE(&stcb->asoc));

View File

@ -853,13 +853,13 @@ struct sctpstat {
u_long sctps_cmt_randry;/* Same for above */
u_long sctps_slowpath_sack; /* Sacks the slow way */
u_long sctps_wu_sacks_sent; /* Window Update only sacks sent */
u_long sctps_locks_in_rcv; /* How man so_rcv buf locks we did */
u_long sctps_locks_in_rcva; /* How man so_rcv buf locks we did */
u_long sctps_locks_in_rcvb; /* How man so_rcv buf locks we did */
u_long sctps_locks_in_rcvc; /* How man so_rcv buf locks we did */
u_long sctps_locks_in_rcvd; /* How man so_rcv buf locks we did */
u_long sctps_locks_in_rcve; /* How man so_rcv buf locks we did */
u_long sctps_locks_in_rcvf; /* How man so_rcv buf locks we did */
u_long sctps_sends_with_flags; /* number of sends with sinfo_flags
* !=0 */
u_long sctps_sends_with_unord;
u_long sctps_sends_with_eof;
u_long sctps_sends_with_abort;
u_long sctps_protocol_drain_calls;
u_long sctps_protocol_drains_done;
};
#define SCTP_STAT_INCR(_x) SCTP_STAT_INCR_BY(_x,1)
@ -884,6 +884,47 @@ union sctp_sockstore {
struct sockaddr sa;
};
struct xsctp_inpcb {
uint32_t last;
uint16_t local_port;
uint16_t number_local_addresses;
uint32_t number_associations;
uint32_t flags;
uint32_t features;
uint32_t total_sends;
uint32_t total_recvs;
uint32_t total_nospaces;
/* add more endpoint specific data here */
};
struct xsctp_tcb {
uint16_t remote_port;
uint16_t number_local_addresses;
uint16_t number_remote_addresses;
uint16_t number_incomming_streams;
uint16_t number_outgoing_streams;
uint32_t state;
uint32_t total_sends;
uint32_t total_recvs;
uint32_t local_tag;
uint32_t remote_tag;
uint32_t initial_tsn;
uint32_t highest_tsn;
uint32_t cumulative_tsn;
uint32_t cumulative_tsn_ack;
/* add more association specific data here */
};
struct xsctp_laddr {
union sctp_sockstore address;
/* add more local address specific data */
};
struct xsctp_raddr {
union sctp_sockstore address;
uint16_t state;
/* add more remote address specific data */
};
/*
* Kernel defined for sctp_send

View File

@ -316,7 +316,8 @@ sctp_notify_mbuf(struct sctp_inpcb *inp,
/* Stop any PMTU timer */
if (callout_pending(&net->pmtu_timer.timer)) {
tmr_stopped = 1;
sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
SCTP_FROM_SCTP_USRREQ + SCTP_LOC_1);
}
/* Adjust destination size limit */
if (net->mtu > nxtsz) {
@ -386,7 +387,7 @@ sctp_notify(struct sctp_inpcb *inp,
* TCB
*/
sctp_abort_notification(stcb, SCTP_PEER_FAULTY);
sctp_free_assoc(inp, stcb, 0);
sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_2);
/* no need to unlock here, since the TCB is gone */
}
} else {
@ -541,6 +542,184 @@ sctp_getcred(SYSCTL_HANDLER_ARGS)
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, getcred, CTLTYPE_OPAQUE | CTLFLAG_RW,
0, 0, sctp_getcred, "S,ucred", "Get the ucred of a SCTP connection");
static int
sctp_assoclist(SYSCTL_HANDLER_ARGS)
{
unsigned int number_of_endpoints;
unsigned int number_of_local_addresses;
unsigned int number_of_associations;
unsigned int number_of_remote_addresses;
unsigned int n;
int error;
struct sctp_inpcb *inp;
struct sctp_tcb *stcb;
struct sctp_nets *net;
struct sctp_laddr *laddr;
struct xsctp_inpcb xinpcb;
struct xsctp_tcb xstcb;
/* struct xsctp_laddr xladdr; */
struct xsctp_raddr xraddr;
number_of_endpoints = 0;
number_of_local_addresses = 0;
number_of_associations = 0;
number_of_remote_addresses = 0;
SCTP_INP_INFO_RLOCK();
if (req->oldptr == USER_ADDR_NULL) {
LIST_FOREACH(inp, &sctppcbinfo.listhead, sctp_list) {
SCTP_INP_RLOCK(inp);
number_of_endpoints++;
/* FIXME MT */
LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
number_of_local_addresses++;
}
LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
number_of_associations++;
/* FIXME MT */
LIST_FOREACH(laddr, &stcb->asoc.sctp_local_addr_list, sctp_nxt_addr) {
number_of_local_addresses++;
}
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
number_of_remote_addresses++;
}
}
SCTP_INP_RUNLOCK(inp);
}
SCTP_INP_INFO_RUNLOCK();
n = (number_of_endpoints + 1) * sizeof(struct xsctp_inpcb) +
number_of_local_addresses * sizeof(struct xsctp_laddr) +
number_of_associations * sizeof(struct xsctp_tcb) +
number_of_remote_addresses * sizeof(struct xsctp_raddr);
#ifdef SCTP_DEBUG
printf("inps = %u, stcbs = %u, laddrs = %u, raddrs = %u\n",
number_of_endpoints, number_of_associations,
number_of_local_addresses, number_of_remote_addresses);
#endif
/* request some more memory than needed */
req->oldidx = (n + n / 8);
return 0;
}
if (req->newptr != USER_ADDR_NULL) {
SCTP_INP_INFO_RUNLOCK();
return EPERM;
}
LIST_FOREACH(inp, &sctppcbinfo.listhead, sctp_list) {
SCTP_INP_RLOCK(inp);
number_of_local_addresses = 0;
number_of_associations = 0;
/*
* LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr)
* { number_of_local_addresses++; }
*/
LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
number_of_associations++;
}
xinpcb.last = 0;
xinpcb.local_port = ntohs(inp->sctp_lport);
xinpcb.number_local_addresses = number_of_local_addresses;
xinpcb.number_associations = number_of_associations;
xinpcb.flags = inp->sctp_flags;
xinpcb.features = inp->sctp_features;
xinpcb.total_sends = inp->total_sends;
xinpcb.total_recvs = inp->total_recvs;
xinpcb.total_nospaces = inp->total_nospaces;
SCTP_INP_INCR_REF(inp);
SCTP_INP_RUNLOCK(inp);
SCTP_INP_INFO_RUNLOCK();
error = SYSCTL_OUT(req, &xinpcb, sizeof(struct xsctp_inpcb));
if (error) {
return error;
}
SCTP_INP_INFO_RLOCK();
SCTP_INP_RLOCK(inp);
/* FIXME MT */
/*
* LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr)
* { error = SYSCTL_OUT(req, &xladdr, sizeof(struct
* xsctp_laddr)); if (error) { #if
* defined(SCTP_APPLE_FINE_GRAINED_LOCKING)
* socket_unlock(inp->ip_inp.inp.inp_socket, 1);
* lck_rw_unlock_shared(sctppcbinfo.ipi_ep_mtx); #endif
* SCTP_INP_RUNLOCK(inp); SCTP_INP_INFO_RUNLOCK(); return
* error; } }
*/
LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
SCTP_TCB_LOCK(stcb);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
number_of_local_addresses = 0;
number_of_remote_addresses = 0;
/* FIXME MT */
/*
* LIST_FOREACH(laddr,
* &stcb->asoc.sctp_local_addr_list, sctp_nxt_addr)
* { number_of_local_addresses++; }
*/
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
number_of_remote_addresses++;
}
xstcb.remote_port = ntohs(stcb->rport);
xstcb.number_local_addresses = number_of_local_addresses;
xstcb.number_remote_addresses = number_of_remote_addresses;
xstcb.number_incomming_streams = 0;
xstcb.number_outgoing_streams = 0;
xstcb.state = stcb->asoc.state;
xstcb.total_sends = stcb->total_sends;
xstcb.total_recvs = stcb->total_recvs;
xstcb.local_tag = stcb->asoc.my_vtag;
xstcb.remote_tag = stcb->asoc.peer_vtag;
xstcb.initial_tsn = stcb->asoc.init_seq_number;
xstcb.highest_tsn = stcb->asoc.sending_seq - 1;
xstcb.cumulative_tsn = stcb->asoc.last_acked_seq;
xstcb.cumulative_tsn_ack = stcb->asoc.cumulative_tsn;
SCTP_INP_RUNLOCK(inp);
SCTP_INP_INFO_RUNLOCK();
error = SYSCTL_OUT(req, &xstcb, sizeof(struct xsctp_tcb));
if (error) {
atomic_add_int(&stcb->asoc.refcnt, -1);
return error;
}
/* FIXME MT */
/*
* LIST_FOREACH(laddr,
* &stcb->asoc.sctp_local_addr_list, sctp_nxt_addr)
* { error = SYSCTL_OUT(req, &xladdr, sizeof(struct
* xsctp_laddr)); if (error) { #if
* defined(SCTP_APPLE_FINE_GRAINED_LOCKING)
* socket_unlock(inp->ip_inp.inp.inp_socket, 1);
* lck_rw_unlock_shared(sctppcbinfo.ipi_ep_mtx);
* #endif SCTP_INP_RUNLOCK(inp);
* SCTP_INP_INFO_RUNLOCK(); return error; }
* */
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
xraddr.state = net->dest_state;
xraddr.address = net->ro._l_addr;
error = SYSCTL_OUT(req, &xraddr, sizeof(struct xsctp_raddr));
if (error) {
atomic_add_int(&stcb->asoc.refcnt, -1);
return error;
}
}
atomic_add_int(&stcb->asoc.refcnt, -1);
SCTP_INP_INFO_RLOCK();
SCTP_INP_RLOCK(inp);
}
SCTP_INP_DECR_REF(inp);
SCTP_INP_RUNLOCK(inp);
}
SCTP_INP_INFO_RUNLOCK();
xinpcb.last = 1;
xinpcb.local_port = 0;
xinpcb.number_local_addresses = 0;
xinpcb.number_associations = 0;
xinpcb.flags = 0;
xinpcb.features = 0;
error = SYSCTL_OUT(req, &xinpcb, sizeof(struct xsctp_inpcb));
return error;
}
/*
* sysctl definitions
@ -604,12 +783,10 @@ SYSCTL_INT(_net_inet_sctp, OID_AUTO, asoc_resource, CTLFLAG_RW,
&sctp_asoc_free_resc_limit, 0,
"Max number of cached resources in an asoc");
SYSCTL_INT(_net_inet_sctp, OID_AUTO, chunkscale, CTLFLAG_RW,
&sctp_chunkscale, 0,
"Tuneable for Scaling of number of chunks and messages");
SYSCTL_UINT(_net_inet_sctp, OID_AUTO, delayed_sack_time, CTLFLAG_RW,
&sctp_delayed_sack_time_default, 0,
"Default delayed SACK timer in msec");
@ -666,7 +843,6 @@ SYSCTL_UINT(_net_inet_sctp, OID_AUTO, add_more_on_output, CTLFLAG_RW,
&sctp_add_more_threshold, 0,
"When space wise is it worthwhile to try to add more to a socket send buffer");
SYSCTL_UINT(_net_inet_sctp, OID_AUTO, nr_outgoing_streams, CTLFLAG_RW,
&sctp_nr_outgoing_streams_default, 0,
"Default number of outgoing streams");
@ -742,6 +918,11 @@ SYSCTL_INT(_net_inet_sctp, OID_AUTO, strict_data_order, CTLFLAG_RW,
SYSCTL_STRUCT(_net_inet_sctp, OID_AUTO, stats, CTLFLAG_RW,
&sctpstat, sctpstat,
"SCTP statistics (struct sctps_stat, netinet/sctp.h");
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, assoclist, CTLFLAG_RD,
0, 0, sctp_assoclist,
"S,xassoc", "List of active SCTP associations");
#ifdef SCTP_DEBUG
SYSCTL_INT(_net_inet_sctp, OID_AUTO, debug, CTLFLAG_RW,
&sctp_debug_on, 0, "Configure debug output");
@ -1106,7 +1287,7 @@ sctp_disconnect(struct socket *so)
(SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
sctp_free_assoc(inp, stcb, 0);
sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_3);
/* No unlock tcb assoc is gone */
splx(s);
return (0);
@ -1187,8 +1368,9 @@ sctp_disconnect(struct socket *so)
SCTP_CAUSE_USER_INITIATED_ABT);
ph->param_length = htons(op_err->m_len);
ippp = (uint32_t *) (ph + 1);
*ippp = htonl(0x30000007);
*ippp = htonl(SCTP_FROM_SCTP_USRREQ + SCTP_LOC_4);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ + SCTP_LOC_4;
sctp_send_abort_tcb(stcb, op_err);
SCTP_STAT_INCR_COUNTER32(sctps_aborted);
if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
@ -1196,7 +1378,7 @@ sctp_disconnect(struct socket *so)
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
SCTP_INP_RUNLOCK(inp);
sctp_free_assoc(inp, stcb, 0);
sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_5);
splx(s);
return (0);
}
@ -1325,8 +1507,9 @@ sctp_shutdown(struct socket *so)
SCTP_CAUSE_USER_INITIATED_ABT);
ph->param_length = htons(op_err->m_len);
ippp = (uint32_t *) (ph + 1);
*ippp = htonl(0x30000008);
*ippp = htonl(SCTP_FROM_SCTP_USRREQ + SCTP_LOC_6);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ + SCTP_LOC_6;
sctp_abort_an_association(stcb->sctp_ep, stcb,
SCTP_RESPONSE_TO_USER_REQ,
op_err);
@ -1744,17 +1927,17 @@ sctp_do_connect_x(struct socket *so,
for (i = 1; i < totaddr; i++) {
if (sa->sa_family == AF_INET) {
incr = sizeof(struct sockaddr_in);
if (sctp_add_remote_addr(stcb, sa, 0, 8)) {
if (sctp_add_remote_addr(stcb, sa, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
/* assoc gone no un-lock */
sctp_free_assoc(inp, stcb, 0);
sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_7);
error = ENOBUFS;
goto out_now;
}
} else if (sa->sa_family == AF_INET6) {
incr = sizeof(struct sockaddr_in6);
if (sctp_add_remote_addr(stcb, sa, 0, 8)) {
if (sctp_add_remote_addr(stcb, sa, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
/* assoc gone no un-lock */
sctp_free_assoc(inp, stcb, 0);
sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_8);
error = ENOBUFS;
goto out_now;
}
@ -3626,7 +3809,9 @@ sctp_optsset(struct socket *so,
if (stcb->asoc.delayed_connection == 1) {
stcb->asoc.delayed_connection = 0;
SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, stcb->asoc.primary_destination);
sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb,
stcb->asoc.primary_destination,
SCTP_FROM_SCTP_USRREQ + SCTP_LOC_9);
sctp_send_initiate(inp, stcb);
} else {
/*
@ -3928,7 +4113,8 @@ sctp_optsset(struct socket *so,
}
if (paddrp->spp_flags & SPP_PMTUD_DISABLE) {
if (callout_pending(&net->pmtu_timer.timer)) {
sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
}
if (paddrp->spp_pathmtu > SCTP_DEFAULT_MINSEGMENT) {
net->mtu = paddrp->spp_pathmtu;
@ -3983,7 +4169,7 @@ sctp_optsset(struct socket *so,
* addresses
*/
if (cnt_of_unconf == 0) {
sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_11);
}
}
if (paddrp->spp_flags & SPP_HB_ENABLE) {

View File

@ -625,7 +625,7 @@ sctp_fill_stat_log(struct mbuf *m)
req->end_at = sctp_cwnd_log_at - 1;
req->num_ret = sctp_cwnd_log_at;
}
#ifdef INVARIENTS
#ifdef INVARIANTS
if (req->num_ret > num) {
panic("Bad statlog get?");
}
@ -1269,6 +1269,7 @@ sctp_timeout_handler(void *t)
splx(s);
return;
}
tmr->stopped_from = 0xa001;
if (!SCTP_IS_TIMER_TYPE_VALID(tmr->type)) {
/*
* printf("SCTP timer fired with invalid type: 0x%x\n",
@ -1277,11 +1278,13 @@ sctp_timeout_handler(void *t)
splx(s);
return;
}
tmr->stopped_from = 0xa002;
if ((tmr->type != SCTP_TIMER_TYPE_ADDR_WQ) && (inp == NULL)) {
splx(s);
return;
}
/* if this is an iterator timeout, get the struct and clear inp */
tmr->stopped_from = 0xa003;
if (tmr->type == SCTP_TIMER_TYPE_ITERATOR) {
it = (struct sctp_iterator *)inp;
inp = NULL;
@ -1300,6 +1303,7 @@ sctp_timeout_handler(void *t)
return;
}
}
tmr->stopped_from = 0xa004;
if (stcb) {
if (stcb->asoc.state == 0) {
splx(s);
@ -1309,6 +1313,7 @@ sctp_timeout_handler(void *t)
return;
}
}
tmr->stopped_from = 0xa005;
#ifdef SCTP_DEBUG
if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
printf("Timer type %d goes off\n", tmr->type);
@ -1321,6 +1326,10 @@ sctp_timeout_handler(void *t)
}
return;
}
tmr->stopped_from = 0xa006;
/* record in stopped what t-o occured */
tmr->stopped_from = tmr->type;
if (stcb) {
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_LOCK(stcb);
@ -1523,8 +1532,8 @@ sctp_timeout_handler(void *t)
SCTP_STAT_INCR(sctps_timoassockill);
/* Can we free it yet? */
SCTP_INP_DECR_REF(inp);
sctp_timer_stop(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL);
sctp_free_assoc(inp, stcb, 0);
sctp_timer_stop(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL, SCTP_FROM_SCTPUTIL + SCTP_LOC_1);
sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL + SCTP_LOC_2);
/*
* free asoc, always unlocks (or destroy's) so prevent
* duplicate unlock or unlock of a free mtx :-0
@ -1539,7 +1548,7 @@ sctp_timeout_handler(void *t)
* killer
*/
SCTP_INP_DECR_REF(inp);
sctp_timer_stop(SCTP_TIMER_TYPE_INPKILL, inp, NULL, NULL);
sctp_timer_stop(SCTP_TIMER_TYPE_INPKILL, inp, NULL, NULL, SCTP_FROM_SCTPUTIL + SCTP_LOC_3);
sctp_inpcb_free(inp, 1, 0);
goto out_no_decr;
break;
@ -1931,6 +1940,7 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
if (t_type == SCTP_TIMER_TYPE_SEND) {
stcb->asoc.num_send_timers_up++;
}
tmr->stopped_from = 0;
tmr->type = t_type;
tmr->ep = (void *)inp;
tmr->tcb = (void *)stcb;
@ -1943,7 +1953,7 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
int
sctp_timer_stop(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
struct sctp_nets *net)
struct sctp_nets *net, uint32_t from)
{
struct sctp_timer *tmr;
@ -2100,6 +2110,7 @@ sctp_timer_stop(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
}
}
tmr->self = NULL;
tmr->stopped_from = from;
callout_stop(&tmr->timer);
return (0);
}
@ -2367,6 +2378,12 @@ sctp_calculate_rto(struct sctp_tcb *stcb,
} else if ((u_long)now.tv_usec < (u_long)old->tv_usec) {
/* impossible .. garbage in nothing out */
return (((net->lastsa >> 2) + net->lastsv) >> 1);
} else if ((u_long)now.tv_usec == (u_long)old->tv_usec) {
/*
* We have to have 1 usec :-D this must be the
* loopback.
*/
calc_time = 1;
} else {
/* impossible .. garbage in nothing out */
return (((net->lastsa >> 2) + net->lastsv) >> 1);
@ -2378,27 +2395,6 @@ sctp_calculate_rto(struct sctp_tcb *stcb,
/***************************/
/* 2. update RTTVAR & SRTT */
/***************************/
#if 0
/* if (net->lastsv || net->lastsa) { */
/* per Section 5.3.1 C3 in SCTP */
/* net->lastsv = (int) *//* RTTVAR */
/*
* (((double)(1.0 - 0.25) * (double)net->lastsv) + (double)(0.25 *
* (double)abs(net->lastsa - calc_time))); net->lastsa = (int)
*//* SRTT */
/*
* (((double)(1.0 - 0.125) * (double)net->lastsa) + (double)(0.125 *
* (double)calc_time)); } else {
*//* the first RTT calculation, per C2 Section 5.3.1 */
/* net->lastsa = calc_time; *//* SRTT */
/* net->lastsv = calc_time / 2; *//* RTTVAR */
/* } */
/* if RTTVAR goes to 0 you set to clock grainularity */
/*
* if (net->lastsv == 0) { net->lastsv = SCTP_CLOCK_GRANULARITY; }
* new_rto = net->lastsa + 4 * net->lastsv;
*/
#endif
o_calctime = calc_time;
/* this is Van Jacobson's integer version */
if (net->RTO) {
@ -3380,7 +3376,7 @@ sctp_abort_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
sctp_send_abort(m, iphlen, sh, vtag, op_err);
if (stcb != NULL) {
/* Ok, now lets free it */
sctp_free_assoc(inp, stcb, 0);
sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL + SCTP_LOC_4);
} else {
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
if (LIST_FIRST(&inp->sctp_asoc_list) == NULL) {
@ -3417,7 +3413,7 @@ sctp_abort_an_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
/* now free the asoc */
sctp_free_assoc(inp, stcb, 0);
sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL + SCTP_LOC_5);
}
void
@ -3787,12 +3783,14 @@ sctp_add_to_readq(struct sctp_inpcb *inp,
if (inp == NULL) {
/* Gak, TSNH!! */
#ifdef INVARIENTS
#ifdef INVARIANTS
panic("Gak, inp NULL on add_to_readq");
#endif
return;
}
SCTP_INP_READ_LOCK(inp);
atomic_add_int(&inp->total_recvs, 1);
atomic_add_int(&stcb->total_recvs, 1);
m = control->data;
control->held_length = 0;
control->length = 0;
@ -3914,7 +3912,7 @@ sctp_append_to_readq(struct sctp_inpcb *inp,
/* Really there should always be a prev */
if (m == NULL) {
/* Huh nothing left? */
#ifdef INVARIENTS
#ifdef INVARIANTS
panic("Nothing left to add?");
#else
goto get_out;
@ -3938,7 +3936,7 @@ sctp_append_to_readq(struct sctp_inpcb *inp,
control->tail_mbuf = tail;
} else {
/* nothing there */
#ifdef INVARIENTS
#ifdef INVARIANTS
if (control->data != NULL) {
panic("This should NOT happen");
}
@ -4233,7 +4231,7 @@ sctp_user_rcvd(struct sctp_tcb *stcb, int *freed_so_far, int hold_rlock,
sctp_chunk_output(stcb->sctp_ep, stcb,
SCTP_OUTPUT_FROM_USR_RCVD);
/* make sure no timer is running */
sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, NULL);
sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTPUTIL + SCTP_LOC_6);
SCTP_TCB_UNLOCK(stcb);
} else {
/* Update how much we have pending */
@ -4248,7 +4246,6 @@ sctp_user_rcvd(struct sctp_tcb *stcb, int *freed_so_far, int hold_rlock,
}
out:
if (so && r_unlocked && hold_rlock) {
SCTP_STAT_INCR(sctps_locks_in_rcv);
SCTP_INP_READ_LOCK(stcb->sctp_ep);
}
SCTP_INP_DECR_REF(stcb->sctp_ep);
@ -4438,7 +4435,7 @@ sctp_sorecvmsg(struct socket *so,
}
control = TAILQ_FIRST(&inp->read_queue);
if ((control == NULL) && (so->so_rcv.sb_cc != 0)) {
#ifdef INVARIENTS
#ifdef INVARIANTS
panic("Huh, its non zero and nothing on control?");
#endif
so->so_rcv.sb_cc = 0;
@ -4454,7 +4451,6 @@ sctp_sorecvmsg(struct socket *so,
* pdapi.. maybe a peer in EEOR that just closed after
* sending and never indicated a EOR.
*/
SCTP_STAT_INCR(sctps_locks_in_rcva);
if (hold_rlock == 0) {
hold_rlock = 1;
SCTP_INP_READ_LOCK(inp);
@ -4701,7 +4697,6 @@ sctp_sorecvmsg(struct socket *so,
m->m_len,
control->length);
#endif
SCTP_STAT_INCR(sctps_locks_in_rcvb);
SCTP_INP_READ_LOCK(inp);
hold_rlock = 1;
}
@ -4756,7 +4751,7 @@ sctp_sorecvmsg(struct socket *so,
* lock ok to null tail
*/
if (control->data == NULL) {
#ifdef INVARIENTS
#ifdef INVARIANTS
if ((control->end_added == 0) ||
(TAILQ_NEXT(control, next) == NULL)) {
/*
@ -4772,7 +4767,7 @@ sctp_sorecvmsg(struct socket *so,
}
#endif
control->tail_mbuf = NULL;
#ifdef INVARIENTS
#ifdef INVARIANTS
if ((control->end_added) && ((out_flags & MSG_EOR) == 0)) {
panic("end_added, nothing left and no MSG_EOR");
}
@ -4854,7 +4849,7 @@ sctp_sorecvmsg(struct socket *so,
/* we are done with this control */
if (control->length == 0) {
if (control->data) {
#ifdef INVARIENTS
#ifdef INVARIANTS
panic("control->data not null at read eor?");
#else
printf("Strange, data left in the control buffer .. invarients would panic?\n");
@ -4880,7 +4875,6 @@ sctp_sorecvmsg(struct socket *so,
* queue).
*/
if (hold_rlock == 0) {
SCTP_STAT_INCR(sctps_locks_in_rcvc);
SCTP_INP_READ_LOCK(inp);
hold_rlock = 1;
}
@ -4907,7 +4901,7 @@ sctp_sorecvmsg(struct socket *so,
* since we are leaving more behind on the
* control to read.
*/
#ifdef INVARIENTS
#ifdef INVARIANTS
if (control->end_added && (control->data == NULL) &&
(control->tail_mbuf == NULL)) {
panic("Gak, control->length is corrupt?");
@ -5000,7 +4994,6 @@ sctp_sorecvmsg(struct socket *so,
goto done_with_control;
}
if (so->so_rcv.sb_cc > held_length) {
SCTP_STAT_INCR(sctps_locks_in_rcvf);
control->held_length = so->so_rcv.sb_cc;
held_length = 0;
}

View File

@ -75,7 +75,7 @@ sctp_timer_start(int, struct sctp_inpcb *, struct sctp_tcb *,
int
sctp_timer_stop(int, struct sctp_inpcb *, struct sctp_tcb *,
struct sctp_nets *);
struct sctp_nets *, uint32_t);
uint32_t sctp_calculate_sum(struct mbuf *, int32_t *, uint32_t);

View File

@ -241,7 +241,15 @@ sctp6_input(mp, offp, proto)
(u_int8_t *) & chunk_buf);
sh->v_tag = init_chk->init.initiate_tag;
}
sctp_send_abort(m, iphlen, sh, 0, NULL);
if (ch->chunk_type == SCTP_SHUTDOWN_ACK) {
sctp_send_shutdown_complete2(m, iphlen, sh);
goto bad;
}
if (ch->chunk_type == SCTP_SHUTDOWN_COMPLETE) {
goto bad;
}
if (ch->chunk_type != SCTP_ABORT_ASSOCIATION)
sctp_send_abort(m, iphlen, sh, 0, NULL);
goto bad;
} else if (stcb == NULL) {
refcount_up = 1;
@ -326,7 +334,7 @@ sctp6_notify_mbuf(struct sctp_inpcb *inp,
*/
nxtsz = ntohl(icmp6->icmp6_mtu);
/* Stop any PMTU timer */
sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, NULL);
sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, NULL, SCTP_FROM_SCTP6_USRREQ + SCTP_LOC_1);
/* Adjust destination size limit */
if (net->mtu > nxtsz) {
@ -822,7 +830,8 @@ sctp6_disconnect(struct socket *so)
(SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
sctp_free_assoc(inp, stcb, 0);
sctp_free_assoc(inp, stcb, SCTP_DONOT_SETSCOPE,
SCTP_FROM_SCTP6_USRREQ + SCTP_LOC_2);
/* No unlock tcb assoc is gone */
splx(s);
return (0);