Cleanup sctp_send_initiate() and sctp_send_initiate_ack() to be
in sync as much as possible. This simplifies upcoming changes.
This commit is contained in:
parent
835b36e211
commit
ce11b8429b
@ -82,12 +82,6 @@ struct sctp_supported_addr_param {
|
||||
uint16_t addr_type[2]; /* array of supported address types */
|
||||
} SCTP_PACKED;
|
||||
|
||||
/* ECN parameter */
|
||||
struct sctp_ecn_supported_param {
|
||||
struct sctp_paramhdr ph;/* type=SCTP_ECN_CAPABLE */
|
||||
} SCTP_PACKED;
|
||||
|
||||
|
||||
/* heartbeat info parameter */
|
||||
struct sctp_heartbeat_info_param {
|
||||
struct sctp_paramhdr ph;
|
||||
|
@ -2505,7 +2505,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
|
||||
SCTP_BUF_LEN(merr) = sizeof(*phd);
|
||||
SCTP_BUF_NEXT(merr) = SCTP_M_COPYM(m, *offset, chk_length, M_NOWAIT);
|
||||
if (SCTP_BUF_NEXT(merr)) {
|
||||
if (sctp_pad_lastmbuf(SCTP_BUF_NEXT(merr), SCTP_SIZE32(chk_length) - chk_length, NULL)) {
|
||||
if (sctp_pad_lastmbuf(SCTP_BUF_NEXT(merr), SCTP_SIZE32(chk_length) - chk_length, NULL) == NULL) {
|
||||
sctp_m_freem(merr);
|
||||
} else {
|
||||
sctp_queue_op_err(stcb, merr);
|
||||
|
@ -5484,7 +5484,7 @@ __attribute__((noinline))
|
||||
SCTP_BUF_LEN(mm) = sizeof(*phd);
|
||||
SCTP_BUF_NEXT(mm) = SCTP_M_COPYM(m, *offset, chk_length, M_NOWAIT);
|
||||
if (SCTP_BUF_NEXT(mm)) {
|
||||
if (sctp_pad_lastmbuf(SCTP_BUF_NEXT(mm), SCTP_SIZE32(chk_length) - chk_length, NULL)) {
|
||||
if (sctp_pad_lastmbuf(SCTP_BUF_NEXT(mm), SCTP_SIZE32(chk_length) - chk_length, NULL) == NULL) {
|
||||
sctp_m_freem(mm);
|
||||
} else {
|
||||
#ifdef SCTP_MBUF_LOGGING
|
||||
|
@ -4700,7 +4700,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
|
||||
#endif
|
||||
)
|
||||
{
|
||||
struct mbuf *m;
|
||||
struct mbuf *m, *m_last;
|
||||
struct sctp_nets *net;
|
||||
struct sctp_init_chunk *init;
|
||||
struct sctp_supported_addr_param *sup_addr;
|
||||
@ -4775,80 +4775,17 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
|
||||
init->init.num_inbound_streams = htons(stcb->asoc.max_inbound_streams);
|
||||
init->init.initial_tsn = htonl(stcb->asoc.init_seq_number);
|
||||
|
||||
if (stcb->asoc.scope.ipv4_addr_legal || stcb->asoc.scope.ipv6_addr_legal) {
|
||||
uint8_t i;
|
||||
|
||||
parameter_len = (uint16_t) sizeof(struct sctp_paramhdr);
|
||||
if (stcb->asoc.scope.ipv4_addr_legal) {
|
||||
parameter_len += (uint16_t) sizeof(uint16_t);
|
||||
}
|
||||
if (stcb->asoc.scope.ipv6_addr_legal) {
|
||||
parameter_len += (uint16_t) sizeof(uint16_t);
|
||||
}
|
||||
sup_addr = (struct sctp_supported_addr_param *)(mtod(m, caddr_t)+chunk_len);
|
||||
sup_addr->ph.param_type = htons(SCTP_SUPPORTED_ADDRTYPE);
|
||||
sup_addr->ph.param_length = htons(parameter_len);
|
||||
i = 0;
|
||||
if (stcb->asoc.scope.ipv4_addr_legal) {
|
||||
sup_addr->addr_type[i++] = htons(SCTP_IPV4_ADDRESS);
|
||||
}
|
||||
if (stcb->asoc.scope.ipv6_addr_legal) {
|
||||
sup_addr->addr_type[i++] = htons(SCTP_IPV6_ADDRESS);
|
||||
}
|
||||
padding_len = 4 - 2 * i;
|
||||
chunk_len += parameter_len;
|
||||
}
|
||||
/* Adaptation layer indication parameter */
|
||||
if (inp->sctp_ep.adaptation_layer_indicator_provided) {
|
||||
if (padding_len > 0) {
|
||||
memset(mtod(m, caddr_t)+chunk_len, 0, padding_len);
|
||||
chunk_len += padding_len;
|
||||
padding_len = 0;
|
||||
}
|
||||
parameter_len = (uint16_t) sizeof(struct sctp_adaptation_layer_indication);
|
||||
ali = (struct sctp_adaptation_layer_indication *)(mtod(m, caddr_t)+chunk_len);
|
||||
ali->ph.param_type = htons(SCTP_ULP_ADAPTATION);
|
||||
ali->ph.param_length = htons(parameter_len);
|
||||
ali->indication = ntohl(inp->sctp_ep.adaptation_layer_indicator);
|
||||
chunk_len += parameter_len;
|
||||
}
|
||||
if (SCTP_BASE_SYSCTL(sctp_inits_include_nat_friendly)) {
|
||||
/* Add NAT friendly parameter. */
|
||||
if (padding_len > 0) {
|
||||
memset(mtod(m, caddr_t)+chunk_len, 0, padding_len);
|
||||
chunk_len += padding_len;
|
||||
padding_len = 0;
|
||||
}
|
||||
parameter_len = (uint16_t) sizeof(struct sctp_paramhdr);
|
||||
ph = (struct sctp_paramhdr *)(mtod(m, caddr_t)+chunk_len);
|
||||
ph->param_type = htons(SCTP_HAS_NAT_SUPPORT);
|
||||
ph->param_length = htons(parameter_len);
|
||||
chunk_len += parameter_len;
|
||||
}
|
||||
/* now any cookie time extensions */
|
||||
if (stcb->asoc.cookie_preserve_req) {
|
||||
struct sctp_cookie_perserve_param *cookie_preserve;
|
||||
|
||||
if (padding_len > 0) {
|
||||
memset(mtod(m, caddr_t)+chunk_len, 0, padding_len);
|
||||
chunk_len += padding_len;
|
||||
padding_len = 0;
|
||||
}
|
||||
parameter_len = (uint16_t) sizeof(struct sctp_cookie_perserve_param);
|
||||
cookie_preserve = (struct sctp_cookie_perserve_param *)(mtod(m, caddr_t)+chunk_len);
|
||||
cookie_preserve->ph.param_type = htons(SCTP_COOKIE_PRESERVE);
|
||||
cookie_preserve->ph.param_length = htons(parameter_len);
|
||||
cookie_preserve->time = htonl(stcb->asoc.cookie_preserve_req);
|
||||
stcb->asoc.cookie_preserve_req = 0;
|
||||
ali->indication = htonl(inp->sctp_ep.adaptation_layer_indicator);
|
||||
chunk_len += parameter_len;
|
||||
}
|
||||
/* ECN parameter */
|
||||
if (stcb->asoc.ecn_allowed == 1) {
|
||||
if (padding_len > 0) {
|
||||
memset(mtod(m, caddr_t)+chunk_len, 0, padding_len);
|
||||
chunk_len += padding_len;
|
||||
padding_len = 0;
|
||||
}
|
||||
parameter_len = (uint16_t) sizeof(struct sctp_paramhdr);
|
||||
ph = (struct sctp_paramhdr *)(mtod(m, caddr_t)+chunk_len);
|
||||
ph->param_type = htons(SCTP_ECN_CAPABLE);
|
||||
@ -4856,21 +4793,24 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
|
||||
chunk_len += parameter_len;
|
||||
}
|
||||
/* And now tell the peer we do support PR-SCTP. */
|
||||
if (padding_len > 0) {
|
||||
memset(mtod(m, caddr_t)+chunk_len, 0, padding_len);
|
||||
chunk_len += padding_len;
|
||||
padding_len = 0;
|
||||
}
|
||||
parameter_len = (uint16_t) sizeof(struct sctp_paramhdr);
|
||||
ph = (struct sctp_paramhdr *)(mtod(m, caddr_t)+chunk_len);
|
||||
ph->param_type = htons(SCTP_PRSCTP_SUPPORTED);
|
||||
ph->param_length = htons(parameter_len);
|
||||
chunk_len += parameter_len;
|
||||
|
||||
/* And now tell the peer we do all the extensions */
|
||||
/* Add NAT friendly parameter. */
|
||||
if (SCTP_BASE_SYSCTL(sctp_inits_include_nat_friendly)) {
|
||||
parameter_len = (uint16_t) sizeof(struct sctp_paramhdr);
|
||||
ph = (struct sctp_paramhdr *)(mtod(m, caddr_t)+chunk_len);
|
||||
ph->param_type = htons(SCTP_HAS_NAT_SUPPORT);
|
||||
ph->param_length = htons(parameter_len);
|
||||
chunk_len += parameter_len;
|
||||
}
|
||||
/* And now tell the peer which extensions we support */
|
||||
num_ext = 0;
|
||||
pr_supported = (struct sctp_supported_chunk_types_param *)(mtod(m, caddr_t)+chunk_len);
|
||||
pr_supported->ph.param_type = htons(SCTP_SUPPORTED_CHUNK_EXT);
|
||||
num_ext = 0;
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_ASCONF;
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_ASCONF_ACK;
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_FORWARD_CUM_TSN;
|
||||
@ -4943,8 +4883,52 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
|
||||
chunk_len += parameter_len;
|
||||
}
|
||||
}
|
||||
SCTP_BUF_LEN(m) = chunk_len;
|
||||
/* now any cookie time extensions */
|
||||
if (stcb->asoc.cookie_preserve_req) {
|
||||
struct sctp_cookie_perserve_param *cookie_preserve;
|
||||
|
||||
if (padding_len > 0) {
|
||||
memset(mtod(m, caddr_t)+chunk_len, 0, padding_len);
|
||||
chunk_len += padding_len;
|
||||
padding_len = 0;
|
||||
}
|
||||
parameter_len = (uint16_t) sizeof(struct sctp_cookie_perserve_param);
|
||||
cookie_preserve = (struct sctp_cookie_perserve_param *)(mtod(m, caddr_t)+chunk_len);
|
||||
cookie_preserve->ph.param_type = htons(SCTP_COOKIE_PRESERVE);
|
||||
cookie_preserve->ph.param_length = htons(parameter_len);
|
||||
cookie_preserve->time = htonl(stcb->asoc.cookie_preserve_req);
|
||||
stcb->asoc.cookie_preserve_req = 0;
|
||||
chunk_len += parameter_len;
|
||||
}
|
||||
if (stcb->asoc.scope.ipv4_addr_legal || stcb->asoc.scope.ipv6_addr_legal) {
|
||||
uint8_t i;
|
||||
|
||||
if (padding_len > 0) {
|
||||
memset(mtod(m, caddr_t)+chunk_len, 0, padding_len);
|
||||
chunk_len += padding_len;
|
||||
padding_len = 0;
|
||||
}
|
||||
parameter_len = (uint16_t) sizeof(struct sctp_paramhdr);
|
||||
if (stcb->asoc.scope.ipv4_addr_legal) {
|
||||
parameter_len += (uint16_t) sizeof(uint16_t);
|
||||
}
|
||||
if (stcb->asoc.scope.ipv6_addr_legal) {
|
||||
parameter_len += (uint16_t) sizeof(uint16_t);
|
||||
}
|
||||
sup_addr = (struct sctp_supported_addr_param *)(mtod(m, caddr_t)+chunk_len);
|
||||
sup_addr->ph.param_type = htons(SCTP_SUPPORTED_ADDRTYPE);
|
||||
sup_addr->ph.param_length = htons(parameter_len);
|
||||
i = 0;
|
||||
if (stcb->asoc.scope.ipv4_addr_legal) {
|
||||
sup_addr->addr_type[i++] = htons(SCTP_IPV4_ADDRESS);
|
||||
}
|
||||
if (stcb->asoc.scope.ipv6_addr_legal) {
|
||||
sup_addr->addr_type[i++] = htons(SCTP_IPV6_ADDRESS);
|
||||
}
|
||||
padding_len = 4 - 2 * i;
|
||||
chunk_len += parameter_len;
|
||||
}
|
||||
SCTP_BUF_LEN(m) = chunk_len;
|
||||
/* now the addresses */
|
||||
/*
|
||||
* To optimize this we could put the scoping stuff into a structure
|
||||
@ -4952,18 +4936,13 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
|
||||
* we could just sifa in the address within the stcb. But for now
|
||||
* this is a quick hack to get the address stuff teased apart.
|
||||
*/
|
||||
sctp_add_addresses_to_i_ia(inp, stcb, &stcb->asoc.scope, m, cnt_inits_to, &padding_len, &chunk_len);
|
||||
m_last = sctp_add_addresses_to_i_ia(inp, stcb, &stcb->asoc.scope,
|
||||
m, cnt_inits_to,
|
||||
&padding_len, &chunk_len);
|
||||
|
||||
init->ch.chunk_length = htons(chunk_len);
|
||||
if (padding_len > 0) {
|
||||
struct mbuf *m_at, *mp_last;
|
||||
|
||||
mp_last = NULL;
|
||||
for (m_at = m; m_at; m_at = SCTP_BUF_NEXT(m_at)) {
|
||||
if (SCTP_BUF_NEXT(m_at) == NULL)
|
||||
mp_last = m_at;
|
||||
}
|
||||
if ((mp_last == NULL) || sctp_add_pad_tombuf(mp_last, padding_len)) {
|
||||
if (sctp_add_pad_tombuf(m_last, padding_len) == NULL) {
|
||||
sctp_m_freem(m);
|
||||
return;
|
||||
}
|
||||
@ -5100,7 +5079,6 @@ sctp_arethere_unrecognized_parameters(struct mbuf *in_initpkt,
|
||||
*nat_friendly = 1;
|
||||
/* fall through */
|
||||
case SCTP_PRSCTP_SUPPORTED:
|
||||
|
||||
if (padded_size != sizeof(struct sctp_paramhdr)) {
|
||||
SCTPDBG(SCTP_DEBUG_OUTPUT1, "Invalid size - error prsctp/nat support %d\n", plen);
|
||||
goto invalid_size;
|
||||
@ -5108,7 +5086,7 @@ sctp_arethere_unrecognized_parameters(struct mbuf *in_initpkt,
|
||||
at += padded_size;
|
||||
break;
|
||||
case SCTP_ECN_CAPABLE:
|
||||
if (padded_size != sizeof(struct sctp_ecn_supported_param)) {
|
||||
if (padded_size != sizeof(struct sctp_paramhdr)) {
|
||||
SCTPDBG(SCTP_DEBUG_OUTPUT1, "Invalid size - error ecn %d\n", plen);
|
||||
goto invalid_size;
|
||||
}
|
||||
@ -5493,13 +5471,13 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
|
||||
uint32_t vrf_id, uint16_t port, int hold_inp_lock)
|
||||
{
|
||||
struct sctp_association *asoc;
|
||||
struct mbuf *m, *m_at, *m_tmp, *m_cookie, *op_err, *mp_last;
|
||||
struct mbuf *m, *m_tmp, *m_last, *m_cookie, *op_err;
|
||||
struct sctp_init_ack_chunk *initack;
|
||||
struct sctp_adaptation_layer_indication *ali;
|
||||
struct sctp_ecn_supported_param *ecn;
|
||||
struct sctp_prsctp_supported_param *prsctp;
|
||||
struct sctp_supported_chunk_types_param *pr_supported;
|
||||
struct sctp_paramhdr *ph;
|
||||
union sctp_sockstore *over_addr;
|
||||
struct sctp_scoping scp;
|
||||
|
||||
#ifdef INET
|
||||
struct sockaddr_in *dst4 = (struct sockaddr_in *)dst;
|
||||
@ -5519,18 +5497,16 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
|
||||
uint8_t *signature = NULL;
|
||||
int cnt_inits_to = 0;
|
||||
uint16_t his_limit, i_want;
|
||||
int abort_flag, padval;
|
||||
int num_ext;
|
||||
int p_len;
|
||||
int abort_flag;
|
||||
int nat_friendly = 0;
|
||||
struct socket *so;
|
||||
uint16_t num_ext, chunk_len, padding_len, parameter_len;
|
||||
|
||||
if (stcb) {
|
||||
asoc = &stcb->asoc;
|
||||
} else {
|
||||
asoc = NULL;
|
||||
}
|
||||
mp_last = NULL;
|
||||
if ((asoc != NULL) &&
|
||||
(SCTP_GET_STATE(asoc) != SCTP_STATE_COOKIE_WAIT) &&
|
||||
(sctp_are_there_new_addresses(asoc, init_pkt, offset, src))) {
|
||||
@ -5573,7 +5549,8 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
|
||||
sctp_m_freem(op_err);
|
||||
return;
|
||||
}
|
||||
SCTP_BUF_LEN(m) = sizeof(struct sctp_init_chunk);
|
||||
chunk_len = (uint16_t) sizeof(struct sctp_init_ack_chunk);
|
||||
padding_len = 0;
|
||||
|
||||
/*
|
||||
* We might not overwrite the identification[] completely and on
|
||||
@ -5897,161 +5874,156 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
|
||||
|
||||
/* adaptation layer indication parameter */
|
||||
if (inp->sctp_ep.adaptation_layer_indicator_provided) {
|
||||
ali = (struct sctp_adaptation_layer_indication *)((caddr_t)initack + sizeof(*initack));
|
||||
parameter_len = (uint16_t) sizeof(struct sctp_adaptation_layer_indication);
|
||||
ali = (struct sctp_adaptation_layer_indication *)(mtod(m, caddr_t)+chunk_len);
|
||||
ali->ph.param_type = htons(SCTP_ULP_ADAPTATION);
|
||||
ali->ph.param_length = htons(sizeof(*ali));
|
||||
ali->indication = ntohl(inp->sctp_ep.adaptation_layer_indicator);
|
||||
SCTP_BUF_LEN(m) += sizeof(*ali);
|
||||
ecn = (struct sctp_ecn_supported_param *)((caddr_t)ali + sizeof(*ali));
|
||||
} else {
|
||||
ecn = (struct sctp_ecn_supported_param *)((caddr_t)initack + sizeof(*initack));
|
||||
ali->ph.param_length = htons(parameter_len);
|
||||
ali->indication = htonl(inp->sctp_ep.adaptation_layer_indicator);
|
||||
chunk_len += parameter_len;
|
||||
}
|
||||
|
||||
/* ECN parameter */
|
||||
if (((asoc != NULL) && (asoc->ecn_allowed == 1)) ||
|
||||
(inp->sctp_ecn_enable == 1)) {
|
||||
ecn->ph.param_type = htons(SCTP_ECN_CAPABLE);
|
||||
ecn->ph.param_length = htons(sizeof(*ecn));
|
||||
SCTP_BUF_LEN(m) += sizeof(*ecn);
|
||||
|
||||
prsctp = (struct sctp_prsctp_supported_param *)((caddr_t)ecn +
|
||||
sizeof(*ecn));
|
||||
} else {
|
||||
prsctp = (struct sctp_prsctp_supported_param *)((caddr_t)ecn);
|
||||
((asoc == NULL) && (inp->sctp_ecn_enable == 1))) {
|
||||
parameter_len = (uint16_t) sizeof(struct sctp_paramhdr);
|
||||
ph = (struct sctp_paramhdr *)(mtod(m, caddr_t)+chunk_len);
|
||||
ph->param_type = htons(SCTP_ECN_CAPABLE);
|
||||
ph->param_length = htons(parameter_len);
|
||||
chunk_len += parameter_len;
|
||||
}
|
||||
/* And now tell the peer we do pr-sctp */
|
||||
prsctp->ph.param_type = htons(SCTP_PRSCTP_SUPPORTED);
|
||||
prsctp->ph.param_length = htons(sizeof(*prsctp));
|
||||
SCTP_BUF_LEN(m) += sizeof(*prsctp);
|
||||
if (nat_friendly) {
|
||||
/* Add NAT friendly parameter */
|
||||
struct sctp_paramhdr *ph;
|
||||
/* And now tell the peer we do pr-sctp */
|
||||
parameter_len = (uint16_t) sizeof(struct sctp_paramhdr);
|
||||
ph = (struct sctp_paramhdr *)(mtod(m, caddr_t)+chunk_len);
|
||||
ph->param_type = htons(SCTP_PRSCTP_SUPPORTED);
|
||||
ph->param_length = htons(parameter_len);
|
||||
chunk_len += parameter_len;
|
||||
|
||||
ph = (struct sctp_paramhdr *)(mtod(m, caddr_t)+SCTP_BUF_LEN(m));
|
||||
/* Add NAT friendly parameter */
|
||||
if (nat_friendly) {
|
||||
parameter_len = (uint16_t) sizeof(struct sctp_paramhdr);
|
||||
ph = (struct sctp_paramhdr *)(mtod(m, caddr_t)+chunk_len);
|
||||
ph->param_type = htons(SCTP_HAS_NAT_SUPPORT);
|
||||
ph->param_length = htons(sizeof(struct sctp_paramhdr));
|
||||
SCTP_BUF_LEN(m) += sizeof(struct sctp_paramhdr);
|
||||
chunk_len += sizeof(struct sctp_paramhdr);
|
||||
}
|
||||
/* And now tell the peer we do all the extensions */
|
||||
pr_supported = (struct sctp_supported_chunk_types_param *)(mtod(m, caddr_t)+SCTP_BUF_LEN(m));
|
||||
pr_supported->ph.param_type = htons(SCTP_SUPPORTED_CHUNK_EXT);
|
||||
/* And now tell the peer which extensions we support */
|
||||
num_ext = 0;
|
||||
pr_supported = (struct sctp_supported_chunk_types_param *)(mtod(m, caddr_t)+chunk_len);
|
||||
pr_supported->ph.param_type = htons(SCTP_SUPPORTED_CHUNK_EXT);
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_ASCONF;
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_ASCONF_ACK;
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_FORWARD_CUM_TSN;
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_PACKET_DROPPED;
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_STREAM_RESET;
|
||||
if (!SCTP_BASE_SYSCTL(sctp_auth_disable))
|
||||
if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) {
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_AUTHENTICATION;
|
||||
if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off))
|
||||
}
|
||||
if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off)) {
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_NR_SELECTIVE_ACK;
|
||||
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);
|
||||
SCTP_BUF_LEN(m) += SCTP_SIZE32(p_len);
|
||||
}
|
||||
parameter_len = (uint16_t) sizeof(struct sctp_supported_chunk_types_param) + num_ext;
|
||||
pr_supported->ph.param_length = htons(parameter_len);
|
||||
padding_len = SCTP_SIZE32(parameter_len) - parameter_len;
|
||||
chunk_len += parameter_len;
|
||||
|
||||
/* add authentication parameters */
|
||||
if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) {
|
||||
struct sctp_auth_random *randp;
|
||||
struct sctp_auth_hmac_algo *hmacs;
|
||||
struct sctp_auth_chunk_list *chunks;
|
||||
uint16_t random_len;
|
||||
|
||||
if (padding_len > 0) {
|
||||
memset(mtod(m, caddr_t)+chunk_len, 0, padding_len);
|
||||
chunk_len += padding_len;
|
||||
padding_len = 0;
|
||||
}
|
||||
/* generate and add RANDOM parameter */
|
||||
random_len = SCTP_AUTH_RANDOM_SIZE_DEFAULT;
|
||||
randp = (struct sctp_auth_random *)(mtod(m, caddr_t)+SCTP_BUF_LEN(m));
|
||||
randp = (struct sctp_auth_random *)(mtod(m, caddr_t)+chunk_len);
|
||||
parameter_len = (uint16_t) sizeof(struct sctp_auth_random) +
|
||||
SCTP_AUTH_RANDOM_SIZE_DEFAULT;
|
||||
randp->ph.param_type = htons(SCTP_RANDOM);
|
||||
p_len = sizeof(*randp) + random_len;
|
||||
randp->ph.param_length = htons(p_len);
|
||||
SCTP_READ_RANDOM(randp->random_data, random_len);
|
||||
/* zero out any padding required */
|
||||
bzero((caddr_t)randp + p_len, SCTP_SIZE32(p_len) - p_len);
|
||||
SCTP_BUF_LEN(m) += SCTP_SIZE32(p_len);
|
||||
randp->ph.param_length = htons(parameter_len);
|
||||
SCTP_READ_RANDOM(randp->random_data, SCTP_AUTH_RANDOM_SIZE_DEFAULT);
|
||||
padding_len = SCTP_SIZE32(parameter_len) - parameter_len;
|
||||
chunk_len += parameter_len;
|
||||
|
||||
if (padding_len > 0) {
|
||||
memset(mtod(m, caddr_t)+chunk_len, 0, padding_len);
|
||||
chunk_len += padding_len;
|
||||
padding_len = 0;
|
||||
}
|
||||
/* add HMAC_ALGO parameter */
|
||||
hmacs = (struct sctp_auth_hmac_algo *)(mtod(m, caddr_t)+SCTP_BUF_LEN(m));
|
||||
p_len = sctp_serialize_hmaclist(inp->sctp_ep.local_hmacs,
|
||||
hmacs = (struct sctp_auth_hmac_algo *)(mtod(m, caddr_t)+chunk_len);
|
||||
parameter_len = (uint16_t) sizeof(struct sctp_auth_hmac_algo) +
|
||||
sctp_serialize_hmaclist(inp->sctp_ep.local_hmacs,
|
||||
(uint8_t *) hmacs->hmac_ids);
|
||||
if (p_len > 0) {
|
||||
p_len += sizeof(*hmacs);
|
||||
hmacs->ph.param_type = htons(SCTP_HMAC_LIST);
|
||||
hmacs->ph.param_length = htons(p_len);
|
||||
/* zero out any padding required */
|
||||
bzero((caddr_t)hmacs + p_len, SCTP_SIZE32(p_len) - p_len);
|
||||
SCTP_BUF_LEN(m) += SCTP_SIZE32(p_len);
|
||||
hmacs->ph.param_type = htons(SCTP_HMAC_LIST);
|
||||
hmacs->ph.param_length = htons(parameter_len);
|
||||
padding_len = SCTP_SIZE32(parameter_len) - parameter_len;
|
||||
chunk_len += parameter_len;
|
||||
|
||||
if (padding_len > 0) {
|
||||
memset(mtod(m, caddr_t)+chunk_len, 0, padding_len);
|
||||
chunk_len += padding_len;
|
||||
padding_len = 0;
|
||||
}
|
||||
/* add CHUNKS parameter */
|
||||
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 = (struct sctp_auth_chunk_list *)(mtod(m, caddr_t)+chunk_len);
|
||||
parameter_len = (uint16_t) sizeof(struct sctp_auth_chunk_list) +
|
||||
sctp_serialize_auth_chunks(inp->sctp_ep.local_auth_chunks,
|
||||
chunks->chunk_types);
|
||||
if (p_len > 0) {
|
||||
p_len += sizeof(*chunks);
|
||||
chunks->ph.param_type = htons(SCTP_CHUNK_LIST);
|
||||
chunks->ph.param_length = htons(p_len);
|
||||
/* zero out any padding required */
|
||||
bzero((caddr_t)chunks + p_len, SCTP_SIZE32(p_len) - p_len);
|
||||
SCTP_BUF_LEN(m) += SCTP_SIZE32(p_len);
|
||||
}
|
||||
chunks->ph.param_type = htons(SCTP_CHUNK_LIST);
|
||||
chunks->ph.param_length = htons(parameter_len);
|
||||
padding_len = SCTP_SIZE32(parameter_len) - parameter_len;
|
||||
chunk_len += parameter_len;
|
||||
}
|
||||
m_at = m;
|
||||
SCTP_BUF_LEN(m) = chunk_len;
|
||||
m_last = m;
|
||||
/* now the addresses */
|
||||
{
|
||||
struct sctp_scoping scp;
|
||||
|
||||
/*
|
||||
* To optimize this we could put the scoping stuff into a
|
||||
* structure and remove the individual uint8's from the stc
|
||||
* structure. Then we could just sifa in the address within
|
||||
* the stc.. but for now this is a quick hack to get the
|
||||
* address stuff teased apart.
|
||||
*/
|
||||
scp.ipv4_addr_legal = stc.ipv4_addr_legal;
|
||||
scp.ipv6_addr_legal = stc.ipv6_addr_legal;
|
||||
scp.loopback_scope = stc.loopback_scope;
|
||||
scp.ipv4_local_scope = stc.ipv4_scope;
|
||||
scp.local_scope = stc.local_scope;
|
||||
scp.site_scope = stc.site_scope;
|
||||
m_at = sctp_add_addresses_to_i_ia(inp, stcb, &scp, m_at, cnt_inits_to, NULL, NULL);
|
||||
/*
|
||||
* To optimize this we could put the scoping stuff into a structure
|
||||
* and remove the individual uint8's from the stc structure. Then we
|
||||
* could just sifa in the address within the stc.. but for now this
|
||||
* is a quick hack to get the address stuff teased apart.
|
||||
*/
|
||||
scp.ipv4_addr_legal = stc.ipv4_addr_legal;
|
||||
scp.ipv6_addr_legal = stc.ipv6_addr_legal;
|
||||
scp.loopback_scope = stc.loopback_scope;
|
||||
scp.ipv4_local_scope = stc.ipv4_scope;
|
||||
scp.local_scope = stc.local_scope;
|
||||
scp.site_scope = stc.site_scope;
|
||||
m_last = sctp_add_addresses_to_i_ia(inp, stcb, &scp, m_last,
|
||||
cnt_inits_to,
|
||||
&padding_len, &chunk_len);
|
||||
/* padding_len can only be positive, if no addresses have been added */
|
||||
if (padding_len > 0) {
|
||||
memset(mtod(m, caddr_t)+chunk_len, 0, padding_len);
|
||||
chunk_len += padding_len;
|
||||
SCTP_BUF_LEN(m) += padding_len;
|
||||
padding_len = 0;
|
||||
}
|
||||
|
||||
/* tack on the operational error if present */
|
||||
if (op_err) {
|
||||
struct mbuf *ol;
|
||||
int llen;
|
||||
|
||||
llen = 0;
|
||||
ol = op_err;
|
||||
|
||||
while (ol) {
|
||||
llen += SCTP_BUF_LEN(ol);
|
||||
ol = SCTP_BUF_NEXT(ol);
|
||||
parameter_len = 0;
|
||||
for (m_tmp = op_err; m_tmp != NULL; m_tmp = SCTP_BUF_NEXT(m_tmp)) {
|
||||
parameter_len += SCTP_BUF_LEN(m_tmp);
|
||||
}
|
||||
if (llen % 4) {
|
||||
/* must add a pad to the param */
|
||||
uint32_t cpthis = 0;
|
||||
int padlen;
|
||||
|
||||
padlen = 4 - (llen % 4);
|
||||
m_copyback(op_err, llen, padlen, (caddr_t)&cpthis);
|
||||
}
|
||||
while (SCTP_BUF_NEXT(m_at) != NULL) {
|
||||
m_at = SCTP_BUF_NEXT(m_at);
|
||||
}
|
||||
SCTP_BUF_NEXT(m_at) = op_err;
|
||||
while (SCTP_BUF_NEXT(m_at) != NULL) {
|
||||
m_at = SCTP_BUF_NEXT(m_at);
|
||||
padding_len = SCTP_SIZE32(parameter_len) - parameter_len;
|
||||
SCTP_BUF_NEXT(m_last) = op_err;
|
||||
while (SCTP_BUF_NEXT(m_last) != NULL) {
|
||||
m_last = SCTP_BUF_NEXT(m_last);
|
||||
}
|
||||
chunk_len += parameter_len;
|
||||
}
|
||||
/* pre-calulate the size and update pkt header and chunk header */
|
||||
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;
|
||||
if (padding_len > 0) {
|
||||
m_last = sctp_add_pad_tombuf(m_last, padding_len);
|
||||
if (m_last == NULL) {
|
||||
/* Houston we have a problem, no space */
|
||||
sctp_m_freem(m);
|
||||
return;
|
||||
}
|
||||
chunk_len += padding_len;
|
||||
padding_len = 0;
|
||||
}
|
||||
|
||||
/* Now we must build a cookie */
|
||||
m_cookie = sctp_add_cookie(init_pkt, offset, m, 0, &stc, &signature);
|
||||
if (m_cookie == NULL) {
|
||||
@ -6060,21 +6032,22 @@ 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 */
|
||||
SCTP_BUF_NEXT(m_tmp) = m_cookie;
|
||||
|
||||
for (m_tmp = m_cookie; m_tmp; m_tmp = SCTP_BUF_NEXT(m_tmp)) {
|
||||
p_len += SCTP_BUF_LEN(m_tmp);
|
||||
SCTP_BUF_NEXT(m_last) = m_cookie;
|
||||
parameter_len = 0;
|
||||
for (m_tmp = m_cookie; m_tmp != NULL; m_tmp = SCTP_BUF_NEXT(m_tmp)) {
|
||||
parameter_len += SCTP_BUF_LEN(m_tmp);
|
||||
if (SCTP_BUF_NEXT(m_tmp) == NULL) {
|
||||
/* m_tmp should now point to last one */
|
||||
mp_last = m_tmp;
|
||||
break;
|
||||
m_last = m_tmp;
|
||||
}
|
||||
}
|
||||
padding_len = SCTP_SIZE32(parameter_len) - parameter_len;
|
||||
chunk_len += parameter_len;
|
||||
|
||||
/*
|
||||
* Place in the size, but we don't include the last pad (if any) in
|
||||
* the INIT-ACK.
|
||||
*/
|
||||
initack->ch.chunk_length = htons(p_len);
|
||||
initack->ch.chunk_length = htons(chunk_len);
|
||||
|
||||
/*
|
||||
* Time to sign the cookie, we don't sign over the cookie signature
|
||||
@ -6088,11 +6061,8 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
|
||||
* We sifa 0 here to NOT set IP_DF if its IPv4, we ignore the return
|
||||
* here since the timer will drive a retranmission.
|
||||
*/
|
||||
padval = p_len % 4;
|
||||
if ((padval) && (mp_last)) {
|
||||
/* see my previous comments on mp_last */
|
||||
if (sctp_add_pad_tombuf(mp_last, (4 - padval))) {
|
||||
/* Houston we have a problem, no space */
|
||||
if (padding_len > 0) {
|
||||
if (sctp_add_pad_tombuf(m_last, padding_len) == NULL) {
|
||||
sctp_m_freem(m);
|
||||
return;
|
||||
}
|
||||
@ -7582,12 +7552,10 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb,
|
||||
int pads;
|
||||
|
||||
pads = SCTP_SIZE32(chk->book_size) - chk->send_size;
|
||||
if (sctp_pad_lastmbuf(chk->data, pads, chk->last_mbuf) == 0) {
|
||||
chk->pad_inplace = 1;
|
||||
}
|
||||
if ((lm = SCTP_BUF_NEXT(chk->last_mbuf)) != NULL) {
|
||||
/* pad added an mbuf */
|
||||
lm = sctp_pad_lastmbuf(chk->data, pads, chk->last_mbuf);
|
||||
if (lm != NULL) {
|
||||
chk->last_mbuf = lm;
|
||||
chk->pad_inplace = 1;
|
||||
}
|
||||
chk->send_size += pads;
|
||||
}
|
||||
@ -10900,7 +10868,8 @@ sctp_send_abort_tcb(struct sctp_tcb *stcb, struct mbuf *operr, int so_locked
|
||||
abort->ch.chunk_length = htons(chunk_len);
|
||||
/* Add padding, if necessary. */
|
||||
if (padding_len > 0) {
|
||||
if ((m_last == NULL) || sctp_add_pad_tombuf(m_last, padding_len)) {
|
||||
if ((m_last == NULL) ||
|
||||
(sctp_add_pad_tombuf(m_last, padding_len) == NULL)) {
|
||||
sctp_m_freem(m_out);
|
||||
return;
|
||||
}
|
||||
@ -11000,7 +10969,7 @@ sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst,
|
||||
padding_len = 4 - padding_len;
|
||||
}
|
||||
if (padding_len != 0) {
|
||||
if (sctp_add_pad_tombuf(m_last, padding_len)) {
|
||||
if (sctp_add_pad_tombuf(m_last, padding_len) == NULL) {
|
||||
sctp_m_freem(cause);
|
||||
return;
|
||||
}
|
||||
|
@ -2516,58 +2516,44 @@ sctp_get_next_param(struct mbuf *m,
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
struct mbuf *
|
||||
sctp_add_pad_tombuf(struct mbuf *m, int padlen)
|
||||
{
|
||||
/*
|
||||
* add padlen bytes of 0 filled padding to the end of the mbuf. If
|
||||
* padlen is > 3 this routine will fail.
|
||||
*/
|
||||
uint8_t *dp;
|
||||
int i;
|
||||
struct mbuf *m_last;
|
||||
caddr_t dp;
|
||||
|
||||
if (padlen > 3) {
|
||||
SCTP_LTRACE_ERR_RET_PKT(m, NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS);
|
||||
return (ENOBUFS);
|
||||
return (NULL);
|
||||
}
|
||||
if (padlen <= M_TRAILINGSPACE(m)) {
|
||||
/*
|
||||
* The easy way. We hope the majority of the time we hit
|
||||
* here :)
|
||||
*/
|
||||
dp = (uint8_t *) (mtod(m, caddr_t)+SCTP_BUF_LEN(m));
|
||||
SCTP_BUF_LEN(m) += padlen;
|
||||
m_last = m;
|
||||
} else {
|
||||
/* Hard way we must grow the mbuf */
|
||||
struct mbuf *tmp;
|
||||
|
||||
tmp = sctp_get_mbuf_for_msg(padlen, 0, M_NOWAIT, 1, MT_DATA);
|
||||
if (tmp == NULL) {
|
||||
/* Out of space GAK! we are in big trouble. */
|
||||
SCTP_LTRACE_ERR_RET_PKT(m, NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS);
|
||||
return (ENOBUFS);
|
||||
/* Hard way we must grow the mbuf chain */
|
||||
m_last = sctp_get_mbuf_for_msg(padlen, 0, M_NOWAIT, 1, MT_DATA);
|
||||
if (m_last == NULL) {
|
||||
return (NULL);
|
||||
}
|
||||
/* setup and insert in middle */
|
||||
SCTP_BUF_LEN(tmp) = padlen;
|
||||
SCTP_BUF_NEXT(tmp) = NULL;
|
||||
SCTP_BUF_NEXT(m) = tmp;
|
||||
dp = mtod(tmp, uint8_t *);
|
||||
SCTP_BUF_LEN(m_last) = 0;
|
||||
SCTP_BUF_NEXT(m_last) = NULL;
|
||||
SCTP_BUF_NEXT(m) = m_last;
|
||||
}
|
||||
/* zero out the pad */
|
||||
for (i = 0; i < padlen; i++) {
|
||||
*dp = 0;
|
||||
dp++;
|
||||
}
|
||||
return (0);
|
||||
dp = mtod(m_last, caddr_t)+SCTP_BUF_LEN(m_last);
|
||||
SCTP_BUF_LEN(m_last) += padlen;
|
||||
memset(dp, 0, padlen);
|
||||
return (m_last);
|
||||
}
|
||||
|
||||
int
|
||||
struct mbuf *
|
||||
sctp_pad_lastmbuf(struct mbuf *m, int padval, struct mbuf *last_mbuf)
|
||||
{
|
||||
/* find the last mbuf in chain and pad it */
|
||||
struct mbuf *m_at;
|
||||
|
||||
if (last_mbuf) {
|
||||
if (last_mbuf != NULL) {
|
||||
return (sctp_add_pad_tombuf(last_mbuf, padval));
|
||||
} else {
|
||||
for (m_at = m; m_at; m_at = SCTP_BUF_NEXT(m_at)) {
|
||||
@ -2576,8 +2562,7 @@ sctp_pad_lastmbuf(struct mbuf *m, int padval, struct mbuf *last_mbuf)
|
||||
}
|
||||
}
|
||||
}
|
||||
SCTP_LTRACE_ERR_RET_PKT(m, NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, EFAULT);
|
||||
return (EFAULT);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -147,9 +147,11 @@ struct sctp_paramhdr *
|
||||
sctp_get_next_param(struct mbuf *, int,
|
||||
struct sctp_paramhdr *, int);
|
||||
|
||||
int sctp_add_pad_tombuf(struct mbuf *, int);
|
||||
struct mbuf *
|
||||
sctp_add_pad_tombuf(struct mbuf *, int);
|
||||
|
||||
int sctp_pad_lastmbuf(struct mbuf *, int, struct mbuf *);
|
||||
struct mbuf *
|
||||
sctp_pad_lastmbuf(struct mbuf *, int, struct mbuf *);
|
||||
|
||||
void
|
||||
sctp_ulp_notify(uint32_t, struct sctp_tcb *, uint32_t, void *, int
|
||||
|
Loading…
Reference in New Issue
Block a user