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:
parent
d398e83b8a
commit
3de80805ff
@ -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) -
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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 { \
|
||||
|
@ -43,6 +43,8 @@ __FBSDID("$FreeBSD$");
|
||||
*/
|
||||
typedef struct mbuf *sctp_mbuf_t;
|
||||
|
||||
#define USER_ADDR_NULL (NULL) /* FIX ME: temp */
|
||||
|
||||
/*
|
||||
* general memory allocation
|
||||
*/
|
||||
|
@ -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?");
|
||||
|
@ -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 */
|
||||
|
@ -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 *);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user