From owner-svn-src-all@FreeBSD.ORG Sat Dec 8 08:22:34 2012 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id BAAEE530; Sat, 8 Dec 2012 08:22:34 +0000 (UTC) (envelope-from tuexen@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 9ECEA8FC12; Sat, 8 Dec 2012 08:22:34 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.5/8.14.5) with ESMTP id qB88MYgR099877; Sat, 8 Dec 2012 08:22:34 GMT (envelope-from tuexen@svn.freebsd.org) Received: (from tuexen@localhost) by svn.freebsd.org (8.14.5/8.14.5/Submit) id qB88MY0Q099875; Sat, 8 Dec 2012 08:22:34 GMT (envelope-from tuexen@svn.freebsd.org) Message-Id: <201212080822.qB88MY0Q099875@svn.freebsd.org> From: Michael Tuexen Date: Sat, 8 Dec 2012 08:22:34 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r244021 - head/sys/netinet X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 08 Dec 2012 08:22:34 -0000 Author: tuexen Date: Sat Dec 8 08:22:33 2012 New Revision: 244021 URL: http://svnweb.freebsd.org/changeset/base/244021 Log: 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(). MFC after: 2 weeks Modified: head/sys/netinet/sctp_output.c head/sys/netinet/sctp_output.h Modified: head/sys/netinet/sctp_output.c ============================================================================== --- head/sys/netinet/sctp_output.c Sat Dec 8 07:37:12 2012 (r244020) +++ head/sys/netinet/sctp_output.c Sat Dec 8 08:22:33 2012 (r244021) @@ -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_NOWAIT, 1, MT_DATA); + SCTP_BUF_NEXT(mret) = sctp_get_mbuf_for_msg(plen, 0, M_NOWAIT, 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: head/sys/netinet/sctp_output.h ============================================================================== --- head/sys/netinet/sctp_output.h Sat Dec 8 07:37:12 2012 (r244020) +++ head/sys/netinet/sctp_output.h Sat Dec 8 08:22:33 2012 (r244021) @@ -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 *);