summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrrs <rrs@FreeBSD.org>2007-04-03 11:15:32 +0000
committerrrs <rrs@FreeBSD.org>2007-04-03 11:15:32 +0000
commitad3d5670174784e5b920754b5b0f8f9902669d09 (patch)
treea29f21245853449d39286dd5084db358d0ca42a9
parentc277843c2225aefe5e5c60e49de3fc0f95f7a798 (diff)
downloadFreeBSD-src-ad3d5670174784e5b920754b5b0f8f9902669d09.zip
FreeBSD-src-ad3d5670174784e5b920754b5b0f8f9902669d09.tar.gz
- fixed several places where we did not release INP locks.
- fixed a refcount bug in the new ifa structures. - use vrf's from default stcb or inp whenever possible. - Address limits raised to account for a full IP fragmented packet (1000 addresses). - flight size correcting updated to include one message only and to handle case where the peer does not cumack the next segment aka lists 1/1 in sack blocks.. - Various bad init/init-ack handling could cause a panic since we tried to unlock the destroyed mutex. Fixes so we properly exit when we need to destroy an assoc. (Found by Cisco DevTest team :D) - name rename in src-addr-selection from pass to sifa. - route structure typedef'd to allow different platforms and updated into sctp_os_bsd file. - Max retransmissions a chunk can be made added. Reviewed by: gnn
-rw-r--r--sys/netinet/sctp_asconf.c34
-rw-r--r--sys/netinet/sctp_bsd_addr.h9
-rw-r--r--sys/netinet/sctp_constants.h20
-rw-r--r--sys/netinet/sctp_indata.c106
-rw-r--r--sys/netinet/sctp_input.c60
-rw-r--r--sys/netinet/sctp_os_bsd.h8
-rw-r--r--sys/netinet/sctp_output.c188
-rw-r--r--sys/netinet/sctp_output.h2
-rw-r--r--sys/netinet/sctp_pcb.c49
-rw-r--r--sys/netinet/sctp_pcb.h5
-rw-r--r--sys/netinet/sctp_sysctl.c22
-rw-r--r--sys/netinet/sctp_sysctl.h17
-rw-r--r--sys/netinet/sctp_timer.c2
-rw-r--r--sys/netinet/sctp_uio.h1
-rw-r--r--sys/netinet/sctp_usrreq.c29
-rw-r--r--sys/netinet/sctputil.c30
-rw-r--r--sys/netinet6/sctp6_usrreq.c26
17 files changed, 387 insertions, 221 deletions
diff --git a/sys/netinet/sctp_asconf.c b/sys/netinet/sctp_asconf.c
index d4f088b..5eaa7cd 100644
--- a/sys/netinet/sctp_asconf.c
+++ b/sys/netinet/sctp_asconf.c
@@ -39,7 +39,6 @@ __FBSDID("$FreeBSD$");
#include <netinet/sctp_header.h>
#include <netinet/sctputil.h>
#include <netinet/sctp_output.h>
-#include <netinet/sctp_bsd_addr.h>
#include <netinet/sctp_asconf.h>
/*
@@ -1054,6 +1053,7 @@ sctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa, uint16_t type
/* take the entry off the appropriate list */
sctp_asconf_addr_mgmt_ack(stcb, aa->ifa, type, 1);
/* free the entry */
+ sctp_free_ifa(aa->ifa);
SCTP_FREE(aa);
return (-1);
}
@@ -1074,6 +1074,7 @@ sctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa, uint16_t type
/* top level elements are "networked" during send */
aa->ap.aph.ph.param_type = type;
aa->ifa = ifa;
+ atomic_add_int(&ifa->refcount, 1);
/* correlation_id filled in during send routine later... */
if (ifa->address.sa.sa_family == AF_INET6) {
/* IPv6 address */
@@ -1150,6 +1151,7 @@ static uint32_t
sctp_asconf_queue_add_sa(struct sctp_tcb *stcb, struct sockaddr *sa,
uint16_t type)
{
+ struct sctp_ifa *ifa;
struct sctp_asconf_addr *aa, *aa_next;
uint32_t vrf_id;
@@ -1178,6 +1180,7 @@ sctp_asconf_queue_add_sa(struct sctp_tcb *stcb, struct sockaddr *sa,
/* delete the existing entry in the queue */
TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next);
/* free the entry */
+ sctp_free_ifa(aa->ifa);
SCTP_FREE(aa);
return (-1);
} else if (type == SCTP_DEL_IP_ADDRESS &&
@@ -1189,11 +1192,22 @@ sctp_asconf_queue_add_sa(struct sctp_tcb *stcb, struct sockaddr *sa,
/* take the entry off the appropriate list */
sctp_asconf_addr_mgmt_ack(stcb, aa->ifa, type, 1);
/* free the entry */
+ sctp_free_ifa(aa->ifa);
SCTP_FREE(aa);
return (-1);
}
} /* for each aa */
+ if (stcb) {
+ vrf_id = stcb->asoc.vrf_id;
+ } else {
+ vrf_id = SCTP_DEFAULT_VRFID;
+ }
+ ifa = sctp_find_ifa_by_addr(sa, vrf_id, 0);
+ if (ifa == NULL) {
+ /* Invalid address */
+ return (-1);
+ }
/* adding new request to the queue */
SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa), "AsconfAddr");
if (aa == NULL) {
@@ -1207,9 +1221,9 @@ sctp_asconf_queue_add_sa(struct sctp_tcb *stcb, struct sockaddr *sa,
}
/* fill in asconf address parameter fields */
/* top level elements are "networked" during send */
- vrf_id = SCTP_DEFAULT_VRFID;
aa->ap.aph.ph.param_type = type;
- aa->ifa = sctp_find_ifa_by_addr(sa, vrf_id, 0);
+ aa->ifa = ifa;
+ atomic_add_int(&ifa->refcount, 1);
/* correlation_id filled in during send routine later... */
if (sa->sa_family == AF_INET6) {
/* IPv6 address */
@@ -1372,6 +1386,7 @@ sctp_asconf_process_param_ack(struct sctp_tcb *stcb,
/* remove the param and free it */
TAILQ_REMOVE(&stcb->asoc.asconf_queue, aparam, next);
+ sctp_free_ifa(aparam->ifa);
SCTP_FREE(aparam);
}
@@ -2413,7 +2428,12 @@ sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m,
}
/* see if this address really (still) exists */
- vrf_id = SCTP_DEFAULT_VRFID;
+ if (stcb) {
+ vrf_id = stcb->asoc.vrf_id;
+ } else {
+ vrf_id = SCTP_DEFAULT_VRFID;
+ }
+
sctp_ifa = sctp_find_ifa_by_addr(sa, vrf_id, 0);
if (sctp_ifa == NULL) {
/* address doesn't exist anymore */
@@ -2626,7 +2646,11 @@ sctp_check_address_list_all(struct sctp_tcb *stcb, struct mbuf *m, int offset,
struct sctp_ifa *sctp_ifa;
uint32_t vrf_id;
- vrf_id = SCTP_DEFAULT_VRFID;
+ if (stcb) {
+ vrf_id = stcb->asoc.vrf_id;
+ } else {
+ vrf_id = SCTP_DEFAULT_VRFID;
+ }
vrf = sctp_find_vrf(vrf_id);
if (vrf == NULL) {
return;
diff --git a/sys/netinet/sctp_bsd_addr.h b/sys/netinet/sctp_bsd_addr.h
index 0752ea3..5a4216f 100644
--- a/sys/netinet/sctp_bsd_addr.h
+++ b/sys/netinet/sctp_bsd_addr.h
@@ -33,8 +33,7 @@ __FBSDID("$FreeBSD$");
#ifndef __sctp_bsd_addr_h__
#define __sctp_bsd_addr_h__
-
-#include <netinet/sctp_header.h>
+#include <netinet/sctp_pcb.h>
#if defined(_KERNEL)
@@ -45,11 +44,9 @@ void sctp_startup_iterator(void);
#endif
-void
- sctp_gather_internal_ifa_flags(struct sctp_ifa *ifa);
-
+void sctp_gather_internal_ifa_flags(struct sctp_ifa *ifa);
-extern void sctp_addr_change(struct ifaddr *ifa, int cmd);
+void sctp_addr_change(struct ifaddr *ifa, int cmd);
#endif
#endif
diff --git a/sys/netinet/sctp_constants.h b/sys/netinet/sctp_constants.h
index 97b8c87..9cd5432 100644
--- a/sys/netinet/sctp_constants.h
+++ b/sys/netinet/sctp_constants.h
@@ -40,26 +40,22 @@ __FBSDID("$FreeBSD$");
#define SCTP_DEFAULT_SACK_FREQ 2
/* Address limit - This variable is calculated
- * based on an 1500 byte mtu. We take out 100 bytes
+ * based on an 65535 byte max ip packet. We take out 100 bytes
* for the cookie, 40 bytes for a v6 header and 32
* bytes for the init structure. A second init structure
* for the init-ack and then finally a third one for the
* imbedded init. This yeilds 100+40+(3 * 32) = 236 bytes.
- * This leaves 1264 bytes for addresses. Now whatever we
- * send in the INIT() we need to allow to get back in the
+ * This leaves 65299 bytes for addresses. We throw out the 299 bytes.
+ * Now whatever we send in the INIT() we need to allow to get back in the
* INIT-ACK plus all the values from INIT and INIT-ACK
* listed in the cookie. Plus we need some overhead for
* maybe copied parameters in the COOKIE. If we
- * allow 20 addresses, and each side has 20 V6 addresses
- * that will be 400 bytes. In the INIT-ACK we will
- * see the INIT-ACK 400 + 800 in the cookie. This leaves
- * 64 bytes slack for misc things in the cookie. Otherwise
- * we need to allow IP fragmentation.. which I believe
- * the INIT-ACK and COOKIE do, I don't think we do that
- * to the INIT though. So the max you could make this
- * value is 60 addresses.
+ * allow 1080 addresses, and each side has 1080 V6 addresses
+ * that will be 21600 bytes. In the INIT-ACK we will
+ * see the INIT-ACK 21600 + 43200 in the cookie. This leaves
+ * about 500 bytes slack for misc things in the cookie.
*/
-#define SCTP_ADDRESS_LIMIT 20
+#define SCTP_ADDRESS_LIMIT 1080
/* Number of addresses where we just skip the counting */
#define SCTP_COUNT_LIMIT 40
diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c
index 462013e..4d142f7 100644
--- a/sys/netinet/sctp_indata.c
+++ b/sys/netinet/sctp_indata.c
@@ -4071,6 +4071,63 @@ skip_cwnd_update:
}
}
+static int sctp_anal_print = 0;
+
+static void
+sctp_print_fs_audit(struct sctp_association *asoc)
+{
+ int cnt, i;
+ struct sctp_tmit_chunk *chk;
+ int inflight = 0, resend = 0, inbetween = 0, acked = 0, above = 0;
+
+ printf("sdqc:%d stqc:%d retran:%d reasm:%d cnt:%d tot_flight:%d tfc:%d\n",
+ (int)asoc->send_queue_cnt,
+ (int)asoc->sent_queue_cnt,
+ (int)asoc->sent_queue_retran_cnt,
+ (int)asoc->size_on_reasm_queue,
+ (int)asoc->cnt_on_reasm_queue,
+ (int)asoc->total_flight,
+ (int)asoc->total_flight_count);
+ printf("my_rwnd:%d peers_rwnd:%d asoc calc cumack:%x\n",
+ (int)asoc->my_rwnd, (int)asoc->peers_rwnd, asoc->last_acked_seq);
+ for (i = 0; i < asoc->streamoutcnt; i++) {
+ struct sctp_stream_queue_pending *sp;
+
+ cnt = 0;
+ TAILQ_FOREACH(sp, &asoc->strmout[i].outqueue, next)
+ cnt++;
+ if (cnt) {
+ printf("Stream %d has %d msgs yet to be sent in strm queue\n", i, cnt);
+ }
+ }
+ cnt = 0;
+ TAILQ_FOREACH(chk, &asoc->control_send_queue, sctp_next) {
+ cnt++;
+ }
+ printf("The control_send_queue has %d pending\n", cnt);
+ cnt = 0;
+ TAILQ_FOREACH(chk, &asoc->send_queue, sctp_next) {
+ cnt++;
+ }
+ printf("The send_queue (waiting to get in flight) has %d chunks pending\n", cnt);
+ TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) {
+ if (chk->sent < SCTP_DATAGRAM_RESEND) {
+ inflight++;
+ } else if (chk->sent == SCTP_DATAGRAM_RESEND) {
+ resend++;
+ } else if (chk->sent < SCTP_DATAGRAM_ACKED) {
+ inbetween++;
+ } else if (chk->sent > SCTP_DATAGRAM_ACKED) {
+ above++;
+ } else {
+ acked++;
+ printf("chk->sent:%x chk->tsn:%x\n",
+ chk->sent, chk->rec.data.TSN_seq);
+ }
+ }
+ printf("The sent_queue stats inflight:%d resend:%d acked:%d above:%d inbetween:%d\n",
+ inflight, resend, acked, above, inbetween);
+}
void
sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
@@ -4081,7 +4138,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
struct sctp_tmit_chunk *tp1, *tp2;
uint32_t old_rwnd;
int win_probe_recovery = 0;
- int j;
+ int j, done_once;;
SCTP_TCB_LOCK_ASSERT(stcb);
asoc = &stcb->asoc;
@@ -4351,6 +4408,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
win_probe_recovery = 1;
}
/* Now assure a timer where data is queued at */
+ done_once = 0;
again:
j = 0;
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
@@ -4402,12 +4460,15 @@ again:
}
}
}
- if ((j == 0) && (!TAILQ_EMPTY(&asoc->sent_queue)) && (asoc->sent_queue_retran_cnt == 0)) {
+ if ((j == 0) &&
+ (!TAILQ_EMPTY(&asoc->sent_queue)) &&
+ (asoc->sent_queue_retran_cnt == 0) &&
+ (done_once == 0)) {
/* huh, this should not happen */
-#ifdef INVARIANTS
- panic("Flight size incorrect? fixing??");
-#else
- printf("Flight size incorrect? fixing\n");
+ if (sctp_anal_print == 0) {
+ printf("Flight size-express incorrect? cumack:%x\n", cumack);
+ sctp_print_fs_audit(asoc);
+ }
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
net->flight_size = 0;
}
@@ -4423,7 +4484,12 @@ again:
asoc->sent_queue_retran_cnt++;
}
}
-#endif
+ if (sctp_anal_print == 0) {
+ printf("After audit, totalflight:%d, retran_cnt:%d\n",
+ asoc->total_flight, asoc->sent_queue_retran_cnt);
+ sctp_anal_print = 1;
+ }
+ done_once = 1;
goto again;
}
/**********************************/
@@ -4527,6 +4593,7 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb,
struct sctp_tmit_chunk *tp1, *tp2;
uint32_t cum_ack, last_tsn, biggest_tsn_acked, biggest_tsn_newly_acked,
this_sack_lowest_newack;
+ uint32_t sav_cum_ack;
uint16_t num_seg, num_dup;
uint16_t wake_him = 0;
unsigned int sack_length;
@@ -4538,6 +4605,7 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb,
int win_probe_recovery = 0;
struct sctp_nets *net = NULL;
int nonce_sum_flag, ecn_seg_sums = 0;
+ int done_once;
uint8_t reneged_all = 0;
uint8_t cmt_dac_flag;
@@ -4668,6 +4736,8 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb,
/* acking something behind */
return;
}
+ sav_cum_ack = asoc->last_acked_seq;
+
/* update the Rwnd of the peer */
if (TAILQ_EMPTY(&asoc->sent_queue) &&
TAILQ_EMPTY(&asoc->send_queue) &&
@@ -5391,6 +5461,7 @@ done_with_it:
* Now we must setup so we have a timer up for anyone with
* outstanding data.
*/
+ done_once = 0;
again:
j = 0;
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
@@ -5423,12 +5494,16 @@ again:
stcb->sctp_ep, stcb, net);
}
}
- if ((j == 0) && (!TAILQ_EMPTY(&asoc->sent_queue)) && (asoc->sent_queue_retran_cnt == 0)) {
+ if ((j == 0) &&
+ (!TAILQ_EMPTY(&asoc->sent_queue)) &&
+ (asoc->sent_queue_retran_cnt == 0) &&
+ (done_once == 0)) {
/* huh, this should not happen */
-#ifdef INVARIANTS
- panic("Flight size incorrect? fixing??");
-#else
- printf("Flight size incorrect? fixing??\n");
+ if (sctp_anal_print == 0) {
+ printf("Flight size incorrect sack-cumack:%x prev_last_ack:%x? fixing??",
+ cum_ack, sav_cum_ack);
+ sctp_print_fs_audit(asoc);
+ }
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
net->flight_size = 0;
}
@@ -5444,7 +5519,12 @@ again:
asoc->sent_queue_retran_cnt++;
}
}
-#endif
+ if (sctp_anal_print == 0) {
+ printf("After audit, totalflight:%d retran count:%d\n",
+ asoc->total_flight, asoc->sent_queue_retran_cnt);
+ sctp_anal_print = 1;
+ }
+ done_once = 1;
goto again;
}
#ifdef SCTP_SACK_RWND_LOGGING
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index b5bbb34..afb8590 100644
--- a/sys/netinet/sctp_input.c
+++ b/sys/netinet/sctp_input.c
@@ -78,7 +78,7 @@ sctp_stop_all_cookie_timers(struct sctp_tcb *stcb)
static void
sctp_handle_init(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
struct sctp_init_chunk *cp, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
- struct sctp_nets *net)
+ struct sctp_nets *net, int *abort_no_unlock)
{
struct sctp_init *init;
struct mbuf *op_err;
@@ -103,12 +103,16 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
* match/restart case?
*/
sctp_abort_association(inp, stcb, m, iphlen, sh, op_err);
+ if (stcb)
+ *abort_no_unlock = 1;
return;
}
if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_init_chunk)) {
/* Invalid length */
op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
sctp_abort_association(inp, stcb, m, iphlen, sh, op_err);
+ if (stcb)
+ *abort_no_unlock = 1;
return;
}
/* validate parameters */
@@ -116,6 +120,8 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
/* protocol error... send abort */
op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
sctp_abort_association(inp, stcb, m, iphlen, sh, op_err);
+ if (stcb)
+ *abort_no_unlock = 1;
return;
}
if (ntohl(init->a_rwnd) < SCTP_MIN_RWND) {
@@ -128,12 +134,16 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
/* protocol error... send abort */
op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
sctp_abort_association(inp, stcb, m, iphlen, sh, op_err);
+ if (stcb)
+ *abort_no_unlock = 1;
return;
}
if (init->num_outbound_streams == 0) {
/* protocol error... send abort */
op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
sctp_abort_association(inp, stcb, m, iphlen, sh, op_err);
+ if (stcb)
+ *abort_no_unlock = 1;
return;
}
init_limit = offset + ntohs(cp->ch.chunk_length);
@@ -141,6 +151,8 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
init_limit)) {
/* auth parameter(s) error... send abort */
sctp_abort_association(inp, stcb, m, iphlen, sh, NULL);
+ if (stcb)
+ *abort_no_unlock = 1;
return;
}
/* send an INIT-ACK w/cookie */
@@ -301,7 +313,7 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb,
static int
sctp_process_init_ack(struct mbuf *m, int iphlen, int offset,
struct sctphdr *sh, struct sctp_init_ack_chunk *cp, struct sctp_tcb *stcb,
- struct sctp_nets *net)
+ struct sctp_nets *net, int *abort_no_unlock)
{
struct sctp_association *asoc;
struct mbuf *op_err;
@@ -330,6 +342,7 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset,
* same param back
*/
sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3);
+ *abort_no_unlock = 1;
}
return (-1);
}
@@ -352,6 +365,7 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset,
#endif
sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, sh,
NULL);
+ *abort_no_unlock = 1;
return (-1);
}
stcb->asoc.peer_hmac_id = sctp_negotiate_hmacid(stcb->asoc.peer_hmacs,
@@ -410,6 +424,7 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset,
}
sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen,
sh, op_err);
+ *abort_no_unlock = 1;
}
return (retval);
}
@@ -910,7 +925,7 @@ sctp_handle_error(struct sctp_chunkhdr *ch,
static int
sctp_handle_init_ack(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
struct sctp_init_ack_chunk *cp, struct sctp_tcb *stcb,
- struct sctp_nets *net)
+ struct sctp_nets *net, int *abort_no_unlock)
{
struct sctp_init_ack *init_ack;
int *state;
@@ -934,6 +949,7 @@ sctp_handle_init_ack(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, sh,
op_err);
+ *abort_no_unlock = 1;
return (-1);
}
init_ack = &cp->init;
@@ -943,6 +959,7 @@ sctp_handle_init_ack(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, sh,
op_err);
+ *abort_no_unlock = 1;
return (-1);
}
if (ntohl(init_ack->a_rwnd) < SCTP_MIN_RWND) {
@@ -950,6 +967,7 @@ sctp_handle_init_ack(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, sh,
op_err);
+ *abort_no_unlock = 1;
return (-1);
}
if (init_ack->num_inbound_streams == 0) {
@@ -957,6 +975,7 @@ sctp_handle_init_ack(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, sh,
op_err);
+ *abort_no_unlock = 1;
return (-1);
}
if (init_ack->num_outbound_streams == 0) {
@@ -964,6 +983,7 @@ sctp_handle_init_ack(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, sh,
op_err);
+ *abort_no_unlock = 1;
return (-1);
}
/* process according to association state... */
@@ -985,8 +1005,8 @@ sctp_handle_init_ack(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED,
stcb, 0, (void *)stcb->asoc.primary_destination);
}
- if (sctp_process_init_ack(m, iphlen, offset, sh, cp, stcb, net
- ) < 0) {
+ if (sctp_process_init_ack(m, iphlen, offset, sh, cp, stcb, net,
+ abort_no_unlock) < 0) {
/* error in parsing parameters */
return (-1);
}
@@ -1536,7 +1556,7 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
struct sockaddr_in *sin;
struct sockaddr_in6 *sin6;
struct sctp_association *asoc;
- uint32_t vrf;
+ uint32_t vrf_id;
int chk_length;
int init_offset, initack_offset, initack_limit;
int retval;
@@ -1544,7 +1564,7 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
uint32_t old_tag;
uint8_t auth_chunk_buf[SCTP_PARAM_BUFFER_SIZE];
- vrf = SCTP_DEFAULT_VRFID;
+ vrf_id = inp->def_vrf_id;
/*
* find and validate the INIT chunk in the cookie (peer's info) the
@@ -1607,7 +1627,7 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
* and popluate
*/
stcb = sctp_aloc_assoc(inp, init_src, 0, &error,
- ntohl(initack_cp->init.initiate_tag), vrf);
+ ntohl(initack_cp->init.initiate_tag), vrf_id);
if (stcb == NULL) {
struct mbuf *op_err;
@@ -3527,6 +3547,7 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length,
int num_chunks = 0; /* number of control chunks processed */
int chk_length;
int ret;
+ int abort_no_unlock = 0;
/*
* How big should this be, and should it be alloc'd? Lets try the
@@ -3829,7 +3850,10 @@ process_control_chunks:
return (NULL);
}
sctp_handle_init(m, iphlen, *offset, sh,
- (struct sctp_init_chunk *)ch, inp, stcb, *netp);
+ (struct sctp_init_chunk *)ch, inp, stcb, *netp, &abort_no_unlock);
+ if (abort_no_unlock)
+ return (NULL);
+
*offset = length;
if (locked_tcb)
SCTP_TCB_UNLOCK(locked_tcb);
@@ -3864,11 +3888,14 @@ process_control_chunks:
return (NULL);
}
ret = sctp_handle_init_ack(m, iphlen, *offset, sh,
- (struct sctp_init_ack_chunk *)ch, stcb, *netp);
+ (struct sctp_init_ack_chunk *)ch, stcb, *netp, &abort_no_unlock);
/*
* Special case, I must call the output routine to
* get the cookie echoed
*/
+ if (abort_no_unlock)
+ return (NULL);
+
if ((stcb) && ret == 0)
sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC);
*offset = length;
@@ -4683,6 +4710,7 @@ sctp_input(i_pak, off)
#endif
struct mbuf *m;
int iphlen;
+ uint32_t vrf_id;
uint8_t ecn_bits;
struct ip *ip;
struct sctphdr *sh;
@@ -4695,7 +4723,8 @@ sctp_input(i_pak, off)
int refcount_up = 0;
int length, mlen, offset;
-
+ vrf_id = SCTP_DEFAULT_VRFID;
+ mlen = SCTP_HEADER_LEN(i_pak);
iphlen = off;
m = SCTP_HEADER_TO_CHAIN(i_pak);
net = NULL;
@@ -4767,7 +4796,7 @@ sctp_input(i_pak, off)
stcb = sctp_findassociation_addr(m, iphlen,
offset - sizeof(*ch),
- sh, ch, &inp, &net);
+ sh, ch, &inp, &net, vrf_id);
if ((inp) && (stcb)) {
sctp_send_packet_dropped(stcb, net, m, iphlen, 1);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_INPUT_ERROR);
@@ -4779,11 +4808,8 @@ sctp_input(i_pak, off)
goto bad;
}
sh->checksum = calc_check;
- } else {
-sctp_skip_csum_4:
- mlen = SCTP_HEADER_LEN(m);
}
-
+sctp_skip_csum_4:
/* destination port of 0 is illegal, based on RFC2960. */
if (sh->dest_port == 0) {
SCTP_STAT_INCR(sctps_hdrops);
@@ -4799,7 +4825,7 @@ sctp_skip_csum_4:
* IP/SCTP/first chunk header...
*/
stcb = sctp_findassociation_addr(m, iphlen, offset - sizeof(*ch),
- sh, ch, &inp, &net);
+ sh, ch, &inp, &net, vrf_id);
/* inp's ref-count increased && stcb locked */
if (inp == NULL) {
struct sctp_init_chunk *init_chk, chunk_buf;
diff --git a/sys/netinet/sctp_os_bsd.h b/sys/netinet/sctp_os_bsd.h
index e74ccfa..81e028c 100644
--- a/sys/netinet/sctp_os_bsd.h
+++ b/sys/netinet/sctp_os_bsd.h
@@ -93,10 +93,8 @@ __FBSDID("$FreeBSD$");
#endif /* INET6 */
-
#include <netinet/ip_options.h>
-
#ifndef in6pcb
#define in6pcb inpcb
#endif
@@ -270,6 +268,12 @@ typedef struct callout sctp_os_timer_t;
#define SCTP_SB_LIMIT_SND(so) so->so_snd.sb_hiwat
/*
+ * routes, output, etc.
+ */
+typedef struct route sctp_route_t;
+
+
+/*
* SCTP AUTH
*/
#define HAVE_SHA2
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c
index 416ab64..ccfd197 100644
--- a/sys/netinet/sctp_output.c
+++ b/sys/netinet/sctp_output.c
@@ -1991,7 +1991,7 @@ sctp_add_addresses_to_i_ia(struct sctp_inpcb *inp, struct sctp_scoping *scope,
int cnt, limit_out = 0, total_count;
uint32_t vrf_id;
- vrf_id = SCTP_DEFAULT_VRFID;
+ vrf_id = inp->def_vrf_id;
SCTP_IPI_ADDR_LOCK();
vrf = sctp_find_vrf(vrf_id);
if (vrf == NULL) {
@@ -2403,7 +2403,7 @@ sctp_is_addr_in_ep(struct sctp_inpcb *inp, struct sctp_ifa *ifa)
static struct sctp_ifa *
sctp_choose_boundspecific_inp(struct sctp_inpcb *inp,
- struct route *ro,
+ sctp_route_t * ro,
uint32_t vrf_id,
int non_asoc_addr_ok,
uint8_t dest_is_priv,
@@ -2414,7 +2414,7 @@ sctp_choose_boundspecific_inp(struct sctp_inpcb *inp,
void *ifn;
int resettotop = 0;
struct sctp_ifn *sctp_ifn;
- struct sctp_ifa *sctp_ifa, *pass;
+ struct sctp_ifa *sctp_ifa, *sifa;
struct sctp_vrf *vrf;
uint32_t ifn_index;
@@ -2435,12 +2435,12 @@ sctp_choose_boundspecific_inp(struct sctp_inpcb *inp,
LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0))
continue;
- pass = sctp_is_ifa_addr_prefered(sctp_ifa, dest_is_loop, dest_is_priv, fam);
- if (pass == NULL)
+ sifa = sctp_is_ifa_addr_prefered(sctp_ifa, dest_is_loop, dest_is_priv, fam);
+ if (sifa == NULL)
continue;
- if (sctp_is_addr_in_ep(inp, pass)) {
- atomic_add_int(&pass->refcount, 1);
- return (pass);
+ if (sctp_is_addr_in_ep(inp, sifa)) {
+ atomic_add_int(&sifa->refcount, 1);
+ return (sifa);
}
}
}
@@ -2461,11 +2461,11 @@ once_again:
/* address has been removed */
continue;
}
- pass = sctp_is_ifa_addr_prefered(laddr->ifa, dest_is_loop, dest_is_priv, fam);
- if (pass == NULL)
+ sifa = sctp_is_ifa_addr_prefered(laddr->ifa, dest_is_loop, dest_is_priv, fam);
+ if (sifa == NULL)
continue;
- atomic_add_int(&pass->refcount, 1);
- return (pass);
+ atomic_add_int(&sifa->refcount, 1);
+ return (sifa);
}
if (resettotop == 0) {
inp->next_addr_touse = NULL;
@@ -2484,11 +2484,11 @@ once_again_too:
/* address has been removed */
continue;
}
- pass = sctp_is_ifa_addr_acceptable(laddr->ifa, dest_is_loop, dest_is_priv, fam);
- if (pass == NULL)
+ sifa = sctp_is_ifa_addr_acceptable(laddr->ifa, dest_is_loop, dest_is_priv, fam);
+ if (sifa == NULL)
continue;
- atomic_add_int(&pass->refcount, 1);
- return (pass);
+ atomic_add_int(&sifa->refcount, 1);
+ return (sifa);
}
if (resettotop == 0) {
inp->next_addr_touse = NULL;
@@ -2507,7 +2507,7 @@ static struct sctp_ifa *
sctp_choose_boundspecific_stcb(struct sctp_inpcb *inp,
struct sctp_tcb *stcb,
struct sctp_nets *net,
- struct route *ro,
+ sctp_route_t * ro,
uint32_t vrf_id,
uint8_t dest_is_priv,
uint8_t dest_is_loop,
@@ -2517,7 +2517,7 @@ sctp_choose_boundspecific_stcb(struct sctp_inpcb *inp,
struct sctp_laddr *laddr, *starting_point;
void *ifn;
struct sctp_ifn *sctp_ifn;
- struct sctp_ifa *sctp_ifa, *pass;
+ struct sctp_ifa *sctp_ifa, *sifa;
uint8_t start_at_beginning = 0;
struct sctp_vrf *vrf;
uint32_t ifn_index;
@@ -2540,21 +2540,21 @@ sctp_choose_boundspecific_stcb(struct sctp_inpcb *inp,
* acceptable.
*/
if (sctp_ifn) {
- /* first try for an prefered address on the ep */
+ /* first try for a prefered address on the ep */
LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0))
continue;
if (sctp_is_addr_in_ep(inp, sctp_ifa)) {
- pass = sctp_is_ifa_addr_prefered(sctp_ifa, dest_is_loop, dest_is_priv, fam);
- if (pass == NULL)
+ sifa = sctp_is_ifa_addr_prefered(sctp_ifa, dest_is_loop, dest_is_priv, fam);
+ if (sifa == NULL)
continue;
if ((non_asoc_addr_ok == 0) &&
- (sctp_is_addr_restricted(stcb, pass))) {
+ (sctp_is_addr_restricted(stcb, sifa))) {
/* on the no-no list */
continue;
}
- atomic_add_int(&pass->refcount, 1);
- return (pass);
+ atomic_add_int(&sifa->refcount, 1);
+ return (sifa);
}
}
/* next try for an acceptable address on the ep */
@@ -2562,16 +2562,16 @@ sctp_choose_boundspecific_stcb(struct sctp_inpcb *inp,
if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0))
continue;
if (sctp_is_addr_in_ep(inp, sctp_ifa)) {
- pass = sctp_is_ifa_addr_acceptable(sctp_ifa, dest_is_loop, dest_is_priv, fam);
- if (pass == NULL)
+ sifa = sctp_is_ifa_addr_acceptable(sctp_ifa, dest_is_loop, dest_is_priv, fam);
+ if (sifa == NULL)
continue;
if ((non_asoc_addr_ok == 0) &&
- (sctp_is_addr_restricted(stcb, pass))) {
+ (sctp_is_addr_restricted(stcb, sifa))) {
/* on the no-no list */
continue;
}
- atomic_add_int(&pass->refcount, 1);
- return (pass);
+ atomic_add_int(&sifa->refcount, 1);
+ return (sifa);
}
}
@@ -2593,17 +2593,17 @@ sctp_from_the_top:
/* address has been removed */
continue;
}
- pass = sctp_is_ifa_addr_prefered(laddr->ifa, dest_is_loop, dest_is_priv, fam);
- if (pass == NULL)
+ sifa = sctp_is_ifa_addr_prefered(laddr->ifa, dest_is_loop, dest_is_priv, fam);
+ if (sifa == NULL)
continue;
if ((non_asoc_addr_ok == 0) &&
- (sctp_is_addr_restricted(stcb, pass))) {
+ (sctp_is_addr_restricted(stcb, sifa))) {
/* on the no-no list */
continue;
}
stcb->asoc.last_used_address = laddr;
- atomic_add_int(&pass->refcount, 1);
- return (pass);
+ atomic_add_int(&sifa->refcount, 1);
+ return (sifa);
}
if (start_at_beginning == 0) {
@@ -2625,17 +2625,17 @@ sctp_from_the_top2:
/* address has been removed */
continue;
}
- pass = sctp_is_ifa_addr_acceptable(laddr->ifa, dest_is_loop, dest_is_priv, fam);
- if (pass == NULL)
+ sifa = sctp_is_ifa_addr_acceptable(laddr->ifa, dest_is_loop, dest_is_priv, fam);
+ if (sifa == NULL)
continue;
if ((non_asoc_addr_ok == 0) &&
- (sctp_is_addr_restricted(stcb, pass))) {
+ (sctp_is_addr_restricted(stcb, sifa))) {
/* on the no-no list */
continue;
}
stcb->asoc.last_used_address = laddr;
- atomic_add_int(&pass->refcount, 1);
- return (pass);
+ atomic_add_int(&sifa->refcount, 1);
+ return (sifa);
}
if (start_at_beginning == 0) {
stcb->asoc.last_used_address = NULL;
@@ -2653,17 +2653,17 @@ sctp_select_nth_prefered_addr_from_ifn_boundall(struct sctp_ifn *ifn,
int addr_wanted,
sa_family_t fam)
{
- struct sctp_ifa *ifa, *pass;
+ struct sctp_ifa *ifa, *sifa;
int num_eligible_addr = 0;
LIST_FOREACH(ifa, &ifn->ifalist, next_ifa) {
if ((ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0))
continue;
- pass = sctp_is_ifa_addr_prefered(ifa, dest_is_loop, dest_is_priv, fam);
- if (pass == NULL)
+ sifa = sctp_is_ifa_addr_prefered(ifa, dest_is_loop, dest_is_priv, fam);
+ if (sifa == NULL)
continue;
if (stcb) {
- if ((non_asoc_addr_ok == 0) && sctp_is_addr_restricted(stcb, pass)) {
+ if ((non_asoc_addr_ok == 0) && sctp_is_addr_restricted(stcb, sifa)) {
/*
* It is restricted for some reason..
* probably not yet added.
@@ -2672,7 +2672,7 @@ sctp_select_nth_prefered_addr_from_ifn_boundall(struct sctp_ifn *ifn,
}
}
if (num_eligible_addr >= addr_wanted) {
- return (pass);
+ return (sifa);
}
num_eligible_addr++;
}
@@ -2688,19 +2688,19 @@ sctp_count_num_prefered_boundall(struct sctp_ifn *ifn,
uint8_t dest_is_priv,
sa_family_t fam)
{
- struct sctp_ifa *ifa, *pass;
+ struct sctp_ifa *ifa, *sifa;
int num_eligible_addr = 0;
LIST_FOREACH(ifa, &ifn->ifalist, next_ifa) {
if ((ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0)) {
continue;
}
- pass = sctp_is_ifa_addr_prefered(ifa, dest_is_loop, dest_is_priv, fam);
- if (pass == NULL) {
+ sifa = sctp_is_ifa_addr_prefered(ifa, dest_is_loop, dest_is_priv, fam);
+ if (sifa == NULL) {
continue;
}
if (stcb) {
- if ((non_asoc_addr_ok == 0) && sctp_is_addr_restricted(stcb, pass)) {
+ if ((non_asoc_addr_ok == 0) && sctp_is_addr_restricted(stcb, sifa)) {
/*
* It is restricted for some reason..
* probably not yet added.
@@ -2717,7 +2717,7 @@ static struct sctp_ifa *
sctp_choose_boundall(struct sctp_inpcb *inp,
struct sctp_tcb *stcb,
struct sctp_nets *net,
- struct route *ro,
+ sctp_route_t * ro,
uint32_t vrf_id,
uint8_t dest_is_priv,
uint8_t dest_is_loop,
@@ -2727,7 +2727,7 @@ sctp_choose_boundall(struct sctp_inpcb *inp,
int cur_addr_num = 0, num_prefered = 0;
void *ifn;
struct sctp_ifn *sctp_ifn, *looked_at = NULL, *emit_ifn;
- struct sctp_ifa *sctp_ifa, *pass;
+ struct sctp_ifa *sctp_ifa, *sifa;
uint32_t ifn_index;
struct sctp_vrf *vrf;
@@ -2854,9 +2854,9 @@ bound_all_plan_b:
if (cur_addr_num >= num_prefered) {
cur_addr_num = 0;
}
- pass = sctp_select_nth_prefered_addr_from_ifn_boundall(sctp_ifn, stcb, non_asoc_addr_ok, dest_is_loop,
+ sifa = sctp_select_nth_prefered_addr_from_ifn_boundall(sctp_ifn, stcb, non_asoc_addr_ok, dest_is_loop,
dest_is_priv, cur_addr_num, fam);
- if (pass == NULL)
+ if (sifa == NULL)
continue;
if (net) {
net->indx_of_eligible_next_to_use = cur_addr_num + 1;
@@ -2864,14 +2864,14 @@ bound_all_plan_b:
if (sctp_debug_on & SCTP_DEBUG_OUTPUT2) {
printf("we selected %d\n", cur_addr_num);
printf("Source:");
- sctp_print_address(&pass->address.sa);
+ sctp_print_address(&sifa->address.sa);
printf("Dest:");
sctp_print_address(&net->ro._l_addr.sa);
}
#endif
}
- atomic_add_int(&pass->refcount, 1);
- return (pass);
+ atomic_add_int(&sifa->refcount, 1);
+ return (sifa);
}
@@ -2888,11 +2888,11 @@ bound_all_plan_b:
LIST_FOREACH(sctp_ifa, &emit_ifn->ifalist, next_ifa) {
if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0))
continue;
- pass = sctp_is_ifa_addr_acceptable(sctp_ifa, dest_is_loop, dest_is_priv, fam);
- if (pass == NULL)
+ sifa = sctp_is_ifa_addr_acceptable(sctp_ifa, dest_is_loop, dest_is_priv, fam);
+ if (sifa == NULL)
continue;
if (stcb) {
- if ((non_asoc_addr_ok == 0) && sctp_is_addr_restricted(stcb, pass)) {
+ if ((non_asoc_addr_ok == 0) && sctp_is_addr_restricted(stcb, sifa)) {
/*
* It is restricted for some reason..
* probably not yet added.
@@ -2900,8 +2900,8 @@ bound_all_plan_b:
continue;
}
}
- atomic_add_int(&pass->refcount, 1);
- return (pass);
+ atomic_add_int(&sifa->refcount, 1);
+ return (sifa);
}
/*
@@ -2927,11 +2927,11 @@ bound_all_plan_b:
LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0))
continue;
- pass = sctp_is_ifa_addr_acceptable(sctp_ifa, dest_is_loop, dest_is_priv, fam);
- if (pass == NULL)
+ sifa = sctp_is_ifa_addr_acceptable(sctp_ifa, dest_is_loop, dest_is_priv, fam);
+ if (sifa == NULL)
continue;
if (stcb) {
- if ((non_asoc_addr_ok == 0) && sctp_is_addr_restricted(stcb, pass)) {
+ if ((non_asoc_addr_ok == 0) && sctp_is_addr_restricted(stcb, sifa)) {
/*
* It is restricted for some
* reason.. probably not yet added.
@@ -2939,8 +2939,8 @@ bound_all_plan_b:
continue;
}
}
- atomic_add_int(&pass->refcount, 1);
- return (pass);
+ atomic_add_int(&sifa->refcount, 1);
+ return (sifa);
}
}
/*
@@ -2957,7 +2957,7 @@ bound_all_plan_b:
struct sctp_ifa *
sctp_source_address_selection(struct sctp_inpcb *inp,
struct sctp_tcb *stcb,
- struct route *ro,
+ sctp_route_t * ro,
struct sctp_nets *net,
int non_asoc_addr_ok, uint32_t vrf_id)
{
@@ -3398,7 +3398,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
int ret;
unsigned int have_mtu;
uint32_t vrf_id;
- struct route *ro;
+ sctp_route_t *ro;
if ((net) && (net->dest_state & SCTP_ADDR_OUT_OF_SCOPE)) {
@@ -3406,7 +3406,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
return (EFAULT);
}
if (stcb == NULL) {
- vrf_id = SCTP_DEFAULT_VRFID;
+ vrf_id = inp->def_vrf_id;
} else {
vrf_id = stcb->asoc.vrf_id;
}
@@ -3436,7 +3436,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
if (to->sa_family == AF_INET) {
struct ip *ip = NULL;
- struct route iproute;
+ sctp_route_t iproute;
uint8_t tos_value;
o_pak = SCTP_GET_HEADER_FOR_OUTPUT(sizeof(struct ip));
@@ -3491,7 +3491,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
memset(&iproute, 0, sizeof(iproute));
memcpy(&ro->ro_dst, to, to->sa_len);
} else {
- ro = (struct route *)&net->ro;
+ ro = (sctp_route_t *) & net->ro;
}
/* Now the address selection part */
ip->ip_dst.s_addr = ((struct sockaddr_in *)to)->sin_addr.s_addr;
@@ -3694,10 +3694,10 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
return (EINVAL);
if (net == NULL) {
memset(&ip6route, 0, sizeof(ip6route));
- ro = (struct route *)&ip6route;
+ ro = (sctp_route_t *) & ip6route;
memcpy(&ro->ro_dst, sin6, sin6->sin6_len);
} else {
- ro = (struct route *)&net->ro;
+ ro = (sctp_route_t *) & net->ro;
}
if (stcb != NULL) {
if ((stcb->asoc.ecn_allowed) && ecn_ok) {
@@ -4100,7 +4100,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
/*
* To optimize this we could put the scoping stuff into a
* structure and remove the individual uint8's from the
- * assoc structure. Then we could just pass in the address
+ * assoc structure. Then we could just sifa in the address
* within the stcb.. but for now this is a quick hack to get
* the address stuff teased apart.
*/
@@ -4124,7 +4124,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
}
initm->msg.ch.chunk_length = htons((p_len - sizeof(struct sctphdr)));
/*
- * We pass 0 here to NOT set IP_DF if its IPv4, we ignore the return
+ * We sifa 0 here to NOT set IP_DF if its IPv4, we ignore the return
* here since the timer will drive a retranmission.
*/
@@ -4523,7 +4523,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
struct sockaddr_storage store;
struct sockaddr_in *sin;
struct sockaddr_in6 *sin6;
- struct route *ro;
+ sctp_route_t *ro;
struct ip *iph;
struct ip6_hdr *ip6;
struct sockaddr *to;
@@ -4536,10 +4536,11 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
int p_len;
uint32_t vrf_id;
- vrf_id = SCTP_DEFAULT_VRFID;
if (stcb) {
asoc = &stcb->asoc;
+ vrf_id = asoc->vrf_id;
} else {
+ vrf_id = inp->def_vrf_id;
asoc = NULL;
}
m_last = NULL;
@@ -4631,7 +4632,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
iph = mtod(init_pkt, struct ip *);
if (iph->ip_v == IPVERSION) {
struct sctp_ifa *addr;
- struct route iproute;
+ sctp_route_t iproute;
sin->sin_family = AF_INET;
sin->sin_len = sizeof(struct sockaddr_in);
@@ -4733,7 +4734,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
}
/* local from address */
memset(&iproute6, 0, sizeof(iproute6));
- ro = (struct route *)&iproute6;
+ ro = (sctp_route_t *) & iproute6;
memcpy(&ro->ro_dst, sin6, sizeof(*sin6));
addr = sctp_source_address_selection(inp, NULL,
ro, NULL, 0, vrf_id);
@@ -4782,7 +4783,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
* did the selection.
*/
net->ro._s_addr = sctp_source_address_selection(inp,
- stcb, (struct route *)&net->ro,
+ stcb, (sctp_route_t *) & net->ro,
net, 0, vrf_id);
if (net->ro._s_addr == NULL)
return;
@@ -4806,7 +4807,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
* did the selection.
*/
net->ro._s_addr = sctp_source_address_selection(inp,
- stcb, (struct route *)&net->ro,
+ stcb, (sctp_route_t *) & net->ro,
net, 0, vrf_id);
if (net->ro._s_addr == NULL)
return;
@@ -4999,7 +5000,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
/*
* To optimize this we could put the scoping stuff into a
* structure and remove the individual uint8's from the stc
- * structure. Then we could just pass in the address within
+ * structure. Then we could just sifa in the address within
* the stc.. but for now this is a quick hack to get the
* address stuff teased apart.
*/
@@ -5093,7 +5094,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
}
/*
- * We pass 0 here to NOT set IP_DF if its IPv4, we ignore the return
+ * We sifa 0 here to NOT set IP_DF if its IPv4, we ignore the return
* here since the timer will drive a retranmission.
*/
padval = p_len % 4;
@@ -5420,7 +5421,7 @@ sctp_msg_append(struct sctp_tcb *stcb,
at = m;
sctp_set_prsctp_policy(stcb, sp);
/*
- * We could in theory (for sendall) pass the length in, but we would
+ * We could in theory (for sendall) sifa the length in, but we would
* still have to hunt through the chain since we need to setup the
* tail_mbuf
*/
@@ -9269,7 +9270,7 @@ sctp_send_shutdown_complete2(struct mbuf *m, int iphlen, struct sctphdr *sh)
comp_cp->sh.checksum = sctp_calculate_sum(mout, NULL, offset_out);
}
if (iph_out != NULL) {
- struct route ro;
+ sctp_route_t ro;
bzero(&ro, sizeof ro);
/* set IPv4 length */
@@ -10121,7 +10122,7 @@ sctp_send_abort(struct mbuf *m, int iphlen, struct sctphdr *sh, uint32_t vtag,
abm->sh.checksum = sctp_calculate_sum(mout, NULL, iphlen_out);
}
if (iph_out != NULL) {
- struct route ro;
+ sctp_route_t ro;
/* zap the stack pointer to the route */
bzero(&ro, sizeof ro);
@@ -10226,7 +10227,7 @@ sctp_send_operr_to(struct mbuf *m, int iphlen,
if (iph->ip_v == IPVERSION) {
/* V4 */
struct ip *out;
- struct route ro;
+ sctp_route_t ro;
o_pak = SCTP_GET_HEADER_FOR_OUTPUT(sizeof(struct ip));
if (o_pak == NULL) {
@@ -10538,8 +10539,12 @@ sctp_sosend(struct socket *so,
use_rcvinfo = 1;
}
}
- error = sctp_lower_sosend(so, addr, uio, top, control, flags,
- use_rcvinfo, &srcv, p);
+ error = sctp_lower_sosend(so, addr, uio, top,
+ control,
+ flags,
+ use_rcvinfo, &srcv
+ ,p
+ );
return (error);
}
@@ -10711,7 +10716,7 @@ sctp_lower_sosend(struct socket *so,
* UDP style, we must go ahead and start the INIT
* process
*/
- uint32_t vrf;
+ uint32_t vrf_id;
if ((use_rcvinfo) && (srcv) &&
((srcv->sinfo_flags & SCTP_ABORT) ||
@@ -10725,8 +10730,9 @@ sctp_lower_sosend(struct socket *so,
goto out_unlocked;
}
/* get an asoc/stcb struct */
- vrf = SCTP_DEFAULT_VRFID;
- stcb = sctp_aloc_assoc(inp, addr, 1, &error, 0, vrf);
+
+ vrf_id = inp->def_vrf_id;
+ stcb = sctp_aloc_assoc(inp, addr, 1, &error, 0, vrf_id);
if (stcb == NULL) {
/* Error is setup for us in the call */
goto out_unlocked;
diff --git a/sys/netinet/sctp_output.h b/sys/netinet/sctp_output.h
index 5daa406..bebce43 100644
--- a/sys/netinet/sctp_output.h
+++ b/sys/netinet/sctp_output.h
@@ -71,7 +71,7 @@ int
struct sctp_ifa *
sctp_source_address_selection(struct sctp_inpcb *inp,
struct sctp_tcb *stcb,
- struct route *ro, struct sctp_nets *net,
+ sctp_route_t * ro, struct sctp_nets *net,
int non_asoc_addr_ok, uint32_t vrf_id);
diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c
index ac9c196..19dde5d 100644
--- a/sys/netinet/sctp_pcb.c
+++ b/sys/netinet/sctp_pcb.c
@@ -207,6 +207,7 @@ sctp_find_vrf(uint32_t vrfid)
return (NULL);
}
+
void
sctp_free_ifa(struct sctp_ifa *sctp_ifap)
{
@@ -215,6 +216,17 @@ sctp_free_ifa(struct sctp_ifa *sctp_ifap)
ret = atomic_fetchadd_int(&sctp_ifap->refcount, -1);
if (ret == 1) {
/* We zero'd the count */
+#ifdef INVARIANTS
+ if (sctp_ifap->in_ifa_list) {
+ panic("Attempt to free item in a list");
+ }
+#else
+ if (sctp_ifap->in_ifa_list) {
+ printf("in_ifa_list was not clear, fixing cnt\n");
+ atomic_add_int(&sctp_ifap->refcount, 1);
+ return;
+ }
+#endif
SCTP_FREE(sctp_ifap);
}
}
@@ -349,6 +361,7 @@ sctp_add_addr_to_vrf(uint32_t vrfid, void *ifn, uint32_t ifn_index,
sctp_ifap->refcount = 1;
LIST_INSERT_HEAD(&sctp_ifnp->ifalist, sctp_ifap, next_ifa);
sctp_ifnp->ifa_count++;
+ sctp_ifap->in_ifa_list = 1;
vrf->total_ifa_count++;
SCTP_IPI_ADDR_UNLOCK();
return (sctp_ifap);
@@ -383,6 +396,7 @@ sctp_del_addr_from_vrf(uint32_t vrfid, struct sockaddr *addr,
vrf->total_ifa_count--;
LIST_REMOVE(sctp_ifap, next_bucket);
LIST_REMOVE(sctp_ifap, next_ifa);
+ sctp_ifap->in_ifa_list = 0;
atomic_add_int(&sctp_ifnp->refcount, -1);
} else {
printf("Del Addr-ifn:%d Could not find address:",
@@ -412,7 +426,7 @@ out_now:
static struct sctp_tcb *
sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from,
- struct sockaddr *to, struct sctp_nets **netp)
+ struct sockaddr *to, struct sctp_nets **netp, uint32_t vrf_id)
{
/**** ASSUMSES THE CALLER holds the INP_INFO_RLOCK */
@@ -462,6 +476,10 @@ sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from,
SCTP_INP_RUNLOCK(inp);
continue;
}
+ if (inp->def_vrf_id == vrf_id) {
+ SCTP_INP_RUNLOCK(inp);
+ continue;
+ }
/* check to see if the ep has one of the addresses */
if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
/* We are NOT bound all, so look further */
@@ -599,7 +617,7 @@ sctp_findassociation_ep_addr(struct sctp_inpcb **inp_p, struct sockaddr *remote,
{
struct sctpasochead *head;
struct sctp_inpcb *inp;
- struct sctp_tcb *stcb;
+ struct sctp_tcb *stcb = NULL;
struct sctp_nets *net;
uint16_t rport;
@@ -620,7 +638,7 @@ sctp_findassociation_ep_addr(struct sctp_inpcb **inp_p, struct sockaddr *remote,
}
SCTP_INP_INFO_RLOCK();
if (inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
- /*
+ /*-
* Now either this guy is our listener or it's the
* connector. If it is the one that issued the connect, then
* it's only chance is to be the first TCB in the list. If
@@ -630,7 +648,7 @@ sctp_findassociation_ep_addr(struct sctp_inpcb **inp_p, struct sockaddr *remote,
if ((inp->sctp_socket) && (inp->sctp_socket->so_qlimit)) {
/* to is peer addr, from is my addr */
stcb = sctp_tcb_special_locate(inp_p, remote, local,
- netp);
+ netp, inp->def_vrf_id);
if ((stcb != NULL) && (locked_tcb == NULL)) {
/* we have a locked tcb, lower refcount */
SCTP_INP_WLOCK(inp);
@@ -1131,9 +1149,9 @@ sctp_findassociation_addr_sa(struct sockaddr *to, struct sockaddr *from,
SCTP_INP_INFO_RLOCK();
if (find_tcp_pool) {
if (inp_p != NULL) {
- retval = sctp_tcb_special_locate(inp_p, from, to, netp);
+ retval = sctp_tcb_special_locate(inp_p, from, to, netp, vrf_id);
} else {
- retval = sctp_tcb_special_locate(&inp, from, to, netp);
+ retval = sctp_tcb_special_locate(&inp, from, to, netp, vrf_id);
}
if (retval != NULL) {
SCTP_INP_INFO_RUNLOCK();
@@ -1331,7 +1349,7 @@ sctp_findassoc_by_vtag(struct sockaddr *from, uint32_t vtag,
struct sctp_tcb *
sctp_findassociation_addr(struct mbuf *m, int iphlen, int offset,
struct sctphdr *sh, struct sctp_chunkhdr *ch,
- struct sctp_inpcb **inp_p, struct sctp_nets **netp)
+ struct sctp_inpcb **inp_p, struct sctp_nets **netp, uint32_t vrf_id)
{
int find_tcp_pool;
struct ip *iph;
@@ -1340,9 +1358,7 @@ sctp_findassociation_addr(struct mbuf *m, int iphlen, int offset,
struct sockaddr *to = (struct sockaddr *)&to_store;
struct sockaddr *from = (struct sockaddr *)&from_store;
struct sctp_inpcb *inp;
- uint32_t vrf_id;
- vrf_id = SCTP_DEFAULT_VRFID;
iph = mtod(m, struct ip *);
if (iph->ip_v == IPVERSION) {
/* its IPv4 */
@@ -1871,6 +1887,7 @@ sctp_move_pcb_and_assoc(struct sctp_inpcb *old_inp, struct sctp_inpcb *new_inp,
SCTP_INCR_LADDR_COUNT();
bzero(laddr, sizeof(*laddr));
laddr->ifa = oladdr->ifa;
+ atomic_add_int(&laddr->ifa->refcount, 1);
LIST_INSERT_HEAD(&new_inp->sctp_addr_list, laddr,
sctp_nxt_addr);
new_inp->laddr_count++;
@@ -2371,6 +2388,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
struct sctp_queued_to_read *sq;
+
int cnt;
sctp_sharedkey_t *shared_key;
@@ -2819,6 +2837,7 @@ sctp_set_initial_cc_param(struct sctp_tcb *stcb, struct sctp_nets *net)
net->ssthresh = stcb->asoc.peers_rwnd;
}
+
int
sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
int set_scope, int from)
@@ -2999,6 +3018,7 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
sin6->sin6_scope_id = 0;
}
rtalloc_ign((struct route *)&net->ro, 0UL);
+
if (newaddr->sa_family == AF_INET6) {
struct sockaddr_in6 *sin6;
@@ -3070,15 +3090,13 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
netlook = TAILQ_NEXT(netfirst, sctp_next);
if (netlook == NULL) {
/* End of the list */
- TAILQ_INSERT_TAIL(&stcb->asoc.nets, net,
- sctp_next);
+ TAILQ_INSERT_TAIL(&stcb->asoc.nets, net, sctp_next);
break;
} else if (netlook->ro.ro_rt == NULL) {
/* next one has NO route */
TAILQ_INSERT_BEFORE(netfirst, net, sctp_next);
break;
- } else if (netlook->ro.ro_rt->rt_ifp !=
- net->ro.ro_rt->rt_ifp) {
+ } else if (netlook->ro.ro_rt->rt_ifp != net->ro.ro_rt->rt_ifp) {
TAILQ_INSERT_AFTER(&stcb->asoc.nets, netlook,
net, sctp_next);
break;
@@ -3268,6 +3286,7 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
SCTP_DECR_ASOC_COUNT();
SCTP_TCB_LOCK_DESTROY(stcb);
SCTP_TCB_SEND_LOCK_DESTROY(stcb);
+ SCTP_INP_WUNLOCK(inp);
*error = ENOBUFS;
return (NULL);
}
@@ -3458,6 +3477,7 @@ sctp_iterator_asoc_being_freed(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
}
}
+
/*
* Free the association after un-hashing the remote port.
*/
@@ -5392,7 +5412,8 @@ sctp_drain()
* flags and asoc_state. "af" (mandatory) is executed for all matching
* assocs and "ef" (optional) is executed when the iterator completes.
* "inpf" (optional) is executed for each new endpoint as it is being
- * iterated through.
+ * iterated through. inpe (optional) is called when the inp completes
+ * its way through all the stcbs.
*/
int
sctp_initiate_iterator(inp_func inpf,
diff --git a/sys/netinet/sctp_pcb.h b/sys/netinet/sctp_pcb.h
index 34a8452..022a359 100644
--- a/sys/netinet/sctp_pcb.h
+++ b/sys/netinet/sctp_pcb.h
@@ -53,7 +53,6 @@ TAILQ_HEAD(sctp_streamhead, sctp_stream_queue_pending);
#include <netinet/sctp_structs.h>
#include <netinet/sctp_uio.h>
#include <netinet/sctp_auth.h>
-#include <netinet/sctp_bsd_addr.h>
/*
* PCB flags (in sctp_flags bitmask)
@@ -158,7 +157,7 @@ struct sctp_ifa {
uint8_t src_is_loop;
uint8_t src_is_priv;
uint8_t src_is_glob;
- uint8_t resv;
+ uint8_t in_ifa_list;
};
struct sctp_laddr {
@@ -477,7 +476,7 @@ int sctp_inpcb_bind(struct socket *, struct sockaddr *, struct thread *);
struct sctp_tcb *
sctp_findassociation_addr(struct mbuf *, int, int,
struct sctphdr *, struct sctp_chunkhdr *, struct sctp_inpcb **,
- struct sctp_nets **);
+ struct sctp_nets **, uint32_t vrf_id);
struct sctp_tcb *
sctp_findassociation_addr_sa(struct sockaddr *,
diff --git a/sys/netinet/sctp_sysctl.c b/sys/netinet/sctp_sysctl.c
index c2aac0d..943399e 100644
--- a/sys/netinet/sctp_sysctl.c
+++ b/sys/netinet/sctp_sysctl.c
@@ -91,7 +91,7 @@ uint32_t sctp_chunkscale = SCTP_CHUNKQUEUE_SCALE;
uint32_t sctp_cmt_on_off = 0;
uint32_t sctp_cmt_use_dac = 0;
-uint32_t sctp_max_retran_chunk = SCTPCTL_MAX_RETRAN_DEFAULT;
+uint32_t sctp_max_retran_chunk = SCTPCTL_MAX_RETRAN_CHUNK_DEFAULT;
uint32_t sctp_L2_abc_variable = 1;
@@ -486,18 +486,6 @@ SYSCTL_INT(_net_inet_sctp, OID_AUTO, strict_data_order, CTLFLAG_RW,
&sctp_strict_data_order, 0,
"Enforce strict data ordering, abort if control inside data");
-SYSCTL_INT(_net_inet_sctp, OID_AUTO, min_residual, CTLFLAG_RW,
- &sctp_min_residual, 0,
- SCTPCTL_MIN_RESIDUAL_DESC);
-
-
-SYSCTL_INT(_net_inet_sctp, OID_AUTO, max_retran_chunk, CTLFLAG_RW,
- &sctp_max_retran_chunk, 0,
- SCTPCTL_MAX_RETRAN_DESC);
-
-
-
-
SYSCTL_STRUCT(_net_inet_sctp, OID_AUTO, stats, CTLFLAG_RW,
&sctpstat, sctpstat,
"SCTP statistics (struct sctps_stat, netinet/sctp.h");
@@ -506,6 +494,14 @@ SYSCTL_PROC(_net_inet_sctp, OID_AUTO, assoclist, CTLFLAG_RD,
0, 0, sctp_assoclist,
"S,xassoc", "List of active SCTP associations");
+SYSCTL_INT(_net_inet_sctp, OID_AUTO, min_residual, CTLFLAG_RW,
+ &sctp_min_residual, 0,
+ SCTPCTL_MIN_RESIDUAL_DESC);
+
+SYSCTL_INT(_net_inet_sctp, OID_AUTO, max_retran_chunk, CTLFLAG_RW,
+ &sctp_max_retran_chunk, 0,
+ SCTPCTL_MAX_RETRAN_CHUNK_DESC);
+
#ifdef SCTP_DEBUG
SYSCTL_INT(_net_inet_sctp, OID_AUTO, debug, CTLFLAG_RW,
&sctp_debug_on, 0, "Configure debug output");
diff --git a/sys/netinet/sctp_sysctl.h b/sys/netinet/sctp_sysctl.h
index 0ad6cf5..9de9393 100644
--- a/sys/netinet/sctp_sysctl.h
+++ b/sys/netinet/sctp_sysctl.h
@@ -376,20 +376,19 @@ __FBSDID("$FreeBSD$");
#define SCTPCTL_STRICT_DATA_ORDER_MAX 1
#define SCTPCTL_STRICT_DATA_ORDER_DEFAULT 0
-/* min residual in in a data fragment leftover */
+/* min_residual: min residual in a data fragment leftover */
#define SCTPCTL_MIN_REDIDUAL 49
#define SCTPCTL_MIN_RESIDUAL_DESC "Minimum residual data chunk in second part of split"
#define SCTPCTL_MIN_RESIDUAL_MIN 20
#define SCTPCTL_MIN_RESIDUAL_MAX 65535
#define SCTPCTL_MIN_RESIDUAL_DEFAULT 1452
-/* min residual in in a data fragment leftover */
-#define SCTPCTL_MAX_RETRAN 50
-#define SCTPCTL_MAX_RETRAN_DESC "Maximum times a unlucky chunk can be retran'd before assoc abort "
-#define SCTPCTL_MAX_RETRAN_MIN 0
-#define SCTPCTL_MAX_RETRAN_MAX 65535
-#define SCTPCTL_MAX_RETRAN_DEFAULT 30
-
+/* max_retran_chunk: max chunk retransmissions */
+#define SCTPCTL_MAX_RETRAN_CHUNK 50
+#define SCTPCTL_MAX_RETRAN_CHUNK_DESC "Maximum times an unlucky chunk can be retran'd before assoc abort"
+#define SCTPCTL_MAX_RETRAN_CHUNK_MIN 0
+#define SCTPCTL_MAX_RETRAN_CHUNK_MAX 65535
+#define SCTPCTL_MAX_RETRAN_CHUNK_DEFAULT 30
#ifdef SCTP_DEBUG
@@ -516,8 +515,8 @@ __FBSDID("$FreeBSD$");
{ "add_more_on_output", CTLTYPE_INT }, \
{ "sys_resource", CTLTYPE_INT }, \
{ "asoc_resource", CTLTYPE_INT }, \
- { "max_retran_chunk", CTLTYPE_INT }, \
{ "min_residual", CTLTYPE_INT }, \
+ { "max_retran_chunk", CTLTYPE_INT }, \
}
#endif
diff --git a/sys/netinet/sctp_timer.c b/sys/netinet/sctp_timer.c
index a075e8e..05865a7 100644
--- a/sys/netinet/sctp_timer.c
+++ b/sys/netinet/sctp_timer.c
@@ -200,6 +200,7 @@ sctp_audit_retranmission_queue(struct sctp_association *asoc)
#endif /* SCTP_DEBUG */
}
+
int
sctp_threshold_management(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
struct sctp_nets *net, uint16_t threshold)
@@ -360,6 +361,7 @@ sctp_find_alternate_net(struct sctp_tcb *stcb,
(void)sa6_embedscope(sin6, ip6_use_defzone);
}
rtalloc_ign((struct route *)&alt->ro, 0UL);
+
if (sin6->sin6_family == AF_INET6) {
(void)sa6_recoverscope(sin6);
}
diff --git a/sys/netinet/sctp_uio.h b/sys/netinet/sctp_uio.h
index 506e9e9..67051ca 100644
--- a/sys/netinet/sctp_uio.h
+++ b/sys/netinet/sctp_uio.h
@@ -966,6 +966,7 @@ int
sctp_lower_sosend(struct socket *so,
struct sockaddr *addr,
struct uio *uio,
+
struct mbuf *top,
struct mbuf *control,
int flags,
diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c
index b3ef38a..2b8be65 100644
--- a/sys/netinet/sctp_usrreq.c
+++ b/sys/netinet/sctp_usrreq.c
@@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$");
#endif
#include <netinet/sctp_sysctl.h>
#include <netinet/sctp_output.h>
-#include <netinet/sctp_bsd_addr.h>
#include <netinet/sctp_uio.h>
#include <netinet/sctp_asconf.h>
#include <netinet/sctputil.h>
@@ -302,6 +301,7 @@ sctp_ctlinput(cmd, sa, vip)
struct sctphdr *sh;
uint32_t vrf_id;
+ /* FIX, for non-bsd is this right? */
vrf_id = SCTP_DEFAULT_VRFID;
if (sa->sa_family != AF_INET ||
((struct sockaddr_in *)sa)->sin_addr.s_addr == INADDR_ANY) {
@@ -375,7 +375,10 @@ sctp_getcred(SYSCTL_HANDLER_ARGS)
int error;
uint32_t vrf_id;
+
+ /* FIX, for non-bsd is this right? */
vrf_id = SCTP_DEFAULT_VRFID;
+
/*
* XXXRW: Other instances of getcred use SUSER_ALLOWJAIL, as socket
* visibility is scoped using cr_canseesocket(), which it is not
@@ -847,6 +850,7 @@ sctp_disconnect(struct socket *so)
return (0);
}
/* not reached */
+ printf("Not reached reached?\n");
} else {
/* UDP model does not support this */
SCTP_INP_RUNLOCK(inp);
@@ -889,6 +893,7 @@ sctp_shutdown(struct socket *so)
* made after an abort or something. Nothing to do
* now.
*/
+ SCTP_INP_RUNLOCK(inp);
return (0);
}
SCTP_TCB_LOCK(stcb);
@@ -1336,15 +1341,11 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
SCTP_PCB_FLAGS_UNBOUND) {
/* Bind a ephemeral port */
- SCTP_INP_WUNLOCK(inp);
error = sctp_inpcb_bind(so, NULL, p);
if (error) {
goto out_now;
}
- } else {
- SCTP_INP_WUNLOCK(inp);
}
-
/* FIX ME: do we want to pass in a vrf on the connect call? */
vrf_id = inp->def_vrf_id;
@@ -2251,6 +2252,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
if (hmaclist == NULL) {
/* no HMACs to return */
*optsize = sizeof(*shmac);
+ SCTP_INP_RUNLOCK(inp);
break;
}
/* is there room for all of the hmac ids? */
@@ -2382,7 +2384,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
printf("inp is NULL?\n");
return EINVAL;
}
- vrf_id = SCTP_DEFAULT_VRFID;
+ vrf_id = inp->def_vrf_id;
error = 0;
switch (optname) {
@@ -3555,8 +3557,6 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
SCTP_INP_RLOCK(inp);
stcb = LIST_FIRST(&inp->sctp_asoc_list);
- if (stcb)
- SCTP_TCB_UNLOCK(stcb);
SCTP_INP_RUNLOCK(inp);
} else {
/*
@@ -3568,6 +3568,8 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL);
if (stcb == NULL) {
SCTP_INP_DECR_REF(inp);
+ } else {
+ SCTP_TCB_LOCK(stcb);
}
}
if (stcb != NULL) {
@@ -3575,7 +3577,7 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
error = EALREADY;
goto out_now;
}
- vrf_id = SCTP_DEFAULT_VRFID;
+ vrf_id = inp->def_vrf_id;
/* We are GOOD to go */
stcb = sctp_aloc_assoc(inp, addr, 1, &error, 0, vrf_id);
if (stcb == NULL) {
@@ -3594,12 +3596,11 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
sctp_initialize_auth_params(inp, stcb);
sctp_send_initiate(inp, stcb);
+ SCTP_TCB_UNLOCK(stcb);
out_now:
if (create_lock_on)
SCTP_ASOC_CREATE_UNLOCK(inp);
- if (stcb)
- SCTP_TCB_UNLOCK(stcb);
SCTP_INP_DECR_REF(inp);
return error;
}
@@ -3686,6 +3687,7 @@ sctp_accept(struct socket *so, struct sockaddr **addr)
}
SCTP_INP_RLOCK(inp);
if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
+ SCTP_INP_RUNLOCK(inp);
return (ENOTSUP);
}
if (so->so_state & SS_ISDISCONNECTED) {
@@ -3808,11 +3810,10 @@ sctp_ingetaddr(struct socket *so, struct sockaddr **addr)
SCTP_TCB_UNLOCK(stcb);
goto notConn;
}
- vrf_id = SCTP_DEFAULT_VRFID;
-
+ vrf_id = inp->def_vrf_id;
sctp_ifa = sctp_source_address_selection(inp,
stcb,
- (struct route *)&net->ro,
+ (sctp_route_t *) & net->ro,
net, 0, vrf_id);
if (sctp_ifa) {
sin->sin_addr = sctp_ifa->address.sin.sin_addr;
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index ee8407a..977ecef 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -49,7 +49,6 @@ __FBSDID("$FreeBSD$");
#include <netinet/sctp_indata.h>/* for sctp_deliver_data() */
#include <netinet/sctp_auth.h>
#include <netinet/sctp_asconf.h>
-#include <netinet/sctp_bsd_addr.h>
#define NUMBER_OF_MTU_SIZES 18
@@ -3708,7 +3707,7 @@ sctp_print_address(struct sockaddr *sa)
char ip6buf[INET6_ADDRSTRLEN];
sin6 = (struct sockaddr_in6 *)sa;
- printf("IPv6 address: %s:%d scope:%u\n",
+ printf("IPv6 address: %s:port:%d scope:%u\n",
ip6_sprintf(ip6buf, &sin6->sin6_addr),
ntohs(sin6->sin6_port),
sin6->sin6_scope_id);
@@ -3780,7 +3779,7 @@ sctp_pull_off_control_to_new_inp(struct sctp_inpcb *old_inp,
struct sctp_queued_to_read *control, *nctl;
struct sctp_readhead tmp_queue;
struct mbuf *m;
- int error;
+ int error = 0;
old_so = old_inp->sctp_socket;
new_so = new_inp->sctp_socket;
@@ -4291,16 +4290,33 @@ sctp_find_ifa_by_addr(struct sockaddr *addr, uint32_t vrf_id, int holds_lock)
struct sctp_ifalist *hash_head;
uint32_t hash_of_addr;
+ if (holds_lock == 0)
+ SCTP_IPI_ADDR_LOCK();
+
vrf = sctp_find_vrf(vrf_id);
- if (vrf == NULL)
+ if (vrf == NULL) {
+ if (holds_lock == 0)
+ SCTP_IPI_ADDR_UNLOCK();
return (NULL);
-
+ }
hash_of_addr = sctp_get_ifa_hash_val(addr);
- if (holds_lock == 0)
- SCTP_IPI_ADDR_LOCK();
hash_head = &vrf->vrf_addr_hash[(hash_of_addr & vrf->vrf_hashmark)];
+ if (hash_head == NULL) {
+ printf("hash_of_addr:%x mask:%x table:%x - ",
+ (u_int)hash_of_addr, (u_int)vrf->vrf_hashmark,
+ (u_int)(hash_of_addr & vrf->vrf_hashmark));
+ sctp_print_address(addr);
+ printf("No such bucket for address\n");
+ if (holds_lock == 0)
+ SCTP_IPI_ADDR_UNLOCK();
+
+ return (NULL);
+ }
LIST_FOREACH(sctp_ifap, hash_head, next_bucket) {
+ if (sctp_ifap == NULL) {
+ panic("Huh LIST_FOREACH corrupt");
+ }
if (addr->sa_family != sctp_ifap->address.sa.sa_family)
continue;
if (addr->sa_family == AF_INET) {
diff --git a/sys/netinet6/sctp6_usrreq.c b/sys/netinet6/sctp6_usrreq.c
index b4f4d33..d08c1f7 100644
--- a/sys/netinet6/sctp6_usrreq.c
+++ b/sys/netinet6/sctp6_usrreq.c
@@ -59,9 +59,7 @@ int
sctp6_input(mp, offp, proto)
struct mbuf **mp;
int *offp;
-
int proto;
-
{
struct mbuf *m;
struct ip6_hdr *ip6;
@@ -69,14 +67,15 @@ sctp6_input(mp, offp, proto)
struct sctp_inpcb *in6p = NULL;
struct sctp_nets *net;
int refcount_up = 0;
- u_int32_t check, calc_check;
+ uint32_t check, calc_check, vrf_id;
struct inpcb *in6p_ip;
struct sctp_chunkhdr *ch;
int length, mlen, offset, iphlen;
- u_int8_t ecn_bits;
+ uint8_t ecn_bits;
struct sctp_tcb *stcb = NULL;
int off = *offp;
+ vrf_id = SCTP_DEFAULT_VRFID;
m = SCTP_HEADER_TO_CHAIN(*mp);
ip6 = mtod(m, struct ip6_hdr *);
@@ -138,7 +137,7 @@ sctp6_input(mp, offp, proto)
}
#endif
stcb = sctp_findassociation_addr(m, iphlen, offset - sizeof(*ch),
- sh, ch, &in6p, &net);
+ sh, ch, &in6p, &net, vrf_id);
/* in6p's ref-count increased && stcb locked */
if ((in6p) && (stcb)) {
sctp_send_packet_dropped(stcb, net, m, iphlen, 1);
@@ -159,7 +158,7 @@ sctp_skip_csum:
* IP/SCTP/first chunk header...
*/
stcb = sctp_findassociation_addr(m, iphlen, offset - sizeof(*ch),
- sh, ch, &in6p, &net);
+ sh, ch, &in6p, &net, vrf_id);
/* in6p's ref-count increased */
if (in6p == NULL) {
struct sctp_init_chunk *init_chk, chunk_buf;
@@ -173,7 +172,7 @@ sctp_skip_csum:
*/
init_chk = (struct sctp_init_chunk *)sctp_m_getptr(m,
iphlen + sizeof(*sh), sizeof(*init_chk),
- (u_int8_t *) & chunk_buf);
+ (uint8_t *) & chunk_buf);
sh->v_tag = init_chk->init.initiate_tag;
}
if (ch->chunk_type == SCTP_SHUTDOWN_ACK) {
@@ -248,7 +247,7 @@ sctp6_notify_mbuf(struct sctp_inpcb *inp,
struct sctp_tcb *stcb,
struct sctp_nets *net)
{
- u_int32_t nxtsz;
+ uint32_t nxtsz;
if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
(icmp6 == NULL) || (sh == NULL)) {
@@ -285,12 +284,12 @@ sctp6_notify_mbuf(struct sctp_inpcb *inp,
/* now off to subtract IP_DF flag if needed */
TAILQ_FOREACH(chk, &stcb->asoc.send_queue, sctp_next) {
- if ((u_int32_t) (chk->send_size + IP_HDR_SIZE) > nxtsz) {
+ if ((uint32_t) (chk->send_size + IP_HDR_SIZE) > nxtsz) {
chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
}
}
TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
- if ((u_int32_t) (chk->send_size + IP_HDR_SIZE) > nxtsz) {
+ if ((uint32_t) (chk->send_size + IP_HDR_SIZE) > nxtsz) {
/*
* For this guy we also mark for immediate
* resend since we sent to big of chunk
@@ -939,7 +938,7 @@ sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
return (ECONNRESET); /* I made the same as TCP since we are
* not setup? */
}
- vrf_id = SCTP_DEFAULT_VRFID;
+ vrf_id = inp->def_vrf_id;
SCTP_ASOC_CREATE_LOCK(inp);
SCTP_INP_RLOCK(inp);
if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
@@ -1095,9 +1094,8 @@ sctp6_getaddr(struct socket *so, struct sockaddr **addr)
/* punt */
goto notConn6;
}
- vrf_id = SCTP_DEFAULT_VRFID;
-
- sctp_ifa = sctp_source_address_selection(inp, stcb, (struct route *)&net->ro, net, 0, vrf_id);
+ vrf_id = inp->def_vrf_id;
+ sctp_ifa = sctp_source_address_selection(inp, stcb, (sctp_route_t *) & net->ro, net, 0, vrf_id);
if (sctp_ifa) {
sin6->sin6_addr = sctp_ifa->address.sin6.sin6_addr;
}
OpenPOWER on IntegriCloud