Author: tuexen
Date: Sun Jul  7 15:18:09 2013
New Revision: 252953
URL: http://svnweb.freebsd.org/changeset/base/252953

Log:
  MFC r244021:
  Ensure that the padding of the last parameter of an INIT chunk
  is not included in the chunk length as required by RFC 4960.
  While there, cleanup sctp_send_initiate().

Modified:
  stable/9/sys/netinet/sctp_output.c
  stable/9/sys/netinet/sctp_output.h
Directory Properties:
  stable/9/sys/   (props changed)

Modified: stable/9/sys/netinet/sctp_output.c
==============================================================================
--- stable/9/sys/netinet/sctp_output.c  Sun Jul  7 14:20:00 2013        
(r252952)
+++ stable/9/sys/netinet/sctp_output.c  Sun Jul  7 15:18:09 2013        
(r252953)
@@ -1940,27 +1940,27 @@ sctp_is_address_in_scope(struct sctp_ifa
 }
 
 static struct mbuf *
-sctp_add_addr_to_mbuf(struct mbuf *m, struct sctp_ifa *ifa)
+sctp_add_addr_to_mbuf(struct mbuf *m, struct sctp_ifa *ifa, uint16_t * len)
 {
        struct sctp_paramhdr *parmh;
        struct mbuf *mret;
-       int len;
+       uint16_t plen;
 
        switch (ifa->address.sa.sa_family) {
 #ifdef INET
        case AF_INET:
-               len = sizeof(struct sctp_ipv4addr_param);
+               plen = (uint16_t) sizeof(struct sctp_ipv4addr_param);
                break;
 #endif
 #ifdef INET6
        case AF_INET6:
-               len = sizeof(struct sctp_ipv6addr_param);
+               plen = (uint16_t) sizeof(struct sctp_ipv6addr_param);
                break;
 #endif
        default:
                return (m);
        }
-       if (M_TRAILINGSPACE(m) >= len) {
+       if (M_TRAILINGSPACE(m) >= plen) {
                /* easy side we just drop it on the end */
                parmh = (struct sctp_paramhdr *)(SCTP_BUF_AT(m, 
SCTP_BUF_LEN(m)));
                mret = m;
@@ -1970,7 +1970,7 @@ sctp_add_addr_to_mbuf(struct mbuf *m, st
                while (SCTP_BUF_NEXT(mret) != NULL) {
                        mret = SCTP_BUF_NEXT(mret);
                }
-               SCTP_BUF_NEXT(mret) = sctp_get_mbuf_for_msg(len, 0, M_DONTWAIT, 
1, MT_DATA);
+               SCTP_BUF_NEXT(mret) = sctp_get_mbuf_for_msg(plen, 0, 
M_DONTWAIT, 1, MT_DATA);
                if (SCTP_BUF_NEXT(mret) == NULL) {
                        /* We are hosed, can't add more addresses */
                        return (m);
@@ -1989,9 +1989,9 @@ sctp_add_addr_to_mbuf(struct mbuf *m, st
                        sin = (struct sockaddr_in *)&ifa->address.sin;
                        ipv4p = (struct sctp_ipv4addr_param *)parmh;
                        parmh->param_type = htons(SCTP_IPV4_ADDRESS);
-                       parmh->param_length = htons(len);
+                       parmh->param_length = htons(plen);
                        ipv4p->addr = sin->sin_addr.s_addr;
-                       SCTP_BUF_LEN(mret) += len;
+                       SCTP_BUF_LEN(mret) += plen;
                        break;
                }
 #endif
@@ -2004,18 +2004,21 @@ sctp_add_addr_to_mbuf(struct mbuf *m, st
                        sin6 = (struct sockaddr_in6 *)&ifa->address.sin6;
                        ipv6p = (struct sctp_ipv6addr_param *)parmh;
                        parmh->param_type = htons(SCTP_IPV6_ADDRESS);
-                       parmh->param_length = htons(len);
+                       parmh->param_length = htons(plen);
                        memcpy(ipv6p->addr, &sin6->sin6_addr,
                            sizeof(ipv6p->addr));
                        /* clear embedded scope in the address */
                        in6_clearscope((struct in6_addr *)ipv6p->addr);
-                       SCTP_BUF_LEN(mret) += len;
+                       SCTP_BUF_LEN(mret) += plen;
                        break;
                }
 #endif
        default:
                return (m);
        }
+       if (len != NULL) {
+               *len += plen;
+       }
        return (mret);
 }
 
@@ -2023,7 +2026,8 @@ sctp_add_addr_to_mbuf(struct mbuf *m, st
 struct mbuf *
 sctp_add_addresses_to_i_ia(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
     struct sctp_scoping *scope,
-    struct mbuf *m_at, int cnt_inits_to)
+    struct mbuf *m_at, int cnt_inits_to,
+    uint16_t * padding_len, uint16_t * chunk_len)
 {
        struct sctp_vrf *vrf = NULL;
        int cnt, limit_out = 0, total_count;
@@ -2103,7 +2107,15 @@ skip_count:
                                            scope->site_scope, 0) == 0) {
                                                continue;
                                        }
-                                       m_at = sctp_add_addr_to_mbuf(m_at, 
sctp_ifap);
+                                       if ((chunk_len != NULL) &&
+                                           (padding_len != NULL) &&
+                                           (*padding_len > 0)) {
+                                               memset(mtod(m_at, 
caddr_t)+*chunk_len, 0, *padding_len);
+                                               SCTP_BUF_LEN(m_at) += 
*padding_len;
+                                               *chunk_len += *padding_len;
+                                               *padding_len = 0;
+                                       }
+                                       m_at = sctp_add_addr_to_mbuf(m_at, 
sctp_ifap, chunk_len);
                                        if (limit_out) {
                                                cnt++;
                                                total_count++;
@@ -2178,7 +2190,15 @@ skip_count:
                                    scope->site_scope, 0) == 0) {
                                        continue;
                                }
-                               m_at = sctp_add_addr_to_mbuf(m_at, laddr->ifa);
+                               if ((chunk_len != NULL) &&
+                                   (padding_len != NULL) &&
+                                   (*padding_len > 0)) {
+                                       memset(mtod(m_at, caddr_t)+*chunk_len, 
0, *padding_len);
+                                       SCTP_BUF_LEN(m_at) += *padding_len;
+                                       *chunk_len += *padding_len;
+                                       *padding_len = 0;
+                               }
+                               m_at = sctp_add_addr_to_mbuf(m_at, laddr->ifa, 
chunk_len);
                                cnt++;
                                if (cnt >= SCTP_ADDRESS_LIMIT) {
                                        break;
@@ -4575,21 +4595,19 @@ sctp_send_initiate(struct sctp_inpcb *in
 #endif
 )
 {
-       struct mbuf *m, *m_at, *mp_last;
+       struct sctp_scoping scp;
+       struct mbuf *m;
        struct sctp_nets *net;
        struct sctp_init_chunk *init;
        struct sctp_supported_addr_param *sup_addr;
        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;
        int cnt_inits_to = 0;
-       int padval, ret;
-       int num_ext;
-       int p_len;
+       int ret;
+       uint16_t num_ext, chunk_len, padding_len, parameter_len;
 
        /* INIT's always go to the primary (and usually ONLY address) */
-       mp_last = NULL;
        net = stcb->asoc.primary_destination;
        if (net == NULL) {
                net = TAILQ_FIRST(&stcb->asoc.nets);
@@ -4606,15 +4624,12 @@ sctp_send_initiate(struct sctp_inpcb *in
        }
        SCTPDBG(SCTP_DEBUG_OUTPUT4, "Sending INIT\n");
 #ifdef INET6
-       if (((struct sockaddr *)&(net->ro._l_addr))->sa_family == AF_INET6) {
+       if (net->ro._l_addr.sa.sa_family == AF_INET6) {
                /*
                 * special hook, if we are sending to link local it will not
                 * show up in our private address count.
                 */
-               struct sockaddr_in6 *sin6l;
-
-               sin6l = &net->ro._l_addr.sin6;
-               if (IN6_IS_ADDR_LINKLOCAL(&sin6l->sin6_addr))
+               if (IN6_IS_ADDR_LINKLOCAL(&net->ro._l_addr.sin6.sin6_addr))
                        cnt_inits_to = 1;
        }
 #endif
@@ -4632,14 +4647,15 @@ sctp_send_initiate(struct sctp_inpcb *in
                SCTPDBG(SCTP_DEBUG_OUTPUT4, "Sending INIT - mbuf?\n");
                return;
        }
-       SCTP_BUF_LEN(m) = sizeof(struct sctp_init_chunk);
+       chunk_len = (uint16_t) sizeof(struct sctp_init_chunk);
+       padding_len = 0;
        /*
         * assume peer supports asconf in order to be able to queue local
         * address changes while an INIT is in flight and before the assoc
         * is established.
         */
        stcb->asoc.peer_supports_asconf = 1;
-       /* Now lets put the SCTP header in place */
+       /* Now lets put the chunk header in place */
        init = mtod(m, struct sctp_init_chunk *);
        /* now the chunk header */
        init->ch.chunk_type = SCTP_INITIATION;
@@ -4651,84 +4667,112 @@ sctp_send_initiate(struct sctp_inpcb *in
        /* set up some of the credits. */
        init->init.a_rwnd = htonl(max(inp->sctp_socket ? 
SCTP_SB_LIMIT_RCV(inp->sctp_socket) : 0,
            SCTP_MINIMAL_RWND));
-
        init->init.num_outbound_streams = htons(stcb->asoc.pre_open_streams);
        init->init.num_inbound_streams = htons(stcb->asoc.max_inbound_streams);
        init->init.initial_tsn = htonl(stcb->asoc.init_seq_number);
+
+#if defined(INET) || defined(INET6)
        /* now the address restriction */
        /* XXX Should we take the address family of the socket into account? */
-       sup_addr = (struct sctp_supported_addr_param *)((caddr_t)init +
-           sizeof(*init));
+       sup_addr = (struct sctp_supported_addr_param *)(mtod(m, 
caddr_t)+chunk_len);
        sup_addr->ph.param_type = htons(SCTP_SUPPORTED_ADDRTYPE);
 #ifdef INET6
 #ifdef INET
        /* we support 2 types: IPv4/IPv6 */
-       sup_addr->ph.param_length = htons(sizeof(struct sctp_paramhdr) + 2 * 
sizeof(uint16_t));
+       parameter_len = (uint16_t) (sizeof(struct sctp_paramhdr) + 2 * 
sizeof(uint16_t));
+       sup_addr->ph.param_length = htons(parameter_len);
        sup_addr->addr_type[0] = htons(SCTP_IPV4_ADDRESS);
        sup_addr->addr_type[1] = htons(SCTP_IPV6_ADDRESS);
+       padding_len = 0;
 #else
        /* we support 1 type: IPv6 */
-       sup_addr->ph.param_length = htons(sizeof(struct sctp_paramhdr) + 
sizeof(uint16_t));
+       parameter_len = (uint16_t) (sizeof(struct sctp_paramhdr) + 
sizeof(uint16_t));
+       sup_addr->ph.param_length = htons(parameter_len);
        sup_addr->addr_type[0] = htons(SCTP_IPV6_ADDRESS);
        sup_addr->addr_type[1] = htons(0);      /* this is the padding */
+       padding_len = (uint16_t) sizeof(uint16_t);
 #endif
 #else
        /* we support 1 type: IPv4 */
-       sup_addr->ph.param_length = htons(sizeof(struct sctp_paramhdr) + 
sizeof(uint16_t));
+       parameter_len = (uint16_t) (sizeof(struct sctp_paramhdr) + 
sizeof(uint16_t));
+       sup_addr->ph.param_length = htons(parameter_len);
        sup_addr->addr_type[0] = htons(SCTP_IPV4_ADDRESS);
        sup_addr->addr_type[1] = htons(0);      /* this is the padding */
+       padding_len = (uint16_t) sizeof(uint16_t);
 #endif
-       SCTP_BUF_LEN(m) += sizeof(struct sctp_supported_addr_param);
-       /* adaptation layer indication parameter */
-       ali = (struct sctp_adaptation_layer_indication *)((caddr_t)sup_addr + 
sizeof(struct sctp_supported_addr_param));
+       chunk_len += parameter_len;
+#endif
+       /* Adaptation layer indication parameter */
+       /* XXX: Should we include this always? */
+       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(sizeof(*ali));
+       ali->ph.param_length = htons(parameter_len);
        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));
+       chunk_len += parameter_len;
 
        if (SCTP_BASE_SYSCTL(sctp_inits_include_nat_friendly)) {
-               /* Add NAT friendly parameter */
-               struct sctp_paramhdr *ph;
-
-               ph = (struct sctp_paramhdr *)(mtod(m, caddr_t)+SCTP_BUF_LEN(m));
+               /* 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(sizeof(struct sctp_paramhdr));
-               SCTP_BUF_LEN(m) += sizeof(struct sctp_paramhdr);
-               ecn = (struct sctp_ecn_supported_param *)((caddr_t)ph + 
sizeof(*ph));
+               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;
 
-               cookie_preserve = (struct sctp_cookie_perserve_param *)(ecn);
+               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(
-                   sizeof(*cookie_preserve));
+               cookie_preserve->ph.param_length = htons(parameter_len);
                cookie_preserve->time = htonl(stcb->asoc.cookie_preserve_req);
-               SCTP_BUF_LEN(m) += sizeof(*cookie_preserve);
-               ecn = (struct sctp_ecn_supported_param *)(
-                   (caddr_t)cookie_preserve + sizeof(*cookie_preserve));
                stcb->asoc.cookie_preserve_req = 0;
+               chunk_len += parameter_len;
        }
        /* ECN parameter */
        if (stcb->asoc.ecn_allowed == 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);
+               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);
+               ph->param_length = htons(parameter_len);
+               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;
        }
-       /* 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);
+       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 */
-       pr_supported = (struct sctp_supported_chunk_types_param *)
-           ((caddr_t)prsctp + sizeof(*prsctp));
+       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;
@@ -4742,99 +4786,94 @@ sctp_send_initiate(struct sctp_inpcb *in
        if (stcb->asoc.sctp_nr_sack_on_off == 1) {
                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;
-
                /* attach RANDOM parameter, if available */
                if (stcb->asoc.authinfo.random != NULL) {
-                       randp = (struct sctp_auth_random *)(mtod(m, 
caddr_t)+SCTP_BUF_LEN(m));
-                       p_len = sizeof(*randp) + stcb->asoc.authinfo.random_len;
+                       struct sctp_auth_random *randp;
+
+                       if (padding_len > 0) {
+                               memset(mtod(m, caddr_t)+chunk_len, 0, 
padding_len);
+                               chunk_len += padding_len;
+                               padding_len = 0;
+                       }
+                       randp = (struct sctp_auth_random *)(mtod(m, 
caddr_t)+chunk_len);
+                       parameter_len = (uint16_t) sizeof(struct 
sctp_auth_random) + stcb->asoc.authinfo.random_len;
                        /* random key already contains the header */
-                       bcopy(stcb->asoc.authinfo.random->key, randp, p_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);
+                       memcpy(randp, stcb->asoc.authinfo.random->key, 
parameter_len);
+                       padding_len = SCTP_SIZE32(parameter_len) - 
parameter_len;
+                       chunk_len += parameter_len;
                }
                /* add HMAC_ALGO parameter */
-               hmacs = (struct sctp_auth_hmac_algo *)(mtod(m, 
caddr_t)+SCTP_BUF_LEN(m));
-               p_len = sctp_serialize_hmaclist(stcb->asoc.local_hmacs,
-                   (uint8_t *) hmacs->hmac_ids);
-               if (p_len > 0) {
-                       p_len += sizeof(*hmacs);
+               if ((stcb->asoc.local_hmacs != NULL) &&
+                   (stcb->asoc.local_hmacs->num_algo > 0)) {
+                       struct sctp_auth_hmac_algo *hmacs;
+
+                       if (padding_len > 0) {
+                               memset(mtod(m, caddr_t)+chunk_len, 0, 
padding_len);
+                               chunk_len += padding_len;
+                               padding_len = 0;
+                       }
+                       hmacs = (struct sctp_auth_hmac_algo *)(mtod(m, 
caddr_t)+chunk_len);
+                       parameter_len = (uint16_t) (sizeof(struct 
sctp_auth_hmac_algo) +
+                           stcb->asoc.local_hmacs->num_algo * 
sizeof(uint16_t));
                        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_length = htons(parameter_len);
+                       sctp_serialize_hmaclist(stcb->asoc.local_hmacs, 
(uint8_t *) hmacs->hmac_ids);
+                       padding_len = SCTP_SIZE32(parameter_len) - 
parameter_len;
+                       chunk_len += parameter_len;
                }
                /* add CHUNKS parameter */
-               chunks = (struct sctp_auth_chunk_list *)(mtod(m, 
caddr_t)+SCTP_BUF_LEN(m));
-               p_len = sctp_serialize_auth_chunks(stcb->asoc.local_auth_chunks,
-                   chunks->chunk_types);
-               if (p_len > 0) {
-                       p_len += sizeof(*chunks);
+               if (sctp_auth_get_chklist_size(stcb->asoc.local_auth_chunks) > 
0) {
+                       struct sctp_auth_chunk_list *chunks;
+
+                       if (padding_len > 0) {
+                               memset(mtod(m, caddr_t)+chunk_len, 0, 
padding_len);
+                               chunk_len += padding_len;
+                               padding_len = 0;
+                       }
+                       chunks = (struct sctp_auth_chunk_list *)(mtod(m, 
caddr_t)+chunk_len);
+                       parameter_len = (uint16_t) (sizeof(struct 
sctp_auth_chunk_list) +
+                           
sctp_auth_get_chklist_size(stcb->asoc.local_auth_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_length = htons(parameter_len);
+                       
sctp_serialize_auth_chunks(stcb->asoc.local_auth_chunks, chunks->chunk_types);
+                       padding_len = SCTP_SIZE32(parameter_len) - 
parameter_len;
+                       chunk_len += parameter_len;
                }
        }
-       /* 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
-                * assoc structure. Then 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.
-                */
-
-               scp.ipv4_addr_legal = stcb->asoc.ipv4_addr_legal;
-               scp.ipv6_addr_legal = stcb->asoc.ipv6_addr_legal;
-               scp.loopback_scope = stcb->asoc.loopback_scope;
-               scp.ipv4_local_scope = stcb->asoc.ipv4_local_scope;
-               scp.local_scope = stcb->asoc.local_scope;
-               scp.site_scope = stcb->asoc.site_scope;
-
-               sctp_add_addresses_to_i_ia(inp, stcb, &scp, m, cnt_inits_to);
-       }
+       SCTP_BUF_LEN(m) = chunk_len;
 
-       /* calulate the size and update pkt header and chunk header */
-       p_len = 0;
-       for (m_at = m; m_at; m_at = SCTP_BUF_NEXT(m_at)) {
-               if (SCTP_BUF_NEXT(m_at) == NULL)
-                       mp_last = m_at;
-               p_len += SCTP_BUF_LEN(m_at);
-       }
-       init->ch.chunk_length = htons(p_len);
+       /* now the addresses */
        /*
-        * We sifa 0 here to NOT set IP_DF if its IPv4, we ignore the return
-        * here since the timer will drive a retranmission.
-        */
+        * To optimize this we could put the scoping stuff into a structure
+        * and remove the individual uint8's from the assoc structure. Then
+        * 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.
+        */
+       scp.ipv4_addr_legal = stcb->asoc.ipv4_addr_legal;
+       scp.ipv6_addr_legal = stcb->asoc.ipv6_addr_legal;
+       scp.loopback_scope = stcb->asoc.loopback_scope;
+       scp.ipv4_local_scope = stcb->asoc.ipv4_local_scope;
+       scp.local_scope = stcb->asoc.local_scope;
+       scp.site_scope = stcb->asoc.site_scope;
+       sctp_add_addresses_to_i_ia(inp, stcb, &scp, 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;
 
-       /* I don't expect this to execute but we will be safe here */
-       padval = p_len % 4;
-       if ((padval) && (mp_last)) {
-               /*
-                * The compiler worries that mp_last may not be set even
-                * though I think it is impossible :-> however we add
-                * mp_last here just in case.
-                */
-               ret = sctp_add_pad_tombuf(mp_last, (4 - padval));
-               if (ret) {
-                       /* Houston we have a problem, no space */
+               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)) {
                        sctp_m_freem(m);
                        return;
                }
@@ -5753,7 +5792,7 @@ do_a_abort:
                /* I can have what I want :> */
                initack->init.num_outbound_streams = htons(i_want);
        }
-       /* tell him his limt. */
+       /* tell him his limit. */
        initack->init.num_inbound_streams =
            htons(inp->sctp_ep.max_open_streams_intome);
 
@@ -5869,7 +5908,7 @@ do_a_abort:
                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);
+               m_at = sctp_add_addresses_to_i_ia(inp, stcb, &scp, m_at, 
cnt_inits_to, NULL, NULL);
        }
 
        /* tack on the operational error if present */

Modified: stable/9/sys/netinet/sctp_output.h
==============================================================================
--- stable/9/sys/netinet/sctp_output.h  Sun Jul  7 14:20:00 2013        
(r252952)
+++ stable/9/sys/netinet/sctp_output.h  Sun Jul  7 15:18:09 2013        
(r252953)
@@ -46,7 +46,8 @@ sctp_add_addresses_to_i_ia(struct sctp_i
     struct sctp_tcb *stcb,
     struct sctp_scoping *scope,
     struct mbuf *m_at,
-    int cnt_inits_to);
+    int cnt_inits_to,
+    uint16_t * padding_len, uint16_t * chunk_len);
 
 
 int sctp_is_addr_restricted(struct sctp_tcb *, struct sctp_ifa *);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to