diff options
-rw-r--r-- | sys/netinet/sctp_asconf.c | 34 | ||||
-rw-r--r-- | sys/netinet/sctp_bsd_addr.h | 9 | ||||
-rw-r--r-- | sys/netinet/sctp_constants.h | 20 | ||||
-rw-r--r-- | sys/netinet/sctp_indata.c | 106 | ||||
-rw-r--r-- | sys/netinet/sctp_input.c | 60 | ||||
-rw-r--r-- | sys/netinet/sctp_os_bsd.h | 8 | ||||
-rw-r--r-- | sys/netinet/sctp_output.c | 188 | ||||
-rw-r--r-- | sys/netinet/sctp_output.h | 2 | ||||
-rw-r--r-- | sys/netinet/sctp_pcb.c | 49 | ||||
-rw-r--r-- | sys/netinet/sctp_pcb.h | 5 | ||||
-rw-r--r-- | sys/netinet/sctp_sysctl.c | 22 | ||||
-rw-r--r-- | sys/netinet/sctp_sysctl.h | 17 | ||||
-rw-r--r-- | sys/netinet/sctp_timer.c | 2 | ||||
-rw-r--r-- | sys/netinet/sctp_uio.h | 1 | ||||
-rw-r--r-- | sys/netinet/sctp_usrreq.c | 29 | ||||
-rw-r--r-- | sys/netinet/sctputil.c | 30 | ||||
-rw-r--r-- | sys/netinet6/sctp6_usrreq.c | 26 |
17 files changed, 387 insertions, 221 deletions
diff --git a/sys/netinet/sctp_asconf.c b/sys/netinet/sctp_asconf.c index d4f088bbc2f2..5eaa7cd6f92a 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 0752ea344d4a..5a4216f0f707 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 97b8c870b77a..9cd54321d574 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 462013e8b311..4d142f713cf0 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 b5bbb3495bf3..afb85909265f 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 e74ccfa1250f..81e028ca681b 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 416ab64c51cb..ccfd19799f79 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 5daa406d9ed8..bebce434efb1 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 ac9c1968f46a..19dde5de7e5e 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 34a8452bcf08..022a359d73a6 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 c2aac0d02a9d..943399e2f9af 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 0ad6cf59f29e..9de9393a4bbf 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 a075e8ecceef..05865a7c985f 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 506e9e926f7c..67051ca8e633 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 b3ef38aa5eff..2b8be650cd09 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 ee8407aec25b..977ecef1b6c5 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 b4f4d33d693a..d08c1f75ad1b 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; } |