- 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
This commit is contained in:
rrs 2007-04-03 11:15:32 +00:00
parent c277843c22
commit ad3d567017
17 changed files with 388 additions and 222 deletions

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -4071,6 +4071,63 @@ sctp_cwnd_update(struct sctp_tcb *stcb,
}
}
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 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
}
}
}
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 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
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 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb,
* Now we must setup so we have a timer up for anyone with
* outstanding data.
*/
done_once = 0;
again:
j = 0;
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
@ -5423,12 +5494,16 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb,
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 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb,
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

View File

@ -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 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length,
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 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length,
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_input(i_pak, off)
* 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;

View File

@ -93,10 +93,8 @@ __FBSDID("$FreeBSD$");
#endif /* INET6 */
#include <netinet/ip_options.h>
#ifndef in6pcb
#define in6pcb inpcb
#endif
@ -269,6 +267,12 @@ typedef struct callout sctp_os_timer_t;
#define SCTP_SB_LIMIT_RCV(so) so->so_rcv.sb_hiwat
#define SCTP_SB_LIMIT_SND(so) so->so_snd.sb_hiwat
/*
* routes, output, etc.
*/
typedef struct route sctp_route_t;
/*
* SCTP AUTH
*/

View File

@ -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 @@ sctp_choose_boundspecific_inp(struct sctp_inpcb *inp,
/* 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 @@ sctp_choose_boundspecific_inp(struct sctp_inpcb *inp,
/* 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_choose_boundspecific_stcb(struct sctp_inpcb *inp,
/* 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_choose_boundspecific_stcb(struct sctp_inpcb *inp,
/* 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 @@ sctp_choose_boundall(struct sctp_inpcb *inp,
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 @@ sctp_choose_boundall(struct sctp_inpcb *inp,
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 @@ sctp_choose_boundall(struct sctp_inpcb *inp,
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 @@ sctp_choose_boundall(struct sctp_inpcb *inp,
continue;
}
}
atomic_add_int(&pass->refcount, 1);
return (pass);
atomic_add_int(&sifa->refcount, 1);
return (sifa);
}
/*
@ -2927,11 +2927,11 @@ sctp_choose_boundall(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_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 @@ sctp_choose_boundall(struct sctp_inpcb *inp,
continue;
}
}
atomic_add_int(&pass->refcount, 1);
return (pass);
atomic_add_int(&sifa->refcount, 1);
return (sifa);
}
}
/*
@ -2957,7 +2957,7 @@ sctp_choose_boundall(struct sctp_inpcb *inp,
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;

View File

@ -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);

View File

@ -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 @@ sctp_del_addr_from_vrf(uint32_t vrfid, struct sockaddr *addr,
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,

View File

@ -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 *,

View File

@ -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");

View File

@ -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

View File

@ -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);
}

View File

@ -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,

View File

@ -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;

View File

@ -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;
vrf = sctp_find_vrf(vrf_id);
if (vrf == NULL)
return (NULL);
hash_of_addr = sctp_get_ifa_hash_val(addr);
if (holds_lock == 0)
SCTP_IPI_ADDR_LOCK();
vrf = sctp_find_vrf(vrf_id);
if (vrf == NULL) {
if (holds_lock == 0)
SCTP_IPI_ADDR_UNLOCK();
return (NULL);
}
hash_of_addr = sctp_get_ifa_hash_val(addr);
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) {

View File

@ -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 @@ sctp6_input(mp, offp, proto)
* 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 @@ sctp6_input(mp, offp, proto)
*/
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;
}