summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/netinet/sctp.h2
-rw-r--r--sys/netinet/sctp_asconf.c14
-rw-r--r--sys/netinet/sctp_auth.c2
-rw-r--r--sys/netinet/sctp_constants.h13
-rw-r--r--sys/netinet/sctp_header.h1
-rw-r--r--sys/netinet/sctp_indata.c58
-rw-r--r--sys/netinet/sctp_input.c167
-rw-r--r--sys/netinet/sctp_os.h1
-rw-r--r--sys/netinet/sctp_os_bsd.h21
-rw-r--r--sys/netinet/sctp_output.c263
-rw-r--r--sys/netinet/sctp_pcb.c119
-rw-r--r--sys/netinet/sctp_pcb.h1
-rw-r--r--sys/netinet/sctp_peeloff.c16
-rw-r--r--sys/netinet/sctp_structs.h6
-rw-r--r--sys/netinet/sctp_sysctl.c8
-rw-r--r--sys/netinet/sctp_sysctl.h18
-rw-r--r--sys/netinet/sctp_timer.c16
-rw-r--r--sys/netinet/sctp_usrreq.c271
-rw-r--r--sys/netinet/sctp_var.h13
-rw-r--r--sys/netinet/sctputil.c164
-rw-r--r--sys/netinet/sctputil.h5
-rw-r--r--sys/netinet6/sctp6_usrreq.c67
-rw-r--r--sys/sys/mbuf.h2
23 files changed, 979 insertions, 269 deletions
diff --git a/sys/netinet/sctp.h b/sys/netinet/sctp.h
index 659ef4e..bd060d0 100644
--- a/sys/netinet/sctp.h
+++ b/sys/netinet/sctp.h
@@ -534,5 +534,7 @@ __attribute__((packed));
#define SCTP_LTRACE_CHUNK_ENABLE 0x00400000
#define SCTP_LTRACE_ERROR_ENABLE 0x00800000
#define SCTP_LAST_PACKET_TRACING 0x01000000
+#define SCTP_THRESHOLD_LOGGING 0x02000000
+
#endif /* !_NETINET_SCTP_H_ */
diff --git a/sys/netinet/sctp_asconf.c b/sys/netinet/sctp_asconf.c
index b66e1b2..d7a8db2 100644
--- a/sys/netinet/sctp_asconf.c
+++ b/sys/netinet/sctp_asconf.c
@@ -1140,6 +1140,13 @@ sctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
net->error_count = 0;
}
stcb->asoc.overall_error_count = 0;
+ if (sctp_logging_level & SCTP_THRESHOLD_LOGGING) {
+ sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
+ stcb->asoc.overall_error_count,
+ 0,
+ SCTP_FROM_SCTP_ASCONF,
+ __LINE__);
+ }
/* queue in an advisory set primary too */
(void)sctp_asconf_queue_mgmt(stcb, ifa, SCTP_SET_PRIM_ADDR);
/* let caller know we should send this out immediately */
@@ -2002,7 +2009,7 @@ sctp_asconf_iterator_end(void *ptr, uint32_t val)
* sa is the sockaddr to ask the peer to set primary to.
* returns: 0 = completed, -1 = error
*/
-int
+int32_t
sctp_set_primary_ip_address_sa(struct sctp_tcb *stcb, struct sockaddr *sa)
{
/* NOTE: we currently don't check the validity of the address! */
@@ -2691,6 +2698,7 @@ sctp_addr_mgmt_ep_sa(struct sctp_inpcb *inp, struct sockaddr *sa,
struct sctp_ifa *ifa;
if (sa->sa_len == 0) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EINVAL);
return (EINVAL);
}
if (sctp_ifap) {
@@ -2713,12 +2721,14 @@ sctp_addr_mgmt_ep_sa(struct sctp_inpcb *inp, struct sockaddr *sa,
sizeof(struct sctp_asconf_iterator),
SCTP_M_ASC_IT);
if (asc == NULL) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, ENOMEM);
return (ENOMEM);
}
wi = SCTP_ZONE_GET(sctppcbinfo.ipi_zone_laddr,
struct sctp_laddr);
if (wi == NULL) {
SCTP_FREE(asc, SCTP_M_ASC_IT);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, ENOMEM);
return (ENOMEM);
}
if (type == SCTP_ADD_IP_ADDRESS) {
@@ -2730,6 +2740,7 @@ sctp_addr_mgmt_ep_sa(struct sctp_inpcb *inp, struct sockaddr *sa,
/* can't delete the last local address */
SCTP_FREE(asc, SCTP_M_ASC_IT);
SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_laddr, wi);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EINVAL);
return (EINVAL);
}
LIST_FOREACH(laddr, &inp->sctp_addr_list,
@@ -2757,6 +2768,7 @@ sctp_addr_mgmt_ep_sa(struct sctp_inpcb *inp, struct sockaddr *sa,
sctp_asconf_iterator_end, inp, 0);
} else {
/* invalid address! */
+ SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EADDRNOTAVAIL);
return (EADDRNOTAVAIL);
}
return (0);
diff --git a/sys/netinet/sctp_auth.c b/sys/netinet/sctp_auth.c
index e5bf051..2e7d457 100644
--- a/sys/netinet/sctp_auth.c
+++ b/sys/netinet/sctp_auth.c
@@ -780,7 +780,7 @@ sctp_alloc_authinfo(void)
/* out of memory */
return (NULL);
}
- bzero(&new_authinfo, sizeof(*new_authinfo));
+ bzero(new_authinfo, sizeof(*new_authinfo));
return (new_authinfo);
}
diff --git a/sys/netinet/sctp_constants.h b/sys/netinet/sctp_constants.h
index cf852a4..f6bdf34 100644
--- a/sys/netinet/sctp_constants.h
+++ b/sys/netinet/sctp_constants.h
@@ -209,8 +209,11 @@ __FBSDID("$FreeBSD$");
#define SCTP_FLIGHT_LOG_DOWN_PMTU 115
#define SCTP_SACK_LOG_NORMAL 116
#define SCTP_SACK_LOG_EXPRESS 117
+#define SCTP_MAP_TSN_ENTERS 118
+#define SCTP_THRESHOLD_CLEAR 119
+#define SCTP_THRESHOLD_INCR 120
-#define SCTP_LOG_MAX_TYPES 118
+#define SCTP_LOG_MAX_TYPES 121
/*
* To turn on various logging, you must first enable 'options KTR' and
* you might want to bump the entires 'options KTR_ENTRIES=80000'.
@@ -220,6 +223,12 @@ __FBSDID("$FreeBSD$");
* This gets the compile in place, but you still need to turn the
* logging flag on too in the sysctl (see in sctp.h).
*/
+
+/* For SCTP only logging */
+#define SCTP_MAX_LOGGING_SIZE 30000
+#define SCTP_TRACE_PARAMS 6
+
+
#define SCTP_LOG_EVENT_UNKNOWN 0
#define SCTP_LOG_EVENT_CWND 1
#define SCTP_LOG_EVENT_BLOCK 2
@@ -480,6 +489,7 @@ __FBSDID("$FreeBSD$");
#define SCTP_STATE_MASK 0x007f
#define SCTP_GET_STATE(asoc) ((asoc)->state & SCTP_STATE_MASK)
+#define SCTP_SET_STATE(asoc, newstate) ((asoc)->state = ((asoc)->state & ~SCTP_STATE_MASK) | newstate)
/* SCTP reachability state for each address */
#define SCTP_ADDR_REACHABLE 0x001
@@ -831,6 +841,7 @@ __FBSDID("$FreeBSD$");
#define SCTP_FROM_SCTP_OUTPUT 0x90000000
#define SCTP_FROM_SCTP_PEELOFF 0xa0000000
#define SCTP_FROM_SCTP_PANDA 0xb0000000
+#define SCTP_FROM_SCTP_SYSCTL 0xc0000000
/* Location ID's */
#define SCTP_LOC_1 0x00000001
diff --git a/sys/netinet/sctp_header.h b/sys/netinet/sctp_header.h
index 121c796..090e96d 100644
--- a/sys/netinet/sctp_header.h
+++ b/sys/netinet/sctp_header.h
@@ -36,7 +36,6 @@ __FBSDID("$FreeBSD$");
#ifndef __sctp_header_h__
#define __sctp_header_h__
-
#include <sys/time.h>
#include <netinet/sctp.h>
#include <netinet/sctp_constants.h>
diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c
index 30aa980..aa85a6f 100644
--- a/sys/netinet/sctp_indata.c
+++ b/sys/netinet/sctp_indata.c
@@ -775,7 +775,7 @@ doit_again:
* but should we?
*/
if ((sctp_is_all_msg_on_reasm(asoc, &tsize) ||
- (tsize > stcb->sctp_ep->partial_delivery_point))) {
+ (tsize >= stcb->sctp_ep->partial_delivery_point))) {
/*
* Yes, we setup to start reception, by
@@ -1452,7 +1452,7 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
protocol_id = ch->dp.protocol_id;
ordered = ((ch->ch.chunk_flags & SCTP_DATA_UNORDERED) == 0);
if (sctp_logging_level & SCTP_MAP_LOGGING_ENABLE) {
- sctp_log_map(0, tsn, asoc->cumulative_tsn, SCTP_MAP_PREPARE_SLIDE);
+ sctp_log_map(tsn, asoc->cumulative_tsn, asoc->highest_tsn_inside_map, SCTP_MAP_TSN_ENTERS);
}
if (stcb == NULL) {
return (0);
@@ -2209,7 +2209,7 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort
*/
struct sctp_association *asoc;
int i, at;
- int all_ones, last_all_ones = 0;
+ int last_all_ones = 0;
int slide_from, slide_end, lgap, distance;
uint32_t old_cumack, old_base, old_highest;
unsigned char aux_array[64];
@@ -2231,7 +2231,6 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort
* We could probably improve this a small bit by calculating the
* offset of the current cum-ack as the starting point.
*/
- all_ones = 1;
at = 0;
for (i = 0; i < stcb->asoc.mapping_array_size; i++) {
@@ -2240,7 +2239,6 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort
last_all_ones = 1;
} else {
/* there is a 0 bit */
- all_ones = 0;
at += sctp_map_lookup_tab[asoc->mapping_array[i]];
last_all_ones = 0;
break;
@@ -2260,24 +2258,16 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort
asoc->highest_tsn_inside_map = asoc->cumulative_tsn;
#endif
}
- if (all_ones ||
- (asoc->cumulative_tsn == asoc->highest_tsn_inside_map && at >= 8)) {
+ if ((asoc->cumulative_tsn == asoc->highest_tsn_inside_map) && (at >= 8)) {
/* The complete array was completed by a single FR */
/* higest becomes the cum-ack */
int clr;
asoc->cumulative_tsn = asoc->highest_tsn_inside_map;
/* clear the array */
- if (all_ones)
+ clr = (at >> 3) + 1;
+ if (clr > asoc->mapping_array_size) {
clr = asoc->mapping_array_size;
- else {
- clr = (at >> 3) + 1;
- /*
- * this should be the allones case but just in case
- * :>
- */
- if (clr > asoc->mapping_array_size)
- clr = asoc->mapping_array_size;
}
memset(asoc->mapping_array, 0, clr);
/* base becomes one ahead of the cum-ack */
@@ -2467,7 +2457,7 @@ doit_again:
* delivery queue and something can be delivered.
*/
if ((sctp_is_all_msg_on_reasm(asoc, &tsize) ||
- (tsize > stcb->sctp_ep->partial_delivery_point))) {
+ (tsize >= stcb->sctp_ep->partial_delivery_point))) {
asoc->fragmented_delivery_inprogress = 1;
asoc->tsn_last_delivered = chk->rec.data.TSN_seq - 1;
asoc->str_of_pdapi = chk->rec.data.stream_number;
@@ -2722,10 +2712,17 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
}
if (num_chunks) {
/*
- * Did we get data, if so update the time for auto-close and
+ * Did we get data, if sa update the time for auto-close and
* give peer credit for being alive.
*/
SCTP_STAT_INCR(sctps_recvpktwithdata);
+ if (sctp_logging_level & SCTP_THRESHOLD_LOGGING) {
+ sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
+ stcb->asoc.overall_error_count,
+ 0,
+ SCTP_FROM_SCTP_INDATA,
+ __LINE__);
+ }
stcb->asoc.overall_error_count = 0;
(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_last_rcvd);
}
@@ -3866,6 +3863,13 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
}
}
asoc->this_sack_highest_gap = cumack;
+ if (sctp_logging_level & SCTP_THRESHOLD_LOGGING) {
+ sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
+ stcb->asoc.overall_error_count,
+ 0,
+ SCTP_FROM_SCTP_INDATA,
+ __LINE__);
+ }
stcb->asoc.overall_error_count = 0;
if (compare_with_wrap(cumack, asoc->last_acked_seq, MAX_TSN)) {
/* process the new consecutive TSN first */
@@ -4187,7 +4191,7 @@ again:
(SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
- asoc->state = SCTP_STATE_SHUTDOWN_SENT;
+ SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
sctp_stop_timers_for_shutdown(stcb);
sctp_send_shutdown(stcb,
stcb->asoc.primary_destination);
@@ -4202,7 +4206,7 @@ again:
goto abort_out_now;
}
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
- asoc->state = SCTP_STATE_SHUTDOWN_ACK_SENT;
+ SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT);
sctp_send_shutdown_ack(stcb,
stcb->asoc.primary_destination);
@@ -4296,6 +4300,13 @@ sctp_handle_sack(struct mbuf *m, int offset,
num_dup = ntohs(sack->num_dup_tsns);
old_rwnd = stcb->asoc.peers_rwnd;
+ if (sctp_logging_level & SCTP_THRESHOLD_LOGGING) {
+ sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
+ stcb->asoc.overall_error_count,
+ 0,
+ SCTP_FROM_SCTP_INDATA,
+ __LINE__);
+ }
stcb->asoc.overall_error_count = 0;
asoc = &stcb->asoc;
if (sctp_logging_level & SCTP_SACK_LOGGING_ENABLE) {
@@ -4847,7 +4858,7 @@ done_with_it:
(SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
- asoc->state = SCTP_STATE_SHUTDOWN_SENT;
+ SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
sctp_stop_timers_for_shutdown(stcb);
sctp_send_shutdown(stcb,
stcb->asoc.primary_destination);
@@ -4863,7 +4874,7 @@ done_with_it:
goto abort_out_now;
}
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
- asoc->state = SCTP_STATE_SHUTDOWN_ACK_SENT;
+ SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT);
sctp_send_shutdown_ack(stcb,
stcb->asoc.primary_destination);
@@ -5254,6 +5265,9 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
if (gap > m_size) {
asoc->highest_tsn_inside_map = back_out_htsn;
+ if (sctp_logging_level & SCTP_MAP_LOGGING_ENABLE) {
+ sctp_log_map(0, 0, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT);
+ }
if ((long)gap > sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv)) {
struct mbuf *oper;
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index 46c23cd..32adf9b 100644
--- a/sys/netinet/sctp_input.c
+++ b/sys/netinet/sctp_input.c
@@ -425,6 +425,13 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset,
op_err = NULL;
}
/* extract the cookie and queue it to "echo" it back... */
+ if (sctp_logging_level & SCTP_THRESHOLD_LOGGING) {
+ sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
+ stcb->asoc.overall_error_count,
+ 0,
+ SCTP_FROM_SCTP_INPUT,
+ __LINE__);
+ }
stcb->asoc.overall_error_count = 0;
net->error_count = 0;
@@ -603,7 +610,8 @@ sctp_handle_abort(struct sctp_abort_chunk *cp,
#ifdef SCTP_ASOCLOG_OF_TSNS
sctp_print_out_track_log(stcb);
#endif
- sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_6);
+ (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC,
+ SCTP_FROM_SCTP_INPUT + SCTP_LOC_6);
SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_abort: finished\n");
}
@@ -645,7 +653,7 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_RECEIVED) &&
(SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT) &&
(SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT)) {
- asoc->state = SCTP_STATE_SHUTDOWN_RECEIVED;
+ SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_RECEIVED);
/*
* notify upper layer that peer has initiated a
* shutdown
@@ -680,7 +688,7 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
(SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
- asoc->state = SCTP_STATE_SHUTDOWN_ACK_SENT;
+ SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT);
/* start SHUTDOWN timer */
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK, stcb->sctp_ep,
@@ -739,7 +747,7 @@ 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, SCTP_NORMAL_PROC,
+ (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC,
SCTP_FROM_SCTP_INPUT + SCTP_LOC_10);
}
@@ -866,7 +874,8 @@ 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, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_11);
+ (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC,
+ SCTP_FROM_SCTP_INPUT + SCTP_LOC_11);
return (-1);
}
/* blast back to INIT state */
@@ -941,7 +950,6 @@ sctp_handle_init_ack(struct mbuf *m, int iphlen, int offset,
struct sctp_nets *net, int *abort_no_unlock, uint32_t vrf_id)
{
struct sctp_init_ack *init_ack;
- int *state;
struct mbuf *op_err;
SCTPDBG(SCTP_DEBUG_INPUT2,
@@ -995,8 +1003,7 @@ sctp_handle_init_ack(struct mbuf *m, int iphlen, int offset,
return (-1);
}
/* process according to association state... */
- state = &stcb->asoc.state;
- switch (*state & SCTP_STATE_MASK) {
+ switch (stcb->asoc.state & SCTP_STATE_MASK) {
case SCTP_STATE_COOKIE_WAIT:
/* this is the expected state for this chunk */
/* process the INIT-ACK parameters */
@@ -1020,14 +1027,16 @@ sctp_handle_init_ack(struct mbuf *m, int iphlen, int offset,
}
/* update our state */
SCTPDBG(SCTP_DEBUG_INPUT2, "moving to COOKIE-ECHOED state\n");
- if (*state & SCTP_STATE_SHUTDOWN_PENDING) {
- *state = SCTP_STATE_COOKIE_ECHOED |
- SCTP_STATE_SHUTDOWN_PENDING;
- } else {
- *state = SCTP_STATE_COOKIE_ECHOED;
- }
+ SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_ECHOED);
/* reset the RTO calc */
+ if (sctp_logging_level & SCTP_THRESHOLD_LOGGING) {
+ sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
+ stcb->asoc.overall_error_count,
+ 0,
+ SCTP_FROM_SCTP_INPUT,
+ __LINE__);
+ }
stcb->asoc.overall_error_count = 0;
(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
/*
@@ -1195,14 +1204,11 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
SCTP_STAT_INCR_COUNTER32(sctps_activeestab);
else
SCTP_STAT_INCR_COUNTER32(sctps_collisionestab);
+
+ SCTP_SET_STATE(asoc, SCTP_STATE_OPEN);
if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
- asoc->state = SCTP_STATE_OPEN | SCTP_STATE_SHUTDOWN_PENDING;
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
stcb->sctp_ep, stcb, asoc->primary_destination);
-
- } else {
- /* if ok, move to OPEN state */
- asoc->state = SCTP_STATE_OPEN;
}
SCTP_STAT_INCR_GAUGE32(sctps_currestab);
sctp_stop_all_cookie_timers(stcb);
@@ -1381,13 +1387,11 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
} else {
SCTP_STAT_INCR_COUNTER32(sctps_collisionestab);
}
+ SCTP_SET_STATE(asoc, SCTP_STATE_OPEN);
if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
- asoc->state = SCTP_STATE_OPEN | SCTP_STATE_SHUTDOWN_PENDING;
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
stcb->sctp_ep, stcb, asoc->primary_destination);
- } else {
- asoc->state = SCTP_STATE_OPEN;
}
sctp_stop_all_cookie_timers(stcb);
sctp_toss_old_cookies(stcb, asoc);
@@ -1438,14 +1442,13 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
SCTP_STAT_INCR_GAUGE32(sctps_collisionestab);
}
if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
- asoc->state = SCTP_STATE_OPEN |
- SCTP_STATE_SHUTDOWN_PENDING;
+ SCTP_SET_STATE(asoc, SCTP_STATE_OPEN);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
stcb->sctp_ep, stcb, asoc->primary_destination);
} else if (!(asoc->state & SCTP_STATE_SHUTDOWN_SENT)) {
/* move to OPEN state, if not in SHUTDOWN_SENT */
- asoc->state = SCTP_STATE_OPEN;
+ SCTP_SET_STATE(asoc, SCTP_STATE_OPEN);
}
asoc->pre_open_streams =
ntohs(initack_cp->init.num_outbound_streams);
@@ -1667,7 +1670,7 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC);
sctp_abort_association(inp, (struct sctp_tcb *)NULL, m, iphlen,
sh, op_err, vrf_id);
- sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
+ (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
SCTP_FROM_SCTP_INPUT + SCTP_LOC_16);
atomic_add_int(&stcb->asoc.refcnt, -1);
return (NULL);
@@ -1692,7 +1695,7 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
retval = 0;
if (retval < 0) {
atomic_add_int(&stcb->asoc.refcnt, 1);
- sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_16);
+ (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_16);
atomic_add_int(&stcb->asoc.refcnt, -1);
return (NULL);
}
@@ -1701,7 +1704,7 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
init_offset + sizeof(struct sctp_init_chunk), initack_offset, sh,
init_src)) {
atomic_add_int(&stcb->asoc.refcnt, 1);
- sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_17);
+ (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_17);
atomic_add_int(&stcb->asoc.refcnt, -1);
return (NULL);
}
@@ -1722,7 +1725,7 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
SCTPDBG(SCTP_DEBUG_AUTH1,
"COOKIE-ECHO: AUTH failed\n");
atomic_add_int(&stcb->asoc.refcnt, 1);
- sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_18);
+ (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_18);
atomic_add_int(&stcb->asoc.refcnt, -1);
return (NULL);
} else {
@@ -1732,12 +1735,10 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
}
/* update current state */
SCTPDBG(SCTP_DEBUG_INPUT2, "moving to OPEN state\n");
+ SCTP_SET_STATE(asoc, SCTP_STATE_OPEN);
if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
- asoc->state = SCTP_STATE_OPEN | SCTP_STATE_SHUTDOWN_PENDING;
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
stcb->sctp_ep, stcb, asoc->primary_destination);
- } else {
- asoc->state = SCTP_STATE_OPEN;
}
sctp_stop_all_cookie_timers(stcb);
SCTP_STAT_INCR_COUNTER32(sctps_passiveestab);
@@ -1772,7 +1773,7 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
sizeof(sin6->sin6_addr));
} else {
atomic_add_int(&stcb->asoc.refcnt, 1);
- sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_19);
+ (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_19);
atomic_add_int(&stcb->asoc.refcnt, -1);
return (NULL);
}
@@ -2201,7 +2202,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, vrf_id);
- sctp_free_assoc(*inp_p, *stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_20);
+ (void)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;
@@ -2304,13 +2305,11 @@ sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp,
if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) {
/* state change only needed when I am in right state */
SCTPDBG(SCTP_DEBUG_INPUT2, "moving to OPEN state\n");
+ SCTP_SET_STATE(asoc, SCTP_STATE_OPEN);
if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
- asoc->state = SCTP_STATE_OPEN | SCTP_STATE_SHUTDOWN_PENDING;
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
stcb->sctp_ep, stcb, asoc->primary_destination);
- } else {
- asoc->state = SCTP_STATE_OPEN;
}
/* update RTO */
SCTP_STAT_INCR_COUNTER32(sctps_activeestab);
@@ -2500,7 +2499,7 @@ sctp_handle_shutdown_complete(struct sctp_shutdown_complete_chunk *cp,
sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_22);
SCTP_STAT_INCR_COUNTER32(sctps_shutdown);
/* free the TCB */
- sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_23);
+ (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_23);
return;
}
@@ -3657,6 +3656,13 @@ __attribute__((noinline))
(ch->chunk_type == SCTP_HEARTBEAT_REQUEST)) &&
(SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED)) {
/* implied cookie-ack.. we must have lost the ack */
+ if (sctp_logging_level & SCTP_THRESHOLD_LOGGING) {
+ sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
+ stcb->asoc.overall_error_count,
+ 0,
+ SCTP_FROM_SCTP_INPUT,
+ __LINE__);
+ }
stcb->asoc.overall_error_count = 0;
sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch, stcb,
*netp);
@@ -3826,7 +3832,7 @@ process_control_chunks:
}
*offset = length;
if (stcb) {
- sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_27);
+ (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_27);
}
return (NULL);
}
@@ -3927,6 +3933,13 @@ process_control_chunks:
chk_length, *netp);
/* He's alive so give him credit */
+ if (sctp_logging_level & SCTP_THRESHOLD_LOGGING) {
+ sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
+ stcb->asoc.overall_error_count,
+ 0,
+ SCTP_FROM_SCTP_INPUT,
+ __LINE__);
+ }
stcb->asoc.overall_error_count = 0;
}
break;
@@ -3941,6 +3954,13 @@ process_control_chunks:
return (NULL);
}
/* He's alive so give him credit */
+ if (sctp_logging_level & SCTP_THRESHOLD_LOGGING) {
+ sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
+ stcb->asoc.overall_error_count,
+ 0,
+ SCTP_FROM_SCTP_INPUT,
+ __LINE__);
+ }
stcb->asoc.overall_error_count = 0;
SCTP_STAT_INCR(sctps_recvheartbeatack);
if (netp && *netp)
@@ -4130,13 +4150,20 @@ process_control_chunks:
if ((stcb) && (stcb->asoc.total_output_queue_size)) {
;
} else if (stcb) {
- sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_27);
+ (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_27);
*offset = length;
return (NULL);
}
}
/* He's alive so give him credit */
if ((stcb) && netp && *netp) {
+ if (sctp_logging_level & SCTP_THRESHOLD_LOGGING) {
+ sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
+ stcb->asoc.overall_error_count,
+ 0,
+ SCTP_FROM_SCTP_INPUT,
+ __LINE__);
+ }
stcb->asoc.overall_error_count = 0;
sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch, stcb, *netp);
}
@@ -4153,6 +4180,13 @@ process_control_chunks:
return (NULL);
}
if (stcb) {
+ if (sctp_logging_level & SCTP_THRESHOLD_LOGGING) {
+ sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
+ stcb->asoc.overall_error_count,
+ 0,
+ SCTP_FROM_SCTP_INPUT,
+ __LINE__);
+ }
stcb->asoc.overall_error_count = 0;
sctp_handle_ecn_echo((struct sctp_ecne_chunk *)ch,
stcb);
@@ -4170,6 +4204,13 @@ process_control_chunks:
return (NULL);
}
if (stcb) {
+ if (sctp_logging_level & SCTP_THRESHOLD_LOGGING) {
+ sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
+ stcb->asoc.overall_error_count,
+ 0,
+ SCTP_FROM_SCTP_INPUT,
+ __LINE__);
+ }
stcb->asoc.overall_error_count = 0;
sctp_handle_ecn_cwr((struct sctp_cwr_chunk *)ch, stcb);
}
@@ -4196,6 +4237,13 @@ process_control_chunks:
SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ASCONF\n");
/* He's alive so give him credit */
if (stcb) {
+ if (sctp_logging_level & SCTP_THRESHOLD_LOGGING) {
+ sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
+ stcb->asoc.overall_error_count,
+ 0,
+ SCTP_FROM_SCTP_INPUT,
+ __LINE__);
+ }
stcb->asoc.overall_error_count = 0;
sctp_handle_asconf(m, *offset,
(struct sctp_asconf_chunk *)ch, stcb);
@@ -4213,6 +4261,13 @@ process_control_chunks:
}
if ((stcb) && netp && *netp) {
/* He's alive so give him credit */
+ if (sctp_logging_level & SCTP_THRESHOLD_LOGGING) {
+ sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
+ stcb->asoc.overall_error_count,
+ 0,
+ SCTP_FROM_SCTP_INPUT,
+ __LINE__);
+ }
stcb->asoc.overall_error_count = 0;
sctp_handle_asconf_ack(m, *offset,
(struct sctp_asconf_ack_chunk *)ch, stcb, *netp);
@@ -4233,10 +4288,17 @@ process_control_chunks:
int abort_flag = 0;
stcb->asoc.overall_error_count = 0;
+ if (sctp_logging_level & SCTP_THRESHOLD_LOGGING) {
+ sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
+ stcb->asoc.overall_error_count,
+ 0,
+ SCTP_FROM_SCTP_INPUT,
+ __LINE__);
+ }
*fwd_tsn_seen = 1;
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
/* We are not interested anymore */
- sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_29);
+ (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_29);
*offset = length;
return (NULL);
}
@@ -4246,6 +4308,13 @@ process_control_chunks:
*offset = length;
return (NULL);
} else {
+ if (sctp_logging_level & SCTP_THRESHOLD_LOGGING) {
+ sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
+ stcb->asoc.overall_error_count,
+ 0,
+ SCTP_FROM_SCTP_INPUT,
+ __LINE__);
+ }
stcb->asoc.overall_error_count = 0;
}
@@ -4263,7 +4332,7 @@ process_control_chunks:
}
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
/* We are not interested anymore */
- sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_30);
+ (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_30);
*offset = length;
return (NULL);
}
@@ -4510,7 +4579,8 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset,
/* always clear this before beginning a packet */
stcb->asoc.authenticated = 0;
stcb->asoc.seen_a_sack_this_pkt = 0;
- if (stcb->asoc.state & SCTP_STATE_WAS_ABORTED) {
+ if ((stcb->asoc.state & SCTP_STATE_WAS_ABORTED) ||
+ (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED)) {
/*-
* If we hit here, we had a ref count
* up when the assoc was aborted and the
@@ -4610,6 +4680,13 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset,
* shows us the cookie-ack was lost. Imply it was
* there.
*/
+ if (sctp_logging_level & SCTP_THRESHOLD_LOGGING) {
+ sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
+ stcb->asoc.overall_error_count,
+ 0,
+ SCTP_FROM_SCTP_INPUT,
+ __LINE__);
+ }
stcb->asoc.overall_error_count = 0;
sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch, stcb, net);
break;
@@ -4928,9 +5005,7 @@ sctp_skip_csum_4:
}
if ((inp) && (refcount_up)) {
/* reduce ref-count */
- SCTP_INP_WLOCK(inp);
SCTP_INP_DECR_REF(inp);
- SCTP_INP_WUNLOCK(inp);
}
return;
bad:
@@ -4939,9 +5014,7 @@ bad:
}
if ((inp) && (refcount_up)) {
/* reduce ref-count */
- SCTP_INP_WLOCK(inp);
SCTP_INP_DECR_REF(inp);
- SCTP_INP_WUNLOCK(inp);
}
if (m) {
sctp_m_freem(m);
diff --git a/sys/netinet/sctp_os.h b/sys/netinet/sctp_os.h
index 1e38cdf..fb7c536 100644
--- a/sys/netinet/sctp_os.h
+++ b/sys/netinet/sctp_os.h
@@ -61,6 +61,7 @@ __FBSDID("$FreeBSD$");
+
/* All os's must implement this address gatherer. If
* no VRF's exist, then vrf 0 is the only one and all
* addresses and ifn's live here.
diff --git a/sys/netinet/sctp_os_bsd.h b/sys/netinet/sctp_os_bsd.h
index a6cdbf6..9a1dc43 100644
--- a/sys/netinet/sctp_os_bsd.h
+++ b/sys/netinet/sctp_os_bsd.h
@@ -121,6 +121,16 @@ MALLOC_DECLARE(SCTP_M_MVRF);
MALLOC_DECLARE(SCTP_M_ITER);
MALLOC_DECLARE(SCTP_M_SOCKOPT);
+#if defined(SCTP_LOCAL_TRACE_BUF)
+
+#define SCTP_GET_CYCLECOUNT get_cyclecount()
+#define SCTP_CTR6 sctp_log_trace
+
+#else
+#define SCTP_CTR6 CTR6
+#endif
+
+
/*
*
*/
@@ -166,11 +176,18 @@ MALLOC_DECLARE(SCTP_M_SOCKOPT);
#endif
#ifdef SCTP_LTRACE_ERRORS
-#define SCTP_LTRACE_ERR(a, b, c, d) if(sctp_logging_level & SCTP_LTRACE_ERROR_ENABLE) CTR6(KTR_SUBSYS, "SCTP:%d[%d]:%x-%x-%x-%x", SCTP_LOG_ERROR_RET, 0, a, b, c, d)
+#define SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, net, file, err) if(sctp_logging_level & SCTP_LTRACE_ERROR_ENABLE) \
+ printf("mbuf:%p inp:%p stcb:%p net:%p file:%x line:%d error:%d\n", \
+ m, inp, stcb, net, file, __LINE__, err);
+#define SCTP_LTRACE_ERR_RET(inp, stcb, net, file, err) if(sctp_logging_level & SCTP_LTRACE_ERROR_ENABLE) \
+ printf("inp:%p stcb:%p net:%p file:%x line:%d error:%d\n", \
+ inp, stcb, net, file, __LINE__, err);
#else
-#define SCTP_LTRACE_ERR(a, b, c, d)
+#define SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, net, file, err)
+#define SCTP_LTRACE_ERR_RET(inp, stcb, net, file, err)
#endif
+
/*
* Local address and interface list handling
*/
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c
index 9e4f0f0..85824fd 100644
--- a/sys/netinet/sctp_output.c
+++ b/sys/netinet/sctp_output.c
@@ -2712,12 +2712,15 @@ sctp_choose_boundall(struct sctp_inpcb *inp,
ifn = SCTP_GET_IFN_VOID_FROM_ROUTE(ro);
ifn_index = SCTP_GET_IF_INDEX_FROM_ROUTE(ro);
-
emit_ifn = looked_at = sctp_ifn = sctp_find_ifn(ifn, ifn_index);
if (sctp_ifn == NULL) {
/* ?? We don't have this guy ?? */
+ SCTPDBG(SCTP_DEBUG_OUTPUT2, "No ifn emit interface?\n");
goto bound_all_plan_b;
}
+ SCTPDBG(SCTP_DEBUG_OUTPUT2, "ifn_index:%d name:%s is emit interface\n",
+ ifn_index, sctp_ifn->ifn_name);
+
if (net) {
cur_addr_num = net->indx_of_eligible_next_to_use;
}
@@ -2726,8 +2729,8 @@ sctp_choose_boundall(struct sctp_inpcb *inp,
non_asoc_addr_ok,
dest_is_loop,
dest_is_priv, fam);
- SCTPDBG(SCTP_DEBUG_OUTPUT2, "Found %d preferred source addresses\n",
- num_preferred);
+ SCTPDBG(SCTP_DEBUG_OUTPUT2, "Found %d preferred source addresses for intf:%s\n",
+ num_preferred, sctp_ifn->ifn_name);
if (num_preferred == 0) {
/*
* no eligible addresses, we must use some other interface
@@ -2768,13 +2771,18 @@ sctp_choose_boundall(struct sctp_inpcb *inp,
bound_all_plan_b:
SCTPDBG(SCTP_DEBUG_OUTPUT2, "Trying Plan B\n");
LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
+ SCTPDBG(SCTP_DEBUG_OUTPUT2, "Examine interface %s\n",
+ sctp_ifn->ifn_name);
if (dest_is_loop == 0 && SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
/* wrong base scope */
+ SCTPDBG(SCTP_DEBUG_OUTPUT2, "skip\n");
continue;
}
- if ((sctp_ifn == looked_at) && looked_at)
+ if ((sctp_ifn == looked_at) && looked_at) {
/* already looked at this guy */
+ SCTPDBG(SCTP_DEBUG_OUTPUT2, "already seen\n");
continue;
+ }
num_preferred = sctp_count_num_preferred_boundall(sctp_ifn, stcb, non_asoc_addr_ok,
dest_is_loop, dest_is_priv, fam);
SCTPDBG(SCTP_DEBUG_OUTPUT2,
@@ -2782,6 +2790,7 @@ bound_all_plan_b:
ifn, num_preferred);
if (num_preferred == 0) {
/* None on this interface. */
+ SCTPDBG(SCTP_DEBUG_OUTPUT2, "No prefered -- skipping to next\n");
continue;
}
SCTPDBG(SCTP_DEBUG_OUTPUT2,
@@ -3259,6 +3268,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
sctp_route_t *ro = NULL;
if ((net) && (net->dest_state & SCTP_ADDR_OUT_OF_SCOPE)) {
+ SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EFAULT);
sctp_m_freem(m);
return (EFAULT);
}
@@ -3276,6 +3286,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
sctphdr = mtod(m, struct sctphdr *);
if (sctp_no_csum_on_loopback &&
(stcb) &&
+ (to->sa_family == AF_INET) &&
(stcb->asoc.loopback_scope)) {
sctphdr->checksum = 0;
/*
@@ -3298,7 +3309,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
newm = sctp_get_mbuf_for_msg(sizeof(struct ip), 1, M_DONTWAIT, 1, MT_DATA);
if (newm == NULL) {
sctp_m_freem(m);
- SCTP_LTRACE_ERR(inp, stcb, ENOMEM, 0);
+ SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
return (ENOMEM);
}
SCTP_ALIGN_TO_END(newm, sizeof(struct ip));
@@ -3474,6 +3485,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
}
}
}
+ SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, EHOSTUNREACH);
sctp_m_freem(m);
return (EHOSTUNREACH);
}
@@ -3489,8 +3501,8 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
if (SCTP_GET_HEADER_FOR_OUTPUT(o_pak)) {
/* failed to prepend data, give up */
+ SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
sctp_m_freem(m);
- SCTP_LTRACE_ERR(inp, stcb, ENOMEM, 0);
return (ENOMEM);
}
#ifdef SCTP_PACKET_LOGGING
@@ -3565,7 +3577,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
newm = sctp_get_mbuf_for_msg(sizeof(struct ip6_hdr), 1, M_DONTWAIT, 1, MT_DATA);
if (newm == NULL) {
sctp_m_freem(m);
- SCTP_LTRACE_ERR(inp, stcb, ENOMEM, 0);
+ SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
return (ENOMEM);
}
SCTP_ALIGN_TO_END(newm, sizeof(struct ip6_hdr));
@@ -3588,8 +3600,10 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
sin6 = &tmp;
/* KAME hack: embed scopeid */
- if (sa6_embedscope(sin6, ip6_use_defzone) != 0)
+ if (sa6_embedscope(sin6, ip6_use_defzone) != 0) {
+ SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
return (EINVAL);
+ }
if (net == NULL) {
memset(&ip6route, 0, sizeof(ip6route));
ro = (sctp_route_t *) & ip6route;
@@ -3681,6 +3695,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
lsa6_storage.sin6_family = AF_INET6;
lsa6_storage.sin6_len = sizeof(lsa6_storage);
if ((error = sa6_recoverscope(&lsa6_storage)) != 0) {
+ SCTPDBG(SCTP_DEBUG_OUTPUT3, "recover scope fails error %d\n", error);
sctp_m_freem(m);
return (error);
}
@@ -3717,7 +3732,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
if (SCTP_GET_HEADER_FOR_OUTPUT(o_pak)) {
/* failed to prepend data, give up */
sctp_m_freem(m);
- SCTP_LTRACE_ERR(inp, stcb, ENOMEM, 0);
+ SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
return (ENOMEM);
}
#ifdef SCTP_PACKET_LOGGING
@@ -3790,6 +3805,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
SCTPDBG(SCTP_DEBUG_OUTPUT1, "Unknown protocol (TSNH) type %d\n",
((struct sockaddr *)to)->sa_family);
sctp_m_freem(m);
+ SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EFAULT);
return (EFAULT);
}
}
@@ -3841,6 +3857,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
}
if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) {
/* This case should not happen */
+ SCTPDBG(SCTP_DEBUG_OUTPUT4, "Sending INIT - failed timer?\n");
return;
}
/* start the INIT timer */
@@ -3849,6 +3866,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
m = sctp_get_mbuf_for_msg(MCLBYTES, 1, M_DONTWAIT, 1, MT_DATA);
if (m == NULL) {
/* No memory, INIT timer will re-attempt. */
+ SCTPDBG(SCTP_DEBUG_OUTPUT4, "Sending INIT - mbuf?\n");
return;
}
SCTP_BUF_LEN(m) = sizeof(struct sctp_init_msg);
@@ -4059,9 +4077,11 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
}
p_len += padval;
}
+ SCTPDBG(SCTP_DEBUG_OUTPUT4, "Sending INIT - calls lowlevel_output\n");
ret = sctp_lowlevel_chunk_output(inp, stcb, net,
(struct sockaddr *)&net->ro._l_addr,
m, 0, NULL, 0, 0, NULL, 0);
+ SCTPDBG(SCTP_DEBUG_OUTPUT4, "lowlevel_output - %d\n", ret);
SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks);
sctp_timer_start(SCTP_TIMER_TYPE_INIT, inp, stcb, net);
(void)SCTP_GETTIME_TIMEVAL(&net->last_sent_time);
@@ -5382,11 +5402,13 @@ sctp_msg_append(struct sctp_tcb *stcb,
holds_lock = hold_stcb_lock;
if (srcv->sinfo_stream >= stcb->asoc.streamoutcnt) {
/* Invalid stream number */
+ SCTP_LTRACE_ERR_RET_PKT(m, NULL, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
error = EINVAL;
goto out_now;
}
if ((stcb->asoc.stream_locked) &&
(stcb->asoc.stream_locked_on != srcv->sinfo_stream)) {
+ SCTP_LTRACE_ERR_RET_PKT(m, NULL, stcb, net, SCTP_FROM_SCTP_OUTPUT, EAGAIN);
error = EAGAIN;
goto out_now;
}
@@ -5397,12 +5419,13 @@ sctp_msg_append(struct sctp_tcb *stcb,
(SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED) ||
(stcb->asoc.state & SCTP_STATE_SHUTDOWN_PENDING)) {
/* got data while shutting down */
+ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ECONNRESET);
error = ECONNRESET;
goto out_now;
}
sctp_alloc_a_strmoq(stcb, sp);
if (sp == NULL) {
- SCTP_LTRACE_ERR(stcb->sctp_ep, stcb, ENOMEM, 0);
+ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
error = ENOMEM;
goto out_now;
}
@@ -5720,7 +5743,7 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
if (SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
- asoc->state = SCTP_STATE_SHUTDOWN_SENT;
+ SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb,
asoc->primary_destination);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb,
@@ -5882,7 +5905,7 @@ sctp_sendall(struct sctp_inpcb *inp, struct uio *uio, struct mbuf *m,
SCTP_M_COPYAL);
if (ca == NULL) {
sctp_m_freem(m);
- SCTP_LTRACE_ERR(inp, NULL, ENOMEM, 0);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
return (ENOMEM);
}
memset(ca, 0, sizeof(struct sctp_copy_all));
@@ -5900,7 +5923,7 @@ sctp_sendall(struct sctp_inpcb *inp, struct uio *uio, struct mbuf *m,
ca->m = sctp_copy_out_all(uio, ca->sndlen);
if (ca->m == NULL) {
SCTP_FREE(ca, SCTP_M_COPYAL);
- SCTP_LTRACE_ERR(inp, NULL, ENOMEM, 0);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
return (ENOMEM);
}
} else {
@@ -5923,6 +5946,7 @@ sctp_sendall(struct sctp_inpcb *inp, struct uio *uio, struct mbuf *m,
if (ret) {
SCTP_PRINTF("Failed to initiate iterator for sendall\n");
SCTP_FREE(ca, SCTP_M_COPYAL);
+ SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, EFAULT);
return (EFAULT);
}
return (0);
@@ -6136,6 +6160,14 @@ sctp_can_we_split_this(struct sctp_tcb *stcb,
return (goal_mtu);
}
}
+ /*-
+ * For those strange folk that make the send buffer
+ * smaller than our fragmentation point, we can't
+ * get a full msg in so we have to allow splitting.
+ */
+ if (SCTP_SB_LIMIT_SND(stcb->sctp_socket) < frag_point) {
+ return (sp->length);
+ }
if ((sp->length <= goal_mtu) ||
((sp->length - goal_mtu) < sctp_min_residual)) {
/* Sub-optimial residual don't split in non-eeor mode. */
@@ -6341,7 +6373,7 @@ out_gu:
rcv_flags |= SCTP_DATA_UNORDERED;
}
/* clear out the chunk before setting up */
- memset(chk, sizeof(*chk), 0);
+ memset(chk, 0, sizeof(*chk));
chk->rec.data.rcv_flags = rcv_flags;
if (SCTP_BUF_IS_EXTENDED(sp->data)) {
chk->copy_by_ref = 1;
@@ -7098,7 +7130,7 @@ again_one_more_time:
chk->send_size, chk->copy_by_ref);
if (outchain == NULL) {
*reason_code = 8;
- SCTP_LTRACE_ERR(inp, stcb, ENOMEM, 0);
+ SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
return (ENOMEM);
}
SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks);
@@ -7195,6 +7227,7 @@ again_one_more_time:
SCTP_BUF_PREPEND(outchain, sizeof(struct sctphdr), M_DONTWAIT);
if (outchain == NULL) {
/* no memory */
+ SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOBUFS);
error = ENOBUFS;
goto error_out_again;
}
@@ -7361,7 +7394,7 @@ again_one_more_time:
sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, net);
}
*reason_code = 3;
- SCTP_LTRACE_ERR(inp, stcb, ENOMEM, 0);
+ SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
return (ENOMEM);
}
/* upate our MTU size */
@@ -7467,6 +7500,7 @@ again_one_more_time:
SCTP_BUF_PREPEND(outchain, sizeof(struct sctphdr), M_DONTWAIT);
if (outchain == NULL) {
/* out of mbufs */
+ SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOBUFS);
error = ENOBUFS;
goto errored_send;
}
@@ -8066,7 +8100,7 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp,
struct mbuf *m, *endofchain;
struct sctphdr *shdr;
int asconf;
- struct sctp_nets *net;
+ struct sctp_nets *net = NULL;
uint32_t tsns_sent = 0;
int no_fragmentflg, bundle_at, cnt_thru;
unsigned int mtu;
@@ -8147,6 +8181,7 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp,
SCTP_BUF_PREPEND(m, sizeof(struct sctphdr), M_DONTWAIT);
if (m == NULL) {
+ SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOBUFS);
return (ENOBUFS);
}
shdr = mtod(m, struct sctphdr *);
@@ -8207,8 +8242,10 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp,
SCTP_PRINTF("Gak, chk->snd_count:%d >= max:%d - send abort\n",
chk->snd_count,
sctp_max_retran_chunk);
- sctp_send_abort_tcb(stcb, NULL);
- sctp_timer_start(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL);
+ atomic_add_int(&stcb->asoc.refcnt, 1);
+ sctp_abort_an_association(stcb->sctp_ep, stcb, 0, NULL);
+ SCTP_TCB_LOCK(stcb);
+ atomic_subtract_int(&stcb->asoc.refcnt, 1);
return (SCTP_RETRAN_EXIT);
}
/* pick up the net */
@@ -8292,7 +8329,7 @@ one_chunk_around:
}
m = sctp_copy_mbufchain(chk->data, m, &endofchain, 0, chk->send_size, chk->copy_by_ref);
if (m == NULL) {
- SCTP_LTRACE_ERR(inp, stcb, ENOMEM, 0);
+ SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
return (ENOMEM);
}
/* Do clear IP_DF ? */
@@ -8344,7 +8381,7 @@ one_chunk_around:
}
m = sctp_copy_mbufchain(fwd->data, m, &endofchain, 0, fwd->send_size, fwd->copy_by_ref);
if (m == NULL) {
- SCTP_LTRACE_ERR(inp, stcb, ENOMEM, 0);
+ SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
return (ENOMEM);
}
/* Do clear IP_DF ? */
@@ -8383,6 +8420,7 @@ one_chunk_around:
}
SCTP_BUF_PREPEND(m, sizeof(struct sctphdr), M_DONTWAIT);
if (m == NULL) {
+ SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOBUFS);
return (ENOBUFS);
}
shdr = mtod(m, struct sctphdr *);
@@ -8831,9 +8869,11 @@ sctp_output(inp, m, addr, control, p, flags)
int flags;
{
if (inp == NULL) {
+ SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, EINVAL);
return (EINVAL);
}
if (inp->sctp_socket == NULL) {
+ SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, EINVAL);
return (EINVAL);
}
return (sctp_sosend(inp->sctp_socket,
@@ -9240,8 +9280,15 @@ sctp_send_sack(struct sctp_tcb *stcb)
offset += 8;
}
if (num_gap_blocks == 0) {
- /* reneged all chunks */
- asoc->highest_tsn_inside_map = asoc->cumulative_tsn;
+ /*
+ * slide not yet happened, and somehow we got called
+ * to send a sack. Cumack needs to move up.
+ */
+ int abort_flag = 0;
+
+ asoc->cumulative_tsn = asoc->highest_tsn_inside_map;
+ sack->sack.cum_tsn_ack = htonl(asoc->cumulative_tsn);
+ sctp_sack_check(stcb, 0, 0, &abort_flag);
}
}
/* now we must add any dups we are going to report. */
@@ -9333,6 +9380,7 @@ sctp_send_abort_tcb(struct sctp_tcb *stcb, struct mbuf *operr)
abort->ch.chunk_flags = 0;
abort->ch.chunk_length = htons(sizeof(*abort) + sz);
+
/* prepend and fill in the SCTP header */
SCTP_BUF_PREPEND(m_out, sizeof(struct sctphdr), M_DONTWAIT);
if (m_out == NULL) {
@@ -9811,6 +9859,9 @@ sctp_send_packet_dropped(struct sctp_tcb *stcb, struct sctp_nets *net,
struct ip *iph;
int fullsz = 0, extra = 0;
long spc;
+ int offset;
+ struct sctp_chunkhdr *ch, chunk_buf;
+ unsigned int chk_length;
asoc = &stcb->asoc;
SCTP_TCB_LOCK_ASSERT(stcb);
@@ -9843,6 +9894,28 @@ sctp_send_packet_dropped(struct sctp_tcb *stcb, struct sctp_nets *net,
ip6h = mtod(m, struct ip6_hdr *);
len = chk->send_size = htons(ip6h->ip6_plen);
}
+ /* Validate that we do not have an ABORT in here. */
+ offset = iphlen + sizeof(struct sctphdr);
+ ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset,
+ sizeof(*ch), (uint8_t *) & chunk_buf);
+ while (ch != NULL) {
+ chk_length = ntohs(ch->chunk_length);
+ if (chk_length < sizeof(*ch)) {
+ /* break to abort land */
+ break;
+ }
+ switch (ch->chunk_type) {
+ case SCTP_ABORT_ASSOCIATION:
+ /* we don't respond with an PKT-DROP to an ABORT */
+ return;
+ default:
+ break;
+ }
+ offset += SCTP_SIZE32(chk_length);
+ ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset,
+ sizeof(*ch), (uint8_t *) & chunk_buf);
+ }
+
if ((len + SCTP_MAX_OVERHEAD + sizeof(struct sctp_pktdrop_chunk)) >
min(stcb->asoc.smallest_mtu, MCLBYTES)) {
/*
@@ -10181,19 +10254,22 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb,
/*-
* Already one pending, must get ACK back to clear the flag.
*/
+ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, EBUSY);
return (EBUSY);
}
if ((send_out_req == 0) && (send_in_req == 0) && (send_tsn_req == 0)) {
/* nothing to do */
+ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, EINVAL);
return (EINVAL);
}
if (send_tsn_req && (send_out_req || send_in_req)) {
/* error, can't do that */
+ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, EINVAL);
return (EINVAL);
}
sctp_alloc_a_chunk(stcb, chk);
if (chk == NULL) {
- SCTP_LTRACE_ERR(stcb->sctp_ep, stcb, ENOMEM, 0);
+ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
return (ENOMEM);
}
chk->copy_by_ref = 0;
@@ -10207,7 +10283,7 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb,
chk->data = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_DONTWAIT, 1, MT_DATA);
if (chk->data == NULL) {
sctp_free_a_chunk(stcb, chk);
- SCTP_LTRACE_ERR(stcb->sctp_ep, stcb, ENOMEM, 0);
+ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
return (ENOMEM);
}
SCTP_BUF_RESV_UF(chk->data, SCTP_MIN_OVERHEAD);
@@ -10586,9 +10662,10 @@ sctp_copy_resume(struct sctp_stream_queue_pending *sp,
m = m_uiotombuf(uio, M_WAITOK, max_send_len, 0,
(M_PKTHDR | (user_marks_eor ? M_EOR : 0)));
- if (m == NULL)
+ if (m == NULL) {
+ SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
*error = ENOMEM;
- else {
+ } else {
*sndout = m_length(m, NULL);
*new_tail = m_last(m);
}
@@ -10605,9 +10682,10 @@ sctp_copy_one(struct sctp_stream_queue_pending *sp,
left = sp->length;
sp->data = m_uiotombuf(uio, M_WAITOK, sp->length,
resv_upfront, 0);
- if (sp->data == NULL)
+ if (sp->data == NULL) {
+ SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
return (ENOMEM);
-
+ }
sp->tail_mbuf = m_last(sp->data);
return (0);
}
@@ -10640,6 +10718,7 @@ sctp_copy_it_in(struct sctp_tcb *stcb,
if (((user_marks_eor == 0) && non_blocking) &&
(uio->uio_resid > (int)SCTP_SB_LIMIT_SND(stcb->sctp_socket))) {
/* It will NEVER fit */
+ SCTP_LTRACE_ERR_RET(NULL, stcb, net, SCTP_FROM_SCTP_OUTPUT, EMSGSIZE);
*error = EMSGSIZE;
goto out_now;
}
@@ -10649,11 +10728,13 @@ sctp_copy_it_in(struct sctp_tcb *stcb,
(SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED) ||
(asoc->state & SCTP_STATE_SHUTDOWN_PENDING)) {
/* got data while shutting down */
+ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ECONNRESET);
*error = ECONNRESET;
goto out_now;
}
sctp_alloc_a_strmoq(stcb, sp);
if (sp == NULL) {
+ SCTP_LTRACE_ERR_RET(NULL, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
*error = ENOMEM;
goto out_now;
}
@@ -10707,8 +10788,7 @@ sctp_sosend(struct socket *so,
struct uio *uio,
struct mbuf *top,
struct mbuf *control,
- int flags
- ,
+ int flags,
struct thread *p
)
{
@@ -10781,30 +10861,41 @@ sctp_lower_sosend(struct socket *so,
asoc = NULL;
t_inp = inp = (struct sctp_inpcb *)so->so_pcb;
if (inp == NULL) {
+ SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, EFAULT);
error = EFAULT;
goto out_unlocked;
}
if ((uio == NULL) && (i_pak == NULL)) {
+ SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
return (EINVAL);
}
atomic_add_int(&inp->total_sends, 1);
- if (uio)
+ if (uio) {
+ if (uio->uio_resid < 0) {
+ SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
+ return (EINVAL);
+ }
sndlen = uio->uio_resid;
- else {
- sndlen = SCTP_HEADER_LEN(i_pak);
+ } else {
top = SCTP_HEADER_TO_CHAIN(i_pak);
+ sndlen = SCTP_HEADER_LEN(i_pak);
}
- /*
- * Pre-screen address, if one is given the sin-len must be set
- * correctly!
+ SCTPDBG(SCTP_DEBUG_OUTPUT1, "Send called addr:%p send length %d\n",
+ addr,
+ sndlen);
+ /*-
+ * Pre-screen address, if one is given the sin-len
+ * must be set correctly!
*/
if (addr) {
if ((addr->sa_family == AF_INET) &&
(addr->sa_len != sizeof(struct sockaddr_in))) {
+ SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
error = EINVAL;
goto out_unlocked;
} else if ((addr->sa_family == AF_INET6) &&
(addr->sa_len != sizeof(struct sockaddr_in6))) {
+ SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
error = EINVAL;
goto out_unlocked;
}
@@ -10814,12 +10905,14 @@ sctp_lower_sosend(struct socket *so,
if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
(inp->sctp_socket->so_qlimit)) {
/* The listener can NOT send */
+ SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, EFAULT);
error = EFAULT;
goto out_unlocked;
}
if ((use_rcvinfo) && srcv) {
if (INVALID_SINFO_FLAG(srcv->sinfo_flags) ||
PR_SCTP_INVALID_POLICY(srcv->sinfo_flags)) {
+ SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
error = EINVAL;
goto out_unlocked;
}
@@ -10840,6 +10933,7 @@ sctp_lower_sosend(struct socket *so,
stcb = LIST_FIRST(&inp->sctp_asoc_list);
if (stcb == NULL) {
SCTP_INP_RUNLOCK(inp);
+ SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOTCONN);
error = ENOTCONN;
goto out_unlocked;
}
@@ -10886,6 +10980,7 @@ sctp_lower_sosend(struct socket *so,
}
}
if (net == NULL) {
+ SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
error = EINVAL;
goto out_unlocked;
}
@@ -10905,6 +11000,7 @@ sctp_lower_sosend(struct socket *so,
struct sockaddr_in *sin;
if (addr == NULL) {
+ SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
error = EINVAL;
goto out_unlocked;
}
@@ -10942,12 +11038,14 @@ sctp_lower_sosend(struct socket *so,
if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
(inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE)) {
/* Should I really unlock ? */
+ SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, EFAULT);
error = EFAULT;
goto out_unlocked;
}
if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
(addr->sa_family == AF_INET6)) {
+ SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
error = EINVAL;
goto out_unlocked;
}
@@ -10964,6 +11062,7 @@ sctp_lower_sosend(struct socket *so,
hold_tcblock = 1;
}
if (t_inp != inp) {
+ SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOTCONN);
error = ENOTCONN;
goto out_unlocked;
}
@@ -10971,9 +11070,11 @@ sctp_lower_sosend(struct socket *so,
if (stcb == NULL) {
if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
(inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
+ SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOTCONN);
error = ENOTCONN;
goto out_unlocked;
} else if (addr == NULL) {
+ SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOENT);
error = ENOENT;
goto out_unlocked;
} else {
@@ -10992,6 +11093,7 @@ sctp_lower_sosend(struct socket *so,
* User asks to abort a non-existant assoc,
* or EOF a non-existant assoc with no data
*/
+ SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOENT);
error = ENOENT;
goto out_unlocked;
}
@@ -11016,7 +11118,7 @@ sctp_lower_sosend(struct socket *so,
*/
queue_only = 1;
asoc = &stcb->asoc;
- asoc->state = SCTP_STATE_COOKIE_WAIT;
+ SCTP_SET_STATE(asoc, SCTP_STATE_COOKIE_WAIT);
(void)SCTP_GETTIME_TIMEVAL(&asoc->time_entered);
/* initialize authentication params for the assoc */
@@ -11134,6 +11236,7 @@ sctp_lower_sosend(struct socket *so,
(sndlen + stcb->asoc.total_output_queue_size)) ||
(stcb->asoc.chunks_on_out_queue >
sctp_max_chunks_on_queue)) {
+ SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EWOULDBLOCK);
error = EWOULDBLOCK;
atomic_add_int(&stcb->sctp_ep->total_nospaces, 1);
goto out_unlocked;
@@ -11146,6 +11249,7 @@ sctp_lower_sosend(struct socket *so,
free_cnt_applied = 1;
if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
+ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ECONNRESET);
error = ECONNRESET;
goto out_unlocked;
}
@@ -11157,6 +11261,7 @@ sctp_lower_sosend(struct socket *so,
/*
* Can't queue any data while stream reset is underway.
*/
+ SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EAGAIN);
error = EAGAIN;
goto out_unlocked;
}
@@ -11181,6 +11286,7 @@ sctp_lower_sosend(struct socket *so,
(srcv->sinfo_flags & SCTP_ABORT)) {
;
} else {
+ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ECONNRESET);
error = ECONNRESET;
goto out_unlocked;
}
@@ -11195,6 +11301,7 @@ sctp_lower_sosend(struct socket *so,
}
}
if (net == NULL) {
+ SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
error = EINVAL;
goto out_unlocked;
}
@@ -11228,6 +11335,7 @@ sctp_lower_sosend(struct socket *so,
(SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)) {
/* It has to be up before we abort */
/* how big is the user initiated abort? */
+ SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
error = EINVAL;
goto out;
}
@@ -11236,14 +11344,15 @@ sctp_lower_sosend(struct socket *so,
hold_tcblock = 0;
}
if (top) {
- struct mbuf *cntm;
+ struct mbuf *cntm = NULL;
mm = sctp_get_mbuf_for_msg(1, 0, M_WAIT, 1, MT_DATA);
-
- cntm = top;
- while (cntm) {
- tot_out += SCTP_BUF_LEN(cntm);
- cntm = SCTP_BUF_NEXT(cntm);
+ if (sndlen != 0) {
+ cntm = top;
+ while (cntm) {
+ tot_out += SCTP_BUF_LEN(cntm);
+ cntm = SCTP_BUF_NEXT(cntm);
+ }
}
tot_demand = (tot_out + sizeof(struct sctp_paramhdr));
} else {
@@ -11254,6 +11363,7 @@ sctp_lower_sosend(struct socket *so,
mm = sctp_get_mbuf_for_msg(tot_demand, 0, M_WAIT, 1, MT_DATA);
}
if (mm == NULL) {
+ SCTP_LTRACE_ERR_RET(NULL, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
error = ENOMEM;
goto out;
}
@@ -11283,7 +11393,9 @@ sctp_lower_sosend(struct socket *so,
mm = NULL;
}
} else {
- SCTP_BUF_NEXT(mm) = top;
+ if (sndlen != 0) {
+ SCTP_BUF_NEXT(mm) = top;
+ }
}
}
if (hold_tcblock == 0) {
@@ -11299,6 +11411,14 @@ sctp_lower_sosend(struct socket *so,
/* now relock the stcb so everything is sane */
hold_tcblock = 0;
stcb = NULL;
+ /*
+ * In this case top is already chained to mm avoid double
+ * free, since we free it below if top != NULL and driver
+ * would free it after sending the packet out
+ */
+ if (sndlen != 0) {
+ top = NULL;
+ }
goto out_unlocked;
}
/* Calculate the maximum we can send */
@@ -11314,16 +11434,18 @@ sctp_lower_sosend(struct socket *so,
/* Is the stream no. valid? */
if (srcv->sinfo_stream >= asoc->streamoutcnt) {
/* Invalid stream number */
+ SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
error = EINVAL;
goto out_unlocked;
}
if (asoc->strmout == NULL) {
/* huh? software error */
+ SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EFAULT);
error = EFAULT;
goto out_unlocked;
}
len = 0;
- if (max_len < sctp_add_more_threshold) {
+ if ((max_len < sctp_add_more_threshold) && (SCTP_SB_LIMIT_SND(so) > sctp_add_more_threshold)) {
/* No room right no ! */
SOCKBUF_LOCK(&so->so_snd);
while (SCTP_SB_LIMIT_SND(so) < (stcb->asoc.total_output_queue_size + sctp_add_more_threshold)) {
@@ -11365,27 +11487,33 @@ sctp_lower_sosend(struct socket *so,
goto out_unlocked;
}
atomic_add_int(&stcb->total_sends, 1);
+ /*
+ * sndlen covers for mbuf case uio_resid covers for the non-mbuf
+ * case NOTE: uio will be null when top/mbuf is passed
+ */
+ if ((sndlen == 0) || ((uio) && (uio->uio_resid == 0))) {
+ if (srcv->sinfo_flags & SCTP_EOF) {
+ got_all_of_the_send = 1;
+ goto dataless_eof;
+ } else {
+ SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
+ error = EINVAL;
+ goto out;
+ }
+ }
if (top == NULL) {
struct sctp_stream_queue_pending *sp;
struct sctp_stream_out *strm;
uint32_t sndout, initial_out;
int user_marks_eor;
- if (uio->uio_resid == 0) {
- if (srcv->sinfo_flags & SCTP_EOF) {
- got_all_of_the_send = 1;
- goto dataless_eof;
- } else {
- error = EINVAL;
- goto out;
- }
- }
initial_out = uio->uio_resid;
SCTP_TCB_SEND_LOCK(stcb);
if ((asoc->stream_locked) &&
(asoc->stream_locked_on != srcv->sinfo_stream)) {
SCTP_TCB_SEND_UNLOCK(stcb);
+ SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EAGAIN);
error = EAGAIN;
goto out;
}
@@ -11459,8 +11587,9 @@ sctp_lower_sosend(struct socket *so,
max_len = 0;
if ((max_len > sctp_add_more_threshold) ||
+ (max_len && (SCTP_SB_LIMIT_SND(so) < sctp_add_more_threshold)) ||
(uio->uio_resid &&
- (uio->uio_resid < (int)max_len))) {
+ (uio->uio_resid <= (int)max_len))) {
sndout = 0;
new_tail = NULL;
if (hold_tcblock) {
@@ -11482,8 +11611,10 @@ sctp_lower_sosend(struct socket *so,
* aborted.
*/
sctp_m_freem(mm);
- if (stcb->asoc.state & SCTP_PCB_FLAGS_WAS_ABORTED)
+ if (stcb->asoc.state & SCTP_PCB_FLAGS_WAS_ABORTED) {
+ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ECONNRESET);
error = ECONNRESET;
+ }
SCTP_TCB_SEND_UNLOCK(stcb);
goto out;
}
@@ -11613,7 +11744,7 @@ sctp_lower_sosend(struct socket *so,
queue_only = 0;
} else {
sctp_send_initiate(inp, stcb);
- stcb->asoc.state = SCTP_STATE_COOKIE_WAIT;
+ SCTP_SET_STATE(asoc, SCTP_STATE_COOKIE_WAIT);
queue_only_for_init = 0;
queue_only = 1;
}
@@ -11659,7 +11790,9 @@ sctp_lower_sosend(struct socket *so,
* size we KNOW we will get to sleep safely with the
* wakeup flag in place.
*/
- if (SCTP_SB_LIMIT_SND(so) < (stcb->asoc.total_output_queue_size + sctp_add_more_threshold)) {
+ if (SCTP_SB_LIMIT_SND(so) <= (stcb->asoc.total_output_queue_size +
+ min(sctp_add_more_threshold, SCTP_SB_LIMIT_SND(so)))
+ ) {
if (sctp_logging_level & SCTP_BLK_LOGGING_ENABLE) {
sctp_log_block(SCTP_BLOCK_LOG_INTO_BLK,
so, asoc, uio->uio_resid);
@@ -11748,7 +11881,7 @@ dataless_eof:
if (SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
- asoc->state = SCTP_STATE_SHUTDOWN_SENT;
+ SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb,
asoc->primary_destination);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb,
@@ -11872,11 +12005,7 @@ skip_out_eof:
queue_only = 0;
} else {
sctp_send_initiate(inp, stcb);
- if (stcb->asoc.state & SCTP_STATE_SHUTDOWN_PENDING)
- stcb->asoc.state = SCTP_STATE_COOKIE_WAIT |
- SCTP_STATE_SHUTDOWN_PENDING;
- else
- stcb->asoc.state = SCTP_STATE_COOKIE_WAIT;
+ SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
queue_only_for_init = 0;
queue_only = 1;
}
@@ -11916,10 +12045,10 @@ skip_out_eof:
(void)sctp_med_chunk_output(inp, stcb, &stcb->asoc, &num_out,
&reason, 1, &cwnd_full, 1, &now, &now_filled, frag_point);
}
- SCTPDBG(SCTP_DEBUG_OUTPUT1, "USR Send complete qo:%d prw:%d unsent:%d tf:%d cooq:%d toqs:%d \n",
+ SCTPDBG(SCTP_DEBUG_OUTPUT1, "USR Send complete qo:%d prw:%d unsent:%d tf:%d cooq:%d toqs:%d err:%d",
queue_only, stcb->asoc.peers_rwnd, un_sent,
stcb->asoc.total_flight, stcb->asoc.chunks_on_out_queue,
- stcb->asoc.total_output_queue_size);
+ stcb->asoc.total_output_queue_size, error);
out:
out_unlocked:
diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c
index b4c2def..3d7ecb7 100644
--- a/sys/netinet/sctp_pcb.c
+++ b/sys/netinet/sctp_pcb.c
@@ -368,7 +368,7 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index,
(sctp_ifap->ifn_p->ifn_index == ifn_index)) {
if (new_ifn_af) {
/* Remove the created one that we don't want */
- sctp_delete_ifn(sctp_ifap->ifn_p, 1);
+ sctp_delete_ifn(sctp_ifnp, 1);
}
if (sctp_ifap->localifa_flags & SCTP_BEING_DELETED) {
/* easy to solve, just switch back to active */
@@ -392,7 +392,7 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index,
* Remove the created one that we
* don't want
*/
- sctp_delete_ifn(sctp_ifap->ifn_p, 1);
+ sctp_delete_ifn(sctp_ifnp, 1);
}
goto exit_stage_left;
} else {
@@ -808,6 +808,7 @@ sctp_findassociation_ep_addr(struct sctp_inpcb **inp_p, struct sockaddr *remote,
* UN-lock so we can do proper locking here this occurs when
* called from load_addresses_from_init.
*/
+ atomic_add_int(&locked_tcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(locked_tcb);
}
SCTP_INP_INFO_RLOCK();
@@ -825,13 +826,12 @@ sctp_findassociation_ep_addr(struct sctp_inpcb **inp_p, struct sockaddr *remote,
netp, inp->def_vrf_id);
if ((stcb != NULL) && (locked_tcb == NULL)) {
/* we have a locked tcb, lower refcount */
- SCTP_INP_WLOCK(inp);
SCTP_INP_DECR_REF(inp);
- SCTP_INP_WUNLOCK(inp);
}
if ((locked_tcb != NULL) && (locked_tcb != stcb)) {
SCTP_INP_RLOCK(locked_tcb->sctp_ep);
SCTP_TCB_LOCK(locked_tcb);
+ atomic_subtract_int(&locked_tcb->asoc.refcnt, 1);
SCTP_INP_RUNLOCK(locked_tcb->sctp_ep);
}
SCTP_INP_INFO_RUNLOCK();
@@ -880,6 +880,9 @@ sctp_findassociation_ep_addr(struct sctp_inpcb **inp_p, struct sockaddr *remote,
} else if (locked_tcb != stcb) {
SCTP_TCB_LOCK(locked_tcb);
}
+ if (locked_tcb) {
+ atomic_subtract_int(&locked_tcb->asoc.refcnt, 1);
+ }
SCTP_INP_WUNLOCK(inp);
SCTP_INP_INFO_RUNLOCK();
return (stcb);
@@ -900,6 +903,9 @@ sctp_findassociation_ep_addr(struct sctp_inpcb **inp_p, struct sockaddr *remote,
} else if (locked_tcb != stcb) {
SCTP_TCB_LOCK(locked_tcb);
}
+ if (locked_tcb) {
+ atomic_subtract_int(&locked_tcb->asoc.refcnt, 1);
+ }
SCTP_INP_WUNLOCK(inp);
SCTP_INP_INFO_RUNLOCK();
return (stcb);
@@ -953,6 +959,9 @@ sctp_findassociation_ep_addr(struct sctp_inpcb **inp_p, struct sockaddr *remote,
} else if (locked_tcb != stcb) {
SCTP_TCB_LOCK(locked_tcb);
}
+ if (locked_tcb) {
+ atomic_subtract_int(&locked_tcb->asoc.refcnt, 1);
+ }
SCTP_INP_WUNLOCK(inp);
SCTP_INP_INFO_RUNLOCK();
return (stcb);
@@ -974,6 +983,9 @@ sctp_findassociation_ep_addr(struct sctp_inpcb **inp_p, struct sockaddr *remote,
} else if (locked_tcb != stcb) {
SCTP_TCB_LOCK(locked_tcb);
}
+ if (locked_tcb) {
+ atomic_subtract_int(&locked_tcb->asoc.refcnt, 1);
+ }
SCTP_INP_WUNLOCK(inp);
SCTP_INP_INFO_RUNLOCK();
return (stcb);
@@ -987,6 +999,7 @@ null_return:
/* clean up for returning null */
if (locked_tcb) {
SCTP_TCB_LOCK(locked_tcb);
+ atomic_subtract_int(&locked_tcb->asoc.refcnt, 1);
}
SCTP_INP_WUNLOCK(inp);
SCTP_INP_INFO_RUNLOCK();
@@ -1793,6 +1806,7 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
if (inp == NULL) {
SCTP_PRINTF("Out of SCTP-INPCB structures - no resources\n");
SCTP_INP_INFO_WUNLOCK();
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOBUFS);
return (ENOBUFS);
}
/* zap it */
@@ -1846,15 +1860,25 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
* in protosw
*/
SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_ep, inp);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EOPNOTSUPP);
return (EOPNOTSUPP);
}
- sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
-
+ if (sctp_default_frag_interleave == SCTP_FRAG_LEVEL_1) {
+ sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
+ sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
+ } else if (sctp_default_frag_interleave == SCTP_FRAG_LEVEL_2) {
+ sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
+ sctp_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
+ } else if (sctp_default_frag_interleave == SCTP_FRAG_LEVEL_0) {
+ sctp_feature_off(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
+ sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
+ }
inp->sctp_tcbhash = SCTP_HASH_INIT(sctp_pcbtblsize,
&inp->sctp_hashmark);
if (inp->sctp_tcbhash == NULL) {
SCTP_PRINTF("Out of SCTP-INPCB->hashinit - no resources\n");
SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_ep, inp);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOBUFS);
return (ENOBUFS);
}
inp->def_vrf_id = vrf_id;
@@ -2152,6 +2176,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
#endif
if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) {
/* already did a bind, subsequent binds NOT allowed ! */
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
return (EINVAL);
}
#ifdef INVARIANTS
@@ -2167,11 +2192,13 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
/* IPV6_V6ONLY socket? */
if (SCTP_IPV6_V6ONLY(ip_inp)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
return (EINVAL);
}
- if (addr->sa_len != sizeof(*sin))
+ if (addr->sa_len != sizeof(*sin)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
return (EINVAL);
-
+ }
sin = (struct sockaddr_in *)addr;
lport = sin->sin_port;
if (prison) {
@@ -2180,8 +2207,10 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
* prison_ip() call will tranmute the ip
* address to the proper valie.
*/
- if (prison_ip(p->td_ucred, 0, &sin->sin_addr.s_addr))
+ if (prison_ip(p->td_ucred, 0, &sin->sin_addr.s_addr)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
return (EINVAL);
+ }
}
if (sin->sin_addr.s_addr != INADDR_ANY) {
bindall = 0;
@@ -2192,9 +2221,10 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
sin6 = (struct sockaddr_in6 *)addr;
- if (addr->sa_len != sizeof(*sin6))
+ if (addr->sa_len != sizeof(*sin6)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
return (EINVAL);
-
+ }
lport = sin6->sin6_port;
/*
* Jail checks for IPv6 should go HERE! i.e. add the
@@ -2204,12 +2234,15 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
bindall = 0;
/* KAME hack: embed scopeid */
- if (sa6_embedscope(sin6, ip6_use_defzone) != 0)
+ if (sa6_embedscope(sin6, ip6_use_defzone) != 0) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
return (EINVAL);
+ }
}
/* this must be cleared for ifa_ifwithaddr() */
sin6->sin6_scope_id = 0;
} else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EAFNOSUPPORT);
return (EAFNOSUPPORT);
}
}
@@ -2240,6 +2273,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
SCTP_INP_DECR_REF(inp);
SCTP_INP_WUNLOCK(inp);
SCTP_INP_INFO_WUNLOCK();
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error);
return (error);
}
SCTP_INP_WUNLOCK(inp);
@@ -2258,6 +2292,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
SCTP_INP_DECR_REF(inp);
/* unlock info */
SCTP_INP_INFO_WUNLOCK();
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EADDRINUSE);
return (EADDRINUSE);
}
} else {
@@ -2274,6 +2309,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
SCTP_INP_DECR_REF(inp);
/* unlock info */
SCTP_INP_INFO_WUNLOCK();
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EADDRINUSE);
return (EADDRINUSE);
}
}
@@ -2285,6 +2321,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
SCTP_INP_DECR_REF(inp);
SCTP_INP_WUNLOCK(inp);
SCTP_INP_INFO_WUNLOCK();
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EADDRINUSE);
return (EADDRINUSE);
}
}
@@ -2303,6 +2340,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
SCTP_INP_DECR_REF(inp);
SCTP_INP_WUNLOCK(inp);
SCTP_INP_INFO_WUNLOCK();
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error);
return (error);
}
first = ipport_lowfirstauto;
@@ -2331,6 +2369,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
SCTP_INP_DECR_REF(inp);
SCTP_INP_WUNLOCK(inp);
SCTP_INP_INFO_WUNLOCK();
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EADDRINUSE);
return (EADDRINUSE);
}
if (candidate == last)
@@ -2350,17 +2389,19 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
*/
SCTP_INP_WUNLOCK(inp);
SCTP_INP_INFO_WUNLOCK();
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
return (EINVAL);
}
/* ok we look clear to give out this port, so lets setup the binding */
if (bindall) {
/* binding to all addresses, so just set in the proper flags */
inp->sctp_flags |= SCTP_PCB_FLAGS_BOUNDALL;
- sctp_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF);
/* set the automatic addr changes from kernel flag */
if (sctp_auto_asconf == 0) {
+ sctp_feature_off(inp, SCTP_PCB_FLAGS_DO_ASCONF);
sctp_feature_off(inp, SCTP_PCB_FLAGS_AUTO_ASCONF);
} else {
+ sctp_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF);
sctp_feature_on(inp, SCTP_PCB_FLAGS_AUTO_ASCONF);
}
} else {
@@ -2411,6 +2452,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
/* Can't find an interface with that address */
SCTP_INP_WUNLOCK(inp);
SCTP_INP_INFO_WUNLOCK();
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EADDRNOTAVAIL);
return (EADDRNOTAVAIL);
}
if (addr->sa_family == AF_INET6) {
@@ -2419,6 +2461,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
/* Can't bind a non-existent addr. */
SCTP_INP_WUNLOCK(inp);
SCTP_INP_INFO_WUNLOCK();
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
return (EINVAL);
}
}
@@ -2586,10 +2629,12 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
for ((asoc = LIST_FIRST(&inp->sctp_asoc_list)); asoc != NULL;
asoc = nasoc) {
nasoc = LIST_NEXT(asoc, sctp_tcblist);
+ SCTP_TCB_LOCK(asoc);
if (asoc->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
/* Skip guys being freed */
asoc->sctp_socket = NULL;
cnt_in_sd++;
+ SCTP_TCB_UNLOCK(asoc);
continue;
}
if ((SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_COOKIE_WAIT) ||
@@ -2605,11 +2650,14 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
* Just abandon things in the front
* states
*/
- sctp_free_assoc(inp, asoc, SCTP_PCBFREE_NOFORCE, SCTP_FROM_SCTP_PCB + SCTP_LOC_2);
+
+ if (sctp_free_assoc(inp, asoc, SCTP_PCBFREE_NOFORCE,
+ SCTP_FROM_SCTP_PCB + SCTP_LOC_2) == 0) {
+ cnt_in_sd++;
+ }
continue;
}
}
- SCTP_TCB_LOCK(asoc);
/* Disconnect the socket please */
asoc->sctp_socket = NULL;
asoc->asoc.state |= SCTP_STATE_CLOSED_SOCKET;
@@ -2645,7 +2693,10 @@ 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, SCTP_PCBFREE_NOFORCE, SCTP_FROM_SCTP_PCB + SCTP_LOC_4);
+ if (sctp_free_assoc(inp, asoc,
+ SCTP_PCBFREE_NOFORCE, SCTP_FROM_SCTP_PCB + SCTP_LOC_4) == 0) {
+ cnt_in_sd++;
+ }
continue;
} else if (TAILQ_EMPTY(&asoc->asoc.send_queue) &&
TAILQ_EMPTY(&asoc->asoc.sent_queue) &&
@@ -2665,7 +2716,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);
}
- asoc->asoc.state = SCTP_STATE_SHUTDOWN_SENT;
+ SCTP_SET_STATE(&asoc->asoc, SCTP_STATE_SHUTDOWN_SENT);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, asoc->sctp_ep, asoc,
asoc->asoc.primary_destination);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, asoc->sctp_ep, asoc,
@@ -2725,7 +2776,11 @@ 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, SCTP_PCBFREE_NOFORCE, SCTP_FROM_SCTP_PCB + SCTP_LOC_6);
+ if (sctp_free_assoc(inp, asoc,
+ SCTP_PCBFREE_NOFORCE,
+ SCTP_FROM_SCTP_PCB + SCTP_LOC_6) == 0) {
+ cnt_in_sd++;
+ }
continue;
}
}
@@ -2801,7 +2856,9 @@ 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, SCTP_PCBFREE_FORCE, SCTP_FROM_SCTP_PCB + SCTP_LOC_8);
+ if (sctp_free_assoc(inp, asoc, SCTP_PCBFREE_FORCE, SCTP_FROM_SCTP_PCB + SCTP_LOC_8) == 0) {
+ cnt++;
+ }
}
if (cnt) {
/* Ok we have someone out there that will kill us */
@@ -3344,10 +3401,12 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
*/
if (sctppcbinfo.ipi_count_asoc >= SCTP_MAX_NUM_OF_ASOC) {
/* Hit max assoc, sorry no more */
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOBUFS);
*error = ENOBUFS;
return (NULL);
}
if (firstaddr == NULL) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
*error = EINVAL;
return (NULL);
}
@@ -3360,6 +3419,7 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
* off, or connected one does this.. its an error.
*/
SCTP_INP_RUNLOCK(inp);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
*error = EINVAL;
return (NULL);
}
@@ -3380,6 +3440,7 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
if ((sin->sin_port == 0) || (sin->sin_addr.s_addr == 0)) {
/* Invalid address */
SCTP_INP_RUNLOCK(inp);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
*error = EINVAL;
return (NULL);
}
@@ -3392,6 +3453,7 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
(IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))) {
/* Invalid address */
SCTP_INP_RUNLOCK(inp);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
*error = EINVAL;
return (NULL);
}
@@ -3399,6 +3461,7 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
} else {
/* not supported family type */
SCTP_INP_RUNLOCK(inp);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
*error = EINVAL;
return (NULL);
}
@@ -3421,6 +3484,7 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
stcb = SCTP_ZONE_GET(sctppcbinfo.ipi_zone_asoc, struct sctp_tcb);
if (stcb == NULL) {
/* out of memory? */
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOMEM);
*error = ENOMEM;
return (NULL);
}
@@ -3454,6 +3518,7 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
SCTP_INP_WUNLOCK(inp);
SCTP_INP_INFO_WUNLOCK();
SCTP_DECR_ASOC_COUNT();
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
*error = EINVAL;
return (NULL);
}
@@ -3481,6 +3546,7 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
SCTP_TCB_SEND_LOCK_DESTROY(stcb);
SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_asoc, stcb);
SCTP_INP_WUNLOCK(inp);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOBUFS);
*error = ENOBUFS;
return (NULL);
}
@@ -3668,8 +3734,13 @@ sctp_iterator_asoc_being_freed(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
}
-/*
- * Free the association after un-hashing the remote port.
+/*-
+ * Free the association after un-hashing the remote port. This
+ * function ALWAYS returns holding NO LOCK on the stcb. It DOES
+ * expect that the input to this function IS a locked TCB.
+ * It will return 0, if it did NOT destroy the association (instead
+ * it unlocks it. It will return NON-zero if it either destroyed the
+ * association OR the association is already destroyed.
*/
int
sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfree, int from_location)
@@ -3689,6 +3760,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
int cnt = 0;
/* first, lets purge the entry from the hash table. */
+ SCTP_TCB_LOCK_ASSERT(stcb);
#ifdef SCTP_LOG_CLOSING
sctp_log_closing(inp, stcb, 6);
@@ -3810,11 +3882,12 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
SCTP_INP_READ_UNLOCK(inp);
if (stcb->block_entry) {
cnt++;
+ SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_PCB, ECONNRESET);
stcb->block_entry->error = ECONNRESET;
stcb->block_entry = NULL;
}
}
- if ((from_inpcbfree != SCTP_PCBFREE_FORCE) && (stcb->asoc.refcnt)) {
+ if (stcb->asoc.refcnt) {
/*
* reader or writer in the way, we have hopefully given him
* something to chew on above.
@@ -4516,6 +4589,7 @@ sctp_insert_laddr(struct sctpladdr *list, struct sctp_ifa *ifa, uint32_t act)
laddr = SCTP_ZONE_GET(sctppcbinfo.ipi_zone_laddr, struct sctp_laddr);
if (laddr == NULL) {
/* out of memory? */
+ SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
return (EINVAL);
}
SCTP_INCR_LADDR_COUNT();
@@ -5666,6 +5740,7 @@ sctp_initiate_iterator(inp_func inpf,
SCTP_MALLOC(it, struct sctp_iterator *, sizeof(struct sctp_iterator),
SCTP_M_ITER);
if (it == NULL) {
+ SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOMEM);
return (ENOMEM);
}
memset(it, 0, sizeof(*it));
diff --git a/sys/netinet/sctp_pcb.h b/sys/netinet/sctp_pcb.h
index 6cdf0ca..2ab7adc 100644
--- a/sys/netinet/sctp_pcb.h
+++ b/sys/netinet/sctp_pcb.h
@@ -533,6 +533,7 @@ int sctp_del_remote_addr(struct sctp_tcb *, struct sockaddr *);
void sctp_pcb_init(void);
+
void sctp_add_local_addr_restricted(struct sctp_tcb *, struct sctp_ifa *);
void sctp_del_local_addr_restricted(struct sctp_tcb *, struct sctp_ifa *);
diff --git a/sys/netinet/sctp_peeloff.c b/sys/netinet/sctp_peeloff.c
index e810e34..daded1f 100644
--- a/sys/netinet/sctp_peeloff.c
+++ b/sys/netinet/sctp_peeloff.c
@@ -55,10 +55,12 @@ sctp_can_peel_off(struct socket *head, sctp_assoc_t assoc_id)
inp = (struct sctp_inpcb *)head->so_pcb;
if (inp == NULL) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, EFAULT);
return (EFAULT);
}
stcb = sctp_findassociation_ep_asocid(inp, assoc_id, 1);
if (stcb == NULL) {
+ SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_PEELOFF, ENOTCONN);
return (ENOTCONN);
}
state = SCTP_GET_STATE((&stcb->asoc));
@@ -67,6 +69,7 @@ sctp_can_peel_off(struct socket *head, sctp_assoc_t assoc_id)
(state == SCTP_STATE_COOKIE_WAIT) ||
(state == SCTP_STATE_COOKIE_ECHOED)) {
SCTP_TCB_UNLOCK(stcb);
+ SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_PEELOFF, ENOTCONN);
return (ENOTCONN);
}
SCTP_TCB_UNLOCK(stcb);
@@ -82,18 +85,22 @@ sctp_do_peeloff(struct socket *head, struct socket *so, sctp_assoc_t assoc_id)
uint32_t state;
inp = (struct sctp_inpcb *)head->so_pcb;
- if (inp == NULL)
+ if (inp == NULL) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, EFAULT);
return (EFAULT);
+ }
stcb = sctp_findassociation_ep_asocid(inp, assoc_id, 1);
- if (stcb == NULL)
+ if (stcb == NULL) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, ENOTCONN);
return (ENOTCONN);
-
+ }
state = SCTP_GET_STATE((&stcb->asoc));
if ((state == SCTP_STATE_EMPTY) ||
(state == SCTP_STATE_INUSE) ||
(state == SCTP_STATE_COOKIE_WAIT) ||
(state == SCTP_STATE_COOKIE_ECHOED)) {
SCTP_TCB_UNLOCK(stcb);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, ENOTCONN);
return (ENOTCONN);
}
n_inp = (struct sctp_inpcb *)so->so_pcb;
@@ -133,11 +140,13 @@ sctp_get_peeloff(struct socket *head, sctp_assoc_t assoc_id, int *error)
SCTPDBG(SCTP_DEBUG_PEEL1, "SCTP peel-off called\n");
inp = (struct sctp_inpcb *)head->so_pcb;
if (inp == NULL) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, EFAULT);
*error = EFAULT;
return (NULL);
}
stcb = sctp_findassociation_ep_asocid(inp, assoc_id, 1);
if (stcb == NULL) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, ENOTCONN);
*error = ENOTCONN;
return (NULL);
}
@@ -145,6 +154,7 @@ sctp_get_peeloff(struct socket *head, sctp_assoc_t assoc_id, int *error)
);
if (newso == NULL) {
SCTPDBG(SCTP_DEBUG_PEEL1, "sctp_peeloff:sonewconn failed\n");
+ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_PEELOFF, ENOMEM);
*error = ENOMEM;
SCTP_TCB_UNLOCK(stcb);
return (NULL);
diff --git a/sys/netinet/sctp_structs.h b/sys/netinet/sctp_structs.h
index 79df612..f4480d4 100644
--- a/sys/netinet/sctp_structs.h
+++ b/sys/netinet/sctp_structs.h
@@ -781,13 +781,13 @@ struct sctp_association {
uint32_t peers_rwnd;
uint32_t my_rwnd;
uint32_t my_last_reported_rwnd;
- uint32_t my_rwnd_control_len;
uint32_t sctp_frag_point;
uint32_t total_output_queue_size;
- uint32_t sb_cc; /* shadow of sb_cc in one-2-one */
- uint32_t sb_mbcnt; /* shadow of sb_mbcnt in one-2-one */
+ uint32_t sb_cc; /* shadow of sb_cc */
+ uint32_t my_rwnd_control_len; /* shadow of sb_mbcnt used for rwnd
+ * control */
/* 32 bit nonce stuff */
uint32_t nonce_resync_tsn;
uint32_t nonce_wait_tsn;
diff --git a/sys/netinet/sctp_sysctl.c b/sys/netinet/sctp_sysctl.c
index b3a6783..02450eb 100644
--- a/sys/netinet/sctp_sysctl.c
+++ b/sys/netinet/sctp_sysctl.c
@@ -99,6 +99,8 @@ uint32_t sctp_max_retran_chunk = SCTPCTL_MAX_RETRAN_CHUNK_DEFAULT;
/* JRS - Variable for default congestion control module */
uint32_t sctp_default_cc_module = SCTPCTL_DEFAULT_CC_MODULE_DEFAULT;
+uint32_t sctp_default_frag_interleave = SCTPCTL_DEFAULT_FRAG_INTERLEAVE_DEFAULT;
+
uint32_t sctp_L2_abc_variable = 1;
uint32_t sctp_early_fr = 0;
uint32_t sctp_early_fr_msec = SCTP_MINFR_MSEC_TIMER;
@@ -345,6 +347,7 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS)
}
if (req->newptr != USER_ADDR_NULL) {
SCTP_INP_INFO_RUNLOCK();
+ SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_SYSCTL, EPERM);
return EPERM;
}
LIST_FOREACH(inp, &sctppcbinfo.listhead, sctp_list) {
@@ -624,6 +627,11 @@ SYSCTL_UINT(_net_inet_sctp, OID_AUTO, default_cc_module, CTLFLAG_RW,
&sctp_default_cc_module, 0,
"Default congestion control module");
+
+SYSCTL_UINT(_net_inet_sctp, OID_AUTO, default_frag_interleave, CTLFLAG_RW,
+ &sctp_default_frag_interleave, 0,
+ SCTPCTL_DEFAULT_FRAG_INTERLEAVE_DESC);
+
SYSCTL_UINT(_net_inet_sctp, OID_AUTO, cwnd_maxburst, CTLFLAG_RW,
&sctp_use_cwnd_based_maxburst, 0,
"Use a CWND adjusting maxburst");
diff --git a/sys/netinet/sctp_sysctl.h b/sys/netinet/sctp_sysctl.h
index 59e0922..86a0f9e 100644
--- a/sys/netinet/sctp_sysctl.h
+++ b/sys/netinet/sctp_sysctl.h
@@ -413,18 +413,27 @@ __FBSDID("$FreeBSD$");
#define SCTPCTL_DEFAULT_CC_MODULE_MAX 2
#define SCTPCTL_DEFAULT_CC_MODULE_DEFAULT 0
+
+/* RRS - default fragment interleave */
+#define SCTPCTL_DEFAULT_FRAG_INTERLEAVE 54
+#define SCTPCTL_DEFAULT_FRAG_INTERLEAVE_DESC "Default fragment interleave level"
+#define SCTPCTL_DEFAULT_FRAG_INTERLEAVE_MIN 0
+#define SCTPCTL_DEFAULT_FRAG_INTERLEAVE_MAX 2
+#define SCTPCTL_DEFAULT_FRAG_INTERLEAVE_DEFAULT 1
+
+
#ifdef SCTP_DEBUG
/* debug: Configure debug output */
-#define SCTPCTL_DEBUG 54
+#define SCTPCTL_DEBUG 55
#define SCTPCTL_DEBUG_DESC "Configure debug output"
#define SCTPCTL_DEBUG_MIN 0
#define SCTPCTL_DEBUG_MAX 0xFFFFFFFF
#define SCTPCTL_DEBUG_DEFAULT 0
-#define SCTPCTL_MAXID 54
-#else
#define SCTPCTL_MAXID 55
+#else
+#define SCTPCTL_MAXID 56
#endif
/*
@@ -487,6 +496,7 @@ __FBSDID("$FreeBSD$");
{ "min_residual", CTLTYPE_INT }, \
{ "max_retran_chunk", CTLTYPE_INT }, \
{ "sctp_logging", CTLTYPE_INT }, \
+ { "frag_interleave", CTLTYPE_INT }, \
{ "debug", CTLTYPE_INT }, \
}
#else
@@ -545,6 +555,7 @@ __FBSDID("$FreeBSD$");
{ "min_residual", CTLTYPE_INT }, \
{ "max_retran_chunk", CTLTYPE_INT }, \
{ "sctp_logging", CTLTYPE_INT }, \
+ { "frag_interleave", CTLTYPE_INT }, \
}
#endif
@@ -594,6 +605,7 @@ extern uint32_t sctp_cmt_pf;
/* JRS - Variable for the default congestion control module */
extern uint32_t sctp_default_cc_module;
+extern uint32_t sctp_default_frag_interleave;
extern uint32_t sctp_use_cwnd_based_maxburst;
extern uint32_t sctp_early_fr;
extern uint32_t sctp_use_rttvar_cc;
diff --git a/sys/netinet/sctp_timer.c b/sys/netinet/sctp_timer.c
index 47720d3..a5322e5 100644
--- a/sys/netinet/sctp_timer.c
+++ b/sys/netinet/sctp_timer.c
@@ -234,9 +234,23 @@ sctp_threshold_management(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
if (net) {
if ((net->dest_state & SCTP_ADDR_UNCONFIRMED) == 0) {
+ if (sctp_logging_level & SCTP_THRESHOLD_LOGGING) {
+ sctp_misc_ints(SCTP_THRESHOLD_INCR,
+ stcb->asoc.overall_error_count,
+ (stcb->asoc.overall_error_count + 1),
+ SCTP_FROM_SCTP_TIMER,
+ __LINE__);
+ }
stcb->asoc.overall_error_count++;
}
} else {
+ if (sctp_logging_level & SCTP_THRESHOLD_LOGGING) {
+ sctp_misc_ints(SCTP_THRESHOLD_INCR,
+ stcb->asoc.overall_error_count,
+ (stcb->asoc.overall_error_count + 1),
+ SCTP_FROM_SCTP_TIMER,
+ __LINE__);
+ }
stcb->asoc.overall_error_count++;
}
SCTPDBG(SCTP_DEBUG_TIMER4, "Overall error count for %p now %d thresh:%u state:%x\n",
@@ -1726,7 +1740,7 @@ sctp_autoclose_timer(struct sctp_inpcb *inp,
(SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
- asoc->state = SCTP_STATE_SHUTDOWN_SENT;
+ SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
stcb->sctp_ep, stcb,
asoc->primary_destination);
diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c
index fa2b922..1cebfba 100644
--- a/sys/netinet/sctp_usrreq.c
+++ b/sys/netinet/sctp_usrreq.c
@@ -187,7 +187,7 @@ sctp_notify_mbuf(struct sctp_inpcb *inp,
}
totsz = ip->ip_len;
- nxtsz = ntohs(icmph->icmp_seq);
+ nxtsz = ntohs(icmph->icmp_nextmtu);
if (nxtsz == 0) {
/*
* old type router that does not tell us what the next size
@@ -300,7 +300,7 @@ sctp_notify(struct sctp_inpcb *inp,
* TCB
*/
sctp_abort_notification(stcb, SCTP_PEER_FAULTY);
- sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_2);
+ (void)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 {
@@ -428,6 +428,7 @@ sctp_getcred(SYSCTL_HANDLER_ARGS)
SCTP_INP_DECR_REF(inp);
goto cred_can_cont;
}
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
error = ENOENT;
goto out;
}
@@ -463,9 +464,9 @@ sctp_abort(struct socket *so)
uint32_t flags;
inp = (struct sctp_inpcb *)so->so_pcb;
- if (inp == 0)
+ if (inp == 0) {
return;
-
+ }
sctp_must_try_again:
flags = inp->sctp_flags;
#ifdef SCTP_LOG_CLOSING
@@ -512,6 +513,7 @@ sctp_attach(struct socket *so, int proto, struct thread *p)
#endif
inp = (struct sctp_inpcb *)so->so_pcb;
if (inp != 0) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return EINVAL;
}
error = SCTP_SORESERVE(so, sctp_sendspace, sctp_recvspace);
@@ -558,21 +560,25 @@ sctp_attach(struct socket *so, int proto, struct thread *p)
static int
sctp_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
{
- struct sctp_inpcb *inp;
+ struct sctp_inpcb *inp = NULL;
int error;
#ifdef INET6
- if (addr && addr->sa_family != AF_INET)
+ if (addr && addr->sa_family != AF_INET) {
/* must be a v4 address! */
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return EINVAL;
+ }
#endif /* INET6 */
if (addr && (addr->sa_len != sizeof(struct sockaddr_in))) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return EINVAL;
}
inp = (struct sctp_inpcb *)so->so_pcb;
- if (inp == 0)
+ if (inp == 0) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return EINVAL;
-
+ }
error = sctp_inpcb_bind(so, addr, NULL, p);
return error;
}
@@ -654,6 +660,7 @@ sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
sctp_m_freem(control);
control = NULL;
}
+ SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
sctp_m_freem(m);
return EINVAL;
}
@@ -664,6 +671,7 @@ sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
) {
goto connected_type;
} else if (addr == NULL) {
+ SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EDESTADDRREQ);
error = EDESTADDRREQ;
sctp_m_freem(m);
if (control) {
@@ -675,13 +683,14 @@ sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
#ifdef INET6
if (addr->sa_family != AF_INET) {
/* must be a v4 address! */
+ SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EDESTADDRREQ);
sctp_m_freem(m);
if (control) {
sctp_m_freem(control);
control = NULL;
}
error = EDESTADDRREQ;
- return EINVAL;
+ return EDESTADDRREQ;
}
#endif /* INET6 */
connected_type:
@@ -731,6 +740,7 @@ sctp_disconnect(struct socket *so)
inp = (struct sctp_inpcb *)so->so_pcb;
if (inp == NULL) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
return (ENOTCONN);
}
SCTP_INP_RLOCK(inp);
@@ -747,6 +757,7 @@ sctp_disconnect(struct socket *so)
stcb = LIST_FIRST(&inp->sctp_asoc_list);
if (stcb == NULL) {
SCTP_INP_RUNLOCK(inp);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (EINVAL);
}
SCTP_TCB_LOCK(stcb);
@@ -786,7 +797,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, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_3);
+ (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_3);
/* No unlock tcb assoc is gone */
return (0);
}
@@ -808,7 +819,7 @@ sctp_disconnect(struct socket *so)
(SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
- asoc->state = SCTP_STATE_SHUTDOWN_SENT;
+ SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
stcb->sctp_ep, stcb,
asoc->primary_destination);
@@ -877,7 +888,7 @@ sctp_disconnect(struct socket *so)
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
SCTP_INP_RUNLOCK(inp);
- sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_5);
+ (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_5);
return (0);
}
}
@@ -889,6 +900,7 @@ sctp_disconnect(struct socket *so)
} else {
/* UDP model does not support this */
SCTP_INP_RUNLOCK(inp);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
return EOPNOTSUPP;
}
}
@@ -900,6 +912,7 @@ sctp_shutdown(struct socket *so)
inp = (struct sctp_inpcb *)so->so_pcb;
if (inp == 0) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return EINVAL;
}
SCTP_INP_RLOCK(inp);
@@ -909,6 +922,7 @@ sctp_shutdown(struct socket *so)
so->so_rcv.sb_state &= ~SBS_CANTRCVMORE;
/* This proc will wakeup for read and do nothing (I hope) */
SCTP_INP_RUNLOCK(inp);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
return (EOPNOTSUPP);
}
/*
@@ -950,7 +964,7 @@ sctp_shutdown(struct socket *so)
(SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
- asoc->state = SCTP_STATE_SHUTDOWN_SENT;
+ SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
stcb->sctp_ep, stcb,
asoc->primary_destination);
@@ -1286,9 +1300,11 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
(inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
/* We are already connected AND the TCP model */
+ SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
return (EADDRINUSE);
}
if (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) {
+ SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (EINVAL);
}
if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
@@ -1297,6 +1313,7 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
SCTP_INP_RUNLOCK(inp);
}
if (stcb) {
+ SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
return (EALREADY);
}
SCTP_INP_INCR_REF(inp);
@@ -1304,6 +1321,7 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
creat_lock_on = 1;
if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
(inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
+ SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
error = EFAULT;
goto out_now;
}
@@ -1317,8 +1335,10 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
creat_lock_on = 0;
if (stcb)
SCTP_TCB_UNLOCK(stcb);
- if (bad_addresses == 0)
+ if (bad_addresses == 0) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
error = EALREADY;
+ }
goto out_now;
}
#ifdef INET6
@@ -1337,6 +1357,7 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
* if IPV6_V6ONLY flag, ignore connections destined
* to a v4 addr or v4-mapped addr
*/
+ SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
goto out_now;
}
@@ -1361,7 +1382,7 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
/* Gak! no memory */
goto out_now;
}
- stcb->asoc.state = SCTP_STATE_COOKIE_WAIT;
+ SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
/* move to second address */
if (sa->sa_family == AF_INET)
sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in));
@@ -1372,7 +1393,7 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
added = sctp_connectx_helper_add(stcb, sa, (totaddr - 1), &error);
/* Fill in the return id */
if (error) {
- sctp_free_assoc(inp, stcb, SCTP_PCBFREE_FORCE, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_12);
+ (void)sctp_free_assoc(inp, stcb, SCTP_PCBFREE_FORCE, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_12);
goto out_now;
}
a_id = (sctp_assoc_t *) optval;
@@ -1415,6 +1436,7 @@ out_now:
} else if (assoc_id != 0) { \
stcb = sctp_findassociation_ep_asocid(inp, assoc_id, 1); \
if (stcb == NULL) { \
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT); \
error = ENOENT; \
break; \
} \
@@ -1426,6 +1448,7 @@ out_now:
#define SCTP_CHECK_AND_CAST(destp, srcp, type, size) {\
if (size < sizeof(type)) { \
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); \
error = EINVAL; \
break; \
} else { \
@@ -1437,16 +1460,19 @@ static int
sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
void *p)
{
- struct sctp_inpcb *inp;
+ struct sctp_inpcb *inp = NULL;
int error, val = 0;
struct sctp_tcb *stcb = NULL;
if (optval == NULL) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (EINVAL);
}
inp = (struct sctp_inpcb *)so->so_pcb;
- if (inp == 0)
+ if (inp == 0) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return EINVAL;
+ }
error = 0;
switch (optname) {
@@ -1466,7 +1492,14 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4);
break;
case SCTP_AUTO_ASCONF:
- val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTO_ASCONF);
+ if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
+ /* only valid for bound all sockets */
+ val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTO_ASCONF);
+ } else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ goto flags_out;
+ }
break;
case SCTP_EXPLICIT_EOR:
val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR);
@@ -1485,6 +1518,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
break;
default:
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
error = ENOPROTOOPT;
} /* end switch (sopt->sopt_name) */
if (optname != SCTP_AUTOCLOSE) {
@@ -1492,8 +1526,10 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
val = (val != 0);
}
if (*optsize < sizeof(val)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
}
+flags_out:
SCTP_INP_RUNLOCK(inp);
if (error == 0) {
/* return the option value */
@@ -1511,6 +1547,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
ret = sctp_copy_out_packet_log(target, (int)*optsize);
*optsize = ret;
#else
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
error = EOPNOTSUPP;
#endif
break;
@@ -1553,9 +1590,11 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
SCTP_TCB_UNLOCK(stcb);
} else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
error = ENOTCONN;
}
} else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
error = ENOPROTOOPT;
}
*optsize = sizeof(*av);
@@ -1595,6 +1634,9 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
error = 0;
}
#endif
+ if (error)
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
+
*optsize = sizeof(*av);
}
break;
@@ -1628,6 +1670,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
ids->gaids_assoc_id[at++] = sctp_get_associd(stcb);
} else {
error = EINVAL;
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
break;
}
}
@@ -1669,6 +1712,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
SCTP_FIND_STCB(inp, stcb, id->assoc_id);
if (stcb == NULL) {
error = EINVAL;
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
break;
}
id->assoc_value = stcb->asoc.vrf_id;
@@ -1676,6 +1720,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
}
case SCTP_GET_VRF_IDS:
{
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
error = EOPNOTSUPP;
break;
}
@@ -1691,6 +1736,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
gnv->gn_local_tag = stcb->asoc.my_vtag;
SCTP_TCB_UNLOCK(stcb);
} else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
error = ENOTCONN;
}
*optsize = sizeof(*gnv);
@@ -1729,6 +1775,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
stcb->asoc.size_on_all_streams);
SCTP_TCB_UNLOCK(stcb);
} else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
error = ENOTCONN;
}
*optsize = sizeof(struct sctp_sockstat);
@@ -1878,6 +1925,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
SCTP_TCB_UNLOCK(stcb);
*value = (uint32_t) size;
} else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
error = ENOTCONN;
}
*optsize = sizeof(uint32_t);
@@ -1932,6 +1980,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
}
SCTP_TCB_UNLOCK(stcb);
} else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
error = ENOENT;
}
}
@@ -1979,7 +2028,37 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
SCTP_INP_DECR_REF(inp);
}
}
+ if (stcb && (net == NULL)) {
+ struct sockaddr *sa;
+
+ sa = (struct sockaddr *)&paddrp->spp_address;
+ if (sa->sa_family == AF_INET) {
+ struct sockaddr_in *sin;
+ sin = (struct sockaddr_in *)sa;
+ if (sin->sin_addr.s_addr) {
+ error = EINVAL;
+ SCTP_TCB_UNLOCK(stcb);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
+ break;
+ }
+ } else if (sa->sa_family == AF_INET6) {
+ struct sockaddr_in6 *sin6;
+
+ sin6 = (struct sockaddr_in6 *)sa;
+ if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
+ error = EINVAL;
+ SCTP_TCB_UNLOCK(stcb);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
+ break;
+ }
+ } else {
+ error = EAFNOSUPPORT;
+ SCTP_TCB_UNLOCK(stcb);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
+ break;
+ }
+ }
if (stcb) {
/* Applys to the specific association */
paddrp->spp_flags = 0;
@@ -2123,6 +2202,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
if (stcb) {
SCTP_TCB_UNLOCK(stcb);
}
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
error = ENOENT;
}
*optsize = sizeof(struct sctp_paddrinfo);
@@ -2147,6 +2227,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
SCTP_FIND_STCB(inp, stcb, sstat->sstat_assoc_id);
if (stcb == NULL) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
error = EINVAL;
break;
}
@@ -2291,6 +2372,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
len);
SCTP_TCB_UNLOCK(stcb);
} else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
error = EINVAL;
}
*optsize = sizeof(*ssp);
@@ -2318,6 +2400,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
size = sizeof(*shmac) + (hmaclist->num_algo *
sizeof(shmac->shmac_idents[0]));
if ((size_t)(*optsize) < size) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
error = EINVAL;
SCTP_INP_RUNLOCK(inp);
break;
@@ -2365,6 +2448,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
size = sctp_auth_get_chklist_size(chklist);
if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
error = EINVAL;
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
} else {
/* copy in the chunks */
(void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
@@ -2378,6 +2462,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
size = sctp_auth_get_chklist_size(chklist);
if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
error = EINVAL;
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
} else {
/* copy in the chunks */
(void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
@@ -2403,12 +2488,14 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
size = sctp_auth_get_chklist_size(chklist);
if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
error = EINVAL;
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
} else {
/* copy in the chunks */
(void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
}
SCTP_TCB_UNLOCK(stcb);
} else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
error = ENOENT;
}
*optsize = sizeof(struct sctp_authchunks) + size;
@@ -2417,6 +2504,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
default:
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
error = ENOPROTOOPT;
*optsize = 0;
break;
@@ -2431,16 +2519,18 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
int error, set_opt;
uint32_t *mopt;
struct sctp_tcb *stcb = NULL;
- struct sctp_inpcb *inp;
+ struct sctp_inpcb *inp = NULL;
uint32_t vrf_id;
if (optval == NULL) {
SCTP_PRINTF("optval is NULL\n");
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (EINVAL);
}
inp = (struct sctp_inpcb *)so->so_pcb;
if (inp == 0) {
SCTP_PRINTF("inp is NULL?\n");
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return EINVAL;
}
vrf_id = inp->def_vrf_id;
@@ -2464,7 +2554,16 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
set_opt = SCTP_PCB_FLAGS_NO_FRAGMENT;
break;
case SCTP_AUTO_ASCONF:
- set_opt = SCTP_PCB_FLAGS_AUTO_ASCONF;
+ /*
+ * NOTE: we don't really support this flag
+ */
+ if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
+ /* only valid for bound all sockets */
+ set_opt = SCTP_PCB_FLAGS_AUTO_ASCONF;
+ } else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ return (EINVAL);
+ }
break;
case SCTP_EXPLICIT_EOR:
set_opt = SCTP_PCB_FLAGS_EXPLICIT_EOR;
@@ -2476,6 +2575,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
set_opt = SCTP_PCB_FLAGS_NEEDS_MAPPED_V4;
} else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (EINVAL);
}
break;
@@ -2485,6 +2585,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
case SCTP_AUTOCLOSE:
if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
(inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (EINVAL);
}
set_opt = SCTP_PCB_FLAGS_AUTOCLOSE;
@@ -2509,6 +2610,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
if (*value > SCTP_SB_LIMIT_RCV(so)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
break;
}
@@ -2532,6 +2634,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
} else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
}
}
@@ -2547,9 +2650,11 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
stcb->asoc.sctp_cmt_on_off = (uint8_t) av->assoc_value;
SCTP_TCB_UNLOCK(stcb);
} else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
error = ENOTCONN;
}
} else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
error = ENOPROTOOPT;
}
}
@@ -2620,6 +2725,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
*/
default:
{
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
SCTP_TCB_UNLOCK(stcb);
break;
@@ -2633,6 +2739,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
inp->sctp_ep.sctp_default_cc_module = av->assoc_value;
break;
default:
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
break;
};
@@ -2640,6 +2747,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
break;
case SCTP_CLR_STAT_LOG:
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
error = EOPNOTSUPP;
break;
case SCTP_CONTEXT:
@@ -2665,6 +2773,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_CHECK_AND_CAST(default_vrfid, optval, uint32_t, optsize);
if (*default_vrfid > SCTP_MAX_VRF_ID) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
break;
}
@@ -2673,11 +2782,13 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
case SCTP_DEL_VRF_ID:
{
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
error = EOPNOTSUPP;
break;
}
case SCTP_ADD_VRF_ID:
{
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
error = EOPNOTSUPP;
break;
}
@@ -2724,8 +2835,10 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_CHECK_AND_CAST(sauth, optval, struct sctp_authchunk, optsize);
SCTP_INP_WLOCK(inp);
- if (sctp_auth_add_chunk(sauth->sauth_chunk, inp->sctp_ep.local_auth_chunks))
+ if (sctp_auth_add_chunk(sauth->sauth_chunk, inp->sctp_ep.local_auth_chunks)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
+ }
SCTP_INP_WUNLOCK(inp);
break;
}
@@ -2753,6 +2866,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
if (size > 0) {
key = sctp_set_key(sca->sca_key, (uint32_t) size);
if (key == NULL) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
error = ENOMEM;
SCTP_TCB_UNLOCK(stcb);
break;
@@ -2761,6 +2875,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
shared_key = sctp_alloc_sharedkey();
if (shared_key == NULL) {
sctp_free_key(key);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
error = ENOMEM;
SCTP_TCB_UNLOCK(stcb);
break;
@@ -2785,6 +2900,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
if (size > 0) {
key = sctp_set_key(sca->sca_key, (uint32_t) size);
if (key == NULL) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
error = ENOMEM;
SCTP_INP_WUNLOCK(inp);
break;
@@ -2793,6 +2909,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
shared_key = sctp_alloc_sharedkey();
if (shared_key == NULL) {
sctp_free_key(key);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
error = ENOMEM;
SCTP_INP_WUNLOCK(inp);
break;
@@ -2815,6 +2932,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
size = (optsize - sizeof(*shmac)) / sizeof(shmac->shmac_idents[0]);
hmaclist = sctp_alloc_hmaclist(size);
if (hmaclist == NULL) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
error = ENOMEM;
break;
}
@@ -2822,6 +2940,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
hmacid = shmac->shmac_idents[i];
if (sctp_auth_add_hmacid(hmaclist, (uint16_t) hmacid)) {
/* invalid HMACs were found */ ;
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
sctp_free_hmaclist(hmaclist);
goto sctp_set_hmac_done;
@@ -2836,6 +2955,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
if (!found) {
sctp_free_hmaclist(hmaclist);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
break;
}
@@ -2858,14 +2978,18 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
/* set the active key on the right place */
if (stcb) {
/* set the active key on the assoc */
- if (sctp_auth_setactivekey(stcb, scact->scact_keynumber))
+ if (sctp_auth_setactivekey(stcb, scact->scact_keynumber)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
+ }
SCTP_TCB_UNLOCK(stcb);
} else {
/* set the active key on the endpoint */
SCTP_INP_WLOCK(inp);
- if (sctp_auth_setactivekey_ep(inp, scact->scact_keynumber))
+ if (sctp_auth_setactivekey_ep(inp, scact->scact_keynumber)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
+ }
SCTP_INP_WUNLOCK(inp);
}
break;
@@ -2879,13 +3003,17 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
/* delete the key from the right place */
if (stcb) {
- if (sctp_delete_sharedkey(stcb, scdel->scact_keynumber))
+ if (sctp_delete_sharedkey(stcb, scdel->scact_keynumber)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
+ }
SCTP_TCB_UNLOCK(stcb);
} else {
SCTP_INP_WLOCK(inp);
- if (sctp_delete_sharedkey_ep(inp, scdel->scact_keynumber))
+ if (sctp_delete_sharedkey_ep(inp, scdel->scact_keynumber)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
+ }
SCTP_INP_WUNLOCK(inp);
}
break;
@@ -2901,6 +3029,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_FIND_STCB(inp, stcb, strrst->strrst_assoc_id);
if (stcb == NULL) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
error = ENOENT;
break;
}
@@ -2911,11 +3040,13 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
* for this feature and this peer, not the
* socket request in general.
*/
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EPROTONOSUPPORT);
error = EPROTONOSUPPORT;
SCTP_TCB_UNLOCK(stcb);
break;
}
if (stcb->asoc.stream_reset_outstanding) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
error = EALREADY;
SCTP_TCB_UNLOCK(stcb);
break;
@@ -2930,6 +3061,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
} else if (strrst->strrst_flags == SCTP_RESET_TSN) {
send_tsn = 1;
} else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
SCTP_TCB_UNLOCK(stcb);
break;
@@ -2938,11 +3070,13 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
if ((send_in) &&
(strrst->strrst_list[i] > stcb->asoc.streamincnt)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
goto get_out;
}
if ((send_out) &&
(strrst->strrst_list[i] > stcb->asoc.streamoutcnt)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
goto get_out;
}
@@ -2964,6 +3098,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
case SCTP_CONNECT_X:
if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
break;
}
@@ -2972,6 +3107,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
case SCTP_CONNECT_X_DELAYED:
if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
break;
}
@@ -3011,6 +3147,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
if (stcb == NULL) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
error = ENOENT;
break;
}
@@ -3026,6 +3163,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
* already expired or did not use delayed
* connectx
*/
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
error = EALREADY;
}
SCTP_TCB_UNLOCK(stcb);
@@ -3182,6 +3320,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
if (s_info->sinfo_stream <= stcb->asoc.streamoutcnt) {
memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
} else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
}
SCTP_TCB_UNLOCK(stcb);
@@ -3219,15 +3358,48 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_INP_DECR_REF(inp);
}
}
+ if (stcb && (net == NULL)) {
+ struct sockaddr *sa;
+
+ sa = (struct sockaddr *)&paddrp->spp_address;
+ if (sa->sa_family == AF_INET) {
+ struct sockaddr_in *sin;
+
+ sin = (struct sockaddr_in *)sa;
+ if (sin->sin_addr.s_addr) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ SCTP_TCB_UNLOCK(stcb);
+ error = EINVAL;
+ break;
+ }
+ } else if (sa->sa_family == AF_INET6) {
+ struct sockaddr_in6 *sin6;
+
+ sin6 = (struct sockaddr_in6 *)sa;
+ if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ SCTP_TCB_UNLOCK(stcb);
+ error = EINVAL;
+ break;
+ }
+ } else {
+ error = EAFNOSUPPORT;
+ SCTP_TCB_UNLOCK(stcb);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
+ break;
+ }
+ }
/* sanity checks */
if ((paddrp->spp_flags & SPP_HB_ENABLE) && (paddrp->spp_flags & SPP_HB_DISABLE)) {
if (stcb)
SCTP_TCB_UNLOCK(stcb);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (EINVAL);
}
if ((paddrp->spp_flags & SPP_PMTUD_ENABLE) && (paddrp->spp_flags & SPP_PMTUD_DISABLE)) {
if (stcb)
SCTP_TCB_UNLOCK(stcb);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (EINVAL);
}
if (stcb) {
@@ -3256,6 +3428,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
/* on demand HB */
if (sctp_send_hb(stcb, 1, net) < 0) {
/* asoc destroyed */
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
break;
}
@@ -3430,6 +3603,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
stcb->asoc.maxrto = new_max;
stcb->asoc.minrto = new_min;
} else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EDOM);
error = EDOM;
}
SCTP_TCB_UNLOCK(stcb);
@@ -3452,6 +3626,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
inp->sctp_ep.sctp_maxrto = new_max;
inp->sctp_ep.sctp_minrto = new_min;
} else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EDOM);
error = EDOM;
}
SCTP_INP_WUNLOCK(inp);
@@ -3557,6 +3732,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
}
} else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
}
if (stcb) {
@@ -3590,6 +3766,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
ifa = sctp_find_ifa_by_addr((struct sockaddr *)&sspp->sspp_addr,
stcb->asoc.vrf_id, 0);
if (ifa == NULL) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
goto out_of_it;
}
@@ -3613,17 +3790,20 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
}
if (!found) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
goto out_of_it;
}
}
if (sctp_set_primary_ip_address_sa(stcb,
(struct sockaddr *)&sspp->sspp_addr) != 0) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
}
out_of_it:
SCTP_TCB_UNLOCK(stcb);
} else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
}
@@ -3645,15 +3825,18 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
if (addrs->addr->sa_family == AF_INET) {
sz = sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in);
if (optsize < sz) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
break;
}
if (prison && prison_ip(td->td_ucred, 0, &(((struct sockaddr_in *)(addrs->addr))->sin_addr.s_addr))) {
+ SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRNOTAVAIL);
error = EADDRNOTAVAIL;
}
} else if (addrs->addr->sa_family == AF_INET6) {
sz = sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6);
if (optsize < sz) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
break;
}
@@ -3679,15 +3862,18 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
if (addrs->addr->sa_family == AF_INET) {
sz = sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in);
if (optsize < sz) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
break;
}
if (prison && prison_ip(td->td_ucred, 0, &(((struct sockaddr_in *)(addrs->addr))->sin_addr.s_addr))) {
+ SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRNOTAVAIL);
error = EADDRNOTAVAIL;
}
} else if (addrs->addr->sa_family == AF_INET6) {
sz = sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6);
if (optsize < sz) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
break;
}
@@ -3699,6 +3885,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
break;
default:
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
error = ENOPROTOOPT;
break;
} /* end switch (opt) */
@@ -3718,6 +3905,7 @@ sctp_ctloutput(struct socket *so, struct sockopt *sopt)
inp = (struct sctp_inpcb *)so->so_pcb;
if (inp == 0) {
/* I made the same as TCP since we are not setup? */
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (ECONNRESET);
}
if (sopt->sopt_level != IPPROTO_SCTP) {
@@ -3734,6 +3922,7 @@ sctp_ctloutput(struct socket *so, struct sockopt *sopt)
if (optsize) {
SCTP_MALLOC(optval, void *, optsize, SCTP_M_SOCKOPT);
if (optval == NULL) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS);
return (ENOBUFS);
}
error = sooptcopyin(sopt, optval, optsize, optsize);
@@ -3748,6 +3937,7 @@ sctp_ctloutput(struct socket *so, struct sockopt *sopt)
} else if (sopt->sopt_dir == SOPT_GET) {
error = sctp_getopt(so, sopt->sopt_name, optval, &optsize, p);
} else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
}
if ((error == 0) && (optval != NULL)) {
@@ -3773,15 +3963,19 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
inp = (struct sctp_inpcb *)so->so_pcb;
if (inp == 0) {
/* I made the same as TCP since we are not setup? */
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (ECONNRESET);
}
- if (addr == NULL)
+ if (addr == NULL) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return EINVAL;
-
+ }
if ((addr->sa_family == AF_INET6) && (addr->sa_len != sizeof(struct sockaddr_in6))) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (EINVAL);
}
if ((addr->sa_family == AF_INET) && (addr->sa_len != sizeof(struct sockaddr_in))) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (EINVAL);
}
SCTP_ASOC_CREATE_LOCK(inp);
@@ -3791,12 +3985,14 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
(inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
/* Should I really unlock ? */
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
error = EFAULT;
goto out_now;
}
#ifdef INET6
if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
(addr->sa_family == AF_INET6)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
goto out_now;
}
@@ -3811,12 +4007,14 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
}
/* Now do we connect? */
if (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
goto out_now;
}
if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
(inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
/* We are already connected AND the TCP model */
+ SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
error = EADDRINUSE;
goto out_now;
}
@@ -3840,6 +4038,7 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
}
if (stcb != NULL) {
/* Already have or am bring up an association */
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
error = EALREADY;
goto out_now;
}
@@ -3855,7 +4054,7 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
/* Set the connected flag so we can queue data */
soisconnecting(so);
}
- stcb->asoc.state = SCTP_STATE_COOKIE_WAIT;
+ SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
/* initialize authentication parameters for the assoc */
@@ -3889,6 +4088,7 @@ sctp_listen(struct socket *so, int backlog, struct thread *p)
inp = (struct sctp_inpcb *)so->so_pcb;
if (inp == 0) {
/* I made the same as TCP since we are not setup? */
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (ECONNRESET);
}
SCTP_INP_RLOCK(inp);
@@ -3909,6 +4109,7 @@ sctp_listen(struct socket *so, int backlog, struct thread *p)
/* We are already connected AND the TCP model */
SCTP_INP_RUNLOCK(inp);
SOCK_UNLOCK(so);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
return (EADDRINUSE);
}
if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
@@ -3951,20 +4152,24 @@ sctp_accept(struct socket *so, struct sockaddr **addr)
inp = (struct sctp_inpcb *)so->so_pcb;
if (inp == 0) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (ECONNRESET);
}
SCTP_INP_RLOCK(inp);
if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
SCTP_INP_RUNLOCK(inp);
- return (ENOTSUP);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
+ return (EOPNOTSUPP);
}
if (so->so_state & SS_ISDISCONNECTED) {
SCTP_INP_RUNLOCK(inp);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ECONNABORTED);
return (ECONNABORTED);
}
stcb = LIST_FIRST(&inp->sctp_asoc_list);
if (stcb == NULL) {
SCTP_INP_RUNLOCK(inp);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (ECONNRESET);
}
SCTP_TCB_LOCK(stcb);
@@ -4044,6 +4249,7 @@ sctp_ingetaddr(struct socket *so, struct sockaddr **addr)
inp = (struct sctp_inpcb *)so->so_pcb;
if (!inp) {
SCTP_FREE_SONAME(sin);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return ECONNRESET;
}
SCTP_INP_RLOCK(inp);
@@ -4112,6 +4318,7 @@ sctp_ingetaddr(struct socket *so, struct sockaddr **addr)
if (!fnd) {
SCTP_FREE_SONAME(sin);
SCTP_INP_RUNLOCK(inp);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
return ENOENT;
}
}
@@ -4135,6 +4342,7 @@ sctp_peeraddr(struct socket *so, struct sockaddr **addr)
if ((inp == NULL) ||
((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
/* UDP type and listeners will drop out here */
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
return (ENOTCONN);
}
SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
@@ -4145,6 +4353,7 @@ sctp_peeraddr(struct socket *so, struct sockaddr **addr)
inp = (struct sctp_inpcb *)so->so_pcb;
if (!inp) {
SCTP_FREE_SONAME(sin);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return ECONNRESET;
}
SCTP_INP_RLOCK(inp);
@@ -4155,6 +4364,7 @@ sctp_peeraddr(struct socket *so, struct sockaddr **addr)
SCTP_INP_RUNLOCK(inp);
if (stcb == NULL) {
SCTP_FREE_SONAME(sin);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return ECONNRESET;
}
fnd = 0;
@@ -4171,6 +4381,7 @@ sctp_peeraddr(struct socket *so, struct sockaddr **addr)
if (!fnd) {
/* No IPv4 address */
SCTP_FREE_SONAME(sin);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
return ENOENT;
}
(*addr) = (struct sockaddr *)sin;
diff --git a/sys/netinet/sctp_var.h b/sys/netinet/sctp_var.h
index 38c694b..ba33d9e 100644
--- a/sys/netinet/sctp_var.h
+++ b/sys/netinet/sctp_var.h
@@ -167,16 +167,10 @@ extern struct pr_usrreqs sctp_usrreqs;
if (val < SCTP_BUF_LEN((m))) {\
panic("stcb->sb_cc goes negative"); \
} \
- val = atomic_fetchadd_int(&(stcb)->asoc.sb_mbcnt,-(MSIZE)); \
+ val = atomic_fetchadd_int(&(stcb)->asoc.my_rwnd_control_len,-(MSIZE)); \
if (val < MSIZE) { \
panic("asoc->mbcnt goes negative"); \
} \
- if (SCTP_BUF_IS_EXTENDED(m)) { \
- val = atomic_fetchadd_int(&(stcb)->asoc.sb_mbcnt,-(SCTP_BUF_EXTEND_SIZE(m))); \
- if (val < SCTP_BUF_EXTEND_SIZE(m)) { \
- panic("assoc stcb->mbcnt would go negative"); \
- } \
- } \
} \
if (SCTP_BUF_TYPE(m) != MT_DATA && SCTP_BUF_TYPE(m) != MT_HEADER && \
SCTP_BUF_TYPE(m) != MT_OOBDATA) \
@@ -191,9 +185,7 @@ extern struct pr_usrreqs sctp_usrreqs;
atomic_add_int(&(sb)->sb_mbcnt,SCTP_BUF_EXTEND_SIZE(m)); \
if (stcb) { \
atomic_add_int(&(stcb)->asoc.sb_cc,SCTP_BUF_LEN((m))); \
- atomic_add_int(&(stcb)->asoc.sb_mbcnt, MSIZE); \
- if (SCTP_BUF_IS_EXTENDED(m)) \
- atomic_add_int(&(stcb)->asoc.sb_mbcnt,SCTP_BUF_EXTEND_SIZE(m)); \
+ atomic_add_int(&(stcb)->asoc.my_rwnd_control_len, MSIZE); \
} \
if (SCTP_BUF_TYPE(m) != MT_DATA && SCTP_BUF_TYPE(m) != MT_HEADER && \
SCTP_BUF_TYPE(m) != MT_OOBDATA) \
@@ -291,6 +283,7 @@ extern struct pr_usrreqs sctp_usrreqs;
#endif
+
struct sctp_nets;
struct sctp_inpcb;
struct sctp_tcb;
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index e7e0987..76dfc28 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -71,7 +71,7 @@ sctp_sblog(struct sockbuf *sb,
else
sctp_clog.x.sb.stcb_sbcc = 0;
sctp_clog.x.sb.incr = incr;
- CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
+ SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
SCTP_LOG_EVENT_SB,
from,
sctp_clog.x.misc.log1,
@@ -95,7 +95,7 @@ sctp_log_closing(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int16_t loc)
sctp_clog.x.close.state = 0;
}
sctp_clog.x.close.loc = loc;
- CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
+ SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
SCTP_LOG_EVENT_CLOSE,
0,
sctp_clog.x.misc.log1,
@@ -112,7 +112,7 @@ rto_logging(struct sctp_nets *net, int from)
sctp_clog.x.rto.net = (void *)net;
sctp_clog.x.rto.rtt = net->prev_rtt;
- CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
+ SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
SCTP_LOG_EVENT_RTT,
from,
sctp_clog.x.misc.log1,
@@ -133,7 +133,7 @@ sctp_log_strm_del_alt(struct sctp_tcb *stcb, uint32_t tsn, uint16_t sseq, uint16
sctp_clog.x.strlog.e_tsn = 0;
sctp_clog.x.strlog.e_sseq = 0;
sctp_clog.x.strlog.strm = stream;
- CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
+ SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
SCTP_LOG_EVENT_STRM,
from,
sctp_clog.x.misc.log1,
@@ -153,7 +153,7 @@ sctp_log_nagle_event(struct sctp_tcb *stcb, int action)
sctp_clog.x.nagle.total_in_queue = stcb->asoc.total_output_queue_size;
sctp_clog.x.nagle.count_in_queue = stcb->asoc.chunks_on_out_queue;
sctp_clog.x.nagle.count_in_flight = stcb->asoc.total_flight_count;
- CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
+ SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
SCTP_LOG_EVENT_NAGLE,
action,
sctp_clog.x.misc.log1,
@@ -173,7 +173,7 @@ sctp_log_sack(uint32_t old_cumack, uint32_t cumack, uint32_t tsn, uint16_t gaps,
sctp_clog.x.sack.tsn = tsn;
sctp_clog.x.sack.numGaps = gaps;
sctp_clog.x.sack.numDups = dups;
- CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
+ SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
SCTP_LOG_EVENT_SACK,
from,
sctp_clog.x.misc.log1,
@@ -190,7 +190,7 @@ sctp_log_map(uint32_t map, uint32_t cum, uint32_t high, int from)
sctp_clog.x.map.base = map;
sctp_clog.x.map.cum = cum;
sctp_clog.x.map.high = high;
- CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
+ SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
SCTP_LOG_EVENT_MAP,
from,
sctp_clog.x.misc.log1,
@@ -208,7 +208,7 @@ sctp_log_fr(uint32_t biggest_tsn, uint32_t biggest_new_tsn, uint32_t tsn,
sctp_clog.x.fr.largest_tsn = biggest_tsn;
sctp_clog.x.fr.largest_new_tsn = biggest_new_tsn;
sctp_clog.x.fr.tsn = tsn;
- CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
+ SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
SCTP_LOG_EVENT_FR,
from,
sctp_clog.x.misc.log1,
@@ -235,7 +235,7 @@ sctp_log_mb(struct mbuf *m, int from)
sctp_clog.x.mb.ext = 0;
sctp_clog.x.mb.refcnt = 0;
}
- CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
+ SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
SCTP_LOG_EVENT_MBUF,
from,
sctp_clog.x.misc.log1,
@@ -266,7 +266,7 @@ sctp_log_strm_del(struct sctp_queued_to_read *control, struct sctp_queued_to_rea
sctp_clog.x.strlog.e_tsn = 0;
sctp_clog.x.strlog.e_sseq = 0;
}
- CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
+ SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
SCTP_LOG_EVENT_STRM,
from,
sctp_clog.x.misc.log1,
@@ -302,7 +302,7 @@ sctp_log_cwnd(struct sctp_tcb *stcb, struct sctp_nets *net, int augment, uint8_t
sctp_clog.x.cwnd.meets_pseudo_cumack = stcb->asoc.peers_rwnd;
}
sctp_clog.x.cwnd.cwnd_augment = augment;
- CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
+ SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
SCTP_LOG_EVENT_CWND,
from,
sctp_clog.x.misc.log1,
@@ -346,7 +346,7 @@ sctp_log_lock(struct sctp_inpcb *inp, struct sctp_tcb *stcb, uint8_t from)
sctp_clog.x.lock.sockrcvbuf_lock = SCTP_LOCK_UNKNOWN;
sctp_clog.x.lock.socksndbuf_lock = SCTP_LOCK_UNKNOWN;
}
- CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
+ SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
SCTP_LOG_LOCK_EVENT,
from,
sctp_clog.x.misc.log1,
@@ -373,7 +373,7 @@ sctp_log_maxburst(struct sctp_tcb *stcb, struct sctp_nets *net, int error, int b
sctp_clog.x.cwnd.cnt_in_str = 255;
else
sctp_clog.x.cwnd.cnt_in_str = stcb->asoc.stream_queue_cnt;
- CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
+ SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
SCTP_LOG_EVENT_MAXBURST,
from,
sctp_clog.x.misc.log1,
@@ -392,7 +392,7 @@ sctp_log_rwnd(uint8_t from, uint32_t peers_rwnd, uint32_t snd_size, uint32_t ove
sctp_clog.x.rwnd.send_size = snd_size;
sctp_clog.x.rwnd.overhead = overhead;
sctp_clog.x.rwnd.new_rwnd = 0;
- CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
+ SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
SCTP_LOG_EVENT_RWND,
from,
sctp_clog.x.misc.log1,
@@ -410,7 +410,7 @@ sctp_log_rwnd_set(uint8_t from, uint32_t peers_rwnd, uint32_t flight_size, uint3
sctp_clog.x.rwnd.send_size = flight_size;
sctp_clog.x.rwnd.overhead = overhead;
sctp_clog.x.rwnd.new_rwnd = a_rwndval;
- CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
+ SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
SCTP_LOG_EVENT_RWND,
from,
sctp_clog.x.misc.log1,
@@ -428,7 +428,7 @@ sctp_log_mbcnt(uint8_t from, uint32_t total_oq, uint32_t book, uint32_t total_mb
sctp_clog.x.mbcnt.size_change = book;
sctp_clog.x.mbcnt.total_queue_mb_size = total_mbcnt_q;
sctp_clog.x.mbcnt.mbcnt_change = mbcnt;
- CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
+ SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
SCTP_LOG_EVENT_MBCNT,
from,
sctp_clog.x.misc.log1,
@@ -441,7 +441,7 @@ sctp_log_mbcnt(uint8_t from, uint32_t total_oq, uint32_t book, uint32_t total_mb
void
sctp_misc_ints(uint8_t from, uint32_t a, uint32_t b, uint32_t c, uint32_t d)
{
- CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
+ SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
SCTP_LOG_MISC_EVENT,
from,
a, b, c, d);
@@ -484,7 +484,7 @@ sctp_wakeup_log(struct sctp_tcb *stcb, uint32_t cumtsn, uint32_t wake_cnt, int f
} else {
sctp_clog.x.wake.sbflags = 0xff;
}
- CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
+ SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
SCTP_LOG_EVENT_WAKE,
from,
sctp_clog.x.misc.log1,
@@ -506,7 +506,7 @@ sctp_log_block(uint8_t from, struct socket *so, struct sctp_association *asoc, i
sctp_clog.x.blk.chunks_on_oque = (uint16_t) asoc->chunks_on_out_queue;
sctp_clog.x.blk.flight_size = (uint16_t) (asoc->total_flight / 1024);
sctp_clog.x.blk.sndlen = sendlen;
- CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
+ SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
SCTP_LOG_EVENT_BLOCK,
from,
sctp_clog.x.misc.log1,
@@ -876,7 +876,7 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb,
asoc = &stcb->asoc;
/* init all variables to a known value. */
- asoc->state = SCTP_STATE_INUSE;
+ SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_INUSE);
asoc->max_burst = m->sctp_ep.max_burst;
asoc->heart_beat_delay = TICKS_TO_MSEC(m->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]);
asoc->cookie_life = m->sctp_ep.def_cookie_life;
@@ -902,6 +902,7 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb,
if (sctp_is_vtag_good(m, override_tag, &now)) {
asoc->my_vtag = override_tag;
} else {
+ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOMEM);
return (ENOMEM);
}
@@ -1095,6 +1096,7 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb,
SCTP_M_STRMO);
if (asoc->strmout == NULL) {
/* big trouble no memory */
+ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOMEM);
return (ENOMEM);
}
for (i = 0; i < asoc->streamoutcnt; i++) {
@@ -1119,6 +1121,7 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb,
SCTP_M_MAP);
if (asoc->mapping_array == NULL) {
SCTP_FREE(asoc->strmout, SCTP_M_STRMO);
+ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOMEM);
return (ENOMEM);
}
memset(asoc->mapping_array, 0, asoc->mapping_array_size);
@@ -1219,8 +1222,6 @@ select_a_new_ep:
SCTP_INP_WLOCK(it->inp);
}
- /* mark the current iterator on the endpoint */
- it->inp->inp_starting_point_for_iterator = it;
SCTP_INP_WUNLOCK(it->inp);
SCTP_INP_RLOCK(it->inp);
@@ -1243,10 +1244,6 @@ select_a_new_ep:
SCTP_INP_RUNLOCK(it->inp);
goto no_stcb;
}
- if ((it->stcb) &&
- (it->stcb->asoc.stcb_starting_point_for_iterator == it)) {
- it->stcb->asoc.stcb_starting_point_for_iterator = NULL;
- }
while (it->stcb) {
SCTP_TCB_LOCK(it->stcb);
if (it->asoc_state && ((it->stcb->asoc.state & it->asoc_state) != it->asoc_state)) {
@@ -1254,18 +1251,20 @@ select_a_new_ep:
SCTP_TCB_UNLOCK(it->stcb);
goto next_assoc;
}
- /* mark the current iterator on the assoc */
- it->stcb->asoc.stcb_starting_point_for_iterator = it;
/* see if we have limited out the iterator loop */
iteration_count++;
if (iteration_count > SCTP_ITERATOR_MAX_AT_ONCE) {
/* Pause to let others grab the lock */
atomic_add_int(&it->stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(it->stcb);
+
+ SCTP_INP_INCR_REF(it->inp);
SCTP_INP_RUNLOCK(it->inp);
SCTP_ITERATOR_UNLOCK();
SCTP_ITERATOR_LOCK();
SCTP_INP_RLOCK(it->inp);
+
+ SCTP_INP_DECR_REF(it->inp);
SCTP_TCB_LOCK(it->stcb);
atomic_add_int(&it->stcb->asoc.refcnt, -1);
iteration_count = 0;
@@ -1297,7 +1296,6 @@ no_stcb:
/* done with all assocs on this endpoint, move on to next endpoint */
it->done_current_ep = 0;
SCTP_INP_WLOCK(it->inp);
- it->inp->inp_starting_point_for_iterator = NULL;
SCTP_INP_WUNLOCK(it->inp);
if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) {
it->inp = NULL;
@@ -1582,10 +1580,15 @@ sctp_timeout_handler(void *t)
case SCTP_TIMER_TYPE_RECV:
if ((stcb == NULL) || (inp == NULL)) {
break;
+ } {
+ int abort_flag;
+
+ SCTP_STAT_INCR(sctps_timosack);
+ stcb->asoc.timosack++;
+ if (stcb->asoc.cumulative_tsn != stcb->asoc.highest_tsn_inside_map)
+ sctp_sack_check(stcb, 0, 0, &abort_flag);
+ sctp_send_sack(stcb);
}
- SCTP_STAT_INCR(sctps_timosack);
- stcb->asoc.timosack++;
- sctp_send_sack(stcb);
#ifdef SCTP_AUDITING_ENABLED
sctp_auditing(4, inp, stcb, net);
#endif
@@ -1769,7 +1772,7 @@ sctp_timeout_handler(void *t)
/* Can we free it yet? */
SCTP_INP_DECR_REF(inp);
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);
+ (void)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
@@ -2176,7 +2179,7 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
tmr->tcb = (void *)stcb;
tmr->net = (void *)net;
tmr->self = (void *)tmr;
- tmr->ticks = ticks;
+ tmr->ticks = sctp_get_tick_count();
(void)SCTP_OS_TIMER_START(&tmr->timer, to_ticks, sctp_timeout_handler, tmr);
return;
}
@@ -2767,6 +2770,7 @@ sctp_add_pad_tombuf(struct mbuf *m, int padlen)
int i;
if (padlen > 3) {
+ SCTP_LTRACE_ERR_RET_PKT(m, NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS);
return (ENOBUFS);
}
if (M_TRAILINGSPACE(m)) {
@@ -2783,6 +2787,7 @@ sctp_add_pad_tombuf(struct mbuf *m, int padlen)
tmp = sctp_get_mbuf_for_msg(padlen, 0, M_DONTWAIT, 1, MT_DATA);
if (tmp == NULL) {
/* Out of space GAK! we are in big trouble. */
+ SCTP_LTRACE_ERR_RET_PKT(m, NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
return (ENOSPC);
}
/* setup and insert in middle */
@@ -2816,6 +2821,7 @@ sctp_pad_lastmbuf(struct mbuf *m, int padval, struct mbuf *last_mbuf)
m_at = SCTP_BUF_NEXT(m_at);
}
}
+ SCTP_LTRACE_ERR_RET_PKT(m, NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, EFAULT);
return (EFAULT);
}
@@ -2849,10 +2855,13 @@ sctp_notify_assoc_change(uint32_t event, struct sctp_tcb *stcb,
if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
((event == SCTP_COMM_LOST) || (event == SCTP_CANT_STR_ASSOC))) {
- if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT)
+ if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) {
+ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ECONNREFUSED);
stcb->sctp_socket->so_error = ECONNREFUSED;
- else
+ } else {
+ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ECONNRESET);
stcb->sctp_socket->so_error = ECONNRESET;
+ }
/* Wake ANY sleepers */
sorwakeup(stcb->sctp_socket);
sowwakeup(stcb->sctp_socket);
@@ -3658,7 +3667,7 @@ sctp_abort_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
sctp_send_abort(m, iphlen, sh, vtag, op_err, vrf_id);
if (stcb != NULL) {
/* Ok, now lets free it */
- sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL + SCTP_LOC_4);
+ (void)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) {
@@ -3766,7 +3775,7 @@ sctp_abort_an_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
#ifdef SCTP_ASOCLOG_OF_TSNS
sctp_print_out_track_log(stcb);
#endif
- sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL + SCTP_LOC_5);
+ (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL + SCTP_LOC_5);
}
void
@@ -4687,6 +4696,7 @@ sctp_sorecvmsg(struct socket *so,
int sockbuf_lock = 0;
if (uio == NULL) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
return (EINVAL);
}
if (msg_flags) {
@@ -4704,6 +4714,7 @@ sctp_sorecvmsg(struct socket *so,
return (EOPNOTSUPP);
}
if ((in_flags & MSG_PEEK) && (mp != NULL)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
return (EINVAL);
}
if ((in_flags & (MSG_DONTWAIT
@@ -4715,6 +4726,7 @@ sctp_sorecvmsg(struct socket *so,
/* setup the endpoint */
inp = (struct sctp_inpcb *)so->so_pcb;
if (inp == NULL) {
+ SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, EFAULT);
return (EFAULT);
}
rwnd_req = (SCTP_SB_LIMIT_RCV(so) >> SCTP_RWND_HIWAT_SHIFT);
@@ -4753,6 +4765,7 @@ restart_nosblocks:
if ((in_flags & MSG_PEEK) == 0)
so->so_error = 0;
} else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOTCONN);
error = ENOTCONN;
}
goto out;
@@ -4773,6 +4786,7 @@ restart_nosblocks:
* You were aborted, passive side
* always hits here
*/
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ECONNRESET);
error = ECONNRESET;
/*
* You get this once if you are
@@ -4792,6 +4806,7 @@ restart_nosblocks:
SS_ISCONNECTED);
if (error == 0) {
if ((inp->sctp_flags & SCTP_PCB_FLAGS_WAS_CONNECTED) == 0) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOTCONN);
error = ENOTCONN;
} else {
inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAS_CONNECTED;
@@ -4825,6 +4840,7 @@ restart_nosblocks:
* You were aborted, passive
* side always hits here
*/
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ECONNRESET);
error = ECONNRESET;
/*
* You get this once if you
@@ -4845,6 +4861,7 @@ restart_nosblocks:
SS_ISCONNECTED);
if (error == 0) {
if ((inp->sctp_flags & SCTP_PCB_FLAGS_WAS_CONNECTED) == 0) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOTCONN);
error = ENOTCONN;
} else {
inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAS_CONNECTED;
@@ -4853,6 +4870,7 @@ restart_nosblocks:
goto out;
}
}
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EWOULDBLOCK);
error = EWOULDBLOCK;
}
goto out;
@@ -5216,6 +5234,7 @@ get_more_data:
embuf = m;
copied_so_far += cp_len;
freed_so_far += cp_len;
+ freed_so_far += MSIZE;
atomic_subtract_int(&control->length, cp_len);
control->data = sctp_m_free(m);
m = control->data;
@@ -5266,6 +5285,7 @@ get_more_data:
copied_so_far += cp_len;
embuf = m;
freed_so_far += cp_len;
+ freed_so_far += MSIZE;
if (sctp_logging_level & SCTP_SB_LOGGING_ENABLE) {
sctp_sblog(&so->so_rcv, control->do_not_ref_stcb ? NULL : stcb,
SCTP_LOG_SBRESULT, 0);
@@ -5483,6 +5503,7 @@ wait_some_more:
}
sctp_sbfree(control, stcb, &so->so_rcv, m);
freed_so_far += SCTP_BUF_LEN(m);
+ freed_so_far += MSIZE;
if (sctp_logging_level & SCTP_SB_LOGGING_ENABLE) {
sctp_sblog(&so->so_rcv,
control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBRESULT, 0);
@@ -5612,6 +5633,7 @@ sctp_dynamic_set_primary(struct sockaddr *sa, uint32_t vrf_id)
ifa = sctp_find_ifa_by_addr(sa, vrf_id, 0);
if (ifa == NULL) {
+ SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, EADDRNOTAVAIL);
return (EADDRNOTAVAIL);
}
/*
@@ -5620,6 +5642,7 @@ sctp_dynamic_set_primary(struct sockaddr *sa, uint32_t vrf_id)
*/
wi = SCTP_ZONE_GET(sctppcbinfo.ipi_zone_laddr, struct sctp_laddr);
if (wi == NULL) {
+ SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOMEM);
return (ENOMEM);
}
/* Now incr the count and int wi structure */
@@ -5666,6 +5689,7 @@ sctp_soreceive(struct socket *so,
inp = (struct sctp_inpcb *)so->so_pcb;
/* pickup the assoc we are reading from */
if (inp == NULL) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
return (EINVAL);
}
if ((sctp_is_feature_off(inp,
@@ -5723,6 +5747,7 @@ sctp_l_soreceive(struct socket *so,
inp = (struct sctp_inpcb *)so->so_pcb;
/* pickup the assoc we are reading from */
if (inp == NULL) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
return (EINVAL);
}
if ((sctp_is_feature_off(inp,
@@ -5790,7 +5815,8 @@ sctp_connectx_helper_add(struct sctp_tcb *stcb, struct sockaddr *addr,
incr = sizeof(struct sockaddr_in);
if (sctp_add_remote_addr(stcb, sa, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
/* assoc gone no un-lock */
- sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_7);
+ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS);
+ (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_7);
*error = ENOBUFS;
goto out_now;
}
@@ -5799,7 +5825,8 @@ sctp_connectx_helper_add(struct sctp_tcb *stcb, struct sockaddr *addr,
incr = sizeof(struct sockaddr_in6);
if (sctp_add_remote_addr(stcb, sa, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
/* assoc gone no un-lock */
- sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_8);
+ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS);
+ (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_8);
*error = ENOBUFS;
goto out_now;
}
@@ -5829,6 +5856,7 @@ sctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr,
(*num_v4) += 1;
incr = sizeof(struct sockaddr_in);
if (sa->sa_len != incr) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
*error = EINVAL;
*bad_addr = 1;
return (NULL);
@@ -5839,6 +5867,7 @@ sctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr,
sin6 = (struct sockaddr_in6 *)sa;
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
/* Must be non-mapped for connectx */
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
*error = EINVAL;
*bad_addr = 1;
return (NULL);
@@ -5846,6 +5875,7 @@ sctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr,
(*num_v6) += 1;
incr = sizeof(struct sockaddr_in6);
if (sa->sa_len != incr) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
*error = EINVAL;
*bad_addr = 1;
return (NULL);
@@ -5886,6 +5916,7 @@ sctp_bindx_add_address(struct socket *so, struct sctp_inpcb *inp,
/* see if we're bound all already! */
if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
*error = EINVAL;
return;
}
@@ -5895,11 +5926,13 @@ sctp_bindx_add_address(struct socket *so, struct sctp_inpcb *inp,
struct sockaddr_in6 *sin6;
if (sa->sa_len != sizeof(struct sockaddr_in6)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
*error = EINVAL;
return;
}
if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
/* can only bind v6 on PF_INET6 sockets */
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
*error = EINVAL;
return;
}
@@ -5908,6 +5941,7 @@ sctp_bindx_add_address(struct socket *so, struct sctp_inpcb *inp,
if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
SCTP_IPV6_V6ONLY(inp)) {
/* can't bind v4-mapped on PF_INET sockets */
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
*error = EINVAL;
return;
}
@@ -5918,12 +5952,14 @@ sctp_bindx_add_address(struct socket *so, struct sctp_inpcb *inp,
#endif
if (sa->sa_family == AF_INET) {
if (sa->sa_len != sizeof(struct sockaddr_in)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
*error = EINVAL;
return;
}
if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
SCTP_IPV6_V6ONLY(inp)) {
/* can't bind v4 on PF_INET sockets */
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
*error = EINVAL;
return;
}
@@ -5931,6 +5967,7 @@ sctp_bindx_add_address(struct socket *so, struct sctp_inpcb *inp,
if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
if (p == NULL) {
/* Can't get proc for Net/Open BSD */
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
*error = EINVAL;
return;
}
@@ -5950,6 +5987,7 @@ sctp_bindx_add_address(struct socket *so, struct sctp_inpcb *inp,
/* validate the incoming port */
if ((lsin->sin_port != 0) &&
(lsin->sin_port != inp->sctp_lport)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
*error = EINVAL;
return;
} else {
@@ -6000,6 +6038,7 @@ sctp_bindx_delete_address(struct socket *so, struct sctp_inpcb *inp,
/* see if we're bound all already! */
if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
*error = EINVAL;
return;
}
@@ -6009,11 +6048,13 @@ sctp_bindx_delete_address(struct socket *so, struct sctp_inpcb *inp,
struct sockaddr_in6 *sin6;
if (sa->sa_len != sizeof(struct sockaddr_in6)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
*error = EINVAL;
return;
}
if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
/* can only bind v6 on PF_INET6 sockets */
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
*error = EINVAL;
return;
}
@@ -6022,6 +6063,7 @@ sctp_bindx_delete_address(struct socket *so, struct sctp_inpcb *inp,
if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
SCTP_IPV6_V6ONLY(inp)) {
/* can't bind mapped-v4 on PF_INET sockets */
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
*error = EINVAL;
return;
}
@@ -6032,12 +6074,14 @@ sctp_bindx_delete_address(struct socket *so, struct sctp_inpcb *inp,
#endif
if (sa->sa_family == AF_INET) {
if (sa->sa_len != sizeof(struct sockaddr_in)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
*error = EINVAL;
return;
}
if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
SCTP_IPV6_V6ONLY(inp)) {
/* can't bind v4 on PF_INET sockets */
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
*error = EINVAL;
return;
}
@@ -6168,3 +6212,43 @@ sctp_local_addr_count(struct sctp_tcb *stcb)
}
return (count);
}
+
+#if defined(SCTP_LOCAL_TRACE_BUF)
+
+struct sctp_dump_log {
+ u_int64_t timestamp;
+ const char *descr;
+ uint32_t subsys;
+ uint32_t params[SCTP_TRACE_PARAMS];
+};
+int sctp_log_index = 0;
+struct sctp_dump_log sctp_log[SCTP_MAX_LOGGING_SIZE];
+
+void
+sctp_log_trace(uint32_t subsys, const char *str, uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t e, uint32_t f)
+{
+ int saveindex, newindex;
+
+ do {
+ saveindex = sctp_log_index;
+ if (saveindex >= SCTP_MAX_LOGGING_SIZE) {
+ newindex = 1;
+ } else {
+ newindex = saveindex + 1;
+ }
+ } while (atomic_cmpset_int(&sctp_log_index, saveindex, newindex) == 0);
+ if (saveindex >= SCTP_MAX_LOGGING_SIZE) {
+ saveindex = 0;
+ }
+ sctp_log[saveindex].timestamp = SCTP_GET_CYCLECOUNT;
+ sctp_log[saveindex].subsys = subsys;
+ sctp_log[saveindex].descr = str;
+ sctp_log[saveindex].params[0] = a;
+ sctp_log[saveindex].params[1] = b;
+ sctp_log[saveindex].params[2] = c;
+ sctp_log[saveindex].params[3] = d;
+ sctp_log[saveindex].params[4] = e;
+ sctp_log[saveindex].params[5] = f;
+}
+
+#endif
diff --git a/sys/netinet/sctputil.h b/sys/netinet/sctputil.h
index 46d63d8..b1f5542 100644
--- a/sys/netinet/sctputil.h
+++ b/sys/netinet/sctputil.h
@@ -54,6 +54,11 @@ void sctp_m_freem(struct mbuf *m);
#define sctp_m_freem m_freem
#endif
+#if defined(SCTP_LOCAL_TRACE_BUF) || defined(__APPLE__)
+void
+ sctp_log_trace(uint32_t fr, const char *str, uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t e, uint32_t f);
+
+#endif
#define sctp_get_associd(stcb) ((sctp_assoc_t)stcb->asoc.assoc_id)
diff --git a/sys/netinet6/sctp6_usrreq.c b/sys/netinet6/sctp6_usrreq.c
index 6517b48..d2ee49c 100644
--- a/sys/netinet6/sctp6_usrreq.c
+++ b/sys/netinet6/sctp6_usrreq.c
@@ -440,10 +440,14 @@ sctp6_getcred(SYSCTL_HANDLER_ARGS)
if (error)
return (error);
- if (req->newlen != sizeof(addrs))
+ if (req->newlen != sizeof(addrs)) {
+ SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return (EINVAL);
- if (req->oldlen != sizeof(struct ucred))
+ }
+ if (req->oldlen != sizeof(struct ucred)) {
+ SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return (EINVAL);
+ }
error = SYSCTL_IN(req, addrs, sizeof(addrs));
if (error)
return (error);
@@ -458,6 +462,7 @@ sctp6_getcred(SYSCTL_HANDLER_ARGS)
SCTP_INP_DECR_REF(inp);
goto cred_can_cont;
}
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOENT);
error = ENOENT;
goto out;
}
@@ -537,9 +542,10 @@ sctp6_attach(struct socket *so, int proto, struct thread *p)
uint32_t vrf_id = SCTP_DEFAULT_VRFID;
inp = (struct sctp_inpcb *)so->so_pcb;
- if (inp != NULL)
+ if (inp != NULL) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return EINVAL;
-
+ }
if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
error = SCTP_SORESERVE(so, sctp_sendspace, sctp_recvspace);
if (error)
@@ -580,16 +586,19 @@ sctp6_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
int error;
inp = (struct sctp_inpcb *)so->so_pcb;
- if (inp == 0)
+ if (inp == 0) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return EINVAL;
-
+ }
if (addr) {
if ((addr->sa_family == AF_INET6) &&
(addr->sa_len != sizeof(struct sockaddr_in6))) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return EINVAL;
}
if ((addr->sa_family == AF_INET) &&
(addr->sa_len != sizeof(struct sockaddr_in))) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return EINVAL;
}
}
@@ -622,6 +631,7 @@ sctp6_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
/* IPV6_V6ONLY socket */
if (addr->sa_family == AF_INET) {
/* can't bind v4 addr to v6 only socket! */
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return EINVAL;
} else {
struct sockaddr_in6 *sin6_p;
@@ -631,7 +641,8 @@ sctp6_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr))
/* can't bind v4-mapped addrs either! */
/* NOTE: we don't support SIIT */
- return EINVAL;
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
+ return EINVAL;
}
}
error = sctp_inpcb_bind(so, addr, NULL, p);
@@ -707,6 +718,7 @@ sctp6_disconnect(struct socket *so)
inp = (struct sctp_inpcb *)so->so_pcb;
if (inp == NULL) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOTCONN);
return (ENOTCONN);
}
SCTP_INP_RLOCK(inp);
@@ -714,6 +726,7 @@ sctp6_disconnect(struct socket *so)
if (SCTP_LIST_EMPTY(&inp->sctp_asoc_list)) {
/* No connection */
SCTP_INP_RUNLOCK(inp);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOTCONN);
return (ENOTCONN);
} else {
int some_on_streamwheel = 0;
@@ -723,6 +736,7 @@ sctp6_disconnect(struct socket *so)
stcb = LIST_FIRST(&inp->sctp_asoc_list);
if (stcb == NULL) {
SCTP_INP_RUNLOCK(inp);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return (EINVAL);
}
SCTP_TCB_LOCK(stcb);
@@ -744,8 +758,10 @@ 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, SCTP_DONOT_SETSCOPE,
- SCTP_FROM_SCTP6_USRREQ + SCTP_LOC_2);
+ if (sctp_free_assoc(inp, stcb, SCTP_DONOT_SETSCOPE,
+ SCTP_FROM_SCTP6_USRREQ + SCTP_LOC_2) == 0) {
+ SCTP_TCB_UNLOCK(stcb);
+ }
/* No unlock tcb assoc is gone */
return (0);
}
@@ -776,7 +792,7 @@ sctp6_disconnect(struct socket *so)
(SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
- asoc->state = SCTP_STATE_SHUTDOWN_SENT;
+ SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
stcb->sctp_ep, stcb,
asoc->primary_destination);
@@ -804,6 +820,7 @@ sctp6_disconnect(struct socket *so)
} else {
/* UDP model does not support this */
SCTP_INP_RUNLOCK(inp);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EOPNOTSUPP);
return EOPNOTSUPP;
}
}
@@ -835,6 +852,7 @@ sctp6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
control = NULL;
}
SCTP_RELEASE_PKT(m);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return EINVAL;
}
in_inp = (struct inpcb *)inp;
@@ -853,6 +871,7 @@ sctp6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
SCTP_RELEASE_PKT(control);
control = NULL;
}
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EDESTADDRREQ);
return (EDESTADDRREQ);
}
#ifdef INET
@@ -863,9 +882,11 @@ sctp6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
* v4 addr or v4-mapped addr
*/
if (addr->sa_family == AF_INET) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return EINVAL;
}
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return EINVAL;
}
}
@@ -879,6 +900,7 @@ sctp6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
control, p);
} else {
/* mapped addresses aren't enabled */
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return EINVAL;
}
}
@@ -940,16 +962,20 @@ sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
inp6 = (struct in6pcb *)so->so_pcb;
inp = (struct sctp_inpcb *)so->so_pcb;
if (inp == 0) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ECONNRESET);
return (ECONNRESET); /* I made the same as TCP since we are
* not setup? */
}
if (addr == NULL) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return (EINVAL);
}
if ((addr->sa_family == AF_INET6) && (addr->sa_len != sizeof(struct sockaddr_in6))) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return (EINVAL);
}
if ((addr->sa_family == AF_INET) && (addr->sa_len != sizeof(struct sockaddr_in))) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return (EINVAL);
}
vrf_id = inp->def_vrf_id;
@@ -972,6 +998,7 @@ sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
/* We are already connected AND the TCP model */
SCTP_INP_RUNLOCK(inp);
SCTP_ASOC_CREATE_UNLOCK(inp);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EADDRINUSE);
return (EADDRINUSE);
}
#ifdef INET
@@ -984,11 +1011,13 @@ sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
if (addr->sa_family == AF_INET) {
SCTP_INP_RUNLOCK(inp);
SCTP_ASOC_CREATE_UNLOCK(inp);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return EINVAL;
}
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
SCTP_INP_RUNLOCK(inp);
SCTP_ASOC_CREATE_UNLOCK(inp);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return EINVAL;
}
}
@@ -1001,6 +1030,7 @@ sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
/* mapped addresses aren't enabled */
SCTP_INP_RUNLOCK(inp);
SCTP_ASOC_CREATE_UNLOCK(inp);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return EINVAL;
}
} else
@@ -1031,6 +1061,7 @@ sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
/* Already have or am bring up an association */
SCTP_ASOC_CREATE_UNLOCK(inp);
SCTP_TCB_UNLOCK(stcb);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EALREADY);
return (EALREADY);
}
/* We are GOOD to go */
@@ -1076,6 +1107,7 @@ sctp6_getaddr(struct socket *so, struct sockaddr **addr)
inp = (struct sctp_inpcb *)so->so_pcb;
if (inp == NULL) {
SCTP_FREE_SONAME(sin6);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ECONNRESET);
return ECONNRESET;
}
SCTP_INP_RLOCK(inp);
@@ -1137,6 +1169,7 @@ sctp6_getaddr(struct socket *so, struct sockaddr **addr)
if (!fnd) {
SCTP_FREE_SONAME(sin6);
SCTP_INP_RUNLOCK(inp);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOENT);
return ENOENT;
}
}
@@ -1168,6 +1201,7 @@ sctp6_peeraddr(struct socket *so, struct sockaddr **addr)
inp = (struct sctp_inpcb *)so->so_pcb;
if ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0) {
/* UDP type and listeners will drop out here */
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOTCONN);
return (ENOTCONN);
}
SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
@@ -1178,6 +1212,7 @@ sctp6_peeraddr(struct socket *so, struct sockaddr **addr)
inp = (struct sctp_inpcb *)so->so_pcb;
if (inp == NULL) {
SCTP_FREE_SONAME(sin6);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ECONNRESET);
return ECONNRESET;
}
SCTP_INP_RLOCK(inp);
@@ -1188,6 +1223,7 @@ sctp6_peeraddr(struct socket *so, struct sockaddr **addr)
SCTP_INP_RUNLOCK(inp);
if (stcb == NULL) {
SCTP_FREE_SONAME(sin6);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ECONNRESET);
return ECONNRESET;
}
fnd = 0;
@@ -1204,6 +1240,7 @@ sctp6_peeraddr(struct socket *so, struct sockaddr **addr)
if (!fnd) {
/* No IPv4 address */
SCTP_FREE_SONAME(sin6);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOENT);
return ENOENT;
}
if ((error = sa6_recoverscope(sin6)) != 0)
@@ -1219,9 +1256,10 @@ sctp6_in6getaddr(struct socket *so, struct sockaddr **nam)
struct in6pcb *inp6 = sotoin6pcb(so);
int error;
- if (inp6 == NULL)
+ if (inp6 == NULL) {
+ SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return EINVAL;
-
+ }
/* allow v6 addresses precedence */
error = sctp6_getaddr(so, nam);
if (error) {
@@ -1251,9 +1289,10 @@ sctp6_getpeeraddr(struct socket *so, struct sockaddr **nam)
struct in6pcb *inp6 = sotoin6pcb(so);
int error;
- if (inp6 == NULL)
+ if (inp6 == NULL) {
+ SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return EINVAL;
-
+ }
/* allow v6 addresses precedence */
error = sctp6_peeraddr(so, nam);
if (error) {
diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h
index bff95b5..bf7c073 100644
--- a/sys/sys/mbuf.h
+++ b/sys/sys/mbuf.h
@@ -178,7 +178,7 @@ struct mbuf {
#define M_PROTO3 0x0040 /* protocol-specific */
#define M_PROTO4 0x0080 /* protocol-specific */
#define M_PROTO5 0x0100 /* protocol-specific */
-#define M_NOTIFICATION 0x2000 /* SCTP notification */
+#define M_NOTIFICATION M_PROTO5/* SCTP notification */
#define M_SKIP_FIREWALL 0x4000 /* skip firewall processing */
#define M_FREELIST 0x8000 /* mbuf is on the free list */
OpenPOWER on IntegriCloud