summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/netinet
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-08-07 14:56:50 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-09-21 10:29:37 +0200
commitc37f9fba70085fedc8eede7559489d2321393005 (patch)
tree042455ebf1fa89a277a825f72e1ed805d0b4d296 /freebsd/sys/netinet
parentUpdate to FreeBSD head 2017-06-01 (diff)
downloadrtems-libbsd-c37f9fba70085fedc8eede7559489d2321393005.tar.bz2
Update to FreeBSD head 2017-08-01
Git mirror commit f5002f5e5f78cae9f0269d812dc0aedb0339312c. Update #3472.
Diffstat (limited to 'freebsd/sys/netinet')
-rw-r--r--freebsd/sys/netinet/cc/cc_newreno.c26
-rw-r--r--freebsd/sys/netinet/ip_output.c6
-rw-r--r--freebsd/sys/netinet/sctp_asconf.c16
-rw-r--r--freebsd/sys/netinet/sctp_auth.c115
-rw-r--r--freebsd/sys/netinet/sctp_constants.h2
-rw-r--r--freebsd/sys/netinet/sctp_indata.c388
-rw-r--r--freebsd/sys/netinet/sctp_input.c78
-rw-r--r--freebsd/sys/netinet/sctp_os_bsd.h4
-rw-r--r--freebsd/sys/netinet/sctp_output.c136
-rw-r--r--freebsd/sys/netinet/sctp_output.h5
-rw-r--r--freebsd/sys/netinet/sctp_pcb.c215
-rw-r--r--freebsd/sys/netinet/sctp_sysctl.c12
-rw-r--r--freebsd/sys/netinet/sctp_usrreq.c13
-rw-r--r--freebsd/sys/netinet/sctputil.c33
-rw-r--r--freebsd/sys/netinet/sctputil.h2
-rw-r--r--freebsd/sys/netinet/tcp_input.c41
-rw-r--r--freebsd/sys/netinet/tcp_output.c16
-rw-r--r--freebsd/sys/netinet/tcp_subr.c216
-rw-r--r--freebsd/sys/netinet/tcp_syncache.c11
-rw-r--r--freebsd/sys/netinet/tcp_syncache.h2
-rw-r--r--freebsd/sys/netinet/tcp_timewait.c2
-rw-r--r--freebsd/sys/netinet/tcp_var.h9
22 files changed, 783 insertions, 565 deletions
diff --git a/freebsd/sys/netinet/cc/cc_newreno.c b/freebsd/sys/netinet/cc/cc_newreno.c
index fb6c1087..474afcc9 100644
--- a/freebsd/sys/netinet/cc/cc_newreno.c
+++ b/freebsd/sys/netinet/cc/cc_newreno.c
@@ -184,42 +184,30 @@ newreno_after_idle(struct cc_var *ccv)
static void
newreno_cong_signal(struct cc_var *ccv, uint32_t type)
{
- uint32_t cwin, ssthresh_on_loss;
- u_int mss;
-
- cwin = CCV(ccv, snd_cwnd);
- mss = CCV(ccv, t_maxseg);
- ssthresh_on_loss =
- max((CCV(ccv, snd_max) - CCV(ccv, snd_una)) / 2 / mss, 2)
- * mss;
+ u_int win;
/* Catch algos which mistakenly leak private signal types. */
KASSERT((type & CC_SIGPRIVMASK) == 0,
("%s: congestion signal type 0x%08x is private\n", __func__, type));
- cwin = max(cwin / 2 / mss, 2) * mss;
+ win = max(CCV(ccv, snd_cwnd) / 2 / CCV(ccv, t_maxseg), 2) *
+ CCV(ccv, t_maxseg);
switch (type) {
case CC_NDUPACK:
if (!IN_FASTRECOVERY(CCV(ccv, t_flags))) {
- if (!IN_CONGRECOVERY(CCV(ccv, t_flags))) {
- CCV(ccv, snd_ssthresh) = ssthresh_on_loss;
- CCV(ccv, snd_cwnd) = cwin;
- }
+ if (!IN_CONGRECOVERY(CCV(ccv, t_flags)))
+ CCV(ccv, snd_ssthresh) = win;
ENTER_RECOVERY(CCV(ccv, t_flags));
}
break;
case CC_ECN:
if (!IN_CONGRECOVERY(CCV(ccv, t_flags))) {
- CCV(ccv, snd_ssthresh) = ssthresh_on_loss;
- CCV(ccv, snd_cwnd) = cwin;
+ CCV(ccv, snd_ssthresh) = win;
+ CCV(ccv, snd_cwnd) = win;
ENTER_CONGRECOVERY(CCV(ccv, t_flags));
}
break;
- case CC_RTO:
- CCV(ccv, snd_ssthresh) = ssthresh_on_loss;
- CCV(ccv, snd_cwnd) = mss;
- break;
}
}
diff --git a/freebsd/sys/netinet/ip_output.c b/freebsd/sys/netinet/ip_output.c
index 234f19fd..d9a5c511 100644
--- a/freebsd/sys/netinet/ip_output.c
+++ b/freebsd/sys/netinet/ip_output.c
@@ -65,7 +65,6 @@ __FBSDID("$FreeBSD$");
#include <net/netisr.h>
#include <net/pfil.h>
#include <net/route.h>
-#include <net/flowtable.h>
#ifdef RADIX_MPATH
#include <net/radix_mpath.h>
#endif
@@ -246,11 +245,6 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
bzero(ro, sizeof (*ro));
}
-#ifdef FLOWTABLE
- if (ro->ro_rt == NULL)
- (void )flowtable_lookup(AF_INET, m, ro);
-#endif
-
if (opt) {
int len = 0;
m = ip_insertoptions(m, opt, &len);
diff --git a/freebsd/sys/netinet/sctp_asconf.c b/freebsd/sys/netinet/sctp_asconf.c
index 04a813d3..aa31e488 100644
--- a/freebsd/sys/netinet/sctp_asconf.c
+++ b/freebsd/sys/netinet/sctp_asconf.c
@@ -184,7 +184,7 @@ sctp_process_asconf_add_ip(struct sockaddr *src, struct sctp_asconf_paramhdr *ap
}
v4addr = (struct sctp_ipv4addr_param *)ph;
sin = &store.sin;
- bzero(sin, sizeof(*sin));
+ memset(sin, 0, sizeof(*sin));
sin->sin_family = AF_INET;
sin->sin_len = sizeof(struct sockaddr_in);
sin->sin_port = stcb->rport;
@@ -207,7 +207,7 @@ sctp_process_asconf_add_ip(struct sockaddr *src, struct sctp_asconf_paramhdr *ap
}
v6addr = (struct sctp_ipv6addr_param *)ph;
sin6 = &store.sin6;
- bzero(sin6, sizeof(*sin6));
+ memset(sin6, 0, sizeof(*sin6));
sin6->sin6_family = AF_INET6;
sin6->sin6_len = sizeof(struct sockaddr_in6);
sin6->sin6_port = stcb->rport;
@@ -334,7 +334,7 @@ sctp_process_asconf_delete_ip(struct sockaddr *src,
}
v4addr = (struct sctp_ipv4addr_param *)ph;
sin = &store.sin;
- bzero(sin, sizeof(*sin));
+ memset(sin, 0, sizeof(*sin));
sin->sin_family = AF_INET;
sin->sin_len = sizeof(struct sockaddr_in);
sin->sin_port = stcb->rport;
@@ -354,7 +354,7 @@ sctp_process_asconf_delete_ip(struct sockaddr *src,
}
v6addr = (struct sctp_ipv6addr_param *)ph;
sin6 = &store.sin6;
- bzero(sin6, sizeof(*sin6));
+ memset(sin6, 0, sizeof(*sin6));
sin6->sin6_family = AF_INET6;
sin6->sin6_len = sizeof(struct sockaddr_in6);
sin6->sin6_port = stcb->rport;
@@ -463,7 +463,7 @@ sctp_process_asconf_set_primary(struct sockaddr *src,
}
v4addr = (struct sctp_ipv4addr_param *)ph;
sin = &store.sin;
- bzero(sin, sizeof(*sin));
+ memset(sin, 0, sizeof(*sin));
sin->sin_family = AF_INET;
sin->sin_len = sizeof(struct sockaddr_in);
sin->sin_addr.s_addr = v4addr->addr;
@@ -481,7 +481,7 @@ sctp_process_asconf_set_primary(struct sockaddr *src,
}
v6addr = (struct sctp_ipv6addr_param *)ph;
sin6 = &store.sin6;
- bzero(sin6, sizeof(*sin6));
+ memset(sin6, 0, sizeof(*sin6));
sin6->sin6_family = AF_INET6;
sin6->sin6_len = sizeof(struct sockaddr_in6);
memcpy((caddr_t)&sin6->sin6_addr, v6addr->addr,
@@ -2606,7 +2606,7 @@ sctp_compose_asconf(struct sctp_tcb *stcb, int *retlen, int addr_locked)
SCTP_BUF_LEN(m_asconf_chk) = sizeof(struct sctp_asconf_chunk);
SCTP_BUF_LEN(m_asconf) = 0;
acp = mtod(m_asconf_chk, struct sctp_asconf_chunk *);
- bzero(acp, sizeof(struct sctp_asconf_chunk));
+ memset(acp, 0, sizeof(struct sctp_asconf_chunk));
/* save pointers to lookup address and asconf params */
lookup_ptr = (caddr_t)(acp + 1); /* after the header */
ptr = mtod(m_asconf, caddr_t); /* beginning of cluster */
@@ -2739,7 +2739,7 @@ sctp_compose_asconf(struct sctp_tcb *stcb, int *retlen, int addr_locked)
/* XXX for now, we send a IPv4 address of 0.0.0.0 */
lookup->ph.param_type = htons(SCTP_IPV4_ADDRESS);
lookup->ph.param_length = htons(SCTP_SIZE32(sizeof(struct sctp_ipv4addr_param)));
- bzero(lookup->addr, sizeof(struct in_addr));
+ memset(lookup->addr, 0, sizeof(struct in_addr));
SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(sizeof(struct sctp_ipv4addr_param));
}
}
diff --git a/freebsd/sys/netinet/sctp_auth.c b/freebsd/sys/netinet/sctp_auth.c
index 4bcb2459..b6dfdaf8 100644
--- a/freebsd/sys/netinet/sctp_auth.c
+++ b/freebsd/sys/netinet/sctp_auth.c
@@ -55,7 +55,7 @@ __FBSDID("$FreeBSD$");
void
sctp_clear_chunklist(sctp_auth_chklist_t *chklist)
{
- bzero(chklist, sizeof(*chklist));
+ memset(chklist, 0, sizeof(*chklist));
/* chklist->num_chunks = 0; */
}
@@ -94,7 +94,7 @@ sctp_copy_chunklist(sctp_auth_chklist_t *list)
if (new_list == NULL)
return (NULL);
/* copy it */
- bcopy(list, new_list, sizeof(*new_list));
+ memcpy(new_list, list, sizeof(*new_list));
return (new_list);
}
@@ -340,7 +340,7 @@ sctp_set_key(uint8_t *key, uint32_t keylen)
/* out of memory */
return (NULL);
}
- bcopy(key, new_key->key, keylen);
+ memcpy(new_key->key, key, keylen);
return (new_key);
}
@@ -429,28 +429,28 @@ sctp_compute_hashkey(sctp_key_t *key1, sctp_key_t *key2, sctp_key_t *shared)
if (sctp_compare_key(key1, key2) <= 0) {
/* key is shared + key1 + key2 */
if (sctp_get_keylen(shared)) {
- bcopy(shared->key, key_ptr, shared->keylen);
+ memcpy(key_ptr, shared->key, shared->keylen);
key_ptr += shared->keylen;
}
if (sctp_get_keylen(key1)) {
- bcopy(key1->key, key_ptr, key1->keylen);
+ memcpy(key_ptr, key1->key, key1->keylen);
key_ptr += key1->keylen;
}
if (sctp_get_keylen(key2)) {
- bcopy(key2->key, key_ptr, key2->keylen);
+ memcpy(key_ptr, key2->key, key2->keylen);
}
} else {
/* key is shared + key2 + key1 */
if (sctp_get_keylen(shared)) {
- bcopy(shared->key, key_ptr, shared->keylen);
+ memcpy(key_ptr, shared->key, shared->keylen);
key_ptr += shared->keylen;
}
if (sctp_get_keylen(key2)) {
- bcopy(key2->key, key_ptr, key2->keylen);
+ memcpy(key_ptr, key2->key, key2->keylen);
key_ptr += key2->keylen;
}
if (sctp_get_keylen(key1)) {
- bcopy(key1->key, key_ptr, key1->keylen);
+ memcpy(key_ptr, key1->key, key1->keylen);
}
}
return (new_key);
@@ -766,7 +766,7 @@ sctp_serialize_hmaclist(sctp_hmaclist_t *list, uint8_t *ptr)
for (i = 0; i < list->num_algo; i++) {
hmac_id = htons(list->hmac[i]);
- bcopy(&hmac_id, ptr, sizeof(hmac_id));
+ memcpy(ptr, &hmac_id, sizeof(hmac_id));
ptr += sizeof(hmac_id);
}
return (list->num_algo * sizeof(hmac_id));
@@ -797,7 +797,7 @@ sctp_alloc_authinfo(void)
/* out of memory */
return (NULL);
}
- bzero(new_authinfo, sizeof(*new_authinfo));
+ memset(new_authinfo, 0, sizeof(*new_authinfo));
return (new_authinfo);
}
@@ -955,10 +955,10 @@ sctp_hmac(uint16_t hmac_algo, uint8_t *key, uint32_t keylen,
key = temp;
}
/* initialize the inner/outer pads with the key and "append" zeroes */
- bzero(ipad, blocklen);
- bzero(opad, blocklen);
- bcopy(key, ipad, keylen);
- bcopy(key, opad, keylen);
+ memset(ipad, 0, blocklen);
+ memset(opad, 0, blocklen);
+ memcpy(ipad, key, keylen);
+ memcpy(opad, key, keylen);
/* XOR the key with ipad and opad values */
for (i = 0; i < blocklen; i++) {
@@ -1015,10 +1015,10 @@ sctp_hmac_m(uint16_t hmac_algo, uint8_t *key, uint32_t keylen,
key = temp;
}
/* initialize the inner/outer pads with the key and "append" zeroes */
- bzero(ipad, blocklen);
- bzero(opad, blocklen);
- bcopy(key, ipad, keylen);
- bcopy(key, opad, keylen);
+ memset(ipad, 0, blocklen);
+ memset(opad, 0, blocklen);
+ memcpy(ipad, key, keylen);
+ memcpy(opad, key, keylen);
/* XOR the key with ipad and opad values */
for (i = 0; i < blocklen; i++) {
@@ -1126,7 +1126,7 @@ sctp_compute_hmac(uint16_t hmac_algo, sctp_key_t *key, uint8_t *text,
sctp_hmac_final(hmac_algo, &ctx, temp);
/* save the hashed key as the new key */
key->keylen = digestlen;
- bcopy(temp, key->key, key->keylen);
+ memcpy(key->key, temp, key->keylen);
}
return (sctp_hmac(hmac_algo, key->key, key->keylen, text, textlen,
digest));
@@ -1160,7 +1160,7 @@ sctp_compute_hmac_m(uint16_t hmac_algo, sctp_key_t *key, struct mbuf *m,
sctp_hmac_final(hmac_algo, &ctx, temp);
/* save the hashed key as the new key */
key->keylen = digestlen;
- bcopy(temp, key->key, key->keylen);
+ memcpy(key->key, temp, key->keylen);
}
return (sctp_hmac_m(hmac_algo, key->key, key->keylen, m, m_offset, digest, 0));
}
@@ -1436,7 +1436,7 @@ sctp_auth_get_cookie_params(struct sctp_tcb *stcb, struct mbuf *m,
if (plen > sizeof(random_store))
break;
phdr = sctp_get_next_param(m, offset,
- (struct sctp_paramhdr *)random_store, min(plen, sizeof(random_store)));
+ (struct sctp_paramhdr *)random_store, plen);
if (phdr == NULL)
return;
/* save the random and length for the key */
@@ -1449,7 +1449,7 @@ sctp_auth_get_cookie_params(struct sctp_tcb *stcb, struct mbuf *m,
if (plen > sizeof(hmacs_store))
break;
phdr = sctp_get_next_param(m, offset,
- (struct sctp_paramhdr *)hmacs_store, min(plen, sizeof(hmacs_store)));
+ (struct sctp_paramhdr *)hmacs_store, plen);
if (phdr == NULL)
return;
/* save the hmacs list and num for the key */
@@ -1471,7 +1471,7 @@ sctp_auth_get_cookie_params(struct sctp_tcb *stcb, struct mbuf *m,
if (plen > sizeof(chunks_store))
break;
phdr = sctp_get_next_param(m, offset,
- (struct sctp_paramhdr *)chunks_store, min(plen, sizeof(chunks_store)));
+ (struct sctp_paramhdr *)chunks_store, plen);
if (phdr == NULL)
return;
chunks = (struct sctp_auth_chunk_list *)phdr;
@@ -1503,17 +1503,17 @@ sctp_auth_get_cookie_params(struct sctp_tcb *stcb, struct mbuf *m,
/* copy in the RANDOM */
if (p_random != NULL) {
keylen = sizeof(*p_random) + random_len;
- bcopy(p_random, new_key->key, keylen);
+ memcpy(new_key->key, p_random, keylen);
}
/* append in the AUTH chunks */
if (chunks != NULL) {
- bcopy(chunks, new_key->key + keylen,
+ memcpy(new_key->key + keylen, chunks,
sizeof(*chunks) + num_chunks);
keylen += sizeof(*chunks) + num_chunks;
}
/* append in the HMACs */
if (hmacs != NULL) {
- bcopy(hmacs, new_key->key + keylen,
+ memcpy(new_key->key + keylen, hmacs,
sizeof(*hmacs) + hmacs_len);
}
}
@@ -1552,7 +1552,7 @@ sctp_fill_hmac_digest_m(struct mbuf *m, uint32_t auth_offset,
/* zero the digest + chunk padding */
digestlen = sctp_get_hmac_digest_len(stcb->asoc.peer_hmac_id);
- bzero(auth->hmac, SCTP_SIZE32(digestlen));
+ memset(auth->hmac, 0, SCTP_SIZE32(digestlen));
/* is the desired key cached? */
if ((keyid != stcb->asoc.authinfo.assoc_keyid) ||
@@ -1590,7 +1590,7 @@ sctp_fill_hmac_digest_m(struct mbuf *m, uint32_t auth_offset,
static void
-sctp_bzero_m(struct mbuf *m, uint32_t m_offset, uint32_t size)
+sctp_zero_m(struct mbuf *m, uint32_t m_offset, uint32_t size)
{
struct mbuf *m_tmp;
uint8_t *data;
@@ -1609,10 +1609,10 @@ sctp_bzero_m(struct mbuf *m, uint32_t m_offset, uint32_t size)
while ((m_tmp != NULL) && (size > 0)) {
data = mtod(m_tmp, uint8_t *)+m_offset;
if (size > (uint32_t)SCTP_BUF_LEN(m_tmp)) {
- bzero(data, SCTP_BUF_LEN(m_tmp));
+ memset(data, 0, SCTP_BUF_LEN(m_tmp));
size -= SCTP_BUF_LEN(m_tmp);
} else {
- bzero(data, size);
+ memset(data, 0, size);
size = 0;
}
/* clear the offset since it's only for the first mbuf */
@@ -1729,8 +1729,8 @@ sctp_handle_auth(struct sctp_tcb *stcb, struct sctp_auth_chunk *auth,
return (-1);
}
/* save a copy of the digest, zero the pseudo header, and validate */
- bcopy(auth->hmac, digest, digestlen);
- sctp_bzero_m(m, offset + sizeof(*auth), SCTP_SIZE32(digestlen));
+ memcpy(digest, auth->hmac, digestlen);
+ sctp_zero_m(m, offset + sizeof(*auth), SCTP_SIZE32(digestlen));
(void)sctp_compute_hmac_m(hmac_id, stcb->asoc.authinfo.recv_key,
m, offset, computed_digest);
@@ -1799,8 +1799,8 @@ sctp_notify_authentication(struct sctp_tcb *stcb, uint32_t indication,
sctp_m_freem(m_notify);
return;
}
- control->spec_flags = M_NOTIFICATION;
control->length = SCTP_BUF_LEN(m_notify);
+ control->spec_flags = M_NOTIFICATION;
/* not that we need this */
control->tail_mbuf = m_notify;
sctp_add_to_readq(stcb->sctp_ep, stcb, control,
@@ -1816,7 +1816,7 @@ sctp_notify_authentication(struct sctp_tcb *stcb, uint32_t indication,
int
sctp_validate_init_auth_params(struct mbuf *m, int offset, int limit)
{
- struct sctp_paramhdr *phdr, parm_buf;
+ struct sctp_paramhdr *phdr, param_buf;
uint16_t ptype, plen;
int peer_supports_asconf = 0;
int peer_supports_auth = 0;
@@ -1825,7 +1825,7 @@ sctp_validate_init_auth_params(struct mbuf *m, int offset, int limit)
uint8_t saw_asconf_ack = 0;
/* go through each of the params. */
- phdr = sctp_get_next_param(m, offset, &parm_buf, sizeof(parm_buf));
+ phdr = sctp_get_next_param(m, offset, &param_buf, sizeof(param_buf));
while (phdr) {
ptype = ntohs(phdr->param_type);
plen = ntohs(phdr->param_length);
@@ -1839,11 +1839,15 @@ sctp_validate_init_auth_params(struct mbuf *m, int offset, int limit)
if (ptype == SCTP_SUPPORTED_CHUNK_EXT) {
/* A supported extension chunk */
struct sctp_supported_chunk_types_param *pr_supported;
- uint8_t local_store[SCTP_PARAM_BUFFER_SIZE];
+ uint8_t local_store[SCTP_SMALL_CHUNK_STORE];
int num_ent, i;
+ if (plen > sizeof(local_store)) {
+ break;
+ }
phdr = sctp_get_next_param(m, offset,
- (struct sctp_paramhdr *)&local_store, min(plen, sizeof(local_store)));
+ (struct sctp_paramhdr *)&local_store,
+ plen);
if (phdr == NULL) {
return (-1);
}
@@ -1861,7 +1865,6 @@ sctp_validate_init_auth_params(struct mbuf *m, int offset, int limit)
}
}
} else if (ptype == SCTP_RANDOM) {
- got_random = 1;
/* enforce the random length */
if (plen != (sizeof(struct sctp_auth_random) +
SCTP_AUTH_RANDOM_SIZE_REQUIRED)) {
@@ -1869,20 +1872,23 @@ sctp_validate_init_auth_params(struct mbuf *m, int offset, int limit)
"SCTP: invalid RANDOM len\n");
return (-1);
}
+ got_random = 1;
} else if (ptype == SCTP_HMAC_LIST) {
- uint8_t store[SCTP_PARAM_BUFFER_SIZE];
struct sctp_auth_hmac_algo *hmacs;
+ uint8_t store[SCTP_PARAM_BUFFER_SIZE];
int num_hmacs;
- if (plen > sizeof(store))
+ if (plen > sizeof(store)) {
break;
+ }
phdr = sctp_get_next_param(m, offset,
- (struct sctp_paramhdr *)store, min(plen, sizeof(store)));
- if (phdr == NULL)
+ (struct sctp_paramhdr *)store,
+ plen);
+ if (phdr == NULL) {
return (-1);
+ }
hmacs = (struct sctp_auth_hmac_algo *)phdr;
- num_hmacs = (plen - sizeof(*hmacs)) /
- sizeof(hmacs->hmac_ids[0]);
+ num_hmacs = (plen - sizeof(*hmacs)) / sizeof(hmacs->hmac_ids[0]);
/* validate the hmac list */
if (sctp_verify_hmac_param(hmacs, num_hmacs)) {
SCTPDBG(SCTP_DEBUG_AUTH1,
@@ -1891,18 +1897,19 @@ sctp_validate_init_auth_params(struct mbuf *m, int offset, int limit)
}
got_hmacs = 1;
} else if (ptype == SCTP_CHUNK_LIST) {
- int i, num_chunks;
+ struct sctp_auth_chunk_list *chunks;
uint8_t chunks_store[SCTP_SMALL_CHUNK_STORE];
+ int i, num_chunks;
- /* did the peer send a non-empty chunk list? */
- struct sctp_auth_chunk_list *chunks = NULL;
-
+ if (plen > sizeof(chunks_store)) {
+ break;
+ }
phdr = sctp_get_next_param(m, offset,
(struct sctp_paramhdr *)chunks_store,
- min(plen, sizeof(chunks_store)));
- if (phdr == NULL)
+ plen);
+ if (phdr == NULL) {
return (-1);
-
+ }
/*-
* Flip through the list and mark that the
* peer supports asconf/asconf_ack.
@@ -1924,8 +1931,8 @@ sctp_validate_init_auth_params(struct mbuf *m, int offset, int limit)
if (offset >= limit) {
break;
}
- phdr = sctp_get_next_param(m, offset, &parm_buf,
- sizeof(parm_buf));
+ phdr = sctp_get_next_param(m, offset, &param_buf,
+ sizeof(param_buf));
}
/* validate authentication required parameters */
if (got_random && got_hmacs) {
diff --git a/freebsd/sys/netinet/sctp_constants.h b/freebsd/sys/netinet/sctp_constants.h
index e779051d..dca34cc5 100644
--- a/freebsd/sys/netinet/sctp_constants.h
+++ b/freebsd/sys/netinet/sctp_constants.h
@@ -758,7 +758,7 @@ __FBSDID("$FreeBSD$");
#define SCTP_DEFAULT_SPLIT_POINT_MIN 2904
/* Maximum length of diagnostic information in error causes */
-#define SCTP_DIAG_INFO_LEN 64
+#define SCTP_DIAG_INFO_LEN 128
/* ABORT CODES and other tell-tale location
* codes are generated by adding the below
diff --git a/freebsd/sys/netinet/sctp_indata.c b/freebsd/sys/netinet/sctp_indata.c
index 57f13a13..1924aeab 100644
--- a/freebsd/sys/netinet/sctp_indata.c
+++ b/freebsd/sys/netinet/sctp_indata.c
@@ -61,7 +61,7 @@ __FBSDID("$FreeBSD$");
* This will cause sctp_service_queues() to get called on the top entry in
* the list.
*/
-static void
+static uint32_t
sctp_add_chk_to_control(struct sctp_queued_to_read *control,
struct sctp_stream_in *strm,
struct sctp_tcb *stcb,
@@ -94,6 +94,8 @@ sctp_calc_rwnd(struct sctp_tcb *stcb, struct sctp_association *asoc)
asoc->size_on_reasm_queue == 0 &&
asoc->size_on_all_streams == 0) {
/* Full rwnd granted */
+ KASSERT(asoc->cnt_on_reasm_queue == 0, ("cnt_on_reasm_queue is %u", asoc->cnt_on_reasm_queue));
+ KASSERT(asoc->cnt_on_all_streams == 0, ("cnt_on_all_streams is %u", asoc->cnt_on_all_streams));
calc = max(SCTP_SB_LIMIT_RCV(stcb->sctp_socket), SCTP_MINIMAL_RWND);
return (calc);
}
@@ -560,7 +562,15 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb,
}
/* EY it wont be queued if it could be delivered directly */
queue_needed = 0;
- asoc->size_on_all_streams -= control->length;
+ if (asoc->size_on_all_streams >= control->length) {
+ asoc->size_on_all_streams -= control->length;
+ } else {
+#ifdef INVARIANTS
+ panic("size_on_all_streams = %u smaller than control length %u", asoc->size_on_all_streams, control->length);
+#else
+ asoc->size_on_all_streams = 0;
+#endif
+ }
sctp_ucount_decr(asoc->cnt_on_all_streams);
strm->last_mid_delivered++;
sctp_mark_non_revokable(asoc, control->sinfo_tsn);
@@ -573,10 +583,18 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb,
nxt_todel = strm->last_mid_delivered + 1;
if (SCTP_MID_EQ(asoc->idata_supported, nxt_todel, control->mid) &&
(((control->sinfo_flags >> 8) & SCTP_DATA_NOT_FRAG) == SCTP_DATA_NOT_FRAG)) {
- asoc->size_on_all_streams -= control->length;
- sctp_ucount_decr(asoc->cnt_on_all_streams);
if (control->on_strm_q == SCTP_ON_ORDERED) {
TAILQ_REMOVE(&strm->inqueue, control, next_instrm);
+ if (asoc->size_on_all_streams >= control->length) {
+ asoc->size_on_all_streams -= control->length;
+ } else {
+#ifdef INVARIANTS
+ panic("size_on_all_streams = %u smaller than control length %u", asoc->size_on_all_streams, control->length);
+#else
+ asoc->size_on_all_streams = 0;
+#endif
+ }
+ sctp_ucount_decr(asoc->cnt_on_all_streams);
#ifdef INVARIANTS
} else {
panic("Huh control: %p is on_strm_q: %d",
@@ -673,7 +691,7 @@ sctp_setup_tail_pointer(struct sctp_queued_to_read *control)
}
static void
-sctp_add_to_tail_pointer(struct sctp_queued_to_read *control, struct mbuf *m)
+sctp_add_to_tail_pointer(struct sctp_queued_to_read *control, struct mbuf *m, uint32_t *added)
{
struct mbuf *prev = NULL;
struct sctp_tcb *stcb;
@@ -717,6 +735,7 @@ sctp_add_to_tail_pointer(struct sctp_queued_to_read *control, struct mbuf *m)
*/
sctp_sballoc(stcb, &stcb->sctp_socket->so_rcv, m);
}
+ *added += SCTP_BUF_LEN(m);
atomic_add_int(&control->length, SCTP_BUF_LEN(m));
m = SCTP_BUF_NEXT(m);
}
@@ -817,7 +836,15 @@ restart:
tchk = TAILQ_FIRST(&control->reasm);
if (tchk->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG) {
TAILQ_REMOVE(&control->reasm, tchk, sctp_next);
- asoc->size_on_reasm_queue -= tchk->send_size;
+ if (asoc->size_on_reasm_queue >= tchk->send_size) {
+ asoc->size_on_reasm_queue -= tchk->send_size;
+ } else {
+#ifdef INVARIANTS
+ panic("size_on_reasm_queue = %u smaller than chunk length %u", asoc->size_on_reasm_queue, tchk->send_size);
+#else
+ asoc->size_on_reasm_queue = 0;
+#endif
+ }
sctp_ucount_decr(asoc->cnt_on_reasm_queue);
nc->first_frag_seen = 1;
nc->fsn_included = tchk->rec.data.fsn;
@@ -1129,6 +1156,16 @@ done_un:
#endif
SCTP_STAT_INCR_COUNTER64(sctps_reasmusrmsgs);
TAILQ_REMOVE(&strm->inqueue, control, next_instrm);
+ if (asoc->size_on_all_streams >= control->length) {
+ asoc->size_on_all_streams -= control->length;
+ } else {
+#ifdef INVARIANTS
+ panic("size_on_all_streams = %u smaller than control length %u", asoc->size_on_all_streams, control->length);
+#else
+ asoc->size_on_all_streams = 0;
+#endif
+ }
+ sctp_ucount_decr(asoc->cnt_on_all_streams);
control->on_strm_q = 0;
}
if (strm->pd_api_started && control->pdapi_started) {
@@ -1175,6 +1212,16 @@ deliver_more:
#endif
SCTP_STAT_INCR_COUNTER64(sctps_reasmusrmsgs);
TAILQ_REMOVE(&strm->inqueue, control, next_instrm);
+ if (asoc->size_on_all_streams >= control->length) {
+ asoc->size_on_all_streams -= control->length;
+ } else {
+#ifdef INVARIANTS
+ panic("size_on_all_streams = %u smaller than control length %u", asoc->size_on_all_streams, control->length);
+#else
+ asoc->size_on_all_streams = 0;
+#endif
+ }
+ sctp_ucount_decr(asoc->cnt_on_all_streams);
control->on_strm_q = 0;
}
ret++;
@@ -1221,7 +1268,7 @@ out:
}
-void
+uint32_t
sctp_add_chk_to_control(struct sctp_queued_to_read *control,
struct sctp_stream_in *strm,
struct sctp_tcb *stcb, struct sctp_association *asoc,
@@ -1231,6 +1278,7 @@ sctp_add_chk_to_control(struct sctp_queued_to_read *control,
* Given a control and a chunk, merge the data from the chk onto the
* control and free up the chunk resources.
*/
+ uint32_t added = 0;
int i_locked = 0;
if (control->on_read_q && (hold_rlock == 0)) {
@@ -1244,7 +1292,7 @@ sctp_add_chk_to_control(struct sctp_queued_to_read *control,
control->data = chk->data;
sctp_setup_tail_pointer(control);
} else {
- sctp_add_to_tail_pointer(control, chk->data);
+ sctp_add_to_tail_pointer(control, chk->data, &added);
}
control->fsn_included = chk->rec.data.fsn;
asoc->size_on_reasm_queue -= chk->send_size;
@@ -1270,6 +1318,16 @@ sctp_add_chk_to_control(struct sctp_queued_to_read *control,
} else if (control->on_strm_q == SCTP_ON_ORDERED) {
/* Ordered */
TAILQ_REMOVE(&strm->inqueue, control, next_instrm);
+ if (asoc->size_on_all_streams >= control->length) {
+ asoc->size_on_all_streams -= control->length;
+ } else {
+#ifdef INVARIANTS
+ panic("size_on_all_streams = %u smaller than control length %u", asoc->size_on_all_streams, control->length);
+#else
+ asoc->size_on_all_streams = 0;
+#endif
+ }
+ sctp_ucount_decr(asoc->cnt_on_all_streams);
control->on_strm_q = 0;
#ifdef INVARIANTS
} else if (control->on_strm_q) {
@@ -1285,6 +1343,7 @@ sctp_add_chk_to_control(struct sctp_queued_to_read *control,
SCTP_INP_READ_UNLOCK(stcb->sctp_ep);
}
sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
+ return (added);
}
/*
@@ -1304,6 +1363,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
struct sctp_tmit_chunk *at, *nat;
struct sctp_stream_in *strm;
int do_wakeup, unordered;
+ uint32_t lenadded;
strm = &asoc->strmin[control->sinfo_stream];
/*
@@ -1316,6 +1376,9 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
}
/* Must be added to the stream-in queue */
if (created_control) {
+ if (unordered == 0) {
+ sctp_ucount_incr(asoc->cnt_on_all_streams);
+ }
if (sctp_place_control_in_stream(strm, asoc, control)) {
/* Duplicate SSN? */
sctp_clean_up_control(stcb, control);
@@ -1375,6 +1438,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
chk->data = NULL;
sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
sctp_setup_tail_pointer(control);
+ asoc->size_on_all_streams += control->length;
} else {
/* Place the chunk in our list */
int inserted = 0;
@@ -1531,7 +1595,8 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
at->rec.data.fsn,
next_fsn, control->fsn_included);
TAILQ_REMOVE(&control->reasm, at, sctp_next);
- sctp_add_chk_to_control(control, strm, stcb, asoc, at, SCTP_READ_LOCK_NOT_HELD);
+ lenadded = sctp_add_chk_to_control(control, strm, stcb, asoc, at, SCTP_READ_LOCK_NOT_HELD);
+ asoc->size_on_all_streams += lenadded;
if (control->on_read_q) {
do_wakeup = 1;
}
@@ -1602,7 +1667,7 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
uint16_t sid;
struct mbuf *op_err;
char msg[SCTP_DIAG_INFO_LEN];
- struct sctp_queued_to_read *control = NULL;
+ struct sctp_queued_to_read *control, *ncontrol;
uint32_t ppid;
uint8_t chk_flags;
struct sctp_stream_reset_list *liste;
@@ -2008,7 +2073,12 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
return (0);
}
if ((chk_flags & SCTP_DATA_NOT_FRAG) == SCTP_DATA_NOT_FRAG) {
+ struct mbuf *mm;
+
control->data = dmbuf;
+ for (mm = control->data; mm; mm = mm->m_next) {
+ control->length += SCTP_BUF_LEN(mm);
+ }
control->tail_mbuf = NULL;
control->end_added = 1;
control->last_frag_seen = 1;
@@ -2118,16 +2188,16 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
/* first one on */
TAILQ_INSERT_TAIL(&asoc->pending_reply_queue, control, next);
} else {
- struct sctp_queued_to_read *ctlOn, *nctlOn;
+ struct sctp_queued_to_read *lcontrol, *nlcontrol;
unsigned char inserted = 0;
- TAILQ_FOREACH_SAFE(ctlOn, &asoc->pending_reply_queue, next, nctlOn) {
- if (SCTP_TSN_GT(control->sinfo_tsn, ctlOn->sinfo_tsn)) {
+ TAILQ_FOREACH_SAFE(lcontrol, &asoc->pending_reply_queue, next, nlcontrol) {
+ if (SCTP_TSN_GT(control->sinfo_tsn, lcontrol->sinfo_tsn)) {
continue;
} else {
/* found it */
- TAILQ_INSERT_BEFORE(ctlOn, control, next);
+ TAILQ_INSERT_BEFORE(lcontrol, control, next);
inserted = 1;
break;
}
@@ -2218,8 +2288,6 @@ finish_express_del:
* pending_reply space 3: distribute any chunks in
* pending_reply_queue.
*/
- struct sctp_queued_to_read *ctl, *nctl;
-
sctp_reset_in_stream(stcb, liste->number_entries, liste->list_of_streams);
TAILQ_REMOVE(&asoc->resetHead, liste, next_resp);
sctp_send_deferred_reset_response(stcb, liste, SCTP_STREAM_RESET_RESULT_PERFORMED);
@@ -2228,34 +2296,34 @@ finish_express_del:
liste = TAILQ_FIRST(&asoc->resetHead);
if (TAILQ_EMPTY(&asoc->resetHead)) {
/* All can be removed */
- TAILQ_FOREACH_SAFE(ctl, &asoc->pending_reply_queue, next, nctl) {
- TAILQ_REMOVE(&asoc->pending_reply_queue, ctl, next);
- sctp_queue_data_to_stream(stcb, asoc, ctl, abort_flag, &need_reasm_check);
+ TAILQ_FOREACH_SAFE(control, &asoc->pending_reply_queue, next, ncontrol) {
+ TAILQ_REMOVE(&asoc->pending_reply_queue, control, next);
+ sctp_queue_data_to_stream(stcb, asoc, control, abort_flag, &need_reasm_check);
if (*abort_flag) {
return (0);
}
if (need_reasm_check) {
- (void)sctp_deliver_reasm_check(stcb, asoc, &asoc->strmin[ctl->sinfo_stream], SCTP_READ_LOCK_NOT_HELD);
+ (void)sctp_deliver_reasm_check(stcb, asoc, &asoc->strmin[control->sinfo_stream], SCTP_READ_LOCK_NOT_HELD);
need_reasm_check = 0;
}
}
} else {
- TAILQ_FOREACH_SAFE(ctl, &asoc->pending_reply_queue, next, nctl) {
- if (SCTP_TSN_GT(ctl->sinfo_tsn, liste->tsn)) {
+ TAILQ_FOREACH_SAFE(control, &asoc->pending_reply_queue, next, ncontrol) {
+ if (SCTP_TSN_GT(control->sinfo_tsn, liste->tsn)) {
break;
}
/*
- * if ctl->sinfo_tsn is <= liste->tsn we can
- * process it which is the NOT of
- * ctl->sinfo_tsn > liste->tsn
+ * if control->sinfo_tsn is <= liste->tsn we
+ * can process it which is the NOT of
+ * control->sinfo_tsn > liste->tsn
*/
- TAILQ_REMOVE(&asoc->pending_reply_queue, ctl, next);
- sctp_queue_data_to_stream(stcb, asoc, ctl, abort_flag, &need_reasm_check);
+ TAILQ_REMOVE(&asoc->pending_reply_queue, control, next);
+ sctp_queue_data_to_stream(stcb, asoc, control, abort_flag, &need_reasm_check);
if (*abort_flag) {
return (0);
}
if (need_reasm_check) {
- (void)sctp_deliver_reasm_check(stcb, asoc, &asoc->strmin[ctl->sinfo_stream], SCTP_READ_LOCK_NOT_HELD);
+ (void)sctp_deliver_reasm_check(stcb, asoc, &asoc->strmin[control->sinfo_stream], SCTP_READ_LOCK_NOT_HELD);
need_reasm_check = 0;
}
}
@@ -4226,47 +4294,44 @@ again:
((*asoc->ss_functions.sctp_ss_is_user_msgs_incomplete) (stcb, asoc))) {
asoc->state |= SCTP_STATE_PARTIAL_MSG_LEFT;
}
+ if (((asoc->state & SCTP_STATE_SHUTDOWN_PENDING) ||
+ (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) &&
+ (asoc->stream_queue_cnt == 1) &&
+ (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
+ struct mbuf *op_err;
+
+ *abort_now = 1;
+ /* XXX */
+ op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
+ stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_24;
+ sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
+ return;
+ }
if ((asoc->state & SCTP_STATE_SHUTDOWN_PENDING) &&
(asoc->stream_queue_cnt == 0)) {
- if (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT) {
- /* Need to abort here */
- struct mbuf *op_err;
+ struct sctp_nets *netp;
- abort_out_now:
- *abort_now = 1;
- /* XXX */
- op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
- stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_24;
- sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
- return;
+ if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
+ (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
+ SCTP_STAT_DECR_GAUGE32(sctps_currestab);
+ }
+ SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
+ SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
+ sctp_stop_timers_for_shutdown(stcb);
+ if (asoc->alternate) {
+ netp = asoc->alternate;
} else {
- struct sctp_nets *netp;
-
- if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
- (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
- SCTP_STAT_DECR_GAUGE32(sctps_currestab);
- }
- SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
- SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
- sctp_stop_timers_for_shutdown(stcb);
- if (asoc->alternate) {
- netp = asoc->alternate;
- } else {
- netp = asoc->primary_destination;
- }
- sctp_send_shutdown(stcb, netp);
- sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
- stcb->sctp_ep, stcb, netp);
- sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
- stcb->sctp_ep, stcb, netp);
+ netp = asoc->primary_destination;
}
+ sctp_send_shutdown(stcb, netp);
+ sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
+ stcb->sctp_ep, stcb, netp);
+ sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
+ stcb->sctp_ep, stcb, netp);
} else if ((SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED) &&
(asoc->stream_queue_cnt == 0)) {
struct sctp_nets *netp;
- if (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT) {
- goto abort_out_now;
- }
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT);
SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
@@ -4922,48 +4987,45 @@ hopeless_peer:
((*asoc->ss_functions.sctp_ss_is_user_msgs_incomplete) (stcb, asoc))) {
asoc->state |= SCTP_STATE_PARTIAL_MSG_LEFT;
}
+ if (((asoc->state & SCTP_STATE_SHUTDOWN_PENDING) ||
+ (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) &&
+ (asoc->stream_queue_cnt == 1) &&
+ (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
+ struct mbuf *op_err;
+
+ *abort_now = 1;
+ /* XXX */
+ op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
+ stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_24;
+ sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
+ return;
+ }
if ((asoc->state & SCTP_STATE_SHUTDOWN_PENDING) &&
(asoc->stream_queue_cnt == 0)) {
- if (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT) {
- /* Need to abort here */
- struct mbuf *op_err;
+ struct sctp_nets *netp;
- abort_out_now:
- *abort_now = 1;
- /* XXX */
- op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
- stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_31;
- sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
- return;
+ if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
+ (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
+ SCTP_STAT_DECR_GAUGE32(sctps_currestab);
+ }
+ SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
+ SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
+ sctp_stop_timers_for_shutdown(stcb);
+ if (asoc->alternate) {
+ netp = asoc->alternate;
} else {
- struct sctp_nets *netp;
-
- if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
- (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
- SCTP_STAT_DECR_GAUGE32(sctps_currestab);
- }
- SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
- SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
- sctp_stop_timers_for_shutdown(stcb);
- if (asoc->alternate) {
- netp = asoc->alternate;
- } else {
- netp = asoc->primary_destination;
- }
- sctp_send_shutdown(stcb, netp);
- sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
- stcb->sctp_ep, stcb, netp);
- sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
- stcb->sctp_ep, stcb, netp);
+ netp = asoc->primary_destination;
}
+ sctp_send_shutdown(stcb, netp);
+ sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
+ stcb->sctp_ep, stcb, netp);
+ sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
+ stcb->sctp_ep, stcb, netp);
return;
} else if ((SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED) &&
(asoc->stream_queue_cnt == 0)) {
struct sctp_nets *netp;
- if (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT) {
- goto abort_out_now;
- }
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT);
SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
@@ -5183,7 +5245,7 @@ static void
sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb,
struct sctp_stream_in *strmin)
{
- struct sctp_queued_to_read *ctl, *nctl;
+ struct sctp_queued_to_read *control, *ncontrol;
struct sctp_association *asoc;
uint32_t mid;
int need_reasm_check = 0;
@@ -5194,43 +5256,51 @@ sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb,
* First deliver anything prior to and including the stream no that
* came in.
*/
- TAILQ_FOREACH_SAFE(ctl, &strmin->inqueue, next_instrm, nctl) {
- if (SCTP_MID_GE(asoc->idata_supported, mid, ctl->mid)) {
+ TAILQ_FOREACH_SAFE(control, &strmin->inqueue, next_instrm, ncontrol) {
+ if (SCTP_MID_GE(asoc->idata_supported, mid, control->mid)) {
/* this is deliverable now */
- if (((ctl->sinfo_flags >> 8) & SCTP_DATA_NOT_FRAG) == SCTP_DATA_NOT_FRAG) {
- if (ctl->on_strm_q) {
- if (ctl->on_strm_q == SCTP_ON_ORDERED) {
- TAILQ_REMOVE(&strmin->inqueue, ctl, next_instrm);
- } else if (ctl->on_strm_q == SCTP_ON_UNORDERED) {
- TAILQ_REMOVE(&strmin->uno_inqueue, ctl, next_instrm);
+ if (((control->sinfo_flags >> 8) & SCTP_DATA_NOT_FRAG) == SCTP_DATA_NOT_FRAG) {
+ if (control->on_strm_q) {
+ if (control->on_strm_q == SCTP_ON_ORDERED) {
+ TAILQ_REMOVE(&strmin->inqueue, control, next_instrm);
+ } else if (control->on_strm_q == SCTP_ON_UNORDERED) {
+ TAILQ_REMOVE(&strmin->uno_inqueue, control, next_instrm);
#ifdef INVARIANTS
} else {
panic("strmin: %p ctl: %p unknown %d",
- strmin, ctl, ctl->on_strm_q);
+ strmin, control, control->on_strm_q);
#endif
}
- ctl->on_strm_q = 0;
+ control->on_strm_q = 0;
}
/* subtract pending on streams */
- asoc->size_on_all_streams -= ctl->length;
+ if (asoc->size_on_all_streams >= control->length) {
+ asoc->size_on_all_streams -= control->length;
+ } else {
+#ifdef INVARIANTS
+ panic("size_on_all_streams = %u smaller than control length %u", asoc->size_on_all_streams, control->length);
+#else
+ asoc->size_on_all_streams = 0;
+#endif
+ }
sctp_ucount_decr(asoc->cnt_on_all_streams);
/* deliver it to at least the delivery-q */
if (stcb->sctp_socket) {
- sctp_mark_non_revokable(asoc, ctl->sinfo_tsn);
+ sctp_mark_non_revokable(asoc, control->sinfo_tsn);
sctp_add_to_readq(stcb->sctp_ep, stcb,
- ctl,
+ control,
&stcb->sctp_socket->so_rcv,
1, SCTP_READ_LOCK_HELD,
SCTP_SO_NOT_LOCKED);
}
} else {
/* Its a fragmented message */
- if (ctl->first_frag_seen) {
+ if (control->first_frag_seen) {
/*
* Make it so this is next to
* deliver, we restore later
*/
- strmin->last_mid_delivered = ctl->mid - 1;
+ strmin->last_mid_delivered = control->mid - 1;
need_reasm_check = 1;
break;
}
@@ -5259,32 +5329,40 @@ sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb,
* now ready.
*/
mid = strmin->last_mid_delivered + 1;
- TAILQ_FOREACH_SAFE(ctl, &strmin->inqueue, next_instrm, nctl) {
- if (SCTP_MID_EQ(asoc->idata_supported, mid, ctl->mid)) {
- if (((ctl->sinfo_flags >> 8) & SCTP_DATA_NOT_FRAG) == SCTP_DATA_NOT_FRAG) {
+ TAILQ_FOREACH_SAFE(control, &strmin->inqueue, next_instrm, ncontrol) {
+ if (SCTP_MID_EQ(asoc->idata_supported, mid, control->mid)) {
+ if (((control->sinfo_flags >> 8) & SCTP_DATA_NOT_FRAG) == SCTP_DATA_NOT_FRAG) {
/* this is deliverable now */
- if (ctl->on_strm_q) {
- if (ctl->on_strm_q == SCTP_ON_ORDERED) {
- TAILQ_REMOVE(&strmin->inqueue, ctl, next_instrm);
- } else if (ctl->on_strm_q == SCTP_ON_UNORDERED) {
- TAILQ_REMOVE(&strmin->uno_inqueue, ctl, next_instrm);
+ if (control->on_strm_q) {
+ if (control->on_strm_q == SCTP_ON_ORDERED) {
+ TAILQ_REMOVE(&strmin->inqueue, control, next_instrm);
+ } else if (control->on_strm_q == SCTP_ON_UNORDERED) {
+ TAILQ_REMOVE(&strmin->uno_inqueue, control, next_instrm);
#ifdef INVARIANTS
} else {
panic("strmin: %p ctl: %p unknown %d",
- strmin, ctl, ctl->on_strm_q);
+ strmin, control, control->on_strm_q);
#endif
}
- ctl->on_strm_q = 0;
+ control->on_strm_q = 0;
}
/* subtract pending on streams */
- asoc->size_on_all_streams -= ctl->length;
+ if (asoc->size_on_all_streams >= control->length) {
+ asoc->size_on_all_streams -= control->length;
+ } else {
+#ifdef INVARIANTS
+ panic("size_on_all_streams = %u smaller than control length %u", asoc->size_on_all_streams, control->length);
+#else
+ asoc->size_on_all_streams = 0;
+#endif
+ }
sctp_ucount_decr(asoc->cnt_on_all_streams);
/* deliver it to at least the delivery-q */
- strmin->last_mid_delivered = ctl->mid;
+ strmin->last_mid_delivered = control->mid;
if (stcb->sctp_socket) {
- sctp_mark_non_revokable(asoc, ctl->sinfo_tsn);
+ sctp_mark_non_revokable(asoc, control->sinfo_tsn);
sctp_add_to_readq(stcb->sctp_ep, stcb,
- ctl,
+ control,
&stcb->sctp_socket->so_rcv, 1,
SCTP_READ_LOCK_HELD, SCTP_SO_NOT_LOCKED);
@@ -5292,12 +5370,12 @@ sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb,
mid = strmin->last_mid_delivered + 1;
} else {
/* Its a fragmented message */
- if (ctl->first_frag_seen) {
+ if (control->first_frag_seen) {
/*
* Make it so this is next to
* deliver
*/
- strmin->last_mid_delivered = ctl->mid - 1;
+ strmin->last_mid_delivered = control->mid - 1;
need_reasm_check = 1;
break;
}
@@ -5349,7 +5427,15 @@ sctp_flush_reassm_for_str_seq(struct sctp_tcb *stcb,
}
cnt_removed++;
TAILQ_REMOVE(&control->reasm, chk, sctp_next);
- asoc->size_on_reasm_queue -= chk->send_size;
+ if (asoc->size_on_reasm_queue >= chk->send_size) {
+ asoc->size_on_reasm_queue -= chk->send_size;
+ } else {
+#ifdef INVARIANTS
+ panic("size_on_reasm_queue = %u smaller than chunk length %u", asoc->size_on_reasm_queue, chk->send_size);
+#else
+ asoc->size_on_reasm_queue = 0;
+#endif
+ }
sctp_ucount_decr(asoc->cnt_on_reasm_queue);
if (chk->data) {
sctp_m_freem(chk->data);
@@ -5375,6 +5461,16 @@ sctp_flush_reassm_for_str_seq(struct sctp_tcb *stcb,
}
if (control->on_strm_q == SCTP_ON_ORDERED) {
TAILQ_REMOVE(&strm->inqueue, control, next_instrm);
+ if (asoc->size_on_all_streams >= control->length) {
+ asoc->size_on_all_streams -= control->length;
+ } else {
+#ifdef INVARIANTS
+ panic("size_on_all_streams = %u smaller than control length %u", asoc->size_on_all_streams, control->length);
+#else
+ asoc->size_on_all_streams = 0;
+#endif
+ }
+ sctp_ucount_decr(asoc->cnt_on_all_streams);
control->on_strm_q = 0;
} else if (control->on_strm_q == SCTP_ON_UNORDERED) {
TAILQ_REMOVE(&strm->uno_inqueue, control, next_instrm);
@@ -5418,7 +5514,7 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
unsigned int i, fwd_sz, m_size;
uint32_t str_seq;
struct sctp_stream_in *strm;
- struct sctp_queued_to_read *ctl, *sv;
+ struct sctp_queued_to_read *control, *sv;
asoc = &stcb->asoc;
if ((fwd_sz = ntohs(fwd->ch.chunk_length)) < sizeof(struct sctp_forward_tsn_chunk)) {
@@ -5577,25 +5673,35 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
for (cur_mid = strm->last_mid_delivered; SCTP_MID_GE(asoc->idata_supported, mid, cur_mid); cur_mid++) {
sctp_flush_reassm_for_str_seq(stcb, asoc, sid, cur_mid, ordered, new_cum_tsn);
}
- TAILQ_FOREACH(ctl, &stcb->sctp_ep->read_queue, next) {
- if ((ctl->sinfo_stream == sid) &&
- (SCTP_MID_EQ(asoc->idata_supported, ctl->mid, mid))) {
+ TAILQ_FOREACH(control, &stcb->sctp_ep->read_queue, next) {
+ if ((control->sinfo_stream == sid) &&
+ (SCTP_MID_EQ(asoc->idata_supported, control->mid, mid))) {
str_seq = (sid << 16) | (0x0000ffff & mid);
- ctl->pdapi_aborted = 1;
+ control->pdapi_aborted = 1;
sv = stcb->asoc.control_pdapi;
- ctl->end_added = 1;
- if (ctl->on_strm_q == SCTP_ON_ORDERED) {
- TAILQ_REMOVE(&strm->inqueue, ctl, next_instrm);
- } else if (ctl->on_strm_q == SCTP_ON_UNORDERED) {
- TAILQ_REMOVE(&strm->uno_inqueue, ctl, next_instrm);
+ control->end_added = 1;
+ if (control->on_strm_q == SCTP_ON_ORDERED) {
+ TAILQ_REMOVE(&strm->inqueue, control, next_instrm);
+ if (asoc->size_on_all_streams >= control->length) {
+ asoc->size_on_all_streams -= control->length;
+ } else {
#ifdef INVARIANTS
- } else if (ctl->on_strm_q) {
+ panic("size_on_all_streams = %u smaller than control length %u", asoc->size_on_all_streams, control->length);
+#else
+ asoc->size_on_all_streams = 0;
+#endif
+ }
+ sctp_ucount_decr(asoc->cnt_on_all_streams);
+ } else if (control->on_strm_q == SCTP_ON_UNORDERED) {
+ TAILQ_REMOVE(&strm->uno_inqueue, control, next_instrm);
+#ifdef INVARIANTS
+ } else if (control->on_strm_q) {
panic("strm: %p ctl: %p unknown %d",
- strm, ctl, ctl->on_strm_q);
+ strm, control, control->on_strm_q);
#endif
}
- ctl->on_strm_q = 0;
- stcb->asoc.control_pdapi = ctl;
+ control->on_strm_q = 0;
+ stcb->asoc.control_pdapi = control;
sctp_ulp_notify(SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION,
stcb,
SCTP_PARTIAL_DELIVERY_ABORTED,
@@ -5603,8 +5709,8 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
SCTP_SO_NOT_LOCKED);
stcb->asoc.control_pdapi = sv;
break;
- } else if ((ctl->sinfo_stream == sid) &&
- SCTP_MID_GT(asoc->idata_supported, ctl->mid, mid)) {
+ } else if ((control->sinfo_stream == sid) &&
+ SCTP_MID_GT(asoc->idata_supported, control->mid, mid)) {
/* We are past our victim SSN */
break;
}
diff --git a/freebsd/sys/netinet/sctp_input.c b/freebsd/sys/netinet/sctp_input.c
index be01c38a..2e844fb5 100644
--- a/freebsd/sys/netinet/sctp_input.c
+++ b/freebsd/sys/netinet/sctp_input.c
@@ -2151,23 +2151,23 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
* cookie was in flight. Only recourse is to abort the
* association.
*/
- atomic_add_int(&stcb->asoc.refcnt, 1);
op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, "");
sctp_abort_association(inp, (struct sctp_tcb *)NULL, m, iphlen,
src, dst, sh, op_err,
mflowtype, mflowid,
vrf_id, port);
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+ atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
+ atomic_subtract_int(&stcb->asoc.refcnt, 1);
#endif
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
SCTP_FROM_SCTP_INPUT + SCTP_LOC_18);
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
- atomic_subtract_int(&stcb->asoc.refcnt, 1);
return (NULL);
}
/* process the INIT-ACK info (my info) */
@@ -2188,36 +2188,36 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
else
retval = 0;
if (retval < 0) {
- atomic_add_int(&stcb->asoc.refcnt, 1);
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+ atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
+ atomic_subtract_int(&stcb->asoc.refcnt, 1);
#endif
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
SCTP_FROM_SCTP_INPUT + SCTP_LOC_19);
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
- atomic_subtract_int(&stcb->asoc.refcnt, 1);
return (NULL);
}
/* load all addresses */
if (sctp_load_addresses_from_init(stcb, m,
init_offset + sizeof(struct sctp_init_chunk), initack_offset,
src, dst, init_src, port)) {
- atomic_add_int(&stcb->asoc.refcnt, 1);
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+ atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
+ atomic_subtract_int(&stcb->asoc.refcnt, 1);
#endif
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
SCTP_FROM_SCTP_INPUT + SCTP_LOC_20);
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
- atomic_subtract_int(&stcb->asoc.refcnt, 1);
return (NULL);
}
/*
@@ -2236,35 +2236,24 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
/* auth HMAC failed, dump the assoc and packet */
SCTPDBG(SCTP_DEBUG_AUTH1,
"COOKIE-ECHO: AUTH failed\n");
- atomic_add_int(&stcb->asoc.refcnt, 1);
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+ atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
+ atomic_subtract_int(&stcb->asoc.refcnt, 1);
#endif
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
SCTP_FROM_SCTP_INPUT + SCTP_LOC_21);
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
- atomic_subtract_int(&stcb->asoc.refcnt, 1);
return (NULL);
} else {
/* remaining chunks checked... good to go */
stcb->asoc.authenticated = 1;
}
}
- /* update current state */
- SCTPDBG(SCTP_DEBUG_INPUT2, "moving to OPEN state\n");
- SCTP_SET_STATE(asoc, SCTP_STATE_OPEN);
- if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
- sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
- stcb->sctp_ep, stcb, asoc->primary_destination);
- }
- sctp_stop_all_cookie_timers(stcb);
- SCTP_STAT_INCR_COUNTER32(sctps_passiveestab);
- SCTP_STAT_INCR_GAUGE32(sctps_currestab);
-
/*
* if we're doing ASCONFs, check to see if we have any new local
* addresses that need to get added to the peer (eg. addresses
@@ -2297,21 +2286,32 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
break;
#endif
default:
- atomic_add_int(&stcb->asoc.refcnt, 1);
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+ atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
+ atomic_subtract_int(&stcb->asoc.refcnt, 1);
#endif
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
SCTP_FROM_SCTP_INPUT + SCTP_LOC_22);
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
- atomic_subtract_int(&stcb->asoc.refcnt, 1);
return (NULL);
}
+ /* update current state */
+ SCTPDBG(SCTP_DEBUG_INPUT2, "moving to OPEN state\n");
+ SCTP_SET_STATE(asoc, SCTP_STATE_OPEN);
+ if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
+ sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
+ stcb->sctp_ep, stcb, asoc->primary_destination);
+ }
+ sctp_stop_all_cookie_timers(stcb);
+ SCTP_STAT_INCR_COUNTER32(sctps_passiveestab);
+ SCTP_STAT_INCR_GAUGE32(sctps_currestab);
+
/* set up to notify upper layer */
*notification = SCTP_NOTIFY_ASSOC_UP;
if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
@@ -2443,6 +2443,12 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
cookie_offset = offset + sizeof(struct sctp_chunkhdr);
cookie_len = ntohs(cp->ch.chunk_length);
+ if (cookie_len < sizeof(struct sctp_cookie_echo_chunk) +
+ sizeof(struct sctp_init_chunk) +
+ sizeof(struct sctp_init_ack_chunk) + SCTP_SIGNATURE_SIZE) {
+ /* cookie too small */
+ return (NULL);
+ }
if ((cookie->peerport != sh->src_port) ||
(cookie->myport != sh->dest_port) ||
(cookie->my_vtag != sh->v_tag)) {
@@ -2455,12 +2461,6 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
*/
return (NULL);
}
- if (cookie_len < sizeof(struct sctp_cookie_echo_chunk) +
- sizeof(struct sctp_init_chunk) +
- sizeof(struct sctp_init_ack_chunk) + SCTP_SIGNATURE_SIZE) {
- /* cookie too small */
- return (NULL);
- }
/*
* split off the signature into its own mbuf (since it should not be
* calculated in the sctp_hmac_m() call).
@@ -3619,7 +3619,7 @@ sctp_handle_stream_reset_response(struct sctp_tcb *stcb,
struct sctp_stream_reset_response *respin)
{
uint16_t type;
- int lparm_len;
+ int lparam_len;
struct sctp_association *asoc = &stcb->asoc;
struct sctp_tmit_chunk *chk;
struct sctp_stream_reset_request *req_param;
@@ -3636,12 +3636,12 @@ sctp_handle_stream_reset_response(struct sctp_tcb *stcb,
if (req_param != NULL) {
stcb->asoc.str_reset_seq_out++;
type = ntohs(req_param->ph.param_type);
- lparm_len = ntohs(req_param->ph.param_length);
+ lparam_len = ntohs(req_param->ph.param_length);
if (type == SCTP_STR_RESET_OUT_REQUEST) {
int no_clear = 0;
req_out_param = (struct sctp_stream_reset_out_request *)req_param;
- number_entries = (lparm_len - sizeof(struct sctp_stream_reset_out_request)) / sizeof(uint16_t);
+ number_entries = (lparam_len - sizeof(struct sctp_stream_reset_out_request)) / sizeof(uint16_t);
asoc->stream_reset_out_is_outstanding = 0;
if (asoc->stream_reset_outstanding)
asoc->stream_reset_outstanding--;
@@ -3667,7 +3667,7 @@ sctp_handle_stream_reset_response(struct sctp_tcb *stcb,
}
} else if (type == SCTP_STR_RESET_IN_REQUEST) {
req_in_param = (struct sctp_stream_reset_in_request *)req_param;
- number_entries = (lparm_len - sizeof(struct sctp_stream_reset_in_request)) / sizeof(uint16_t);
+ number_entries = (lparam_len - sizeof(struct sctp_stream_reset_in_request)) / sizeof(uint16_t);
if (asoc->stream_reset_outstanding)
asoc->stream_reset_outstanding--;
if (action == SCTP_STREAM_RESET_RESULT_DENIED) {
@@ -5196,17 +5196,27 @@ process_control_chunks:
return (NULL);
}
}
- /*
+ /*-
* First are we accepting? We do this again here
* since it is possible that a previous endpoint WAS
* listening responded to a INIT-ACK and then
* closed. We opened and bound.. and are now no
* longer listening.
+ *
+ * XXXGL: notes on checking listen queue length.
+ * 1) SCTP_IS_LISTENING() doesn't necessarily mean
+ * SOLISTENING(), because a listening "UDP type"
+ * socket isn't listening in terms of the socket
+ * layer. It is a normal data flow socket, that
+ * can fork off new connections. Thus, we should
+ * look into sol_qlen only in case we are !UDP.
+ * 2) Checking sol_qlen in general requires locking
+ * the socket, and this code lacks that.
*/
-
if ((stcb == NULL) &&
(!SCTP_IS_LISTENING(inp) ||
- inp->sctp_socket->so_qlen >= inp->sctp_socket->so_qlimit)) {
+ (!(inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
+ inp->sctp_socket->sol_qlen >= inp->sctp_socket->sol_qlimit))) {
if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
(SCTP_BASE_SYSCTL(sctp_abort_if_one_2_one_hits_limit))) {
op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, "");
diff --git a/freebsd/sys/netinet/sctp_os_bsd.h b/freebsd/sys/netinet/sctp_os_bsd.h
index f2bea00e..194a03ed 100644
--- a/freebsd/sys/netinet/sctp_os_bsd.h
+++ b/freebsd/sys/netinet/sctp_os_bsd.h
@@ -392,8 +392,8 @@ typedef struct callout sctp_os_timer_t;
(sb).sb_mb = NULL; \
(sb).sb_mbcnt = 0;
-#define SCTP_SB_LIMIT_RCV(so) so->so_rcv.sb_hiwat
-#define SCTP_SB_LIMIT_SND(so) so->so_snd.sb_hiwat
+#define SCTP_SB_LIMIT_RCV(so) (SOLISTENING(so) ? so->sol_sbrcv_hiwat : so->so_rcv.sb_hiwat)
+#define SCTP_SB_LIMIT_SND(so) (SOLISTENING(so) ? so->sol_sbsnd_hiwat : so->so_snd.sb_hiwat)
/*
* routes, output, etc.
diff --git a/freebsd/sys/netinet/sctp_output.c b/freebsd/sys/netinet/sctp_output.c
index 221d0570..5e2fbbc2 100644
--- a/freebsd/sys/netinet/sctp_output.c
+++ b/freebsd/sys/netinet/sctp_output.c
@@ -1942,7 +1942,7 @@ static struct mbuf *
sctp_add_addr_to_mbuf(struct mbuf *m, struct sctp_ifa *ifa, uint16_t *len)
{
#if defined(INET) || defined(INET6)
- struct sctp_paramhdr *parmh;
+ struct sctp_paramhdr *paramh;
struct mbuf *mret;
uint16_t plen;
#endif
@@ -1964,7 +1964,7 @@ sctp_add_addr_to_mbuf(struct mbuf *m, struct sctp_ifa *ifa, uint16_t *len)
#if defined(INET) || defined(INET6)
if (M_TRAILINGSPACE(m) >= plen) {
/* easy side we just drop it on the end */
- parmh = (struct sctp_paramhdr *)(SCTP_BUF_AT(m, SCTP_BUF_LEN(m)));
+ paramh = (struct sctp_paramhdr *)(SCTP_BUF_AT(m, SCTP_BUF_LEN(m)));
mret = m;
} else {
/* Need more space */
@@ -1978,7 +1978,7 @@ sctp_add_addr_to_mbuf(struct mbuf *m, struct sctp_ifa *ifa, uint16_t *len)
return (m);
}
mret = SCTP_BUF_NEXT(mret);
- parmh = mtod(mret, struct sctp_paramhdr *);
+ paramh = mtod(mret, struct sctp_paramhdr *);
}
/* now add the parameter */
switch (ifa->address.sa.sa_family) {
@@ -1989,9 +1989,9 @@ sctp_add_addr_to_mbuf(struct mbuf *m, struct sctp_ifa *ifa, uint16_t *len)
struct sockaddr_in *sin;
sin = &ifa->address.sin;
- ipv4p = (struct sctp_ipv4addr_param *)parmh;
- parmh->param_type = htons(SCTP_IPV4_ADDRESS);
- parmh->param_length = htons(plen);
+ ipv4p = (struct sctp_ipv4addr_param *)paramh;
+ paramh->param_type = htons(SCTP_IPV4_ADDRESS);
+ paramh->param_length = htons(plen);
ipv4p->addr = sin->sin_addr.s_addr;
SCTP_BUF_LEN(mret) += plen;
break;
@@ -2004,9 +2004,9 @@ sctp_add_addr_to_mbuf(struct mbuf *m, struct sctp_ifa *ifa, uint16_t *len)
struct sockaddr_in6 *sin6;
sin6 = &ifa->address.sin6;
- ipv6p = (struct sctp_ipv6addr_param *)parmh;
- parmh->param_type = htons(SCTP_IPV6_ADDRESS);
- parmh->param_length = htons(plen);
+ ipv6p = (struct sctp_ipv6addr_param *)paramh;
+ paramh->param_type = htons(SCTP_IPV6_ADDRESS);
+ paramh->param_length = htons(plen);
memcpy(ipv6p->addr, &sin6->sin6_addr,
sizeof(ipv6p->addr));
/* clear embedded scope in the address */
@@ -4406,7 +4406,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
* we can try their selection but it may not be
* bound.
*/
- bzero(&lsa6_tmp, sizeof(lsa6_tmp));
+ memset(&lsa6_tmp, 0, sizeof(lsa6_tmp));
lsa6_tmp.sin6_family = AF_INET6;
lsa6_tmp.sin6_len = sizeof(lsa6_tmp);
lsa6 = &lsa6_tmp;
@@ -4491,7 +4491,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
* XXX: sa6 may not have a valid sin6_scope_id in
* the non-SCOPEDROUTING case.
*/
- bzero(&lsa6_storage, sizeof(lsa6_storage));
+ memset(&lsa6_storage, 0, sizeof(lsa6_storage));
lsa6_storage.sin6_family = AF_INET6;
lsa6_storage.sin6_len = sizeof(lsa6_storage);
lsa6_storage.sin6_addr = lsa6->sin6_addr;
@@ -5143,7 +5143,10 @@ sctp_arethere_unrecognized_parameters(struct mbuf *in_initpkt,
s.param_length = htons(sizeof(s) + plen);
m_copyback(op_err, err_at, sizeof(s), (caddr_t)&s);
err_at += sizeof(s);
- phdr = sctp_get_next_param(mat, at, (struct sctp_paramhdr *)tempbuf, min(sizeof(tempbuf), plen));
+ if (plen > sizeof(tempbuf)) {
+ plen = sizeof(tempbuf);
+ }
+ phdr = sctp_get_next_param(mat, at, (struct sctp_paramhdr *)tempbuf, plen);
if (phdr == NULL) {
sctp_m_freem(op_err);
/*
@@ -5211,7 +5214,7 @@ sctp_arethere_unrecognized_parameters(struct mbuf *in_initpkt,
if (plen > sizeof(tempbuf)) {
plen = sizeof(tempbuf);
}
- phdr = sctp_get_next_param(mat, at, (struct sctp_paramhdr *)tempbuf, min(sizeof(tempbuf), plen));
+ phdr = sctp_get_next_param(mat, at, (struct sctp_paramhdr *)tempbuf, plen);
if (phdr == NULL) {
sctp_m_freem(op_err);
/*
@@ -5392,10 +5395,12 @@ sctp_are_there_new_addresses(struct sctp_association *asoc,
{
struct sctp_ipv4addr_param *p4, p4_buf;
+ if (plen != sizeof(struct sctp_ipv4addr_param)) {
+ return (1);
+ }
phdr = sctp_get_next_param(in_initpkt, offset,
(struct sctp_paramhdr *)&p4_buf, sizeof(p4_buf));
- if (plen != sizeof(struct sctp_ipv4addr_param) ||
- phdr == NULL) {
+ if (phdr == NULL) {
return (1);
}
if (asoc->scope.ipv4_addr_legal) {
@@ -5411,10 +5416,12 @@ sctp_are_there_new_addresses(struct sctp_association *asoc,
{
struct sctp_ipv6addr_param *p6, p6_buf;
+ if (plen != sizeof(struct sctp_ipv6addr_param)) {
+ return (1);
+ }
phdr = sctp_get_next_param(in_initpkt, offset,
(struct sctp_paramhdr *)&p6_buf, sizeof(p6_buf));
- if (plen != sizeof(struct sctp_ipv6addr_param) ||
- phdr == NULL) {
+ if (phdr == NULL) {
return (1);
}
if (asoc->scope.ipv6_addr_legal) {
@@ -6245,11 +6252,7 @@ sctp_get_frag_point(struct sctp_tcb *stcb,
} else {
ovh = SCTP_MIN_V4_OVERHEAD;
}
- if (stcb->asoc.idata_supported) {
- ovh += sizeof(struct sctp_idata_chunk);
- } else {
- ovh += sizeof(struct sctp_data_chunk);
- }
+ ovh += SCTP_DATA_CHUNK_OVERHEAD(stcb);
if (stcb->asoc.sctp_frag_point > asoc->smallest_mtu)
siz = asoc->smallest_mtu - ovh;
else
@@ -6754,7 +6757,7 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
}
}
un_sent = ((stcb->asoc.total_output_queue_size - stcb->asoc.total_flight) +
- (stcb->asoc.stream_queue_cnt * sizeof(struct sctp_data_chunk)));
+ (stcb->asoc.stream_queue_cnt * SCTP_DATA_CHUNK_OVERHEAD(stcb)));
if ((sctp_is_feature_off(inp, SCTP_PCB_FLAGS_NODELAY)) &&
(stcb->asoc.total_flight > 0) &&
@@ -7454,11 +7457,7 @@ dont_do_it:
} else {
atomic_subtract_int(&sp->length, to_move);
}
- if (stcb->asoc.idata_supported == 0) {
- leading = sizeof(struct sctp_data_chunk);
- } else {
- leading = sizeof(struct sctp_idata_chunk);
- }
+ leading = SCTP_DATA_CHUNK_OVERHEAD(stcb);
if (M_LEADINGSPACE(chk->data) < leading) {
/* Not enough room for a chunk header, get some */
struct mbuf *m;
@@ -7500,11 +7499,7 @@ dont_do_it:
M_ALIGN(chk->data, 4);
}
}
- if (stcb->asoc.idata_supported == 0) {
- SCTP_BUF_PREPEND(chk->data, sizeof(struct sctp_data_chunk), M_NOWAIT);
- } else {
- SCTP_BUF_PREPEND(chk->data, sizeof(struct sctp_idata_chunk), M_NOWAIT);
- }
+ SCTP_BUF_PREPEND(chk->data, SCTP_DATA_CHUNK_OVERHEAD(stcb), M_NOWAIT);
if (chk->data == NULL) {
/* HELP, TSNH since we assured it would not above? */
#ifdef INVARIANTS
@@ -7517,13 +7512,8 @@ dont_do_it:
to_move = 0;
goto out_of;
}
- if (stcb->asoc.idata_supported == 0) {
- sctp_snd_sb_alloc(stcb, sizeof(struct sctp_data_chunk));
- chk->book_size = chk->send_size = (uint16_t)(to_move + sizeof(struct sctp_data_chunk));
- } else {
- sctp_snd_sb_alloc(stcb, sizeof(struct sctp_idata_chunk));
- chk->book_size = chk->send_size = (uint16_t)(to_move + sizeof(struct sctp_idata_chunk));
- }
+ sctp_snd_sb_alloc(stcb, SCTP_DATA_CHUNK_OVERHEAD(stcb));
+ chk->book_size = chk->send_size = (uint16_t)(to_move + SCTP_DATA_CHUNK_OVERHEAD(stcb));
chk->book_size_scale = 0;
chk->sent = SCTP_DATAGRAM_UNSENT;
@@ -7723,11 +7713,7 @@ sctp_fill_outqueue(struct sctp_tcb *stcb,
break;
}
/* Need an allowance for the data chunk header too */
- if (stcb->asoc.idata_supported == 0) {
- space_left -= sizeof(struct sctp_data_chunk);
- } else {
- space_left -= sizeof(struct sctp_idata_chunk);
- }
+ space_left -= SCTP_DATA_CHUNK_OVERHEAD(stcb);
/* must make even word boundary */
space_left &= 0xfffffffc;
@@ -7744,18 +7730,10 @@ sctp_fill_outqueue(struct sctp_tcb *stcb,
strq = stcb->asoc.ss_functions.sctp_ss_select_stream(stcb, net, asoc);
total_moved += moved;
space_left -= moved;
- if (stcb->asoc.idata_supported == 0) {
- if (space_left >= sizeof(struct sctp_data_chunk)) {
- space_left -= sizeof(struct sctp_data_chunk);
- } else {
- space_left = 0;
- }
+ if (space_left >= SCTP_DATA_CHUNK_OVERHEAD(stcb)) {
+ space_left -= SCTP_DATA_CHUNK_OVERHEAD(stcb);
} else {
- if (space_left >= sizeof(struct sctp_idata_chunk)) {
- space_left -= sizeof(struct sctp_idata_chunk);
- } else {
- space_left = 0;
- }
+ space_left = 0;
}
space_left &= 0xfffffffc;
}
@@ -9002,7 +8980,7 @@ sctp_send_cookie_echo(struct mbuf *m,
*/
int at;
struct mbuf *cookie;
- struct sctp_paramhdr parm, *phdr;
+ struct sctp_paramhdr param, *phdr;
struct sctp_chunkhdr *hdr;
struct sctp_tmit_chunk *chk;
uint16_t ptype, plen;
@@ -9012,7 +8990,7 @@ sctp_send_cookie_echo(struct mbuf *m,
cookie = NULL;
at = offset + sizeof(struct sctp_init_chunk);
for (;;) {
- phdr = sctp_get_next_param(m, at, &parm, sizeof(parm));
+ phdr = sctp_get_next_param(m, at, &param, sizeof(param));
if (phdr == NULL) {
return (-3);
}
@@ -10204,8 +10182,7 @@ do_it_again:
* and we have data in flight we stop, except if we
* are handling a fragmented user message.
*/
- un_sent = ((stcb->asoc.total_output_queue_size - stcb->asoc.total_flight) +
- (stcb->asoc.stream_queue_cnt * sizeof(struct sctp_data_chunk)));
+ un_sent = stcb->asoc.total_output_queue_size - stcb->asoc.total_flight;
if ((un_sent < (int)(stcb->asoc.smallest_mtu - SCTP_MIN_OVERHEAD)) &&
(stcb->asoc.total_flight > 0)) {
/* && sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR))) {*/
@@ -12443,7 +12420,7 @@ sctp_copy_it_in(struct sctp_tcb *stcb,
sp->sender_all_done = 0;
sp->some_taken = 0;
sp->put_last_out = 0;
- resv_in_first = sizeof(struct sctp_data_chunk);
+ resv_in_first = SCTP_DATA_CHUNK_OVERHEAD(stcb);
sp->data = sp->tail_mbuf = NULL;
if (sp->length == 0) {
*error = 0;
@@ -12860,12 +12837,19 @@ sctp_lower_sosend(struct socket *so,
}
/* would we block? */
if (non_blocking) {
+ uint32_t amount;
+
if (hold_tcblock == 0) {
SCTP_TCB_LOCK(stcb);
hold_tcblock = 1;
}
- inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * sizeof(struct sctp_data_chunk));
- if ((SCTP_SB_LIMIT_SND(so) < (sndlen + inqueue_bytes + stcb->asoc.sb_send_resv)) ||
+ inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb));
+ if (user_marks_eor == 0) {
+ amount = sndlen;
+ } else {
+ amount = 1;
+ }
+ if ((SCTP_SB_LIMIT_SND(so) < (amount + inqueue_bytes + stcb->asoc.sb_send_resv)) ||
(stcb->asoc.chunks_on_out_queue >= SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue))) {
SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EWOULDBLOCK);
if (sndlen > SCTP_SB_LIMIT_SND(so))
@@ -13033,7 +13017,7 @@ sctp_lower_sosend(struct socket *so,
goto out_unlocked;
}
/* Calculate the maximum we can send */
- inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * sizeof(struct sctp_data_chunk));
+ inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb));
if (SCTP_SB_LIMIT_SND(so) > inqueue_bytes) {
if (non_blocking) {
/* we already checked for non-blocking above. */
@@ -13090,7 +13074,7 @@ sctp_lower_sosend(struct socket *so,
((stcb->asoc.chunks_on_out_queue + stcb->asoc.stream_queue_cnt) >= SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue))) {
/* No room right now ! */
SOCKBUF_LOCK(&so->so_snd);
- inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * sizeof(struct sctp_data_chunk));
+ inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb));
while ((SCTP_SB_LIMIT_SND(so) < (inqueue_bytes + local_add_more)) ||
((stcb->asoc.stream_queue_cnt + stcb->asoc.chunks_on_out_queue) >= SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue))) {
SCTPDBG(SCTP_DEBUG_OUTPUT1, "pre_block limit:%u <(inq:%d + %d) || (%d+%d > %d)\n",
@@ -13126,7 +13110,7 @@ sctp_lower_sosend(struct socket *so,
SOCKBUF_UNLOCK(&so->so_snd);
goto out_unlocked;
}
- inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * sizeof(struct sctp_data_chunk));
+ inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb));
}
if (SCTP_SB_LIMIT_SND(so) > inqueue_bytes) {
max_len = SCTP_SB_LIMIT_SND(so) - inqueue_bytes;
@@ -13219,8 +13203,9 @@ skip_preblock:
/* How much room do we have? */
struct mbuf *new_tail, *mm;
- if (SCTP_SB_LIMIT_SND(so) > stcb->asoc.total_output_queue_size)
- max_len = SCTP_SB_LIMIT_SND(so) - stcb->asoc.total_output_queue_size;
+ inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb));
+ if (SCTP_SB_LIMIT_SND(so) > inqueue_bytes)
+ max_len = SCTP_SB_LIMIT_SND(so) - inqueue_bytes;
else
max_len = 0;
@@ -13296,8 +13281,8 @@ skip_preblock:
hold_tcblock = 1;
}
sctp_prune_prsctp(stcb, asoc, srcv, sndlen);
- inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * sizeof(struct sctp_data_chunk));
- if (SCTP_SB_LIMIT_SND(so) > stcb->asoc.total_output_queue_size)
+ inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb));
+ if (SCTP_SB_LIMIT_SND(so) > inqueue_bytes)
max_len = SCTP_SB_LIMIT_SND(so) - inqueue_bytes;
else
max_len = 0;
@@ -13338,8 +13323,7 @@ skip_preblock:
}
asoc->ifp_had_enobuf = 0;
}
- un_sent = ((stcb->asoc.total_output_queue_size - stcb->asoc.total_flight) +
- (stcb->asoc.stream_queue_cnt * sizeof(struct sctp_data_chunk)));
+ un_sent = stcb->asoc.total_output_queue_size - stcb->asoc.total_flight;
if ((sctp_is_feature_off(inp, SCTP_PCB_FLAGS_NODELAY)) &&
(stcb->asoc.total_flight > 0) &&
(stcb->asoc.stream_queue_cnt < SCTP_MAX_DATA_BUNDLING) &&
@@ -13413,7 +13397,8 @@ skip_preblock:
* size we KNOW we will get to sleep safely with the
* wakeup flag in place.
*/
- if (SCTP_SB_LIMIT_SND(so) <= (stcb->asoc.total_output_queue_size +
+ inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb));
+ if (SCTP_SB_LIMIT_SND(so) <= (inqueue_bytes +
min(SCTP_BASE_SYSCTL(sctp_add_more_threshold), SCTP_SB_LIMIT_SND(so)))) {
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_BLK_LOGGING_ENABLE) {
sctp_log_block(SCTP_BLOCK_LOG_INTO_BLK,
@@ -13610,8 +13595,7 @@ skip_out_eof:
}
asoc->ifp_had_enobuf = 0;
}
- un_sent = ((stcb->asoc.total_output_queue_size - stcb->asoc.total_flight) +
- (stcb->asoc.stream_queue_cnt * sizeof(struct sctp_data_chunk)));
+ un_sent = stcb->asoc.total_output_queue_size - stcb->asoc.total_flight;
if ((sctp_is_feature_off(inp, SCTP_PCB_FLAGS_NODELAY)) &&
(stcb->asoc.total_flight > 0) &&
(stcb->asoc.stream_queue_cnt < SCTP_MAX_DATA_BUNDLING) &&
@@ -13750,7 +13734,7 @@ sctp_add_auth_chunk(struct mbuf *m, struct mbuf **m_end,
SCTP_BUF_RESV_UF(m_auth, SCTP_MIN_OVERHEAD);
/* fill in the AUTH chunk details */
auth = mtod(m_auth, struct sctp_auth_chunk *);
- bzero(auth, sizeof(*auth));
+ memset(auth, 0, sizeof(*auth));
auth->ch.chunk_type = SCTP_AUTHENTICATION;
auth->ch.chunk_flags = 0;
chunk_len = sizeof(*auth) +
diff --git a/freebsd/sys/netinet/sctp_output.h b/freebsd/sys/netinet/sctp_output.h
index cd90b7d7..32f968c1 100644
--- a/freebsd/sys/netinet/sctp_output.h
+++ b/freebsd/sys/netinet/sctp_output.h
@@ -135,6 +135,11 @@ void sctp_fix_ecn_echo(struct sctp_association *);
void sctp_move_chunks_from_net(struct sctp_tcb *stcb, struct sctp_nets *net);
+
+#define SCTP_DATA_CHUNK_OVERHEAD(stcb) ((stcb)->asoc.idata_supported ? \
+ sizeof(struct sctp_idata_chunk) : \
+ sizeof(struct sctp_data_chunk))
+
int
sctp_output(struct sctp_inpcb *, struct mbuf *, struct sockaddr *,
struct mbuf *, struct thread *, int);
diff --git a/freebsd/sys/netinet/sctp_pcb.c b/freebsd/sys/netinet/sctp_pcb.c
index e32e63f4..1907991e 100644
--- a/freebsd/sys/netinet/sctp_pcb.c
+++ b/freebsd/sys/netinet/sctp_pcb.c
@@ -704,7 +704,7 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index,
return (NULL);
}
SCTP_INCR_LADDR_COUNT();
- bzero(wi, sizeof(*wi));
+ memset(wi, 0, sizeof(*wi));
(void)SCTP_GETTIME_TIMEVAL(&wi->start_time);
wi->ifa = sctp_ifap;
wi->action = SCTP_ADD_IP_ADDRESS;
@@ -813,7 +813,7 @@ out_now:
return;
}
SCTP_INCR_LADDR_COUNT();
- bzero(wi, sizeof(*wi));
+ memset(wi, 0, sizeof(*wi));
(void)SCTP_GETTIME_TIMEVAL(&wi->start_time);
wi->ifa = sctp_ifap;
wi->action = SCTP_DEL_IP_ADDRESS;
@@ -2048,7 +2048,7 @@ sctp_findassociation_special_addr(struct mbuf *m, int offset,
struct sctphdr *sh, struct sctp_inpcb **inp_p, struct sctp_nets **netp,
struct sockaddr *dst)
{
- struct sctp_paramhdr *phdr, parm_buf;
+ struct sctp_paramhdr *phdr, param_buf;
#if defined(INET) || defined(INET6)
struct sctp_tcb *stcb;
uint16_t ptype;
@@ -2076,7 +2076,7 @@ sctp_findassociation_special_addr(struct mbuf *m, int offset,
offset += sizeof(struct sctp_init_chunk);
- phdr = sctp_get_next_param(m, offset, &parm_buf, sizeof(parm_buf));
+ phdr = sctp_get_next_param(m, offset, &param_buf, sizeof(param_buf));
while (phdr != NULL) {
/* now we must see if we want the parameter */
#if defined(INET) || defined(INET6)
@@ -2090,10 +2090,10 @@ sctp_findassociation_special_addr(struct mbuf *m, int offset,
if (ptype == SCTP_IPV4_ADDRESS &&
plen == sizeof(struct sctp_ipv4addr_param)) {
/* Get the rest of the address */
- struct sctp_ipv4addr_param ip4_parm, *p4;
+ struct sctp_ipv4addr_param ip4_param, *p4;
phdr = sctp_get_next_param(m, offset,
- (struct sctp_paramhdr *)&ip4_parm, min(plen, sizeof(ip4_parm)));
+ (struct sctp_paramhdr *)&ip4_param, sizeof(ip4_param));
if (phdr == NULL) {
return (NULL);
}
@@ -2111,10 +2111,10 @@ sctp_findassociation_special_addr(struct mbuf *m, int offset,
if (ptype == SCTP_IPV6_ADDRESS &&
plen == sizeof(struct sctp_ipv6addr_param)) {
/* Get the rest of the address */
- struct sctp_ipv6addr_param ip6_parm, *p6;
+ struct sctp_ipv6addr_param ip6_param, *p6;
phdr = sctp_get_next_param(m, offset,
- (struct sctp_paramhdr *)&ip6_parm, min(plen, sizeof(ip6_parm)));
+ (struct sctp_paramhdr *)&ip6_param, sizeof(ip6_param));
if (phdr == NULL) {
return (NULL);
}
@@ -2129,8 +2129,8 @@ sctp_findassociation_special_addr(struct mbuf *m, int offset,
}
#endif
offset += SCTP_SIZE32(plen);
- phdr = sctp_get_next_param(m, offset, &parm_buf,
- sizeof(parm_buf));
+ phdr = sctp_get_next_param(m, offset, &param_buf,
+ sizeof(param_buf));
}
return (NULL);
}
@@ -2303,7 +2303,7 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int offset,
{
struct sctp_tcb *stcb;
union sctp_sockstore remote_store;
- struct sctp_paramhdr parm_buf, *phdr;
+ struct sctp_paramhdr param_buf, *phdr;
int ptype;
int zero_address = 0;
#ifdef INET
@@ -2315,7 +2315,7 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int offset,
memset(&remote_store, 0, sizeof(remote_store));
phdr = sctp_get_next_param(m, offset + sizeof(struct sctp_asconf_chunk),
- &parm_buf, sizeof(struct sctp_paramhdr));
+ &param_buf, sizeof(struct sctp_paramhdr));
if (phdr == NULL) {
SCTPDBG(SCTP_DEBUG_INPUT3, "%s: failed to get asconf lookup addr\n",
__func__);
@@ -2335,7 +2335,7 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int offset,
}
p6 = (struct sctp_ipv6addr_param *)sctp_get_next_param(m,
offset + sizeof(struct sctp_asconf_chunk),
- &p6_buf.ph, sizeof(*p6));
+ &p6_buf.ph, sizeof(p6_buf));
if (p6 == NULL) {
SCTPDBG(SCTP_DEBUG_INPUT3, "%s: failed to get asconf v6 lookup addr\n",
__func__);
@@ -2362,7 +2362,7 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int offset,
}
p4 = (struct sctp_ipv4addr_param *)sctp_get_next_param(m,
offset + sizeof(struct sctp_asconf_chunk),
- &p4_buf.ph, sizeof(*p4));
+ &p4_buf.ph, sizeof(p4_buf));
if (p4 == NULL) {
SCTPDBG(SCTP_DEBUG_INPUT3, "%s: failed to get asconf v4 lookup addr\n",
__func__);
@@ -2431,7 +2431,7 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
return (ENOBUFS);
}
/* zap it */
- bzero(inp, sizeof(*inp));
+ memset(inp, 0, sizeof(*inp));
/* bump generations */
/* setup socket pointers */
@@ -2717,7 +2717,7 @@ sctp_move_pcb_and_assoc(struct sctp_inpcb *old_inp, struct sctp_inpcb *new_inp,
continue;
}
SCTP_INCR_LADDR_COUNT();
- bzero(laddr, sizeof(*laddr));
+ memset(laddr, 0, sizeof(*laddr));
(void)SCTP_GETTIME_TIMEVAL(&laddr->start_time);
laddr->ifa = oladdr->ifa;
atomic_add_int(&laddr->ifa->refcount, 1);
@@ -2767,7 +2767,7 @@ sctp_insert_laddr(struct sctpladdr *list, struct sctp_ifa *ifa, uint32_t act)
return (EINVAL);
}
SCTP_INCR_LADDR_COUNT();
- bzero(laddr, sizeof(*laddr));
+ memset(laddr, 0, sizeof(*laddr));
(void)SCTP_GETTIME_TIMEVAL(&laddr->start_time);
laddr->ifa = ifa;
laddr->action = act;
@@ -3770,7 +3770,7 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
/* Invalid address */
return (-1);
}
- /* zero out the bzero area */
+ /* zero out the zero area */
memset(&sin->sin_zero, 0, sizeof(sin->sin_zero));
/* assure len is set */
@@ -3853,7 +3853,7 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
return (-1);
}
SCTP_INCR_RADDR_COUNT();
- bzero(net, sizeof(struct sctp_nets));
+ memset(net, 0, sizeof(struct sctp_nets));
(void)SCTP_GETTIME_TIMEVAL(&net->start_time);
memcpy(&net->ro._l_addr, newaddr, newaddr->sa_len);
switch (newaddr->sa_family) {
@@ -4289,7 +4289,7 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
}
SCTP_INCR_ASOC_COUNT();
- bzero(stcb, sizeof(*stcb));
+ memset(stcb, 0, sizeof(*stcb));
asoc = &stcb->asoc;
asoc->assoc_id = sctp_aloc_a_assoc_id(inp, stcb);
@@ -4603,21 +4603,21 @@ void
sctp_clean_up_stream(struct sctp_tcb *stcb, struct sctp_readhead *rh)
{
struct sctp_tmit_chunk *chk, *nchk;
- struct sctp_queued_to_read *ctl, *nctl;
+ struct sctp_queued_to_read *control, *ncontrol;
- TAILQ_FOREACH_SAFE(ctl, rh, next_instrm, nctl) {
- TAILQ_REMOVE(rh, ctl, next_instrm);
- ctl->on_strm_q = 0;
- if (ctl->on_read_q == 0) {
- sctp_free_remote_addr(ctl->whoFrom);
- if (ctl->data) {
- sctp_m_freem(ctl->data);
- ctl->data = NULL;
+ TAILQ_FOREACH_SAFE(control, rh, next_instrm, ncontrol) {
+ TAILQ_REMOVE(rh, control, next_instrm);
+ control->on_strm_q = 0;
+ if (control->on_read_q == 0) {
+ sctp_free_remote_addr(control->whoFrom);
+ if (control->data) {
+ sctp_m_freem(control->data);
+ control->data = NULL;
}
}
/* Reassembly free? */
- TAILQ_FOREACH_SAFE(chk, &ctl->reasm, sctp_next, nchk) {
- TAILQ_REMOVE(&ctl->reasm, chk, sctp_next);
+ TAILQ_FOREACH_SAFE(chk, &control->reasm, sctp_next, nchk) {
+ TAILQ_REMOVE(&control->reasm, chk, sctp_next);
if (chk->data) {
sctp_m_freem(chk->data);
chk->data = NULL;
@@ -4633,8 +4633,8 @@ sctp_clean_up_stream(struct sctp_tcb *stcb, struct sctp_readhead *rh)
* We don't free the address here since all the net's were
* freed above.
*/
- if (ctl->on_read_q == 0) {
- sctp_free_a_readq(stcb, ctl);
+ if (control->on_read_q == 0) {
+ sctp_free_a_readq(stcb, control);
}
}
}
@@ -4860,7 +4860,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
inp->sctp_flags &= ~SCTP_PCB_FLAGS_CONNECTED;
inp->sctp_flags |= SCTP_PCB_FLAGS_WAS_CONNECTED;
if (so) {
- SOCK_LOCK(so);
+ SOCKBUF_LOCK(&so->so_rcv);
if (so->so_rcv.sb_cc == 0) {
so->so_state &= ~(SS_ISCONNECTING |
SS_ISDISCONNECTING |
@@ -5735,7 +5735,7 @@ sctp_pcb_init()
SCTP_BASE_VAR(sctp_pcb_initialized) = 1;
#if defined(SCTP_LOCAL_TRACE_BUF)
- bzero(&SCTP_BASE_SYSCTL(sctp_log), sizeof(struct sctp_log));
+ memset(&SCTP_BASE_SYSCTL(sctp_log), 0, sizeof(struct sctp_log));
#endif
#if defined(__FreeBSD__) && defined(SMP) && defined(SCTP_USE_PERCPU_STAT)
SCTP_MALLOC(SCTP_BASE_STATS, struct sctpstat *,
@@ -5744,11 +5744,11 @@ sctp_pcb_init()
#endif
(void)SCTP_GETTIME_TIMEVAL(&tv);
#if defined(__FreeBSD__) && defined(SMP) && defined(SCTP_USE_PERCPU_STAT)
- bzero(SCTP_BASE_STATS, (sizeof(struct sctpstat) * (mp_maxid + 1)));
+ memset(SCTP_BASE_STATS, 0, sizeof(struct sctpstat) * (mp_maxid + 1));
SCTP_BASE_STATS[PCPU_GET(cpuid)].sctps_discontinuitytime.tv_sec = (uint32_t)tv.tv_sec;
SCTP_BASE_STATS[PCPU_GET(cpuid)].sctps_discontinuitytime.tv_usec = (uint32_t)tv.tv_usec;
#else
- bzero(&SCTP_BASE_STATS, sizeof(struct sctpstat));
+ memset(&SCTP_BASE_STATS, 0, sizeof(struct sctpstat));
SCTP_BASE_STAT(sctps_discontinuitytime).tv_sec = (uint32_t)tv.tv_sec;
SCTP_BASE_STAT(sctps_discontinuitytime).tv_usec = (uint32_t)tv.tv_usec;
#endif
@@ -6030,7 +6030,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
*/
struct sctp_inpcb *inp;
struct sctp_nets *net, *nnet, *net_tmp;
- struct sctp_paramhdr *phdr, parm_buf;
+ struct sctp_paramhdr *phdr, param_buf;
struct sctp_tcb *stcb_tmp;
uint16_t ptype, plen;
struct sockaddr *sa;
@@ -6140,7 +6140,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
return (-4);
}
/* now we must go through each of the params. */
- phdr = sctp_get_next_param(m, offset, &parm_buf, sizeof(parm_buf));
+ phdr = sctp_get_next_param(m, offset, &param_buf, sizeof(param_buf));
while (phdr) {
ptype = ntohs(phdr->param_type);
plen = ntohs(phdr->param_length);
@@ -6378,7 +6378,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
}
phdr = sctp_get_next_param(m, offset,
(struct sctp_paramhdr *)&lstore,
- min(plen, sizeof(lstore)));
+ plen);
if (phdr == NULL) {
return (-24);
}
@@ -6431,8 +6431,11 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
uint8_t local_store[SCTP_PARAM_BUFFER_SIZE];
int num_ent, i;
+ if (plen > sizeof(local_store)) {
+ return (-35);
+ }
phdr = sctp_get_next_param(m, offset,
- (struct sctp_paramhdr *)&local_store, min(sizeof(local_store), plen));
+ (struct sctp_paramhdr *)&local_store, plen);
if (phdr == NULL) {
return (-25);
}
@@ -6479,7 +6482,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
}
phdr = sctp_get_next_param(m, offset,
(struct sctp_paramhdr *)random_store,
- min(sizeof(random_store), plen));
+ plen);
if (phdr == NULL)
return (-26);
p_random = (struct sctp_auth_random *)phdr;
@@ -6502,7 +6505,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
}
phdr = sctp_get_next_param(m, offset,
(struct sctp_paramhdr *)hmacs_store,
- min(plen, sizeof(hmacs_store)));
+ plen);
if (phdr == NULL)
return (-28);
hmacs = (struct sctp_auth_hmac_algo *)phdr;
@@ -6533,7 +6536,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
}
phdr = sctp_get_next_param(m, offset,
(struct sctp_paramhdr *)chunks_store,
- min(plen, sizeof(chunks_store)));
+ plen);
if (phdr == NULL)
return (-30);
chunks = (struct sctp_auth_chunk_list *)phdr;
@@ -6581,8 +6584,8 @@ next_param:
if (offset >= limit) {
break;
}
- phdr = sctp_get_next_param(m, offset, &parm_buf,
- sizeof(parm_buf));
+ phdr = sctp_get_next_param(m, offset, &param_buf,
+ sizeof(param_buf));
}
/* Now check to see if we need to purge any addresses */
TAILQ_FOREACH_SAFE(net, &stcb->asoc.nets, sctp_next, nnet) {
@@ -6657,17 +6660,17 @@ next_param:
/* copy in the RANDOM */
if (p_random != NULL) {
keylen = sizeof(*p_random) + random_len;
- bcopy(p_random, new_key->key, keylen);
+ memcpy(new_key->key, p_random, keylen);
}
/* append in the AUTH chunks */
if (chunks != NULL) {
- bcopy(chunks, new_key->key + keylen,
+ memcpy(new_key->key + keylen, chunks,
sizeof(*chunks) + num_chunks);
keylen += sizeof(*chunks) + num_chunks;
}
/* append in the HMACs */
if (hmacs != NULL) {
- bcopy(hmacs, new_key->key + keylen,
+ memcpy(new_key->key + keylen, hmacs,
sizeof(*hmacs) + hmacs_len);
}
} else {
@@ -6802,7 +6805,7 @@ sctp_drain_mbufs(struct sctp_tcb *stcb)
struct sctp_association *asoc;
struct sctp_tmit_chunk *chk, *nchk;
uint32_t cumulative_tsn_p1;
- struct sctp_queued_to_read *ctl, *nctl;
+ struct sctp_queued_to_read *control, *ncontrol;
int cnt, strmat;
uint32_t gap, i;
int fnd = 0;
@@ -6819,88 +6822,124 @@ sctp_drain_mbufs(struct sctp_tcb *stcb)
cnt = 0;
/* Ok that was fun, now we will drain all the inbound streams? */
for (strmat = 0; strmat < asoc->streamincnt; strmat++) {
- TAILQ_FOREACH_SAFE(ctl, &asoc->strmin[strmat].inqueue, next_instrm, nctl) {
+ TAILQ_FOREACH_SAFE(control, &asoc->strmin[strmat].inqueue, next_instrm, ncontrol) {
#ifdef INVARIANTS
- if (ctl->on_strm_q != SCTP_ON_ORDERED) {
+ if (control->on_strm_q != SCTP_ON_ORDERED) {
panic("Huh control: %p on_q: %d -- not ordered?",
- ctl, ctl->on_strm_q);
+ control, control->on_strm_q);
}
#endif
- if (SCTP_TSN_GT(ctl->sinfo_tsn, cumulative_tsn_p1)) {
+ if (SCTP_TSN_GT(control->sinfo_tsn, cumulative_tsn_p1)) {
/* Yep it is above cum-ack */
cnt++;
- SCTP_CALC_TSN_TO_GAP(gap, ctl->sinfo_tsn, asoc->mapping_array_base_tsn);
- asoc->size_on_all_streams = sctp_sbspace_sub(asoc->size_on_all_streams, ctl->length);
+ SCTP_CALC_TSN_TO_GAP(gap, control->sinfo_tsn, asoc->mapping_array_base_tsn);
+ KASSERT(control->length > 0, ("control has zero length"));
+ if (asoc->size_on_all_streams >= control->length) {
+ asoc->size_on_all_streams -= control->length;
+ } else {
+#ifdef INVARIANTS
+ panic("size_on_all_streams = %u smaller than control length %u", asoc->size_on_all_streams, control->length);
+#else
+ asoc->size_on_all_streams = 0;
+#endif
+ }
sctp_ucount_decr(asoc->cnt_on_all_streams);
SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, gap);
- if (ctl->on_read_q) {
- TAILQ_REMOVE(&stcb->sctp_ep->read_queue, ctl, next);
- ctl->on_read_q = 0;
+ if (control->on_read_q) {
+ TAILQ_REMOVE(&stcb->sctp_ep->read_queue, control, next);
+ control->on_read_q = 0;
}
- TAILQ_REMOVE(&asoc->strmin[strmat].inqueue, ctl, next_instrm);
- ctl->on_strm_q = 0;
- if (ctl->data) {
- sctp_m_freem(ctl->data);
- ctl->data = NULL;
+ TAILQ_REMOVE(&asoc->strmin[strmat].inqueue, control, next_instrm);
+ control->on_strm_q = 0;
+ if (control->data) {
+ sctp_m_freem(control->data);
+ control->data = NULL;
}
- sctp_free_remote_addr(ctl->whoFrom);
+ sctp_free_remote_addr(control->whoFrom);
/* Now its reasm? */
- TAILQ_FOREACH_SAFE(chk, &ctl->reasm, sctp_next, nchk) {
+ TAILQ_FOREACH_SAFE(chk, &control->reasm, sctp_next, nchk) {
cnt++;
SCTP_CALC_TSN_TO_GAP(gap, chk->rec.data.tsn, asoc->mapping_array_base_tsn);
- asoc->size_on_reasm_queue = sctp_sbspace_sub(asoc->size_on_reasm_queue, chk->send_size);
+ KASSERT(chk->send_size > 0, ("chunk has zero length"));
+ if (asoc->size_on_reasm_queue >= chk->send_size) {
+ asoc->size_on_reasm_queue -= chk->send_size;
+ } else {
+#ifdef INVARIANTS
+ panic("size_on_reasm_queue = %u smaller than chunk length %u", asoc->size_on_reasm_queue, chk->send_size);
+#else
+ asoc->size_on_reasm_queue = 0;
+#endif
+ }
sctp_ucount_decr(asoc->cnt_on_reasm_queue);
SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, gap);
- TAILQ_REMOVE(&ctl->reasm, chk, sctp_next);
+ TAILQ_REMOVE(&control->reasm, chk, sctp_next);
if (chk->data) {
sctp_m_freem(chk->data);
chk->data = NULL;
}
sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
}
- sctp_free_a_readq(stcb, ctl);
+ sctp_free_a_readq(stcb, control);
}
}
- TAILQ_FOREACH_SAFE(ctl, &asoc->strmin[strmat].uno_inqueue, next_instrm, nctl) {
+ TAILQ_FOREACH_SAFE(control, &asoc->strmin[strmat].uno_inqueue, next_instrm, ncontrol) {
#ifdef INVARIANTS
- if (ctl->on_strm_q != SCTP_ON_UNORDERED) {
+ if (control->on_strm_q != SCTP_ON_UNORDERED) {
panic("Huh control: %p on_q: %d -- not unordered?",
- ctl, ctl->on_strm_q);
+ control, control->on_strm_q);
}
#endif
- if (SCTP_TSN_GT(ctl->sinfo_tsn, cumulative_tsn_p1)) {
+ if (SCTP_TSN_GT(control->sinfo_tsn, cumulative_tsn_p1)) {
/* Yep it is above cum-ack */
cnt++;
- SCTP_CALC_TSN_TO_GAP(gap, ctl->sinfo_tsn, asoc->mapping_array_base_tsn);
- asoc->size_on_all_streams = sctp_sbspace_sub(asoc->size_on_all_streams, ctl->length);
+ SCTP_CALC_TSN_TO_GAP(gap, control->sinfo_tsn, asoc->mapping_array_base_tsn);
+ KASSERT(control->length > 0, ("control has zero length"));
+ if (asoc->size_on_all_streams >= control->length) {
+ asoc->size_on_all_streams -= control->length;
+ } else {
+#ifdef INVARIANTS
+ panic("size_on_all_streams = %u smaller than control length %u", asoc->size_on_all_streams, control->length);
+#else
+ asoc->size_on_all_streams = 0;
+#endif
+ }
sctp_ucount_decr(asoc->cnt_on_all_streams);
SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, gap);
- if (ctl->on_read_q) {
- TAILQ_REMOVE(&stcb->sctp_ep->read_queue, ctl, next);
- ctl->on_read_q = 0;
+ if (control->on_read_q) {
+ TAILQ_REMOVE(&stcb->sctp_ep->read_queue, control, next);
+ control->on_read_q = 0;
}
- TAILQ_REMOVE(&asoc->strmin[strmat].uno_inqueue, ctl, next_instrm);
- ctl->on_strm_q = 0;
- if (ctl->data) {
- sctp_m_freem(ctl->data);
- ctl->data = NULL;
+ TAILQ_REMOVE(&asoc->strmin[strmat].uno_inqueue, control, next_instrm);
+ control->on_strm_q = 0;
+ if (control->data) {
+ sctp_m_freem(control->data);
+ control->data = NULL;
}
- sctp_free_remote_addr(ctl->whoFrom);
+ sctp_free_remote_addr(control->whoFrom);
/* Now its reasm? */
- TAILQ_FOREACH_SAFE(chk, &ctl->reasm, sctp_next, nchk) {
+ TAILQ_FOREACH_SAFE(chk, &control->reasm, sctp_next, nchk) {
cnt++;
SCTP_CALC_TSN_TO_GAP(gap, chk->rec.data.tsn, asoc->mapping_array_base_tsn);
- asoc->size_on_reasm_queue = sctp_sbspace_sub(asoc->size_on_reasm_queue, chk->send_size);
+ KASSERT(chk->send_size > 0, ("chunk has zero length"));
+ if (asoc->size_on_reasm_queue >= chk->send_size) {
+ asoc->size_on_reasm_queue -= chk->send_size;
+ } else {
+#ifdef INVARIANTS
+ panic("size_on_reasm_queue = %u smaller than chunk length %u", asoc->size_on_reasm_queue, chk->send_size);
+#else
+ asoc->size_on_reasm_queue = 0;
+#endif
+ }
sctp_ucount_decr(asoc->cnt_on_reasm_queue);
SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, gap);
- TAILQ_REMOVE(&ctl->reasm, chk, sctp_next);
+ TAILQ_REMOVE(&control->reasm, chk, sctp_next);
if (chk->data) {
sctp_m_freem(chk->data);
chk->data = NULL;
}
sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
}
- sctp_free_a_readq(stcb, ctl);
+ sctp_free_a_readq(stcb, control);
}
}
}
diff --git a/freebsd/sys/netinet/sctp_sysctl.c b/freebsd/sys/netinet/sctp_sysctl.c
index db150112..a2364431 100644
--- a/freebsd/sys/netinet/sctp_sysctl.c
+++ b/freebsd/sys/netinet/sctp_sysctl.c
@@ -417,12 +417,12 @@ sctp_sysctl_handle_assoclist(SYSCTL_HANDLER_ARGS)
xinpcb.qlen = 0;
xinpcb.maxqlen = 0;
} else {
- xinpcb.qlen = so->so_qlen;
- xinpcb.qlen_old = so->so_qlen > USHRT_MAX ?
- USHRT_MAX : (uint16_t)so->so_qlen;
- xinpcb.maxqlen = so->so_qlimit;
- xinpcb.maxqlen_old = so->so_qlimit > USHRT_MAX ?
- USHRT_MAX : (uint16_t)so->so_qlimit;
+ xinpcb.qlen = so->sol_qlen;
+ xinpcb.qlen_old = so->sol_qlen > USHRT_MAX ?
+ USHRT_MAX : (uint16_t)so->sol_qlen;
+ xinpcb.maxqlen = so->sol_qlimit;
+ xinpcb.maxqlen_old = so->sol_qlimit > USHRT_MAX ?
+ USHRT_MAX : (uint16_t)so->sol_qlimit;
}
SCTP_INP_INCR_REF(inp);
SCTP_INP_RUNLOCK(inp);
diff --git a/freebsd/sys/netinet/sctp_usrreq.c b/freebsd/sys/netinet/sctp_usrreq.c
index b65f74d1..fa136d4e 100644
--- a/freebsd/sys/netinet/sctp_usrreq.c
+++ b/freebsd/sys/netinet/sctp_usrreq.c
@@ -87,7 +87,7 @@ sctp_init(void)
#if defined(SCTP_PACKET_LOGGING)
SCTP_BASE_VAR(packet_log_writers) = 0;
SCTP_BASE_VAR(packet_log_end) = 0;
- bzero(&SCTP_BASE_VAR(packet_log_buffer), SCTP_PACKET_LOG_SIZE);
+ memset(&SCTP_BASE_VAR(packet_log_buffer), 0, SCTP_PACKET_LOG_SIZE);
#endif
}
@@ -7140,19 +7140,16 @@ sctp_listen(struct socket *so, int backlog, struct thread *p)
}
}
SCTP_INP_WLOCK(inp);
- SOCK_LOCK(so);
- /* It appears for 7.0 and on, we must always call this. */
- solisten_proto(so, backlog);
- if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
- /* remove the ACCEPTCONN flag for one-to-many sockets */
- so->so_options &= ~SO_ACCEPTCONN;
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) == 0) {
+ SOCK_LOCK(so);
+ solisten_proto(so, backlog);
+ SOCK_UNLOCK(so);
}
if (backlog > 0) {
inp->sctp_flags |= SCTP_PCB_FLAGS_ACCEPTING;
} else {
inp->sctp_flags &= ~SCTP_PCB_FLAGS_ACCEPTING;
}
- SOCK_UNLOCK(so);
SCTP_INP_WUNLOCK(inp);
return (error);
}
diff --git a/freebsd/sys/netinet/sctputil.c b/freebsd/sys/netinet/sctputil.c
index 4c6ba598..75c989d3 100644
--- a/freebsd/sys/netinet/sctputil.c
+++ b/freebsd/sys/netinet/sctputil.c
@@ -2595,7 +2595,7 @@ sctp_m_getptr(struct mbuf *m, int off, int len, uint8_t *in_ptr)
/* else, it spans more than one mbuf, so save a temp copy... */
while ((m != NULL) && (len > 0)) {
count = min(SCTP_BUF_LEN(m) - off, len);
- bcopy(mtod(m, caddr_t)+off, ptr, count);
+ memcpy(ptr, mtod(m, caddr_t)+off, count);
len -= count;
ptr += count;
off = 0;
@@ -2756,9 +2756,9 @@ sctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb,
m_notify);
if (control != NULL) {
control->length = SCTP_BUF_LEN(m_notify);
+ control->spec_flags = M_NOTIFICATION;
/* not that we need this */
control->tail_mbuf = m_notify;
- control->spec_flags = M_NOTIFICATION;
sctp_add_to_readq(stcb->sctp_ep, stcb,
control,
&stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD,
@@ -2794,6 +2794,7 @@ set_error:
stcb->sctp_socket->so_error = ECONNABORTED;
}
}
+ SOCK_UNLOCK(stcb->sctp_socket);
}
/* Wake ANY sleepers */
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
@@ -2813,7 +2814,7 @@ set_error:
if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC))) {
- socantrcvmore_locked(stcb->sctp_socket);
+ socantrcvmore(stcb->sctp_socket);
}
sorwakeup(stcb->sctp_socket);
sowwakeup(stcb->sctp_socket);
@@ -3040,7 +3041,10 @@ sctp_notify_send_failed(struct sctp_tcb *stcb, uint8_t sent, uint32_t error,
sctp_m_freem(m_notify);
return;
}
+ control->length = SCTP_BUF_LEN(m_notify);
control->spec_flags = M_NOTIFICATION;
+ /* not that we need this */
+ control->tail_mbuf = m_notify;
sctp_add_to_readq(stcb->sctp_ep, stcb,
control,
&stcb->sctp_socket->so_rcv, 1,
@@ -3140,7 +3144,10 @@ sctp_notify_send_failed2(struct sctp_tcb *stcb, uint32_t error,
sctp_m_freem(m_notify);
return;
}
+ control->length = SCTP_BUF_LEN(m_notify);
control->spec_flags = M_NOTIFICATION;
+ /* not that we need this */
+ control->tail_mbuf = m_notify;
sctp_add_to_readq(stcb->sctp_ep, stcb,
control,
&stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, so_locked);
@@ -3241,12 +3248,10 @@ sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb, uint32_t error,
sctp_m_freem(m_notify);
return;
}
- control->spec_flags = M_NOTIFICATION;
control->length = SCTP_BUF_LEN(m_notify);
+ control->spec_flags = M_NOTIFICATION;
/* not that we need this */
control->tail_mbuf = m_notify;
- control->held_length = 0;
- control->length = 0;
sb = &stcb->sctp_socket->so_rcv;
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBALLOC, SCTP_BUF_LEN(m_notify));
@@ -3255,7 +3260,6 @@ sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb, uint32_t error,
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBRESULT, 0);
}
- atomic_add_int(&control->length, SCTP_BUF_LEN(m_notify));
control->end_added = 1;
if (stcb->asoc.control_pdapi)
TAILQ_INSERT_AFTER(&stcb->sctp_ep->read_queue, stcb->asoc.control_pdapi, control, next);
@@ -3350,8 +3354,8 @@ sctp_notify_shutdown_event(struct sctp_tcb *stcb)
sctp_m_freem(m_notify);
return;
}
- control->spec_flags = M_NOTIFICATION;
control->length = SCTP_BUF_LEN(m_notify);
+ control->spec_flags = M_NOTIFICATION;
/* not that we need this */
control->tail_mbuf = m_notify;
sctp_add_to_readq(stcb->sctp_ep, stcb,
@@ -3457,8 +3461,8 @@ sctp_notify_stream_reset_add(struct sctp_tcb *stcb, uint16_t numberin, uint16_t
sctp_m_freem(m_notify);
return;
}
- control->spec_flags = M_NOTIFICATION;
control->length = SCTP_BUF_LEN(m_notify);
+ control->spec_flags = M_NOTIFICATION;
/* not that we need this */
control->tail_mbuf = m_notify;
sctp_add_to_readq(stcb->sctp_ep, stcb,
@@ -3507,8 +3511,8 @@ sctp_notify_stream_reset_tsn(struct sctp_tcb *stcb, uint32_t sending_tsn, uint32
sctp_m_freem(m_notify);
return;
}
- control->spec_flags = M_NOTIFICATION;
control->length = SCTP_BUF_LEN(m_notify);
+ control->spec_flags = M_NOTIFICATION;
/* not that we need this */
control->tail_mbuf = m_notify;
sctp_add_to_readq(stcb->sctp_ep, stcb,
@@ -3572,8 +3576,8 @@ sctp_notify_stream_reset(struct sctp_tcb *stcb,
sctp_m_freem(m_notify);
return;
}
- control->spec_flags = M_NOTIFICATION;
control->length = SCTP_BUF_LEN(m_notify);
+ control->spec_flags = M_NOTIFICATION;
/* not that we need this */
control->tail_mbuf = m_notify;
sctp_add_to_readq(stcb->sctp_ep, stcb,
@@ -3628,9 +3632,9 @@ sctp_notify_remote_error(struct sctp_tcb *stcb, uint16_t error, struct sctp_erro
m_notify);
if (control != NULL) {
control->length = SCTP_BUF_LEN(m_notify);
+ control->spec_flags = M_NOTIFICATION;
/* not that we need this */
control->tail_mbuf = m_notify;
- control->spec_flags = M_NOTIFICATION;
sctp_add_to_readq(stcb->sctp_ep, stcb,
control,
&stcb->sctp_socket->so_rcv, 1,
@@ -6165,7 +6169,7 @@ sctp_dynamic_set_primary(struct sockaddr *sa, uint32_t vrf_id)
}
/* Now incr the count and int wi structure */
SCTP_INCR_LADDR_COUNT();
- bzero(wi, sizeof(*wi));
+ memset(wi, 0, sizeof(*wi));
(void)SCTP_GETTIME_TIMEVAL(&wi->start_time);
wi->ifa = ifa;
wi->action = SCTP_SET_PRIM_ADDR;
@@ -7241,8 +7245,6 @@ sctp_over_udp_start(void)
return (0);
}
-#if defined(INET6) || defined(INET)
-
/*
* sctp_min_mtu ()returns the minimum of all non-zero arguments.
* If all arguments are zero, zero is returned.
@@ -7326,4 +7328,3 @@ sctp_hc_get_mtu(union sctp_sockstore *addr, uint16_t fibnum)
}
return ((uint32_t)tcp_hc_getmtu(&inc));
}
-#endif
diff --git a/freebsd/sys/netinet/sctputil.h b/freebsd/sys/netinet/sctputil.h
index 50118b7a..97b33654 100644
--- a/freebsd/sys/netinet/sctputil.h
+++ b/freebsd/sys/netinet/sctputil.h
@@ -388,10 +388,8 @@ sctp_auditing(int, struct sctp_inpcb *, struct sctp_tcb *,
void sctp_audit_log(uint8_t, uint8_t);
#endif
-#if defined(INET6) || defined(INET)
uint32_t sctp_min_mtu(uint32_t, uint32_t, uint32_t);
void sctp_hc_set_mtu(union sctp_sockstore *, uint16_t, uint32_t);
uint32_t sctp_hc_get_mtu(union sctp_sockstore *, uint16_t);
-#endif
#endif /* _KERNEL */
#endif
diff --git a/freebsd/sys/netinet/tcp_input.c b/freebsd/sys/netinet/tcp_input.c
index d7091928..2195a778 100644
--- a/freebsd/sys/netinet/tcp_input.c
+++ b/freebsd/sys/netinet/tcp_input.c
@@ -437,16 +437,9 @@ cc_cong_signal(struct tcpcb *tp, struct tcphdr *th, uint32_t type)
tp->t_dupacks = 0;
tp->t_bytes_acked = 0;
EXIT_RECOVERY(tp->t_flags);
- if (CC_ALGO(tp)->cong_signal == NULL) {
- /*
- * RFC5681 Section 3.1
- * ssthresh = max (FlightSize / 2, 2*SMSS) eq (4)
- */
- tp->snd_ssthresh =
- max((tp->snd_max - tp->snd_una) / 2 / maxseg, 2)
- * maxseg;
- tp->snd_cwnd = maxseg;
- }
+ tp->snd_ssthresh = max(2, min(tp->snd_wnd, tp->snd_cwnd) / 2 /
+ maxseg) * maxseg;
+ tp->snd_cwnd = maxseg;
break;
case CC_RTO_ERR:
TCPSTAT_INC(tcps_sndrexmitbad);
@@ -2013,8 +2006,10 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
/*
* If the state is SYN_SENT:
- * if seg contains a RST, then drop the connection.
- * if seg does not contain SYN, then drop it.
+ * if seg contains a RST with valid ACK (SEQ.ACK has already
+ * been verified), then drop the connection.
+ * if seg contains a RST without an ACK, drop the seg.
+ * if seg does not contain SYN, then drop the seg.
* Otherwise this is an acceptable SYN segment
* initialize tp->rcv_nxt and tp->irs
* if seg contains ack then advance tp->snd_una
@@ -2613,15 +2608,6 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
if (awnd < tp->snd_ssthresh) {
tp->snd_cwnd += maxseg;
- /*
- * RFC5681 Section 3.2 talks about cwnd
- * inflation on additional dupacks and
- * deflation on recovering from loss.
- *
- * We keep cwnd into check so that
- * we don't have to 'deflate' it when we
- * get out of recovery.
- */
if (tp->snd_cwnd > tp->snd_ssthresh)
tp->snd_cwnd = tp->snd_ssthresh;
}
@@ -2661,22 +2647,19 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
TCPSTAT_INC(
tcps_sack_recovery_episode);
tp->sack_newdata = tp->snd_nxt;
- if (CC_ALGO(tp)->cong_signal == NULL)
- tp->snd_cwnd = maxseg;
+ tp->snd_cwnd = maxseg;
(void) tp->t_fb->tfb_tcp_output(tp);
goto drop;
}
tp->snd_nxt = th->th_ack;
- if (CC_ALGO(tp)->cong_signal == NULL)
- tp->snd_cwnd = maxseg;
+ tp->snd_cwnd = maxseg;
(void) tp->t_fb->tfb_tcp_output(tp);
KASSERT(tp->snd_limited <= 2,
("%s: tp->snd_limited too big",
__func__));
- if (CC_ALGO(tp)->cong_signal == NULL)
- tp->snd_cwnd = tp->snd_ssthresh +
- maxseg *
- (tp->t_dupacks - tp->snd_limited);
+ tp->snd_cwnd = tp->snd_ssthresh +
+ maxseg *
+ (tp->t_dupacks - tp->snd_limited);
if (SEQ_GT(onxt, tp->snd_nxt))
tp->snd_nxt = onxt;
goto drop;
diff --git a/freebsd/sys/netinet/tcp_output.c b/freebsd/sys/netinet/tcp_output.c
index d2606fb6..30ec34de 100644
--- a/freebsd/sys/netinet/tcp_output.c
+++ b/freebsd/sys/netinet/tcp_output.c
@@ -132,6 +132,12 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, sendbuf_max, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(tcp_autosndbuf_max), 0,
"Max size of automatic send buffer");
+VNET_DEFINE(int, tcp_sendbuf_auto_lowat) = 0;
+#define V_tcp_sendbuf_auto_lowat VNET(tcp_sendbuf_auto_lowat)
+SYSCTL_INT(_net_inet_tcp, OID_AUTO, sendbuf_auto_lowat, CTLFLAG_VNET | CTLFLAG_RW,
+ &VNET_NAME(tcp_sendbuf_auto_lowat), 0,
+ "Modify threshold for auto send buffer growth to account for SO_SNDLOWAT");
+
/*
* Make sure that either retransmit or persist timer is set for SYN, FIN and
* non-ACK.
@@ -382,7 +388,7 @@ after_sack_rexmit:
*/
if (sack_rxmit == 0) {
if (sack_bytes_rxmt == 0)
- len = ((int32_t)ulmin(sbavail(&so->so_snd), sendwin) -
+ len = ((int32_t)min(sbavail(&so->so_snd), sendwin) -
off);
else {
int32_t cwin;
@@ -523,8 +529,12 @@ after_sack_rexmit:
* XXXGL: should there be used sbused() or sbavail()?
*/
if (V_tcp_do_autosndbuf && so->so_snd.sb_flags & SB_AUTOSIZE) {
- if ((tp->snd_wnd / 4 * 5) >= so->so_snd.sb_hiwat &&
- sbused(&so->so_snd) >= (so->so_snd.sb_hiwat / 8 * 7) &&
+ int autosndbuf_mod = 0;
+ if (V_tcp_sendbuf_auto_lowat)
+ autosndbuf_mod = so->so_snd.sb_lowat;
+
+ if ((tp->snd_wnd / 4 * 5) >= so->so_snd.sb_hiwat - autosndbuf_mod &&
+ sbused(&so->so_snd) >= (so->so_snd.sb_hiwat / 8 * 7) - autosndbuf_mod &&
sbused(&so->so_snd) < V_tcp_autosndbuf_max &&
sendwin >= (sbused(&so->so_snd) -
(tp->snd_nxt - tp->snd_una))) {
diff --git a/freebsd/sys/netinet/tcp_subr.c b/freebsd/sys/netinet/tcp_subr.c
index 30464e1b..dff41275 100644
--- a/freebsd/sys/netinet/tcp_subr.c
+++ b/freebsd/sys/netinet/tcp_subr.c
@@ -281,7 +281,7 @@ find_tcp_functions_locked(struct tcp_function_set *fs)
struct tcp_function_block *blk=NULL;
TAILQ_FOREACH(f, &t_functions, tf_next) {
- if (strcmp(f->tf_fb->tfb_tcp_block_name, fs->function_set_name) == 0) {
+ if (strcmp(f->tf_name, fs->function_set_name) == 0) {
blk = f->tf_fb;
break;
}
@@ -382,6 +382,7 @@ sysctl_net_inet_list_available(SYSCTL_HANDLER_ARGS)
struct tcp_function *f;
char *buffer, *cp;
size_t bufsz, outsz;
+ bool alias;
cnt = 0;
rw_rlock(&tcp_function_lock);
@@ -390,22 +391,25 @@ sysctl_net_inet_list_available(SYSCTL_HANDLER_ARGS)
}
rw_runlock(&tcp_function_lock);
- bufsz = (cnt+2) * (TCP_FUNCTION_NAME_LEN_MAX + 12) + 1;
+ bufsz = (cnt+2) * ((TCP_FUNCTION_NAME_LEN_MAX * 2) + 13) + 1;
buffer = malloc(bufsz, M_TEMP, M_WAITOK);
error = 0;
cp = buffer;
- linesz = snprintf(cp, bufsz, "\n%-32s%c %s\n", "Stack", 'D', "PCB count");
+ linesz = snprintf(cp, bufsz, "\n%-32s%c %-32s %s\n", "Stack", 'D',
+ "Alias", "PCB count");
cp += linesz;
bufsz -= linesz;
outsz = linesz;
rw_rlock(&tcp_function_lock);
TAILQ_FOREACH(f, &t_functions, tf_next) {
- linesz = snprintf(cp, bufsz, "%-32s%c %u\n",
+ alias = (f->tf_name != f->tf_fb->tfb_tcp_block_name);
+ linesz = snprintf(cp, bufsz, "%-32s%c %-32s %u\n",
f->tf_fb->tfb_tcp_block_name,
(f->tf_fb == tcp_func_set_ptr) ? '*' : ' ',
+ alias ? f->tf_name : "-",
f->tf_fb->tfb_refcnt);
if (linesz >= bufsz) {
error = EOVERFLOW;
@@ -506,12 +510,31 @@ maketcp_hashsize(int size)
return (hashsize);
}
+/*
+ * Register a TCP function block with the name provided in the names
+ * array. (Note that this function does NOT automatically register
+ * blk->tfb_tcp_block_name as a stack name. Therefore, you should
+ * explicitly include blk->tfb_tcp_block_name in the list of names if
+ * you wish to register the stack with that name.)
+ *
+ * Either all name registrations will succeed or all will fail. If
+ * a name registration fails, the function will update the num_names
+ * argument to point to the array index of the name that encountered
+ * the failure.
+ *
+ * Returns 0 on success, or an error code on failure.
+ */
int
-register_tcp_functions(struct tcp_function_block *blk, int wait)
+register_tcp_functions_as_names(struct tcp_function_block *blk, int wait,
+ const char *names[], int *num_names)
{
- struct tcp_function_block *lblk;
struct tcp_function *n;
struct tcp_function_set fs;
+ int error, i;
+
+ KASSERT(names != NULL && *num_names > 0,
+ ("%s: Called with 0-length name list", __func__));
+ KASSERT(names != NULL, ("%s: Called with NULL name list", __func__));
if (t_functions_inited == 0) {
init_tcp_functions();
@@ -524,6 +547,7 @@ register_tcp_functions(struct tcp_function_block *blk, int wait)
* These functions are required and you
* need a name.
*/
+ *num_names = 0;
return (EINVAL);
}
if (blk->tfb_tcp_timer_stop_all ||
@@ -538,34 +562,99 @@ register_tcp_functions(struct tcp_function_block *blk, int wait)
(blk->tfb_tcp_timer_activate == NULL) ||
(blk->tfb_tcp_timer_active == NULL) ||
(blk->tfb_tcp_timer_stop == NULL)) {
- return (EINVAL);
+ *num_names = 0;
+ return (EINVAL);
}
- }
- n = malloc(sizeof(struct tcp_function), M_TCPFUNCTIONS, wait);
- if (n == NULL) {
- return (ENOMEM);
- }
- n->tf_fb = blk;
- strcpy(fs.function_set_name, blk->tfb_tcp_block_name);
- rw_wlock(&tcp_function_lock);
- lblk = find_tcp_functions_locked(&fs);
- if (lblk) {
- /* Duplicate name space not allowed */
- rw_wunlock(&tcp_function_lock);
- free(n, M_TCPFUNCTIONS);
- return (EALREADY);
}
+
refcount_init(&blk->tfb_refcnt, 0);
blk->tfb_flags = 0;
- TAILQ_INSERT_TAIL(&t_functions, n, tf_next);
- rw_wunlock(&tcp_function_lock);
+ for (i = 0; i < *num_names; i++) {
+ n = malloc(sizeof(struct tcp_function), M_TCPFUNCTIONS, wait);
+ if (n == NULL) {
+ error = ENOMEM;
+ goto cleanup;
+ }
+ n->tf_fb = blk;
+
+ (void)strncpy(fs.function_set_name, names[i],
+ TCP_FUNCTION_NAME_LEN_MAX);
+ fs.function_set_name[TCP_FUNCTION_NAME_LEN_MAX - 1] = '\0';
+ rw_wlock(&tcp_function_lock);
+ if (find_tcp_functions_locked(&fs) != NULL) {
+ /* Duplicate name space not allowed */
+ rw_wunlock(&tcp_function_lock);
+ free(n, M_TCPFUNCTIONS);
+ error = EALREADY;
+ goto cleanup;
+ }
+ (void)strncpy(n->tf_name, names[i], TCP_FUNCTION_NAME_LEN_MAX);
+ n->tf_name[TCP_FUNCTION_NAME_LEN_MAX - 1] = '\0';
+ TAILQ_INSERT_TAIL(&t_functions, n, tf_next);
+ rw_wunlock(&tcp_function_lock);
+ }
return(0);
-}
+
+cleanup:
+ /*
+ * Deregister the names we just added. Because registration failed
+ * for names[i], we don't need to deregister that name.
+ */
+ *num_names = i;
+ rw_wlock(&tcp_function_lock);
+ while (--i >= 0) {
+ TAILQ_FOREACH(n, &t_functions, tf_next) {
+ if (!strncmp(n->tf_name, names[i],
+ TCP_FUNCTION_NAME_LEN_MAX)) {
+ TAILQ_REMOVE(&t_functions, n, tf_next);
+ n->tf_fb = NULL;
+ free(n, M_TCPFUNCTIONS);
+ break;
+ }
+ }
+ }
+ rw_wunlock(&tcp_function_lock);
+ return (error);
+}
+
+/*
+ * Register a TCP function block using the name provided in the name
+ * argument.
+ *
+ * Returns 0 on success, or an error code on failure.
+ */
+int
+register_tcp_functions_as_name(struct tcp_function_block *blk, const char *name,
+ int wait)
+{
+ const char *name_list[1];
+ int num_names, rv;
+
+ num_names = 1;
+ if (name != NULL)
+ name_list[0] = name;
+ else
+ name_list[0] = blk->tfb_tcp_block_name;
+ rv = register_tcp_functions_as_names(blk, wait, name_list, &num_names);
+ return (rv);
+}
+
+/*
+ * Register a TCP function block using the name defined in
+ * blk->tfb_tcp_block_name.
+ *
+ * Returns 0 on success, or an error code on failure.
+ */
+int
+register_tcp_functions(struct tcp_function_block *blk, int wait)
+{
+
+ return (register_tcp_functions_as_name(blk, NULL, wait));
+}
int
deregister_tcp_functions(struct tcp_function_block *blk)
{
- struct tcp_function_block *lblk;
struct tcp_function *f;
int error=ENOENT;
@@ -585,8 +674,7 @@ deregister_tcp_functions(struct tcp_function_block *blk)
rw_wunlock(&tcp_function_lock);
return (EBUSY);
}
- lblk = find_tcp_fb_locked(blk, &f);
- if (lblk) {
+ while (find_tcp_fb_locked(blk, &f) != NULL) {
/* Found */
TAILQ_REMOVE(&t_functions, f, tf_next);
f->tf_fb = NULL;
@@ -1582,7 +1670,6 @@ tcp_close(struct tcpcb *tp)
("tcp_close: !SS_PROTOREF"));
inp->inp_flags &= ~INP_SOCKREF;
INP_WUNLOCK(inp);
- ACCEPT_LOCK();
SOCK_LOCK(so);
so->so_state &= ~SS_PROTOREF;
sofree(so);
@@ -1969,16 +2056,16 @@ tcp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
if (inp != NULL && PRC_IS_REDIRECT(cmd)) {
/* signal EHOSTDOWN, as it flushes the cached route */
inp = (*notify)(inp, EHOSTDOWN);
- if (inp != NULL)
- INP_WUNLOCK(inp);
- } else if (inp != NULL) {
+ goto out;
+ }
+ icmp_tcp_seq = th->th_seq;
+ if (inp != NULL) {
if (!(inp->inp_flags & INP_TIMEWAIT) &&
!(inp->inp_flags & INP_DROPPED) &&
!(inp->inp_socket == NULL)) {
- icmp_tcp_seq = ntohl(th->th_seq);
tp = intotcpcb(inp);
- if (SEQ_GEQ(icmp_tcp_seq, tp->snd_una) &&
- SEQ_LT(icmp_tcp_seq, tp->snd_max)) {
+ if (SEQ_GEQ(ntohl(icmp_tcp_seq), tp->snd_una) &&
+ SEQ_LT(ntohl(icmp_tcp_seq), tp->snd_max)) {
if (cmd == PRC_MSGSIZE) {
/*
* MTU discovery:
@@ -1986,7 +2073,7 @@ tcp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
* in the route to the suggested new
* value (if given) and then notify.
*/
- mtu = ntohs(icp->icmp_nextmtu);
+ mtu = ntohs(icp->icmp_nextmtu);
/*
* If no alternative MTU was
* proposed, try the next smaller
@@ -2017,16 +2104,17 @@ tcp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
inetctlerrmap[cmd]);
}
}
- if (inp != NULL)
- INP_WUNLOCK(inp);
} else {
bzero(&inc, sizeof(inc));
inc.inc_fport = th->th_dport;
inc.inc_lport = th->th_sport;
inc.inc_faddr = faddr;
inc.inc_laddr = ip->ip_src;
- syncache_unreach(&inc, th);
+ syncache_unreach(&inc, icmp_tcp_seq);
}
+out:
+ if (inp != NULL)
+ INP_WUNLOCK(inp);
INP_INFO_RUNLOCK(&V_tcbinfo);
}
#endif /* INET */
@@ -2036,7 +2124,6 @@ void
tcp6_ctlinput(int cmd, struct sockaddr *sa, void *d)
{
struct in6_addr *dst;
- struct tcphdr *th;
struct inpcb *(*notify)(struct inpcb *, int) = tcp_notify;
struct ip6_hdr *ip6;
struct mbuf *m;
@@ -2046,11 +2133,14 @@ tcp6_ctlinput(int cmd, struct sockaddr *sa, void *d)
struct ip6ctlparam *ip6cp = NULL;
const struct sockaddr_in6 *sa6_src = NULL;
struct in_conninfo inc;
+ struct tcp_ports {
+ uint16_t th_sport;
+ uint16_t th_dport;
+ } t_ports;
tcp_seq icmp_tcp_seq;
unsigned int mtu;
unsigned int off;
-
if (sa->sa_family != AF_INET6 ||
sa->sa_len != sizeof(struct sockaddr_in6))
return;
@@ -2099,27 +2189,31 @@ tcp6_ctlinput(int cmd, struct sockaddr *sa, void *d)
/* Check if we can safely get the ports from the tcp hdr */
if (m == NULL ||
(m->m_pkthdr.len <
- (int32_t) (off + offsetof(struct tcphdr, th_seq)))) {
+ (int32_t) (off + sizeof(struct tcp_ports)))) {
return;
}
-
- th = (struct tcphdr *) mtodo(ip6cp->ip6c_m, ip6cp->ip6c_off);
+ bzero(&t_ports, sizeof(struct tcp_ports));
+ m_copydata(m, off, sizeof(struct tcp_ports), (caddr_t)&t_ports);
INP_INFO_RLOCK(&V_tcbinfo);
- inp = in6_pcblookup(&V_tcbinfo, &ip6->ip6_dst, th->th_dport,
- &ip6->ip6_src, th->th_sport, INPLOOKUP_WLOCKPCB, NULL);
+ inp = in6_pcblookup(&V_tcbinfo, &ip6->ip6_dst, t_ports.th_dport,
+ &ip6->ip6_src, t_ports.th_sport, INPLOOKUP_WLOCKPCB, NULL);
if (inp != NULL && PRC_IS_REDIRECT(cmd)) {
/* signal EHOSTDOWN, as it flushes the cached route */
inp = (*notify)(inp, EHOSTDOWN);
- if (inp != NULL)
- INP_WUNLOCK(inp);
- } else if (inp != NULL) {
+ goto out;
+ }
+ off += sizeof(struct tcp_ports);
+ if (m->m_pkthdr.len < (int32_t) (off + sizeof(tcp_seq))) {
+ goto out;
+ }
+ m_copydata(m, off, sizeof(tcp_seq), (caddr_t)&icmp_tcp_seq);
+ if (inp != NULL) {
if (!(inp->inp_flags & INP_TIMEWAIT) &&
!(inp->inp_flags & INP_DROPPED) &&
!(inp->inp_socket == NULL)) {
- icmp_tcp_seq = ntohl(th->th_seq);
tp = intotcpcb(inp);
- if (SEQ_GEQ(icmp_tcp_seq, tp->snd_una) &&
- SEQ_LT(icmp_tcp_seq, tp->snd_max)) {
+ if (SEQ_GEQ(ntohl(icmp_tcp_seq), tp->snd_una) &&
+ SEQ_LT(ntohl(icmp_tcp_seq), tp->snd_max)) {
if (cmd == PRC_MSGSIZE) {
/*
* MTU discovery:
@@ -2136,22 +2230,20 @@ tcp6_ctlinput(int cmd, struct sockaddr *sa, void *d)
*/
if (mtu < IPV6_MMTU)
mtu = IPV6_MMTU - 8;
-
-
bzero(&inc, sizeof(inc));
inc.inc_fibnum = M_GETFIB(m);
inc.inc_flags |= INC_ISIPV6;
inc.inc6_faddr = *dst;
if (in6_setscope(&inc.inc6_faddr,
m->m_pkthdr.rcvif, NULL))
- goto unlock_inp;
-
+ goto out;
/*
* Only process the offered MTU if it
* is smaller than the current one.
*/
if (mtu < tp->t_maxseg +
- (sizeof (*th) + sizeof (*ip6))) {
+ sizeof (struct tcphdr) +
+ sizeof (struct ip6_hdr)) {
tcp_hc_updatemtu(&inc, mtu);
tcp_mtudisc(inp, mtu);
ICMP6STAT_INC(icp6s_pmtuchg);
@@ -2161,19 +2253,19 @@ tcp6_ctlinput(int cmd, struct sockaddr *sa, void *d)
inet6ctlerrmap[cmd]);
}
}
-unlock_inp:
- if (inp != NULL)
- INP_WUNLOCK(inp);
} else {
bzero(&inc, sizeof(inc));
inc.inc_fibnum = M_GETFIB(m);
inc.inc_flags |= INC_ISIPV6;
- inc.inc_fport = th->th_dport;
- inc.inc_lport = th->th_sport;
+ inc.inc_fport = t_ports.th_dport;
+ inc.inc_lport = t_ports.th_sport;
inc.inc6_faddr = *dst;
inc.inc6_laddr = ip6->ip6_src;
- syncache_unreach(&inc, th);
+ syncache_unreach(&inc, icmp_tcp_seq);
}
+out:
+ if (inp != NULL)
+ INP_WUNLOCK(inp);
INP_INFO_RUNLOCK(&V_tcbinfo);
}
#endif /* INET6 */
diff --git a/freebsd/sys/netinet/tcp_syncache.c b/freebsd/sys/netinet/tcp_syncache.c
index 13170ae9..cf1f0ad1 100644
--- a/freebsd/sys/netinet/tcp_syncache.c
+++ b/freebsd/sys/netinet/tcp_syncache.c
@@ -604,7 +604,7 @@ syncache_badack(struct in_conninfo *inc)
}
void
-syncache_unreach(struct in_conninfo *inc, struct tcphdr *th)
+syncache_unreach(struct in_conninfo *inc, tcp_seq th_seq)
{
struct syncache *sc;
struct syncache_head *sch;
@@ -615,7 +615,7 @@ syncache_unreach(struct in_conninfo *inc, struct tcphdr *th)
goto done;
/* If the sequence number != sc_iss, then it's a bogus ICMP msg */
- if (ntohl(th->th_seq) != sc->sc_iss)
+ if (ntohl(th_seq) != sc->sc_iss)
goto done;
/*
@@ -1274,6 +1274,7 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
* soon as possible.
*/
so = *lsop;
+ KASSERT(SOLISTENING(so), ("%s: %p not listening", __func__, so));
tp = sototcpcb(so);
cred = crhold(so->so_cred);
@@ -1284,7 +1285,7 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
#endif
ip_ttl = inp->inp_ip_ttl;
ip_tos = inp->inp_ip_tos;
- win = sbspace(&so->so_rcv);
+ win = so->sol_sbrcv_hiwat;
ltflags = (tp->t_flags & (TF_NOOPT | TF_SIGNATURE));
#ifdef TCP_RFC7413
@@ -1297,7 +1298,7 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
* listen queue with bogus TFO connections.
*/
if (atomic_fetchadd_int(tp->t_tfo_pending, 1) <=
- (so->so_qlimit / 2)) {
+ (so->sol_qlimit / 2)) {
int result;
result = tcp_fastopen_check_cookie(inc,
@@ -2125,7 +2126,7 @@ syncookie_lookup(struct in_conninfo *inc, struct syncache_head *sch,
sc->sc_flags |= SCF_WINSCALE;
}
- wnd = sbspace(&lso->so_rcv);
+ wnd = lso->sol_sbrcv_hiwat;
wnd = imax(wnd, 0);
wnd = imin(wnd, TCP_MAXWIN);
sc->sc_wnd = wnd;
diff --git a/freebsd/sys/netinet/tcp_syncache.h b/freebsd/sys/netinet/tcp_syncache.h
index ebf9fb84..3932cab7 100644
--- a/freebsd/sys/netinet/tcp_syncache.h
+++ b/freebsd/sys/netinet/tcp_syncache.h
@@ -38,7 +38,7 @@ void syncache_init(void);
#ifdef VIMAGE
void syncache_destroy(void);
#endif
-void syncache_unreach(struct in_conninfo *, struct tcphdr *);
+void syncache_unreach(struct in_conninfo *, tcp_seq);
int syncache_expand(struct in_conninfo *, struct tcpopt *,
struct tcphdr *, struct socket **, struct mbuf *);
int syncache_add(struct in_conninfo *, struct tcpopt *,
diff --git a/freebsd/sys/netinet/tcp_timewait.c b/freebsd/sys/netinet/tcp_timewait.c
index de7d08da..13105339 100644
--- a/freebsd/sys/netinet/tcp_timewait.c
+++ b/freebsd/sys/netinet/tcp_timewait.c
@@ -354,7 +354,6 @@ tcp_twstart(struct tcpcb *tp)
("tcp_twstart: !SS_PROTOREF"));
inp->inp_flags &= ~INP_SOCKREF;
INP_WUNLOCK(inp);
- ACCEPT_LOCK();
SOCK_LOCK(so);
so->so_state &= ~SS_PROTOREF;
sofree(so);
@@ -493,7 +492,6 @@ tcp_twclose(struct tcptw *tw, int reuse)
if (inp->inp_flags & INP_SOCKREF) {
inp->inp_flags &= ~INP_SOCKREF;
INP_WUNLOCK(inp);
- ACCEPT_LOCK();
SOCK_LOCK(so);
KASSERT(so->so_state & SS_PROTOREF,
("tcp_twclose: INP_SOCKREF && !SS_PROTOREF"));
diff --git a/freebsd/sys/netinet/tcp_var.h b/freebsd/sys/netinet/tcp_var.h
index d298c9dd..2e2f88ac 100644
--- a/freebsd/sys/netinet/tcp_var.h
+++ b/freebsd/sys/netinet/tcp_var.h
@@ -272,8 +272,9 @@ struct tcp_function_block {
};
struct tcp_function {
- TAILQ_ENTRY(tcp_function) tf_next;
- struct tcp_function_block *tf_fb;
+ TAILQ_ENTRY(tcp_function) tf_next;
+ char tf_name[TCP_FUNCTION_NAME_LEN_MAX];
+ struct tcp_function_block *tf_fb;
};
TAILQ_HEAD(tcp_funchead, tcp_function);
@@ -785,6 +786,10 @@ void tcp_do_segment(struct mbuf *, struct tcphdr *,
int);
int register_tcp_functions(struct tcp_function_block *blk, int wait);
+int register_tcp_functions_as_names(struct tcp_function_block *blk,
+ int wait, const char *names[], int *num_names);
+int register_tcp_functions_as_name(struct tcp_function_block *blk,
+ const char *name, int wait);
int deregister_tcp_functions(struct tcp_function_block *blk);
struct tcp_function_block *find_and_ref_tcp_functions(struct tcp_function_set *fs);
struct tcp_function_block *find_and_ref_tcp_fb(struct tcp_function_block *blk);