diff options
author | tuexen <tuexen@FreeBSD.org> | 2014-08-01 12:42:37 +0000 |
---|---|---|
committer | tuexen <tuexen@FreeBSD.org> | 2014-08-01 12:42:37 +0000 |
commit | 418772ad46d5fe7103c56ed605b4665b23adbac6 (patch) | |
tree | 10eda7303b772a543fb0c625621e9b58c0db4dbc | |
parent | f484e00cba11cc9a0349663251cca555828fdfe7 (diff) | |
download | FreeBSD-src-418772ad46d5fe7103c56ed605b4665b23adbac6.zip FreeBSD-src-418772ad46d5fe7103c56ed605b4665b23adbac6.tar.gz |
Cleanup sctp_send_initiate() and sctp_send_initiate_ack() to be
in sync as much as possible. This simplifies upcoming changes.
-rw-r--r-- | sys/netinet/sctp_header.h | 6 | ||||
-rw-r--r-- | sys/netinet/sctp_indata.c | 2 | ||||
-rw-r--r-- | sys/netinet/sctp_input.c | 2 | ||||
-rw-r--r-- | sys/netinet/sctp_output.c | 419 | ||||
-rw-r--r-- | sys/netinet/sctputil.c | 55 | ||||
-rw-r--r-- | sys/netinet/sctputil.h | 6 |
6 files changed, 220 insertions, 270 deletions
diff --git a/sys/netinet/sctp_header.h b/sys/netinet/sctp_header.h index 8f898a4..9e03d78 100644 --- a/sys/netinet/sctp_header.h +++ b/sys/netinet/sctp_header.h @@ -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; diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c index eac73e5..f1a288a 100644 --- a/sys/netinet/sctp_indata.c +++ b/sys/netinet/sctp_indata.c @@ -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); diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index c44c388..dd10e4c 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -5484,7 +5484,7 @@ process_control_chunks: 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 diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 161ce6b..6e3c016 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -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 @@ do_a_abort: 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 @@ do_a_abort: /* 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); - } - 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); + 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); } - 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 @@ do_a_abort: 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 @@ do_a_abort: * 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 @@ dont_do_it: 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; } diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c index 34b92f8..380b49f 100644 --- a/sys/netinet/sctputil.c +++ b/sys/netinet/sctputil.c @@ -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); - } - /* 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 *); - } - /* zero out the pad */ - for (i = 0; i < padlen; i++) { - *dp = 0; - dp++; + /* 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); + } + SCTP_BUF_LEN(m_last) = 0; + SCTP_BUF_NEXT(m_last) = NULL; + SCTP_BUF_NEXT(m) = m_last; } - 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 diff --git a/sys/netinet/sctputil.h b/sys/netinet/sctputil.h index 1e0b478..559daa3 100644 --- a/sys/netinet/sctputil.h +++ b/sys/netinet/sctputil.h @@ -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 |