- Fixed 1-2-1 model to not worry about associd in sockopts

- Fixed RTOinfo for bounding.
- Fixed connect() to return ECONNREFUSED when an ABORT is received.
- Added comments to direct Static Analysis not to look at some things
  it does not understand (comments are /* sa_ignore XXXXX */)
- Bind when colliding was broken, missing not_found = 1 before
  checking to see if the port was in use caused endless bind loop.
- Cookie life needs to be in milliseconds to conform to socket api.
- Cookie life is not supposed to change if its 0, On the assoc
  level set we changed it to 0 opps.
- Two more static analysis issues identified by the cisco
  tool. Null checks needed.
- An issue for sendfile(). Need to validate the correct
  input argument.
- When sending failed due to a no route to host, we leaked
  the mbuf chain failing to call m_freem().
- Fix #ifdef issue for getting hash block len when HAVE_SHA2 is NOT defined
Reviewed by:	gnn
This commit is contained in:
Randall Stewart 2007-05-17 12:16:24 +00:00
parent 9cb24de6ed
commit 3c503c28da
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=169655
14 changed files with 175 additions and 103 deletions

View File

@ -116,7 +116,8 @@ struct sctp_paramhdr {
/* authentication support */
#define SCTP_PEER_AUTH_CHUNKS 0x00000102
#define SCTP_LOCAL_AUTH_CHUNKS 0x00000103
#define SCTP_GET_ASSOC_NUMBER 0x00000104 /* ro */
#define SCTP_GET_ASSOC_ID_LIST 0x00000105 /* ro */
/*
* user socket options: BSD implementation specific
@ -153,9 +154,8 @@ struct sctp_paramhdr {
/* read only */
#define SCTP_GET_SNDBUF_USE 0x00001101
#define SCTP_GET_STAT_LOG 0x00001103
#define SCTP_GET_ASOC_ID_LIST 0x00001104 /* ro */
#define SCTP_PCB_STATUS 0x00001105
#define SCTP_GET_NONCE_VALUES 0x00001106
#define SCTP_PCB_STATUS 0x00001104
#define SCTP_GET_NONCE_VALUES 0x00001105
/* Special hook for dynamically setting primary for all assoc's,
* this is a write only option that requires root privledge.

View File

@ -286,8 +286,10 @@ sctp_process_asconf_add_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph,
m_reply =
sctp_asconf_success_response(aph->correlation_id);
}
sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_ASCONF + SCTP_LOC_1);
sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, NULL);
sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb,
NULL, SCTP_FROM_SCTP_ASCONF + SCTP_LOC_1);
sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep,
stcb, NULL);
}
return m_reply;
@ -864,7 +866,8 @@ sctp_asconf_cleanup(struct sctp_tcb *stcb, struct sctp_nets *net)
/*
* clear out any existing asconfs going out
*/
sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_ASCONF + SCTP_LOC_2);
sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net,
SCTP_FROM_SCTP_ASCONF + SCTP_LOC_2);
stcb->asoc.asconf_seq_out++;
/* remove the old ASCONF on our outbound queue */
sctp_toss_old_asconf(stcb);
@ -1328,7 +1331,8 @@ sctp_handle_asconf_ack(struct mbuf *m, int offset,
return;
}
/* stop our timer */
sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_ASCONF + SCTP_LOC_3);
sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net,
SCTP_FROM_SCTP_ASCONF + SCTP_LOC_3);
/* process the ASCONF-ACK contents */
ack_length = ntohs(cp->ch.chunk_length) -
@ -1664,7 +1668,8 @@ sctp_iterator_ep_end(struct sctp_inpcb *inp, void *ptr, uint32_t val)
LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) {
ifa = l->ifa;
if (l->action == SCTP_ADD_IP_ADDRESS) {
LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
LIST_FOREACH(laddr, &inp->sctp_addr_list,
sctp_nxt_addr) {
if (laddr->ifa == ifa) {
laddr->action = 0;
break;
@ -1821,7 +1826,6 @@ sctp_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
/* does the peer do asconf? */
if (stcb->asoc.peer_supports_asconf) {
/* queue an asconf for this addr */
status = sctp_asconf_queue_add(stcb, ifa, type);
/*
* if queued ok, and in correct state, set
@ -2175,7 +2179,8 @@ sctp_compose_asconf(struct sctp_tcb *stcb, int *retlen)
}
/* chain it all together */
SCTP_BUF_NEXT(m_asconf_chk) = m_asconf;
*retlen = acp->ch.chunk_length = ntohs(SCTP_BUF_LEN(m_asconf_chk) + SCTP_BUF_LEN(m_asconf));
*retlen = SCTP_BUF_LEN(m_asconf_chk) + SCTP_BUF_LEN(m_asconf);
acp->ch.chunk_length = ntohs(*retlen);
/* update "sent" flag */
stcb->asoc.asconf_sent++;
@ -2537,7 +2542,8 @@ sctp_check_address_list(struct sctp_tcb *stcb, struct mbuf *m, int offset,
* sctp_bindx() support
*/
uint32_t
sctp_addr_mgmt_ep_sa(struct sctp_inpcb *inp, struct sockaddr *sa, uint32_t type, uint32_t vrf_id)
sctp_addr_mgmt_ep_sa(struct sctp_inpcb *inp, struct sockaddr *sa,
uint32_t type, uint32_t vrf_id)
{
struct sctp_ifa *ifa;
@ -2559,11 +2565,13 @@ sctp_addr_mgmt_ep_sa(struct sctp_inpcb *inp, struct sockaddr *sa, uint32_t type,
struct sctp_laddr *wi;
SCTP_MALLOC(asc, struct sctp_asconf_iterator *,
sizeof(struct sctp_asconf_iterator), "SCTP_ASCONF_ITERATOR");
sizeof(struct sctp_asconf_iterator),
"SCTP_ASCONF_ITERATOR");
if (asc == NULL) {
return (ENOMEM);
}
wi = SCTP_ZONE_GET(sctppcbinfo.ipi_zone_laddr, struct sctp_laddr);
wi = SCTP_ZONE_GET(sctppcbinfo.ipi_zone_laddr,
struct sctp_laddr);
if (wi == NULL) {
SCTP_FREE(asc);
return (ENOMEM);
@ -2573,7 +2581,12 @@ sctp_addr_mgmt_ep_sa(struct sctp_inpcb *inp, struct sockaddr *sa, uint32_t type,
} else if (type == SCTP_DEL_IP_ADDRESS) {
struct sctp_laddr *laddr;
LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
if (inp->laddr_count < 2) {
/* can't delete the last local address */
return (EINVAL);
}
LIST_FOREACH(laddr, &inp->sctp_addr_list,
sctp_nxt_addr) {
if (ifa == laddr->ifa) {
/* Mark in the delete */
laddr->action = type;
@ -2591,7 +2604,8 @@ sctp_addr_mgmt_ep_sa(struct sctp_inpcb *inp, struct sockaddr *sa, uint32_t type,
sctp_iterator_stcb,
sctp_iterator_ep_end,
SCTP_PCB_ANY_FLAGS,
SCTP_PCB_ANY_FEATURES, SCTP_ASOC_ANY_STATE, (void *)asc, 0,
SCTP_PCB_ANY_FEATURES,
SCTP_ASOC_ANY_STATE, (void *)asc, 0,
sctp_iterator_end, inp, 0);
} else {
/* invalid address! */

View File

@ -837,8 +837,8 @@ sctp_get_hmac_block_len(uint16_t hmac_algo)
case SCTP_AUTH_HMAC_ID_MD5:
#ifdef HAVE_SHA224
case SCTP_AUTH_HMAC_ID_SHA224:
return (64);
#endif
return (64);
#ifdef HAVE_SHA2
case SCTP_AUTH_HMAC_ID_SHA256:
return (64);

View File

@ -490,8 +490,8 @@ __FBSDID("$FreeBSD$");
*/
#define SCTP_DEFAULT_MBUFS_IN_CHAIN 5
/* How long a cookie lives in seconds */
#define SCTP_DEFAULT_COOKIE_LIFE 60
/* How long a cookie lives in milli-seconds */
#define SCTP_DEFAULT_COOKIE_LIFE 60000
/* resource limit of streams */
#define MAX_SCTP_STREAMS 2048

View File

@ -389,6 +389,7 @@ sctp_service_reassembly(struct sctp_tcb *stcb, struct sctp_association *asoc)
/* Now free the address and data */
sctp_free_remote_addr(chk->whoTo);
sctp_free_a_chunk(stcb, chk);
/* sa_ignore FREED_MEMORY */
chk = TAILQ_FIRST(&asoc->reasmqueue);
}
return;
@ -515,6 +516,7 @@ sctp_service_reassembly(struct sctp_tcb *stcb, struct sctp_association *asoc)
}
break;
}
/* sa_ignore FREED_MEMORY */
chk = TAILQ_FIRST(&asoc->reasmqueue);
} while (chk);
}
@ -2107,6 +2109,7 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
sctp_reset_in_stream(stcb, liste->number_entries, liste->req.list_of_streams);
TAILQ_REMOVE(&asoc->resetHead, liste, next_resp);
SCTP_FREE(liste);
/* sa_ignore FREED_MEMORY */
liste = TAILQ_FIRST(&asoc->resetHead);
ctl = TAILQ_FIRST(&asoc->pending_reply_queue);
if (ctl && (liste == NULL)) {
@ -3458,6 +3461,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
*/
tp1->no_fr_allowed = 1;
alt = tp1->whoTo;
/* sa_ignore NO_NULL_CHK */
alt = sctp_find_alternate_net(stcb, alt, 1);
if (alt == NULL) {
alt = tp1->whoTo;
@ -3550,6 +3554,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
if (alt != tp1->whoTo) {
/* yes, there is an alternate. */
sctp_free_remote_addr(tp1->whoTo);
/* sa_ignore FREED_MEMORY */
tp1->whoTo = alt;
atomic_add_int(&alt->ref_count, 1);
}
@ -4443,6 +4448,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
* Find first chunk that was used with window probe
* and clear the sent
*/
/* sa_ignore FREED_MEMORY */
TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
if (tp1->window_probe) {
/* move back to data send queue */

View File

@ -224,6 +224,7 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb,
sp, stcb);
sctp_free_a_strmoq(stcb, sp);
/* sa_ignore FREED_MEMORY */
sp = TAILQ_FIRST(&outs->outqueue);
}
}
@ -294,6 +295,7 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb,
* removed). Up front when the INIT arrives we will discard it if it
* is a restart and new addresses have been added.
*/
/* sa_ignore MEMLEAK */
return (0);
}
@ -1921,7 +1923,7 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
*/
(void)SCTP_GETTIME_TIMEVAL(&now);
/* Expire time is in Ticks, so we convert to seconds */
time_expires.tv_sec = cookie->time_entered.tv_sec + cookie->cookie_life;
time_expires.tv_sec = cookie->time_entered.tv_sec + TICKS_TO_SEC(cookie->cookie_life);
time_expires.tv_usec = cookie->time_entered.tv_usec;
if (timevalcmp(&now, &time_expires, >)) {
/* cookie is stale! */
@ -4485,6 +4487,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset,
}
if (IS_SCTP_CONTROL(ch)) {
/* process the control portion of the SCTP packet */
/* sa_ignore NO_NULL_CHK */
stcb = sctp_process_control(m, iphlen, &offset, length, sh, ch,
inp, stcb, &net, &fwd_tsn_seen, vrf_id, table_id);
if (stcb) {
@ -4864,6 +4867,7 @@ sctp_input(i_pak, off)
ecn_bits = ip->ip_tos;
/* sa_ignore NO_NULL_CHK */
sctp_common_input_processing(&m, iphlen, offset, length, sh, ch,
inp, stcb, net, ecn_bits, vrf_id,
table_id);

View File

@ -3445,6 +3445,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
}
}
}
sctp_m_freem(m);
return (EHOSTUNREACH);
}
if (ro != &iproute) {
@ -4282,10 +4283,12 @@ sctp_arethere_unrecognized_parameters(struct mbuf *in_initpkt,
l_len = sizeof(struct ip6_hdr) + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);
l_len += (2 * sizeof(struct sctp_paramhdr));
op_err = sctp_get_mbuf_for_msg(l_len, 0, M_DONTWAIT, 1, MT_DATA);
SCTP_BUF_LEN(op_err) = 0;
SCTP_BUF_RESV_UF(op_err, sizeof(struct ip6_hdr));
SCTP_BUF_RESV_UF(op_err, sizeof(struct sctphdr));
SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr));
if (op_err) {
SCTP_BUF_LEN(op_err) = 0;
SCTP_BUF_RESV_UF(op_err, sizeof(struct ip6_hdr));
SCTP_BUF_RESV_UF(op_err, sizeof(struct sctphdr));
SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr));
}
}
if ((op_err) && phdr) {
struct sctp_paramhdr s;
@ -6112,6 +6115,7 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb, struct sctp_nets *net,
SCTP_TCB_LOCK_ASSERT(stcb);
asoc = &stcb->asoc;
one_more_time:
/* sa_ignore FREED_MEMORY */
sp = TAILQ_FIRST(&strq->outqueue);
if (sp == NULL) {
*locked = 0;
@ -10574,7 +10578,7 @@ sctp_lower_sosend(struct socket *so,
error = EFAULT;
goto out_unlocked;
}
if ((uio == NULL) && (top == NULL)) {
if ((uio == NULL) && (i_pak == NULL)) {
return (EINVAL);
}
atomic_add_int(&inp->total_sends, 1);

View File

@ -1860,7 +1860,7 @@ sctp_inpcb_alloc(struct socket *so)
sctp_timer_start(SCTP_TIMER_TYPE_NEWCOOKIE, inp, NULL, NULL);
/* How long is a cookie good for ? */
m->def_cookie_life = sctp_valid_cookie_life_default;
m->def_cookie_life = MSEC_TO_TICKS(sctp_valid_cookie_life_default);
/*
* Initialize authentication parameters
*/
@ -1996,7 +1996,6 @@ sctp_isport_inuse(struct sctp_inpcb *inp, uint16_t lport, uint32_t vrf_id)
head = &sctppcbinfo.sctp_ephash[SCTP_PCBHASH_ALLADDR(lport,
sctppcbinfo.hashmark)];
LIST_FOREACH(t_inp, head, sctp_hash) {
if (t_inp->sctp_lport != lport) {
continue;
@ -2106,9 +2105,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
return (EAFNOSUPPORT);
}
}
/*
* Setup a vrf_id to be the default for the non-bind-all case.
*/
/* Setup a vrf_id to be the default for the non-bind-all case. */
vrf_id = inp->def_vrf_id;
SCTP_INP_INFO_WLOCK();
@ -2210,11 +2207,12 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
if (port_attempt < IPPORT_RESERVED) {
port_attempt += IPPORT_RESERVED;
}
not_found = 1;
vrf_id = inp->def_vrf_id;
if (sctp_isport_inuse(inp, htons(port_attempt), vrf_id) == 1) {
if (sctp_isport_inuse(inp, htons(port_attempt),
vrf_id) == 1) {
/* got a port we can use */
not_found = 0;
break;
}
if (not_found == 1) {
/* We can use this port */
@ -2224,17 +2222,19 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
/* try upper half */
next_half:
port_attempt = ((port_guess >> 16) & 0x0000ffff);
if (port_attempt == 0) {
goto last_try;
}
if (port_attempt < IPPORT_RESERVED) {
port_attempt += IPPORT_RESERVED;
}
not_found = 1;
vrf_id = inp->def_vrf_id;
if (sctp_isport_inuse(inp, htons(port_attempt), vrf_id) == 1) {
if (sctp_isport_inuse(inp, htons(port_attempt),
vrf_id) == 1) {
/* got a port we can use */
not_found = 0;
break;
}
if (not_found == 1) {
/* We can use this port */
@ -2252,11 +2252,11 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
if (port_attempt < IPPORT_RESERVED) {
port_attempt += IPPORT_RESERVED;
}
not_found = 1;
vrf_id = inp->def_vrf_id;
if (sctp_isport_inuse(inp, htons(port_attempt), vrf_id) == 1) {
/* got a port we can use */
not_found = 0;
break;
}
if (not_found == 1) {
/* We can use this port */
@ -2322,7 +2322,8 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
* zero out the port to find the address! yuck! can't do
* this earlier since need port for sctp_pcb_findep()
*/
ifa = sctp_find_ifa_by_addr((struct sockaddr *)&store_sa, vrf_id, 0);
ifa = sctp_find_ifa_by_addr((struct sockaddr *)&store_sa,
vrf_id, 0);
if (ifa == NULL) {
/* Can't find an interface with that address */
SCTP_INP_WUNLOCK(inp);
@ -2340,15 +2341,12 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
}
/* we're not bound all */
inp->sctp_flags &= ~SCTP_PCB_FLAGS_BOUNDALL;
/* set the automatic addr changes from kernel flag */
/* allow bindx() to send ASCONF's for binding changes */
sctp_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF);
/* set the automatic addr changes from kernel flag */
if (sctp_auto_asconf == 0) {
sctp_feature_off(inp, SCTP_PCB_FLAGS_AUTO_ASCONF);
} else {
/*
* allow bindx() to send ASCONF's for binding
* changes
*/
sctp_feature_on(inp, SCTP_PCB_FLAGS_AUTO_ASCONF);
}
@ -2752,6 +2750,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
(void)SCTP_OS_TIMER_STOP(&inp->sctp_ep.signature_change.timer);
inp->sctp_ep.signature_change.type = SCTP_TIMER_TYPE_NONE;
/* Clear the read queue */
/* sa_ignore FREED_MEMORY */
while ((sq = TAILQ_FIRST(&inp->read_queue)) != NULL) {
/* Its only abandoned if it had data left */
if (sq->length)
@ -2813,6 +2812,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
while (shared_key) {
LIST_REMOVE(shared_key, next);
sctp_free_sharedkey(shared_key);
/* sa_ignore FREED_MEMORY */
shared_key = LIST_FIRST(&inp->sctp_ep.shared_keys);
}
@ -3885,10 +3885,12 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
/* Free the zone stuff */
SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_strmoq, sp);
SCTP_DECR_STRMOQ_COUNT();
/* sa_ignore FREED_MEMORY */
sp = TAILQ_FIRST(&outs->outqueue);
}
}
/* sa_ignore FREED_MEMORY */
while ((liste = TAILQ_FIRST(&asoc->resetHead)) != NULL) {
TAILQ_REMOVE(&asoc->resetHead, liste, next_resp);
SCTP_FREE(liste);
@ -3907,6 +3909,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
/* Free the ctl entry */
SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_readq, sq);
SCTP_DECR_READQ_COUNT();
/* sa_ignore FREED_MEMORY */
sq = TAILQ_FIRST(&asoc->pending_reply_queue);
}
@ -3922,6 +3925,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
SCTP_DECR_CHK_COUNT();
atomic_subtract_int(&sctppcbinfo.ipi_free_chunks, 1);
asoc->free_chunk_cnt--;
/* sa_ignore FREED_MEMORY */
chk = TAILQ_FIRST(&asoc->free_chunks);
}
/* pending send queue SHOULD be empty */
@ -3937,6 +3941,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
sctp_free_remote_addr(chk->whoTo);
SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_chunk, chk);
SCTP_DECR_CHK_COUNT();
/* sa_ignore FREED_MEMORY */
chk = TAILQ_FIRST(&asoc->send_queue);
}
}
@ -3959,6 +3964,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
sctp_free_remote_addr(chk->whoTo);
SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_chunk, chk);
SCTP_DECR_CHK_COUNT();
/* sa_ignore FREED_MEMORY */
chk = TAILQ_FIRST(&asoc->sent_queue);
}
}
@ -3981,6 +3987,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
sctp_free_remote_addr(chk->whoTo);
SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_chunk, chk);
SCTP_DECR_CHK_COUNT();
/* sa_ignore FREED_MEMORY */
chk = TAILQ_FIRST(&asoc->control_send_queue);
}
}
@ -4002,6 +4009,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
ccnt++;
SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_chunk, chk);
SCTP_DECR_CHK_COUNT();
/* sa_ignore FREED_MEMORY */
chk = TAILQ_FIRST(&asoc->reasmqueue);
}
}
@ -4052,6 +4060,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
}
asoc->streamincnt = 0;
while (!TAILQ_EMPTY(&asoc->nets)) {
/* sa_ignore FREED_MEMORY */
net = TAILQ_FIRST(&asoc->nets);
/* pull from list */
if ((sctppcbinfo.ipi_count_raddr == 0) || (prev == net)) {
@ -4066,12 +4075,14 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
}
while (!SCTP_LIST_EMPTY(&asoc->sctp_restricted_addrs)) {
/* sa_ignore FREED_MEMORY */
laddr = LIST_FIRST(&asoc->sctp_restricted_addrs);
sctp_remove_laddr(laddr);
}
/* pending asconf (address) parameters */
while (!TAILQ_EMPTY(&asoc->asconf_queue)) {
/* sa_ignore FREED_MEMORY */
aparam = TAILQ_FIRST(&asoc->asconf_queue);
TAILQ_REMOVE(&asoc->asconf_queue, aparam, next);
SCTP_FREE(aparam);
@ -4097,6 +4108,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
while (shared_key) {
LIST_REMOVE(shared_key, next);
sctp_free_sharedkey(shared_key);
/* sa_ignore FREED_MEMORY */
shared_key = LIST_FIRST(&asoc->shared_keys);
}
@ -5612,5 +5624,6 @@ sctp_initiate_iterator(inp_func inpf,
sctp_timer_start(SCTP_TIMER_TYPE_ITERATOR, (struct sctp_inpcb *)it,
NULL, NULL);
#endif
/* sa_ignore MEMLEAK {memory is put on the tailq for the iterator} */
return (0);
}

View File

@ -195,6 +195,12 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS)
xinpcb.total_recvs = inp->total_recvs;
xinpcb.total_nospaces = inp->total_nospaces;
xinpcb.fragmentation_point = inp->sctp_frag_point;
if (inp->sctp_socket != NULL) {
sotoxsocket(inp->sctp_socket, &xinpcb.xsocket);
} else {
bzero(&xinpcb.xsocket, sizeof xinpcb.xsocket);
xinpcb.xsocket.xso_protocol = IPPROTO_SCTP;
}
SCTP_INP_INCR_REF(inp);
SCTP_INP_RUNLOCK(inp);
SCTP_INP_INFO_RUNLOCK();
@ -407,7 +413,7 @@ SYSCTL_UINT(_net_inet_sctp, OID_AUTO, init_rto_max, CTLFLAG_RW,
SYSCTL_UINT(_net_inet_sctp, OID_AUTO, valid_cookie_life, CTLFLAG_RW,
&sctp_valid_cookie_life_default, 0,
"Default cookie lifetime in sec");
"Default cookie lifetime in ticks");
SYSCTL_UINT(_net_inet_sctp, OID_AUTO, init_rtx_max, CTLFLAG_RW,
&sctp_init_rtx_max_default, 0,

View File

@ -346,6 +346,7 @@ sctp_find_alternate_net(struct sctp_tcb *stcb,
if (
((alt->dest_state & SCTP_ADDR_REACHABLE) == SCTP_ADDR_REACHABLE) &&
(alt->ro.ro_rt != NULL) &&
/* sa_ignore NO_NULL_CHK */
(!(alt->dest_state & SCTP_ADDR_UNCONFIRMED))
) {
/* Found a reachable address */
@ -368,6 +369,7 @@ sctp_find_alternate_net(struct sctp_tcb *stcb,
}
alt = TAILQ_FIRST(&stcb->asoc.nets);
}
/* sa_ignore NO_NULL_CHK */
if ((!(alt->dest_state & SCTP_ADDR_UNCONFIRMED)) &&
(alt != net)) {
/* Found an alternate address */

View File

@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/socketvar.h>
#include <netinet/in.h>
typedef uint32_t sctp_assoc_t;
@ -528,12 +529,8 @@ struct sctp_assoc_value {
uint32_t assoc_value;
};
#define MAX_ASOC_IDS_RET 255
struct sctp_assoc_ids {
uint16_t asls_assoc_start; /* array of index's start at 0 */
uint8_t asls_numb_present;
uint8_t asls_more_to_get;
sctp_assoc_t asls_assoc_id[MAX_ASOC_IDS_RET];
sctp_assoc_t gaids_assoc_id[0];
};
struct sctp_cwnd_args {
@ -934,6 +931,7 @@ struct xsctp_inpcb {
uint32_t total_recvs;
uint32_t total_nospaces;
uint32_t fragmentation_point;
struct xsocket xsocket;
/* add more endpoint specific data here */
};

View File

@ -1364,18 +1364,21 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
soisconnecting(so);
}
out_now:
if (creat_lock_on)
if (creat_lock_on) {
SCTP_ASOC_CREATE_UNLOCK(inp);
}
SCTP_INP_DECR_REF(inp);
return error;
}
#define SCTP_FIND_STCB(inp, stcb, assoc_id) { \
if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) { \
if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||\
(inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { \
SCTP_INP_RLOCK(inp); \
stcb = LIST_FIRST(&inp->sctp_asoc_list); \
if (stcb) \
if (stcb) { \
SCTP_TCB_LOCK(stcb); \
} \
SCTP_INP_RUNLOCK(inp); \
} else if (assoc_id != 0) { \
stcb = sctp_findassociation_ep_asocid(inp, assoc_id, 1); \
@ -1534,49 +1537,41 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
*optsize = sizeof(*av);
}
break;
case SCTP_GET_ASOC_ID_LIST:
case SCTP_GET_ASSOC_NUMBER:
{
struct sctp_assoc_ids *ids;
int cnt, at;
uint16_t orig;
uint32_t *value, cnt;
SCTP_CHECK_AND_CAST(ids, optval, struct sctp_assoc_ids, *optsize);
SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
cnt = 0;
SCTP_INP_RLOCK(inp);
stcb = LIST_FIRST(&inp->sctp_asoc_list);
if (stcb == NULL) {
none_out_now:
ids->asls_numb_present = 0;
ids->asls_more_to_get = 0;
SCTP_INP_RUNLOCK(inp);
break;
LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
cnt++;
}
orig = ids->asls_assoc_start;
stcb = LIST_FIRST(&inp->sctp_asoc_list);
while (orig) {
stcb = LIST_NEXT(stcb, sctp_tcblist);
orig--;
cnt--;
if (stcb == NULL)
goto none_out_now;
}
if (stcb == NULL)
goto none_out_now;
SCTP_INP_RUNLOCK(inp);
*value = cnt;
*optsize = sizeof(uint32_t);
}
break;
case SCTP_GET_ASSOC_ID_LIST:
{
struct sctp_assoc_ids *ids;
unsigned int at, limit;
SCTP_CHECK_AND_CAST(ids, optval, struct sctp_assoc_ids, *optsize);
at = 0;
ids->asls_numb_present = 0;
ids->asls_more_to_get = 1;
while (at < MAX_ASOC_IDS_RET) {
ids->asls_assoc_id[at] = sctp_get_associd(stcb);
at++;
ids->asls_numb_present++;
stcb = LIST_NEXT(stcb, sctp_tcblist);
if (stcb == NULL) {
ids->asls_more_to_get = 0;
limit = *optsize / sizeof(sctp_assoc_t);
SCTP_INP_RLOCK(inp);
LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
if (at < limit) {
ids->gaids_assoc_id[at++] = sctp_get_associd(stcb);
} else {
error = EINVAL;
break;
}
}
SCTP_INP_RUNLOCK(inp);
*optsize = at * sizeof(sctp_assoc_t);
}
break;
case SCTP_CONTEXT:
@ -1896,8 +1891,9 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
sas = (struct sockaddr_storage *)&saddr->addr[0];
limit = *optsize - sizeof(sctp_assoc_t);
actual = sctp_fill_up_addresses(inp, stcb, limit, sas);
if (stcb)
if (stcb) {
SCTP_TCB_UNLOCK(stcb);
}
*optsize = sizeof(struct sockaddr_storage) + actual;
}
break;
@ -2143,7 +2139,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
sasoc->sasoc_number_peer_destinations = stcb->asoc.numnets;
sasoc->sasoc_peer_rwnd = stcb->asoc.peers_rwnd;
sasoc->sasoc_local_rwnd = stcb->asoc.my_rwnd;
sasoc->sasoc_cookie_life = stcb->asoc.cookie_life;
sasoc->sasoc_cookie_life = TICKS_TO_MSEC(stcb->asoc.cookie_life);
sasoc->sasoc_sack_delay = stcb->asoc.delayed_ack;
sasoc->sasoc_sack_freq = stcb->asoc.sack_freq;
SCTP_TCB_UNLOCK(stcb);
@ -2153,7 +2149,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
sasoc->sasoc_number_peer_destinations = 0;
sasoc->sasoc_peer_rwnd = 0;
sasoc->sasoc_local_rwnd = sbspace(&inp->sctp_socket->so_rcv);
sasoc->sasoc_cookie_life = inp->sctp_ep.def_cookie_life;
sasoc->sasoc_cookie_life = TICKS_TO_MSEC(inp->sctp_ep.def_cookie_life);
sasoc->sasoc_sack_delay = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]);
sasoc->sasoc_sack_freq = inp->sctp_ep.sctp_sack_freq;
SCTP_INP_RUNLOCK(inp);
@ -3146,31 +3142,53 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
case SCTP_RTOINFO:
{
struct sctp_rtoinfo *srto;
uint32_t new_init, new_min, new_max;
SCTP_CHECK_AND_CAST(srto, optval, struct sctp_rtoinfo, optsize);
SCTP_FIND_STCB(inp, stcb, srto->srto_assoc_id);
if (stcb) {
/* Set in ms we hope :-) */
if (srto->srto_initial)
stcb->asoc.initial_rto = srto->srto_initial;
new_init = srto->srto_initial;
else
new_init = stcb->asoc.initial_rto;
if (srto->srto_max)
stcb->asoc.maxrto = srto->srto_max;
new_max = srto->srto_max;
else
new_max = stcb->asoc.maxrto;
if (srto->srto_min)
stcb->asoc.minrto = srto->srto_min;
new_min = srto->srto_min;
else
new_min = stcb->asoc.minrto;
if ((new_min <= new_init) && (new_init <= new_max)) {
stcb->asoc.initial_rto = new_init;
stcb->asoc.maxrto = new_max;
stcb->asoc.minrto = new_min;
} else {
error = EDOM;
}
SCTP_TCB_UNLOCK(stcb);
} else {
SCTP_INP_WLOCK(inp);
/*
* If we have a null asoc, its default for
* the endpoint
*/
if (srto->srto_initial)
inp->sctp_ep.initial_rto = srto->srto_initial;
new_init = srto->srto_initial;
else
new_init = inp->sctp_ep.initial_rto;
if (srto->srto_max)
inp->sctp_ep.sctp_maxrto = srto->srto_max;
new_max = srto->srto_max;
else
new_max = inp->sctp_ep.sctp_maxrto;
if (srto->srto_min)
inp->sctp_ep.sctp_minrto = srto->srto_min;
new_min = srto->srto_min;
else
new_min = inp->sctp_ep.sctp_minrto;
if ((new_min <= new_init) && (new_init <= new_max)) {
inp->sctp_ep.initial_rto = new_init;
inp->sctp_ep.sctp_maxrto = new_max;
inp->sctp_ep.sctp_minrto = new_min;
} else {
error = EDOM;
}
SCTP_INP_WUNLOCK(inp);
}
}
@ -3188,8 +3206,8 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
sasoc->sasoc_number_peer_destinations = stcb->asoc.numnets;
sasoc->sasoc_peer_rwnd = 0;
sasoc->sasoc_local_rwnd = 0;
if (stcb->asoc.cookie_life)
stcb->asoc.cookie_life = sasoc->sasoc_cookie_life;
if (sasoc->sasoc_cookie_life)
stcb->asoc.cookie_life = MSEC_TO_TICKS(sasoc->sasoc_cookie_life);
stcb->asoc.delayed_ack = sasoc->sasoc_sack_delay;
if (sasoc->sasoc_sack_freq) {
stcb->asoc.sack_freq = sasoc->sasoc_sack_freq;
@ -3203,7 +3221,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
sasoc->sasoc_peer_rwnd = 0;
sasoc->sasoc_local_rwnd = 0;
if (sasoc->sasoc_cookie_life)
inp->sctp_ep.def_cookie_life = sasoc->sasoc_cookie_life;
inp->sctp_ep.def_cookie_life = MSEC_TO_TICKS(sasoc->sasoc_cookie_life);
inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV] = MSEC_TO_TICKS(sasoc->sasoc_sack_delay);
if (sasoc->sasoc_sack_freq) {
inp->sctp_ep.sctp_sack_freq = sasoc->sasoc_sack_freq;
@ -3419,8 +3437,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
*/
if (addrs->sget_assoc_id == 0) {
/* delete the address */
(void)sctp_addr_mgmt_ep_sa(inp, addr_touse,
SCTP_DEL_IP_ADDRESS, vrf_id);
error = sctp_addr_mgmt_ep_sa(inp, addr_touse,
SCTP_DEL_IP_ADDRESS,
vrf_id);
} else {
/*
* FIX: decide whether we allow assoc based

View File

@ -1292,6 +1292,7 @@ sctp_iterator_worker(void)
SCTP_IPI_ITERATOR_WQ_UNLOCK();
sctp_iterator_work(it);
SCTP_IPI_ITERATOR_WQ_LOCK();
/* sa_ignore FREED_MEMORY */
it = TAILQ_FIRST(&sctppcbinfo.iteratorhead);
}
if (TAILQ_FIRST(&sctppcbinfo.iteratorhead)) {
@ -1859,7 +1860,7 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
}
}
if (cnt_of_unconf) {
lnet = NULL;
net = lnet = NULL;
(void)sctp_heartbeat_timer(inp, stcb, lnet, cnt_of_unconf);
}
if (stcb->asoc.hb_random_idx > 3) {
@ -2745,7 +2746,7 @@ sctp_notify_assoc_change(uint32_t event, struct sctp_tcb *stcb,
*/
if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
((event == SCTP_COMM_LOST) || (event == SCTP_SHUTDOWN_COMP))) {
((event == SCTP_COMM_LOST) || (event == SCTP_CANT_STR_ASSOC))) {
if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT)
stcb->sctp_socket->so_error = ECONNREFUSED;
else
@ -3444,6 +3445,7 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, int holds_lock)
sp->net = NULL;
/* Free the chunk */
sctp_free_a_strmoq(stcb, sp);
/* sa_ignore FREED_MEMORY */
sp = TAILQ_FIRST(&outs->outqueue);
}
}
@ -3474,6 +3476,7 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, int holds_lock)
sctp_free_remote_addr(chk->whoTo);
chk->whoTo = NULL;
sctp_free_a_chunk(stcb, chk);
/* sa_ignore FREED_MEMORY */
chk = TAILQ_FIRST(&asoc->send_queue);
}
}
@ -3504,6 +3507,7 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, int holds_lock)
sctp_free_remote_addr(chk->whoTo);
chk->whoTo = NULL;
sctp_free_a_chunk(stcb, chk);
/* sa_ignore FREED_MEMORY */
chk = TAILQ_FIRST(&asoc->sent_queue);
}
}
@ -4782,6 +4786,7 @@ sctp_sorecvmsg(struct socket *so,
hold_sblock = 0;
}
/* we possibly have data we can read */
/* sa_ignore FREED_MEMORY */
control = TAILQ_FIRST(&inp->read_queue);
if (control == NULL) {
/*

View File

@ -217,6 +217,7 @@ sctp6_input(i_pak, offp, proto)
/* Length now holds the total packet length payload + iphlen */
length = ntohs(ip6->ip6_plen) + iphlen;
/* sa_ignore NO_NULL_CHK */
sctp_common_input_processing(&m, iphlen, offset, length, sh, ch,
in6p, stcb, net, ecn_bits, vrf_id, table_id);
/* inp's ref-count reduced && stcb unlocked */