Author: tuexen
Date: Fri Aug  1 12:42:37 2014
New Revision: 269376
URL: http://svnweb.freebsd.org/changeset/base/269376

Log:
  Cleanup sctp_send_initiate() and sctp_send_initiate_ack() to be
  in sync as much as possible. This simplifies upcoming changes.

Modified:
  head/sys/netinet/sctp_header.h
  head/sys/netinet/sctp_indata.c
  head/sys/netinet/sctp_input.c
  head/sys/netinet/sctp_output.c
  head/sys/netinet/sctputil.c
  head/sys/netinet/sctputil.h

Modified: head/sys/netinet/sctp_header.h
==============================================================================
--- head/sys/netinet/sctp_header.h      Fri Aug  1 10:35:35 2014        
(r269375)
+++ head/sys/netinet/sctp_header.h      Fri Aug  1 12:42:37 2014        
(r269376)
@@ -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;

Modified: head/sys/netinet/sctp_indata.c
==============================================================================
--- head/sys/netinet/sctp_indata.c      Fri Aug  1 10:35:35 2014        
(r269375)
+++ head/sys/netinet/sctp_indata.c      Fri Aug  1 12:42:37 2014        
(r269376)
@@ -2505,7 +2505,7 @@ sctp_process_data(struct mbuf **mm, int 
                                                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);

Modified: head/sys/netinet/sctp_input.c
==============================================================================
--- head/sys/netinet/sctp_input.c       Fri Aug  1 10:35:35 2014        
(r269375)
+++ head/sys/netinet/sctp_input.c       Fri Aug  1 12:42:37 2014        
(r269376)
@@ -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

Modified: head/sys/netinet/sctp_output.c
==============================================================================
--- head/sys/netinet/sctp_output.c      Fri Aug  1 10:35:35 2014        
(r269375)
+++ head/sys/netinet/sctp_output.c      Fri Aug  1 12:42:37 2014        
(r269376)
@@ -4700,7 +4700,7 @@ sctp_send_initiate(struct sctp_inpcb *in
 #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 *in
        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 *in
                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 *in
                        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 *in
         * 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(st
                        *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(st
                        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
     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
        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);
-       }
-       /* 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;
+           ((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 */
+       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);
-               }
-               SCTP_BUF_NEXT(m_at) = op_err;
-               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);
+               }
+               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 *stc
        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,
                        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;
                        }

Modified: head/sys/netinet/sctputil.c
==============================================================================
--- head/sys/netinet/sctputil.c Fri Aug  1 10:35:35 2014        (r269375)
+++ head/sys/netinet/sctputil.c Fri Aug  1 12:42:37 2014        (r269376)
@@ -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++;
-       }
-       return (0);
+               /* 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;
+       }
+       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 pa
                        }
                }
        }
-       SCTP_LTRACE_ERR_RET_PKT(m, NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, 
EFAULT);
-       return (EFAULT);
+       return (NULL);
 }
 
 static void

Modified: head/sys/netinet/sctputil.h
==============================================================================
--- head/sys/netinet/sctputil.h Fri Aug  1 10:35:35 2014        (r269375)
+++ head/sys/netinet/sctputil.h Fri Aug  1 12:42:37 2014        (r269376)
@@ -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
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to