summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorrrs <rrs@FreeBSD.org>2007-05-17 12:16:24 +0000
committerrrs <rrs@FreeBSD.org>2007-05-17 12:16:24 +0000
commitf03ff79b8eb759f4448ea239b33f54a4de64e72b (patch)
tree9c331efc7294abb10b0a637e060b8adcbb36b8be /sys
parent471f392f70d74931953e70708e2b2883ec00fcdd (diff)
downloadFreeBSD-src-f03ff79b8eb759f4448ea239b33f54a4de64e72b.zip
FreeBSD-src-f03ff79b8eb759f4448ea239b33f54a4de64e72b.tar.gz
- 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
Diffstat (limited to 'sys')
-rw-r--r--sys/netinet/sctp.h8
-rw-r--r--sys/netinet/sctp_asconf.c38
-rw-r--r--sys/netinet/sctp_auth.c2
-rw-r--r--sys/netinet/sctp_constants.h4
-rw-r--r--sys/netinet/sctp_indata.c6
-rw-r--r--sys/netinet/sctp_input.c6
-rw-r--r--sys/netinet/sctp_output.c14
-rw-r--r--sys/netinet/sctp_pcb.c45
-rw-r--r--sys/netinet/sctp_sysctl.c8
-rw-r--r--sys/netinet/sctp_timer.c2
-rw-r--r--sys/netinet/sctp_uio.h8
-rw-r--r--sys/netinet/sctp_usrreq.c127
-rw-r--r--sys/netinet/sctputil.c9
-rw-r--r--sys/netinet6/sctp6_usrreq.c1
14 files changed, 175 insertions, 103 deletions
diff --git a/sys/netinet/sctp.h b/sys/netinet/sctp.h
index e15b3dd..a8bcec6 100644
--- a/sys/netinet/sctp.h
+++ b/sys/netinet/sctp.h
@@ -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.
diff --git a/sys/netinet/sctp_asconf.c b/sys/netinet/sctp_asconf.c
index 92ab278..4151524 100644
--- a/sys/netinet/sctp_asconf.c
+++ b/sys/netinet/sctp_asconf.c
@@ -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! */
diff --git a/sys/netinet/sctp_auth.c b/sys/netinet/sctp_auth.c
index 5ea9ca9..42ba003 100644
--- a/sys/netinet/sctp_auth.c
+++ b/sys/netinet/sctp_auth.c
@@ -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);
diff --git a/sys/netinet/sctp_constants.h b/sys/netinet/sctp_constants.h
index 8c623aa..b695d81 100644
--- a/sys/netinet/sctp_constants.h
+++ b/sys/netinet/sctp_constants.h
@@ -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
diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c
index ba8a9a0..a021fed 100644
--- a/sys/netinet/sctp_indata.c
+++ b/sys/netinet/sctp_indata.c
@@ -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 @@ finish_express_del:
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 @@ again:
* 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 */
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index 6ac5f6d..bacdfe3 100644
--- a/sys/netinet/sctp_input.c
+++ b/sys/netinet/sctp_input.c
@@ -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_skip_csum_4:
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);
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c
index 3ec5245..39de2af 100644
--- a/sys/netinet/sctp_output.c
+++ b/sys/netinet/sctp_output.c
@@ -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 @@ invalid_size:
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);
diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c
index 09bdd2e..536ab72 100644
--- a/sys/netinet/sctp_pcb.c
+++ b/sys/netinet/sctp_pcb.c
@@ -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);
}
diff --git a/sys/netinet/sctp_sysctl.c b/sys/netinet/sctp_sysctl.c
index 13e0ab0..ce1ab45 100644
--- a/sys/netinet/sctp_sysctl.c
+++ b/sys/netinet/sctp_sysctl.c
@@ -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,
diff --git a/sys/netinet/sctp_timer.c b/sys/netinet/sctp_timer.c
index b027f0b..d00ff79 100644
--- a/sys/netinet/sctp_timer.c
+++ b/sys/netinet/sctp_timer.c
@@ -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 */
diff --git a/sys/netinet/sctp_uio.h b/sys/netinet/sctp_uio.h
index 8a67a0e..f3e0836 100644
--- a/sys/netinet/sctp_uio.h
+++ b/sys/netinet/sctp_uio.h
@@ -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 */
};
diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c
index f5bbbfc..b38a28b 100644
--- a/sys/netinet/sctp_usrreq.c
+++ b/sys/netinet/sctp_usrreq.c
@@ -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;
- }
- 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;
+ LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
+ cnt++;
}
- 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
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index 0a2d4f4..f3c685a 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -1292,6 +1292,7 @@ again:
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 @@ restart_nosblocks:
hold_sblock = 0;
}
/* we possibly have data we can read */
+ /* sa_ignore FREED_MEMORY */
control = TAILQ_FIRST(&inp->read_queue);
if (control == NULL) {
/*
diff --git a/sys/netinet6/sctp6_usrreq.c b/sys/netinet6/sctp6_usrreq.c
index 58fb8a5..1a5e411 100644
--- a/sys/netinet6/sctp6_usrreq.c
+++ b/sys/netinet6/sctp6_usrreq.c
@@ -217,6 +217,7 @@ sctp_skip_csum:
/* 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 */
OpenPOWER on IntegriCloud