diff options
-rw-r--r-- | sys/netinet/sctp_asconf.c | 47 | ||||
-rw-r--r-- | sys/netinet/sctp_asconf.h | 7 | ||||
-rw-r--r-- | sys/netinet/sctp_auth.c | 50 | ||||
-rw-r--r-- | sys/netinet/sctp_bsd_addr.c | 17 | ||||
-rw-r--r-- | sys/netinet/sctp_indata.c | 324 | ||||
-rw-r--r-- | sys/netinet/sctp_input.c | 171 | ||||
-rw-r--r-- | sys/netinet/sctp_os.h | 6 | ||||
-rw-r--r-- | sys/netinet/sctp_os_bsd.h | 69 | ||||
-rw-r--r-- | sys/netinet/sctp_output.c | 965 | ||||
-rw-r--r-- | sys/netinet/sctp_pcb.c | 102 | ||||
-rw-r--r-- | sys/netinet/sctp_pcb.h | 1 | ||||
-rw-r--r-- | sys/netinet/sctp_structs.h | 8 | ||||
-rw-r--r-- | sys/netinet/sctp_timer.c | 19 | ||||
-rw-r--r-- | sys/netinet/sctp_usrreq.c | 247 | ||||
-rw-r--r-- | sys/netinet/sctp_var.h | 80 | ||||
-rw-r--r-- | sys/netinet/sctputil.c | 410 | ||||
-rw-r--r-- | sys/netinet6/sctp6_usrreq.c | 40 |
17 files changed, 1222 insertions, 1341 deletions
diff --git a/sys/netinet/sctp_asconf.c b/sys/netinet/sctp_asconf.c index de1bc86..0d2fe04 100644 --- a/sys/netinet/sctp_asconf.c +++ b/sys/netinet/sctp_asconf.c @@ -178,7 +178,7 @@ sctp_asconf_success_response(uint32_t id) aph->correlation_id = id; aph->ph.param_type = htons(SCTP_SUCCESS_REPORT); aph->ph.param_length = sizeof(struct sctp_asconf_paramhdr); - m_reply->m_len = aph->ph.param_length; + SCTP_BUF_LEN(m_reply) = aph->ph.param_length; aph->ph.param_length = htons(aph->ph.param_length); return m_reply; @@ -229,7 +229,7 @@ sctp_asconf_error_response(uint32_t id, uint16_t cause, uint8_t * error_tlv, tlv = (uint8_t *) (error + 1); memcpy(tlv, error_tlv, tlv_length); } - m_reply->m_len = aph->ph.param_length; + SCTP_BUF_LEN(m_reply) = aph->ph.param_length; error->length = htons(error->length); aph->ph.param_length = htons(aph->ph.param_length); @@ -327,7 +327,7 @@ sctp_process_asconf_add_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph, } /* end switch */ /* if 0.0.0.0/::0, add the source address instead */ - if (zero_address) { + if (zero_address && sctp_nat_friendly) { sa = (struct sockaddr *)&sa_source; sctp_asconf_get_source_ip(m, sa); #ifdef SCTP_DEBUG @@ -500,7 +500,7 @@ sctp_process_asconf_delete_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph, return m_reply; } /* if deleting 0.0.0.0/::0, delete all addresses except src addr */ - if (zero_address) { + if (zero_address && sctp_nat_friendly) { result = sctp_asconf_del_remote_addrs_except(stcb, (struct sockaddr *)&sa_source); @@ -637,7 +637,7 @@ sctp_process_asconf_set_primary(struct mbuf *m, } /* if 0.0.0.0/::0, use the source address instead */ - if (zero_address) { + if (zero_address && sctp_nat_friendly) { sa = (struct sockaddr *)&sa_source; sctp_asconf_get_source_ip(m, sa); #ifdef SCTP_DEBUG @@ -744,7 +744,7 @@ sctp_handle_asconf(struct mbuf *m, unsigned int offset, sctp_m_freem(asoc->last_asconf_ack_sent); asoc->last_asconf_ack_sent = NULL; } - m_ack = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_ack_chunk), 1, + m_ack = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_ack_chunk), 0, M_DONTWAIT, 1, MT_DATA); if (m_ack == NULL) { #ifdef SCTP_DEBUG @@ -762,9 +762,8 @@ sctp_handle_asconf(struct mbuf *m, unsigned int offset, ack_cp->ch.chunk_flags = 0; ack_cp->serial_number = htonl(serial_num); /* set initial lengths (eg. just an ASCONF-ACK), ntohx at the end! */ - m_ack->m_len = sizeof(struct sctp_asconf_ack_chunk); + SCTP_BUF_LEN(m_ack) = sizeof(struct sctp_asconf_ack_chunk); ack_cp->ch.chunk_length = sizeof(struct sctp_asconf_ack_chunk); - m_ack->m_pkthdr.len = sizeof(struct sctp_asconf_ack_chunk); /* skip the lookup address parameter */ offset += sizeof(struct sctp_asconf_chunk); @@ -881,12 +880,11 @@ sctp_handle_asconf(struct mbuf *m, unsigned int offset, /* add any (error) result to the reply mbuf chain */ if (m_result != NULL) { - m_tail->m_next = m_result; + SCTP_BUF_NEXT(m_tail) = m_result; m_tail = m_result; /* update lengths, make sure it's aligned too */ - m_result->m_len = SCTP_SIZE32(m_result->m_len); - m_ack->m_pkthdr.len += m_result->m_len; - ack_cp->ch.chunk_length += m_result->m_len; + SCTP_BUF_LEN(m_result) = SCTP_SIZE32(SCTP_BUF_LEN(m_result)); + ack_cp->ch.chunk_length += SCTP_BUF_LEN(m_result); /* set flag to force success reports */ error = 1; } @@ -2245,7 +2243,7 @@ sctp_find_valid_localaddr_ep(struct sctp_tcb *stcb) * mbuf, no ASCONF params queued, etc) */ struct mbuf * -sctp_compose_asconf(struct sctp_tcb *stcb) +sctp_compose_asconf(struct sctp_tcb *stcb, int *retlen) { struct mbuf *m_asconf, *m_asconf_chk; struct sctp_asconf_addr *aa; @@ -2266,7 +2264,7 @@ sctp_compose_asconf(struct sctp_tcb *stcb) * it's simpler to fill in the asconf chunk header lookup address on * the fly */ - m_asconf_chk = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_chunk), 1, M_DONTWAIT, 1, MT_DATA); + m_asconf_chk = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_chunk), 0, M_DONTWAIT, 1, MT_DATA); if (m_asconf_chk == NULL) { /* no mbuf's */ #ifdef SCTP_DEBUG @@ -2275,7 +2273,7 @@ sctp_compose_asconf(struct sctp_tcb *stcb) #endif /* SCTP_DEBUG */ return (NULL); } - m_asconf = sctp_get_mbuf_for_msg(MCLBYTES, 1, M_DONTWAIT, 1, MT_DATA); + m_asconf = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_DONTWAIT, 1, MT_DATA); if (m_asconf == NULL) { /* no mbuf's */ #ifdef SCTP_DEBUG @@ -2285,8 +2283,8 @@ sctp_compose_asconf(struct sctp_tcb *stcb) sctp_m_freem(m_asconf_chk); return (NULL); } - m_asconf_chk->m_len = sizeof(struct sctp_asconf_chunk); - m_asconf->m_len = 0; + 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)); /* save pointers to lookup address and asconf params */ @@ -2303,7 +2301,7 @@ sctp_compose_asconf(struct sctp_tcb *stcb) /* get the parameter length */ p_length = SCTP_SIZE32(aa->ap.aph.ph.param_length); /* will it fit in current chunk? */ - if (m_asconf->m_len + p_length > stcb->asoc.smallest_mtu) { + if (SCTP_BUF_LEN(m_asconf) + p_length > stcb->asoc.smallest_mtu) { /* won't fit, so we're done with this chunk */ break; } @@ -2336,7 +2334,7 @@ sctp_compose_asconf(struct sctp_tcb *stcb) } lookup->ph.param_length = htons(SCTP_SIZE32(p_size)); memcpy(lookup->addr, &aa->ap.addrp.addr, addr_size); - m_asconf_chk->m_len += SCTP_SIZE32(p_size); + SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(p_size); lookup_used = 1; } /* copy into current space */ @@ -2351,7 +2349,7 @@ sctp_compose_asconf(struct sctp_tcb *stcb) aap->addrp.ph.param_type = htons(aap->addrp.ph.param_type); aap->addrp.ph.param_length = htons(aap->addrp.ph.param_length); - m_asconf->m_len += SCTP_SIZE32(p_length); + SCTP_BUF_LEN(m_asconf) += SCTP_SIZE32(p_length); ptr += SCTP_SIZE32(p_length); /* @@ -2395,7 +2393,7 @@ sctp_compose_asconf(struct sctp_tcb *stcb) } lookup->ph.param_length = htons(SCTP_SIZE32(p_size)); memcpy(lookup->addr, addr_ptr, addr_size); - m_asconf_chk->m_len += SCTP_SIZE32(p_size); + SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(p_size); lookup_used = 1; } else { /* uh oh... don't have any address?? */ @@ -2407,14 +2405,13 @@ sctp_compose_asconf(struct sctp_tcb *stcb) 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)); - m_asconf_chk->m_len += SCTP_SIZE32(sizeof(struct sctp_ipv4addr_param)); + SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(sizeof(struct sctp_ipv4addr_param)); lookup_used = 1; } } /* chain it all together */ - m_asconf_chk->m_next = m_asconf; - m_asconf_chk->m_pkthdr.len = m_asconf_chk->m_len + m_asconf->m_len; - acp->ch.chunk_length = ntohs(m_asconf_chk->m_pkthdr.len); + SCTP_BUF_NEXT(m_asconf_chk) = m_asconf; + *retlen = acp->ch.chunk_length = ntohs(SCTP_BUF_LEN(m_asconf_chk) + SCTP_BUF_LEN(m_asconf)); /* update "sent" flag */ stcb->asoc.asconf_sent++; diff --git a/sys/netinet/sctp_asconf.h b/sys/netinet/sctp_asconf.h index e3e7df4..df9e465 100644 --- a/sys/netinet/sctp_asconf.h +++ b/sys/netinet/sctp_asconf.h @@ -36,16 +36,17 @@ __FBSDID("$FreeBSD$"); #ifndef _NETINET_SCTP_ASCONF_H_ #define _NETINET_SCTP_ASCONF_H_ - #include <sys/malloc.h> - #if defined(_KERNEL) +/* + * function prototypes + */ extern void sctp_asconf_cleanup(struct sctp_tcb *, struct sctp_nets *); -extern struct mbuf *sctp_compose_asconf(struct sctp_tcb *); +extern struct mbuf *sctp_compose_asconf(struct sctp_tcb *, int *); extern void sctp_handle_asconf(struct mbuf *, unsigned int, struct sctp_asconf_chunk *, diff --git a/sys/netinet/sctp_auth.c b/sys/netinet/sctp_auth.c index a87f47f..d5fe70a 100644 --- a/sys/netinet/sctp_auth.c +++ b/sys/netinet/sctp_auth.c @@ -372,7 +372,7 @@ sctp_generate_random_key(uint32_t keylen) /* out of memory */ return (NULL); } - sctp_read_random(new_key->key, keylen); + SCTP_READ_RANDOM(new_key->key, keylen); new_key->keylen = keylen; return (new_key); } @@ -1110,17 +1110,18 @@ sctp_hmac_m(uint16_t hmac_algo, uint8_t * key, uint32_t keylen, sctp_hmac_update(hmac_algo, &ctx, ipad, blocklen); /* find the correct starting mbuf and offset (get start of text) */ m_tmp = m; - while ((m_tmp != NULL) && (m_offset >= (uint32_t) m_tmp->m_len)) { - m_offset -= m_tmp->m_len; - m_tmp = m_tmp->m_next; + while ((m_tmp != NULL) && (m_offset >= (uint32_t) SCTP_BUF_LEN(m_tmp))) { + m_offset -= SCTP_BUF_LEN(m_tmp); + m_tmp = SCTP_BUF_NEXT(m_tmp); } /* now use the rest of the mbuf chain for the text */ while (m_tmp != NULL) { sctp_hmac_update(hmac_algo, &ctx, mtod(m_tmp, uint8_t *) + m_offset, - m_tmp->m_len - m_offset); + SCTP_BUF_LEN(m_tmp) - m_offset); + /* clear the offset since it's only for the first mbuf */ m_offset = 0; - m_tmp = m_tmp->m_next; + m_tmp = SCTP_BUF_NEXT(m_tmp); } sctp_hmac_final(hmac_algo, &ctx, temp); @@ -1618,23 +1619,23 @@ sctp_bzero_m(struct mbuf *m, uint32_t m_offset, uint32_t size) /* find the correct starting mbuf and offset (get start position) */ m_tmp = m; - while ((m_tmp != NULL) && (m_offset >= (uint32_t) m_tmp->m_len)) { - m_offset -= m_tmp->m_len; - m_tmp = m_tmp->m_next; + while ((m_tmp != NULL) && (m_offset >= (uint32_t) SCTP_BUF_LEN(m_tmp))) { + m_offset -= SCTP_BUF_LEN(m_tmp); + m_tmp = SCTP_BUF_NEXT(m_tmp); } /* now use the rest of the mbuf chain */ while ((m_tmp != NULL) && (size > 0)) { data = mtod(m_tmp, uint8_t *) + m_offset; - if (size > (uint32_t) m_tmp->m_len) { - bzero(data, m_tmp->m_len); - size -= m_tmp->m_len; + if (size > (uint32_t) SCTP_BUF_LEN(m_tmp)) { + bzero(data, SCTP_BUF_LEN(m_tmp)); + size -= SCTP_BUF_LEN(m_tmp); } else { bzero(data, size); size = 0; } /* clear the offset since it's only for the first mbuf */ m_offset = 0; - m_tmp = m_tmp->m_next; + m_tmp = SCTP_BUF_NEXT(m_tmp); } } @@ -1685,17 +1686,17 @@ sctp_handle_auth(struct sctp_tcb *stcb, struct sctp_auth_chunk *auth, * report this in an Error Chunk: Unsupported HMAC * Identifier */ - m_err = sctp_get_mbuf_for_msg(sizeof(*err), 1, M_DONTWAIT, 1, MT_HEADER); + m_err = sctp_get_mbuf_for_msg(sizeof(*err), 0, M_DONTWAIT, 1, MT_HEADER); if (m_err != NULL) { /* pre-reserve some space */ - m_err->m_data += sizeof(struct sctp_chunkhdr); + SCTP_BUF_RESV_UF(m_err, sizeof(struct sctp_chunkhdr)); /* fill in the error */ err = mtod(m_err, struct sctp_auth_invalid_hmac *); bzero(err, sizeof(*err)); err->ph.param_type = htons(SCTP_CAUSE_UNSUPPORTED_HMACID); err->ph.param_length = htons(sizeof(*err)); err->hmac_id = ntohs(hmac_id); - m_err->m_pkthdr.len = m_err->m_len = sizeof(*err); + SCTP_BUF_LEN(m_err) = sizeof(*err); /* queue it */ sctp_queue_op_err(stcb, m_err); } @@ -1787,11 +1788,12 @@ sctp_notify_authentication(struct sctp_tcb *stcb, uint32_t indication, return; m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_authkey_event), - 1, M_DONTWAIT, 1, MT_HEADER); + 0, M_DONTWAIT, 1, MT_HEADER); if (m_notify == NULL) /* no space left */ return; - m_notify->m_len = 0; + + SCTP_BUF_LEN(m_notify) = 0; auth = mtod(m_notify, struct sctp_authkey_event *); auth->auth_type = SCTP_AUTHENTICATION_EVENT; auth->auth_flags = 0; @@ -1801,11 +1803,8 @@ sctp_notify_authentication(struct sctp_tcb *stcb, uint32_t indication, auth->auth_indication = indication; auth->auth_assoc_id = sctp_get_associd(stcb); - m_notify->m_flags |= M_EOR | M_NOTIFICATION; - m_notify->m_pkthdr.len = sizeof(*auth); - m_notify->m_pkthdr.rcvif = 0; - m_notify->m_len = sizeof(*auth); - m_notify->m_next = NULL; + SCTP_BUF_LEN(m_notify) = sizeof(*auth); + SCTP_BUF_NEXT(m_notify) = NULL; /* append to socket */ control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, @@ -1815,7 +1814,8 @@ sctp_notify_authentication(struct sctp_tcb *stcb, uint32_t indication, sctp_m_freem(m_notify); return; } - control->length = m_notify->m_len; + control->spec_flags = M_NOTIFICATION; + control->length = SCTP_BUF_LEN(m_notify); /* not that we need this */ control->tail_mbuf = m_notify; sctp_add_to_readq(stcb->sctp_ep, stcb, control, @@ -1969,7 +1969,7 @@ sctp_initialize_auth_params(struct sctp_inpcb *inp, struct sctp_tcb *stcb) new_key = sctp_alloc_key(keylen); if (new_key != NULL) { /* generate and copy in the RANDOM */ - sctp_read_random(new_key->key, random_len); + SCTP_READ_RANDOM(new_key->key, random_len); keylen = random_len; /* append in the AUTH chunks */ if (stcb->asoc.local_auth_chunks) { diff --git a/sys/netinet/sctp_bsd_addr.c b/sys/netinet/sctp_bsd_addr.c index 7d1265c..6cdbc6c 100644 --- a/sys/netinet/sctp_bsd_addr.c +++ b/sys/netinet/sctp_bsd_addr.c @@ -1873,23 +1873,22 @@ sctp_add_addr_to_mbuf(struct mbuf *m, struct ifaddr *ifa) /* unknown type */ return (m); } - if (M_TRAILINGSPACE(m) >= len) { /* easy side we just drop it on the end */ - parmh = (struct sctp_paramhdr *)(m->m_data + m->m_len); + parmh = (struct sctp_paramhdr *)(SCTP_BUF_AT(m, SCTP_BUF_LEN(m))); mret = m; } else { /* Need more space */ mret = m; - while (mret->m_next != NULL) { - mret = mret->m_next; + while (SCTP_BUF_NEXT(mret) != NULL) { + mret = SCTP_BUF_NEXT(mret); } - mret->m_next = sctp_get_mbuf_for_msg(len, 0, M_DONTWAIT, 1, MT_DATA); - if (mret->m_next == NULL) { + SCTP_BUF_NEXT(mret) = sctp_get_mbuf_for_msg(len, 0, M_DONTWAIT, 1, MT_DATA); + if (SCTP_BUF_NEXT(mret) == NULL) { /* We are hosed, can't add more addresses */ return (m); } - mret = mret->m_next; + mret = SCTP_BUF_NEXT(mret); parmh = mtod(mret, struct sctp_paramhdr *); } /* now add the parameter */ @@ -1902,7 +1901,7 @@ sctp_add_addr_to_mbuf(struct mbuf *m, struct ifaddr *ifa) parmh->param_type = htons(SCTP_IPV4_ADDRESS); parmh->param_length = htons(len); ipv4p->addr = sin->sin_addr.s_addr; - mret->m_len += len; + SCTP_BUF_LEN(mret) += len; } else if (ifa->ifa_addr->sa_family == AF_INET6) { struct sctp_ipv6addr_param *ipv6p; struct sockaddr_in6 *sin6; @@ -1915,7 +1914,7 @@ sctp_add_addr_to_mbuf(struct mbuf *m, struct ifaddr *ifa) sizeof(ipv6p->addr)); /* clear embedded scope in the address */ in6_clearscope((struct in6_addr *)ipv6p->addr); - mret->m_len += len; + SCTP_BUF_LEN(mret) += len; } else { return (m); } diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c index de25893..935ecf1 100644 --- a/sys/netinet/sctp_indata.c +++ b/sys/netinet/sctp_indata.c @@ -252,6 +252,7 @@ sctp_build_readq_entry(struct sctp_tcb *stcb, read_queue_e->length = 0; atomic_add_int(&net->ref_count, 1); read_queue_e->data = dm; + read_queue_e->spec_flags = 0; read_queue_e->tail_mbuf = NULL; read_queue_e->stcb = stcb; read_queue_e->port_from = stcb->rport; @@ -292,6 +293,7 @@ sctp_build_readq_entry_chk(struct sctp_tcb *stcb, read_queue_e->tail_mbuf = NULL; read_queue_e->stcb = stcb; read_queue_e->port_from = stcb->rport; + read_queue_e->spec_flags = 0; read_queue_e->do_not_ref_stcb = 0; read_queue_e->end_added = 0; read_queue_e->pdapi_aborted = 0; @@ -323,7 +325,7 @@ sctp_build_ctl_nchunk(struct sctp_inpcb *inp, ret = sctp_get_mbuf_for_msg(len, - 1, M_DONTWAIT, 1, MT_DATA); + 0, M_DONTWAIT, 1, MT_DATA); if (ret == NULL) { /* No space */ @@ -342,11 +344,11 @@ sctp_build_ctl_nchunk(struct sctp_inpcb *inp, cmh->cmsg_len = len; *outinfo = *sinfo; } - ret->m_len = cmh->cmsg_len; - ret->m_pkthdr.len = ret->m_len; + SCTP_BUF_LEN(ret) = cmh->cmsg_len; return (ret); } + /* * We are delivering currently from the reassembly queue. We must continue to * deliver until we either: 1) run out of space. 2) run out of sequential @@ -356,7 +358,6 @@ static void sctp_service_reassembly(struct sctp_tcb *stcb, struct sctp_association *asoc) { struct sctp_tmit_chunk *chk; - struct mbuf *m; uint16_t nxt_todel; uint16_t stream_no; int end = 0; @@ -410,34 +411,6 @@ sctp_service_reassembly(struct sctp_tcb *stcb, struct sctp_association *asoc) */ return; } - if ((chk->data->m_flags & M_PKTHDR) == 0) { - m = sctp_get_mbuf_for_msg(1, - 1, M_DONTWAIT, 1, MT_DATA); - if (m == NULL) { - /* no room! */ - return; - } - m->m_pkthdr.len = chk->send_size; - m->m_len = 0; - m->m_next = chk->data; - chk->data = m; - } - if (chk->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) { - if (chk->data->m_next == NULL) { - /* hopefully we hit here most of the time */ - chk->data->m_flags |= M_EOR; - } else { - /* - * Add the flag to the LAST mbuf in the - * chain - */ - m = chk->data; - while (m->m_next != NULL) { - m = m->m_next; - } - m->m_flags |= M_EOR; - } - } if (chk->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG) { control = sctp_build_readq_entry_chk(stcb, chk); @@ -540,7 +513,7 @@ sctp_service_reassembly(struct sctp_tcb *stcb, struct sctp_association *asoc) nxt_todel = strm->last_sequence_delivered + 1; } } - return; + break; } chk = TAILQ_FIRST(&asoc->reasmqueue); } while (chk); @@ -611,17 +584,17 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb, struct sctp_association *asoc, * association destruction */ TAILQ_INSERT_HEAD(&strm->inqueue, control, next); - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), + oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), 0, M_DONTWAIT, 1, MT_DATA); if (oper) { struct sctp_paramhdr *ph; uint32_t *ippp; - oper->m_len = sizeof(struct sctp_paramhdr) + + SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) + (sizeof(uint32_t) * 3); ph = mtod(oper, struct sctp_paramhdr *); ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION); - ph->param_length = htons(oper->m_len); + ph->param_length = htons(SCTP_BUF_LEN(oper)); ippp = (uint32_t *) (ph + 1); *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_1); ippp++; @@ -789,6 +762,7 @@ sctp_deliver_reasm_check(struct sctp_tcb *stcb, struct sctp_association *asoc) uint16_t nxt_todel; uint32_t tsize; +doit_again: chk = TAILQ_FIRST(&asoc->reasmqueue); if (chk == NULL) { /* Huh? */ @@ -826,7 +800,20 @@ sctp_deliver_reasm_check(struct sctp_tcb *stcb, struct sctp_association *asoc) } } } else { + /* + * Service re-assembly will deliver stream data queued at + * the end of fragmented delivery.. but it wont know to go + * back and call itself again... we do that here with the + * got doit_again + */ sctp_service_reassembly(stcb, asoc); + if (asoc->fragmented_delivery_inprogress == 0) { + /* + * finished our Fragmented delivery, could be more + * waiting? + */ + goto doit_again; + } } } @@ -870,20 +857,20 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, printf("Gak, Evil plot, its not first, no fragmented delivery in progress\n"); } #endif - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), + oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), 0, M_DONTWAIT, 1, MT_DATA); if (oper) { struct sctp_paramhdr *ph; uint32_t *ippp; - oper->m_len = + SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) + (sizeof(uint32_t) * 3); ph = mtod(oper, struct sctp_paramhdr *); ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION); - ph->param_length = htons(oper->m_len); + ph->param_length = htons(SCTP_BUF_LEN(oper)); ippp = (uint32_t *) (ph + 1); *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_2); ippp++; @@ -908,19 +895,19 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, printf("Gak, Evil plot, it IS a first and fragmented delivery in progress\n"); } #endif - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), + oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), 0, M_DONTWAIT, 1, MT_DATA); if (oper) { struct sctp_paramhdr *ph; uint32_t *ippp; - oper->m_len = + SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) + (3 * sizeof(uint32_t)); ph = mtod(oper, struct sctp_paramhdr *); ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION); - ph->param_length = htons(oper->m_len); + ph->param_length = htons(SCTP_BUF_LEN(oper)); ippp = (uint32_t *) (ph + 1); *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_3); ippp++; @@ -947,13 +934,13 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, asoc->str_of_pdapi); } #endif - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), + oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), 0, M_DONTWAIT, 1, MT_DATA); if (oper) { struct sctp_paramhdr *ph; uint32_t *ippp; - oper->m_len = + SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) + (sizeof(uint32_t) * 3); ph = mtod(oper, @@ -961,7 +948,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION); ph->param_length = - htons(oper->m_len); + htons(SCTP_BUF_LEN(oper)); ippp = (uint32_t *) (ph + 1); *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_4); ippp++; @@ -985,13 +972,13 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, asoc->ssn_of_pdapi); } #endif - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), + oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), 0, M_DONTWAIT, 1, MT_DATA); if (oper) { struct sctp_paramhdr *ph; uint32_t *ippp; - oper->m_len = + SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) + (3 * sizeof(uint32_t)); ph = mtod(oper, @@ -999,7 +986,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION); ph->param_length = - htons(oper->m_len); + htons(SCTP_BUF_LEN(oper)); ippp = (uint32_t *) (ph + 1); *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_5); ippp++; @@ -1088,13 +1075,13 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, printf("Gak, Evil plot, it's a FIRST!\n"); } #endif - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), + oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), 0, M_DONTWAIT, 1, MT_DATA); if (oper) { struct sctp_paramhdr *ph; uint32_t *ippp; - oper->m_len = + SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) + (3 * sizeof(uint32_t)); ph = mtod(oper, @@ -1102,7 +1089,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION); ph->param_length = - htons(oper->m_len); + htons(SCTP_BUF_LEN(oper)); ippp = (uint32_t *) (ph + 1); *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_6); ippp++; @@ -1130,13 +1117,13 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, prev->rec.data.stream_number); } #endif - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), + oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), 0, M_DONTWAIT, 1, MT_DATA); if (oper) { struct sctp_paramhdr *ph; uint32_t *ippp; - oper->m_len = + SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) + (3 * sizeof(uint32_t)); ph = mtod(oper, @@ -1144,7 +1131,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION); ph->param_length = - htons(oper->m_len); + htons(SCTP_BUF_LEN(oper)); ippp = (uint32_t *) (ph + 1); *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_7); ippp++; @@ -1173,13 +1160,13 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, prev->rec.data.stream_seq); } #endif - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), + oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), 0, M_DONTWAIT, 1, MT_DATA); if (oper) { struct sctp_paramhdr *ph; uint32_t *ippp; - oper->m_len = + SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) + (3 * sizeof(uint32_t)); ph = mtod(oper, @@ -1187,7 +1174,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION); ph->param_length = - htons(oper->m_len); + htons(SCTP_BUF_LEN(oper)); ippp = (uint32_t *) (ph + 1); *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_8); ippp++; @@ -1212,13 +1199,13 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, printf("Prev check - Gak, evil plot, its not FIRST and it must be!\n"); } #endif - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), + oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), 0, M_DONTWAIT, 1, MT_DATA); if (oper) { struct sctp_paramhdr *ph; uint32_t *ippp; - oper->m_len = + SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) + (3 * sizeof(uint32_t)); ph = mtod(oper, @@ -1226,7 +1213,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION); ph->param_length = - htons(oper->m_len); + htons(SCTP_BUF_LEN(oper)); ippp = (uint32_t *) (ph + 1); *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_9); ippp++; @@ -1262,13 +1249,13 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, printf("Gak, Evil plot, its not a last!\n"); } #endif - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), + oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), 0, M_DONTWAIT, 1, MT_DATA); if (oper) { struct sctp_paramhdr *ph; uint32_t *ippp; - oper->m_len = + SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) + (3 * sizeof(uint32_t)); ph = mtod(oper, @@ -1276,7 +1263,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION); ph->param_length = - htons(oper->m_len); + htons(SCTP_BUF_LEN(oper)); ippp = (uint32_t *) (ph + 1); *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_10); ippp++; @@ -1307,13 +1294,13 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, printf("Gak, Evil plot, new prev chunk is a LAST\n"); } #endif - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), + oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), 0, M_DONTWAIT, 1, MT_DATA); if (oper) { struct sctp_paramhdr *ph; uint32_t *ippp; - oper->m_len = + SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) + (3 * sizeof(uint32_t)); ph = mtod(oper, @@ -1321,7 +1308,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION); ph->param_length = - htons(oper->m_len); + htons(SCTP_BUF_LEN(oper)); ippp = (uint32_t *) (ph + 1); *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_11); ippp++; @@ -1350,13 +1337,13 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, next->rec.data.stream_number); } #endif - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), + oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), 0, M_DONTWAIT, 1, MT_DATA); if (oper) { struct sctp_paramhdr *ph; uint32_t *ippp; - oper->m_len = + SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) + (3 * sizeof(uint32_t)); ph = mtod(oper, @@ -1364,7 +1351,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION); ph->param_length = - htons(oper->m_len); + htons(SCTP_BUF_LEN(oper)); ippp = (uint32_t *) (ph + 1); *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_12); ippp++; @@ -1394,13 +1381,13 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, next->rec.data.stream_seq); } #endif - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), + oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), 0, M_DONTWAIT, 1, MT_DATA); if (oper) { struct sctp_paramhdr *ph; uint32_t *ippp; - oper->m_len = + SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) + (3 * sizeof(uint32_t)); ph = mtod(oper, @@ -1408,7 +1395,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION); ph->param_length = - htons(oper->m_len); + htons(SCTP_BUF_LEN(oper)); ippp = (uint32_t *) (ph + 1); *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_13); ippp++; @@ -1506,6 +1493,7 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, uint32_t tsn, gap; struct mbuf *dmbuf; int indx, the_len; + int need_reasm_check = 0; uint16_t strmno, strmseq; struct mbuf *oper; struct sctp_queued_to_read *control; @@ -1553,7 +1541,7 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, asoc->dup_tsns[asoc->numduptsns] = tsn; asoc->numduptsns++; } - if (!callout_pending(&asoc->dack_timer.timer)) { + if (!SCTP_OS_TIMER_PENDING(&asoc->dack_timer.timer)) { /* * By starting the timer we assure that we WILL sack * at the end of the packet when sctp_sack_check @@ -1634,18 +1622,17 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, struct mbuf *mb; mb = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) * 2), - 1, M_DONTWAIT, 1, MT_DATA); + 0, M_DONTWAIT, 1, MT_DATA); if (mb != NULL) { /* add some space up front so prepend will work well */ - mb->m_data += sizeof(struct sctp_chunkhdr); + SCTP_BUF_RESV_UF(mb, sizeof(struct sctp_chunkhdr)); phdr = mtod(mb, struct sctp_paramhdr *); /* * Error causes are just param's and this one has * two back to back phdr, one with the error type * and size, the other with the streamid and a rsvd */ - mb->m_pkthdr.len = mb->m_len = - (sizeof(struct sctp_paramhdr) * 2); + SCTP_BUF_LEN(mb) = (sizeof(struct sctp_paramhdr) * 2); phdr->param_type = htons(SCTP_CAUSE_INVALID_STREAM); phdr->param_length = htons(sizeof(struct sctp_paramhdr) * 2); @@ -1684,17 +1671,17 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, * throw it in the stream so it gets cleaned up in * association destruction */ - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), + oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), 0, M_DONTWAIT, 1, MT_DATA); if (oper) { struct sctp_paramhdr *ph; uint32_t *ippp; - oper->m_len = sizeof(struct sctp_paramhdr) + + SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) + (3 * sizeof(uint32_t)); ph = mtod(oper, struct sctp_paramhdr *); ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION); - ph->param_length = htons(oper->m_len); + ph->param_length = htons(SCTP_BUF_LEN(oper)); ippp = (uint32_t *) (ph + 1); *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_14); ippp++; @@ -1720,21 +1707,39 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, mat = dmbuf; while (mat) { - if (mat->m_flags & M_EXT) { + if (SCTP_BUF_IS_EXTENDED(mat)) { sctp_log_mb(mat, SCTP_MBUF_ICOPY); } - mat = mat->m_next; + mat = SCTP_BUF_NEXT(mat); } } #endif } else { /* We can steal the last chunk */ + int l_len; + dmbuf = *m; /* lop off the top part */ m_adj(dmbuf, (offset + sizeof(struct sctp_data_chunk))); - if (dmbuf->m_pkthdr.len > the_len) { + if (SCTP_BUF_NEXT(dmbuf) == NULL) { + l_len = SCTP_BUF_LEN(dmbuf); + } else { + /* + * need to count up the size hopefully does not hit + * this to often :-0 + */ + struct mbuf *lat; + + l_len = 0; + lat = dmbuf; + while (lat) { + l_len += SCTP_BUF_LEN(lat); + lat = SCTP_BUF_NEXT(lat); + } + } + if (l_len > the_len) { /* Trim the end round bytes off too */ - m_adj(dmbuf, -(dmbuf->m_pkthdr.len - the_len)); + m_adj(dmbuf, -(l_len - the_len)); } } if (dmbuf == NULL) { @@ -1821,7 +1826,6 @@ failed_express_del: asoc->last_flags_delivered = ch->ch.chunk_flags; asoc->last_strm_seq_delivered = strmseq; asoc->last_strm_no_delivered = strmno; - if (end) { /* clean up the flags and such */ asoc->fragmented_delivery_inprogress = 0; @@ -1829,6 +1833,13 @@ failed_express_del: asoc->strmin[strmno].last_sequence_delivered++; } stcb->asoc.control_pdapi = NULL; + if (TAILQ_EMPTY(&asoc->reasmqueue) == 0) { + /* + * There could be another message + * ready + */ + need_reasm_check = 1; + } } control = NULL; goto finish_express_del; @@ -1901,19 +1912,19 @@ failed_pdapi_express_del: control->data = NULL; sctp_free_remote_addr(control->whoFrom); sctp_free_a_readq(stcb, control); - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), + oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), 0, M_DONTWAIT, 1, MT_DATA); if (oper) { struct sctp_paramhdr *ph; uint32_t *ippp; - oper->m_len = + SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) + (3 * sizeof(uint32_t)); ph = mtod(oper, struct sctp_paramhdr *); ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION); - ph->param_length = htons(oper->m_len); + ph->param_length = htons(SCTP_BUF_LEN(oper)); ippp = (uint32_t *) (ph + 1); *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_15); ippp++; @@ -1934,13 +1945,13 @@ failed_pdapi_express_del: sctp_free_remote_addr(control->whoFrom); sctp_free_a_readq(stcb, control); - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), + oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), 0, M_DONTWAIT, 1, MT_DATA); if (oper) { struct sctp_paramhdr *ph; uint32_t *ippp; - oper->m_len = + SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) + (3 * sizeof(uint32_t)); ph = mtod(oper, @@ -1948,7 +1959,7 @@ failed_pdapi_express_del: ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION); ph->param_length = - htons(oper->m_len); + htons(SCTP_BUF_LEN(oper)); ippp = (uint32_t *) (ph + 1); *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_16); ippp++; @@ -1978,13 +1989,13 @@ failed_pdapi_express_del: control->data = NULL; sctp_free_remote_addr(control->whoFrom); sctp_free_a_readq(stcb, control); - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), + oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), 0, M_DONTWAIT, 1, MT_DATA); if (oper) { struct sctp_paramhdr *ph; uint32_t *ippp; - oper->m_len = + SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) + (3 * sizeof(uint32_t)); ph = mtod(oper, @@ -1992,7 +2003,7 @@ failed_pdapi_express_del: ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION); ph->param_length = - htons(oper->m_len); + htons(SCTP_BUF_LEN(oper)); ippp = (uint32_t *) (ph + 1); *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_17); ippp++; @@ -2118,6 +2129,10 @@ finish_express_del: asoc->highest_tsn_inside_map, SCTP_MAP_PREPARE_SLIDE); #endif SCTP_SET_TSN_PRESENT(asoc->mapping_array, gap); + if (need_reasm_check) { + /* Another one waits ? */ + sctp_deliver_reasm_check(stcb, asoc); + } return (1); } @@ -2367,7 +2382,7 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort * maker sure SACK timer is off and instead send a * SHUTDOWN and a SACK */ - if (callout_pending(&stcb->asoc.dack_timer.timer)) { + if (SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) { sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_INDATA + SCTP_LOC_18); } @@ -2393,15 +2408,15 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort (stcb->asoc.numduptsns) || /* we have dup's */ (is_a_gap) || /* is still a gap */ (stcb->asoc.delayed_ack == 0) || - (callout_pending(&stcb->asoc.dack_timer.timer)) /* timer was up . second - * packet */ + (SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) /* timer was up . second + * packet */ ) { if ((sctp_cmt_on_off) && (sctp_cmt_use_dac) && (stcb->asoc.first_ack_sent == 1) && (stcb->asoc.numduptsns == 0) && (stcb->asoc.delayed_ack) && - (!callout_pending(&stcb->asoc.dack_timer.timer))) { + (!SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer))) { /* * CMT DAC algorithm: With CMT, @@ -2456,6 +2471,7 @@ sctp_service_queues(struct sctp_tcb *stcb, struct sctp_association *asoc) * Now is there some other chunk I can deliver from the reassembly * queue. */ +doit_again: chk = TAILQ_FIRST(&asoc->reasmqueue); if (chk == NULL) { asoc->size_on_reasm_queue = 0; @@ -2485,6 +2501,9 @@ sctp_service_queues(struct sctp_tcb *stcb, struct sctp_association *asoc) asoc->pdapi_ppid = chk->rec.data.payloadtype; asoc->fragment_flags = chk->rec.data.rcv_flags; sctp_service_reassembly(stcb, asoc); + if (asoc->fragmented_delivery_inprogress == 0) { + goto doit_again; + } } } } @@ -2542,23 +2561,19 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length, * to a smaller mbuf and free up the cluster mbuf. This will help * with cluster starvation. */ - if (m->m_len < (long)MHLEN && m->m_next == NULL) { + if (SCTP_BUF_LEN(m) < (long)MHLEN && SCTP_BUF_NEXT(m) == NULL) { /* we only handle mbufs that are singletons.. not chains */ - m = sctp_get_mbuf_for_msg(m->m_len, 1, M_DONTWAIT, 1, MT_DATA); + m = sctp_get_mbuf_for_msg(SCTP_BUF_LEN(m), 0, M_DONTWAIT, 1, MT_DATA); if (m) { /* ok lets see if we can copy the data up */ caddr_t *from, *to; - if ((*mm)->m_flags & M_PKTHDR) { - /* got to copy the header first */ - M_MOVE_PKTHDR(m, (*mm)); - } /* get the pointers and copy */ to = mtod(m, caddr_t *); from = mtod((*mm), caddr_t *); - memcpy(to, from, (*mm)->m_len); + memcpy(to, from, SCTP_BUF_LEN((*mm))); /* copy the length and free up the old */ - m->m_len = (*mm)->m_len; + SCTP_BUF_LEN(m) = SCTP_BUF_LEN((*mm)); sctp_m_freem(*mm); /* sucess, back copy */ *mm = m; @@ -2594,19 +2609,19 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length, */ struct mbuf *op_err; - op_err = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), + op_err = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 2 * sizeof(uint32_t)), 0, M_DONTWAIT, 1, MT_DATA); if (op_err) { struct sctp_paramhdr *ph; uint32_t *ippp; - op_err->m_len = sizeof(struct sctp_paramhdr) + + SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr) + (2 * sizeof(uint32_t)); ph = mtod(op_err, struct sctp_paramhdr *); ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION); - ph->param_length = htons(op_err->m_len); + ph->param_length = htons(SCTP_BUF_LEN(op_err)); ippp = (uint32_t *) (ph + 1); *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_19); ippp++; @@ -2689,7 +2704,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length, struct mbuf *mm; struct sctp_paramhdr *phd; - mm = sctp_get_mbuf_for_msg(sizeof(*phd), 1, M_DONTWAIT, 1, MT_DATA); + mm = sctp_get_mbuf_for_msg(sizeof(*phd), 0, M_DONTWAIT, 1, MT_DATA); if (mm) { phd = mtod(mm, struct sctp_paramhdr *); /* @@ -2704,14 +2719,11 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length, htons(SCTP_CAUSE_UNRECOG_CHUNK); phd->param_length = htons(chk_length + sizeof(*phd)); - mm->m_len = sizeof(*phd); - mm->m_next = sctp_m_copym(m, *offset, + SCTP_BUF_LEN(mm) = sizeof(*phd); + SCTP_BUF_NEXT(mm) = sctp_m_copym(m, *offset, SCTP_SIZE32(chk_length), M_DONTWAIT); - if (mm->m_next) { - mm->m_pkthdr.len = - SCTP_SIZE32(chk_length) + - sizeof(*phd); + if (SCTP_BUF_NEXT(mm)) { sctp_queue_op_err(stcb, mm); } else { sctp_m_freem(mm); @@ -2776,9 +2788,9 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length, /* need to do the slide */ sctp_sack_check(stcb, 1, was_a_gap, &abort_flag); } else { - if (callout_pending(&stcb->asoc.dack_timer.timer)) { + if (SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) { stcb->asoc.first_ack_sent = 1; - callout_stop(&stcb->asoc.dack_timer.timer); + SCTP_OS_TIMER_STOP(&stcb->asoc.dack_timer.timer); sctp_send_sack(stcb); } else { sctp_timer_start(SCTP_TIMER_TYPE_RECV, @@ -2797,7 +2809,8 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length, static void sctp_handle_segments(struct sctp_tcb *stcb, struct sctp_association *asoc, struct sctp_sack_chunk *ch, uint32_t last_tsn, uint32_t * biggest_tsn_acked, - uint32_t * biggest_newly_acked_tsn, uint32_t * this_sack_lowest_newack, int num_seg, int *ecn_seg_sums) + uint32_t * biggest_newly_acked_tsn, uint32_t * this_sack_lowest_newack, + int num_seg, int *ecn_seg_sums) { /************************************************/ /* process fragments and update sendqueue */ @@ -3898,7 +3911,7 @@ sctp_cwnd_update(struct sctp_tcb *stcb, * to illicit a sack with gaps to force out * the others. */ - if (callout_pending(&net->fr_timer.timer)) { + if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) { SCTP_STAT_INCR(sctps_earlyfrstpidsck2); sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_20); @@ -3907,7 +3920,7 @@ sctp_cwnd_update(struct sctp_tcb *stcb, sctp_timer_start(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net); } else { /* No, stop it if its running */ - if (callout_pending(&net->fr_timer.timer)) { + if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) { SCTP_STAT_INCR(sctps_earlyfrstpidsck3); sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_21); @@ -4088,6 +4101,44 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack, net->net_ack = 0; net->net_ack2 = 0; } + if (sctp_strict_sacks) { + uint32_t send_s; + + if (TAILQ_EMPTY(&asoc->send_queue)) { + send_s = asoc->sending_seq; + } else { + tp1 = TAILQ_FIRST(&asoc->send_queue); + send_s = tp1->rec.data.TSN_seq; + } + if ((cumack == send_s) || + compare_with_wrap(cumack, send_s, MAX_TSN)) { +#ifdef INVARIANTS /* for testing only */ + panic("Impossible sack 1"); +#else + struct mbuf *oper; + + *abort_now = 1; + /* XXX */ + oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), + 0, M_DONTWAIT, 1, MT_DATA); + if (oper) { + struct sctp_paramhdr *ph; + uint32_t *ippp; + + SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) + + sizeof(uint32_t); + ph = mtod(oper, struct sctp_paramhdr *); + ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION); + ph->param_length = htons(SCTP_BUF_LEN(oper)); + ippp = (uint32_t *) (ph + 1); + *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_25); + } + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_25; + sctp_abort_an_association(stcb->sctp_ep, stcb, SCTP_PEER_FAULTY, oper); + return; +#endif + } + } asoc->this_sack_highest_gap = cumack; stcb->asoc.overall_error_count = 0; /* process the new consecutive TSN first */ @@ -4276,16 +4327,16 @@ again: to_ticks = MSEC_TO_TICKS(net->RTO); } j++; - callout_reset(&net->rxt_timer.timer, to_ticks, + SCTP_OS_TIMER_START(&net->rxt_timer.timer, to_ticks, sctp_timeout_handler, &net->rxt_timer); } else { - if (callout_pending(&net->rxt_timer.timer)) { + if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) { sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_22); } if (sctp_early_fr) { - if (callout_pending(&net->fr_timer.timer)) { + if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) { SCTP_STAT_INCR(sctps_earlyfrstpidsck4); sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_23); @@ -4359,11 +4410,11 @@ again: struct sctp_paramhdr *ph; uint32_t *ippp; - oper->m_len = sizeof(struct sctp_paramhdr) + + SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) + sizeof(uint32_t); ph = mtod(oper, struct sctp_paramhdr *); ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT); - ph->param_length = htons(oper->m_len); + ph->param_length = htons(SCTP_BUF_LEN(oper)); ippp = (uint32_t *) (ph + 1); *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_24); } @@ -4515,6 +4566,10 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb, if (sctp_strict_sacks) { if (cum_ack == send_s || compare_with_wrap(cum_ack, send_s, MAX_TSN)) { +#ifdef INVARIANTS /* for testing only */ + hopeless_peer: + panic("Impossible sack 1"); +#else struct mbuf *oper; /* @@ -4530,17 +4585,18 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb, struct sctp_paramhdr *ph; uint32_t *ippp; - oper->m_len = sizeof(struct sctp_paramhdr) + + SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) + sizeof(uint32_t); ph = mtod(oper, struct sctp_paramhdr *); ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION); - ph->param_length = htons(oper->m_len); + ph->param_length = htons(SCTP_BUF_LEN(oper)); ippp = (uint32_t *) (ph + 1); *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_25); } stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_25; sctp_abort_an_association(stcb->sctp_ep, stcb, SCTP_PEER_FAULTY, oper); return; +#endif } } /**********************/ @@ -4573,7 +4629,7 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb, sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_26); if (sctp_early_fr) { - if (callout_pending(&net->fr_timer.timer)) { + if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) { SCTP_STAT_INCR(sctps_earlyfrstpidsck1); sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_26); @@ -4927,7 +4983,7 @@ done_with_it: TAILQ_FOREACH(net, &asoc->nets, sctp_next) { /* stop all timers */ if (sctp_early_fr) { - if (callout_pending(&net->fr_timer.timer)) { + if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) { SCTP_STAT_INCR(sctps_earlyfrstpidsck4); sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_29); @@ -4991,11 +5047,11 @@ done_with_it: struct sctp_paramhdr *ph; uint32_t *ippp; - oper->m_len = sizeof(struct sctp_paramhdr) + + SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) + sizeof(uint32_t); ph = mtod(oper, struct sctp_paramhdr *); ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT); - ph->param_length = htons(oper->m_len); + ph->param_length = htons(SCTP_BUF_LEN(oper)); ippp = (uint32_t *) (ph + 1); *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_31); } @@ -5653,4 +5709,8 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb, sctp_kick_prsctp_reorder_queue(stcb, strm); } } + if (TAILQ_FIRST(&asoc->reasmqueue)) { + /* now lets kick out and check for more fragmented delivery */ + sctp_deliver_reasm_check(stcb, &stcb->asoc); + } } diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index adeb48b..8674713 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -455,7 +455,7 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset, */ struct sctp_inv_mandatory_param *mp; - op_err->m_len = + SCTP_BUF_LEN(op_err) = sizeof(struct sctp_inv_mandatory_param); mp = mtod(op_err, struct sctp_inv_mandatory_param *); @@ -612,9 +612,6 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp, SCTP_INP_READ_LOCK(stcb->sctp_ep); asoc->control_pdapi->end_added = 1; asoc->control_pdapi->pdapi_aborted = 1; - if (asoc->control_pdapi->tail_mbuf) { - asoc->control_pdapi->tail_mbuf->m_flags |= M_EOR; - } asoc->control_pdapi = NULL; SCTP_INP_READ_UNLOCK(stcb->sctp_ep); sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket); @@ -704,9 +701,6 @@ sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp, SCTP_INP_READ_LOCK(stcb->sctp_ep); asoc->control_pdapi->end_added = 1; asoc->control_pdapi->pdapi_aborted = 1; - if (asoc->control_pdapi->tail_mbuf) { - asoc->control_pdapi->tail_mbuf->m_flags |= M_EOR; - } asoc->control_pdapi = NULL; SCTP_INP_READ_UNLOCK(stcb->sctp_ep); sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket); @@ -1119,17 +1113,17 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, sctp_send_shutdown_ack(stcb, stcb->asoc.primary_destination); op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), - 1, M_DONTWAIT, 1, MT_DATA); + 0, M_DONTWAIT, 1, MT_DATA); if (op_err == NULL) { /* FOOBAR */ return (NULL); } /* pre-reserve some space */ - op_err->m_data += sizeof(struct ip6_hdr); - op_err->m_data += sizeof(struct sctphdr); - op_err->m_data += sizeof(struct sctp_chunkhdr); + SCTP_BUF_RESV_UF(op_err, sizeof(struct ip6_hdr)); + SCTP_BUF_RESV_UF(op_err, sizeof(struct sctphdr)); + SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr)); /* Set the len */ - op_err->m_len = op_err->m_pkthdr.len = sizeof(struct sctp_paramhdr); + SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr); ph = mtod(op_err, struct sctp_paramhdr *); ph->param_type = htons(SCTP_CAUSE_COOKIE_IN_SHUTDOWN); ph->param_length = htons(sizeof(struct sctp_paramhdr)); @@ -1371,10 +1365,35 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, /* temp code */ sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_14); sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_15); + *sac_assoc_id = sctp_get_associd(stcb); /* notify upper layer */ *notification = SCTP_NOTIFY_ASSOC_RESTART; atomic_add_int(&stcb->asoc.refcnt, 1); + if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) { + asoc->state = SCTP_STATE_OPEN | + SCTP_STATE_SHUTDOWN_PENDING; + sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, + stcb->sctp_ep, stcb, asoc->primary_destination); + + } else if (!(asoc->state & SCTP_STATE_SHUTDOWN_SENT)) { + /* move to OPEN state, if not in SHUTDOWN_SENT */ + asoc->state = SCTP_STATE_OPEN; + } + asoc->pre_open_streams = + ntohs(initack_cp->init.num_outbound_streams); + asoc->init_seq_number = ntohl(initack_cp->init.initial_tsn); + asoc->sending_seq = asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number; + + asoc->last_cwr_tsn = asoc->init_seq_number - 1; + asoc->asconf_seq_in = asoc->last_acked_seq = asoc->init_seq_number - 1; + + asoc->str_reset_seq_in = asoc->init_seq_number; + + asoc->advanced_peer_ack_point = asoc->last_acked_seq; + if (asoc->mapping_array) + memset(asoc->mapping_array, 0, + asoc->mapping_array_size); SCTP_TCB_UNLOCK(stcb); SCTP_INP_INFO_WLOCK(); SCTP_INP_WLOCK(stcb->sctp_ep); @@ -1412,20 +1431,6 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, LIST_INSERT_HEAD(head, stcb, sctp_tcbrestarhash); stcb->asoc.in_restart_hash = 1; } - asoc->pre_open_streams = - ntohs(initack_cp->init.num_outbound_streams); - asoc->init_seq_number = ntohl(initack_cp->init.initial_tsn); - asoc->sending_seq = asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number; - - asoc->last_cwr_tsn = asoc->init_seq_number - 1; - asoc->asconf_seq_in = asoc->last_acked_seq = asoc->init_seq_number - 1; - - asoc->str_reset_seq_in = asoc->init_seq_number; - - asoc->advanced_peer_ack_point = asoc->last_acked_seq; - if (asoc->mapping_array) - memset(asoc->mapping_array, 0, - asoc->mapping_array_size); /* process the INIT info (peer's info) */ SCTP_TCB_SEND_UNLOCK(stcb); SCTP_INP_WUNLOCK(stcb->sctp_ep); @@ -1446,16 +1451,6 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, initack_offset, sh, init_src)) { return (NULL); } - if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) { - asoc->state = SCTP_STATE_OPEN | - SCTP_STATE_SHUTDOWN_PENDING; - sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, - stcb->sctp_ep, stcb, asoc->primary_destination); - - } else if (!(asoc->state & SCTP_STATE_SHUTDOWN_SENT)) { - /* move to OPEN state, if not in SHUTDOWN_SENT */ - asoc->state = SCTP_STATE_OPEN; - } /* respond with a COOKIE-ACK */ sctp_stop_all_cookie_timers(stcb); sctp_toss_old_cookies(stcb, asoc); @@ -1799,6 +1794,8 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, sin->sin_len = sizeof(*sin); sin->sin_port = sh->dest_port; sin->sin_addr.s_addr = iph->ip_dst.s_addr; + size_of_pkt = SCTP_GET_IPV4_LENGTH(iph); + } else if (iph->ip_v == (IPV6_VERSION >> 4)) { /* its IPv6 */ struct ip6_hdr *ip6; @@ -1811,6 +1808,7 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, ip6 = mtod(m, struct ip6_hdr *); sin6->sin6_port = sh->dest_port; sin6->sin6_addr = ip6->ip6_dst; + size_of_pkt = SCTP_GET_IPV6_LENGTH(ip6); } else { return (NULL); } @@ -1831,20 +1829,6 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, */ return (NULL); } - /* compute size of packet */ - if (m->m_flags & M_PKTHDR) { - size_of_pkt = m->m_pkthdr.len; - } else { - /* Should have a pkt hdr really */ - struct mbuf *mat; - - mat = m; - size_of_pkt = 0; - while (mat != NULL) { - size_of_pkt += mat->m_len; - mat = mat->m_next; - } - } if (cookie_len > size_of_pkt || cookie_len < sizeof(struct sctp_cookie_echo_chunk) + sizeof(struct sctp_init_chunk) + @@ -1925,35 +1909,10 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, struct mbuf *m_at; m_at = m; - while (m_at->m_next != NULL) { - m_at = m_at->m_next; - } - m_at->m_next = m_sig; - if (m->m_flags & M_PKTHDR) { - /* - * We should only do this if and only if the front - * mbuf has a m_pkthdr... it should in theory. - */ - if (m_sig->m_flags & M_PKTHDR) { - /* Add back to the pkt hdr of main m chain */ - m->m_pkthdr.len += m_sig->m_pkthdr.len; - } else { - /* - * Got a problem, no pkthdr in split chain. - * TSNH but we will handle it just in case - */ - int mmlen = 0; - struct mbuf *lat; - - printf("Warning: Hitting m_split join TSNH code - fixed\n"); - lat = m_sig; - while (lat) { - mmlen += lat->m_len; - lat = lat->m_next; - } - m->m_pkthdr.len += mmlen; - } + while (SCTP_BUF_NEXT(m_at) != NULL) { + m_at = SCTP_BUF_NEXT(m_at); } + SCTP_BUF_NEXT(m_at) = m_sig; } if (cookie_ok == 0) { @@ -1980,18 +1939,18 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, uint32_t tim; op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_stale_cookie_msg), - 1, M_DONTWAIT, 1, MT_DATA); + 0, M_DONTWAIT, 1, MT_DATA); if (op_err == NULL) { /* FOOBAR */ return (NULL); } /* pre-reserve some space */ - op_err->m_data += sizeof(struct ip6_hdr); - op_err->m_data += sizeof(struct sctphdr); - op_err->m_data += sizeof(struct sctp_chunkhdr); + SCTP_BUF_RESV_UF(op_err, sizeof(struct ip6_hdr)); + SCTP_BUF_RESV_UF(op_err, sizeof(struct sctphdr)); + SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr)); /* Set the len */ - op_err->m_len = op_err->m_pkthdr.len = sizeof(struct sctp_stale_cookie_msg); + SCTP_BUF_LEN(op_err) = sizeof(struct sctp_stale_cookie_msg); scm = mtod(op_err, struct sctp_stale_cookie_msg *); scm->ph.param_type = htons(SCTP_CAUSE_STALE_COOKIE); scm->ph.param_length = htons((sizeof(struct sctp_paramhdr) + @@ -3117,7 +3076,7 @@ sctp_handle_stream_reset(struct sctp_tcb *stcb, struct sctp_stream_reset_out_req chk->asoc = &stcb->asoc; chk->no_fr_allowed = 0; chk->book_size = chk->send_size = sizeof(struct sctp_chunkhdr); - chk->data = sctp_get_mbuf_for_msg(MCLBYTES, 1, M_DONTWAIT, 1, MT_DATA); + chk->data = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_DONTWAIT, 1, MT_DATA); if (chk->data == NULL) { strres_nochunk: if (chk->data) { @@ -3127,7 +3086,7 @@ strres_nochunk: sctp_free_a_chunk(stcb, chk); return (ret_code); } - chk->data->m_data += SCTP_MIN_OVERHEAD; + SCTP_BUF_RESV_UF(chk->data, SCTP_MIN_OVERHEAD); /* setup chunk parameters */ chk->sent = SCTP_DATAGRAM_UNSENT; @@ -3139,7 +3098,7 @@ strres_nochunk: ch->chunk_type = SCTP_STREAM_RESET; ch->chunk_flags = 0; ch->chunk_length = htons(chk->send_size); - chk->data->m_pkthdr.len = chk->data->m_len = SCTP_SIZE32(chk->send_size); + SCTP_BUF_LEN(chk->data) = SCTP_SIZE32(chk->send_size); ph = (struct sctp_paramhdr *)&sr_req->sr_req; @@ -3706,12 +3665,11 @@ process_control_chunks: oper = NULL; oper = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), - 1, M_DONTWAIT, 1, MT_DATA); + 0, M_DONTWAIT, 1, MT_DATA); if (oper) { /* pre-reserve some space */ - oper->m_data += sizeof(struct sctp_chunkhdr); - oper->m_len = sizeof(struct sctp_paramhdr); - oper->m_pkthdr.len = oper->m_len; + SCTP_BUF_RESV_UF(oper, sizeof(struct sctp_chunkhdr)); + SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr); phdr = mtod(oper, struct sctp_paramhdr *); phdr->param_type = htons(SCTP_CAUSE_OUT_OF_RESC); phdr->param_length = htons(sizeof(struct sctp_paramhdr)); @@ -4016,10 +3974,9 @@ process_control_chunks: if (sctp_abort_if_one_2_one_hits_limit) { oper = NULL; oper = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), - 1, M_DONTWAIT, 1, MT_DATA); + 0, M_DONTWAIT, 1, MT_DATA); if (oper) { - oper->m_len = - oper->m_pkthdr.len = + SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr); phdr = mtod(oper, struct sctp_paramhdr *); @@ -4296,7 +4253,7 @@ process_control_chunks: struct sctp_paramhdr *phd; mm = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), - 1, M_DONTWAIT, 1, MT_DATA); + 0, M_DONTWAIT, 1, MT_DATA); if (mm) { phd = mtod(mm, struct sctp_paramhdr *); /* @@ -4308,11 +4265,10 @@ process_control_chunks: */ phd->param_type = htons(SCTP_CAUSE_UNRECOG_CHUNK); phd->param_length = htons(chk_length + sizeof(*phd)); - mm->m_len = sizeof(*phd); - mm->m_next = sctp_m_copym(m, *offset, SCTP_SIZE32(chk_length), + SCTP_BUF_LEN(mm) = sizeof(*phd); + SCTP_BUF_NEXT(mm) = sctp_m_copym(m, *offset, SCTP_SIZE32(chk_length), M_DONTWAIT); - if (mm->m_next) { - mm->m_pkthdr.len = SCTP_SIZE32(chk_length) + sizeof(*phd); + if (SCTP_BUF_NEXT(mm)) { sctp_queue_op_err(stcb, mm); } else { sctp_m_freem(mm); @@ -4648,8 +4604,8 @@ uint8_t sctp_list_of_chunks[30000]; void -sctp_input(m, off) - struct mbuf *m; +sctp_input(i_pak, off) + struct mbuf *i_pak; int off; { @@ -4657,6 +4613,7 @@ sctp_input(m, off) struct mbuf *mat; #endif + struct mbuf *m; int iphlen; int s; uint8_t ecn_bits; @@ -4673,6 +4630,7 @@ sctp_input(m, off) iphlen = off; + m = SCTP_HEADER_TO_CHAIN(i_pak); net = NULL; SCTP_STAT_INCR(sctps_recvpackets); SCTP_STAT_INCR_COUNTER64(sctps_inpackets); @@ -4684,10 +4642,10 @@ sctp_input(m, off) /* Log in any input mbufs */ mat = m; while (mat) { - if (mat->m_flags & M_EXT) { + if (SCTP_BUF_IS_EXTENDED(mat)) { sctp_log_mb(mat, SCTP_MBUF_INPUT); } - mat = mat->m_next; + mat = SCTP_BUF_NEXT(mat); } #endif if ((size_t)iphlen > sizeof(struct ip)) { @@ -4699,7 +4657,7 @@ sctp_input(m, off) */ ip = mtod(m, struct ip *); offset = iphlen + sizeof(*sh) + sizeof(*ch); - if (m->m_len < offset) { + if (SCTP_BUF_LEN(m) < offset) { if ((m = m_pullup(m, offset)) == 0) { SCTP_STAT_INCR(sctps_hdrops); return; @@ -4716,7 +4674,7 @@ sctp_input(m, off) if (((ch->chunk_type == SCTP_INITIATION) || (ch->chunk_type == SCTP_INITIATION_ACK) || (ch->chunk_type == SCTP_COOKIE_ECHO)) && - (in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif))) { + (SCTP_IS_IT_BROADCAST(ip->ip_dst, i_pak))) { /* * We only look at broadcast if its a front state, All * others we will not have a tcb for anyway. @@ -4730,8 +4688,7 @@ sctp_input(m, off) } /* validate SCTP checksum */ if ((sctp_no_csum_on_loopback == 0) || - (m->m_pkthdr.rcvif == NULL) || - (m->m_pkthdr.rcvif->if_type != IFT_LOOP)) { + SCTP_IS_IT_LOOPBACK(i_pak)) { /* * we do NOT validate things from the loopback if the sysctl * is set to 1. @@ -4772,7 +4729,7 @@ sctp_input(m, off) sh->checksum = calc_check; } else { sctp_skip_csum_4: - mlen = m->m_pkthdr.len; + mlen = SCTP_HEADER_LEN(i_pak); } /* validate mbuf chain length with IP payload length */ if (mlen < (ip->ip_len - iphlen)) { diff --git a/sys/netinet/sctp_os.h b/sys/netinet/sctp_os.h index 436eb37..a4545b3 100644 --- a/sys/netinet/sctp_os.h +++ b/sys/netinet/sctp_os.h @@ -55,13 +55,9 @@ __FBSDID("$FreeBSD$"); * SCTP_ZONE_DESTROY(zone) */ -/* - * Functions: - * sctp_read_random(void *buffer, uint32_t bytes) - */ - #include <netinet/sctp_os_bsd.h> + #endif diff --git a/sys/netinet/sctp_os_bsd.h b/sys/netinet/sctp_os_bsd.h index 9b557a2..d355324 100644 --- a/sys/netinet/sctp_os_bsd.h +++ b/sys/netinet/sctp_os_bsd.h @@ -37,7 +37,6 @@ __FBSDID("$FreeBSD$"); */ #include <sys/random.h> - /* * */ @@ -85,8 +84,74 @@ typedef struct uma_zone *sctp_zone_t; uma_zfree(zone, element); /* + * timers + */ +#include <sys/callout.h> +typedef struct callout sctp_os_timer_t; + +#define SCTP_OS_TIMER_INIT(tmr) callout_init(tmr, 1) +#define SCTP_OS_TIMER_START callout_reset +#define SCTP_OS_TIMER_STOP callout_stop +#define SCTP_OS_TIMER_PENDING callout_pending +#define SCTP_OS_TIMER_ACTIVE callout_active +#define SCTP_OS_TIMER_DEACTIVATE callout_deactivate + +/* * Functions */ -#define sctp_read_random(buf, len) read_random(buf, len) +#define SCTP_READ_RANDOM(buf, len) read_random(buf, len) + +/* Mbuf manipulation and access macros */ +#define SCTP_BUF_LEN(m) (m->m_len) +#define SCTP_BUF_NEXT(m) (m->m_next) +#define SCTP_BUF_NEXT_PKT(m) (m->m_nextpkt) +#define SCTP_BUF_RESV_UF(m, size) m->m_data += size +#define SCTP_BUF_AT(m, size) m->m_data + size +#define SCTP_BUF_IS_EXTENDED(m) (m->m_flags & M_EXT) +#define SCTP_BUF_EXTEND_SIZE(m) (m->m_ext.ext_size) +#define SCTP_BUF_TYPE(m) (m->m_type) +#define SCTP_BUF_RECVIF(m) (m->m_pkthdr.rcvif) +#define SCTP_BUF_PREPEND M_PREPEND +/*************************/ +/* These are for logging */ +/*************************/ +/* return the base ext data pointer */ +#define SCTP_BUF_EXTEND_BASE(m) (m->m_ext.ext_buf) + /* return the refcnt of the data pointer */ +#define SCTP_BUF_EXTEND_REFCNT(m) (*m->m_ext.ref_cnt) +/* return any buffer related flags, this is + * used beyond logging for apple only. + */ +#define SCTP_BUF_GET_FLAGS(m) (m->m_flags) + +/* For BSD this just accesses the M_PKTHDR length + * so it operates on an mbuf with hdr flag. Other + * O/S's may have seperate packet header and mbuf + * chain pointers.. thus the macro. + */ +#define SCTP_HEADER_TO_CHAIN(m) (m) +#define SCTP_HEADER_LEN(m) (m->m_pkthdr.len) +#define SCTP_GET_HEADER_FOR_OUTPUT(len) sctp_get_mbuf_for_msg(len, 1, M_DONTWAIT, 1, MT_DATA) + +/* Attach the chain of data into the sendable packet. */ +#define SCTP_ATTACH_CHAIN(pak, m, packet_length) do { \ + pak->m_next = m; \ + pak->m_pkthdr.len = packet_length; \ + } while(0) + +/* Other m_pkthdr type things */ +#define SCTP_IS_IT_BROADCAST(dst, m) in_broadcast(dst, m->m_pkthdr.rcvif) +#define SCTP_IS_IT_LOOPBACK(m) ((m->m_pkthdr.rcvif == NULL) ||(m->m_pkthdr.rcvif->if_type == IFT_LOOP)) + + +/* This converts any input packet header + * into the chain of data holders, for BSD + * its a NOP. + */ +#define SCTP_PAK_TO_BUF(i_pak) (i_pak) + +/* Macro's for getting length from V6/V4 header */ +#define SCTP_GET_IPV4_LENGTH(iph) (iph->ip_len) +#define SCTP_GET_IPV6_LENGTH(ip6) (ntohs(ip6->ip6_plen)) #endif diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 74e1181..261b66e 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -1931,7 +1931,7 @@ sctp_find_cmsg(int c_type, void *data, struct mbuf *control, int cpsize) struct cmsghdr cmh; int tlen, at; - tlen = control->m_len; + tlen = SCTP_BUF_LEN(control); at = 0; /* * Independent of how many mbufs, find the c_type inside the control @@ -2020,7 +2020,7 @@ try_again: if (m == NULL) { return (NULL); } - if ((m->m_flags & M_EXT) == 0) { + if (SCTP_BUF_IS_EXTENDED(m) == 0) { if ((aloc_size != MCLBYTES) && (allonebuf == 0)) { aloc_size -= 10; @@ -2030,17 +2030,13 @@ try_again: return (NULL); } } - m->m_len = 0; - m->m_next = m->m_nextpkt = NULL; + SCTP_BUF_LEN(m) = 0; + SCTP_BUF_NEXT(m) = SCTP_BUF_NEXT_PKT(m) = NULL; #ifdef SCTP_MBUF_LOGGING - if (m->m_flags & M_EXT) { + if (SCTP_BUF_IS_EXTENDED(m)) { sctp_log_mb(m, SCTP_MBUF_IALLOC); } #endif - - if (want_header) { - m->m_pkthdr.len = 0; - } return (m); } @@ -2079,7 +2075,7 @@ sctp_add_cookie(struct sctp_inpcb *inp, struct mbuf *init, int init_offset, } /* easy side we just drop it on the end */ ph = mtod(mret, struct sctp_paramhdr *); - mret->m_len = sizeof(struct sctp_state_cookie) + + SCTP_BUF_LEN(mret) = sizeof(struct sctp_state_cookie) + sizeof(struct sctp_paramhdr); stc = (struct sctp_state_cookie *)((caddr_t)ph + sizeof(struct sctp_paramhdr)); @@ -2091,25 +2087,25 @@ sctp_add_cookie(struct sctp_inpcb *inp, struct mbuf *init, int init_offset, /* tack the INIT and then the INIT-ACK onto the chain */ cookie_sz = 0; m_at = mret; - for (m_at = mret; m_at; m_at = m_at->m_next) { - cookie_sz += m_at->m_len; - if (m_at->m_next == NULL) { - m_at->m_next = copy_init; + for (m_at = mret; m_at; m_at = SCTP_BUF_NEXT(m_at)) { + cookie_sz += SCTP_BUF_LEN(m_at); + if (SCTP_BUF_NEXT(m_at) == NULL) { + SCTP_BUF_NEXT(m_at) = copy_init; break; } } - for (m_at = copy_init; m_at; m_at = m_at->m_next) { - cookie_sz += m_at->m_len; - if (m_at->m_next == NULL) { - m_at->m_next = copy_initack; + for (m_at = copy_init; m_at; m_at = SCTP_BUF_NEXT(m_at)) { + cookie_sz += SCTP_BUF_LEN(m_at); + if (SCTP_BUF_NEXT(m_at) == NULL) { + SCTP_BUF_NEXT(m_at) = copy_initack; break; } } - for (m_at = copy_initack; m_at; m_at = m_at->m_next) { - cookie_sz += m_at->m_len; - if (m_at->m_next == NULL) { + for (m_at = copy_initack; m_at; m_at = SCTP_BUF_NEXT(m_at)) { + cookie_sz += SCTP_BUF_LEN(m_at); + if (SCTP_BUF_NEXT(m_at) == NULL) { break; } } @@ -2119,8 +2115,8 @@ sctp_add_cookie(struct sctp_inpcb *inp, struct mbuf *init, int init_offset, sctp_m_freem(mret); return (NULL); } - sig->m_len = 0; - m_at->m_next = sig; + SCTP_BUF_LEN(sig) = 0; + SCTP_BUF_NEXT(m_at) = sig; sig_offset = 0; signature = (uint8_t *) (mtod(sig, caddr_t)+sig_offset); /* Time to sign the cookie */ @@ -2128,7 +2124,7 @@ sctp_add_cookie(struct sctp_inpcb *inp, struct mbuf *init, int init_offset, (uint8_t *) inp->sctp_ep.secret_key[(int)(inp->sctp_ep.current_secret_number)], SCTP_SECRET_SIZE, mret, sizeof(struct sctp_paramhdr), (uint8_t *) signature); - sig->m_len += SCTP_SIGNATURE_SIZE; + SCTP_BUF_LEN(sig) += SCTP_SIGNATURE_SIZE; cookie_sz += SCTP_SIGNATURE_SIZE; ph->param_length = htons(cookie_sz); @@ -2204,16 +2200,20 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, /* nofragment_flag to tell if IP_DF should be set (IPv4 only) */ { /* - * Given a mbuf chain (via m_next) that holds a packet header WITH a - * SCTPHDR but no IP header, endpoint inp and sa structure. - fill - * in the HMAC digest of any AUTH chunk in the packet - calculate - * SCTP checksum and fill in - prepend a IP address header - if - * boundall use INADDR_ANY - if boundspecific do source address - * selection - set fragmentation option for ipV4 - On return from IP - * output, check/adjust mtu size - of output interface and - * smallest_mtu size as well. + * Given a mbuf chain (via SCTP_BUF_NEXT()) that holds a packet + * header WITH a SCTPHDR but no IP header, endpoint inp and sa + * structure. - fill in the HMAC digest of any AUTH chunk in the + * packet - calculate SCTP checksum and fill in - prepend a IP + * address header - if boundall use INADDR_ANY - if boundspecific do + * source address selection - set fragmentation option for ipV4 - On + * return from IP output, check/adjust mtu size - of output + * interface and smallest_mtu size as well. */ + /* Will need ifdefs around this */ + struct mbuf *o_pak; + struct sctphdr *sctphdr; + int packet_length; int o_flgs; uint32_t csum; int ret; @@ -2224,15 +2224,6 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, sctp_m_freem(m); return (EFAULT); } - if ((m->m_flags & M_PKTHDR) == 0) { -#ifdef SCTP_DEBUG - if (sctp_debug_on & SCTP_DEBUG_OUTPUT1) { - printf("Software error: sctp_lowlevel_chunk_output() called with non pkthdr!\n"); - } -#endif - sctp_m_freem(m); - return (EFAULT); - } /* fill in the HMAC digest for any AUTH chunk in the packet */ if ((auth != NULL) && (stcb != NULL)) { sctp_fill_hmac_digest_m(m, auth_offset, auth, stcb); @@ -2249,23 +2240,28 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, * no more bad pktlen's coming in. But we will wait a while * yet. */ - m->m_pkthdr.len = sctp_calculate_len(m); + packet_length = sctp_calculate_len(m); } else { sctphdr->checksum = 0; - csum = sctp_calculate_sum(m, &m->m_pkthdr.len, 0); + csum = sctp_calculate_sum(m, &packet_length, 0); sctphdr->checksum = csum; } + if (to->sa_family == AF_INET) { struct ip *ip; struct route iproute; uint8_t tos_value; - M_PREPEND(m, sizeof(struct ip), M_DONTWAIT); - if (m == NULL) { + o_pak = SCTP_GET_HEADER_FOR_OUTPUT(sizeof(struct ip)); + if (o_pak == NULL) { /* failed to prepend data, give up */ + sctp_m_freem(m); return (ENOMEM); } - ip = mtod(m, struct ip *); + SCTP_BUF_LEN(SCTP_HEADER_TO_CHAIN(o_pak)) = sizeof(struct ip); + packet_length += sizeof(struct ip); + SCTP_ATTACH_CHAIN(o_pak, m, packet_length); + ip = mtod(SCTP_HEADER_TO_CHAIN(o_pak), struct ip *); ip->ip_v = IPVERSION; ip->ip_hl = (sizeof(struct ip) >> 2); if (net) { @@ -2287,7 +2283,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, ip->ip_id = ip_newid(); ip->ip_ttl = inp->ip_inp.inp.inp_ip_ttl; - ip->ip_len = m->m_pkthdr.len; + ip->ip_len = SCTP_HEADER_LEN(o_pak); if (stcb) { if ((stcb->asoc.ecn_allowed) && ecn_ok) { /* Enable ECN */ @@ -2330,7 +2326,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, /* * If source address selection fails and we find no route - * then the ip_ouput should fail as well with a + * then the ip_output should fail as well with a * NO_ROUTE_TO_HOST type error. We probably should catch * that somewhere and abort the association right away * (assuming this is an INIT being sent). @@ -2372,7 +2368,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, } } } - sctp_m_freem(m); + sctp_m_freem(o_pak); return (EHOSTUNREACH); } else { have_mtu = ro->ro_rt->rt_ifp->if_mtu; @@ -2397,7 +2393,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, if (ro != &iproute) { memcpy(&iproute, ro, sizeof(*ro)); } - ret = ip_output(m, inp->ip_inp.inp.inp_options, + ret = ip_output(o_pak, inp->ip_inp.inp.inp_options, ro, o_flgs, inp->ip_inp.inp.inp_moptions ,(struct inpcb *)NULL ); @@ -2454,13 +2450,16 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, } else { flowlabel = ((struct in6pcb *)inp)->in6p_flowinfo; } - M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT); - if (m == NULL) { + o_pak = SCTP_GET_HEADER_FOR_OUTPUT(sizeof(struct ip6_hdr)); + if (o_pak == NULL) { /* failed to prepend data, give up */ + sctp_m_freem(m); return (ENOMEM); } - ip6h = mtod(m, struct ip6_hdr *); - + SCTP_BUF_LEN(SCTP_HEADER_TO_CHAIN(o_pak)) = sizeof(struct ip6_hdr); + packet_length += sizeof(struct ip6_hdr); + SCTP_ATTACH_CHAIN(o_pak, m, packet_length); + ip6h = mtod(SCTP_HEADER_TO_CHAIN(o_pak), struct ip6_hdr *); /* * We assume here that inp_flow is in host byte order within * the TCB! @@ -2497,7 +2496,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, } ip6h->ip6_flow = htonl(((tosTop << 24) | ((tosBottom | flowTop) << 16) | flowBottom)); ip6h->ip6_nxt = IPPROTO_SCTP; - ip6h->ip6_plen = m->m_pkthdr.len; + ip6h->ip6_plen = (SCTP_HEADER_LEN(o_pak) - sizeof(struct ip6_hdr)); ip6h->ip6_dst = sin6->sin6_addr; /* @@ -2536,7 +2535,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, printf("low_level_output: dropped v6 pkt- no valid source addr\n"); } #endif - sctp_m_freem(m); + sctp_m_freem(o_pak); if (net) { if ((net->dest_state & SCTP_ADDR_REACHABLE) && stcb) sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, @@ -2572,7 +2571,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, lsa6_storage.sin6_family = AF_INET6; lsa6_storage.sin6_len = sizeof(lsa6_storage); if ((error = sa6_recoverscope(&lsa6_storage)) != 0) { - sctp_m_freem(m); + sctp_m_freem(o_pak); return (error); } /* XXX */ @@ -2610,7 +2609,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, prev_scope = sin6->sin6_scope_id; prev_port = sin6->sin6_port; } - ret = ip6_output(m, ((struct in6pcb *)inp)->in6p_outputopts, + ret = ip6_output(o_pak, ((struct in6pcb *)inp)->in6p_outputopts, (struct route_in6 *)ro, o_flgs, ((struct in6pcb *)inp)->in6p_moptions, @@ -2721,7 +2720,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb) if (IN6_IS_ADDR_LINKLOCAL(&sin6l->sin6_addr)) cnt_inits_to = 1; } - if (callout_pending(&net->rxt_timer.timer)) { + if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) { /* This case should not happen */ return; } @@ -2735,9 +2734,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb) /* No memory, INIT timer will re-attempt. */ return; } - m->m_pkthdr.len = 0; - m->m_data += SCTP_MIN_OVERHEAD; - m->m_len = sizeof(struct sctp_init_msg); + SCTP_BUF_LEN(m) = sizeof(struct sctp_init_msg); /* Now lets put the SCTP header in place */ initm = mtod(m, struct sctp_init_msg *); initm->sh.src_port = inp->sctp_lport; @@ -2767,7 +2764,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb) sizeof(uint16_t)); sup_addr->addr_type[0] = htons(SCTP_IPV4_ADDRESS); sup_addr->addr_type[1] = htons(SCTP_IPV6_ADDRESS); - m->m_len += sizeof(*sup_addr) + sizeof(uint16_t); + SCTP_BUF_LEN(m) += sizeof(*sup_addr) + sizeof(uint16_t); if (inp->sctp_ep.adaptation_layer_indicator) { struct sctp_adaptation_layer_indication *ali; @@ -2777,7 +2774,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb) ali->ph.param_type = htons(SCTP_ULP_ADAPTATION); ali->ph.param_length = htons(sizeof(*ali)); ali->indication = ntohl(inp->sctp_ep.adaptation_layer_indicator); - m->m_len += sizeof(*ali); + SCTP_BUF_LEN(m) += sizeof(*ali); ecn = (struct sctp_ecn_supported_param *)((caddr_t)ali + sizeof(*ali)); } else { @@ -2794,7 +2791,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb) cookie_preserve->ph.param_length = htons( sizeof(*cookie_preserve)); cookie_preserve->time = htonl(stcb->asoc.cookie_preserve_req); - m->m_len += sizeof(*cookie_preserve); + SCTP_BUF_LEN(m) += sizeof(*cookie_preserve); ecn = (struct sctp_ecn_supported_param *)( (caddr_t)cookie_preserve + sizeof(*cookie_preserve)); stcb->asoc.cookie_preserve_req = 0; @@ -2803,7 +2800,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb) if (sctp_ecn_enable == 1) { ecn->ph.param_type = htons(SCTP_ECN_CAPABLE); ecn->ph.param_length = htons(sizeof(*ecn)); - m->m_len += sizeof(*ecn); + SCTP_BUF_LEN(m) += sizeof(*ecn); prsctp = (struct sctp_prsctp_supported_param *)((caddr_t)ecn + sizeof(*ecn)); } else { @@ -2812,7 +2809,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb) /* And now tell the peer we do pr-sctp */ prsctp->ph.param_type = htons(SCTP_PRSCTP_SUPPORTED); prsctp->ph.param_length = htons(sizeof(*prsctp)); - m->m_len += sizeof(*prsctp); + SCTP_BUF_LEN(m) += sizeof(*prsctp); /* And now tell the peer we do all the extensions */ pr_supported = (struct sctp_supported_chunk_types_param *) @@ -2829,7 +2826,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb) p_len = sizeof(*pr_supported) + num_ext; pr_supported->ph.param_length = htons(p_len); bzero((caddr_t)pr_supported + p_len, SCTP_SIZE32(p_len) - p_len); - m->m_len += SCTP_SIZE32(p_len); + SCTP_BUF_LEN(m) += SCTP_SIZE32(p_len); /* ECN nonce: And now tell the peer we support ECN nonce */ if (sctp_ecn_nonce) { @@ -2837,7 +2834,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb) ((caddr_t)pr_supported + SCTP_SIZE32(p_len)); ecn_nonce->ph.param_type = htons(SCTP_ECN_NONCE_SUPPORTED); ecn_nonce->ph.param_length = htons(sizeof(*ecn_nonce)); - m->m_len += sizeof(*ecn_nonce); + SCTP_BUF_LEN(m) += sizeof(*ecn_nonce); } /* add authentication parameters */ if (!sctp_auth_disable) { @@ -2847,7 +2844,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb) /* attach RANDOM parameter, if available */ if (stcb->asoc.authinfo.random != NULL) { - random = (struct sctp_auth_random *)(mtod(m, caddr_t)+m->m_len); + random = (struct sctp_auth_random *)(mtod(m, caddr_t)+SCTP_BUF_LEN(m)); random->ph.param_type = htons(SCTP_RANDOM); p_len = sizeof(*random) + stcb->asoc.authinfo.random_len; random->ph.param_length = htons(p_len); @@ -2855,10 +2852,10 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb) stcb->asoc.authinfo.random_len); /* zero out any padding required */ bzero((caddr_t)random + p_len, SCTP_SIZE32(p_len) - p_len); - m->m_len += SCTP_SIZE32(p_len); + SCTP_BUF_LEN(m) += SCTP_SIZE32(p_len); } /* add HMAC_ALGO parameter */ - hmacs = (struct sctp_auth_hmac_algo *)(mtod(m, caddr_t)+m->m_len); + hmacs = (struct sctp_auth_hmac_algo *)(mtod(m, caddr_t)+SCTP_BUF_LEN(m)); p_len = sctp_serialize_hmaclist(stcb->asoc.local_hmacs, (uint8_t *) hmacs->hmac_ids); if (p_len > 0) { @@ -2867,10 +2864,10 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb) hmacs->ph.param_length = htons(p_len); /* zero out any padding required */ bzero((caddr_t)hmacs + p_len, SCTP_SIZE32(p_len) - p_len); - m->m_len += SCTP_SIZE32(p_len); + SCTP_BUF_LEN(m) += SCTP_SIZE32(p_len); } /* add CHUNKS parameter */ - chunks = (struct sctp_auth_chunk_list *)(mtod(m, caddr_t)+m->m_len); + chunks = (struct sctp_auth_chunk_list *)(mtod(m, caddr_t)+SCTP_BUF_LEN(m)); p_len = sctp_serialize_auth_chunks(stcb->asoc.local_auth_chunks, chunks->chunk_types); if (p_len > 0) { @@ -2879,7 +2876,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb) chunks->ph.param_length = htons(p_len); /* zero out any padding required */ bzero((caddr_t)chunks + p_len, SCTP_SIZE32(p_len) - p_len); - m->m_len += SCTP_SIZE32(p_len); + SCTP_BUF_LEN(m) += SCTP_SIZE32(p_len); } } m_at = m; @@ -2906,21 +2903,20 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb) /* calulate the size and update pkt header and chunk header */ - m->m_pkthdr.len = 0; - for (m_at = m; m_at; m_at = m_at->m_next) { - if (m_at->m_next == NULL) + p_len = 0; + for (m_at = m; m_at; m_at = SCTP_BUF_NEXT(m_at)) { + if (SCTP_BUF_NEXT(m_at) == NULL) m_last = m_at; - m->m_pkthdr.len += m_at->m_len; + p_len += SCTP_BUF_LEN(m_at); } - initm->msg.ch.chunk_length = htons((m->m_pkthdr.len - - sizeof(struct sctphdr))); + initm->msg.ch.chunk_length = htons((p_len - sizeof(struct sctphdr))); /* * We pass 0 here to NOT set IP_DF if its IPv4, we ignore the return * here since the timer will drive a retranmission. */ /* I don't expect this to execute but we will be safe here */ - padval = m->m_pkthdr.len % 4; + padval = p_len % 4; if ((padval) && (m_last)) { /* * The compiler worries that m_last may not be set even @@ -2935,7 +2931,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb) sctp_m_freem(m); return; } - m->m_pkthdr.len += padval; + p_len += padval; } ret = sctp_lowlevel_chunk_output(inp, stcb, net, (struct sockaddr *)&net->ro._l_addr, @@ -3038,17 +3034,16 @@ sctp_arethere_unrecognized_parameters(struct mbuf *in_initpkt, l_len = sizeof(struct ip6_hdr) + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr); l_len += plen; l_len += sizeof(struct sctp_paramhdr); - op_err = sctp_get_mbuf_for_msg(l_len, 1, M_DONTWAIT, 1, MT_DATA); + op_err = sctp_get_mbuf_for_msg(l_len, 0, M_DONTWAIT, 1, MT_DATA); if (op_err) { - op_err->m_len = 0; - op_err->m_pkthdr.len = 0; + SCTP_BUF_LEN(op_err) = 0; /* * pre-reserve space for ip and sctp * header and chunk hdr */ - op_err->m_data += sizeof(struct ip6_hdr); - op_err->m_data += sizeof(struct sctphdr); - op_err->m_data += sizeof(struct sctp_chunkhdr); + SCTP_BUF_RESV_UF(op_err, sizeof(struct ip6_hdr)); + SCTP_BUF_RESV_UF(op_err, sizeof(struct sctphdr)); + SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr)); } } if (op_err) { @@ -3095,13 +3090,12 @@ sctp_arethere_unrecognized_parameters(struct mbuf *in_initpkt, l_len = sizeof(struct ip6_hdr) + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr); l_len += plen; l_len += sizeof(struct sctp_paramhdr); - op_err = sctp_get_mbuf_for_msg(l_len, 1, M_DONTWAIT, 1, MT_DATA); + op_err = sctp_get_mbuf_for_msg(l_len, 0, M_DONTWAIT, 1, MT_DATA); if (op_err) { - op_err->m_len = 0; - op_err->m_pkthdr.len = 0; - op_err->m_data += sizeof(struct ip6_hdr); - op_err->m_data += sizeof(struct sctphdr); - op_err->m_data += sizeof(struct sctp_chunkhdr); + SCTP_BUF_LEN(op_err) = 0; + SCTP_BUF_RESV_UF(op_err, sizeof(struct ip6_hdr)); + SCTP_BUF_RESV_UF(op_err, sizeof(struct sctphdr)); + SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr)); } } if (op_err) { @@ -3354,16 +3348,14 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, sctp_send_abort(init_pkt, iphlen, sh, init_chk->init.initiate_tag, op_err); return; } - m = sctp_get_mbuf_for_msg(MCLBYTES, 1, M_DONTWAIT, 1, MT_DATA); + m = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_DONTWAIT, 1, MT_DATA); if (m == NULL) { /* No memory, INIT timer will re-attempt. */ if (op_err) sctp_m_freem(op_err); return; } - m->m_data += SCTP_MIN_OVERHEAD; - m->m_pkthdr.rcvif = 0; - m->m_len = sizeof(struct sctp_init_msg); + SCTP_BUF_LEN(m) = sizeof(struct sctp_init_msg); /* the time I built cookie */ SCTP_GETTIME_TIMEVAL(&stc.time_entered); @@ -3512,6 +3504,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, /* pull out the scope_id from incoming pkt */ /* FIX ME: does this have scope from rcvif? */ (void)sa6_recoverscope(sin6); + sa6_embedscope(sin6, ip6_use_defzone); stc.scope_id = sin6->sin6_scope_id; } else if (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) { @@ -3674,7 +3667,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, ali->ph.param_type = htons(SCTP_ULP_ADAPTATION); ali->ph.param_length = htons(sizeof(*ali)); ali->indication = ntohl(inp->sctp_ep.adaptation_layer_indicator); - m->m_len += sizeof(*ali); + SCTP_BUF_LEN(m) += sizeof(*ali); ecn = (struct sctp_ecn_supported_param *)((caddr_t)ali + sizeof(*ali)); } else { @@ -3686,7 +3679,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, if (sctp_ecn_enable == 1) { ecn->ph.param_type = htons(SCTP_ECN_CAPABLE); ecn->ph.param_length = htons(sizeof(*ecn)); - m->m_len += sizeof(*ecn); + SCTP_BUF_LEN(m) += sizeof(*ecn); prsctp = (struct sctp_prsctp_supported_param *)((caddr_t)ecn + sizeof(*ecn)); @@ -3696,7 +3689,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, /* And now tell the peer we do pr-sctp */ prsctp->ph.param_type = htons(SCTP_PRSCTP_SUPPORTED); prsctp->ph.param_length = htons(sizeof(*prsctp)); - m->m_len += sizeof(*prsctp); + SCTP_BUF_LEN(m) += sizeof(*prsctp); /* And now tell the peer we do all the extensions */ pr_supported = (struct sctp_supported_chunk_types_param *) @@ -3714,7 +3707,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, p_len = sizeof(*pr_supported) + num_ext; pr_supported->ph.param_length = htons(p_len); bzero((caddr_t)pr_supported + p_len, SCTP_SIZE32(p_len) - p_len); - m->m_len += SCTP_SIZE32(p_len); + SCTP_BUF_LEN(m) += SCTP_SIZE32(p_len); /* ECN nonce: And now tell the peer we support ECN nonce */ if (sctp_ecn_nonce) { @@ -3722,7 +3715,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, ((caddr_t)pr_supported + SCTP_SIZE32(p_len)); ecn_nonce->ph.param_type = htons(SCTP_ECN_NONCE_SUPPORTED); ecn_nonce->ph.param_length = htons(sizeof(*ecn_nonce)); - m->m_len += sizeof(*ecn_nonce); + SCTP_BUF_LEN(m) += sizeof(*ecn_nonce); } /* add authentication parameters */ if (!sctp_auth_disable) { @@ -3733,17 +3726,17 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, /* generate and add RANDOM parameter */ random_len = sctp_auth_random_len; - random = (struct sctp_auth_random *)(mtod(m, caddr_t)+m->m_len); + random = (struct sctp_auth_random *)(mtod(m, caddr_t)+SCTP_BUF_LEN(m)); random->ph.param_type = htons(SCTP_RANDOM); p_len = sizeof(*random) + random_len; random->ph.param_length = htons(p_len); - sctp_read_random(random->random_data, random_len); + SCTP_READ_RANDOM(random->random_data, random_len); /* zero out any padding required */ bzero((caddr_t)random + p_len, SCTP_SIZE32(p_len) - p_len); - m->m_len += SCTP_SIZE32(p_len); + SCTP_BUF_LEN(m) += SCTP_SIZE32(p_len); /* add HMAC_ALGO parameter */ - hmacs = (struct sctp_auth_hmac_algo *)(mtod(m, caddr_t)+m->m_len); + hmacs = (struct sctp_auth_hmac_algo *)(mtod(m, caddr_t)+SCTP_BUF_LEN(m)); p_len = sctp_serialize_hmaclist(inp->sctp_ep.local_hmacs, (uint8_t *) hmacs->hmac_ids); if (p_len > 0) { @@ -3752,10 +3745,10 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, hmacs->ph.param_length = htons(p_len); /* zero out any padding required */ bzero((caddr_t)hmacs + p_len, SCTP_SIZE32(p_len) - p_len); - m->m_len += SCTP_SIZE32(p_len); + SCTP_BUF_LEN(m) += SCTP_SIZE32(p_len); } /* add CHUNKS parameter */ - chunks = (struct sctp_auth_chunk_list *)(mtod(m, caddr_t)+m->m_len); + chunks = (struct sctp_auth_chunk_list *)(mtod(m, caddr_t)+SCTP_BUF_LEN(m)); p_len = sctp_serialize_auth_chunks(inp->sctp_ep.local_auth_chunks, chunks->chunk_types); if (p_len > 0) { @@ -3764,7 +3757,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, chunks->ph.param_length = htons(p_len); /* zero out any padding required */ bzero((caddr_t)chunks + p_len, SCTP_SIZE32(p_len) - p_len); - m->m_len += SCTP_SIZE32(p_len); + SCTP_BUF_LEN(m) += SCTP_SIZE32(p_len); } } m_at = m; @@ -3790,29 +3783,38 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, /* tack on the operational error if present */ if (op_err) { - if (op_err->m_pkthdr.len % 4) { + struct mbuf *ol; + int llen; + + llen = 0; + ol = op_err; + while (ol) { + llen += SCTP_BUF_LEN(ol); + ol = SCTP_BUF_NEXT(ol); + } + if (llen % 4) { /* must add a pad to the param */ uint32_t cpthis = 0; int padlen; - padlen = 4 - (op_err->m_pkthdr.len % 4); - m_copyback(op_err, op_err->m_pkthdr.len, padlen, (caddr_t)&cpthis); + padlen = 4 - (llen % 4); + m_copyback(op_err, llen, padlen, (caddr_t)&cpthis); } - while (m_at->m_next != NULL) { - m_at = m_at->m_next; + while (SCTP_BUF_NEXT(m_at) != NULL) { + m_at = SCTP_BUF_NEXT(m_at); } - m_at->m_next = op_err; - while (m_at->m_next != NULL) { - m_at = m_at->m_next; + SCTP_BUF_NEXT(m_at) = op_err; + while (SCTP_BUF_NEXT(m_at) != NULL) { + m_at = SCTP_BUF_NEXT(m_at); } } /* Get total size of init packet */ sz_of = SCTP_SIZE32(ntohs(init_chk->ch.chunk_length)); /* pre-calulate the size and update pkt header and chunk header */ - m->m_pkthdr.len = 0; - for (m_tmp = m; m_tmp; m_tmp = m_tmp->m_next) { - m->m_pkthdr.len += m_tmp->m_len; - if (m_tmp->m_next == NULL) { + p_len = 0; + for (m_tmp = m; m_tmp; m_tmp = SCTP_BUF_NEXT(m_tmp)) { + p_len += SCTP_BUF_LEN(m_tmp); + if (SCTP_BUF_NEXT(m_tmp) == NULL) { /* m_tmp should now point to last one */ break; } @@ -3829,10 +3831,10 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, */ /* add once for the INIT-ACK */ - sz_of += (m->m_pkthdr.len - sizeof(struct sctphdr)); + sz_of += (p_len - sizeof(struct sctphdr)); /* add a second time for the INIT-ACK in the cookie */ - sz_of += (m->m_pkthdr.len - sizeof(struct sctphdr)); + sz_of += (p_len - sizeof(struct sctphdr)); /* Now add the cookie header and cookie message struct */ sz_of += sizeof(struct sctp_state_cookie_param); @@ -3849,10 +3851,10 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, return; } /* Now append the cookie to the end and update the space/size */ - m_tmp->m_next = m_cookie; - for (; m_tmp; m_tmp = m_tmp->m_next) { - m->m_pkthdr.len += m_tmp->m_len; - if (m_tmp->m_next == NULL) { + SCTP_BUF_NEXT(m_tmp) = m_cookie; + for (; m_tmp; m_tmp = SCTP_BUF_NEXT(m_tmp)) { + p_len += SCTP_BUF_LEN(m_tmp); + if (SCTP_BUF_NEXT(m_tmp) == NULL) { /* m_tmp should now point to last one */ m_last = m_tmp; break; @@ -3863,7 +3865,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, * We pass 0 here to NOT set IP_DF if its IPv4, we ignore the return * here since the timer will drive a retranmission. */ - padval = m->m_pkthdr.len % 4; + padval = p_len % 4; if ((padval) && (m_last)) { /* see my previous comments on m_last */ int ret; @@ -3874,7 +3876,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, sctp_m_freem(m); return; } - m->m_pkthdr.len += padval; + p_len += padval; } sctp_lowlevel_chunk_output(inp, NULL, NULL, to, m, 0, NULL, 0, 0, NULL, 0); @@ -4187,23 +4189,16 @@ sctp_msg_append(struct sctp_tcb *stcb, sp->length = 0; at = m; sctp_set_prsctp_policy(stcb, sp); + /* + * We could in theory (for sendall) pass the length in, but we would + * still have to hunt through the chain since we need to setup the + * tail_mbuf + */ while (at) { - if (at->m_next == NULL) + if (SCTP_BUF_NEXT(at) == NULL) sp->tail_mbuf = at; - sp->length += at->m_len; - at = at->m_next; - } - if (sp->data->m_flags & M_PKTHDR) { - sp->data->m_pkthdr.len = sp->length; - } else { - /* Get an HDR in front please */ - at = sctp_get_mbuf_for_msg(1, 1, M_DONTWAIT, 1, MT_DATA); - if (at) { - at->m_pkthdr.len = sp->length; - at->m_len = 0; - at->m_next = sp->data; - sp->data = at; - } + sp->length += SCTP_BUF_LEN(at); + at = SCTP_BUF_NEXT(at); } SCTP_TCB_SEND_LOCK(stcb); sctp_snd_sb_alloc(stcb, sp->length); @@ -4258,14 +4253,14 @@ error_out: if (outchain == NULL) { /* This is the general case */ new_mbuf: - outchain = sctp_get_mbuf_for_msg(MCLBYTES, 1, M_DONTWAIT, 1, MT_HEADER); + outchain = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_DONTWAIT, 1, MT_HEADER); if (outchain == NULL) { goto error_out; } - outchain->m_len = 0; + SCTP_BUF_LEN(outchain) = 0; *endofchain = outchain; /* get the prepend space */ - outchain->m_data += (SCTP_FIRST_MBUF_RESV + 4); + SCTP_BUF_RESV_UF(outchain, (SCTP_FIRST_MBUF_RESV + 4)); } else { /* * We really should not get a NULL @@ -4274,11 +4269,11 @@ error_out: /* find end */ m = outchain; while (m) { - if (m->m_next == NULL) { + if (SCTP_BUF_NEXT(m) == NULL) { *endofchain = m; break; } - m = m->m_next; + m = SCTP_BUF_NEXT(m); } /* sanity */ if (*endofchain == NULL) { @@ -4297,52 +4292,36 @@ error_out: len = M_TRAILINGSPACE(*endofchain); } /* Find the end of the data, for appending */ - cp = (mtod((*endofchain), caddr_t)+(*endofchain)->m_len); + cp = (mtod((*endofchain), caddr_t)+SCTP_BUF_LEN((*endofchain))); /* Now lets copy it out */ if (len >= sizeofcpy) { /* It all fits, copy it in */ m_copydata(clonechain, 0, sizeofcpy, cp); - (*endofchain)->m_len += sizeofcpy; - if (outchain->m_flags & M_PKTHDR) - outchain->m_pkthdr.len += sizeofcpy; + SCTP_BUF_LEN((*endofchain)) += sizeofcpy; } else { /* fill up the end of the chain */ if (len > 0) { m_copydata(clonechain, 0, len, cp); - (*endofchain)->m_len += len; - if (outchain->m_flags & M_PKTHDR) - outchain->m_pkthdr.len += len; + SCTP_BUF_LEN((*endofchain)) += len; /* now we need another one */ sizeofcpy -= len; } - m = sctp_get_mbuf_for_msg(MCLBYTES, 1, M_DONTWAIT, 1, MT_HEADER); + m = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_DONTWAIT, 1, MT_HEADER); if (m == NULL) { /* We failed */ goto error_out; } - (*endofchain)->m_next = m; + SCTP_BUF_NEXT((*endofchain)) = m; *endofchain = m; cp = mtod((*endofchain), caddr_t); m_copydata(clonechain, len, sizeofcpy, cp); - (*endofchain)->m_len += sizeofcpy; - if (outchain->m_flags & M_PKTHDR) { - outchain->m_pkthdr.len += sizeofcpy; - } + SCTP_BUF_LEN((*endofchain)) += sizeofcpy; } return (outchain); } else { /* copy the old fashion way */ - /* - * Supposedly m_copypacket is an optimization, use - * it if we can - */ - if (clonechain->m_flags & M_PKTHDR) { - appendchain = m_copypacket(clonechain, M_DONTWAIT); - } else { - appendchain = m_copy(clonechain, 0, M_COPYALL); - } - + appendchain = m_copy(clonechain, 0, M_COPYALL); } } if (appendchain == NULL) { @@ -4351,79 +4330,41 @@ error_out: sctp_m_freem(outchain); return (NULL); } - /* if outchain is null, check our special reservation flag */ - if (outchain == NULL) { - /* - * need a lead mbuf in this one if we don't have space for: - * - E-net header (12+2+2) - IP header (20/40) - SCTP Common - * Header (12) - */ - if (M_LEADINGSPACE(appendchain) < (SCTP_FIRST_MBUF_RESV)) { - outchain = sctp_get_mbuf_for_msg(8, 1, M_DONTWAIT, 1, MT_HEADER); - if (outchain) { - /* - * if we don't hit here we have a problem - * anyway :o We reserve all the mbuf for - * prepends. - */ - outchain->m_pkthdr.len = 0; - outchain->m_len = 0; - outchain->m_next = NULL; - MH_ALIGN(outchain, 4); - *endofchain = outchain; - } - } - } if (outchain) { /* tack on to the end */ if (*endofchain != NULL) { - (*endofchain)->m_next = appendchain; + SCTP_BUF_NEXT(((*endofchain))) = appendchain; } else { m = outchain; while (m) { - if (m->m_next == NULL) { - m->m_next = appendchain; + if (SCTP_BUF_NEXT(m) == NULL) { + SCTP_BUF_NEXT(m) = appendchain; break; } - m = m->m_next; + m = SCTP_BUF_NEXT(m); } } - if (outchain->m_flags & M_PKTHDR) { - int append_tot; - - m = appendchain; - append_tot = 0; - while (m) { - append_tot += m->m_len; - if (m->m_next == NULL) { - *endofchain = m; - } - m = m->m_next; - } - outchain->m_pkthdr.len += append_tot; - } else { - /* - * save off the end and update the end-chain postion - */ - m = appendchain; - while (m) { - if (m->m_next == NULL) { - *endofchain = m; - break; - } - m = m->m_next; + /* + * save off the end and update the end-chain postion + */ + m = appendchain; + while (m) { + if (SCTP_BUF_NEXT(m) == NULL) { + *endofchain = m; + break; } + m = SCTP_BUF_NEXT(m); } return (outchain); } else { /* save off the end and update the end-chain postion */ m = appendchain; while (m) { - if (m->m_next == NULL) { + if (SCTP_BUF_NEXT(m) == NULL) { *endofchain = m; break; } - m = m->m_next; + m = SCTP_BUF_NEXT(m); } return (appendchain); } @@ -4457,7 +4398,7 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr, /* TSNH */ return; } - if ((ca->m) && (ca->m->m_pkthdr.len)) { + if ((ca->m) && ca->sndlen) { m = m_copym(ca->m, 0, M_COPYALL, M_DONTWAIT); if (m == NULL) { /* can't copy so we are done */ @@ -4473,11 +4414,11 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr, if (m) { struct sctp_paramhdr *ph; - M_PREPEND(m, sizeof(struct sctp_paramhdr), M_DONTWAIT); + SCTP_BUF_PREPEND(m, sizeof(struct sctp_paramhdr), M_DONTWAIT); if (m) { ph = mtod(m, struct sctp_paramhdr *); ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT); - ph->param_length = htons(m->m_pkthdr.len); + ph->param_length = htons(ca->sndlen); } /* * We add one here to keep the assoc from @@ -4635,7 +4576,7 @@ sctp_sendall_completes(void *ptr, uint32_t val) #define MC_ALIGN(m, len) do { \ - (m)->m_data += (MCLBYTES - (len)) & ~(sizeof(long) - 1); \ + SCTP_BUF_RESV_UF(m, ((MCLBYTES - (len)) & ~(sizeof(long) - 1)); \ } while (0) @@ -4646,14 +4587,13 @@ sctp_copy_out_all(struct uio *uio, int len) struct mbuf *ret, *at; int left, willcpy, cancpy, error; - ret = sctp_get_mbuf_for_msg(MCLBYTES, 1, M_WAIT, 1, MT_DATA); + ret = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_WAIT, 1, MT_DATA); if (ret == NULL) { /* TSNH */ return (NULL); } left = len; - ret->m_len = 0; - ret->m_pkthdr.len = len; + SCTP_BUF_LEN(ret) = 0; /* save space for the data chunk header */ cancpy = M_TRAILINGSPACE(ret); willcpy = min(cancpy, left); @@ -4666,16 +4606,16 @@ sctp_copy_out_all(struct uio *uio, int len) sctp_m_freem(at); return (NULL); } - at->m_len = willcpy; - at->m_nextpkt = at->m_next = 0; + SCTP_BUF_LEN(at) = willcpy; + SCTP_BUF_NEXT_PKT(at) = SCTP_BUF_NEXT(at) = 0; left -= willcpy; if (left > 0) { - at->m_next = sctp_get_mbuf_for_msg(left, 0, M_WAIT, 1, MT_DATA); - if (at->m_next == NULL) { + SCTP_BUF_NEXT(at) = sctp_get_mbuf_for_msg(left, 0, M_WAIT, 1, MT_DATA); + if (SCTP_BUF_NEXT(at) == NULL) { goto err_out_now; } - at = at->m_next; - at->m_len = 0; + at = SCTP_BUF_NEXT(at); + SCTP_BUF_LEN(at) = 0; cancpy = M_TRAILINGSPACE(at); willcpy = min(cancpy, left); } @@ -4710,32 +4650,18 @@ sctp_sendall(struct sctp_inpcb *inp, struct uio *uio, struct mbuf *m, ca->sndlen = uio->uio_resid; ca->m = sctp_copy_out_all(uio, ca->sndlen); if (ca->m == NULL) { - out_no_mem: SCTP_FREE(ca); return (ENOMEM); } } else { - if ((m->m_flags & M_PKTHDR) == 0) { - struct mbuf *mat; + /* Gather the length of the send */ + struct mbuf *mat; - mat = m; - ca->sndlen = 0; - while (m) { - ca->sndlen += m->m_len; - m = m->m_next; - } - mat = sctp_get_mbuf_for_msg(1, 1, M_WAIT, 1, MT_DATA); - if (mat) { - sctp_m_freem(m); - goto out_no_mem; - } - /* We MUST have a header on the front */ - mat->m_next = m; - mat->m_len = 0; - mat->m_pkthdr.len = ca->sndlen; - ca->m = mat; - } else { - ca->sndlen = m->m_pkthdr.len; + mat = m; + ca->sndlen = 0; + while (m) { + ca->sndlen += SCTP_BUF_LEN(m); + m = SCTP_BUF_NEXT(m); } ca->m = m; } @@ -5089,7 +5015,7 @@ out_gu: memset(chk, sizeof(*chk), 0); chk->rec.data.rcv_flags = rcv_flags; SCTP_TCB_SEND_LOCK(stcb); - if (sp->data->m_flags & M_EXT) { + if (SCTP_BUF_IS_EXTENDED(sp->data)) { chk->copy_by_ref = 1; } else { chk->copy_by_ref = 0; @@ -5116,9 +5042,9 @@ out_gu: m_adj(sp->data, to_move); /* Now lets work our way down and compact it */ m = sp->data; - while (m && (m->m_len == 0)) { - sp->data = m->m_next; - m->m_next = NULL; + while (m && (SCTP_BUF_LEN(m) == 0)) { + sp->data = SCTP_BUF_NEXT(m); + SCTP_BUF_NEXT(m) = NULL; if (sp->tail_mbuf == m) { /* freeing tail */ sp->tail_mbuf = sp->data; @@ -5133,19 +5059,14 @@ out_gu: sp->length -= to_move; } - /* Update the new length in */ - if (sp->data && (sp->data->m_flags & M_PKTHDR)) { - /* update length */ - sp->data->m_pkthdr.len = sp->length; - } if (M_LEADINGSPACE(chk->data) < sizeof(struct sctp_data_chunk)) { /* Not enough room for a chunk header, get some */ struct mbuf *m; - m = sctp_get_mbuf_for_msg(1, 1, M_DONTWAIT, 0, MT_DATA); + m = sctp_get_mbuf_for_msg(1, 0, M_DONTWAIT, 0, MT_DATA); if (m == NULL) { /* - * we're in trouble here. M_PREPEND below will free + * we're in trouble here. _PREPEND below will free * all the data if there is no leading space, so we * must put the data back and restore. */ @@ -5159,25 +5080,21 @@ out_gu: /* reassemble the data */ m = sp->data; sp->data = chk->data; - sp->data->m_next = m; + SCTP_BUF_NEXT(sp->data) = m; } sp->some_taken = some_taken; sp->length += to_move; - if (sp->data && (sp->data->m_flags & M_PKTHDR)) { - sp->data->m_pkthdr.len = sp->length; - } sctp_free_a_chunk(stcb, chk); SCTP_TCB_SEND_UNLOCK(stcb); goto out_gu; } else { - m->m_len = 0; - m->m_next = chk->data; + SCTP_BUF_LEN(m) = 0; + SCTP_BUF_NEXT(m) = chk->data; chk->data = m; - chk->data->m_pkthdr.len = to_move; - MH_ALIGN(chk->data, 4); + M_ALIGN(chk->data, 4); } } - M_PREPEND(chk->data, sizeof(struct sctp_data_chunk), M_DONTWAIT); + SCTP_BUF_PREPEND(chk->data, sizeof(struct sctp_data_chunk), M_DONTWAIT); if (chk->data == NULL) { /* HELP */ sctp_free_a_chunk(stcb, chk); @@ -5195,8 +5112,8 @@ out_gu: */ if (chk->last_mbuf == NULL) { chk->last_mbuf = chk->data; - while (chk->last_mbuf->m_next != NULL) { - chk->last_mbuf = chk->last_mbuf->m_next; + while (SCTP_BUF_NEXT(chk->last_mbuf) != NULL) { + chk->last_mbuf = SCTP_BUF_NEXT(chk->last_mbuf); } } chk->flags = 0; @@ -5247,13 +5164,10 @@ out_gu: if (sctp_pad_lastmbuf(chk->data, pads, chk->last_mbuf) == 0) { chk->pad_inplace = 1; } - if ((lm = chk->last_mbuf->m_next) != NULL) { + if ((lm = SCTP_BUF_NEXT(chk->last_mbuf)) != NULL) { /* pad added an mbuf */ chk->last_mbuf = lm; } - if (chk->data->m_flags & M_PKTHDR) { - chk->data->m_pkthdr.len += pads; - } chk->send_size += pads; } /* We only re-set the policy if it is on */ @@ -5695,15 +5609,6 @@ again_one_more_time: if (chk->data == NULL) { continue; } - if ((chk->data->m_flags & M_PKTHDR) == 0) { - /* - * NOTE: the chk queue MUST have the PKTHDR - * flag set on it with a total in the - * m_pkthdr.len field!! else the chunk will - * ALWAYS be skipped - */ - continue; - } if (chk->sent != SCTP_DATAGRAM_UNSENT) { /* * It must be unsent. Cookies and ASCONF's @@ -5727,7 +5632,7 @@ again_one_more_time: } else omtu = 0; /* Here we do NOT factor the r_mtu */ - if ((chk->data->m_pkthdr.len < (int)(mtu - omtu)) || + if ((chk->send_size < (int)(mtu - omtu)) || (chk->flags & CHUNK_FLAGS_FRAGMENT_OK)) { /* * We probably should glom the mbuf chain @@ -5756,18 +5661,18 @@ again_one_more_time: } outchain = sctp_copy_mbufchain(chk->data, outchain, &endoutchain, (int)chk->rec.chunk_id.can_take_data, - chk->data->m_pkthdr.len, chk->copy_by_ref); + chk->send_size, chk->copy_by_ref); if (outchain == NULL) { *reason_code = 8; return (ENOMEM); } SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks); /* update our MTU size */ - if (mtu > (chk->data->m_pkthdr.len + omtu)) - mtu -= (chk->data->m_pkthdr.len + omtu); + if (mtu > (chk->send_size + omtu)) + mtu -= (chk->send_size + omtu); else mtu = 0; - to_out += (chk->data->m_pkthdr.len + omtu); + to_out += (chk->send_size + omtu); /* Do clear IP_DF ? */ if (chk->flags & CHUNK_FLAGS_FRAGMENT_OK) { no_fragmentflg = 0; @@ -5791,7 +5696,7 @@ again_one_more_time: /* remove these chunks at the end */ if (chk->rec.chunk_id.id == SCTP_SELECTIVE_ACK) { /* turn off the timer */ - if (callout_pending(&stcb->asoc.dack_timer.timer)) { + if (SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) { sctp_timer_stop(SCTP_TIMER_TYPE_RECV, inp, stcb, net, SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_1); } @@ -5834,7 +5739,7 @@ again_one_more_time: sctp_timer_start(SCTP_TIMER_TYPE_COOKIE, inp, stcb, net); cookie = 0; } - M_PREPEND(outchain, sizeof(struct sctphdr), M_DONTWAIT); + SCTP_BUF_PREPEND(outchain, sizeof(struct sctphdr), M_DONTWAIT); if (outchain == NULL) { /* no memory */ error = ENOBUFS; @@ -6006,7 +5911,7 @@ again_one_more_time: printf("No memory?\n"); } #endif - if (!callout_pending(&net->rxt_timer.timer)) { + if (!SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) { sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, net); } *reason_code = 3; @@ -6076,7 +5981,7 @@ again_one_more_time: cookie = 0; } /* must start a send timer if data is being sent */ - if (bundle_at && (!callout_pending(&net->rxt_timer.timer))) { + if (bundle_at && (!SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer))) { /* * no timer running on this destination * restart it. @@ -6084,7 +5989,7 @@ again_one_more_time: sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, net); } /* Now send it, if there is anything to send :> */ - M_PREPEND(outchain, sizeof(struct sctphdr), M_DONTWAIT); + SCTP_BUF_PREPEND(outchain, sizeof(struct sctphdr), M_DONTWAIT); if (outchain == NULL) { /* out of mbufs */ error = ENOBUFS; @@ -6173,7 +6078,7 @@ again_one_more_time: if (sctp_early_fr) { if (net->flight_size < net->cwnd) { /* start or restart it */ - if (callout_pending(&net->fr_timer.timer)) { + if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) { sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, inp, stcb, net, SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_2); } @@ -6181,7 +6086,7 @@ again_one_more_time: sctp_timer_start(SCTP_TIMER_TYPE_EARLYFR, inp, stcb, net); } else { /* stop it if its running */ - if (callout_pending(&net->fr_timer.timer)) { + if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) { SCTP_STAT_INCR(sctps_earlyfrstpout); sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, inp, stcb, net, SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_3); @@ -6237,7 +6142,7 @@ sctp_queue_op_err(struct sctp_tcb *stcb, struct mbuf *op_err) return; } chk->copy_by_ref = 0; - M_PREPEND(op_err, sizeof(struct sctp_chunkhdr), M_DONTWAIT); + SCTP_BUF_PREPEND(op_err, sizeof(struct sctp_chunkhdr), M_DONTWAIT); if (op_err == NULL) { sctp_free_a_chunk(stcb, chk); return; @@ -6245,8 +6150,8 @@ sctp_queue_op_err(struct sctp_tcb *stcb, struct mbuf *op_err) chk->send_size = 0; mat = op_err; while (mat != NULL) { - chk->send_size += mat->m_len; - mat = mat->m_next; + chk->send_size += SCTP_BUF_LEN(mat); + mat = SCTP_BUF_NEXT(mat); } chk->rec.chunk_id.id = SCTP_OPERATION_ERROR; chk->rec.chunk_id.can_take_data = 1; @@ -6278,7 +6183,7 @@ sctp_send_cookie_echo(struct mbuf *m, * queue. */ int at; - struct mbuf *cookie, *mat; + struct mbuf *cookie; struct sctp_paramhdr parm, *phdr; struct sctp_chunkhdr *hdr; struct sctp_tmit_chunk *chk; @@ -6322,20 +6227,6 @@ sctp_send_cookie_echo(struct mbuf *m, hdr = mtod(cookie, struct sctp_chunkhdr *); hdr->chunk_type = SCTP_COOKIE_ECHO; hdr->chunk_flags = 0; - /* now we MUST have a PKTHDR on it */ - if ((cookie->m_flags & M_PKTHDR) != M_PKTHDR) { - /* we hope this happens rarely */ - mat = sctp_get_mbuf_for_msg(8, 1, M_DONTWAIT, 1, MT_HEADER); - if (mat == NULL) { - sctp_m_freem(cookie); - return (-4); - } - mat->m_len = 0; - mat->m_pkthdr.rcvif = 0; - mat->m_next = cookie; - cookie = mat; - } - cookie->m_pkthdr.len = plen; /* get the chunk stuff now and place it in the FRONT of the queue */ sctp_alloc_a_chunk(stcb, chk); if (chk == NULL) { @@ -6344,7 +6235,7 @@ sctp_send_cookie_echo(struct mbuf *m, return (-5); } chk->copy_by_ref = 0; - chk->send_size = cookie->m_pkthdr.len; + chk->send_size = plen; chk->rec.chunk_id.id = SCTP_COOKIE_ECHO; chk->rec.chunk_id.can_take_data = 0; chk->sent = SCTP_DATAGRAM_UNSENT; @@ -6386,28 +6277,13 @@ sctp_send_heartbeat_ack(struct sctp_tcb *stcb, chdr = mtod(outchain, struct sctp_chunkhdr *); chdr->chunk_type = SCTP_HEARTBEAT_ACK; chdr->chunk_flags = 0; - if ((outchain->m_flags & M_PKTHDR) != M_PKTHDR) { - /* should not happen but we are cautious. */ - struct mbuf *tmp; - - tmp = sctp_get_mbuf_for_msg(1, 1, M_DONTWAIT, 1, MT_HEADER); - if (tmp == NULL) { - return; - } - tmp->m_len = 0; - tmp->m_pkthdr.rcvif = 0; - tmp->m_next = outchain; - outchain = tmp; - } - outchain->m_pkthdr.len = chk_length; if (chk_length % 4) { /* need pad */ uint32_t cpthis = 0; int padlen; - padlen = 4 - (outchain->m_pkthdr.len % 4); - m_copyback(outchain, outchain->m_pkthdr.len, padlen, - (caddr_t)&cpthis); + padlen = 4 - (chk_length % 4); + m_copyback(outchain, chk_length, padlen, (caddr_t)&cpthis); } sctp_alloc_a_chunk(stcb, chk); if (chk == NULL) { @@ -6441,12 +6317,12 @@ sctp_send_cookie_ack(struct sctp_tcb *stcb) cookie_ack = NULL; SCTP_TCB_LOCK_ASSERT(stcb); - cookie_ack = sctp_get_mbuf_for_msg(sizeof(struct sctp_chunkhdr), 1, M_DONTWAIT, 1, MT_HEADER); + cookie_ack = sctp_get_mbuf_for_msg(sizeof(struct sctp_chunkhdr), 0, M_DONTWAIT, 1, MT_HEADER); if (cookie_ack == NULL) { /* no mbuf's */ return (-1); } - cookie_ack->m_data += SCTP_MIN_OVERHEAD; + SCTP_BUF_RESV_UF(cookie_ack, SCTP_MIN_OVERHEAD); sctp_alloc_a_chunk(stcb, chk); if (chk == NULL) { /* no memory */ @@ -6472,8 +6348,7 @@ sctp_send_cookie_ack(struct sctp_tcb *stcb) hdr->chunk_type = SCTP_COOKIE_ACK; hdr->chunk_flags = 0; hdr->chunk_length = htons(chk->send_size); - cookie_ack->m_pkthdr.len = cookie_ack->m_len = chk->send_size; - cookie_ack->m_pkthdr.rcvif = 0; + SCTP_BUF_LEN(cookie_ack) = chk->send_size; TAILQ_INSERT_TAIL(&chk->asoc->control_send_queue, chk, sctp_next); chk->asoc->ctrl_queue_cnt++; return (0); @@ -6488,12 +6363,12 @@ sctp_send_shutdown_ack(struct sctp_tcb *stcb, struct sctp_nets *net) struct sctp_shutdown_ack_chunk *ack_cp; struct sctp_tmit_chunk *chk; - m_shutdown_ack = sctp_get_mbuf_for_msg(sizeof(struct sctp_shutdown_ack_chunk), 1, M_DONTWAIT, 1, MT_HEADER); + m_shutdown_ack = sctp_get_mbuf_for_msg(sizeof(struct sctp_shutdown_ack_chunk), 0, M_DONTWAIT, 1, MT_HEADER); if (m_shutdown_ack == NULL) { /* no mbuf's */ return (-1); } - m_shutdown_ack->m_data += SCTP_MIN_OVERHEAD; + SCTP_BUF_RESV_UF(m_shutdown_ack, SCTP_MIN_OVERHEAD); sctp_alloc_a_chunk(stcb, chk); if (chk == NULL) { /* no memory */ @@ -6517,8 +6392,7 @@ sctp_send_shutdown_ack(struct sctp_tcb *stcb, struct sctp_nets *net) ack_cp->ch.chunk_type = SCTP_SHUTDOWN_ACK; ack_cp->ch.chunk_flags = 0; ack_cp->ch.chunk_length = htons(chk->send_size); - m_shutdown_ack->m_pkthdr.len = m_shutdown_ack->m_len = chk->send_size; - m_shutdown_ack->m_pkthdr.rcvif = 0; + SCTP_BUF_LEN(m_shutdown_ack) = chk->send_size; TAILQ_INSERT_TAIL(&chk->asoc->control_send_queue, chk, sctp_next); chk->asoc->ctrl_queue_cnt++; return (0); @@ -6532,12 +6406,12 @@ sctp_send_shutdown(struct sctp_tcb *stcb, struct sctp_nets *net) struct sctp_shutdown_chunk *shutdown_cp; struct sctp_tmit_chunk *chk; - m_shutdown = sctp_get_mbuf_for_msg(sizeof(struct sctp_shutdown_chunk), 1, M_DONTWAIT, 1, MT_HEADER); + m_shutdown = sctp_get_mbuf_for_msg(sizeof(struct sctp_shutdown_chunk), 0, M_DONTWAIT, 1, MT_HEADER); if (m_shutdown == NULL) { /* no mbuf's */ return (-1); } - m_shutdown->m_data += SCTP_MIN_OVERHEAD; + SCTP_BUF_RESV_UF(m_shutdown, SCTP_MIN_OVERHEAD); sctp_alloc_a_chunk(stcb, chk); if (chk == NULL) { /* no memory */ @@ -6561,8 +6435,7 @@ sctp_send_shutdown(struct sctp_tcb *stcb, struct sctp_nets *net) shutdown_cp->ch.chunk_flags = 0; shutdown_cp->ch.chunk_length = htons(chk->send_size); shutdown_cp->cumulative_tsn_ack = htonl(stcb->asoc.cumulative_tsn); - m_shutdown->m_pkthdr.len = m_shutdown->m_len = chk->send_size; - m_shutdown->m_pkthdr.rcvif = 0; + SCTP_BUF_LEN(m_shutdown) = chk->send_size; TAILQ_INSERT_TAIL(&chk->asoc->control_send_queue, chk, sctp_next); chk->asoc->ctrl_queue_cnt++; return (0); @@ -6578,11 +6451,12 @@ sctp_send_asconf(struct sctp_tcb *stcb, struct sctp_nets *net) struct sctp_tmit_chunk *chk; struct mbuf *m_asconf; struct sctp_asconf_chunk *acp; + int len; SCTP_TCB_LOCK_ASSERT(stcb); /* compose an ASCONF chunk, maximum length is PMTU */ - m_asconf = sctp_compose_asconf(stcb); + m_asconf = sctp_compose_asconf(stcb, &len); if (m_asconf == NULL) { return (-1); } @@ -6595,7 +6469,7 @@ sctp_send_asconf(struct sctp_tcb *stcb, struct sctp_nets *net) } chk->copy_by_ref = 0; chk->data = m_asconf; - chk->send_size = m_asconf->m_pkthdr.len; + chk->send_size = len; chk->rec.chunk_id.id = SCTP_ASCONF; chk->rec.chunk_id.can_take_data = 0; chk->sent = SCTP_DATAGRAM_UNSENT; @@ -6617,7 +6491,7 @@ sctp_send_asconf_ack(struct sctp_tcb *stcb, uint32_t retrans) * must be stored in the tcb */ struct sctp_tmit_chunk *chk; - struct mbuf *m_ack; + struct mbuf *m_ack, *m; SCTP_TCB_LOCK_ASSERT(stcb); /* is there a asconf-ack mbuf chain to send? */ @@ -6625,14 +6499,8 @@ sctp_send_asconf_ack(struct sctp_tcb *stcb, uint32_t retrans) return (-1); } /* copy the asconf_ack */ - /* - * Supposedly the m_copypacket is a optimzation, use it if we can. - */ - if (stcb->asoc.last_asconf_ack_sent->m_flags & M_PKTHDR) { - m_ack = m_copypacket(stcb->asoc.last_asconf_ack_sent, M_DONTWAIT); - } else - m_ack = m_copy(stcb->asoc.last_asconf_ack_sent, 0, M_COPYALL); - + /* We no longer have pak headers here so m_copy is it */ + m_ack = m_copy(stcb->asoc.last_asconf_ack_sent, 0, M_COPYALL); if (m_ack == NULL) { /* couldn't copy it */ @@ -6674,7 +6542,13 @@ sctp_send_asconf_ack(struct sctp_tcb *stcb, uint32_t retrans) stcb->asoc.used_alt_asconfack = 0; } chk->data = m_ack; - chk->send_size = m_ack->m_pkthdr.len; + chk->send_size = 0; + /* Get size */ + m = m_ack; + while (m) { + chk->send_size += SCTP_BUF_LEN(m); + m = SCTP_BUF_NEXT(m); + } chk->rec.chunk_id.id = SCTP_ASCONF_ACK; chk->rec.chunk_id.can_take_data = 1; chk->sent = SCTP_DATAGRAM_UNSENT; @@ -6790,7 +6664,7 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp, } else if (chk->rec.chunk_id.id == SCTP_ASCONF) sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, inp, stcb, chk->whoTo); - M_PREPEND(m, sizeof(struct sctphdr), M_DONTWAIT); + SCTP_BUF_PREPEND(m, sizeof(struct sctphdr), M_DONTWAIT); if (m == NULL) { return (ENOBUFS); } @@ -7003,7 +6877,7 @@ one_chunk_around: * No matter if we fail/or suceed we should start a * timer. A failure is like a lost IP packet :-) */ - if (!callout_pending(&net->rxt_timer.timer)) { + if (!SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) { /* * no timer running on this destination * restart it. @@ -7011,7 +6885,7 @@ one_chunk_around: sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, net); tmr_started = 1; } - M_PREPEND(m, sizeof(struct sctphdr), M_DONTWAIT); + SCTP_BUF_PREPEND(m, sizeof(struct sctphdr), M_DONTWAIT); if (m == NULL) { return (ENOBUFS); } @@ -7159,7 +7033,7 @@ sctp_timer_validation(struct sctp_inpcb *inp, /* Validate that a timer is running somewhere */ TAILQ_FOREACH(net, &asoc->nets, sctp_next) { - if (callout_pending(&net->rxt_timer.timer)) { + if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) { /* Here is a timer */ return (ret); } @@ -7223,9 +7097,9 @@ sctp_chunk_output(struct sctp_inpcb *inp, * Do we have something to send, data or control AND a sack timer * running, if so piggy-back the sack. */ - if (callout_pending(&stcb->asoc.dack_timer.timer)) { + if (SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) { sctp_send_sack(stcb); - callout_stop(&stcb->asoc.dack_timer.timer); + SCTP_OS_TIMER_STOP(&stcb->asoc.dack_timer.timer); } while (asoc->sent_queue_retran_cnt) { /* @@ -7491,13 +7365,13 @@ send_forward_tsn(struct sctp_tcb *stcb, chk->rec.chunk_id.id = SCTP_FORWARD_CUM_TSN; chk->rec.chunk_id.can_take_data = 0; chk->asoc = asoc; - chk->data = sctp_get_mbuf_for_msg(MCLBYTES, 1, M_DONTWAIT, 1, MT_DATA); + chk->data = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_DONTWAIT, 1, MT_DATA); if (chk->data == NULL) { atomic_subtract_int(&chk->whoTo->ref_count, 1); sctp_free_a_chunk(stcb, chk); return; } - chk->data->m_data += SCTP_MIN_OVERHEAD; + SCTP_BUF_RESV_UF(chk->data, SCTP_MIN_OVERHEAD); chk->sent = SCTP_DATAGRAM_UNSENT; chk->snd_count = 0; chk->whoTo = asoc->primary_destination; @@ -7509,7 +7383,7 @@ sctp_fill_in_rest: * Here we go through and fill out the part that deals with * stream/seq of the ones we skip. */ - chk->data->m_pkthdr.len = chk->data->m_len = 0; + SCTP_BUF_LEN(chk->data) = 0; { struct sctp_tmit_chunk *at, *tp1, *last; struct sctp_strseq *strseq; @@ -7576,7 +7450,7 @@ sctp_fill_in_rest: fwdtsn->new_cumulative_tsn = htonl(asoc->advanced_peer_ack_point); chk->send_size = (sizeof(struct sctp_forward_tsn_chunk) + (cnt_of_skipped * sizeof(struct sctp_strseq))); - chk->data->m_pkthdr.len = chk->data->m_len = chk->send_size; + SCTP_BUF_LEN(chk->data) = chk->send_size; fwdtsn++; /* * Move pointer to after the fwdtsn and transfer to the @@ -7722,7 +7596,7 @@ sctp_send_sack(struct sctp_tcb *stcb) space_req = MCLBYTES; } /* Ok now lets formulate a MBUF with our sack */ - a_chk->data = sctp_get_mbuf_for_msg(space_req, 1, M_DONTWAIT, 1, MT_DATA); + a_chk->data = sctp_get_mbuf_for_msg(space_req, 0, M_DONTWAIT, 1, MT_DATA); if ((a_chk->data == NULL) || (a_chk->whoTo == NULL)) { /* rats, no mbuf memory */ @@ -7741,7 +7615,7 @@ sctp_send_sack(struct sctp_tcb *stcb) return; } /* ok, lets go through and fill it in */ - a_chk->data->m_data += SCTP_MIN_OVERHEAD; + SCTP_BUF_RESV_UF(a_chk->data, SCTP_MIN_OVERHEAD); space = M_TRAILINGSPACE(a_chk->data); if (space > (a_chk->whoTo->mtu - SCTP_MIN_OVERHEAD)) { space = (a_chk->whoTo->mtu - SCTP_MIN_OVERHEAD); @@ -7860,7 +7734,7 @@ sctp_send_sack(struct sctp_tcb *stcb) a_chk->send_size = (sizeof(struct sctp_sack_chunk) + (num_gap_blocks * sizeof(struct sctp_gap_ack_block)) + (num_dups * sizeof(int32_t))); - a_chk->data->m_pkthdr.len = a_chk->data->m_len = a_chk->send_size; + SCTP_BUF_LEN(a_chk->data) = a_chk->send_size; sack->sack.num_gap_ack_blks = htons(num_gap_blocks); sack->sack.num_dup_tsns = htons(num_dups); sack->ch.chunk_length = htons(a_chk->send_size); @@ -7892,7 +7766,7 @@ sctp_send_abort_tcb(struct sctp_tcb *stcb, struct mbuf *operr) stcb, SCTP_ABORT_ASSOCIATION); } SCTP_TCB_LOCK_ASSERT(stcb); - m_abort = sctp_get_mbuf_for_msg(sizeof(struct sctp_abort_chunk), 1, M_DONTWAIT, 1, MT_HEADER); + m_abort = sctp_get_mbuf_for_msg(sizeof(struct sctp_abort_chunk), 0, M_DONTWAIT, 1, MT_HEADER); if (m_abort == NULL) { /* no mbuf's */ if (m_out) @@ -7900,28 +7774,25 @@ sctp_send_abort_tcb(struct sctp_tcb *stcb, struct mbuf *operr) return; } /* link in any error */ - m_abort->m_next = operr; + SCTP_BUF_NEXT(m_abort) = operr; sz = 0; if (operr) { struct mbuf *n; n = operr; while (n) { - sz += n->m_len; - n = n->m_next; + sz += SCTP_BUF_LEN(n); + n = SCTP_BUF_NEXT(n); } } - m_abort->m_len = sizeof(*abort); - m_abort->m_pkthdr.len = m_abort->m_len + sz; - m_abort->m_pkthdr.rcvif = 0; + SCTP_BUF_LEN(m_abort) = sizeof(*abort); if (m_out == NULL) { /* NO Auth chunk prepended, so reserve space in front */ - m_abort->m_data += SCTP_MIN_OVERHEAD; + SCTP_BUF_RESV_UF(m_abort, SCTP_MIN_OVERHEAD); m_out = m_abort; } else { /* Put AUTH chunk at the front of the chain */ - m_out->m_pkthdr.len += m_abort->m_pkthdr.len; - m_end->m_next = m_abort; + SCTP_BUF_NEXT(m_end) = m_abort; } /* fill in the ABORT chunk */ @@ -7931,7 +7802,7 @@ sctp_send_abort_tcb(struct sctp_tcb *stcb, struct mbuf *operr) abort->ch.chunk_length = htons(sizeof(*abort) + sz); /* prepend and fill in the SCTP header */ - M_PREPEND(m_out, sizeof(struct sctphdr), M_DONTWAIT); + SCTP_BUF_PREPEND(m_out, sizeof(struct sctphdr), M_DONTWAIT); if (m_out == NULL) { /* TSNH: no memory */ return; @@ -7958,12 +7829,11 @@ sctp_send_shutdown_complete(struct sctp_tcb *stcb, struct mbuf *m_shutdown_comp; struct sctp_shutdown_complete_msg *comp_cp; - m_shutdown_comp = sctp_get_mbuf_for_msg(sizeof(struct sctp_shutdown_complete_msg), 1, M_DONTWAIT, 1, MT_HEADER); + m_shutdown_comp = sctp_get_mbuf_for_msg(sizeof(struct sctp_shutdown_complete_msg), 0, M_DONTWAIT, 1, MT_HEADER); if (m_shutdown_comp == NULL) { /* no mbuf's */ return (-1); } - m_shutdown_comp->m_data += sizeof(struct ip6_hdr); comp_cp = mtod(m_shutdown_comp, struct sctp_shutdown_complete_msg *); comp_cp->shut_cmp.ch.chunk_type = SCTP_SHUTDOWN_COMPLETE; comp_cp->shut_cmp.ch.chunk_flags = 0; @@ -7973,8 +7843,7 @@ sctp_send_shutdown_complete(struct sctp_tcb *stcb, comp_cp->sh.v_tag = htonl(stcb->asoc.peer_vtag); comp_cp->sh.checksum = 0; - m_shutdown_comp->m_pkthdr.len = m_shutdown_comp->m_len = sizeof(struct sctp_shutdown_complete_msg); - m_shutdown_comp->m_pkthdr.rcvif = 0; + SCTP_BUF_LEN(m_shutdown_comp) = sizeof(struct sctp_shutdown_complete_msg); sctp_lowlevel_chunk_output(stcb->sctp_ep, stcb, net, (struct sockaddr *)&net->ro._l_addr, m_shutdown_comp, 0, NULL, 1, 0, NULL, 0); @@ -7986,25 +7855,30 @@ int sctp_send_shutdown_complete2(struct mbuf *m, int iphlen, struct sctphdr *sh) { /* formulate and SEND a SHUTDOWN-COMPLETE */ + struct mbuf *o_pak; struct mbuf *mout; struct ip *iph, *iph_out; struct ip6_hdr *ip6, *ip6_out; - int offset_out; + int offset_out, len; struct sctp_shutdown_complete_msg *comp_cp; - mout = sctp_get_mbuf_for_msg(sizeof(struct sctp_shutdown_complete_msg), 1, M_DONTWAIT, 1, MT_HEADER); - if (mout == NULL) { + /* Get room for the largest message */ + len = (sizeof(struct ip6_hdr) + sizeof(struct sctp_shutdown_complete_msg)); + + o_pak = SCTP_GET_HEADER_FOR_OUTPUT(len); + if (o_pak == NULL) { /* no mbuf's */ return (-1); } + mout = SCTP_HEADER_TO_CHAIN(o_pak); iph = mtod(m, struct ip *); iph_out = NULL; ip6_out = NULL; offset_out = 0; if (iph->ip_v == IPVERSION) { - mout->m_len = sizeof(struct ip) + + SCTP_BUF_LEN(mout) = sizeof(struct ip) + sizeof(struct sctp_shutdown_complete_msg); - mout->m_next = NULL; + SCTP_BUF_NEXT(mout) = NULL; iph_out = mtod(mout, struct ip *); /* Fill in the IP header for the ABORT */ @@ -8025,9 +7899,9 @@ sctp_send_shutdown_complete2(struct mbuf *m, int iphlen, struct sctphdr *sh) (caddr_t)iph_out + offset_out); } else if (iph->ip_v == (IPV6_VERSION >> 4)) { ip6 = (struct ip6_hdr *)iph; - mout->m_len = sizeof(struct ip6_hdr) + + SCTP_BUF_LEN(mout) = sizeof(struct ip6_hdr) + sizeof(struct sctp_shutdown_complete_msg); - mout->m_next = NULL; + SCTP_BUF_NEXT(mout) = NULL; ip6_out = mtod(mout, struct ip6_hdr *); /* Fill in the IPv6 header for the ABORT */ @@ -8036,7 +7910,11 @@ sctp_send_shutdown_complete2(struct mbuf *m, int iphlen, struct sctphdr *sh) ip6_out->ip6_nxt = IPPROTO_SCTP; ip6_out->ip6_src = ip6->ip6_dst; ip6_out->ip6_dst = ip6->ip6_src; - ip6_out->ip6_plen = mout->m_len; + /* + * ?? The old code had both the iph len + payload, I think + * this is wrong and would never have worked + */ + ip6_out->ip6_plen = sizeof(struct sctp_shutdown_complete_msg); offset_out += sizeof(*ip6_out); comp_cp = (struct sctp_shutdown_complete_msg *)( (caddr_t)ip6_out + offset_out); @@ -8045,6 +7923,7 @@ sctp_send_shutdown_complete2(struct mbuf *m, int iphlen, struct sctphdr *sh) return (-1); } + SCTP_HEADER_LEN(o_pak) = SCTP_BUF_LEN(mout); /* Now copy in and fill in the ABORT tags etc. */ comp_cp->sh.src_port = sh->dest_port; comp_cp->sh.dest_port = sh->src_port; @@ -8054,27 +7933,20 @@ sctp_send_shutdown_complete2(struct mbuf *m, int iphlen, struct sctphdr *sh) comp_cp->shut_cmp.ch.chunk_type = SCTP_SHUTDOWN_COMPLETE; comp_cp->shut_cmp.ch.chunk_length = htons(sizeof(struct sctp_shutdown_complete_chunk)); - mout->m_pkthdr.len = mout->m_len; /* add checksum */ - if ((sctp_no_csum_on_loopback) && - (m->m_pkthdr.rcvif) && - (m->m_pkthdr.rcvif->if_type == IFT_LOOP)) { + if ((sctp_no_csum_on_loopback) && SCTP_IS_IT_LOOPBACK(o_pak)) { comp_cp->sh.checksum = 0; } else { comp_cp->sh.checksum = sctp_calculate_sum(mout, NULL, offset_out); } - - /* zap the rcvif, it should be null */ - mout->m_pkthdr.rcvif = 0; - /* zap the stack pointer to the route */ if (iph_out != NULL) { struct route ro; bzero(&ro, sizeof ro); /* set IPv4 length */ - iph_out->ip_len = mout->m_pkthdr.len; + iph_out->ip_len = SCTP_HEADER_LEN(o_pak); /* out it goes */ - ip_output(mout, 0, &ro, IP_RAWOUTPUT, NULL + ip_output(o_pak, 0, &ro, IP_RAWOUTPUT, NULL ,NULL ); /* Free the route if we got one back */ @@ -8085,7 +7957,7 @@ sctp_send_shutdown_complete2(struct mbuf *m, int iphlen, struct sctphdr *sh) bzero(&ro, sizeof(ro)); - ip6_output(mout, NULL, &ro, 0, NULL, NULL + ip6_output(o_pak, NULL, &ro, 0, NULL, NULL ,NULL ); /* Free the route if we got one back */ @@ -8233,13 +8105,13 @@ sctp_send_hb(struct sctp_tcb *stcb, int user_req, struct sctp_nets *u_net) chk->asoc = &stcb->asoc; chk->send_size = sizeof(struct sctp_heartbeat_chunk); - chk->data = sctp_get_mbuf_for_msg(chk->send_size, 1, M_DONTWAIT, 1, MT_HEADER); + chk->data = sctp_get_mbuf_for_msg(chk->send_size, 0, M_DONTWAIT, 1, MT_HEADER); if (chk->data == NULL) { sctp_free_a_chunk(stcb, chk); return (0); } - chk->data->m_data += SCTP_MIN_OVERHEAD; - chk->data->m_pkthdr.len = chk->data->m_len = chk->send_size; + SCTP_BUF_RESV_UF(chk->data, SCTP_MIN_OVERHEAD); + SCTP_BUF_LEN(chk->data) = chk->send_size; chk->sent = SCTP_DATAGRAM_UNSENT; chk->snd_count = 0; chk->whoTo = net; @@ -8342,13 +8214,13 @@ sctp_send_ecn_echo(struct sctp_tcb *stcb, struct sctp_nets *net, chk->rec.chunk_id.can_take_data = 0; chk->asoc = &stcb->asoc; chk->send_size = sizeof(struct sctp_ecne_chunk); - chk->data = sctp_get_mbuf_for_msg(chk->send_size, 1, M_DONTWAIT, 1, MT_HEADER); + chk->data = sctp_get_mbuf_for_msg(chk->send_size, 0, M_DONTWAIT, 1, MT_HEADER); if (chk->data == NULL) { sctp_free_a_chunk(stcb, chk); return; } - chk->data->m_data += SCTP_MIN_OVERHEAD; - chk->data->m_pkthdr.len = chk->data->m_len = chk->send_size; + SCTP_BUF_RESV_UF(chk->data, SCTP_MIN_OVERHEAD); + SCTP_BUF_LEN(chk->data) = chk->send_size; chk->sent = SCTP_DATAGRAM_UNSENT; chk->snd_count = 0; chk->whoTo = net; @@ -8407,18 +8279,14 @@ sctp_send_packet_dropped(struct sctp_tcb *stcb, struct sctp_nets *net, ip6h = mtod(m, struct ip6_hdr *); len = chk->send_size = htons(ip6h->ip6_plen); } - if ((len + iphlen) > m->m_pkthdr.len) { - /* huh */ - chk->send_size = len = m->m_pkthdr.len - iphlen; - } chk->asoc = &stcb->asoc; - chk->data = sctp_get_mbuf_for_msg(MCLBYTES, 1, M_DONTWAIT, 1, MT_DATA); + chk->data = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_DONTWAIT, 1, MT_DATA); if (chk->data == NULL) { jump_out: sctp_free_a_chunk(stcb, chk); return; } - chk->data->m_data += SCTP_MIN_OVERHEAD; + SCTP_BUF_RESV_UF(chk->data, SCTP_MIN_OVERHEAD); drp = mtod(chk->data, struct sctp_pktdrop_chunk *); if (drp == NULL) { sctp_m_freem(chk->data); @@ -8448,7 +8316,7 @@ jump_out: drp->ch.chunk_flags |= SCTP_BADCRC; } chk->send_size += sizeof(struct sctp_pktdrop_chunk); - chk->data->m_pkthdr.len = chk->data->m_len = chk->send_size; + SCTP_BUF_LEN(chk->data) = chk->send_size; chk->sent = SCTP_DATAGRAM_UNSENT; chk->snd_count = 0; if (net) { @@ -8516,13 +8384,13 @@ sctp_send_cwr(struct sctp_tcb *stcb, struct sctp_nets *net, uint32_t high_tsn) chk->rec.chunk_id.can_take_data = 1; chk->asoc = &stcb->asoc; chk->send_size = sizeof(struct sctp_cwr_chunk); - chk->data = sctp_get_mbuf_for_msg(chk->send_size, 1, M_DONTWAIT, 1, MT_HEADER); + chk->data = sctp_get_mbuf_for_msg(chk->send_size, 0, M_DONTWAIT, 1, MT_HEADER); if (chk->data == NULL) { sctp_free_a_chunk(stcb, chk); return; } - chk->data->m_data += SCTP_MIN_OVERHEAD; - chk->data->m_pkthdr.len = chk->data->m_len = chk->send_size; + SCTP_BUF_RESV_UF(chk->data, SCTP_MIN_OVERHEAD); + SCTP_BUF_LEN(chk->data) = chk->send_size; chk->sent = SCTP_DATAGRAM_UNSENT; chk->snd_count = 0; chk->whoTo = net; @@ -8574,9 +8442,9 @@ sctp_add_stream_reset_out(struct sctp_tmit_chunk *chk, } /* now fix the chunk length */ ch->chunk_length = htons(len + old_len); - chk->send_size = len + old_len; - chk->book_size = SCTP_SIZE32(chk->send_size); - chk->data->m_pkthdr.len = chk->data->m_len = SCTP_SIZE32(chk->send_size); + chk->book_size = len + old_len; + chk->send_size = SCTP_SIZE32(chk->book_size); + SCTP_BUF_LEN(chk->data) = chk->send_size; return; } @@ -8617,9 +8485,9 @@ sctp_add_stream_reset_in(struct sctp_tmit_chunk *chk, } /* now fix the chunk length */ ch->chunk_length = htons(len + old_len); - chk->send_size = len + old_len; - chk->book_size = SCTP_SIZE32(chk->send_size); - chk->data->m_pkthdr.len = chk->data->m_len = SCTP_SIZE32(chk->send_size); + chk->book_size = len + old_len; + chk->send_size = SCTP_SIZE32(chk->book_size); + SCTP_BUF_LEN(chk->data) = chk->send_size; return; } @@ -8649,7 +8517,7 @@ sctp_add_stream_reset_tsn(struct sctp_tmit_chunk *chk, ch->chunk_length = htons(len + old_len); chk->send_size = len + old_len; chk->book_size = SCTP_SIZE32(chk->send_size); - chk->data->m_pkthdr.len = chk->data->m_len = SCTP_SIZE32(chk->send_size); + SCTP_BUF_LEN(chk->data) = SCTP_SIZE32(chk->send_size); return; } @@ -8677,9 +8545,9 @@ sctp_add_stream_reset_result(struct sctp_tmit_chunk *chk, /* now fix the chunk length */ ch->chunk_length = htons(len + old_len); - chk->send_size = len + old_len; - chk->book_size = SCTP_SIZE32(chk->send_size); - chk->data->m_pkthdr.len = chk->data->m_len = SCTP_SIZE32(chk->send_size); + chk->book_size = len + old_len; + chk->send_size = SCTP_SIZE32(chk->book_size); + SCTP_BUF_LEN(chk->data) = chk->send_size; return; } @@ -8712,9 +8580,9 @@ sctp_add_stream_reset_result_tsn(struct sctp_tmit_chunk *chk, /* now fix the chunk length */ ch->chunk_length = htons(len + old_len); - chk->send_size = len + old_len; - chk->book_size = SCTP_SIZE32(chk->send_size); - chk->data->m_pkthdr.len = chk->data->m_len = SCTP_SIZE32(chk->send_size); + chk->book_size = len + old_len; + chk->send_size = SCTP_SIZE32(chk->book_size); + SCTP_BUF_LEN(chk->data) = chk->send_size; return; } @@ -8755,14 +8623,15 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb, chk->rec.chunk_id.id = SCTP_STREAM_RESET; chk->rec.chunk_id.can_take_data = 0; chk->asoc = &stcb->asoc; - chk->book_size = SCTP_SIZE32(chk->send_size = sizeof(struct sctp_chunkhdr)); + chk->book_size = sizeof(struct sctp_chunkhdr); + chk->send_size = SCTP_SIZE32(chk->book_size); - chk->data = sctp_get_mbuf_for_msg(MCLBYTES, 1, M_DONTWAIT, 1, MT_DATA); + chk->data = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_DONTWAIT, 1, MT_DATA); if (chk->data == NULL) { sctp_free_a_chunk(stcb, chk); return (ENOMEM); } - chk->data->m_data += SCTP_MIN_OVERHEAD; + SCTP_BUF_RESV_UF(chk->data, SCTP_MIN_OVERHEAD); /* setup chunk parameters */ chk->sent = SCTP_DATAGRAM_UNSENT; @@ -8773,8 +8642,8 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb, ch = mtod(chk->data, struct sctp_chunkhdr *); ch->chunk_type = SCTP_STREAM_RESET; ch->chunk_flags = 0; - ch->chunk_length = htons(chk->send_size); - chk->data->m_pkthdr.len = chk->data->m_len = SCTP_SIZE32(chk->send_size); + ch->chunk_length = htons(chk->book_size); + SCTP_BUF_LEN(chk->data) = chk->send_size; seq = stcb->asoc.str_reset_seq_out; if (send_out_req) { @@ -8810,6 +8679,7 @@ sctp_send_abort(struct mbuf *m, int iphlen, struct sctphdr *sh, uint32_t vtag, /* * Formulate the abort message, and send it back down. */ + struct mbuf *o_pak; struct mbuf *mout; struct sctp_abort_msg *abm; struct ip *iph, *iph_out; @@ -8822,20 +8692,20 @@ sctp_send_abort(struct mbuf *m, int iphlen, struct sctphdr *sh, uint32_t vtag, sctp_m_freem(err_cause); return; } - mout = sctp_get_mbuf_for_msg((sizeof(struct ip6_hdr) + sizeof(struct sctp_abort_msg)), - 1, M_DONTWAIT, 1, MT_HEADER); - if (mout == NULL) { + o_pak = SCTP_GET_HEADER_FOR_OUTPUT((sizeof(struct ip6_hdr) + sizeof(struct sctp_abort_msg))); + if (o_pak == NULL) { if (err_cause) sctp_m_freem(err_cause); return; } + mout = SCTP_HEADER_TO_CHAIN(o_pak); iph = mtod(m, struct ip *); iph_out = NULL; ip6_out = NULL; if (iph->ip_v == IPVERSION) { iph_out = mtod(mout, struct ip *); - mout->m_len = sizeof(*iph_out) + sizeof(*abm); - mout->m_next = err_cause; + SCTP_BUF_LEN(mout) = sizeof(*iph_out) + sizeof(*abm); + SCTP_BUF_NEXT(mout) = err_cause; /* Fill in the IP header for the ABORT */ iph_out->ip_v = IPVERSION; @@ -8855,8 +8725,8 @@ sctp_send_abort(struct mbuf *m, int iphlen, struct sctphdr *sh, uint32_t vtag, } else if (iph->ip_v == (IPV6_VERSION >> 4)) { ip6 = (struct ip6_hdr *)iph; ip6_out = mtod(mout, struct ip6_hdr *); - mout->m_len = sizeof(*ip6_out) + sizeof(*abm); - mout->m_next = err_cause; + SCTP_BUF_LEN(mout) = sizeof(*ip6_out) + sizeof(*abm); + SCTP_BUF_NEXT(mout) = err_cause; /* Fill in the IP6 header for the ABORT */ ip6_out->ip6_flow = ip6->ip6_flow; @@ -8890,35 +8760,31 @@ sctp_send_abort(struct mbuf *m, int iphlen, struct sctphdr *sh, uint32_t vtag, /* get length of the err_cause chain */ while (m_tmp != NULL) { - err_len += m_tmp->m_len; - m_tmp = m_tmp->m_next; + err_len += SCTP_BUF_LEN(m_tmp); + m_tmp = SCTP_BUF_NEXT(m_tmp); } - mout->m_pkthdr.len = mout->m_len + err_len; + SCTP_HEADER_LEN(o_pak) = SCTP_BUF_LEN(mout) + err_len; if (err_len % 4) { /* need pad at end of chunk */ uint32_t cpthis = 0; int padlen; - padlen = 4 - (mout->m_pkthdr.len % 4); - m_copyback(mout, mout->m_pkthdr.len, padlen, (caddr_t)&cpthis); + padlen = 4 - (SCTP_HEADER_LEN(o_pak) % 4); + m_copyback(mout, SCTP_HEADER_LEN(o_pak), padlen, (caddr_t)&cpthis); + SCTP_HEADER_LEN(o_pak) += padlen; } abm->msg.ch.chunk_length = htons(sizeof(abm->msg.ch) + err_len); } else { - mout->m_pkthdr.len = mout->m_len; + SCTP_HEADER_LEN(mout) = SCTP_BUF_LEN(mout); abm->msg.ch.chunk_length = htons(sizeof(abm->msg.ch)); } /* add checksum */ - if ((sctp_no_csum_on_loopback) && - (m->m_pkthdr.rcvif) && - (m->m_pkthdr.rcvif->if_type == IFT_LOOP)) { + if ((sctp_no_csum_on_loopback) && SCTP_IS_IT_LOOPBACK(m)) { abm->sh.checksum = 0; } else { abm->sh.checksum = sctp_calculate_sum(mout, NULL, iphlen_out); } - - /* zap the rcvif, it should be null */ - mout->m_pkthdr.rcvif = 0; if (iph_out != NULL) { struct route ro; @@ -8931,9 +8797,9 @@ sctp_send_abort(struct mbuf *m, int iphlen, struct sctphdr *sh, uint32_t vtag, } #endif /* set IPv4 length */ - iph_out->ip_len = mout->m_pkthdr.len; + iph_out->ip_len = SCTP_HEADER_LEN(o_pak); /* out it goes */ - (void)ip_output(mout, 0, &ro, IP_RAWOUTPUT, NULL + (void)ip_output(o_pak, 0, &ro, IP_RAWOUTPUT, NULL ,NULL ); /* Free the route if we got one back */ @@ -8951,7 +8817,8 @@ sctp_send_abort(struct mbuf *m, int iphlen, struct sctphdr *sh, uint32_t vtag, sctp_print_address_pkt((struct ip *)ip6_out, &abm->sh); } #endif - ip6_output(mout, NULL, &ro, 0, NULL, NULL + ip6_out->ip6_plen = SCTP_HEADER_LEN(o_pak) - sizeof(*ip6_out); + ip6_output(o_pak, NULL, &ro, 0, NULL, NULL ,NULL ); /* Free the route if we got one back */ @@ -8967,6 +8834,7 @@ sctp_send_operr_to(struct mbuf *m, int iphlen, struct mbuf *scm, uint32_t vtag) { + struct mbuf *o_pak; struct sctphdr *ihdr; int retcode; struct sctphdr *ohdr; @@ -8979,16 +8847,13 @@ sctp_send_operr_to(struct mbuf *m, int iphlen, #endif uint32_t val; + struct mbuf *at; + int len; iph = mtod(m, struct ip *); ihdr = (struct sctphdr *)((caddr_t)iph + iphlen); - if (!(scm->m_flags & M_PKTHDR)) { - /* must be a pkthdr */ - printf("Huh, not a packet header in send_operr\n"); - sctp_m_freem(scm); - return; - } - M_PREPEND(scm, (sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr)), M_DONTWAIT); + + SCTP_BUF_PREPEND(scm, (sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr)), M_DONTWAIT); if (scm == NULL) { /* can't send because we can't add a mbuf */ return; @@ -9001,18 +8866,24 @@ sctp_send_operr_to(struct mbuf *m, int iphlen, ophdr = (struct sctp_chunkhdr *)(ohdr + 1); ophdr->chunk_type = SCTP_OPERATION_ERROR; ophdr->chunk_flags = 0; - ophdr->chunk_length = htons(scm->m_pkthdr.len - sizeof(struct sctphdr)); - if (scm->m_pkthdr.len % 4) { + len = 0; + at = scm; + while (at) { + len += SCTP_BUF_LEN(at); + at = SCTP_BUF_NEXT(at); + } + + ophdr->chunk_length = htons(len - sizeof(struct sctphdr)); + if (len % 4) { /* need padding */ uint32_t cpthis = 0; int padlen; - padlen = 4 - (scm->m_pkthdr.len % 4); - m_copyback(scm, scm->m_pkthdr.len, padlen, (caddr_t)&cpthis); + padlen = 4 - (len % 4); + m_copyback(scm, len, padlen, (caddr_t)&cpthis); + len += padlen; } - if ((sctp_no_csum_on_loopback) && - (m->m_pkthdr.rcvif) && - (m->m_pkthdr.rcvif->if_type == IFT_LOOP)) { + if ((sctp_no_csum_on_loopback) && SCTP_IS_IT_LOOPBACK(m)) { val = 0; } else { val = sctp_calculate_sum(scm, NULL, 0); @@ -9023,11 +8894,16 @@ sctp_send_operr_to(struct mbuf *m, int iphlen, struct ip *out; struct route ro; - M_PREPEND(scm, sizeof(struct ip), M_DONTWAIT); - if (scm == NULL) + o_pak = SCTP_GET_HEADER_FOR_OUTPUT(sizeof(struct ip)); + if (o_pak == NULL) { + sctp_m_freem(scm); return; + } + SCTP_BUF_LEN(SCTP_HEADER_TO_CHAIN(o_pak)) = sizeof(struct ip); + len += sizeof(struct ip); + SCTP_ATTACH_CHAIN(o_pak, scm, len); bzero(&ro, sizeof ro); - out = mtod(scm, struct ip *); + out = mtod(SCTP_HEADER_TO_CHAIN(o_pak), struct ip *); out->ip_v = iph->ip_v; out->ip_hl = (sizeof(struct ip) / 4); out->ip_tos = iph->ip_tos; @@ -9038,8 +8914,8 @@ sctp_send_operr_to(struct mbuf *m, int iphlen, out->ip_sum = 0; out->ip_src = iph->ip_dst; out->ip_dst = iph->ip_src; - out->ip_len = scm->m_pkthdr.len; - retcode = ip_output(scm, 0, &ro, IP_RAWOUTPUT, NULL + out->ip_len = SCTP_HEADER_LEN(o_pak); + retcode = ip_output(o_pak, 0, &ro, IP_RAWOUTPUT, NULL ,NULL ); SCTP_STAT_INCR(sctps_sendpackets); @@ -9053,18 +8929,24 @@ sctp_send_operr_to(struct mbuf *m, int iphlen, struct ip6_hdr *out6, *in6; - M_PREPEND(scm, sizeof(struct ip6_hdr), M_DONTWAIT); - if (scm == NULL) + o_pak = SCTP_GET_HEADER_FOR_OUTPUT(sizeof(struct ip6_hdr)); + if (o_pak == NULL) { + sctp_m_freem(scm); return; + } + SCTP_BUF_LEN(SCTP_HEADER_TO_CHAIN(o_pak)) = sizeof(struct ip6_hdr); + len += sizeof(struct ip6_hdr); + SCTP_ATTACH_CHAIN(o_pak, scm, len); + bzero(&ro, sizeof ro); in6 = mtod(m, struct ip6_hdr *); - out6 = mtod(scm, struct ip6_hdr *); + out6 = mtod(SCTP_HEADER_TO_CHAIN(o_pak), struct ip6_hdr *); out6->ip6_flow = in6->ip6_flow; out6->ip6_hlim = ip6_defhlim; out6->ip6_nxt = IPPROTO_SCTP; out6->ip6_src = in6->ip6_dst; out6->ip6_dst = in6->ip6_src; - + out6->ip6_plen = len - sizeof(struct ip6_hdr); #ifdef SCTP_DEBUG bzero(&lsa6, sizeof(lsa6)); lsa6.sin6_len = sizeof(lsa6); @@ -9082,7 +8964,7 @@ sctp_send_operr_to(struct mbuf *m, int iphlen, sctp_print_address((struct sockaddr *)&fsa6); } #endif /* SCTP_DEBUG */ - ip6_output(scm, NULL, &ro, 0, NULL, NULL + ip6_output(o_pak, NULL, &ro, 0, NULL, NULL ,NULL ); SCTP_STAT_INCR(sctps_sendpackets); @@ -9105,14 +8987,12 @@ sctp_copy_resume(struct sctp_stream_queue_pending *sp, uint32_t * sndout, struct mbuf **new_tail) { - int left, cancpy, willcpy, need_hdr = 0; + int left, cancpy, willcpy; struct mbuf *m, *prev, *head; left = min(uio->uio_resid, max_send_len); /* Always get a header just in case */ - need_hdr = 1; - - head = sctp_get_mbuf_for_msg(left, need_hdr, M_WAIT, 0, MT_DATA); + head = sctp_get_mbuf_for_msg(left, 0, M_WAIT, 0, MT_DATA); cancpy = M_TRAILINGSPACE(head); willcpy = min(cancpy, left); *error = uiomove(mtod(head, caddr_t), willcpy, uio); @@ -9122,20 +9002,20 @@ sctp_copy_resume(struct sctp_stream_queue_pending *sp, } *sndout += willcpy; left -= willcpy; - head->m_len = willcpy; + SCTP_BUF_LEN(head) = willcpy; m = head; *new_tail = head; while (left > 0) { /* move in user data */ - m->m_next = sctp_get_mbuf_for_msg(left, 0, M_WAIT, 0, MT_DATA); - if (m->m_next == NULL) { + SCTP_BUF_NEXT(m) = sctp_get_mbuf_for_msg(left, 0, M_WAIT, 0, MT_DATA); + if (SCTP_BUF_NEXT(m) == NULL) { sctp_m_freem(head); *new_tail = NULL; *error = ENOMEM; return (NULL); } prev = m; - m = m->m_next; + m = SCTP_BUF_NEXT(m); cancpy = M_TRAILINGSPACE(m); willcpy = min(cancpy, left); *error = uiomove(mtod(m, caddr_t), willcpy, uio); @@ -9145,12 +9025,12 @@ sctp_copy_resume(struct sctp_stream_queue_pending *sp, *error = EFAULT; return (NULL); } - m->m_len = willcpy; + SCTP_BUF_LEN(m) = willcpy; left -= willcpy; *sndout += willcpy; *new_tail = m; if (left == 0) { - m->m_next = NULL; + SCTP_BUF_NEXT(m) = NULL; } } return (head); @@ -9167,7 +9047,7 @@ sctp_copy_one(struct sctp_stream_queue_pending *sp, /* First one gets a header */ left = sp->length; - head = m = sctp_get_mbuf_for_msg((left + resv_upfront), 1, M_WAIT, 0, MT_DATA); + head = m = sctp_get_mbuf_for_msg((left + resv_upfront), 0, M_WAIT, 0, MT_DATA); if (m == NULL) { return (ENOMEM); } @@ -9175,7 +9055,7 @@ sctp_copy_one(struct sctp_stream_queue_pending *sp, * Add this one for m in now, that way if the alloc fails we won't * have a bad cnt. */ - m->m_data += resv_upfront; + SCTP_BUF_RESV_UF(m, resv_upfront); cancpy = M_TRAILINGSPACE(m); willcpy = min(cancpy, left); while (left > 0) { @@ -9185,12 +9065,12 @@ sctp_copy_one(struct sctp_stream_queue_pending *sp, sctp_m_freem(head); return (error); } - m->m_len = willcpy; + SCTP_BUF_LEN(m) = willcpy; left -= willcpy; cpsz += willcpy; if (left > 0) { - m->m_next = sctp_get_mbuf_for_msg(left, 0, M_WAIT, 0, MT_DATA); - if (m->m_next == NULL) { + SCTP_BUF_NEXT(m) = sctp_get_mbuf_for_msg(left, 0, M_WAIT, 0, MT_DATA); + if (SCTP_BUF_NEXT(m) == NULL) { /* * the head goes back to caller, he can free * the rest @@ -9198,12 +9078,12 @@ sctp_copy_one(struct sctp_stream_queue_pending *sp, sctp_m_freem(head); return (ENOMEM); } - m = m->m_next; + m = SCTP_BUF_NEXT(m); cancpy = M_TRAILINGSPACE(m); willcpy = min(cancpy, left); } else { sp->tail_mbuf = m; - m->m_next = NULL; + SCTP_BUF_NEXT(m) = NULL; } } sp->data = head; @@ -9296,7 +9176,6 @@ sctp_copy_it_in(struct sctp_tcb *stcb, sp->addr_over = 0; } atomic_add_int(&sp->net->ref_count, 1); - sp->data->m_pkthdr.len = sp->length; sctp_set_prsctp_policy(stcb, sp); } out_now: @@ -9341,7 +9220,7 @@ int sctp_lower_sosend(struct socket *so, struct sockaddr *addr, struct uio *uio, - struct mbuf *top, + struct mbuf *i_pak, struct mbuf *control, int flags, int use_rcvinfo, @@ -9351,6 +9230,7 @@ sctp_lower_sosend(struct socket *so, { unsigned int sndlen, max_len; int error, len; + struct mbuf *top = NULL; int s, queue_only = 0, queue_only_for_init = 0; int free_cnt_applied = 0; int un_sent = 0; @@ -9382,8 +9262,10 @@ sctp_lower_sosend(struct socket *so, atomic_add_int(&inp->total_sends, 1); if (uio) sndlen = uio->uio_resid; - else - sndlen = top->m_pkthdr.len; + else { + sndlen = SCTP_HEADER_LEN(i_pak); + top = SCTP_HEADER_TO_CHAIN(i_pak); + } s = splnet(); hold_tcblock = 0; @@ -9746,25 +9628,22 @@ sctp_lower_sosend(struct socket *so, hold_tcblock = 0; } if (top) { - mm = sctp_get_mbuf_for_msg(1, 1, M_WAIT, 1, MT_DATA); - if (top->m_flags & M_PKTHDR) - tot_out = top->m_pkthdr.len; - else { - struct mbuf *cntm; + struct mbuf *cntm; - tot_out = 0; - cntm = top; - while (cntm) { - tot_out += cntm->m_len; - cntm = cntm->m_next; - } + mm = sctp_get_mbuf_for_msg(1, 0, M_WAIT, 1, MT_DATA); + + tot_out = 0; + cntm = top; + while (cntm) { + tot_out += SCTP_BUF_LEN(cntm); + cntm = SCTP_BUF_NEXT(cntm); } tot_demand = (tot_out + sizeof(struct sctp_paramhdr)); } else { /* Must fit in a MTU */ tot_out = uio->uio_resid; tot_demand = (tot_out + sizeof(struct sctp_paramhdr)); - mm = sctp_get_mbuf_for_msg(tot_demand, 1, M_WAIT, 1, MT_DATA); + mm = sctp_get_mbuf_for_msg(tot_demand, 0, M_WAIT, 1, MT_DATA); } if (mm == NULL) { error = ENOMEM; @@ -9783,8 +9662,7 @@ sctp_lower_sosend(struct socket *so, ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT); ph->param_length = htons((sizeof(struct sctp_paramhdr) + tot_out)); ph++; - mm->m_pkthdr.len = tot_out + sizeof(struct sctp_paramhdr); - mm->m_len = mm->m_pkthdr.len; + SCTP_BUF_LEN(mm) = tot_out + sizeof(struct sctp_paramhdr); if (top == NULL) { error = uiomove((caddr_t)ph, (int)tot_out, uio); if (error) { @@ -9797,7 +9675,7 @@ sctp_lower_sosend(struct socket *so, mm = NULL; } } else { - mm->m_next = top; + SCTP_BUF_NEXT(mm) = top; } } if (hold_tcblock == 0) { @@ -9997,7 +9875,7 @@ sctp_lower_sosend(struct socket *so, } if (sp->tail_mbuf) { /* tack it to the end */ - sp->tail_mbuf->m_next = mm; + SCTP_BUF_NEXT(sp->tail_mbuf) = mm; sp->tail_mbuf = new_tail; } else { /* A stolen mbuf */ @@ -10016,10 +9894,6 @@ sctp_lower_sosend(struct socket *so, } else { sp->msg_is_complete = 0; } - if (sp->data->m_flags & M_PKTHDR) { - /* update length */ - sp->data->m_pkthdr.len = sp->length; - } SCTP_TCB_SEND_UNLOCK(stcb); } if (uio->uio_resid == 0) { @@ -10467,14 +10341,14 @@ sctp_add_auth_chunk(struct mbuf *m, struct mbuf **m_end, if (!sctp_auth_is_required_chunk(chunk, stcb->asoc.peer_auth_chunks)) { return (m); } - m_auth = sctp_get_mbuf_for_msg(sizeof(*auth), 1, M_DONTWAIT, 1, MT_HEADER); + m_auth = sctp_get_mbuf_for_msg(sizeof(*auth), 0, M_DONTWAIT, 1, MT_HEADER); if (m_auth == NULL) { /* no mbuf's */ return (m); } /* reserve some space if this will be the first mbuf */ if (m == NULL) - m_auth->m_data += SCTP_MIN_OVERHEAD; + 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)); @@ -10487,13 +10361,20 @@ sctp_add_auth_chunk(struct mbuf *m, struct mbuf **m_end, /* key id and hmac digest will be computed and filled in upon send */ /* save the offset where the auth was inserted into the chain */ - if (m != NULL) - *offset = m->m_pkthdr.len; - else + if (m != NULL) { + struct mbuf *cn; + + *offset = 0; + cn = m; + while (cn) { + *offset += SCTP_BUF_LEN(cn); + cn = SCTP_BUF_NEXT(cn); + } + } else *offset = 0; /* update length and return pointer to the auth chunk */ - m_auth->m_pkthdr.len = m_auth->m_len = chunk_len; + SCTP_BUF_LEN(m_auth) = chunk_len; m = sctp_copy_mbufchain(m_auth, m, m_end, 1, chunk_len, 0); if (auth_ret != NULL) *auth_ret = auth; diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c index 89e649b..67b5189 100644 --- a/sys/netinet/sctp_pcb.c +++ b/sys/netinet/sctp_pcb.c @@ -52,8 +52,6 @@ __FBSDID("$FreeBSD$"); #include <sys/kernel.h> #include <sys/sysctl.h> -#include <sys/callout.h> - #include <sys/limits.h> #include <machine/cpu.h> @@ -1461,7 +1459,7 @@ sctp_inpcb_alloc(struct socket *so) LIST_INIT(&inp->sctp_asoc_free_list); #endif /* Init the timer structure for signature change */ - callout_init(&inp->sctp_ep.signature_change.timer, 1); + SCTP_OS_TIMER_INIT(&inp->sctp_ep.signature_change.timer); inp->sctp_ep.signature_change.type = SCTP_TIMER_TYPE_NEWCOOKIE; /* now init the actual endpoint default data */ @@ -1498,7 +1496,7 @@ sctp_inpcb_alloc(struct socket *so) /* seed random number generator */ m->random_counter = 1; m->store_at = SCTP_SIGNATURE_SIZE; - sctp_read_random(m->random_numbers, sizeof(m->random_numbers)); + SCTP_READ_RANDOM(m->random_numbers, sizeof(m->random_numbers)); sctp_fill_random_store(m); /* Minimum cookie size */ @@ -2162,13 +2160,13 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) struct sctp_paramhdr *ph; uint32_t *ippp; - op_err->m_len = + SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr) + sizeof(uint32_t); ph = mtod(op_err, struct sctp_paramhdr *); ph->param_type = htons( SCTP_CAUSE_USER_INITIATED_ABT); - ph->param_length = htons(op_err->m_len); + ph->param_length = htons(SCTP_BUF_LEN(op_err)); ippp = (uint32_t *) (ph + 1); *ippp = htonl(SCTP_FROM_SCTP_PCB + SCTP_LOC_3); } @@ -2238,14 +2236,14 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) struct sctp_paramhdr *ph; uint32_t *ippp; - op_err->m_len = + SCTP_BUF_LEN(op_err) = (sizeof(struct sctp_paramhdr) + sizeof(uint32_t)); ph = mtod(op_err, struct sctp_paramhdr *); ph->param_type = htons( SCTP_CAUSE_USER_INITIATED_ABT); - ph->param_length = htons(op_err->m_len); + ph->param_length = htons(SCTP_BUF_LEN(op_err)); ippp = (uint32_t *) (ph + 1); *ippp = htonl(SCTP_FROM_SCTP_PCB + SCTP_LOC_5); } @@ -2312,12 +2310,12 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) /* Fill in the user initiated abort */ struct sctp_paramhdr *ph; - op_err->m_len = (sizeof(struct sctp_paramhdr) + + SCTP_BUF_LEN(op_err) = (sizeof(struct sctp_paramhdr) + sizeof(uint32_t)); ph = mtod(op_err, struct sctp_paramhdr *); ph->param_type = htons( SCTP_CAUSE_USER_INITIATED_ABT); - ph->param_length = htons(op_err->m_len); + ph->param_length = htons(SCTP_BUF_LEN(op_err)); ippp = (uint32_t *) (ph + 1); *ippp = htonl(SCTP_FROM_SCTP_PCB + SCTP_LOC_7); @@ -2338,7 +2336,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) } if (cnt) { /* Ok we have someone out there that will kill us */ - callout_stop(&inp->sctp_ep.signature_change.timer); + SCTP_OS_TIMER_STOP(&inp->sctp_ep.signature_change.timer); SCTP_INP_WUNLOCK(inp); SCTP_ASOC_CREATE_UNLOCK(inp); SCTP_INP_INFO_WUNLOCK(); @@ -2349,7 +2347,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) return; } if ((inp->refcount) || (inp->sctp_flags & SCTP_PCB_FLAGS_CLOSE_IP)) { - callout_stop(&inp->sctp_ep.signature_change.timer); + SCTP_OS_TIMER_STOP(&inp->sctp_ep.signature_change.timer); sctp_timer_start(SCTP_TIMER_TYPE_INPKILL, inp, NULL, NULL); SCTP_INP_WUNLOCK(inp); SCTP_ASOC_CREATE_UNLOCK(inp); @@ -2360,7 +2358,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) #endif return; } - callout_stop(&inp->sctp_ep.signature_change.timer); + SCTP_OS_TIMER_STOP(&inp->sctp_ep.signature_change.timer); inp->sctp_ep.signature_change.type = 0; inp->sctp_flags |= SCTP_PCB_FLAGS_SOCKET_ALLGONE; @@ -2368,7 +2366,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) sctp_log_closing(inp, NULL, 5); #endif - callout_stop(&inp->sctp_ep.signature_change.timer); + SCTP_OS_TIMER_STOP(&inp->sctp_ep.signature_change.timer); inp->sctp_ep.signature_change.type = SCTP_TIMER_TYPE_NONE; /* Clear the read queue */ while ((sq = TAILQ_FIRST(&inp->read_queue)) != NULL) { @@ -2727,9 +2725,9 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr, net->tos_flowlabel = stcb->asoc.default_flowlabel; #endif /* Init the timer structure */ - callout_init(&net->rxt_timer.timer, 1); - callout_init(&net->fr_timer.timer, 1); - callout_init(&net->pmtu_timer.timer, 1); + SCTP_OS_TIMER_INIT(&net->rxt_timer.timer); + SCTP_OS_TIMER_INIT(&net->fr_timer.timer); + SCTP_OS_TIMER_INIT(&net->pmtu_timer.timer); /* Now generate a route for this guy */ /* KAME hack: embed scopeid */ @@ -3019,13 +3017,14 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr, return (NULL); } /* Init all the timers */ - callout_init(&asoc->hb_timer.timer, 1); - callout_init(&asoc->dack_timer.timer, 1); - callout_init(&asoc->asconf_timer.timer, 1); - callout_init(&asoc->strreset_timer.timer, 1); - callout_init(&asoc->shut_guard_timer.timer, 1); - callout_init(&asoc->autoclose_timer.timer, 1); - callout_init(&asoc->delayed_event_timer.timer, 1); + SCTP_OS_TIMER_INIT(&asoc->hb_timer.timer); + SCTP_OS_TIMER_INIT(&asoc->dack_timer.timer); + SCTP_OS_TIMER_INIT(&asoc->strreset_timer.timer); + SCTP_OS_TIMER_INIT(&asoc->asconf_timer.timer); + SCTP_OS_TIMER_INIT(&asoc->shut_guard_timer.timer); + SCTP_OS_TIMER_INIT(&asoc->autoclose_timer.timer); + SCTP_OS_TIMER_INIT(&asoc->delayed_event_timer.timer); + LIST_INSERT_HEAD(&inp->sctp_asoc_list, stcb, sctp_tcblist); /* now file the port under the hash as well */ if (inp->sctp_tcbhash != NULL) { @@ -3282,18 +3281,18 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre } } /* now clean up any other timers */ - callout_stop(&asoc->hb_timer.timer); - callout_stop(&asoc->dack_timer.timer); - callout_stop(&asoc->strreset_timer.timer); - callout_stop(&asoc->asconf_timer.timer); - callout_stop(&asoc->autoclose_timer.timer); - callout_stop(&asoc->shut_guard_timer.timer); - callout_stop(&asoc->delayed_event_timer.timer); + SCTP_OS_TIMER_STOP(&asoc->hb_timer.timer); + SCTP_OS_TIMER_STOP(&asoc->dack_timer.timer); + SCTP_OS_TIMER_STOP(&asoc->strreset_timer.timer); + SCTP_OS_TIMER_STOP(&asoc->asconf_timer.timer); + SCTP_OS_TIMER_STOP(&asoc->autoclose_timer.timer); + SCTP_OS_TIMER_STOP(&asoc->shut_guard_timer.timer); + SCTP_OS_TIMER_STOP(&asoc->delayed_event_timer.timer); TAILQ_FOREACH(net, &asoc->nets, sctp_next) { - callout_stop(&net->fr_timer.timer); - callout_stop(&net->rxt_timer.timer); - callout_stop(&net->pmtu_timer.timer); + SCTP_OS_TIMER_STOP(&net->fr_timer.timer); + SCTP_OS_TIMER_STOP(&net->rxt_timer.timer); + SCTP_OS_TIMER_STOP(&net->pmtu_timer.timer); } /* Now the read queue needs to be cleaned up (only once) */ cnt = 0; @@ -3421,7 +3420,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre } } /* Stop any timer someone may have started */ - callout_stop(&asoc->strreset_timer.timer); + SCTP_OS_TIMER_STOP(&asoc->strreset_timer.timer); /* * Make it invalid too, that way if its about to run it will abort * and return. @@ -3433,18 +3432,18 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre atomic_add_int(&stcb->asoc.refcnt, -1); } /* now restop the timers to be sure - this is paranoia at is finest! */ - callout_stop(&asoc->hb_timer.timer); - callout_stop(&asoc->dack_timer.timer); - callout_stop(&asoc->strreset_timer.timer); - callout_stop(&asoc->asconf_timer.timer); - callout_stop(&asoc->shut_guard_timer.timer); - callout_stop(&asoc->autoclose_timer.timer); - callout_stop(&asoc->delayed_event_timer.timer); + SCTP_OS_TIMER_STOP(&asoc->hb_timer.timer); + SCTP_OS_TIMER_STOP(&asoc->dack_timer.timer); + SCTP_OS_TIMER_STOP(&asoc->strreset_timer.timer); + SCTP_OS_TIMER_STOP(&asoc->asconf_timer.timer); + SCTP_OS_TIMER_STOP(&asoc->shut_guard_timer.timer); + SCTP_OS_TIMER_STOP(&asoc->autoclose_timer.timer); + SCTP_OS_TIMER_STOP(&asoc->delayed_event_timer.timer); TAILQ_FOREACH(net, &asoc->nets, sctp_next) { - callout_stop(&net->fr_timer.timer); - callout_stop(&net->rxt_timer.timer); - callout_stop(&net->pmtu_timer.timer); + SCTP_OS_TIMER_STOP(&net->fr_timer.timer); + SCTP_OS_TIMER_STOP(&net->rxt_timer.timer); + SCTP_OS_TIMER_STOP(&net->pmtu_timer.timer); } asoc->state = 0; if (inp->sctp_tcbhash) { @@ -4198,7 +4197,6 @@ static char sctp_pcb_initialized = 0; static int sctp_max_number_of_assoc = SCTP_MAX_NUM_OF_ASOC; static int sctp_scale_up_for_address = SCTP_SCALE_FOR_ADDR; - void sctp_pcb_init() { @@ -4308,8 +4306,7 @@ sctp_pcb_init() sctppcbinfo.ipi_free_strmoq = 0; sctppcbinfo.ipi_free_chunks = 0; - - callout_init(&sctppcbinfo.addr_wq_timer.timer, 1); + SCTP_OS_TIMER_INIT(&sctppcbinfo.addr_wq_timer.timer); /* port stuff */ sctppcbinfo.lastlow = ipport_firstauto; @@ -5213,7 +5210,7 @@ sctp_drain_mbufs(struct sctp_inpcb *inp, struct sctp_tcb *stcb) asoc->highest_tsn_inside_map = asoc->cumulative_tsn; } asoc->last_revoke_count = cnt; - callout_stop(&stcb->asoc.dack_timer.timer); + SCTP_OS_TIMER_STOP(&stcb->asoc.dack_timer.timer); sctp_send_sack(stcb); reneged_asoc_ids[reneged_at] = sctp_get_associd(stcb); reneged_at++; @@ -5300,7 +5297,7 @@ sctp_initiate_iterator(inp_func inpf, asoc_func af, uint32_t pcb_state, } /* Init the timer */ - callout_init(&it->tmr.timer, 1); + SCTP_OS_TIMER_INIT(&it->tmr.timer); /* add to the list of all iterators */ SCTP_INP_INFO_WLOCK(); LIST_INSERT_HEAD(&sctppcbinfo.iteratorhead, it, sctp_nxt_itr); @@ -5311,8 +5308,3 @@ sctp_initiate_iterator(inp_func inpf, asoc_func af, uint32_t pcb_state, splx(s); return (0); } - - -/* - * Callout/Timer routines for OS that doesn't have them - */ diff --git a/sys/netinet/sctp_pcb.h b/sys/netinet/sctp_pcb.h index 82f7db2..d421c36 100644 --- a/sys/netinet/sctp_pcb.h +++ b/sys/netinet/sctp_pcb.h @@ -510,6 +510,5 @@ sctp_initiate_iterator(inp_func inpf, asoc_func af, uint32_t, uint32_t, uint32_t, void *, uint32_t, end_func ef, struct sctp_inpcb *, uint8_t co_off); - #endif /* _KERNEL */ #endif /* !__sctp_pcb_h__ */ diff --git a/sys/netinet/sctp_structs.h b/sys/netinet/sctp_structs.h index 9f4e9d0..35f7f7f 100644 --- a/sys/netinet/sctp_structs.h +++ b/sys/netinet/sctp_structs.h @@ -37,8 +37,6 @@ __FBSDID("$FreeBSD$"); #define __sctp_structs_h__ #include <sys/queue.h> - -#include <sys/callout.h> #include <sys/socket.h> #ifdef IPSEC @@ -46,12 +44,14 @@ __FBSDID("$FreeBSD$"); #include <netkey/key.h> #endif +#include <netinet/sctp_os.h> #include <netinet/sctp_header.h> #include <netinet/sctp_uio.h> #include <netinet/sctp_auth.h> struct sctp_timer { - struct callout timer; + sctp_os_timer_t timer; + int type; /* * Depending on the timer type these will be setup and cast with the @@ -367,9 +367,11 @@ struct sctp_queued_to_read { /* sinfo structure Pluse more */ struct sctp_tcb *stcb; /* assoc, used for window update */ TAILQ_ENTRY(sctp_queued_to_read) next; uint16_t port_from; + uint16_t spec_flags; /* Flags to hold the notification field */ uint8_t do_not_ref_stcb; uint8_t end_added; uint8_t pdapi_aborted; + uint8_t resv; }; /* This data structure will be on the outbound diff --git a/sys/netinet/sctp_timer.c b/sys/netinet/sctp_timer.c index dc55ef6..dae2a81 100644 --- a/sys/netinet/sctp_timer.c +++ b/sys/netinet/sctp_timer.c @@ -318,11 +318,11 @@ sctp_threshold_management(struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct sctp_paramhdr *ph; uint32_t *ippp; - oper->m_len = sizeof(struct sctp_paramhdr) + + SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) + sizeof(uint32_t); ph = mtod(oper, struct sctp_paramhdr *); ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION); - ph->param_length = htons(oper->m_len); + ph->param_length = htons(SCTP_BUF_LEN(oper)); ippp = (uint32_t *) (ph + 1); *ippp = htonl(SCTP_FROM_SCTP_TIMER + SCTP_LOC_1); } @@ -544,8 +544,8 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb, window_probe, SCTP_FR_T3_MARK_TIME); sctp_log_fr(net->flight_size, - callout_pending(&net->fr_timer.timer), - callout_active(&net->fr_timer.timer), + SCTP_OS_TIMER_PENDING(&net->fr_timer.timer), + SCTP_OS_TIMER_ACTIVE(&net->fr_timer.timer), SCTP_FR_CWND_REPORT); sctp_log_fr(net->flight_size, net->cwnd, stcb->asoc.total_flight, SCTP_FR_CWND_REPORT); #endif @@ -1091,11 +1091,11 @@ sctp_cookie_timer(struct sctp_inpcb *inp, struct sctp_paramhdr *ph; uint32_t *ippp; - oper->m_len = sizeof(struct sctp_paramhdr) + + SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) + sizeof(uint32_t); ph = mtod(oper, struct sctp_paramhdr *); ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION); - ph->param_length = htons(oper->m_len); + ph->param_length = htons(SCTP_BUF_LEN(oper)); ippp = (uint32_t *) (ph + 1); *ippp = htonl(SCTP_FROM_SCTP_TIMER + SCTP_LOC_2); } @@ -1472,7 +1472,7 @@ sctp_heartbeat_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int sctp_is_hb_timer_running(struct sctp_tcb *stcb) { - if (callout_pending(&stcb->asoc.hb_timer.timer)) { + if (SCTP_OS_TIMER_PENDING(&stcb->asoc.hb_timer.timer)) { /* its running */ return (1); } else { @@ -1484,7 +1484,7 @@ sctp_is_hb_timer_running(struct sctp_tcb *stcb) int sctp_is_sack_timer_running(struct sctp_tcb *stcb) { - if (callout_pending(&stcb->asoc.dack_timer.timer)) { + if (SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) { /* its running */ return (1); } else { @@ -1493,7 +1493,6 @@ sctp_is_sack_timer_running(struct sctp_tcb *stcb) } } - #define SCTP_NUMBER_OF_MTU_SIZES 18 static uint32_t mtu_sizes[] = { 68, @@ -1656,7 +1655,7 @@ done_with_iterator: LIST_REMOVE(it, sctp_nxt_itr); /* stopping the callout is not needed, in theory */ SCTP_INP_INFO_WUNLOCK(); - callout_stop(&it->tmr.timer); + SCTP_OS_TIMER_STOP(&it->tmr.timer); if (it->function_atend != NULL) { (*it->function_atend) (it->pointer, it->val); } diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c index c650e35..79a62a0 100644 --- a/sys/netinet/sctp_usrreq.c +++ b/sys/netinet/sctp_usrreq.c @@ -163,6 +163,7 @@ unsigned int sctp_early_fr_msec = SCTP_MINFR_MSEC_TIMER; unsigned int sctp_use_rttvar_cc = 0; int sctp_says_check_for_deadlock = 0; unsigned int sctp_asconf_auth_nochk = 0; +unsigned int sctp_nat_friendly = 1; unsigned int sctp_auth_disable = 0; unsigned int sctp_auth_random_len = SCTP_AUTH_RANDOM_SIZE_DEFAULT; unsigned int sctp_auth_hmac_id_default = SCTP_AUTH_HMAC_ID_SHA1; @@ -314,7 +315,7 @@ sctp_notify_mbuf(struct sctp_inpcb *inp, nxtsz = find_next_best_mtu(totsz); } /* Stop any PMTU timer */ - if (callout_pending(&net->pmtu_timer.timer)) { + if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) { tmr_stopped = 1; sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_1); @@ -923,6 +924,10 @@ SYSCTL_PROC(_net_inet_sctp, OID_AUTO, assoclist, CTLFLAG_RD, 0, 0, sctp_assoclist, "S,xassoc", "List of active SCTP associations"); +SYSCTL_UINT(_net_inet_sctp, OID_AUTO, nat_friendly, CTLFLAG_RW, + &sctp_nat_friendly, 0, + "SCTP NAT friendly operation"); + #ifdef SCTP_DEBUG SYSCTL_INT(_net_inet_sctp, OID_AUTO, debug, CTLFLAG_RW, &sctp_debug_on, 0, "Configure debug output"); @@ -1179,21 +1184,9 @@ connected_type: } inp->control = control; } - /* add it in possibly */ - if ((inp->pkt) && (inp->pkt->m_flags & M_PKTHDR)) { - struct mbuf *x; - int c_len; - - c_len = 0; - /* How big is it */ - for (x = m; x; x = x->m_next) { - c_len += x->m_len; - } - inp->pkt->m_pkthdr.len += c_len; - } /* Place the data */ if (inp->pkt) { - inp->pkt_last->m_next = m; + SCTP_BUF_NEXT(inp->pkt_last) = m; inp->pkt_last = m; } else { inp->pkt_last = inp->pkt = m; @@ -1275,9 +1268,9 @@ sctp_disconnect(struct socket *so) struct sctp_paramhdr *ph; ph = mtod(err, struct sctp_paramhdr *); - err->m_len = sizeof(struct sctp_paramhdr); + SCTP_BUF_LEN(err) = sizeof(struct sctp_paramhdr); ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT); - ph->param_length = htons(err->m_len); + ph->param_length = htons(SCTP_BUF_LEN(err)); } sctp_send_abort_tcb(stcb, err); SCTP_STAT_INCR_COUNTER32(sctps_aborted); @@ -1360,13 +1353,13 @@ sctp_disconnect(struct socket *so) struct sctp_paramhdr *ph; uint32_t *ippp; - op_err->m_len = + SCTP_BUF_LEN(op_err) = (sizeof(struct sctp_paramhdr) + sizeof(uint32_t)); ph = mtod(op_err, struct sctp_paramhdr *); ph->param_type = htons( SCTP_CAUSE_USER_INITIATED_ABT); - ph->param_length = htons(op_err->m_len); + ph->param_length = htons(SCTP_BUF_LEN(op_err)); ippp = (uint32_t *) (ph + 1); *ippp = htonl(SCTP_FROM_SCTP_USRREQ + SCTP_LOC_4); } @@ -1499,13 +1492,13 @@ sctp_shutdown(struct socket *so) struct sctp_paramhdr *ph; uint32_t *ippp; - op_err->m_len = + SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr) + sizeof(uint32_t); ph = mtod(op_err, struct sctp_paramhdr *); ph->param_type = htons( SCTP_CAUSE_USER_INITIATED_ABT); - ph->param_length = htons(op_err->m_len); + ph->param_length = htons(SCTP_BUF_LEN(op_err)); ippp = (uint32_t *) (ph + 1); *ippp = htonl(SCTP_FROM_SCTP_USRREQ + SCTP_LOC_6); } @@ -1869,7 +1862,7 @@ sctp_do_connect_x(struct socket *so, error = EALREADY; goto out_now; } - if ((at + incr) > m->m_len) { + if ((at + incr) > SCTP_BUF_LEN(m)) { totaddr = i; break; } @@ -2040,57 +2033,57 @@ sctp_optsget(struct socket *so, /* make it an "on/off" value */ optval = (optval != 0); } - if ((size_t)m->m_len < sizeof(int)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(int)) { error = EINVAL; } SCTP_INP_RUNLOCK(inp); if (error == 0) { /* return the option value */ *mtod(m, int *)= optval; - m->m_len = sizeof(optval); + SCTP_BUF_LEN(m) = sizeof(optval); } break; case SCTP_PARTIAL_DELIVERY_POINT: { - if ((size_t)m->m_len < sizeof(unsigned int)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(unsigned int)) { error = EINVAL; break; } *mtod(m, unsigned int *)= inp->partial_delivery_point; - m->m_len = sizeof(unsigned int); + SCTP_BUF_LEN(m) = sizeof(unsigned int); } break; case SCTP_FRAGMENT_INTERLEAVE: { - if ((size_t)m->m_len < sizeof(unsigned int)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(unsigned int)) { error = EINVAL; break; } *mtod(m, unsigned int *)= sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE); - m->m_len = sizeof(unsigned int); + SCTP_BUF_LEN(m) = sizeof(unsigned int); } break; case SCTP_CMT_ON_OFF: { - if ((size_t)m->m_len < sizeof(unsigned int)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(unsigned int)) { error = EINVAL; break; } *mtod(m, unsigned int *)= sctp_cmt_sockopt_on_off; - m->m_len = sizeof(unsigned int); + SCTP_BUF_LEN(m) = sizeof(unsigned int); } break; case SCTP_CMT_USE_DAC: { *mtod(m, unsigned int *)= sctp_cmt_sockopt_use_dac; - m->m_len = sizeof(unsigned int); + SCTP_BUF_LEN(m) = sizeof(unsigned int); } break; case SCTP_GET_ADDR_LEN: { struct sctp_assoc_value *av; - if ((size_t)m->m_len < sizeof(struct sctp_assoc_value)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_assoc_value)) { error = EINVAL; break; } @@ -2116,7 +2109,7 @@ sctp_optsget(struct socket *so, int cnt, at; uint16_t orig; - if ((size_t)m->m_len < sizeof(struct sctp_assoc_ids)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_assoc_ids)) { error = EINVAL; break; } @@ -2164,7 +2157,7 @@ sctp_optsget(struct socket *so, struct sctp_assoc_value *av; - if ((size_t)m->m_len < sizeof(struct sctp_assoc_value)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_assoc_value)) { error = EINVAL; break; } @@ -2186,7 +2179,7 @@ sctp_optsget(struct socket *so, { struct sctp_get_nonce_values *gnv; - if ((size_t)m->m_len < sizeof(struct sctp_get_nonce_values)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_get_nonce_values)) { error = EINVAL; break; } @@ -2206,7 +2199,7 @@ sctp_optsget(struct socket *so, { struct sctp_assoc_value *tm; - if ((size_t)m->m_len < sizeof(struct sctp_assoc_value)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_assoc_value)) { error = EINVAL; break; } @@ -2237,7 +2230,7 @@ sctp_optsget(struct socket *so, break; case SCTP_GET_SNDBUF_USE: - if ((size_t)m->m_len < sizeof(struct sctp_sockstat)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_sockstat)) { error = EINVAL; } else { struct sctp_sockstat *ss; @@ -2255,7 +2248,7 @@ sctp_optsget(struct socket *so, asoc->size_on_all_streams); SCTP_TCB_UNLOCK(stcb); error = 0; - m->m_len = sizeof(struct sctp_sockstat); + SCTP_BUF_LEN(m) = sizeof(struct sctp_sockstat); } } break; @@ -2267,7 +2260,7 @@ sctp_optsget(struct socket *so, SCTP_INP_RLOCK(inp); *burst = inp->sctp_ep.max_burst; SCTP_INP_RUNLOCK(inp); - m->m_len = sizeof(uint8_t); + SCTP_BUF_LEN(m) = sizeof(uint8_t); } break; @@ -2277,17 +2270,17 @@ sctp_optsget(struct socket *so, sctp_assoc_t *assoc_id; int ovh; - if ((size_t)m->m_len < sizeof(uint32_t)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(uint32_t)) { error = EINVAL; break; } - if ((size_t)m->m_len < sizeof(sctp_assoc_t)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(sctp_assoc_t)) { error = EINVAL; break; } assoc_id = mtod(m, sctp_assoc_t *); segsize = mtod(m, uint32_t *); - m->m_len = sizeof(uint32_t); + SCTP_BUF_LEN(m) = sizeof(uint32_t); if (((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) || @@ -2332,14 +2325,14 @@ sctp_optsget(struct socket *so, { uint32_t *level; - if ((size_t)m->m_len < sizeof(uint32_t)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(uint32_t)) { error = EINVAL; break; } level = mtod(m, uint32_t *); error = 0; *level = sctp_debug_on; - m->m_len = sizeof(uint32_t); + SCTP_BUF_LEN(m) = sizeof(uint32_t); printf("Returning DEBUG LEVEL %x is set\n", (uint32_t) sctp_debug_on); } @@ -2358,7 +2351,7 @@ sctp_optsget(struct socket *so, { struct sctp_event_subscribe *events; - if ((size_t)m->m_len < sizeof(struct sctp_event_subscribe)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_event_subscribe)) { error = EINVAL; break; } @@ -2395,40 +2388,40 @@ sctp_optsget(struct socket *so, if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT)) events->sctp_stream_reset_events = 1; SCTP_INP_RUNLOCK(inp); - m->m_len = sizeof(struct sctp_event_subscribe); + SCTP_BUF_LEN(m) = sizeof(struct sctp_event_subscribe); } break; case SCTP_ADAPTATION_LAYER: - if ((size_t)m->m_len < sizeof(int)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(int)) { error = EINVAL; break; } SCTP_INP_RLOCK(inp); *mtod(m, int *)= inp->sctp_ep.adaptation_layer_indicator; SCTP_INP_RUNLOCK(inp); - m->m_len = sizeof(int); + SCTP_BUF_LEN(m) = sizeof(int); break; case SCTP_SET_INITIAL_DBG_SEQ: - if ((size_t)m->m_len < sizeof(int)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(int)) { error = EINVAL; break; } SCTP_INP_RLOCK(inp); *mtod(m, int *)= inp->sctp_ep.initial_sequence_debug; SCTP_INP_RUNLOCK(inp); - m->m_len = sizeof(int); + SCTP_BUF_LEN(m) = sizeof(int); break; case SCTP_GET_LOCAL_ADDR_SIZE: - if ((size_t)m->m_len < sizeof(int)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(int)) { error = EINVAL; break; } SCTP_INP_RLOCK(inp); *mtod(m, int *)= sctp_count_max_addresses(inp); SCTP_INP_RUNLOCK(inp); - m->m_len = sizeof(int); + SCTP_BUF_LEN(m) = sizeof(int); break; case SCTP_GET_REMOTE_ADDR_SIZE: { @@ -2436,7 +2429,7 @@ sctp_optsget(struct socket *so, uint32_t *val, sz; struct sctp_nets *net; - if ((size_t)m->m_len < sizeof(sctp_assoc_t)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(sctp_assoc_t)) { error = EINVAL; break; } @@ -2473,7 +2466,7 @@ sctp_optsget(struct socket *so, } SCTP_TCB_UNLOCK(stcb); *val = sz; - m->m_len = sizeof(uint32_t); + SCTP_BUF_LEN(m) = sizeof(uint32_t); } break; case SCTP_GET_PEER_ADDRESSES: @@ -2487,11 +2480,11 @@ sctp_optsget(struct socket *so, struct sctp_nets *net; struct sctp_getaddresses *saddr; - if ((size_t)m->m_len < sizeof(struct sctp_getaddresses)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_getaddresses)) { error = EINVAL; break; } - left = m->m_len - sizeof(struct sctp_getaddresses); + left = SCTP_BUF_LEN(m) - sizeof(struct sctp_getaddresses); saddr = mtod(m, struct sctp_getaddresses *); if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) { SCTP_INP_RLOCK(inp); @@ -2506,7 +2499,7 @@ sctp_optsget(struct socket *so, error = ENOENT; break; } - m->m_len = sizeof(struct sctp_getaddresses); + SCTP_BUF_LEN(m) = sizeof(struct sctp_getaddresses); sas = (struct sockaddr_storage *)&saddr->addr[0]; TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { @@ -2535,7 +2528,7 @@ sctp_optsget(struct socket *so, sas = (struct sockaddr_storage *)((caddr_t)sas + cpsz); left -= cpsz; - m->m_len += cpsz; + SCTP_BUF_LEN(m) += cpsz; } SCTP_TCB_UNLOCK(stcb); } @@ -2546,7 +2539,7 @@ sctp_optsget(struct socket *so, struct sockaddr_storage *sas; struct sctp_getaddresses *saddr; - if ((size_t)m->m_len < sizeof(struct sctp_getaddresses)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_getaddresses)) { error = EINVAL; break; } @@ -2578,11 +2571,11 @@ sctp_optsget(struct socket *so, SCTP_INP_RUNLOCK(inp); } sas = (struct sockaddr_storage *)&saddr->addr[0]; - limit = m->m_len - sizeof(sctp_assoc_t); + limit = SCTP_BUF_LEN(m) - sizeof(sctp_assoc_t); actual = sctp_fill_up_addresses(inp, stcb, limit, sas); if (stcb) SCTP_TCB_UNLOCK(stcb); - m->m_len = sizeof(struct sockaddr_storage) + actual; + SCTP_BUF_LEN(m) = sizeof(struct sockaddr_storage) + actual; } break; case SCTP_PEER_ADDR_PARAMS: @@ -2590,7 +2583,7 @@ sctp_optsget(struct socket *so, struct sctp_paddrparams *paddrp; struct sctp_nets *net; - if ((size_t)m->m_len < sizeof(struct sctp_paddrparams)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_paddrparams)) { error = EINVAL; break; } @@ -2653,7 +2646,7 @@ sctp_optsget(struct socket *so, else paddrp->spp_flags |= SPP_HB_ENABLE; /* get flags for PMTU */ - if (callout_pending(&net->pmtu_timer.timer)) { + if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) { paddrp->spp_flags |= SPP_PMTUD_ENABLE; } else { paddrp->spp_flags |= SPP_PMTUD_DISABLE; @@ -2725,7 +2718,7 @@ sctp_optsget(struct socket *so, SCTP_INP_RUNLOCK(inp); } - m->m_len = sizeof(struct sctp_paddrparams); + SCTP_BUF_LEN(m) = sizeof(struct sctp_paddrparams); } break; case SCTP_GET_PEER_ADDR_INFO: @@ -2733,7 +2726,7 @@ sctp_optsget(struct socket *so, struct sctp_paddrinfo *paddri; struct sctp_nets *net; - if ((size_t)m->m_len < sizeof(struct sctp_paddrinfo)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_paddrinfo)) { error = EINVAL; break; } @@ -2771,7 +2764,7 @@ sctp_optsget(struct socket *so, error = ENOENT; break; } - m->m_len = sizeof(struct sctp_paddrinfo); + SCTP_BUF_LEN(m) = sizeof(struct sctp_paddrinfo); paddri->spinfo_state = net->dest_state & (SCTP_REACHABLE_MASK | SCTP_ADDR_NOHB); paddri->spinfo_cwnd = net->cwnd; paddri->spinfo_srtt = ((net->lastsa >> 2) + net->lastsv) >> 1; @@ -2784,13 +2777,13 @@ sctp_optsget(struct socket *so, { struct sctp_pcbinfo *spcb; - if ((size_t)m->m_len < sizeof(struct sctp_pcbinfo)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_pcbinfo)) { error = EINVAL; break; } spcb = mtod(m, struct sctp_pcbinfo *); sctp_fill_pcbinfo(spcb); - m->m_len = sizeof(struct sctp_pcbinfo); + SCTP_BUF_LEN(m) = sizeof(struct sctp_pcbinfo); } break; case SCTP_STATUS: @@ -2798,7 +2791,7 @@ sctp_optsget(struct socket *so, struct sctp_nets *net; struct sctp_status *sstat; - if ((size_t)m->m_len < sizeof(struct sctp_status)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_status)) { error = EINVAL; break; } @@ -2852,14 +2845,14 @@ sctp_optsget(struct socket *so, sstat->sstat_primary.spinfo_mtu = net->mtu; sstat->sstat_primary.spinfo_assoc_id = sctp_get_associd(stcb); SCTP_TCB_UNLOCK(stcb); - m->m_len = sizeof(*sstat); + SCTP_BUF_LEN(m) = sizeof(*sstat); } break; case SCTP_RTOINFO: { struct sctp_rtoinfo *srto; - if ((size_t)m->m_len < sizeof(struct sctp_rtoinfo)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_rtoinfo)) { error = EINVAL; break; } @@ -2890,14 +2883,14 @@ sctp_optsget(struct socket *so, srto->srto_max = stcb->asoc.maxrto; srto->srto_min = stcb->asoc.minrto; SCTP_TCB_UNLOCK(stcb); - m->m_len = sizeof(*srto); + SCTP_BUF_LEN(m) = sizeof(*srto); } break; case SCTP_ASSOCINFO: { struct sctp_assocparams *sasoc; - if ((size_t)m->m_len < sizeof(struct sctp_assocparams)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_assocparams)) { error = EINVAL; break; } @@ -2938,14 +2931,14 @@ sctp_optsget(struct socket *so, sasoc->sasoc_cookie_life = inp->sctp_ep.def_cookie_life; SCTP_INP_RUNLOCK(inp); } - m->m_len = sizeof(*sasoc); + SCTP_BUF_LEN(m) = sizeof(*sasoc); } break; case SCTP_DEFAULT_SEND_PARAM: { struct sctp_sndrcvinfo *s_info; - if (m->m_len != sizeof(struct sctp_sndrcvinfo)) { + if (SCTP_BUF_LEN(m) != sizeof(struct sctp_sndrcvinfo)) { error = EINVAL; break; } @@ -2966,14 +2959,14 @@ sctp_optsget(struct socket *so, /* Copy it out */ *s_info = stcb->asoc.def_send; SCTP_TCB_UNLOCK(stcb); - m->m_len = sizeof(*s_info); + SCTP_BUF_LEN(m) = sizeof(*s_info); } break; case SCTP_INITMSG: { struct sctp_initmsg *sinit; - if ((size_t)m->m_len < sizeof(struct sctp_initmsg)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_initmsg)) { error = EINVAL; break; } @@ -2984,7 +2977,7 @@ sctp_optsget(struct socket *so, sinit->sinit_max_attempts = inp->sctp_ep.max_init_times; sinit->sinit_max_init_timeo = inp->sctp_ep.initial_init_rto_max; SCTP_INP_RUNLOCK(inp); - m->m_len = sizeof(*sinit); + SCTP_BUF_LEN(m) = sizeof(*sinit); } break; case SCTP_PRIMARY_ADDR: @@ -2992,7 +2985,7 @@ sctp_optsget(struct socket *so, { struct sctp_setprim *ssp; - if ((size_t)m->m_len < sizeof(struct sctp_setprim)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_setprim)) { error = EINVAL; break; } @@ -3030,7 +3023,7 @@ sctp_optsget(struct socket *so, &stcb->asoc.primary_destination->ro._l_addr, ((struct sockaddr *)&stcb->asoc.primary_destination->ro._l_addr)->sa_len); SCTP_TCB_UNLOCK(stcb); - m->m_len = sizeof(*ssp); + SCTP_BUF_LEN(m) = sizeof(*ssp); } break; @@ -3041,7 +3034,7 @@ sctp_optsget(struct socket *so, uint32_t size; int i; - if ((size_t)(m->m_len) < sizeof(*shmac)) { + if ((size_t)(SCTP_BUF_LEN(m)) < sizeof(*shmac)) { error = EINVAL; break; } @@ -3050,13 +3043,13 @@ sctp_optsget(struct socket *so, hmaclist = inp->sctp_ep.local_hmacs; if (hmaclist == NULL) { /* no HMACs to return */ - m->m_len = sizeof(*shmac); + SCTP_BUF_LEN(m) = sizeof(*shmac); break; } /* is there room for all of the hmac ids? */ size = sizeof(*shmac) + (hmaclist->num_algo * sizeof(shmac->shmac_idents[0])); - if ((size_t)(m->m_len) < size) { + if ((size_t)(SCTP_BUF_LEN(m)) < size) { error = EINVAL; SCTP_INP_RUNLOCK(inp); break; @@ -3065,14 +3058,14 @@ sctp_optsget(struct socket *so, for (i = 0; i < hmaclist->num_algo; i++) shmac->shmac_idents[i] = hmaclist->hmac[i]; SCTP_INP_RUNLOCK(inp); - m->m_len = size; + SCTP_BUF_LEN(m) = size; break; } case SCTP_AUTH_ACTIVE_KEY: { struct sctp_authkeyid *scact; - if ((size_t)(m->m_len) < sizeof(*scact)) { + if ((size_t)(SCTP_BUF_LEN(m)) < sizeof(*scact)) { error = EINVAL; break; } @@ -3104,7 +3097,7 @@ sctp_optsget(struct socket *so, scact->scact_keynumber = inp->sctp_ep.default_keyid; SCTP_INP_RUNLOCK(inp); } - m->m_len = sizeof(*scact); + SCTP_BUF_LEN(m) = sizeof(*scact); break; } case SCTP_LOCAL_AUTH_CHUNKS: @@ -3113,7 +3106,7 @@ sctp_optsget(struct socket *so, sctp_auth_chklist_t *chklist = NULL; int size = 0; - if ((size_t)(m->m_len) < sizeof(*sac)) { + if ((size_t)(SCTP_BUF_LEN(m)) < sizeof(*sac)) { error = EINVAL; break; } @@ -3145,7 +3138,7 @@ sctp_optsget(struct socket *so, } /* is there enough space? */ size = sctp_auth_get_chklist_size(chklist); - if ((size_t)m->m_len < (sizeof(struct sctp_authchunks) + size)) { + if ((size_t)SCTP_BUF_LEN(m) < (sizeof(struct sctp_authchunks) + size)) { error = EINVAL; SCTP_TCB_UNLOCK(stcb); break; @@ -3164,7 +3157,7 @@ sctp_optsget(struct socket *so, } /* is there enough space? */ size = sctp_auth_get_chklist_size(chklist); - if ((size_t)m->m_len < (sizeof(struct sctp_authchunks) + size)) { + if ((size_t)SCTP_BUF_LEN(m) < (sizeof(struct sctp_authchunks) + size)) { error = EINVAL; SCTP_INP_RUNLOCK(inp); break; @@ -3173,7 +3166,7 @@ sctp_optsget(struct socket *so, sctp_serialize_auth_chunks(chklist, sac->gauth_chunks); SCTP_INP_RUNLOCK(inp); } - m->m_len = sizeof(struct sctp_authchunks) + size; + SCTP_BUF_LEN(m) = sizeof(struct sctp_authchunks) + size; break; } case SCTP_PEER_AUTH_CHUNKS: @@ -3182,7 +3175,7 @@ sctp_optsget(struct socket *so, sctp_auth_chklist_t *chklist = NULL; int size = 0; - if ((size_t)(m->m_len) < sizeof(*sac)) { + if ((size_t)(SCTP_BUF_LEN(m)) < sizeof(*sac)) { error = EINVAL; break; } @@ -3213,7 +3206,7 @@ sctp_optsget(struct socket *so, } /* is there enough space? */ size = sctp_auth_get_chklist_size(chklist); - if ((size_t)m->m_len < (sizeof(struct sctp_authchunks) + size)) { + if ((size_t)SCTP_BUF_LEN(m) < (sizeof(struct sctp_authchunks) + size)) { error = EINVAL; SCTP_TCB_UNLOCK(stcb); break; @@ -3221,14 +3214,14 @@ sctp_optsget(struct socket *so, /* copy in the chunks */ sctp_serialize_auth_chunks(chklist, sac->gauth_chunks); SCTP_TCB_UNLOCK(stcb); - m->m_len = sizeof(struct sctp_authchunks) + size; + SCTP_BUF_LEN(m) = sizeof(struct sctp_authchunks) + size; break; } default: error = ENOPROTOOPT; - m->m_len = 0; + SCTP_BUF_LEN(m) = 0; break; } /* end switch (sopt->sopt_name) */ return (error); @@ -3268,7 +3261,7 @@ sctp_optsset(struct socket *so, case SCTP_USE_EXT_RCVINFO: case SCTP_I_WANT_MAPPED_V4_ADDR: /* copy in the option value */ - if ((size_t)m->m_len < sizeof(int)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(int)) { error = EINVAL; break; } @@ -3318,12 +3311,12 @@ sctp_optsset(struct socket *so, break; case SCTP_PARTIAL_DELIVERY_POINT: { - if ((size_t)m->m_len < sizeof(unsigned int)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(unsigned int)) { error = EINVAL; break; } inp->partial_delivery_point = *mtod(m, unsigned int *); - m->m_len = sizeof(unsigned int); + SCTP_BUF_LEN(m) = sizeof(unsigned int); } break; case SCTP_FRAGMENT_INTERLEAVE: @@ -3331,7 +3324,7 @@ sctp_optsset(struct socket *so, { int on_off; - if ((size_t)m->m_len < sizeof(int)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(int)) { error = EINVAL; break; } @@ -3347,7 +3340,7 @@ sctp_optsset(struct socket *so, { struct sctp_assoc_value *av; - if ((size_t)m->m_len < sizeof(struct sctp_assoc_value)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_assoc_value)) { error = EINVAL; break; } @@ -3371,7 +3364,7 @@ sctp_optsset(struct socket *so, break; case SCTP_CMT_USE_DAC: { - if ((size_t)m->m_len < sizeof(unsigned int)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(unsigned int)) { error = EINVAL; break; } @@ -3392,7 +3385,7 @@ sctp_optsset(struct socket *so, struct sctp_assoc_value *av; - if ((size_t)m->m_len < sizeof(struct sctp_assoc_value)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_assoc_value)) { error = EINVAL; break; } @@ -3414,7 +3407,7 @@ sctp_optsset(struct socket *so, { struct sctp_assoc_value *tm; - if ((size_t)m->m_len < sizeof(struct sctp_assoc_value)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_assoc_value)) { error = EINVAL; break; } @@ -3453,7 +3446,7 @@ sctp_optsset(struct socket *so, { struct sctp_authchunk *sauth; - if ((size_t)m->m_len < sizeof(*sauth)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(*sauth)) { error = EINVAL; break; } @@ -3471,7 +3464,7 @@ sctp_optsset(struct socket *so, sctp_key_t *key = NULL; int size; - size = m->m_len - sizeof(*sca); + size = SCTP_BUF_LEN(m) - sizeof(*sca); if (size < 0) { error = EINVAL; break; @@ -3564,7 +3557,7 @@ sctp_optsset(struct socket *so, uint32_t hmacid; int size, i; - size = m->m_len - sizeof(*shmac); + size = SCTP_BUF_LEN(m) - sizeof(*shmac); if (size < 0) { error = EINVAL; break; @@ -3598,7 +3591,7 @@ sctp_optsset(struct socket *so, { struct sctp_authkeyid *scact; - if ((size_t)m->m_len < sizeof(*scact)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(*scact)) { error = EINVAL; break; } @@ -3639,7 +3632,7 @@ sctp_optsset(struct socket *so, { struct sctp_authkeyid *scdel; - if ((size_t)m->m_len < sizeof(*scdel)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(*scdel)) { error = EINVAL; break; } @@ -3681,7 +3674,7 @@ sctp_optsset(struct socket *so, uint8_t send_in = 0, send_tsn = 0, send_out = 0; int i; - if ((size_t)m->m_len < sizeof(struct sctp_stream_reset)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_stream_reset)) { error = EINVAL; break; } @@ -3760,7 +3753,7 @@ sctp_optsset(struct socket *so, } break; case SCTP_CONNECT_X: - if ((size_t)m->m_len < (sizeof(int) + sizeof(struct sockaddr_in))) { + if ((size_t)SCTP_BUF_LEN(m) < (sizeof(int) + sizeof(struct sockaddr_in))) { error = EINVAL; break; } @@ -3768,7 +3761,7 @@ sctp_optsset(struct socket *so, break; case SCTP_CONNECT_X_DELAYED: - if ((size_t)m->m_len < (sizeof(int) + sizeof(struct sockaddr_in))) { + if ((size_t)SCTP_BUF_LEN(m) < (sizeof(int) + sizeof(struct sockaddr_in))) { error = EINVAL; break; } @@ -3780,7 +3773,7 @@ sctp_optsset(struct socket *so, struct sockaddr *sa; struct sctp_nets *net; - if ((size_t)m->m_len < sizeof(struct sockaddr_in)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sockaddr_in)) { error = EINVAL; break; } @@ -3863,7 +3856,7 @@ sctp_optsset(struct socket *so, { uint32_t *level; - if ((size_t)m->m_len < sizeof(uint32_t)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(uint32_t)) { error = EINVAL; break; } @@ -3883,7 +3876,7 @@ sctp_optsset(struct socket *so, { struct sctp_event_subscribe *events; - if ((size_t)m->m_len < sizeof(struct sctp_event_subscribe)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_event_subscribe)) { error = EINVAL; break; } @@ -3956,7 +3949,7 @@ sctp_optsset(struct socket *so, { struct sctp_setadaptation *adap_bits; - if ((size_t)m->m_len < sizeof(struct sctp_setadaptation)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_setadaptation)) { error = EINVAL; break; } @@ -3970,7 +3963,7 @@ sctp_optsset(struct socket *so, { uint32_t *vvv; - if ((size_t)m->m_len < sizeof(uint32_t)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(uint32_t)) { error = EINVAL; break; } @@ -3984,7 +3977,7 @@ sctp_optsset(struct socket *so, { struct sctp_sndrcvinfo *s_info; - if (m->m_len != sizeof(struct sctp_sndrcvinfo)) { + if (SCTP_BUF_LEN(m) != sizeof(struct sctp_sndrcvinfo)) { error = EINVAL; break; } @@ -4027,7 +4020,7 @@ sctp_optsset(struct socket *so, struct sctp_paddrparams *paddrp; struct sctp_nets *net; - if ((size_t)m->m_len < sizeof(struct sctp_paddrparams)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_paddrparams)) { error = EINVAL; break; } @@ -4112,7 +4105,7 @@ sctp_optsset(struct socket *so, net->dest_state &= ~SCTP_ADDR_NOHB; } if (paddrp->spp_flags & SPP_PMTUD_DISABLE) { - if (callout_pending(&net->pmtu_timer.timer)) { + if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) { sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10); } @@ -4123,7 +4116,7 @@ sctp_optsset(struct socket *so, } } if (paddrp->spp_flags & SPP_PMTUD_ENABLE) { - if (callout_pending(&net->pmtu_timer.timer)) { + if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) { sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net); } } @@ -4220,7 +4213,7 @@ sctp_optsset(struct socket *so, { struct sctp_rtoinfo *srto; - if ((size_t)m->m_len < sizeof(struct sctp_rtoinfo)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_rtoinfo)) { error = EINVAL; break; } @@ -4266,7 +4259,7 @@ sctp_optsset(struct socket *so, { struct sctp_assocparams *sasoc; - if ((size_t)m->m_len < sizeof(struct sctp_assocparams)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_assocparams)) { error = EINVAL; break; } @@ -4314,7 +4307,7 @@ sctp_optsset(struct socket *so, { struct sctp_initmsg *sinit; - if ((size_t)m->m_len < sizeof(struct sctp_initmsg)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_initmsg)) { error = EINVAL; break; } @@ -4343,7 +4336,7 @@ sctp_optsset(struct socket *so, struct sctp_setprim *spa; struct sctp_nets *net, *lnet; - if ((size_t)m->m_len < sizeof(struct sctp_setprim)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_setprim)) { error = EINVAL; break; } @@ -4405,7 +4398,7 @@ sctp_optsset(struct socket *so, { struct sctp_setpeerprim *sspp; - if ((size_t)m->m_len < sizeof(struct sctp_setpeerprim)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_setpeerprim)) { error = EINVAL; break; } @@ -4441,7 +4434,7 @@ sctp_optsset(struct socket *so, error = EINVAL; break; } - if ((size_t)m->m_len < sizeof(struct sctp_getaddresses)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_getaddresses)) { error = EINVAL; break; } @@ -4517,7 +4510,7 @@ sctp_optsset(struct socket *so, error = EINVAL; break; } - if ((size_t)m->m_len < sizeof(struct sctp_getaddresses)) { + if ((size_t)SCTP_BUF_LEN(m) < sizeof(struct sctp_getaddresses)) { error = EINVAL; break; } @@ -4606,7 +4599,7 @@ sctp_ctloutput(struct socket *so, struct sockopt *sopt) (void)sctp_m_free(m); goto out; } - m->m_len = sopt->sopt_valsize; + SCTP_BUF_LEN(m) = sopt->sopt_valsize; } if (sopt->sopt_dir == SOPT_SET) { error = sctp_optsset(so, sopt->sopt_name, &m, sopt->sopt_td); @@ -4616,7 +4609,7 @@ sctp_ctloutput(struct socket *so, struct sockopt *sopt) error = EINVAL; } if ((error == 0) && (m != NULL)) { - error = sooptcopyout(sopt, mtod(m, caddr_t), m->m_len); + error = sooptcopyout(sopt, mtod(m, caddr_t), SCTP_BUF_LEN(m)); sctp_m_freem(m); } else if (m != NULL) { sctp_m_freem(m); diff --git a/sys/netinet/sctp_var.h b/sys/netinet/sctp_var.h index 4461074..2293cb5 100644 --- a/sys/netinet/sctp_var.h +++ b/sys/netinet/sctp_var.h @@ -96,11 +96,12 @@ __FBSDID("$FreeBSD$"); #define SCTPCTL_ADD_MORE 47 #define SCTPCTL_SYS_RESC 48 #define SCTPCTL_ASOC_RESC 49 +#define SCTPCTL_NAT_FRIENDLY 50 #ifdef SCTP_DEBUG -#define SCTPCTL_DEBUG 50 -#define SCTPCTL_MAXID 50 +#define SCTPCTL_DEBUG 51 +#define SCTPCTL_MAXID 51 #else -#define SCTPCTL_MAXID 49 +#define SCTPCTL_MAXID 50 #endif #ifdef SCTP_DEBUG @@ -155,6 +156,7 @@ __FBSDID("$FreeBSD$"); { "add_more_on_output", CTLTYPE_INT }, \ { "sys_resource", CTLTYPE_INT }, \ { "asoc_resource", CTLTYPE_INT }, \ + { "nat_friendly", CTLTYPE_INT }, \ { "debug", CTLTYPE_INT }, \ } #else @@ -209,12 +211,12 @@ __FBSDID("$FreeBSD$"); { "add_more_on_output", CTLTYPE_INT }, \ { "sys_resource", CTLTYPE_INT }, \ { "asoc_resource", CTLTYPE_INT }, \ + { "nat_friendly", CTLTYPE_INT }, \ } #endif - #if defined(_KERNEL) #ifdef SYSCTL_DECL @@ -317,14 +319,12 @@ extern uint32_t sctp_system_free_resc_limit; - - #define sctp_free_remote_addr(__net) { \ if ((__net)) { \ if (atomic_fetchadd_int(&(__net)->ref_count, -1) == 1) { \ - callout_stop(&(__net)->rxt_timer.timer); \ - callout_stop(&(__net)->pmtu_timer.timer); \ - callout_stop(&(__net)->fr_timer.timer); \ + SCTP_OS_TIMER_STOP(&(__net)->rxt_timer.timer); \ + SCTP_OS_TIMER_STOP(&(__net)->pmtu_timer.timer); \ + SCTP_OS_TIMER_STOP(&(__net)->fr_timer.timer); \ (__net)->dest_state = SCTP_ADDR_NOT_REACHABLE; \ SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_net, (__net)); \ SCTP_DECR_RADDR_COUNT(); \ @@ -332,59 +332,58 @@ extern uint32_t sctp_system_free_resc_limit; } \ } - #define sctp_sbfree(ctl, stcb, sb, m) { \ uint32_t val; \ - val = atomic_fetchadd_int(&(sb)->sb_cc,-((m)->m_len)); \ - if(val < (m)->m_len) { \ + val = atomic_fetchadd_int(&(sb)->sb_cc,-(SCTP_BUF_LEN((m)))); \ + if(val < SCTP_BUF_LEN((m))) { \ panic("sb_cc goes negative"); \ } \ val = atomic_fetchadd_int(&(sb)->sb_mbcnt,-(MSIZE)); \ if(val < MSIZE) { \ panic("sb_mbcnt goes negative"); \ } \ - if ((m)->m_flags & M_EXT) { \ - val = atomic_fetchadd_int(&(sb)->sb_mbcnt,-((m)->m_ext.ext_size)); \ - if(val < (m)->m_ext.ext_size) { \ + if (SCTP_BUF_IS_EXTENDED(m)) { \ + val = atomic_fetchadd_int(&(sb)->sb_mbcnt,-(SCTP_BUF_EXTEND_SIZE(m))); \ + if(val < SCTP_BUF_EXTEND_SIZE(m)) { \ panic("sb_mbcnt goes negative2"); \ } \ } \ if (((ctl)->do_not_ref_stcb == 0) && stcb) {\ - val = atomic_fetchadd_int(&(stcb)->asoc.sb_cc,-((m)->m_len)); \ - if(val < (m)->m_len) {\ + val = atomic_fetchadd_int(&(stcb)->asoc.sb_cc,-(SCTP_BUF_LEN((m)))); \ + if(val < SCTP_BUF_LEN((m))) {\ panic("stcb->sb_cc goes negative"); \ } \ val = atomic_fetchadd_int(&(stcb)->asoc.sb_mbcnt,-(MSIZE)); \ if(val < MSIZE) { \ panic("asoc->mbcnt goes negative"); \ } \ - if ((m)->m_flags & M_EXT) { \ - val = atomic_fetchadd_int(&(stcb)->asoc.sb_mbcnt,-((m)->m_ext.ext_size)); \ - if(val < (m)->m_ext.ext_size) { \ + if (SCTP_BUF_IS_EXTENDED(m)) { \ + val = atomic_fetchadd_int(&(stcb)->asoc.sb_mbcnt,-(SCTP_BUF_EXTEND_SIZE(m))); \ + if(val < SCTP_BUF_EXTEND_SIZE(m)) { \ panic("assoc stcb->mbcnt would go negative"); \ } \ } \ } \ - if ((m)->m_type != MT_DATA && (m)->m_type != MT_HEADER && \ - (m)->m_type != MT_OOBDATA) \ - atomic_subtract_int(&(sb)->sb_ctl,(m)->m_len); \ + if (SCTP_BUF_TYPE(m) != MT_DATA && SCTP_BUF_TYPE(m) != MT_HEADER && \ + SCTP_BUF_TYPE(m) != MT_OOBDATA) \ + atomic_subtract_int(&(sb)->sb_ctl,SCTP_BUF_LEN((m))); \ } #define sctp_sballoc(stcb, sb, m) { \ - atomic_add_int(&(sb)->sb_cc,(m)->m_len); \ + atomic_add_int(&(sb)->sb_cc,SCTP_BUF_LEN((m))); \ atomic_add_int(&(sb)->sb_mbcnt, MSIZE); \ - if ((m)->m_flags & M_EXT) \ - atomic_add_int(&(sb)->sb_mbcnt,(m)->m_ext.ext_size); \ + if (SCTP_BUF_IS_EXTENDED(m)) \ + atomic_add_int(&(sb)->sb_mbcnt,SCTP_BUF_EXTEND_SIZE(m)); \ if(stcb) { \ - atomic_add_int(&(stcb)->asoc.sb_cc,(m)->m_len); \ + atomic_add_int(&(stcb)->asoc.sb_cc,SCTP_BUF_LEN((m))); \ atomic_add_int(&(stcb)->asoc.sb_mbcnt, MSIZE); \ - if ((m)->m_flags & M_EXT) \ - atomic_add_int(&(stcb)->asoc.sb_mbcnt,(m)->m_ext.ext_size); \ + if (SCTP_BUF_IS_EXTENDED(m)) \ + atomic_add_int(&(stcb)->asoc.sb_mbcnt,SCTP_BUF_EXTEND_SIZE(m)); \ } \ - if ((m)->m_type != MT_DATA && (m)->m_type != MT_HEADER && \ - (m)->m_type != MT_OOBDATA) \ - atomic_add_int(&(sb)->sb_ctl,(m)->m_len); \ + if (SCTP_BUF_TYPE(m) != MT_DATA && SCTP_BUF_TYPE(m) != MT_HEADER && \ + SCTP_BUF_TYPE(m) != MT_OOBDATA) \ + atomic_add_int(&(sb)->sb_ctl,SCTP_BUF_LEN((m))); \ } @@ -403,15 +402,18 @@ extern uint32_t sctp_system_free_resc_limit; #define sctp_mbuf_crush(data) do { \ struct mbuf *_m; \ _m = (data); \ - while(_m && (_m->m_len == 0)) { \ - (data) = _m->m_next; \ - _m->m_next = NULL; \ + while(_m && (SCTP_BUF_LEN(_m) == 0)) { \ + (data) = SCTP_BUF_NEXT(_m); \ + SCTP_BUF_NEXT(_m) = NULL; \ sctp_m_free(_m); \ _m = (data); \ } \ } while (0) +/* + * some sysctls + */ extern int sctp_sendspace; extern int sctp_recvspace; extern int sctp_ecn_enable; @@ -420,12 +422,13 @@ extern int sctp_use_cwnd_based_maxburst; extern unsigned int sctp_cmt_on_off; extern unsigned int sctp_cmt_use_dac; extern unsigned int sctp_cmt_sockopt_on_off; +extern uint32_t sctp_nat_friendly; + struct sctp_nets; struct sctp_inpcb; struct sctp_tcb; struct sctphdr; - void sctp_ctlinput __P((int, struct sockaddr *, void *)); int sctp_ctloutput __P((struct socket *, struct sockopt *)); void sctp_input __P((struct mbuf *, int)); @@ -450,11 +453,9 @@ __P((struct sctp_inpcb *, int, struct sctphdr *, /* can't use sctp_assoc_t here */ int sctp_peeloff(struct socket *, struct socket *, int, caddr_t, int *); - sctp_assoc_t sctp_getassocid(struct sockaddr *); - int sctp_ingetaddr(struct socket *, struct sockaddr ** ); @@ -465,12 +466,9 @@ __P((struct sctp_inpcb *, int, struct sctphdr *, int sctp_listen(struct socket *, int, struct thread *); - int sctp_accept(struct socket *, struct sockaddr **); - - #endif /* _KERNEL */ #endif /* !_NETINET_SCTP_VAR_H_ */ diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c index 18fe59d..6882cee 100644 --- a/sys/netinet/sctputil.c +++ b/sys/netinet/sctputil.c @@ -63,8 +63,6 @@ __FBSDID("$FreeBSD$"); #include <sys/uio.h> #include <sys/jail.h> -#include <sys/callout.h> - #include <net/radix.h> #include <net/route.h> @@ -300,12 +298,12 @@ sctp_log_mb(struct mbuf *m, int from) sctp_clog[sctp_cwnd_log_at].from = (uint8_t) from; sctp_clog[sctp_cwnd_log_at].event_type = (uint8_t) SCTP_LOG_EVENT_MBUF; sctp_clog[sctp_cwnd_log_at].x.mb.mp = m; - sctp_clog[sctp_cwnd_log_at].x.mb.mbuf_flags = (uint8_t) (m->m_flags); - sctp_clog[sctp_cwnd_log_at].x.mb.size = (uint16_t) (m->m_len); - sctp_clog[sctp_cwnd_log_at].x.mb.data = m->m_data; - if (m->m_flags & M_EXT) { - sctp_clog[sctp_cwnd_log_at].x.mb.ext = m->m_ext.ext_buf; - sctp_clog[sctp_cwnd_log_at].x.mb.refcnt = (uint8_t) (*m->m_ext.ref_cnt); + sctp_clog[sctp_cwnd_log_at].x.mb.mbuf_flags = (uint8_t) (SCTP_BUF_GET_FLAGS(m)); + sctp_clog[sctp_cwnd_log_at].x.mb.size = (uint16_t) (SCTP_BUF_LEN(m)); + sctp_clog[sctp_cwnd_log_at].x.mb.data = SCTP_BUF_AT(m, 0); + if (SCTP_BUF_IS_EXTENDED(m)) { + sctp_clog[sctp_cwnd_log_at].x.mb.ext = SCTP_BUF_EXTEND_BASE(m); + sctp_clog[sctp_cwnd_log_at].x.mb.refcnt = (uint8_t) (SCTP_BUF_EXTEND_REFCNT(m)); } else { sctp_clog[sctp_cwnd_log_at].x.mb.ext = 0; sctp_clog[sctp_cwnd_log_at].x.mb.refcnt = 0; @@ -567,7 +565,7 @@ sctp_fill_stat_log(struct mbuf *m) if (m == NULL) return (EINVAL); - size_limit = (m->m_len - sizeof(struct sctp_cwnd_log_req)); + size_limit = (SCTP_BUF_LEN(m) - sizeof(struct sctp_cwnd_log_req)); if (size_limit < sizeof(struct sctp_cwnd_log)) { return (EINVAL); } @@ -637,7 +635,7 @@ sctp_fill_stat_log(struct mbuf *m) if (at >= SCTP_STAT_LOG_SIZE) at = 0; } - m->m_len = (cnt_out * sizeof(struct sctp_cwnd_log)) + sizeof(struct sctp_cwnd_log_req); + SCTP_BUF_LEN(m) = (cnt_out * sizeof(struct sctp_cwnd_log)) + sizeof(struct sctp_cwnd_log_req); return (0); } @@ -875,15 +873,15 @@ sctp_stop_timers_for_shutdown(struct sctp_tcb *stcb) asoc = &stcb->asoc; - callout_stop(&asoc->hb_timer.timer); - callout_stop(&asoc->dack_timer.timer); - callout_stop(&asoc->strreset_timer.timer); - callout_stop(&asoc->asconf_timer.timer); - callout_stop(&asoc->autoclose_timer.timer); - callout_stop(&asoc->delayed_event_timer.timer); + SCTP_OS_TIMER_STOP(&asoc->hb_timer.timer); + SCTP_OS_TIMER_STOP(&asoc->dack_timer.timer); + SCTP_OS_TIMER_STOP(&asoc->strreset_timer.timer); + SCTP_OS_TIMER_STOP(&asoc->asconf_timer.timer); + SCTP_OS_TIMER_STOP(&asoc->autoclose_timer.timer); + SCTP_OS_TIMER_STOP(&asoc->delayed_event_timer.timer); TAILQ_FOREACH(net, &asoc->nets, sctp_next) { - callout_stop(&net->fr_timer.timer); - callout_stop(&net->pmtu_timer.timer); + SCTP_OS_TIMER_STOP(&net->fr_timer.timer); + SCTP_OS_TIMER_STOP(&net->pmtu_timer.timer); } } @@ -935,7 +933,7 @@ sctp_select_initial_TSN(struct sctp_pcb *m) * the initial stream sequence number, using RFC1750 as a good * guideline */ - u_long x, *xp; + uint32_t x, *xp; uint8_t *p; if (m->initial_sequence_debug != 0) { @@ -950,9 +948,9 @@ sctp_select_initial_TSN(struct sctp_pcb *m) sctp_fill_random_store(m); } p = &m->random_store[(int)m->store_at]; - xp = (u_long *)p; + xp = (uint32_t *) p; x = *xp; - m->store_at += sizeof(u_long); + m->store_at += sizeof(uint32_t); return (x); } @@ -1015,6 +1013,7 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_association *asoc, if (override_tag) { struct timeval now; + SCTP_GETTIME_TIMEVAL(&now); if (sctp_is_vtag_good(m, override_tag, &now)) { asoc->my_vtag = override_tag; } else { @@ -1319,7 +1318,7 @@ sctp_timeout_handler(void *t) printf("Timer type %d goes off\n", tmr->type); } #endif /* SCTP_DEBUG */ - if (!callout_active(&tmr->timer)) { + if (!SCTP_OS_TIMER_ACTIVE(&tmr->timer)) { splx(s); if (inp) { SCTP_INP_DECR_REF(inp); @@ -1336,7 +1335,7 @@ sctp_timeout_handler(void *t) atomic_add_int(&stcb->asoc.refcnt, -1); } /* mark as being serviced now */ - callout_deactivate(&tmr->timer); + SCTP_OS_TIMER_DEACTIVATE(&tmr->timer); /* call the handler for the appropriate timer type */ switch (tmr->type) { @@ -1602,9 +1601,7 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb, int to_ticks; struct sctp_timer *tmr; - - if ((t_type != SCTP_TIMER_TYPE_ADDR_WQ) && - (inp == NULL)) + if ((t_type != SCTP_TIMER_TYPE_ADDR_WQ) && (inp == NULL)) return (EFAULT); to_ticks = 0; @@ -1929,7 +1926,7 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb, #endif /* SCTP_DEBUG */ return (EFAULT); } - if (callout_pending(&tmr->timer)) { + if (SCTP_OS_TIMER_PENDING(&tmr->timer)) { /* * we do NOT allow you to have it already running. if it is * we leave the current one up unchanged @@ -1947,7 +1944,7 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb, tmr->net = (void *)net; tmr->self = (void *)tmr; tmr->ticks = ticks; - callout_reset(&tmr->timer, to_ticks, sctp_timeout_handler, tmr); + SCTP_OS_TIMER_START(&tmr->timer, to_ticks, sctp_timeout_handler, tmr); return (0); } @@ -2111,7 +2108,7 @@ sctp_timer_stop(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb, } tmr->self = NULL; tmr->stopped_from = from; - callout_stop(&tmr->timer); + SCTP_OS_TIMER_STOP(&tmr->timer); return (0); } @@ -2165,8 +2162,8 @@ sctp_calculate_len(struct mbuf *m) at = m; while (at) { - tlen += at->m_len; - at = at->m_next; + tlen += SCTP_BUF_LEN(at); + at = SCTP_BUF_NEXT(at); } return (tlen); } @@ -2179,11 +2176,11 @@ sctp_calculate_sum(struct mbuf *m, int32_t * pktlen, uint32_t offset) /* * given a mbuf chain with a packetheader offset by 'offset' * pointing at a sctphdr (with csum set to 0) go through the chain - * of m_next's and calculate the SCTP checksum. This is currently - * Adler32 but will change to CRC32x soon. Also has a side bonus - * calculate the total length of the mbuf chain. Note: if offset is - * greater than the total mbuf length, checksum=1, pktlen=0 is - * returned (ie. no real error code) + * of SCTP_BUF_NEXT()'s and calculate the SCTP checksum. This is + * currently Adler32 but will change to CRC32x soon. Also has a side + * bonus calculate the total length of the mbuf chain. Note: if + * offset is greater than the total mbuf length, checksum=1, + * pktlen=0 is returned (ie. no real error code) */ if (pktlen == NULL) return (0); @@ -2201,11 +2198,11 @@ sctp_calculate_sum(struct mbuf *m, int32_t * pktlen, uint32_t offset) /* * given a mbuf chain with a packetheader offset by 'offset' * pointing at a sctphdr (with csum set to 0) go through the chain - * of m_next's and calculate the SCTP checksum. This is currently - * Adler32 but will change to CRC32x soon. Also has a side bonus - * calculate the total length of the mbuf chain. Note: if offset is - * greater than the total mbuf length, checksum=1, pktlen=0 is - * returned (ie. no real error code) + * of SCTP_BUF_NEXT()'s and calculate the SCTP checksum. This is + * currently Adler32 but will change to CRC32x soon. Also has a side + * bonus calculate the total length of the mbuf chain. Note: if + * offset is greater than the total mbuf length, checksum=1, + * pktlen=0 is returned (ie. no real error code) */ int32_t tlen = 0; struct mbuf *at; @@ -2213,8 +2210,8 @@ sctp_calculate_sum(struct mbuf *m, int32_t * pktlen, uint32_t offset) at = m; while (at) { - tlen += at->m_len; - at = at->m_next; + tlen += SCTP_BUF_LEN(at); + at = SCTP_BUF_NEXT(at); } the_sum = (uint32_t) (in_cksum_skip(m, tlen, offset)); if (pktlen != NULL) @@ -2231,11 +2228,11 @@ sctp_calculate_sum(struct mbuf *m, int32_t * pktlen, uint32_t offset) /* * given a mbuf chain with a packetheader offset by 'offset' * pointing at a sctphdr (with csum set to 0) go through the chain - * of m_next's and calculate the SCTP checksum. This is currently - * Adler32 but will change to CRC32x soon. Also has a side bonus - * calculate the total length of the mbuf chain. Note: if offset is - * greater than the total mbuf length, checksum=1, pktlen=0 is - * returned (ie. no real error code) + * of SCTP_BUF_NEXT()'s and calculate the SCTP checksum. This is + * currently Adler32 but will change to CRC32x soon. Also has a side + * bonus calculate the total length of the mbuf chain. Note: if + * offset is greater than the total mbuf length, checksum=1, + * pktlen=0 is returned (ie. no real error code) */ int32_t tlen = 0; @@ -2250,38 +2247,39 @@ sctp_calculate_sum(struct mbuf *m, int32_t * pktlen, uint32_t offset) at = m; /* find the correct mbuf and offset into mbuf */ - while ((at != NULL) && (offset > (uint32_t) at->m_len)) { - offset -= at->m_len; /* update remaining offset left */ - at = at->m_next; + while ((at != NULL) && (offset > (uint32_t) SCTP_BUF_LEN(at))) { + offset -= SCTP_BUF_LEN(at); /* update remaining offset + * left */ + at = SCTP_BUF_NEXT(at); } while (at != NULL) { - if ((at->m_len - offset) > 0) { + if ((SCTP_BUF_LEN(at) - offset) > 0) { #ifdef SCTP_USE_ADLER32 base = update_adler32(base, - (unsigned char *)(at->m_data + offset), - (unsigned int)(at->m_len - offset)); + (unsigned char *)(SCTP_BUF_AT(at, offset)), + (unsigned int)(SCTP_BUF_LEN(at) - offset)); #else - if ((at->m_len - offset) < 4) { + if ((SCTP_BUF_LEN(at) - offset) < 4) { /* Use old method if less than 4 bytes */ base = old_update_crc32(base, - (unsigned char *)(at->m_data + offset), - (unsigned int)(at->m_len - offset)); + (unsigned char *)(SCTP_BUF_AT(at, offset)), + (unsigned int)(SCTP_BUF_LEN(at) - offset)); } else { base = update_crc32(base, - (unsigned char *)(at->m_data + offset), - (unsigned int)(at->m_len - offset)); + (unsigned char *)(SCTP_BUF_AT(at, offset)), + (unsigned int)(SCTP_BUF_LEN(at) - offset)); } #endif /* SCTP_USE_ADLER32 */ - tlen += at->m_len - offset; + tlen += SCTP_BUF_LEN(at) - offset; /* we only offset once into the first mbuf */ } if (offset) { - if (offset < at->m_len) + if (offset < SCTP_BUF_LEN(at)) offset = 0; else - offset -= at->m_len; + offset -= SCTP_BUF_LEN(at); } - at = at->m_next; + at = SCTP_BUF_NEXT(at); } if (pktlen != NULL) { *pktlen = tlen; @@ -2471,26 +2469,26 @@ sctp_m_getptr(struct mbuf *m, int off, int len, uint8_t * in_ptr) /* find the desired start location */ while ((m != NULL) && (off > 0)) { - if (off < m->m_len) + if (off < SCTP_BUF_LEN(m)) break; - off -= m->m_len; - m = m->m_next; + off -= SCTP_BUF_LEN(m); + m = SCTP_BUF_NEXT(m); } if (m == NULL) return (NULL); /* is the current mbuf large enough (eg. contiguous)? */ - if ((m->m_len - off) >= len) { + if ((SCTP_BUF_LEN(m) - off) >= len) { return (mtod(m, caddr_t)+off); } else { /* else, it spans more than one mbuf, so save a temp copy... */ while ((m != NULL) && (len > 0)) { - count = min(m->m_len - off, len); + count = min(SCTP_BUF_LEN(m) - off, len); bcopy(mtod(m, caddr_t)+off, ptr, count); len -= count; ptr += count; off = 0; - m = m->m_next; + m = SCTP_BUF_NEXT(m); } if ((m == NULL) && (len > 0)) return (NULL); @@ -2530,8 +2528,8 @@ sctp_add_pad_tombuf(struct mbuf *m, int padlen) * The easy way. We hope the majority of the time we hit * here :) */ - dp = (uint8_t *) (mtod(m, caddr_t)+m->m_len); - m->m_len += padlen; + dp = (uint8_t *) (mtod(m, caddr_t)+SCTP_BUF_LEN(m)); + SCTP_BUF_LEN(m) += padlen; } else { /* Hard way we must grow the mbuf */ struct mbuf *tmp; @@ -2542,9 +2540,9 @@ sctp_add_pad_tombuf(struct mbuf *m, int padlen) return (ENOSPC); } /* setup and insert in middle */ - tmp->m_next = m->m_next; - tmp->m_len = padlen; - m->m_next = tmp; + SCTP_BUF_NEXT(tmp) = SCTP_BUF_NEXT(m); + SCTP_BUF_LEN(tmp) = padlen; + SCTP_BUF_NEXT(m) = tmp; dp = mtod(tmp, uint8_t *); } /* zero out the pad */ @@ -2566,10 +2564,10 @@ sctp_pad_lastmbuf(struct mbuf *m, int padval, struct mbuf *last_mbuf) return (sctp_add_pad_tombuf(last_mbuf, padval)); } else { while (m_at) { - if (m_at->m_next == NULL) { + if (SCTP_BUF_NEXT(m_at) == NULL) { return (sctp_add_pad_tombuf(m_at, padval)); } - m_at = m_at->m_next; + m_at = SCTP_BUF_NEXT(m_at); } } return (EFAULT); @@ -2616,11 +2614,11 @@ sctp_notify_assoc_change(uint32_t event, struct sctp_tcb *stcb, /* event not enabled */ return; } - m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_assoc_change), 1, M_DONTWAIT, 1, MT_DATA); + m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_assoc_change), 0, M_DONTWAIT, 1, MT_DATA); if (m_notify == NULL) /* no space left */ return; - m_notify->m_len = 0; + SCTP_BUF_LEN(m_notify) = 0; sac = mtod(m_notify, struct sctp_assoc_change *); sac->sac_type = SCTP_ASSOC_CHANGE; @@ -2632,11 +2630,8 @@ sctp_notify_assoc_change(uint32_t event, struct sctp_tcb *stcb, sac->sac_outbound_streams = stcb->asoc.streamoutcnt; sac->sac_inbound_streams = stcb->asoc.streamincnt; sac->sac_assoc_id = sctp_get_associd(stcb); - m_notify->m_flags |= M_EOR | M_NOTIFICATION; - m_notify->m_pkthdr.len = sizeof(struct sctp_assoc_change); - m_notify->m_pkthdr.rcvif = 0; - m_notify->m_len = sizeof(struct sctp_assoc_change); - m_notify->m_next = NULL; + SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_assoc_change); + SCTP_BUF_NEXT(m_notify) = NULL; control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 0, 0, 0, 0, 0, 0, m_notify); @@ -2645,9 +2640,10 @@ sctp_notify_assoc_change(uint32_t event, struct sctp_tcb *stcb, sctp_m_freem(m_notify); return; } - control->length = m_notify->m_len; + control->length = SCTP_BUF_LEN(m_notify); /* 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); @@ -2669,10 +2665,10 @@ sctp_notify_peer_addr_change(struct sctp_tcb *stcb, uint32_t state, /* event not enabled */ return; - m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_paddr_change), 1, M_DONTWAIT, 1, MT_DATA); + m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_paddr_change), 0, M_DONTWAIT, 1, MT_DATA); if (m_notify == NULL) return; - m_notify->m_len = 0; + SCTP_BUF_LEN(m_notify) = 0; spc = mtod(m_notify, struct sctp_paddr_change *); spc->spc_type = SCTP_PEER_ADDR_CHANGE; spc->spc_flags = 0; @@ -2686,11 +2682,8 @@ sctp_notify_peer_addr_change(struct sctp_tcb *stcb, uint32_t state, spc->spc_error = error; spc->spc_assoc_id = sctp_get_associd(stcb); - m_notify->m_flags |= M_EOR | M_NOTIFICATION; - m_notify->m_pkthdr.len = sizeof(struct sctp_paddr_change); - m_notify->m_pkthdr.rcvif = 0; - m_notify->m_len = sizeof(struct sctp_paddr_change); - m_notify->m_next = NULL; + SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_paddr_change); + SCTP_BUF_NEXT(m_notify) = NULL; /* append to socket */ control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, @@ -2701,7 +2694,8 @@ sctp_notify_peer_addr_change(struct sctp_tcb *stcb, uint32_t state, sctp_m_freem(m_notify); return; } - control->length = m_notify->m_len; + 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, @@ -2724,11 +2718,11 @@ sctp_notify_send_failed(struct sctp_tcb *stcb, uint32_t error, return; length = sizeof(struct sctp_send_failed) + chk->send_size; - m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_send_failed), 1, M_DONTWAIT, 1, MT_DATA); + m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_send_failed), 0, M_DONTWAIT, 1, MT_DATA); if (m_notify == NULL) /* no space left */ return; - m_notify->m_len = 0; + SCTP_BUF_LEN(m_notify) = 0; ssf = mtod(m_notify, struct sctp_send_failed *); ssf->ssf_type = SCTP_SEND_FAILED; if (error == SCTP_NOTIFY_DATAGRAM_UNSENT) @@ -2745,11 +2739,8 @@ sctp_notify_send_failed(struct sctp_tcb *stcb, uint32_t error, ssf->ssf_info.sinfo_context = chk->rec.data.context; ssf->ssf_info.sinfo_assoc_id = sctp_get_associd(stcb); ssf->ssf_assoc_id = sctp_get_associd(stcb); - m_notify->m_next = chk->data; - m_notify->m_flags |= M_NOTIFICATION; - m_notify->m_pkthdr.len = length; - m_notify->m_pkthdr.rcvif = 0; - m_notify->m_len = sizeof(struct sctp_send_failed); + SCTP_BUF_NEXT(m_notify) = chk->data; + SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed); /* Steal off the mbuf */ chk->data = NULL; @@ -2758,7 +2749,7 @@ sctp_notify_send_failed(struct sctp_tcb *stcb, uint32_t error, * is going away we don't want to overfill the socket buffer for a * non-reader */ - if (sctp_sbspace_failedmsgs(&stcb->sctp_socket->so_rcv) < m_notify->m_len) { + if (sctp_sbspace_failedmsgs(&stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) { sctp_m_freem(m_notify); return; } @@ -2771,6 +2762,7 @@ sctp_notify_send_failed(struct sctp_tcb *stcb, uint32_t error, sctp_m_freem(m_notify); return; } + control->spec_flags = M_NOTIFICATION; sctp_add_to_readq(stcb->sctp_ep, stcb, control, &stcb->sctp_socket->so_rcv, 1); @@ -2791,11 +2783,11 @@ sctp_notify_send_failed2(struct sctp_tcb *stcb, uint32_t error, return; length = sizeof(struct sctp_send_failed) + sp->length; - m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_adaption_event), 1, M_DONTWAIT, 1, MT_DATA); + m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_adaption_event), 0, M_DONTWAIT, 1, MT_DATA); if (m_notify == NULL) /* no space left */ return; - m_notify->m_len = 0; + SCTP_BUF_LEN(m_notify) = 0; ssf = mtod(m_notify, struct sctp_send_failed *); ssf->ssf_type = SCTP_SEND_FAILED; if (error == SCTP_NOTIFY_DATAGRAM_UNSENT) @@ -2812,11 +2804,8 @@ sctp_notify_send_failed2(struct sctp_tcb *stcb, uint32_t error, ssf->ssf_info.sinfo_context = sp->context; ssf->ssf_info.sinfo_assoc_id = sctp_get_associd(stcb); ssf->ssf_assoc_id = sctp_get_associd(stcb); - m_notify->m_next = sp->data; - m_notify->m_flags |= M_NOTIFICATION; - m_notify->m_pkthdr.len = length; - m_notify->m_pkthdr.rcvif = 0; - m_notify->m_len = sizeof(struct sctp_send_failed); + SCTP_BUF_NEXT(m_notify) = sp->data; + SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed); /* Steal off the mbuf */ sp->data = NULL; @@ -2825,7 +2814,7 @@ sctp_notify_send_failed2(struct sctp_tcb *stcb, uint32_t error, * is going away we don't want to overfill the socket buffer for a * non-reader */ - if (sctp_sbspace_failedmsgs(&stcb->sctp_socket->so_rcv) < m_notify->m_len) { + if (sctp_sbspace_failedmsgs(&stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) { sctp_m_freem(m_notify); return; } @@ -2838,6 +2827,7 @@ sctp_notify_send_failed2(struct sctp_tcb *stcb, uint32_t error, sctp_m_freem(m_notify); return; } + control->spec_flags = M_NOTIFICATION; sctp_add_to_readq(stcb->sctp_ep, stcb, control, &stcb->sctp_socket->so_rcv, 1); @@ -2857,11 +2847,11 @@ sctp_notify_adaptation_layer(struct sctp_tcb *stcb, /* event not enabled */ return; - m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_adaption_event), 1, M_DONTWAIT, 1, MT_DATA); + m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_adaption_event), 0, M_DONTWAIT, 1, MT_DATA); if (m_notify == NULL) /* no space left */ return; - m_notify->m_len = 0; + SCTP_BUF_LEN(m_notify) = 0; sai = mtod(m_notify, struct sctp_adaptation_event *); sai->sai_type = SCTP_ADAPTATION_INDICATION; sai->sai_flags = 0; @@ -2869,11 +2859,8 @@ sctp_notify_adaptation_layer(struct sctp_tcb *stcb, sai->sai_adaptation_ind = error; sai->sai_assoc_id = sctp_get_associd(stcb); - m_notify->m_flags |= M_EOR | M_NOTIFICATION; - m_notify->m_pkthdr.len = sizeof(struct sctp_adaptation_event); - m_notify->m_pkthdr.rcvif = 0; - m_notify->m_len = sizeof(struct sctp_adaptation_event); - m_notify->m_next = NULL; + SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_adaptation_event); + SCTP_BUF_NEXT(m_notify) = NULL; /* append to socket */ control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, @@ -2884,7 +2871,8 @@ sctp_notify_adaptation_layer(struct sctp_tcb *stcb, sctp_m_freem(m_notify); return; } - control->length = m_notify->m_len; + 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, @@ -2906,11 +2894,11 @@ sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb, /* event not enabled */ return; - m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_pdapi_event), 1, M_DONTWAIT, 1, MT_DATA); + m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_pdapi_event), 0, M_DONTWAIT, 1, MT_DATA); if (m_notify == NULL) /* no space left */ return; - m_notify->m_len = 0; + SCTP_BUF_LEN(m_notify) = 0; pdapi = mtod(m_notify, struct sctp_pdapi_event *); pdapi->pdapi_type = SCTP_PARTIAL_DELIVERY_EVENT; pdapi->pdapi_flags = 0; @@ -2918,11 +2906,8 @@ sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb, pdapi->pdapi_indication = error; pdapi->pdapi_assoc_id = sctp_get_associd(stcb); - m_notify->m_flags |= M_EOR | M_NOTIFICATION; - m_notify->m_pkthdr.len = sizeof(struct sctp_pdapi_event); - m_notify->m_pkthdr.rcvif = 0; - m_notify->m_len = sizeof(struct sctp_pdapi_event); - m_notify->m_next = NULL; + SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_pdapi_event); + SCTP_BUF_NEXT(m_notify) = NULL; control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 0, 0, 0, 0, 0, 0, m_notify); @@ -2931,7 +2916,8 @@ sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb, sctp_m_freem(m_notify); return; } - control->length = m_notify->m_len; + control->spec_flags = M_NOTIFICATION; + control->length = SCTP_BUF_LEN(m_notify); /* not that we need this */ control->tail_mbuf = m_notify; control->held_length = 0; @@ -2941,13 +2927,13 @@ sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb, } sb = &stcb->sctp_socket->so_rcv; #ifdef SCTP_SB_LOGGING - sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBALLOC, m_notify->m_len); + sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBALLOC, SCTP_BUF_LEN(m_notify)); #endif sctp_sballoc(stcb, sb, m_notify); #ifdef SCTP_SB_LOGGING sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBRESULT, 0); #endif - atomic_add_int(&control->length, m_notify->m_len); + 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); @@ -2984,22 +2970,18 @@ sctp_notify_shutdown_event(struct sctp_tcb *stcb) /* event not enabled */ return; - m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_shutdown_event), 1, M_DONTWAIT, 1, MT_DATA); + m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_shutdown_event), 0, M_DONTWAIT, 1, MT_DATA); if (m_notify == NULL) /* no space left */ return; - m_notify->m_len = 0; sse = mtod(m_notify, struct sctp_shutdown_event *); sse->sse_type = SCTP_SHUTDOWN_EVENT; sse->sse_flags = 0; sse->sse_length = sizeof(struct sctp_shutdown_event); sse->sse_assoc_id = sctp_get_associd(stcb); - m_notify->m_flags |= M_EOR | M_NOTIFICATION; - m_notify->m_pkthdr.len = sizeof(struct sctp_shutdown_event); - m_notify->m_pkthdr.rcvif = 0; - m_notify->m_len = sizeof(struct sctp_shutdown_event); - m_notify->m_next = NULL; + SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_shutdown_event); + SCTP_BUF_NEXT(m_notify) = NULL; /* append to socket */ control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, @@ -3010,7 +2992,8 @@ sctp_notify_shutdown_event(struct sctp_tcb *stcb) sctp_m_freem(m_notify); return; } - control->length = m_notify->m_len; + control->spec_flags = M_NOTIFICATION; + control->length = SCTP_BUF_LEN(m_notify); /* not that we need this */ control->tail_mbuf = m_notify; sctp_add_to_readq(stcb->sctp_ep, stcb, @@ -3031,11 +3014,11 @@ sctp_notify_stream_reset(struct sctp_tcb *stcb, /* event not enabled */ return; - m_notify = sctp_get_mbuf_for_msg(MCLBYTES, 1, M_DONTWAIT, 1, MT_DATA); + m_notify = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_DONTWAIT, 1, MT_DATA); if (m_notify == NULL) /* no space left */ return; - m_notify->m_len = 0; + SCTP_BUF_LEN(m_notify) = 0; len = sizeof(struct sctp_stream_reset_event) + (number_entries * sizeof(uint16_t)); if (len > M_TRAILINGSPACE(m_notify)) { /* never enough room */ @@ -3058,12 +3041,9 @@ sctp_notify_stream_reset(struct sctp_tcb *stcb, strreset->strreset_list[i] = ntohs(list[i]); } } - m_notify->m_flags |= M_EOR | M_NOTIFICATION; - m_notify->m_pkthdr.len = len; - m_notify->m_pkthdr.rcvif = 0; - m_notify->m_len = len; - m_notify->m_next = NULL; - if (sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv) < m_notify->m_len) { + SCTP_BUF_LEN(m_notify) = len; + SCTP_BUF_NEXT(m_notify) = NULL; + if (sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) { /* no space */ sctp_m_freem(m_notify); return; @@ -3077,7 +3057,8 @@ sctp_notify_stream_reset(struct sctp_tcb *stcb, sctp_m_freem(m_notify); return; } - control->length = m_notify->m_len; + control->spec_flags = M_NOTIFICATION; + control->length = SCTP_BUF_LEN(m_notify); /* not that we need this */ control->tail_mbuf = m_notify; sctp_add_to_readq(stcb->sctp_ep, stcb, @@ -3669,7 +3650,7 @@ sctp_print_address_pkt(struct ip *iph, struct sctphdr *sh) #define SCTP_SBLINKRECORD(sb, m0) do { \ if ((sb)->sb_lastrecord != NULL) \ - (sb)->sb_lastrecord->m_nextpkt = (m0); \ + SCTP_BUF_NEXT_PKT((sb)->sb_lastrecord) = (m0); \ else \ (sb)->sb_mb = (m0); \ (sb)->sb_lastrecord = (m0); \ @@ -3725,13 +3706,13 @@ sctp_pull_off_control_to_new_inp(struct sctp_inpcb *old_inp, m = control->data; while (m) { #ifdef SCTP_SB_LOGGING - sctp_sblog(&old_so->so_rcv, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBFREE, m->m_len); + sctp_sblog(&old_so->so_rcv, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBFREE, SCTP_BUF_LEN(m)); #endif sctp_sbfree(control, stcb, &old_so->so_rcv, m); #ifdef SCTP_SB_LOGGING sctp_sblog(&old_so->so_rcv, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBRESULT, 0); #endif - m = m->m_next; + m = SCTP_BUF_NEXT(m); } } control = nctl; @@ -3753,13 +3734,13 @@ sctp_pull_off_control_to_new_inp(struct sctp_inpcb *old_inp, m = control->data; while (m) { #ifdef SCTP_SB_LOGGING - sctp_sblog(&new_so->so_rcv, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBALLOC, m->m_len); + sctp_sblog(&new_so->so_rcv, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBALLOC, SCTP_BUF_LEN(m)); #endif sctp_sballoc(stcb, &new_so->so_rcv, m); #ifdef SCTP_SB_LOGGING sctp_sblog(&new_so->so_rcv, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBRESULT, 0); #endif - m = m->m_next; + m = SCTP_BUF_NEXT(m); } control = nctl; } @@ -3795,15 +3776,15 @@ sctp_add_to_readq(struct sctp_inpcb *inp, control->held_length = 0; control->length = 0; while (m) { - if (m->m_len == 0) { + if (SCTP_BUF_LEN(m) == 0) { /* Skip mbufs with NO length */ if (prev == NULL) { /* First one */ control->data = sctp_m_free(m); m = control->data; } else { - prev->m_next = sctp_m_free(m); - m = prev->m_next; + SCTP_BUF_NEXT(prev) = sctp_m_free(m); + m = SCTP_BUF_NEXT(prev); } if (m == NULL) { control->tail_mbuf = prev;; @@ -3812,21 +3793,19 @@ sctp_add_to_readq(struct sctp_inpcb *inp, } prev = m; #ifdef SCTP_SB_LOGGING - sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBALLOC, m->m_len); + sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBALLOC, SCTP_BUF_LEN(m)); #endif sctp_sballoc(stcb, sb, m); #ifdef SCTP_SB_LOGGING sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBRESULT, 0); #endif - atomic_add_int(&control->length, m->m_len); - m = m->m_next; + atomic_add_int(&control->length, SCTP_BUF_LEN(m)); + m = SCTP_BUF_NEXT(m); } if (prev != NULL) { control->tail_mbuf = prev; - if (end) { - prev->m_flags |= M_EOR; - } } else { + /* Everything got collapsed out?? */ return; } if (end) { @@ -3871,8 +3850,7 @@ get_out: } return (-1); } - if ((control->tail_mbuf) && - (control->tail_mbuf->m_flags & M_EOR)) { + if (control->end_added) { /* huh this one is complete? */ goto get_out; } @@ -3881,30 +3859,30 @@ get_out: goto get_out; } while (mm) { - if (mm->m_len == 0) { + if (SCTP_BUF_LEN(mm) == 0) { /* Skip mbufs with NO lenght */ if (prev == NULL) { /* First one */ m = sctp_m_free(mm); mm = m; } else { - prev->m_next = sctp_m_free(mm); - mm = prev->m_next; + SCTP_BUF_NEXT(prev) = sctp_m_free(mm); + mm = SCTP_BUF_NEXT(prev); } continue; } prev = mm; - len += mm->m_len; + len += SCTP_BUF_LEN(mm); if (sb) { #ifdef SCTP_SB_LOGGING - sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBALLOC, mm->m_len); + sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBALLOC, SCTP_BUF_LEN(mm)); #endif sctp_sballoc(stcb, sb, mm); #ifdef SCTP_SB_LOGGING sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBRESULT, 0); #endif } - mm = mm->m_next; + mm = SCTP_BUF_NEXT(mm); } if (prev) { tail = prev; @@ -3922,7 +3900,6 @@ get_out: } if (end) { /* message is complete */ - tail->m_flags |= M_EOR; if (control == stcb->asoc.control_pdapi) { stcb->asoc.control_pdapi = NULL; } @@ -3932,7 +3909,7 @@ get_out: atomic_add_int(&control->length, len); if (control->tail_mbuf) { /* append */ - control->tail_mbuf->m_next = m; + SCTP_BUF_NEXT(control->tail_mbuf) = m; control->tail_mbuf = tail; } else { /* nothing there */ @@ -3980,7 +3957,7 @@ sctp_generate_invmanparam(int err) if (m) { struct sctp_paramhdr *ph; - m->m_len = sizeof(struct sctp_paramhdr); + SCTP_BUF_LEN(m) = sizeof(struct sctp_paramhdr); ph = mtod(m, struct sctp_paramhdr *); ph->param_length = htons(sizeof(struct sctp_paramhdr)); ph->param_type = htons(err); @@ -4147,13 +4124,6 @@ sctp_find_ifa_by_addr(struct sockaddr *sa) return (NULL); } - - - - - - - static void sctp_user_rcvd(struct sctp_tcb *stcb, int *freed_so_far, int hold_rlock, uint32_t rwnd_req) @@ -4463,13 +4433,12 @@ restart_nosblocks: m = control->data; while (m) { - cnt += m->m_len; - if (m->m_next == NULL) { + cnt += SCTP_BUF_LEN(m); + if (SCTP_BUF_NEXT(m) == NULL) { control->tail_mbuf = m; - m->m_flags |= M_EOR; control->end_added = 1; } - m = m->m_next; + m = SCTP_BUF_NEXT(m); } control->length = cnt; } else { @@ -4572,7 +4541,7 @@ found_one: s_extra->next_ppid = nxt->sinfo_ppid; s_extra->next_stream = nxt->sinfo_stream; if (nxt->tail_mbuf != NULL) { - if (nxt->tail_mbuf->m_flags & M_EOR) { + if (nxt->end_added) { s_extra->next_flags |= SCTP_NEXT_MSG_ISCOMPLETE; } } @@ -4653,7 +4622,7 @@ get_more_data: while (m) { /* Move out all we can */ cp_len = (int)uio->uio_resid; - my_len = (int)m->m_len; + my_len = (int)SCTP_BUF_LEN(m); if (cp_len > my_len) { /* not enough in this buf */ cp_len = my_len; @@ -4685,8 +4654,8 @@ get_more_data: /* error we are out of here */ goto release; } - if ((m->m_next == NULL) && - (cp_len >= m->m_len) && + if ((SCTP_BUF_NEXT(m) == NULL) && + (cp_len >= SCTP_BUF_LEN(m)) && ((control->end_added == 0) || (control->end_added && (TAILQ_NEXT(control, next) == NULL))) ) { @@ -4694,13 +4663,13 @@ get_more_data: sctp_misc_ints(SCTP_SORCV_DOESLCK, so->so_rcv.sb_cc, cp_len, - m->m_len, + SCTP_BUF_LEN(m), control->length); #endif SCTP_INP_READ_LOCK(inp); hold_rlock = 1; } - if (cp_len == m->m_len) { + if (cp_len == SCTP_BUF_LEN(m)) { #ifdef SCTP_RECV_DETAIL_RWND_LOGGING sctp_misc_ints(SCTP_SORCV_DOESADJ, so->so_rcv.sb_cc, @@ -4708,22 +4677,23 @@ get_more_data: cp_len, 0); #endif - if (m->m_flags & M_EOR) { + if ((SCTP_BUF_NEXT(m) == NULL) && + (control->end_added)) { out_flags |= MSG_EOR; } - if (m->m_flags & M_NOTIFICATION) { + if (control->spec_flags & M_NOTIFICATION) { out_flags |= MSG_NOTIFICATION; } /* we ate up the mbuf */ if (in_flags & MSG_PEEK) { /* just looking */ - m = m->m_next; + m = SCTP_BUF_NEXT(m); copied_so_far += cp_len; } else { /* dispose of the mbuf */ #ifdef SCTP_SB_LOGGING sctp_sblog(&so->so_rcv, - control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBFREE, m->m_len); + control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBFREE, SCTP_BUF_LEN(m)); #endif sctp_sbfree(control, stcb, &so->so_rcv, m); #ifdef SCTP_SB_LOGGING @@ -4783,21 +4753,12 @@ get_more_data: } } else { /* Do we need to trim the mbuf? */ - if (m->m_flags & M_NOTIFICATION) { + if (control->spec_flags & M_NOTIFICATION) { out_flags |= MSG_NOTIFICATION; } if ((in_flags & MSG_PEEK) == 0) { - if (out_flags & MSG_NOTIFICATION) { - /* - * remark this one with the - * notify flag, they read - * only part of the - * notification. - */ - m->m_flags |= M_NOTIFICATION; - } - m->m_data += cp_len; - m->m_len -= cp_len; + SCTP_BUF_RESV_UF(m, cp_len); + SCTP_BUF_LEN(m) -= cp_len; #ifdef SCTP_SB_LOGGING sctp_sblog(&so->so_rcv, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBFREE, cp_len); #endif @@ -5037,10 +4998,10 @@ get_more_data2: hold_rlock = 1; } } - if (control->tail_mbuf->m_flags & M_EOR) { + if (control->end_added) { out_flags |= MSG_EOR; } - if (control->data->m_flags & M_NOTIFICATION) { + if (control->spec_flags & M_NOTIFICATION) { out_flags |= MSG_NOTIFICATION; } if (uio) @@ -5050,15 +5011,15 @@ get_more_data2: while (m) { #ifdef SCTP_SB_LOGGING sctp_sblog(&so->so_rcv, - control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBFREE, m->m_len); + control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBFREE, SCTP_BUF_LEN(m)); #endif sctp_sbfree(control, stcb, &so->so_rcv, m); - freed_so_far += m->m_len; + freed_so_far += SCTP_BUF_LEN(m); #ifdef SCTP_SB_LOGGING sctp_sblog(&so->so_rcv, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBRESULT, 0); #endif - m = m->m_next; + m = SCTP_BUF_NEXT(m); } control->data = control->tail_mbuf = NULL; control->length = 0; @@ -5126,29 +5087,29 @@ get_more_data2: hold_rlock = 1; } } - if (m->m_flags & M_NOTIFICATION) { + if (control->spec_flags & M_NOTIFICATION) { out_flags |= MSG_NOTIFICATION; } while ((m) && (cp_len > 0)) { - if (cp_len >= m->m_len) { + if (cp_len >= SCTP_BUF_LEN(m)) { *mp = m; - atomic_subtract_int(&control->length, m->m_len); + atomic_subtract_int(&control->length, SCTP_BUF_LEN(m)); if (uio) - uio->uio_resid -= m->m_len; - cp_len -= m->m_len; - control->data = m->m_next; - m->m_next = NULL; + uio->uio_resid -= SCTP_BUF_LEN(m); + cp_len -= SCTP_BUF_LEN(m); + control->data = SCTP_BUF_NEXT(m); + SCTP_BUF_NEXT(m) = NULL; #ifdef SCTP_SB_LOGGING sctp_sblog(&so->so_rcv, - control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBFREE, m->m_len); + control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBFREE, SCTP_BUF_LEN(m)); #endif sctp_sbfree(control, stcb, &so->so_rcv, m); - freed_so_far += m->m_len; + freed_so_far += SCTP_BUF_LEN(m); #ifdef SCTP_SB_LOGGING sctp_sblog(&so->so_rcv, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBRESULT, 0); #endif - mp = &m->m_next; + mp = &SCTP_BUF_NEXT(m); m = control->data; } else { /* @@ -5156,8 +5117,8 @@ get_more_data2: * this mbuf only. */ if (uio) - uio->uio_resid -= m->m_len; - cp_len -= m->m_len; + uio->uio_resid -= SCTP_BUF_LEN(m); + cp_len -= SCTP_BUF_LEN(m); if (hold_rlock) { SCTP_INP_READ_UNLOCK(inp); hold_rlock = 0; @@ -5185,8 +5146,8 @@ get_more_data2: stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { no_rcv_needed = 1; } - m->m_data += cp_len; - m->m_len -= cp_len; + SCTP_BUF_RESV_UF(m, cp_len); + SCTP_BUF_LEN(m) -= cp_len; #ifdef SCTP_SB_LOGGING sctp_sblog(&so->so_rcv, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBFREE, cp_len); #endif @@ -5203,13 +5164,6 @@ get_more_data2: sctp_sblog(&so->so_rcv, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBRESULT, 0); #endif - if (out_flags & MSG_NOTIFICATION) { - /* - * remark the first mbuf if - * they took a partial read. - */ - control->data->m_flags |= M_NOTIFICATION; - } goto release; } } @@ -5290,7 +5244,7 @@ out: struct mbuf * sctp_m_free(struct mbuf *m) { - if (m->m_flags & M_EXT) { + if (SCTP_BUF_IS_EXTENDED(m)) { sctp_log_mb(m, SCTP_MBUF_IFREE); } return (m_free(m)); diff --git a/sys/netinet6/sctp6_usrreq.c b/sys/netinet6/sctp6_usrreq.c index 7bf4aaf..ab1141a 100644 --- a/sys/netinet6/sctp6_usrreq.c +++ b/sys/netinet6/sctp6_usrreq.c @@ -118,7 +118,7 @@ sctp6_input(mp, offp, proto) int proto; { - struct mbuf *m = *mp; + struct mbuf *m; struct ip6_hdr *ip6; struct sctphdr *sh; struct sctp_inpcb *in6p = NULL; @@ -133,6 +133,8 @@ sctp6_input(mp, offp, proto) int off = *offp; int s; + m = SCTP_HEADER_TO_CHAIN(*mp); + ip6 = mtod(m, struct ip6_hdr *); #ifndef PULLDOWN_TEST /* If PULLDOWN_TEST off, must be in a single mbuf. */ @@ -163,7 +165,7 @@ sctp6_input(mp, offp, proto) SCTP_STAT_INCR_COUNTER64(sctps_inpackets); #ifdef SCTP_DEBUG if (sctp_debug_on & SCTP_DEBUG_INPUT1) { - printf("V6 input gets a packet iphlen:%d pktlen:%d\n", iphlen, m->m_pkthdr.len); + printf("V6 input gets a packet iphlen:%d pktlen:%d\n", iphlen, SCTP_HEADER_LEN((*mp))); } #endif if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { @@ -174,8 +176,7 @@ sctp6_input(mp, offp, proto) if (sh->dest_port == 0) goto bad; if ((sctp_no_csum_on_loopback == 0) || - (m->m_pkthdr.rcvif == NULL) || - (m->m_pkthdr.rcvif->if_type != IFT_LOOP)) { + (!SCTP_IS_IT_LOOPBACK(m))) { /* * we do NOT validate things from the loopback if the sysctl * is set to 1. @@ -214,10 +215,8 @@ sctp6_input(mp, offp, proto) goto bad; } sh->checksum = calc_check; - } else { -sctp_skip_csum: - mlen = m->m_pkthdr.len; } +sctp_skip_csum: net = NULL; /* * Locate pcb and tcb for datagram sctp_findassociation_addr() wants @@ -270,9 +269,12 @@ sctp_skip_csum: /* * CONTROL chunk processing */ - length = ntohs(ip6->ip6_plen) + iphlen; offset -= sizeof(*ch); ecn_bits = ((ntohl(ip6->ip6_flow) >> 20) & 0x000000ff); + + /* Length now holds the total packet length payload + iphlen */ + length = ntohs(ip6->ip6_plen) + iphlen; + s = splnet(); (void)sctp_common_input_processing(&m, iphlen, offset, length, sh, ch, in6p, stcb, net, ecn_bits); @@ -420,8 +422,7 @@ sctp6_ctlinput(cmd, pktdst, d) struct sctp_nets *net = NULL; struct sockaddr_in6 final; - if (ip6cp->ip6c_m == NULL || - (size_t)ip6cp->ip6c_m->m_pkthdr.len < (ip6cp->ip6c_off + sizeof(sh))) + if (ip6cp->ip6c_m == NULL) return; bzero(&sh, sizeof(sh)); @@ -818,9 +819,9 @@ sctp6_disconnect(struct socket *so) struct sctp_paramhdr *ph; ph = mtod(err, struct sctp_paramhdr *); - err->m_len = sizeof(struct sctp_paramhdr); + SCTP_BUF_LEN(err) = sizeof(struct sctp_paramhdr); ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT); - ph->param_length = htons(err->m_len); + ph->param_length = htons(SCTP_BUF_LEN(err)); } sctp_send_abort_tcb(stcb, err); SCTP_STAT_INCR_COUNTER32(sctps_aborted); @@ -982,22 +983,9 @@ connected_type: } inp->control = control; } - /* add it in possibly */ - if ((inp->pkt) && - (inp->pkt->m_flags & M_PKTHDR)) { - struct mbuf *x; - int c_len; - - c_len = 0; - /* How big is it */ - for (x = m; x; x = x->m_next) { - c_len += x->m_len; - } - inp->pkt->m_pkthdr.len += c_len; - } /* Place the data */ if (inp->pkt) { - inp->pkt_last->m_next = m; + SCTP_BUF_NEXT(inp->pkt_last) = m; inp->pkt_last = m; } else { inp->pkt_last = inp->pkt = m; |