18c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*- 28c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. 3ecc6b8c25a7e8d9d2b78889e88224354a1cc3160tuexen * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. 4ecc6b8c25a7e8d9d2b78889e88224354a1cc3160tuexen * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. 58c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 68c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Redistribution and use in source and binary forms, with or without 78c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * modification, are permitted provided that the following conditions are met: 88c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 98c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * a) Redistributions of source code must retain the above copyright notice, 100ac02f34d6041cd0018437596a5a9a94685e6919tuexen * this list of conditions and the following disclaimer. 118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * b) Redistributions in binary form must reproduce the above copyright 138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * notice, this list of conditions and the following disclaimer in 140ac02f34d6041cd0018437596a5a9a94685e6919tuexen * the documentation and/or other materials provided with the distribution. 158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * c) Neither the name of Cisco Systems, Inc. nor the names of its 178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * contributors may be used to endorse or promote products derived 188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * from this software without specific prior written permission. 198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * THE POSSIBILITY OF SUCH DAMAGE. 318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef __FreeBSD__ 348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <sys/cdefs.h> 351b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t__FBSDID("$FreeBSD: head/sys/netinet/sctp_asconf.c 271228 2014-09-07 17:07:19Z tuexen $"); 368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 37ecc6b8c25a7e8d9d2b78889e88224354a1cc3160tuexen 388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_os.h> 398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_var.h> 408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_sysctl.h> 418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_pcb.h> 428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_header.h> 438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctputil.h> 448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_output.h> 458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_asconf.h> 468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_timer.h> 478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * debug flags: 508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * SCTP_DEBUG_ASCONF1: protocol info, general info and errors 518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * SCTP_DEBUG_ASCONF2: detailed info 528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__) 558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#define APPLE_FILE_NO 1 568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 59e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen * RFC 5061 608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * An ASCONF parameter queue exists per asoc which holds the pending address 628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * operations. Lists are updated upon receipt of ASCONF-ACK. 638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * A restricted_addrs list exists per assoc to hold local addresses that are 658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * not (yet) usable by the assoc as a source address. These addresses are 668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * either pending an ASCONF operation (and exist on the ASCONF parameter 678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * queue), or they are permanently restricted (the peer has returned an 688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ERROR indication to an ASCONF(ADD), or the peer does not support ASCONF). 698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Deleted addresses are always immediately removed from the lists as they will 718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * (shortly) no longer exist in the kernel. We send ASCONFs as a courtesy, 728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * only if allowed. 738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ASCONF parameter processing. 778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * response_required: set if a reply is required (eg. SUCCESS_REPORT). 788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * returns a mbuf to an "error" response parameter or NULL/"success" if ok. 798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * FIX: allocating this many mbufs on the fly is pretty inefficient... 808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic struct mbuf * 828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_asconf_success_response(uint32_t id) 838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *m_reply = NULL; 858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_asconf_paramhdr *aph; 868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m_reply = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_paramhdr), 8868beeca578347438d9c434680197647ed551935ft 0, M_NOWAIT, 1, MT_DATA); 898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (m_reply == NULL) { 908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, 918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "asconf_success_response: couldn't get mbuf!\n"); 92b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (NULL); 938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aph = mtod(m_reply, struct sctp_asconf_paramhdr *); 958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aph->correlation_id = id; 968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aph->ph.param_type = htons(SCTP_SUCCESS_REPORT); 978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aph->ph.param_length = sizeof(struct sctp_asconf_paramhdr); 988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BUF_LEN(m_reply) = aph->ph.param_length; 998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aph->ph.param_length = htons(aph->ph.param_length); 1008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 101b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (m_reply); 1028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 1038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 1048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic struct mbuf * 1058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_asconf_error_response(uint32_t id, uint16_t cause, uint8_t *error_tlv, 1068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t tlv_length) 1078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 1088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *m_reply = NULL; 1098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_asconf_paramhdr *aph; 1108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_error_cause *error; 1118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint8_t *tlv; 1128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 1138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m_reply = sctp_get_mbuf_for_msg((sizeof(struct sctp_asconf_paramhdr) + 1148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tlv_length + 1158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_error_cause)), 11668beeca578347438d9c434680197647ed551935ft 0, M_NOWAIT, 1, MT_DATA); 1178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (m_reply == NULL) { 1188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, 1198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "asconf_error_response: couldn't get mbuf!\n"); 120b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (NULL); 1218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aph = mtod(m_reply, struct sctp_asconf_paramhdr *); 1238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen error = (struct sctp_error_cause *)(aph + 1); 1248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 1258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aph->correlation_id = id; 1268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aph->ph.param_type = htons(SCTP_ERROR_CAUSE_IND); 1278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen error->code = htons(cause); 1288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen error->length = tlv_length + sizeof(struct sctp_error_cause); 1298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aph->ph.param_length = error->length + 1308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_asconf_paramhdr); 1318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 1328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (aph->ph.param_length > MLEN) { 1338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, 1348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "asconf_error_response: tlv_length (%xh) too big\n", 1358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tlv_length); 1368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(m_reply); /* discard */ 137b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (NULL); 1388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (error_tlv != NULL) { 1408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tlv = (uint8_t *) (error + 1); 1418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memcpy(tlv, error_tlv, tlv_length); 1428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BUF_LEN(m_reply) = aph->ph.param_length; 1448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen error->length = htons(error->length); 1458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aph->ph.param_length = htons(aph->ph.param_length); 1468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 147b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (m_reply); 1488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 1498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 1508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic struct mbuf * 151e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexensctp_process_asconf_add_ip(struct sockaddr *src, struct sctp_asconf_paramhdr *aph, 1528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *stcb, int send_hb, int response_required) 1538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 1548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net; 1558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *m_reply = NULL; 156bfb1bf7e665a02b48026482bf33d05c83dfad73bt union sctp_sockstore store; 1578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_paramhdr *ph; 158facb9a509f7ae3621b7d2771319811985d9c46b7t uint16_t param_type, aparam_length; 159facb9a509f7ae3621b7d2771319811985d9c46b7t#if defined(INET) || defined(INET6) 160facb9a509f7ae3621b7d2771319811985d9c46b7t uint16_t param_length; 161facb9a509f7ae3621b7d2771319811985d9c46b7t#endif 1628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr *sa; 1638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int zero_address = 0; 1648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int bad_address = 0; 1658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 1668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in *sin; 1678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ipv4addr_param *v4addr; 1688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 1698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 1708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in6 *sin6; 1718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ipv6addr_param *v6addr; 1728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 1738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 1748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aparam_length = ntohs(aph->ph.param_length); 1758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ph = (struct sctp_paramhdr *)(aph + 1); 1768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen param_type = ntohs(ph->param_type); 177facb9a509f7ae3621b7d2771319811985d9c46b7t#if defined(INET) || defined(INET6) 1788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen param_length = ntohs(ph->param_length); 179facb9a509f7ae3621b7d2771319811985d9c46b7t#endif 180bfb1bf7e665a02b48026482bf33d05c83dfad73bt sa = &store.sa; 1818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (param_type) { 1828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 1838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_IPV4_ADDRESS: 1848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (param_length != sizeof(struct sctp_ipv4addr_param)) { 1858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* invalid param size */ 186b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (NULL); 1878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen v4addr = (struct sctp_ipv4addr_param *)ph; 189bfb1bf7e665a02b48026482bf33d05c83dfad73bt sin = &store.sin; 1908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen bzero(sin, sizeof(*sin)); 1918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin->sin_family = AF_INET; 1927b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN_LEN 1938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin->sin_len = sizeof(struct sockaddr_in); 1948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 1958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin->sin_port = stcb->rport; 1968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin->sin_addr.s_addr = v4addr->addr; 1978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((sin->sin_addr.s_addr == INADDR_BROADCAST) || 1988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) { 1998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen bad_address = 1; 2008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sin->sin_addr.s_addr == INADDR_ANY) 2028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen zero_address = 1; 2038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_add_ip: adding "); 2048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); 2058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 2068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 2078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 2088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_IPV6_ADDRESS: 2098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (param_length != sizeof(struct sctp_ipv6addr_param)) { 2108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* invalid param size */ 211b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (NULL); 2128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen v6addr = (struct sctp_ipv6addr_param *)ph; 214bfb1bf7e665a02b48026482bf33d05c83dfad73bt sin6 = &store.sin6; 2158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen bzero(sin6, sizeof(*sin6)); 2168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6->sin6_family = AF_INET6; 2177b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN6_LEN 2188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6->sin6_len = sizeof(struct sockaddr_in6); 2198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 2208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6->sin6_port = stcb->rport; 2218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memcpy((caddr_t)&sin6->sin6_addr, v6addr->addr, 2228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct in6_addr)); 2238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { 2248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen bad_address = 1; 2258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) 2278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen zero_address = 1; 2288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_add_ip: adding "); 2298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); 2308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 2318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 2328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 2338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m_reply = sctp_asconf_error_response(aph->correlation_id, 2348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_CAUSE_INVALID_PARAM, (uint8_t *) aph, 2358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aparam_length); 236b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (m_reply); 2378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } /* end switch */ 2388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 2398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* if 0.0.0.0/::0, add the source address instead */ 2408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (zero_address && SCTP_BASE_SYSCTL(sctp_nat_friendly)) { 241e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen sa = src; 2428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, 2438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "process_asconf_add_ip: using source addr "); 244e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, src); 2458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* add the address */ 2478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (bad_address) { 2488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m_reply = sctp_asconf_error_response(aph->correlation_id, 2498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_CAUSE_INVALID_PARAM, (uint8_t *) aph, 250000a5bac556b28e74e4e98c540f66b1743e9312dtuexen aparam_length); 2518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (sctp_add_remote_addr(stcb, sa, &net, SCTP_DONOT_SETSCOPE, 2528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ADDR_DYNAMIC_ADDED) != 0) { 2538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, 2548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "process_asconf_add_ip: error adding address\n"); 2558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m_reply = sctp_asconf_error_response(aph->correlation_id, 2568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_CAUSE_RESOURCE_SHORTAGE, (uint8_t *) aph, 2578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aparam_length); 2588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 2598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* notify upper layer */ 2608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ulp_notify(SCTP_NOTIFY_ASCONF_ADD_IP, stcb, 0, sa, SCTP_SO_NOT_LOCKED); 2618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (response_required) { 2628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m_reply = 2638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_asconf_success_response(aph->correlation_id); 2648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, stcb->sctp_ep, stcb, net); 2668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, 2678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb, net); 2688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (send_hb) { 2698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED); 2708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 272b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (m_reply); 2738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 2748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 2758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int 2768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_asconf_del_remote_addrs_except(struct sctp_tcb *stcb, struct sockaddr *src) 2778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 2788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *src_net, *net; 2798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 2808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* make sure the source address exists as a destination net */ 2818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen src_net = sctp_findnet(stcb, src); 2828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (src_net == NULL) { 2838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* not found */ 284b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (-1); 2858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 2878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* delete all destination addresses except the source */ 2888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 2898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net != src_net) { 2908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* delete this address */ 2918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_remove_net(stcb, net); 2928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, 2938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "asconf_del_remote_addrs_except: deleting "); 2948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, 2958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (struct sockaddr *)&net->ro._l_addr); 2968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* notify upper layer */ 2978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ulp_notify(SCTP_NOTIFY_ASCONF_DELETE_IP, stcb, 0, 2988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (struct sockaddr *)&net->ro._l_addr, SCTP_SO_NOT_LOCKED); 2998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 301b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (0); 3028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 3038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 3048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic struct mbuf * 305e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexensctp_process_asconf_delete_ip(struct sockaddr *src, 306e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen struct sctp_asconf_paramhdr *aph, 3078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *stcb, int response_required) 3088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 3098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *m_reply = NULL; 310bfb1bf7e665a02b48026482bf33d05c83dfad73bt union sctp_sockstore store; 3118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_paramhdr *ph; 312facb9a509f7ae3621b7d2771319811985d9c46b7t uint16_t param_type, aparam_length; 313facb9a509f7ae3621b7d2771319811985d9c46b7t#if defined(INET) || defined(INET6) 314facb9a509f7ae3621b7d2771319811985d9c46b7t uint16_t param_length; 315facb9a509f7ae3621b7d2771319811985d9c46b7t#endif 3168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr *sa; 3178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int zero_address = 0; 3188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int result; 3198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 3208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in *sin; 3218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ipv4addr_param *v4addr; 3228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 3238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 3248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in6 *sin6; 3258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ipv6addr_param *v6addr; 3268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 3278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 3288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aparam_length = ntohs(aph->ph.param_length); 3298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ph = (struct sctp_paramhdr *)(aph + 1); 3308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen param_type = ntohs(ph->param_type); 331facb9a509f7ae3621b7d2771319811985d9c46b7t#if defined(INET) || defined(INET6) 3328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen param_length = ntohs(ph->param_length); 333facb9a509f7ae3621b7d2771319811985d9c46b7t#endif 334bfb1bf7e665a02b48026482bf33d05c83dfad73bt sa = &store.sa; 3358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (param_type) { 3368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 3378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_IPV4_ADDRESS: 3388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (param_length != sizeof(struct sctp_ipv4addr_param)) { 3398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* invalid param size */ 340b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (NULL); 3418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen v4addr = (struct sctp_ipv4addr_param *)ph; 343bfb1bf7e665a02b48026482bf33d05c83dfad73bt sin = &store.sin; 3448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen bzero(sin, sizeof(*sin)); 3458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin->sin_family = AF_INET; 3467b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN_LEN 3478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin->sin_len = sizeof(struct sockaddr_in); 3488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 3498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin->sin_port = stcb->rport; 3508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin->sin_addr.s_addr = v4addr->addr; 3518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sin->sin_addr.s_addr == INADDR_ANY) 3528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen zero_address = 1; 3538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, 3548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "process_asconf_delete_ip: deleting "); 3558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); 3568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 3578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 3588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 3598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_IPV6_ADDRESS: 3608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (param_length != sizeof(struct sctp_ipv6addr_param)) { 3618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* invalid param size */ 362b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (NULL); 3638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen v6addr = (struct sctp_ipv6addr_param *)ph; 365bfb1bf7e665a02b48026482bf33d05c83dfad73bt sin6 = &store.sin6; 3668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen bzero(sin6, sizeof(*sin6)); 3678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6->sin6_family = AF_INET6; 3687b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN6_LEN 3698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6->sin6_len = sizeof(struct sockaddr_in6); 3708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 3718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6->sin6_port = stcb->rport; 3728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memcpy(&sin6->sin6_addr, v6addr->addr, 3738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct in6_addr)); 3748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) 3758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen zero_address = 1; 3768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, 3778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "process_asconf_delete_ip: deleting "); 3788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); 3798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 3808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 3818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 3828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m_reply = sctp_asconf_error_response(aph->correlation_id, 3838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph, 3848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aparam_length); 385b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (m_reply); 3868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 3888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* make sure the source address is not being deleted */ 389e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen if (sctp_cmpaddr(sa, src)) { 3908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* trying to delete the source address! */ 3918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_delete_ip: tried to delete source addr\n"); 3928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m_reply = sctp_asconf_error_response(aph->correlation_id, 3938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_CAUSE_DELETING_SRC_ADDR, (uint8_t *) aph, 3948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aparam_length); 395b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (m_reply); 3968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 3988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* if deleting 0.0.0.0/::0, delete all addresses except src addr */ 3998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (zero_address && SCTP_BASE_SYSCTL(sctp_nat_friendly)) { 400e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen result = sctp_asconf_del_remote_addrs_except(stcb, src); 4018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 4028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (result) { 4038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* src address did not exist? */ 4048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_delete_ip: src addr does not exist?\n"); 4058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* what error to reply with?? */ 4068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m_reply = 4078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_asconf_error_response(aph->correlation_id, 4088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_CAUSE_REQUEST_REFUSED, (uint8_t *) aph, 4098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aparam_length); 4108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (response_required) { 4118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m_reply = 4128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_asconf_success_response(aph->correlation_id); 4138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 414b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (m_reply); 4158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 4178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* delete the address */ 4188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen result = sctp_del_remote_addr(stcb, sa); 4198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 4208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * note if result == -2, the address doesn't exist in the asoc but 4218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * since it's being deleted anyways, we just ack the delete -- but 4228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * this probably means something has already gone awry 4238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 4248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (result == -1) { 4258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* only one address in the asoc */ 4268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_delete_ip: tried to delete last IP addr!\n"); 4278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m_reply = sctp_asconf_error_response(aph->correlation_id, 4288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_CAUSE_DELETING_LAST_ADDR, (uint8_t *) aph, 4298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aparam_length); 4308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 4318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (response_required) { 432e2828360ea9cf8951730d46f5c14626c9425cb30t m_reply = sctp_asconf_success_response(aph->correlation_id); 4338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* notify upper layer */ 4358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ulp_notify(SCTP_NOTIFY_ASCONF_DELETE_IP, stcb, 0, sa, SCTP_SO_NOT_LOCKED); 4368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 437b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (m_reply); 4388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 4398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 4408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic struct mbuf * 441e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexensctp_process_asconf_set_primary(struct sockaddr *src, 4428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_asconf_paramhdr *aph, 4438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *stcb, int response_required) 4448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 4458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *m_reply = NULL; 446bfb1bf7e665a02b48026482bf33d05c83dfad73bt union sctp_sockstore store; 4478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_paramhdr *ph; 448facb9a509f7ae3621b7d2771319811985d9c46b7t uint16_t param_type, aparam_length; 449facb9a509f7ae3621b7d2771319811985d9c46b7t#if defined(INET) || defined(INET6) 450facb9a509f7ae3621b7d2771319811985d9c46b7t uint16_t param_length; 451facb9a509f7ae3621b7d2771319811985d9c46b7t#endif 4528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr *sa; 4538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int zero_address = 0; 4548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 4558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in *sin; 4568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ipv4addr_param *v4addr; 4578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 4588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 4598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in6 *sin6; 4608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ipv6addr_param *v6addr; 4618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 4628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 4638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aparam_length = ntohs(aph->ph.param_length); 4648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ph = (struct sctp_paramhdr *)(aph + 1); 4658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen param_type = ntohs(ph->param_type); 466facb9a509f7ae3621b7d2771319811985d9c46b7t#if defined(INET) || defined(INET6) 4678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen param_length = ntohs(ph->param_length); 468facb9a509f7ae3621b7d2771319811985d9c46b7t#endif 469bfb1bf7e665a02b48026482bf33d05c83dfad73bt sa = &store.sa; 4708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (param_type) { 4718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 4728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_IPV4_ADDRESS: 4738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (param_length != sizeof(struct sctp_ipv4addr_param)) { 4748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* invalid param size */ 475b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (NULL); 4768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen v4addr = (struct sctp_ipv4addr_param *)ph; 478bfb1bf7e665a02b48026482bf33d05c83dfad73bt sin = &store.sin; 4798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen bzero(sin, sizeof(*sin)); 4808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin->sin_family = AF_INET; 4817b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN_LEN 4828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin->sin_len = sizeof(struct sockaddr_in); 4838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 4848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin->sin_addr.s_addr = v4addr->addr; 4858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sin->sin_addr.s_addr == INADDR_ANY) 4868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen zero_address = 1; 4878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_set_primary: "); 4888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); 4898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 4908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 4918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 4928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_IPV6_ADDRESS: 4938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (param_length != sizeof(struct sctp_ipv6addr_param)) { 4948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* invalid param size */ 495b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (NULL); 4968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen v6addr = (struct sctp_ipv6addr_param *)ph; 498bfb1bf7e665a02b48026482bf33d05c83dfad73bt sin6 = &store.sin6; 4998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen bzero(sin6, sizeof(*sin6)); 5008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6->sin6_family = AF_INET6; 5017b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN6_LEN 5028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6->sin6_len = sizeof(struct sockaddr_in6); 5038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 5048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memcpy((caddr_t)&sin6->sin6_addr, v6addr->addr, 5058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct in6_addr)); 5068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) 5078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen zero_address = 1; 5088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_set_primary: "); 5098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); 5108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 5118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 5128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 5138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m_reply = sctp_asconf_error_response(aph->correlation_id, 5148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph, 5158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aparam_length); 516b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (m_reply); 5178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 5198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* if 0.0.0.0/::0, use the source address instead */ 5208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (zero_address && SCTP_BASE_SYSCTL(sctp_nat_friendly)) { 521e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen sa = src; 5228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, 5238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "process_asconf_set_primary: using source addr "); 524e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, src); 5258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* set the primary address */ 5278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_set_primary_addr(stcb, sa, NULL) == 0) { 5288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, 5298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "process_asconf_set_primary: primary address set\n"); 5308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* notify upper layer */ 5318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ulp_notify(SCTP_NOTIFY_ASCONF_SET_PRIMARY, stcb, 0, sa, SCTP_SO_NOT_LOCKED); 5328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb->asoc.primary_destination->dest_state & SCTP_ADDR_REACHABLE) && 5338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (!(stcb->asoc.primary_destination->dest_state & SCTP_ADDR_PF)) && 5348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb->asoc.alternate)) { 5358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(stcb->asoc.alternate); 5368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.alternate = NULL; 5378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (response_required) { 5398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m_reply = sctp_asconf_success_response(aph->correlation_id); 5408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Mobility adaptation. 5428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen Ideally, when the reception of SET PRIMARY with DELETE IP 5438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ADDRESS of the previous primary destination, unacknowledged 5448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen DATA are retransmitted immediately to the new primary 5458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen destination for seamless handover. 5468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen If the destination is UNCONFIRMED and marked to REQ_PRIM, 5478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen The retransmission occur when reception of the 5488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen HEARTBEAT-ACK. (See sctp_handle_heartbeat_ack in 5498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_input.c) 5508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen Also, when change of the primary destination, it is better 5518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen that all subsequent new DATA containing already queued DATA 5528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen are transmitted to the new primary destination. (by micchie) 5538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 5548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((sctp_is_mobility_feature_on(stcb->sctp_ep, 555e2828360ea9cf8951730d46f5c14626c9425cb30t SCTP_MOBILITY_BASE) || 5568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_is_mobility_feature_on(stcb->sctp_ep, 557e2828360ea9cf8951730d46f5c14626c9425cb30t SCTP_MOBILITY_FASTHANDOFF)) && 5588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_is_mobility_feature_on(stcb->sctp_ep, 559e2828360ea9cf8951730d46f5c14626c9425cb30t SCTP_MOBILITY_PRIM_DELETED) && 5608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb->asoc.primary_destination->dest_state & 5618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ADDR_UNCONFIRMED) == 0) { 5628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 5638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_stop(SCTP_TIMER_TYPE_PRIM_DELETED, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_TIMER+SCTP_LOC_7); 5648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_is_mobility_feature_on(stcb->sctp_ep, 5658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MOBILITY_FASTHANDOFF)) { 5668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_assoc_immediate_retrans(stcb, 5678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.primary_destination); 5688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_is_mobility_feature_on(stcb->sctp_ep, 5708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MOBILITY_BASE)) { 5718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_move_chunks_from_net(stcb, 5728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.deleted_primary); 5738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_delete_prim_timer(stcb->sctp_ep, stcb, 5758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.deleted_primary); 5768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 5788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* couldn't set the requested primary address! */ 5798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, 5808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "process_asconf_set_primary: set primary failed!\n"); 5818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* must have been an invalid address, so report */ 5828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m_reply = sctp_asconf_error_response(aph->correlation_id, 5838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph, 5848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aparam_length); 5858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 587b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (m_reply); 5888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 5898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 5908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 5918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * handles an ASCONF chunk. 5928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * if all parameters are processed ok, send a plain (empty) ASCONF-ACK 5938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 5948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 5958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_handle_asconf(struct mbuf *m, unsigned int offset, 596e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen struct sockaddr *src, 5978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_asconf_chunk *cp, struct sctp_tcb *stcb, 5988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int first) 5998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 6008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc; 6018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t serial_num; 6028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *n, *m_ack, *m_result, *m_tail; 6038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_asconf_ack_chunk *ack_cp; 6048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_asconf_paramhdr *aph, *ack_aph; 6058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ipv6addr_param *p_addr; 6068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen unsigned int asconf_limit, cnt; 6078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int error = 0; /* did an error occur? */ 6088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 6098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* asconf param buffer */ 6108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint8_t aparam_buf[SCTP_PARAM_BUFFER_SIZE]; 6118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_asconf_ack *ack, *ack_next; 6128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 6138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* verify minimum length */ 6148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_asconf_chunk)) { 6158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, 6168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "handle_asconf: chunk too small = %xh\n", 6178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ntohs(cp->ch.chunk_length)); 6188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 6198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc = &stcb->asoc; 6218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen serial_num = ntohl(cp->serial_number); 6228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 6238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GE(asoc->asconf_seq_in, serial_num)) { 6248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* got a duplicate ASCONF */ 6258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, 6268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "handle_asconf: got duplicate serial number = %xh\n", 6278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen serial_num); 6288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 6298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (serial_num != (asoc->asconf_seq_in + 1)) { 6308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: incorrect serial number = %xh (expected next = %xh)\n", 6318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen serial_num, asoc->asconf_seq_in + 1); 6328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 6338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 6358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* it's the expected "next" sequence number, so process it */ 6368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->asconf_seq_in = serial_num; /* update sequence */ 6378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* get length of all the param's in the ASCONF */ 6388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asconf_limit = offset + ntohs(cp->ch.chunk_length); 6398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, 6408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "handle_asconf: asconf_limit=%u, sequence=%xh\n", 6418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asconf_limit, serial_num); 6428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 6438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (first) { 6448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* delete old cache */ 6458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1,"handle_asconf: Now processing first ASCONF. Try to delete old cache\n"); 6468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 6478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(ack, &asoc->asconf_ack_sent, next, ack_next) { 6488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ack->serial_number == serial_num) 6498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 6508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1,"handle_asconf: delete old(%u) < first(%u)\n", 6518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ack->serial_number, serial_num); 6528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&asoc->asconf_ack_sent, ack, next); 6538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ack->data != NULL) { 6548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(ack->data); 6558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asconf_ack), ack); 6578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 6608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m_ack = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_ack_chunk), 0, 66168beeca578347438d9c434680197647ed551935ft M_NOWAIT, 1, MT_DATA); 6628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (m_ack == NULL) { 6638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, 6648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "handle_asconf: couldn't get mbuf!\n"); 6658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 6668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m_tail = m_ack; /* current reply chain's tail */ 6688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 6698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* fill in ASCONF-ACK header */ 6708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ack_cp = mtod(m_ack, struct sctp_asconf_ack_chunk *); 6718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ack_cp->ch.chunk_type = SCTP_ASCONF_ACK; 6728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ack_cp->ch.chunk_flags = 0; 6738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ack_cp->serial_number = htonl(serial_num); 6748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* set initial lengths (eg. just an ASCONF-ACK), ntohx at the end! */ 6758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BUF_LEN(m_ack) = sizeof(struct sctp_asconf_ack_chunk); 6768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ack_cp->ch.chunk_length = sizeof(struct sctp_asconf_ack_chunk); 6778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 6788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* skip the lookup address parameter */ 6798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen offset += sizeof(struct sctp_asconf_chunk); 6808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen p_addr = (struct sctp_ipv6addr_param *)sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr), (uint8_t *)&aparam_buf); 6818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (p_addr == NULL) { 6828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, 6838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "handle_asconf: couldn't get lookup addr!\n"); 6848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* respond with a missing/invalid mandatory parameter error */ 6858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 6868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* param_length is already validated in process_control... */ 6888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen offset += ntohs(p_addr->ph.param_length); /* skip lookup addr */ 6898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 6908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* get pointer to first asconf param in ASCONF-ACK */ 691b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen ack_aph = (struct sctp_asconf_paramhdr *)(mtod(m_ack, caddr_t) + sizeof(struct sctp_asconf_ack_chunk)); 6928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ack_aph == NULL) { 6938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "Gak in asconf2\n"); 6948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 6958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* get pointer to first asconf param in ASCONF */ 6978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, sizeof(struct sctp_asconf_paramhdr), (uint8_t *)&aparam_buf); 6988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (aph == NULL) { 6998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "Empty ASCONF received?\n"); 7008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto send_reply; 7018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* process through all parameters */ 7038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cnt = 0; 7048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen while (aph != NULL) { 7058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen unsigned int param_length, param_type; 7068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 7078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen param_type = ntohs(aph->ph.param_type); 7088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen param_length = ntohs(aph->ph.param_length); 7098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (offset + param_length > asconf_limit) { 7108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* parameter goes beyond end of chunk! */ 7118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(m_ack); 7128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 7138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m_result = NULL; 7158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 7168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (param_length > sizeof(aparam_buf)) { 7178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: param length (%u) larger than buffer size!\n", param_length); 7188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(m_ack); 7198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 7208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (param_length <= sizeof(struct sctp_paramhdr)) { 7228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: param length (%u) too short\n", param_length); 7238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(m_ack); 7248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* get the entire parameter */ 7268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, param_length, aparam_buf); 7278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (aph == NULL) { 7288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: couldn't get entire param\n"); 7298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(m_ack); 7308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 7318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (param_type) { 7338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_ADD_IP_ADDRESS: 734e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen m_result = sctp_process_asconf_add_ip(src, aph, stcb, 7358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (cnt < SCTP_BASE_SYSCTL(sctp_hb_maxburst)), error); 7368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cnt++; 7378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 7388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_DEL_IP_ADDRESS: 739e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen m_result = sctp_process_asconf_delete_ip(src, aph, stcb, 7408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen error); 7418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 7428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_ERROR_CAUSE_IND: 7438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* not valid in an ASCONF chunk */ 7448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 7458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_SET_PRIM_ADDR: 746e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen m_result = sctp_process_asconf_set_primary(src, aph, 7478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb, error); 7488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 7498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_NAT_VTAGS: 7508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: sees a NAT VTAG state parameter\n"); 7518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 7528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_SUCCESS_REPORT: 7538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* not valid in an ASCONF chunk */ 7548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 7558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_ULP_ADAPTATION: 7568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* FIX */ 7578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 7588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 7598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((param_type & 0x8000) == 0) { 7608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Been told to STOP at this param */ 7618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asconf_limit = offset; 7628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 7638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * FIX FIX - We need to call 7648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sctp_arethere_unrecognized_parameters() 7658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * to get a operr and send it for any 7668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * param's with the 0x4000 bit set OR do it 7678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * here ourselves... note we still must STOP 7688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * if the 0x8000 bit is clear. 7698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 7708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* unknown/invalid param type */ 7728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 7738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } /* switch */ 7748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 7758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* add any (error) result to the reply mbuf chain */ 7768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (m_result != NULL) { 7778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BUF_NEXT(m_tail) = m_result; 7788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m_tail = m_result; 7798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* update lengths, make sure it's aligned too */ 7808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BUF_LEN(m_result) = SCTP_SIZE32(SCTP_BUF_LEN(m_result)); 7818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ack_cp->ch.chunk_length += SCTP_BUF_LEN(m_result); 7828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* set flag to force success reports */ 7838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen error = 1; 7848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen offset += SCTP_SIZE32(param_length); 7868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* update remaining ASCONF message length to process */ 7878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (offset >= asconf_limit) { 7888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* no more data in the mbuf chain */ 7898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 7908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* get pointer to next asconf param */ 7928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, 7938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_asconf_paramhdr), 7948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (uint8_t *)&aparam_buf); 7958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (aph == NULL) { 7968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* can't get an asconf paramhdr */ 7978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: can't get asconf param hdr!\n"); 7988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* FIX ME - add error here... */ 7998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 8028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen send_reply: 8038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ack_cp->ch.chunk_length = htons(ack_cp->ch.chunk_length); 8048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* save the ASCONF-ACK reply */ 8058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ack = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_asconf_ack), 8068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_asconf_ack); 8078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ack == NULL) { 8088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(m_ack); 8098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 8108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ack->serial_number = serial_num; 8128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ack->last_sent_to = NULL; 8138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ack->data = m_ack; 8148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ack->len = 0; 8158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (n = m_ack; n != NULL; n = SCTP_BUF_NEXT(n)) { 8168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ack->len += SCTP_BUF_LEN(n); 8178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INSERT_TAIL(&stcb->asoc.asconf_ack_sent, ack, next); 8198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 8208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* see if last_control_chunk_from is set properly (use IP src addr) */ 8218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.last_control_chunk_from == NULL) { 8228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 8238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * this could happen if the source address was just newly 8248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * added 8258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 8268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: looking up net for IP source address\n"); 8270c9710564cb3e091ff51af93a22257aa33f2e6catuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "Looking for IP source: "); 8280c9710564cb3e091ff51af93a22257aa33f2e6catuexen SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, src); 8290c9710564cb3e091ff51af93a22257aa33f2e6catuexen /* look up the from address */ 8300c9710564cb3e091ff51af93a22257aa33f2e6catuexen stcb->asoc.last_control_chunk_from = sctp_findnet(stcb, src); 8318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_DEBUG 8320c9710564cb3e091ff51af93a22257aa33f2e6catuexen if (stcb->asoc.last_control_chunk_from == NULL) { 8330c9710564cb3e091ff51af93a22257aa33f2e6catuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: IP source address not found?!\n"); 8348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8350c9710564cb3e091ff51af93a22257aa33f2e6catuexen#endif 8368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 8388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 8398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 8408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * does the address match? returns 0 if not, 1 if so 8418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 8428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic uint32_t 8438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_asconf_addr_match(struct sctp_asconf_addr *aa, struct sockaddr *sa) 8448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 8458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (sa->sa_family) { 8468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 8478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 8488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 8498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* XXX scopeid */ 8508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; 8518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 8528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((aa->ap.addrp.ph.param_type == SCTP_IPV6_ADDRESS) && 8538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (memcmp(&aa->ap.addrp.addr, &sin6->sin6_addr, 8548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct in6_addr)) == 0)) { 8558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (1); 8568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 8588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 8608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 8618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 8628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 8638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in *sin = (struct sockaddr_in *)sa; 8648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 8658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((aa->ap.addrp.ph.param_type == SCTP_IPV4_ADDRESS) && 8668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (memcmp(&aa->ap.addrp.addr, &sin->sin_addr, 8678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct in_addr)) == 0)) { 8688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (1); 8698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 8718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 8738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 8748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 8758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 8778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 8788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 8798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 8808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * does the address match? returns 0 if not, 1 if so 8818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 8828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic uint32_t 8838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_addr_match(struct sctp_paramhdr *ph, struct sockaddr *sa) 8848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 885facb9a509f7ae3621b7d2771319811985d9c46b7t#if defined(INET) || defined(INET6) 8868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t param_type, param_length; 8878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 8888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen param_type = ntohs(ph->param_type); 8898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen param_length = ntohs(ph->param_length); 890facb9a509f7ae3621b7d2771319811985d9c46b7t#endif 8918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (sa->sa_family) { 8928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 8938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 8948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 8958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* XXX scopeid */ 8968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; 8978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ipv6addr_param *v6addr; 8988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 8998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen v6addr = (struct sctp_ipv6addr_param *)ph; 9008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((param_type == SCTP_IPV6_ADDRESS) && 901facb9a509f7ae3621b7d2771319811985d9c46b7t (param_length == sizeof(struct sctp_ipv6addr_param)) && 9028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (memcmp(&v6addr->addr, &sin6->sin6_addr, 9038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct in6_addr)) == 0)) { 9048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (1); 9058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 9078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 9098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 9108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 9118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 9128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in *sin = (struct sockaddr_in *)sa; 9138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ipv4addr_param *v4addr; 9148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 9158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen v4addr = (struct sctp_ipv4addr_param *)ph; 9168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((param_type == SCTP_IPV4_ADDRESS) && 917facb9a509f7ae3621b7d2771319811985d9c46b7t (param_length == sizeof(struct sctp_ipv4addr_param)) && 9188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (memcmp(&v4addr->addr, &sin->sin_addr, 9198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct in_addr)) == 0)) { 9208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (1); 9218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 9238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 9258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 9268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 9278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 9298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 9308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 9318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Cleanup for non-responded/OP ERR'd ASCONF 9328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 9338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 9348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_asconf_cleanup(struct sctp_tcb *stcb, struct sctp_nets *net) 9358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 9368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 9378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * clear out any existing asconfs going out 9388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 9398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net, 940b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen SCTP_FROM_SCTP_ASCONF+SCTP_LOC_2); 9418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.asconf_seq_out_acked = stcb->asoc.asconf_seq_out; 9428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* remove the old ASCONF on our outbound queue */ 9438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_toss_old_asconf(stcb); 9448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 9458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 9468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 9478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * cleanup any cached source addresses that may be topologically 9488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * incorrect after a new address has been added to this interface. 9498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 9508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 9518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_asconf_nets_cleanup(struct sctp_tcb *stcb, struct sctp_ifn *ifn) 9528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 9538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net; 9548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 9558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 9568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Ideally, we want to only clear cached routes and source addresses 9578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * that are topologically incorrect. But since there is no easy way 9588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * to know whether the newly added address on the ifn would cause a 9598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * routing change (i.e. a new egress interface would be chosen) 9608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * without doing a new routing lookup and source address selection, 9618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we will (for now) just flush any cached route using a different 9628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ifn (and cached source addrs) and let output re-choose them during 9638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the next send on that net. 9648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 9658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 9668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 9678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * clear any cached route (and cached source address) if the 9688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * route's interface is NOT the same as the address change. 9698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * If it's the same interface, just clear the cached source 9708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * address. 9718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 9728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_ROUTE_HAS_VALID_IFN(&net->ro) && 9738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ((ifn == NULL) || 9748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (SCTP_GET_IF_INDEX_FROM_ROUTE(&net->ro) != ifn->ifn_index))) { 9758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* clear any cached route */ 9768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen RTFREE(net->ro.ro_rt); 9778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->ro.ro_rt = NULL; 9788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* clear any cached source address */ 9808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->src_addr_selected) { 9818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_ifa(net->ro._s_addr); 9828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->ro._s_addr = NULL; 9838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->src_addr_selected = 0; 9848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 9878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 9888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 9898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 9908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_assoc_immediate_retrans(struct sctp_tcb *stcb, struct sctp_nets *dstnet) 9918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 9928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int error; 9938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 9948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (dstnet->dest_state & SCTP_ADDR_UNCONFIRMED) { 9958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 9968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.deleted_primary == NULL) { 9988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 9998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 10008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 10018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!TAILQ_EMPTY(&stcb->asoc.sent_queue)) { 10028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "assoc_immediate_retrans: Deleted primary is "); 10038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &stcb->asoc.deleted_primary->ro._l_addr.sa); 10048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "Current Primary is "); 10058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &stcb->asoc.primary_destination->ro._l_addr.sa); 10068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, 10078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.deleted_primary, 10088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FROM_SCTP_TIMER+SCTP_LOC_8); 10098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.num_send_timers_up--; 10108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.num_send_timers_up < 0) { 10118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.num_send_timers_up = 0; 10128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 10138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK_ASSERT(stcb); 10148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen error = sctp_t3rxt_timer(stcb->sctp_ep, stcb, 10158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.deleted_primary); 10168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (error) { 10178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_DECR_REF(stcb->sctp_ep); 10188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 10198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 10208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK_ASSERT(stcb); 10218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_AUDITING_ENABLED 10228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_auditing(4, stcb->sctp_ep, stcb, stcb->asoc.deleted_primary); 10238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 10248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED); 10258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb->asoc.num_send_timers_up == 0) && 10268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb->asoc.sent_queue_cnt > 0)) { 10278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *chk; 1028000a5bac556b28e74e4e98c540f66b1743e9312dtuexen 10298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk = TAILQ_FIRST(&stcb->asoc.sent_queue); 10308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, 10318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb, chk->whoTo); 10328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 10338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 10348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 10358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 10368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 10378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Userspace__) 10388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int 10398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_asconf_queue_mgmt(struct sctp_tcb *, struct sctp_ifa *, uint16_t); 10408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 10418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 10428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_net_immediate_retrans(struct sctp_tcb *stcb, struct sctp_nets *net) 10438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 10448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *chk; 10458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 10468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "net_immediate_retrans: RTO is %d\n", net->RTO); 10478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net, 10488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FROM_SCTP_TIMER+SCTP_LOC_5); 10498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net); 10508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->error_count = 0; 10518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) { 10528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->whoTo == net) { 10538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->sent < SCTP_DATAGRAM_RESEND) { 10548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->sent = SCTP_DATAGRAM_RESEND; 10558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 10568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_flight_size_decrease(chk); 10578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_total_flight_decrease(stcb, chk); 10588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->marked_retrans++; 10598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.marked_retrans++; 10608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 10618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 10628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 10638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->marked_retrans) { 10648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED); 10658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 10668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 10678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 10688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 10698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_path_check_and_react(struct sctp_tcb *stcb, struct sctp_ifa *newifa) 10708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 10718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net; 10728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int addrnum, changed; 10738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 10748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* If number of local valid addresses is 1, the valid address is 10758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen probably newly added address. 10768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen Several valid addresses in this association. A source address 10778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen may not be changed. Additionally, they can be configured on a 10788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen same interface as "alias" addresses. (by micchie) 10798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 10808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen addrnum = sctp_local_addr_count(stcb); 10818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "p_check_react(): %d local addresses\n", 10828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen addrnum); 10838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (addrnum == 1) { 10848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 10858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* clear any cached route and source address */ 10868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->ro.ro_rt) { 10878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen RTFREE(net->ro.ro_rt); 10888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->ro.ro_rt = NULL; 10898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 10908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->src_addr_selected) { 10918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_ifa(net->ro._s_addr); 10928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->ro._s_addr = NULL; 10938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->src_addr_selected = 0; 10948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 10958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Retransmit unacknowledged DATA chunks immediately */ 10968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_is_mobility_feature_on(stcb->sctp_ep, 1097e2828360ea9cf8951730d46f5c14626c9425cb30t SCTP_MOBILITY_FASTHANDOFF)) { 10988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_net_immediate_retrans(stcb, net); 10998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 11008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* also, SET PRIMARY is maybe already sent */ 11018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 11028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 11038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 11048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 11058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Multiple local addresses exsist in the association. */ 11068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 11078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* clear any cached route and source address */ 11088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->ro.ro_rt) { 11098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen RTFREE(net->ro.ro_rt); 11108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->ro.ro_rt = NULL; 11118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 11128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->src_addr_selected) { 11138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_ifa(net->ro._s_addr); 11148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->ro._s_addr = NULL; 11158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->src_addr_selected = 0; 11168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 11178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Check if the nexthop is corresponding to the new address. 11188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen If the new address is corresponding to the current nexthop, 11198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen the path will be changed. 11208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen If the new address is NOT corresponding to the current 11218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen nexthop, the path will not be changed. 11228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 11238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_RTALLOC((sctp_route_t *)&net->ro, 11248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep->def_vrf_id); 11258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->ro.ro_rt == NULL) 11268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 11278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 11288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen changed = 0; 11298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (net->ro._l_addr.sa.sa_family) { 11308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 11318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 11328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_v4src_match_nexthop(newifa, (sctp_route_t *)&net->ro)) { 11338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen changed = 1; 11348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 11358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 11368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 11378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 11388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 11398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_v6src_match_nexthop( 11408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen &newifa->address.sin6, (sctp_route_t *)&net->ro)) { 11418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen changed = 1; 11428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 11438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 11448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 11458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 11468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 11478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 11488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* if the newly added address does not relate routing 11498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen information, we skip. 11508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 11518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (changed == 0) 11528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 11538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Retransmit unacknowledged DATA chunks immediately */ 11548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_is_mobility_feature_on(stcb->sctp_ep, 1155e2828360ea9cf8951730d46f5c14626c9425cb30t SCTP_MOBILITY_FASTHANDOFF)) { 11568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_net_immediate_retrans(stcb, net); 11578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 11588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Send SET PRIMARY for this new address */ 11598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net == stcb->asoc.primary_destination) { 11608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)sctp_asconf_queue_mgmt(stcb, newifa, 11618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SET_PRIM_ADDR); 11628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 11638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 11648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 11658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* __FreeBSD__ __APPLE__ __Userspace__ */ 11668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 11678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 11688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * process an ADD/DELETE IP ack from peer. 11698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * addr: corresponding sctp_ifa to the address being added/deleted. 11708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * type: SCTP_ADD_IP_ADDRESS or SCTP_DEL_IP_ADDRESS. 11718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * flag: 1=success, 0=failure. 11728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 11738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 11740ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_asconf_addr_mgmt_ack(struct sctp_tcb *stcb, struct sctp_ifa *addr, uint32_t flag) 11758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 11768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 11778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * do the necessary asoc list work- if we get a failure indication, 11788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * leave the address on the assoc's restricted list. If we get a 11798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * success indication, remove the address from the restricted list. 11808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 11818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 11828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Note: this will only occur for ADD_IP_ADDRESS, since 11838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * DEL_IP_ADDRESS is never actually added to the list... 11848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 11858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (flag) { 11868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* success case, so remove from the restricted list */ 11878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_del_local_addr_restricted(stcb, addr); 11888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 11898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Userspace__) 11908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_is_mobility_feature_on(stcb->sctp_ep, 1191e2828360ea9cf8951730d46f5c14626c9425cb30t SCTP_MOBILITY_BASE) || 11928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_is_mobility_feature_on(stcb->sctp_ep, 1193e2828360ea9cf8951730d46f5c14626c9425cb30t SCTP_MOBILITY_FASTHANDOFF)) { 11948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_path_check_and_react(stcb, addr); 11958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 11968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 11978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* __FreeBSD__ __APPLE__ __Userspace__ */ 11988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* clear any cached/topologically incorrect source addresses */ 11998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_asconf_nets_cleanup(stcb, addr->ifn_p); 12008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* else, leave it on the list */ 12028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 12038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 12048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 12058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * add an asconf add/delete/set primary IP address parameter to the queue. 12068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * type = SCTP_ADD_IP_ADDRESS, SCTP_DEL_IP_ADDRESS, SCTP_SET_PRIM_ADDR. 12078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * returns 0 if queued, -1 if not queued/removed. 12088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * NOTE: if adding, but a delete for the same address is already scheduled 12098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * (and not yet sent out), simply remove it from queue. Same for deleting 12108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * an address already scheduled for add. If a duplicate operation is found, 12118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ignore the new one. 12128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 12138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int 12148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_asconf_queue_mgmt(struct sctp_tcb *stcb, struct sctp_ifa *ifa, 12158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t type) 12168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 12178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_asconf_addr *aa, *aa_next; 12188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 12198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* make sure the request isn't already in the queue */ 12208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) { 12218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* address match? */ 12228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_asconf_addr_match(aa, &ifa->address.sa) == 0) 12238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 12248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* is the request already in queue but not sent? 12258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * pass the request already sent in order to resolve the following case: 12268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 1. arrival of ADD, then sent 12278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 2. arrival of DEL. we can't remove the ADD request already sent 12288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 3. arrival of ADD 12298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 12308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (aa->ap.aph.ph.param_type == type && aa->sent == 0) { 12318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 12328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* is the negative request already in queue, and not sent */ 12348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((aa->sent == 0) && (type == SCTP_ADD_IP_ADDRESS) && 12358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS)) { 12368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* add requested, delete already queued */ 12378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next); 12388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* remove the ifa from the restricted list */ 12398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_del_local_addr_restricted(stcb, ifa); 12408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* free the asconf param */ 12418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FREE(aa, SCTP_M_ASC_ADDR); 12428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF2, "asconf_queue_mgmt: add removes queued entry\n"); 12438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 12448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((aa->sent == 0) && (type == SCTP_DEL_IP_ADDRESS) && 12468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (aa->ap.aph.ph.param_type == SCTP_ADD_IP_ADDRESS)) { 12478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* delete requested, add already queued */ 12488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next); 12498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* remove the aa->ifa from the restricted list */ 12508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_del_local_addr_restricted(stcb, aa->ifa); 12518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* free the asconf param */ 12528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FREE(aa, SCTP_M_ASC_ADDR); 12538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF2, "asconf_queue_mgmt: delete removes queued entry\n"); 12548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 12558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } /* for each aa */ 12578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 12588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* adding new request to the queue */ 12598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa), 12608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_M_ASC_ADDR); 12618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (aa == NULL) { 12628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* didn't get memory */ 12638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "asconf_queue_mgmt: failed to get memory!\n"); 12648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 12658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->special_del = 0; 12678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* fill in asconf address parameter fields */ 12688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* top level elements are "networked" during send */ 12698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->ap.aph.ph.param_type = type; 12708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->ifa = ifa; 12718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&ifa->refcount, 1); 12728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* correlation_id filled in during send routine later... */ 12738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (ifa->address.sa.sa_family) { 12748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 12758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 12768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 12778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in6 *sin6; 12788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 1279bfb1bf7e665a02b48026482bf33d05c83dfad73bt sin6 = &ifa->address.sin6; 12808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS; 12818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param)); 12828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + 12838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_ipv6addr_param); 12848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr, 12858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct in6_addr)); 12868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 12878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 12898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 12908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 12918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 12928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in *sin; 12938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 1294bfb1bf7e665a02b48026482bf33d05c83dfad73bt sin = &ifa->address.sin; 12958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS; 12968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param)); 12978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + 12988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_ipv4addr_param); 12998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memcpy(&aa->ap.addrp.addr, &sin->sin_addr, 13008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct in_addr)); 13018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 13028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 13048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 13058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* invalid family! */ 13068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FREE(aa, SCTP_M_ASC_ADDR); 13078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_ifa(ifa); 13088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 13098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->sent = 0; /* clear sent flag */ 13118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 13128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next); 13138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_DEBUG 13148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_debug_on) & SCTP_DEBUG_ASCONF2) { 13158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (type == SCTP_ADD_IP_ADDRESS) { 13168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("asconf_queue_mgmt: inserted asconf ADD_IP_ADDRESS: "); 13176377430fc6bf9f87402ccef28103c25a684dce20t SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, &ifa->address.sa); 13188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (type == SCTP_DEL_IP_ADDRESS) { 13198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("asconf_queue_mgmt: appended asconf DEL_IP_ADDRESS: "); 13206377430fc6bf9f87402ccef28103c25a684dce20t SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, &ifa->address.sa); 13218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 13228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("asconf_queue_mgmt: appended asconf SET_PRIM_ADDR: "); 13236377430fc6bf9f87402ccef28103c25a684dce20t SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, &ifa->address.sa); 13248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 13278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 13288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 13298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 13308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 13318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 13328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 13338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * add an asconf operation for the given ifa and type. 13348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * type = SCTP_ADD_IP_ADDRESS, SCTP_DEL_IP_ADDRESS, SCTP_SET_PRIM_ADDR. 13358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * returns 0 if completed, -1 if not completed, 1 if immediate send is 13368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * advisable. 13378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 13388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int 13398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa, 13408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t type) 13418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 13428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t status; 13438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int pending_delete_queued = 0; 13448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 13458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* see if peer supports ASCONF */ 1346fb3816eaffe5878bb1286adb120fd160da178a05t if (stcb->asoc.asconf_supported == 0) { 13478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 13488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 13508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 13518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * if this is deleting the last address from the assoc, mark it as 13528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * pending. 13538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 13548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((type == SCTP_DEL_IP_ADDRESS) && !stcb->asoc.asconf_del_pending && 13558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (sctp_local_addr_count(stcb) < 2)) { 13568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* set the pending delete info only */ 13578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.asconf_del_pending = 1; 13588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.asconf_addr_del_pending = ifa; 13598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&ifa->refcount, 1); 13608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF2, 13618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "asconf_queue_add: mark delete last address pending\n"); 13628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 13638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 13658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* queue an asconf parameter */ 13668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen status = sctp_asconf_queue_mgmt(stcb, ifa, type); 13678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 13688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 13698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * if this is an add, and there is a delete also pending (i.e. the 13708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * last local address is being changed), queue the pending delete too. 13718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 13728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((type == SCTP_ADD_IP_ADDRESS) && stcb->asoc.asconf_del_pending && (status == 0)) { 13738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* queue in the pending delete */ 13748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_asconf_queue_mgmt(stcb, 13758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.asconf_addr_del_pending, 13768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_DEL_IP_ADDRESS) == 0) { 13778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF2, "asconf_queue_add: queing pending delete\n"); 13788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen pending_delete_queued = 1; 13798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* clear out the pending delete info */ 13808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.asconf_del_pending = 0; 13818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_ifa(stcb->asoc.asconf_addr_del_pending); 13828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.asconf_addr_del_pending = NULL; 13838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 13868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (pending_delete_queued) { 13878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net; 13888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 13898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * since we know that the only/last address is now being 13908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * changed in this case, reset the cwnd/rto on all nets to 13918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * start as a new address and path. Also clear the error 13928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * counts to give the assoc the best chance to complete the 13938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * address change. 13948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 13958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 13968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, 13978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net); 13988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->RTO = 0; 13998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->error_count = 0; 14008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 14018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count = 0; 14028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 14038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 14048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count, 14058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 14068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FROM_SCTP_ASCONF, 14078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen __LINE__); 14088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 14098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 14108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* queue in an advisory set primary too */ 14118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)sctp_asconf_queue_mgmt(stcb, ifa, SCTP_SET_PRIM_ADDR); 14128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* let caller know we should send this out immediately */ 14138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen status = 1; 14148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 14158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (status); 14168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 14178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 14188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*- 14198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * add an asconf delete IP address parameter to the queue by sockaddr and 14208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * possibly with no sctp_ifa available. This is only called by the routine 14218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * that checks the addresses in an INIT-ACK against the current address list. 14228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * returns 0 if completed, non-zero if not completed. 14238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * NOTE: if an add is already scheduled (and not yet sent out), simply 14248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * remove it from queue. If a duplicate operation is found, ignore the 14258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * new one. 14268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 14278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int 14288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_asconf_queue_sa_delete(struct sctp_tcb *stcb, struct sockaddr *sa) 14298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 14308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ifa *ifa; 14318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_asconf_addr *aa, *aa_next; 14328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t vrf_id; 14338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 14348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb == NULL) { 14358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 14368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 14378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* see if peer supports ASCONF */ 1438fb3816eaffe5878bb1286adb120fd160da178a05t if (stcb->asoc.asconf_supported == 0) { 14398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 14408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 14418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* make sure the request isn't already in the queue */ 14428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) { 14438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* address match? */ 14448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_asconf_addr_match(aa, sa) == 0) 14458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 14468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* is the request already in queue (sent or not) */ 14478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS) { 14488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 14498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 14508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* is the negative request already in queue, and not sent */ 14518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (aa->sent == 1) 14528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 14538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (aa->ap.aph.ph.param_type == SCTP_ADD_IP_ADDRESS) { 14548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* add already queued, so remove existing entry */ 14558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next); 14568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_del_local_addr_restricted(stcb, aa->ifa); 14578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* free the entry */ 14588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FREE(aa, SCTP_M_ASC_ADDR); 14598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 14608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 14618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } /* for each aa */ 14628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 14638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* find any existing ifa-- NOTE ifa CAN be allowed to be NULL */ 14648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb) { 14658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf_id = stcb->asoc.vrf_id; 14668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 14678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf_id = SCTP_DEFAULT_VRFID; 14688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 14698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED); 14708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 14718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* adding new request to the queue */ 14728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa), 14738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_M_ASC_ADDR); 14748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (aa == NULL) { 14758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* didn't get memory */ 14768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, 14778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "sctp_asconf_queue_sa_delete: failed to get memory!\n"); 14788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 14798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 14808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->special_del = 0; 14818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* fill in asconf address parameter fields */ 14828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* top level elements are "networked" during send */ 14838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->ap.aph.ph.param_type = SCTP_DEL_IP_ADDRESS; 14848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->ifa = ifa; 14858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ifa) 14868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&ifa->refcount, 1); 14878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* correlation_id filled in during send routine later... */ 14888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (sa->sa_family) { 14898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 14908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 14918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 14928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* IPv6 address */ 14938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in6 *sin6; 14948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 14958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6 = (struct sockaddr_in6 *)sa; 14968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS; 14978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param)); 14988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv6addr_param); 14998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr, 15008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct in6_addr)); 15018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 15028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 15048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 15058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 15068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 15078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* IPv4 address */ 15088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in *sin = (struct sockaddr_in *)sa; 15098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 15108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS; 15118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param)); 15128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv4addr_param); 15138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memcpy(&aa->ap.addrp.addr, &sin->sin_addr, 15148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct in_addr)); 15158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 15168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 15188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 15198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* invalid family! */ 15208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FREE(aa, SCTP_M_ASC_ADDR); 15218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ifa) 15228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_ifa(ifa); 15238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 15248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->sent = 0; /* clear sent flag */ 15268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 15278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* delete goes to the back of the queue */ 15288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next); 15298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 15308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* sa_ignore MEMLEAK {memory is put on the tailq} */ 15318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 15328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 15338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 15348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 15358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * find a specific asconf param on our "sent" queue 15368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 15378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic struct sctp_asconf_addr * 15388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_asconf_find_param(struct sctp_tcb *stcb, uint32_t correlation_id) 15398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 15408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_asconf_addr *aa; 15418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 15428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) { 15438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (aa->ap.aph.correlation_id == correlation_id && 15448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->sent == 1) { 15458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* found it */ 15468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (aa); 15478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* didn't find it */ 15508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 15518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 15528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 15538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 15548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * process an SCTP_ERROR_CAUSE_IND for a ASCONF-ACK parameter and do 15558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * notifications based on the error response 15568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 15578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 1558fb3816eaffe5878bb1286adb120fd160da178a05tsctp_asconf_process_error(struct sctp_tcb *stcb SCTP_UNUSED, 15598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_asconf_paramhdr *aph) 15608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 15618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_error_cause *eh; 15628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_paramhdr *ph; 15638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t param_type; 15648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t error_code; 15658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 15668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen eh = (struct sctp_error_cause *)(aph + 1); 15678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ph = (struct sctp_paramhdr *)(eh + 1); 15688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* validate lengths */ 15698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (htons(eh->length) + sizeof(struct sctp_error_cause) > 15708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen htons(aph->ph.param_length)) { 15718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* invalid error cause length */ 15728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, 15738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "asconf_process_error: cause element too long\n"); 15748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 15758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (htons(ph->param_length) + sizeof(struct sctp_paramhdr) > 15778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen htons(eh->length)) { 15788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* invalid included TLV length */ 15798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, 15808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "asconf_process_error: included TLV too long\n"); 15818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 15828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* which error code ? */ 15848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen error_code = ntohs(eh->code); 15858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen param_type = ntohs(aph->ph.param_type); 15868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* FIX: this should go back up the REMOTE_ERROR ULP notify */ 15878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (error_code) { 15888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_CAUSE_RESOURCE_SHORTAGE: 15898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* we allow ourselves to "try again" for this error */ 15908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 15918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 15928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* peer can't handle it... */ 15938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (param_type) { 15948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_ADD_IP_ADDRESS: 15958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_DEL_IP_ADDRESS: 15968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_SET_PRIM_ADDR: 15978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 15988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 15998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 16008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 16038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 16048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 16058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * process an asconf queue param. 16068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * aparam: parameter to process, will be removed from the queue. 16078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * flag: 1=success case, 0=failure case 16088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 16098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 16108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_asconf_process_param_ack(struct sctp_tcb *stcb, 16118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_asconf_addr *aparam, uint32_t flag) 16128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 16138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t param_type; 16148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 16158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* process this param */ 16168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen param_type = aparam->ap.aph.ph.param_type; 16178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (param_type) { 16188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_ADD_IP_ADDRESS: 16198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, 16208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "process_param_ack: added IP address\n"); 16210ac02f34d6041cd0018437596a5a9a94685e6919tuexen sctp_asconf_addr_mgmt_ack(stcb, aparam->ifa, flag); 16228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 16238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_DEL_IP_ADDRESS: 16248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, 16258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "process_param_ack: deleted IP address\n"); 16268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* nothing really to do... lists already updated */ 16278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 16288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_SET_PRIM_ADDR: 16298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, 16308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "process_param_ack: set primary IP address\n"); 16318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* nothing to do... peer may start using this addr */ 16328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 16338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 16348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* should NEVER happen */ 16358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 16368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 16388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* remove the param and free it */ 16398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&stcb->asoc.asconf_queue, aparam, next); 16408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (aparam->ifa) 16418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_ifa(aparam->ifa); 16428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FREE(aparam, SCTP_M_ASC_ADDR); 16438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 16448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 16458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 16468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * cleanup from a bad asconf ack parameter 16478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 16488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 1649fb3816eaffe5878bb1286adb120fd160da178a05tsctp_asconf_ack_clear(struct sctp_tcb *stcb SCTP_UNUSED) 16508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 16518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* assume peer doesn't really know how to do asconfs */ 16528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* XXX we could free the pending queue here */ 1653fb3816eaffe5878bb1286adb120fd160da178a05t 16548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 16558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 16568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 16578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_handle_asconf_ack(struct mbuf *m, int offset, 16588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_asconf_ack_chunk *cp, struct sctp_tcb *stcb, 16598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net, int *abort_no_unlock) 16608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 16618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc; 16628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t serial_num; 16638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t ack_length; 16648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_asconf_paramhdr *aph; 16658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_asconf_addr *aa, *aa_next; 16668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t last_error_id = 0; /* last error correlation id */ 16678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t id; 16688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_asconf_addr *ap; 16698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 16708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* asconf param buffer */ 16718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint8_t aparam_buf[SCTP_PARAM_BUFFER_SIZE]; 16728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 16738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* verify minimum length */ 16748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_asconf_ack_chunk)) { 16758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, 16768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "handle_asconf_ack: chunk too small = %xh\n", 16778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ntohs(cp->ch.chunk_length)); 16788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 16798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc = &stcb->asoc; 16818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen serial_num = ntohl(cp->serial_number); 16828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 16838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 16848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * NOTE: we may want to handle this differently- currently, we will 16858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * abort when we get an ack for the expected serial number + 1 (eg. 16868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we didn't send it), process an ack normally if it is the expected 16878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * serial number, and re-send the previous ack for *ALL* other 16888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * serial numbers 16898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 16908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 16918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 16928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * if the serial number is the next expected, but I didn't send it, 16938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * abort the asoc, since someone probably just hijacked us... 16948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 16958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (serial_num == (asoc->asconf_seq_out + 1)) { 16968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf_ack: got unexpected next serial number! Aborting asoc!\n"); 169747674b651417d493ff4e0318113fd7beeef119dbtuexen sctp_abort_an_association(stcb->sctp_ep, stcb, NULL, SCTP_SO_NOT_LOCKED); 16988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_no_unlock = 1; 16998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 17008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (serial_num != asoc->asconf_seq_out_acked + 1) { 17028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* got a duplicate/unexpected ASCONF-ACK */ 17038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf_ack: got duplicate/unexpected serial number = %xh (expected = %xh)\n", 17048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen serial_num, asoc->asconf_seq_out_acked + 1); 17058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 17068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 17088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (serial_num == asoc->asconf_seq_out - 1) { 17098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* stop our timer */ 17108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net, 1711b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen SCTP_FROM_SCTP_ASCONF+SCTP_LOC_3); 17128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 17148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* process the ASCONF-ACK contents */ 17158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ack_length = ntohs(cp->ch.chunk_length) - 17168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_asconf_ack_chunk); 17178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen offset += sizeof(struct sctp_asconf_ack_chunk); 17188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* process through all parameters */ 17198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen while (ack_length >= sizeof(struct sctp_asconf_paramhdr)) { 17208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen unsigned int param_length, param_type; 17218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 17228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* get pointer to next asconf parameter */ 17238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, 17248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_asconf_paramhdr), aparam_buf); 17258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (aph == NULL) { 17268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* can't get an asconf paramhdr */ 17278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_asconf_ack_clear(stcb); 17288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 17298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen param_type = ntohs(aph->ph.param_type); 17318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen param_length = ntohs(aph->ph.param_length); 17328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (param_length > ack_length) { 17338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_asconf_ack_clear(stcb); 17348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 17358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (param_length < sizeof(struct sctp_paramhdr)) { 17378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_asconf_ack_clear(stcb); 17388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 17398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* get the complete parameter... */ 17418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (param_length > sizeof(aparam_buf)) { 17428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, 17438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "param length (%u) larger than buffer size!\n", param_length); 17448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_asconf_ack_clear(stcb); 17458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 17468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, param_length, aparam_buf); 17488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (aph == NULL) { 17498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_asconf_ack_clear(stcb); 17508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 17518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* correlation_id is transparent to peer, no ntohl needed */ 17538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen id = aph->correlation_id; 17548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 17558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (param_type) { 17568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_ERROR_CAUSE_IND: 17578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen last_error_id = id; 17588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* find the corresponding asconf param in our queue */ 17598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ap = sctp_asconf_find_param(stcb, id); 17608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ap == NULL) { 17618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* hmm... can't find this in our queue! */ 17628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 17638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* process the parameter, failed flag */ 17658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_asconf_process_param_ack(stcb, ap, 0); 17668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* process the error response */ 17678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_asconf_process_error(stcb, aph); 17688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 17698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_SUCCESS_REPORT: 17708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* find the corresponding asconf param in our queue */ 17718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ap = sctp_asconf_find_param(stcb, id); 17728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ap == NULL) { 17738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* hmm... can't find this in our queue! */ 17748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 17758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* process the parameter, success flag */ 17778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_asconf_process_param_ack(stcb, ap, 1); 17788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 17798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 17808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 17818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } /* switch */ 17828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 17838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* update remaining ASCONF-ACK message length to process */ 17848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ack_length -= SCTP_SIZE32(param_length); 17858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ack_length <= 0) { 17868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* no more data in the mbuf chain */ 17878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 17888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen offset += SCTP_SIZE32(param_length); 17908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } /* while */ 17918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 17928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 17938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * if there are any "sent" params still on the queue, these are 17948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * implicitly "success", or "failed" (if we got an error back) ... 17958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * so process these appropriately 17968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 17978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we assume that the correlation_id's are monotonically increasing 17988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * beginning from 1 and that we don't have *that* many outstanding 17998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * at any given time 18008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 18018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (last_error_id == 0) 18028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen last_error_id--; /* set to "max" value */ 18038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) { 18048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (aa->sent == 1) { 18058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 18068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * implicitly successful or failed if correlation_id 18078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * < last_error_id, then success else, failure 18088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 18098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (aa->ap.aph.correlation_id < last_error_id) 18108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_asconf_process_param_ack(stcb, aa, 1); 18118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen else 18128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_asconf_process_param_ack(stcb, aa, 0); 18138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 18148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 18158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * since we always process in order (FIFO queue) if 18168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we reach one that hasn't been sent, the rest 18178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * should not have been sent either. so, we're 18188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * done... 18198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 18208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 18218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 18248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* update the next sequence number to use */ 18258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->asconf_seq_out_acked++; 18268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* remove the old ASCONF on our outbound queue */ 18278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_toss_old_asconf(stcb); 18288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!TAILQ_EMPTY(&stcb->asoc.asconf_queue)) { 18298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_TIMER_BASED_ASCONF 18308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* we have more params, so restart our timer */ 18318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, 18328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb, net); 18338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 18348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* we have more params, so send out more */ 18358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_asconf(stcb, net, SCTP_ADDR_NOT_LOCKED); 18368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 18378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 18398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 18408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 18418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic uint32_t 18428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_is_scopeid_in_nets(struct sctp_tcb *stcb, struct sockaddr *sa) 18438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 18448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in6 *sin6, *net6; 18458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net; 18468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 18478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sa->sa_family != AF_INET6) { 18488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* wrong family */ 18498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 18508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6 = (struct sockaddr_in6 *)sa; 18528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) == 0) { 18538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* not link local address */ 18548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 18558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* hunt through our destination nets list for this scope_id */ 18578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 18588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (((struct sockaddr *)(&net->ro._l_addr))->sa_family != 18598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen AF_INET6) 18608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 18618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net6 = (struct sockaddr_in6 *)&net->ro._l_addr; 18628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (IN6_IS_ADDR_LINKLOCAL(&net6->sin6_addr) == 0) 18638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 18648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_is_same_scope(sin6, net6)) { 18658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* found one */ 18668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (1); 18678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* didn't find one */ 18708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 18718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 18728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 18738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 18748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 18758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * address management functions 18768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 18778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 18788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 18798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ifa *ifa, uint16_t type, int addr_locked) 18808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 18818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int status; 18828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 18838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0 || 18848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_ASCONF)) { 18858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* subset bound, no ASCONF allowed case, so ignore */ 18868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 18878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 18898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * note: we know this is not the subset bound, no ASCONF case eg. 18908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * this is boundall or subset bound w/ASCONF allowed 18918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 18928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 1893998635733088fde643e6d807fa76679c4ceeaa00t /* first, make sure that the address is IPv4 or IPv6 and not jailed */ 18948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (ifa->address.sa.sa_family) { 18958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 18968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 1897998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__) 1898998635733088fde643e6d807fa76679c4ceeaa00t if (prison_check_ip6(inp->ip_inp.inp.inp_cred, 1899998635733088fde643e6d807fa76679c4ceeaa00t &ifa->address.sin6.sin6_addr) != 0) { 1900998635733088fde643e6d807fa76679c4ceeaa00t return; 1901998635733088fde643e6d807fa76679c4ceeaa00t } 1902998635733088fde643e6d807fa76679c4ceeaa00t#endif 19038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 19048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 19058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 19068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 1907998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__) 1908998635733088fde643e6d807fa76679c4ceeaa00t if (prison_check_ip4(inp->ip_inp.inp.inp_cred, 1909998635733088fde643e6d807fa76679c4ceeaa00t &ifa->address.sin.sin_addr) != 0) { 1910998635733088fde643e6d807fa76679c4ceeaa00t return; 1911998635733088fde643e6d807fa76679c4ceeaa00t } 1912998635733088fde643e6d807fa76679c4ceeaa00t#endif 19138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 19148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 19158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 19168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 19178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 19188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 19198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* make sure we're "allowed" to add this type of addr */ 19208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ifa->address.sa.sa_family == AF_INET6) { 19218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* invalid if we're not a v6 endpoint */ 19228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) 19238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 19248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* is the v6 addr really valid ? */ 19258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) { 19268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 19278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 19288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 19298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 19308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* put this address on the "pending/do not use yet" list */ 19318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_add_local_addr_restricted(stcb, ifa); 19328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 19338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * check address scope if address is out of scope, don't queue 19348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * anything... note: this would leave the address on both inp and 19358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * asoc lists 19368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 19378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (ifa->address.sa.sa_family) { 19388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 19398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 19408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 19418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in6 *sin6; 19428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 1943bfb1bf7e665a02b48026482bf33d05c83dfad73bt sin6 = &ifa->address.sin6; 19448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 19458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* we skip unspecifed addresses */ 19468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 19478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 19488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 19497988ea8f0c067cf3757e798b473b1ae4d34b6dfdt if (stcb->asoc.scope.local_scope == 0) { 19508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 19518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 19528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* is it the right link local scope? */ 19538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_is_scopeid_in_nets(stcb, &ifa->address.sa) == 0) { 19548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 19558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 19568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 19577988ea8f0c067cf3757e798b473b1ae4d34b6dfdt if (stcb->asoc.scope.site_scope == 0 && 19588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) { 19598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 19608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 19618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 19628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 19638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 19648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 19658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 19668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 19678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in *sin; 19688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct in6pcb *inp6; 19698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 19708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp6 = (struct in6pcb *)&inp->ip_inp.inp; 19718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* invalid if we are a v6 only endpoint */ 19728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && 19738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPV6_V6ONLY(inp6)) 19748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 19758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 1976bfb1bf7e665a02b48026482bf33d05c83dfad73bt sin = &ifa->address.sin; 19778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sin->sin_addr.s_addr == 0) { 19788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* we skip unspecifed addresses */ 19798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 19808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 19817988ea8f0c067cf3757e798b473b1ae4d34b6dfdt if (stcb->asoc.scope.ipv4_local_scope == 0 && 19828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) { 19838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 19848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 19858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 19868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 19878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 19888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 19898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* else, not AF_INET or AF_INET6, so skip */ 19908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 19918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 19928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 19938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* queue an asconf for this address add/delete */ 19948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF)) { 19958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* does the peer do asconf? */ 1996fb3816eaffe5878bb1286adb120fd160da178a05t if (stcb->asoc.asconf_supported) { 19978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* queue an asconf for this addr */ 19988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen status = sctp_asconf_queue_add(stcb, ifa, type); 19998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 20008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 20018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * if queued ok, and in the open state, send out the 20028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ASCONF. If in the non-open state, these will be 20038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sent when the state goes open. 20048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 20058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (status == 0 && 20068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) { 20078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_TIMER_BASED_ASCONF 20088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, inp, 20098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb, stcb->asoc.primary_destination); 20108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 20118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_asconf(stcb, NULL, addr_locked); 20128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 20138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 20178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 20188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 20198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint 20200ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_asconf_iterator_ep(struct sctp_inpcb *inp, void *ptr, uint32_t val SCTP_UNUSED) 20218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 20228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_asconf_iterator *asc; 20238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ifa *ifa; 20248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_laddr *l; 2025b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen int cnt_invalid = 0; 20268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 20278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asc = (struct sctp_asconf_iterator *)ptr; 20288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) { 20298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ifa = l->ifa; 20308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (ifa->address.sa.sa_family) { 20318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 20328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 20338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* invalid if we're not a v6 endpoint */ 20348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) { 20358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cnt_invalid++; 20368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asc->cnt == cnt_invalid) 20378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (1); 20388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 20408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 20418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 20428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 20438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 20448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* invalid if we are a v6 only endpoint */ 20458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct in6pcb *inp6; 20468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp6 = (struct in6pcb *)&inp->ip_inp.inp; 20478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && 20488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPV6_V6ONLY(inp6)) { 20498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cnt_invalid++; 20508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asc->cnt == cnt_invalid) 20518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (1); 20528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 20548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 20568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 20578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* invalid address family */ 20588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cnt_invalid++; 20598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asc->cnt == cnt_invalid) 20608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (1); 20618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 20648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 20658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 20668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int 20670ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_asconf_iterator_ep_end(struct sctp_inpcb *inp, void *ptr, uint32_t val SCTP_UNUSED) 20688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 20698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ifa *ifa; 20708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_asconf_iterator *asc; 20718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_laddr *laddr, *nladdr, *l; 20728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 20738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Only for specific case not bound all */ 20748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asc = (struct sctp_asconf_iterator *)ptr; 20758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) { 20768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ifa = l->ifa; 20778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (l->action == SCTP_ADD_IP_ADDRESS) { 20788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(laddr, &inp->sctp_addr_list, 20798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_nxt_addr) { 20808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (laddr->ifa == ifa) { 20818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen laddr->action = 0; 20828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 20838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 20858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (l->action == SCTP_DEL_IP_ADDRESS) { 20878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH_SAFE(laddr, &inp->sctp_addr_list, sctp_nxt_addr, nladdr) { 20888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* remove only after all guys are done */ 20898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (laddr->ifa == ifa) { 20908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_del_local_addr_ep(inp, ifa); 20918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 20968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 20978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 20988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 20998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 21000ac02f34d6041cd0018437596a5a9a94685e6919tuexen void *ptr, uint32_t val SCTP_UNUSED) 21018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 21028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_asconf_iterator *asc; 21038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ifa *ifa; 21048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_laddr *l; 21058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int cnt_invalid = 0; 21068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int type, status; 21078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int num_queued = 0; 21088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 21098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asc = (struct sctp_asconf_iterator *)ptr; 21108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) { 21118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ifa = l->ifa; 21128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen type = l->action; 21138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 21148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* address's vrf_id must be the vrf_id of the assoc */ 21158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ifa->vrf_id != stcb->asoc.vrf_id) { 21168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 21178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 21188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 21198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Same checks again for assoc */ 21208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (ifa->address.sa.sa_family) { 21218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 21228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 21238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 21248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* invalid if we're not a v6 endpoint */ 21258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in6 *sin6; 21268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 21278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) { 21288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cnt_invalid++; 21298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asc->cnt == cnt_invalid) 21308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 21318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen else 21328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 21338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2134bfb1bf7e665a02b48026482bf33d05c83dfad73bt sin6 = &ifa->address.sin6; 21358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 21368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* we skip unspecifed addresses */ 21378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 21388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2139998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__) 2140998635733088fde643e6d807fa76679c4ceeaa00t if (prison_check_ip6(inp->ip_inp.inp.inp_cred, 2141998635733088fde643e6d807fa76679c4ceeaa00t &sin6->sin6_addr) != 0) { 2142998635733088fde643e6d807fa76679c4ceeaa00t continue; 2143998635733088fde643e6d807fa76679c4ceeaa00t } 2144998635733088fde643e6d807fa76679c4ceeaa00t#endif 21458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 21467988ea8f0c067cf3757e798b473b1ae4d34b6dfdt if (stcb->asoc.scope.local_scope == 0) { 21478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 21488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 21498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* is it the right link local scope? */ 21508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_is_scopeid_in_nets(stcb, &ifa->address.sa) == 0) { 21518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 21528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 21538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 21548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 21558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 21568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 21578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 21588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 21598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 21608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* invalid if we are a v6 only endpoint */ 21618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct in6pcb *inp6; 21628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in *sin; 21638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 21648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp6 = (struct in6pcb *)&inp->ip_inp.inp; 21658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* invalid if we are a v6 only endpoint */ 21668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && 21678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPV6_V6ONLY(inp6)) 21688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 21698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 2170bfb1bf7e665a02b48026482bf33d05c83dfad73bt sin = &ifa->address.sin; 21718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sin->sin_addr.s_addr == 0) { 21728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* we skip unspecifed addresses */ 21738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 21748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2175998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__) 2176998635733088fde643e6d807fa76679c4ceeaa00t if (prison_check_ip4(inp->ip_inp.inp.inp_cred, 2177998635733088fde643e6d807fa76679c4ceeaa00t &sin->sin_addr) != 0) { 2178998635733088fde643e6d807fa76679c4ceeaa00t continue; 2179998635733088fde643e6d807fa76679c4ceeaa00t } 2180998635733088fde643e6d807fa76679c4ceeaa00t#endif 21817988ea8f0c067cf3757e798b473b1ae4d34b6dfdt if (stcb->asoc.scope.ipv4_local_scope == 0 && 21828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) { 21838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 21848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 21858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && 21868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPV6_V6ONLY(inp6)) { 21878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cnt_invalid++; 21888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asc->cnt == cnt_invalid) 21898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 21908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen else 21918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 21928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 21938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 21948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 21958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 21968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 21978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* invalid address family */ 21988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cnt_invalid++; 21998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asc->cnt == cnt_invalid) 22008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 22018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen else 22028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 2203000a5bac556b28e74e4e98c540f66b1743e9312dtuexen break; 22048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 22068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (type == SCTP_ADD_IP_ADDRESS) { 22078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* prevent this address from being used as a source */ 22088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_add_local_addr_restricted(stcb, ifa); 22098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (type == SCTP_DEL_IP_ADDRESS) { 22108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net; 22118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 22128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_rtentry_t *rt; 22138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 22148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* delete this address if cached */ 22158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->ro._s_addr == ifa) { 22168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_ifa(net->ro._s_addr); 22178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->ro._s_addr = NULL; 22188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->src_addr_selected = 0; 22198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rt = net->ro.ro_rt; 22208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (rt) { 22218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen RTFREE(rt); 22228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->ro.ro_rt = NULL; 22238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 22258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Now we deleted our src address, 22268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * should we not also now reset the 22278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * cwnd/rto to start as if its a new 22288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * address? 22298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 22308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net); 22318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->RTO = 0; 22328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 22338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (type == SCTP_SET_PRIM_ADDR) { 22368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) { 22378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* must validate the ifa is in the ep */ 2238998635733088fde643e6d807fa76679c4ceeaa00t if (sctp_is_addr_in_ep(stcb->sctp_ep, ifa) == 0) { 22398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 22408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 22428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Need to check scopes for this guy */ 22437988ea8f0c067cf3757e798b473b1ae4d34b6dfdt if (sctp_is_address_in_scope(ifa, &stcb->asoc.scope, 0) == 0) { 22448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 22458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* queue an asconf for this address add/delete */ 22498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF) && 2250fb3816eaffe5878bb1286adb120fd160da178a05t stcb->asoc.asconf_supported == 1) { 22518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* queue an asconf for this addr */ 22528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen status = sctp_asconf_queue_add(stcb, ifa, type); 22538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 22548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * if queued ok, and in the open state, update the 22558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * count of queued params. If in the non-open state, 22568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * these get sent when the assoc goes open. 22578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 22588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) { 22598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (status >= 0) { 22608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen num_queued++; 22618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 22668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * If we have queued params in the open state, send out an ASCONF. 22678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 22688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (num_queued > 0) { 22698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED); 22708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 22728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 22738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 22740ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_asconf_iterator_end(void *ptr, uint32_t val SCTP_UNUSED) 22758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 22768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_asconf_iterator *asc; 22778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ifa *ifa; 22788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_laddr *l, *nl; 22798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 22808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asc = (struct sctp_asconf_iterator *)ptr; 22818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH_SAFE(l, &asc->list_of_work, sctp_nxt_addr, nl) { 22828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ifa = l->ifa; 22838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (l->action == SCTP_ADD_IP_ADDRESS) { 22848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Clear the defer use flag */ 22858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE; 22868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_ifa(ifa); 22888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_laddr), l); 22898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_DECR_LADDR_COUNT(); 22908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FREE(asc, SCTP_M_ASC_IT); 22928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 22938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 22948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 22958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sa is the sockaddr to ask the peer to set primary to. 22968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * returns: 0 = completed, -1 = error 22978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 22988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint32_t 22998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_set_primary_ip_address_sa(struct sctp_tcb *stcb, struct sockaddr *sa) 23008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 2301e2828360ea9cf8951730d46f5c14626c9425cb30t uint32_t vrf_id; 23028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ifa *ifa; 23038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 23048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* find the ifa for the desired set primary */ 23058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf_id = stcb->asoc.vrf_id; 23068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED); 23078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ifa == NULL) { 23088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Invalid address */ 23098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 23108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 23118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 23128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* queue an ASCONF:SET_PRIM_ADDR to be sent */ 23138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!sctp_asconf_queue_add(stcb, ifa, SCTP_SET_PRIM_ADDR)) { 23148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* set primary queuing succeeded */ 23158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, 23168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "set_primary_ip_address_sa: queued on tcb=%p, ", 2317ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t (void *)stcb); 23188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); 23198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) { 23208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_TIMER_BASED_ASCONF 23218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, 23228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep, stcb, 23238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.primary_destination); 23248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 23258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED); 23268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 23278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 23288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 23298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "set_primary_ip_address_sa: failed to add to queue on tcb=%p, ", 2330ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t (void *)stcb); 23318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); 23328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 23338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 23348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 23358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 23368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 23378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 23388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_set_primary_ip_address(struct sctp_ifa *ifa) 23398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 23408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_inpcb *inp; 23418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 23428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* go through all our PCB's */ 23438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(inp, &SCTP_BASE_INFO(listhead), sctp_list) { 23448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *stcb; 23458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 23468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* process for all associations for this endpoint */ 23478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { 23488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* queue an ASCONF:SET_PRIM_ADDR to be sent */ 23498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!sctp_asconf_queue_add(stcb, ifa, 23508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SET_PRIM_ADDR)) { 23518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* set primary queuing succeeded */ 23528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "set_primary_ip_address: queued on stcb=%p, ", 2353ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t (void *)stcb); 23548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &ifa->address.sa); 23558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) { 23568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_TIMER_BASED_ASCONF 23578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, 23588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep, stcb, 23598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.primary_destination); 23608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 23618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED); 23628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 23638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 23648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 23658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } /* for each stcb */ 23668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } /* for each inp */ 23678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 23688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 23698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint 23708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_is_addr_pending(struct sctp_tcb *stcb, struct sctp_ifa *sctp_ifa) 23718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 23728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *chk, *nchk; 23738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen unsigned int offset, asconf_limit; 23748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_asconf_chunk *acp; 23758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_asconf_paramhdr *aph; 23768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint8_t aparam_buf[SCTP_PARAM_BUFFER_SIZE]; 23778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_paramhdr *ph; 23788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int add_cnt, del_cnt; 23798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t last_param_type; 23808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 23818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen add_cnt = del_cnt = 0; 23828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen last_param_type = 0; 23838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(chk, &stcb->asoc.asconf_send_queue, sctp_next, nchk) { 23848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->data == NULL) { 23858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: No mbuf data?\n"); 23868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 23878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 23888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen offset = 0; 23898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen acp = mtod(chk->data, struct sctp_asconf_chunk *); 23908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen offset += sizeof(struct sctp_asconf_chunk); 23918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asconf_limit = ntohs(acp->ch.chunk_length); 23928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ph = (struct sctp_paramhdr *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_paramhdr), aparam_buf); 23938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ph == NULL) { 23948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: couldn't get lookup addr!\n"); 23958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 23968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 23978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen offset += ntohs(ph->param_length); 23988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 23998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_asconf_paramhdr), aparam_buf); 24008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (aph == NULL) { 24018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: Empty ASCONF will be sent?\n"); 24028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 24038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 24048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen while (aph != NULL) { 24058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen unsigned int param_length, param_type; 24068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 24078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen param_type = ntohs(aph->ph.param_type); 24088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen param_length = ntohs(aph->ph.param_length); 24098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (offset + param_length > asconf_limit) { 24108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* parameter goes beyond end of chunk! */ 24118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 24128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 24138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (param_length > sizeof(aparam_buf)) { 24148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: param length (%u) larger than buffer size!\n", param_length); 24158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 24168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 24178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (param_length <= sizeof(struct sctp_paramhdr)) { 24188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: param length(%u) too short\n", param_length); 24198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 24208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 24218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 24228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(chk->data, offset, param_length, aparam_buf); 24238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (aph == NULL) { 24248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: couldn't get entire param\n"); 24258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 24268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 24278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 24288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ph = (struct sctp_paramhdr *)(aph + 1); 24298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_addr_match(ph, &sctp_ifa->address.sa) != 0) { 24308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (param_type) { 24318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_ADD_IP_ADDRESS: 24328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen add_cnt++; 24338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 24348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_DEL_IP_ADDRESS: 24358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen del_cnt++; 24368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 24378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 24388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 24398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 24408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen last_param_type = param_type; 24418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 24428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 24438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen offset += SCTP_SIZE32(param_length); 24448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (offset >= asconf_limit) { 24458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* no more data in the mbuf chain */ 24468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 24478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 24488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* get pointer to next asconf param */ 24498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_asconf_paramhdr), aparam_buf); 24508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 24518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 24528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 24538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* we want to find the sequences which consist of ADD -> DEL -> ADD or DEL -> ADD */ 24548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (add_cnt > del_cnt || 24558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (add_cnt == del_cnt && last_param_type == SCTP_ADD_IP_ADDRESS)) { 2456b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (1); 24578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2458b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (0); 24598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 24608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 24618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic struct sockaddr * 24628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_find_valid_localaddr(struct sctp_tcb *stcb, int addr_locked) 24638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 24648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_vrf *vrf = NULL; 24658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ifn *sctp_ifn; 24668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ifa *sctp_ifa; 24678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 24688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (addr_locked == SCTP_ADDR_NOT_LOCKED) 24698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ADDR_RLOCK(); 24708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf = sctp_find_vrf(stcb->asoc.vrf_id); 24718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (vrf == NULL) { 24728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (addr_locked == SCTP_ADDR_NOT_LOCKED) 24738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ADDR_RUNLOCK(); 24748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 24758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 24768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) { 24777988ea8f0c067cf3757e798b473b1ae4d34b6dfdt if (stcb->asoc.scope.loopback_scope == 0 && 24788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) { 24798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Skip if loopback_scope not set */ 24808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 24818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 24828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) { 24838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (sctp_ifa->address.sa.sa_family) { 24848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 24858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 24867988ea8f0c067cf3757e798b473b1ae4d34b6dfdt if (stcb->asoc.scope.ipv4_addr_legal) { 24878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in *sin; 24888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 2489bfb1bf7e665a02b48026482bf33d05c83dfad73bt sin = &sctp_ifa->address.sin; 24908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sin->sin_addr.s_addr == 0) { 24918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* skip unspecifed addresses */ 24928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 24938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2494998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__) 2495998635733088fde643e6d807fa76679c4ceeaa00t if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred, 2496998635733088fde643e6d807fa76679c4ceeaa00t &sin->sin_addr) != 0) { 2497998635733088fde643e6d807fa76679c4ceeaa00t continue; 2498998635733088fde643e6d807fa76679c4ceeaa00t } 2499998635733088fde643e6d807fa76679c4ceeaa00t#endif 25007988ea8f0c067cf3757e798b473b1ae4d34b6dfdt if (stcb->asoc.scope.ipv4_local_scope == 0 && 25018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) 25028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 25038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 25048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_is_addr_restricted(stcb, sctp_ifa) && 25058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (!sctp_is_addr_pending(stcb, sctp_ifa))) 25068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 25078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* found a valid local v4 address to use */ 25088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (addr_locked == SCTP_ADDR_NOT_LOCKED) 25098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ADDR_RUNLOCK(); 25108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (&sctp_ifa->address.sa); 25118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 25138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 25148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 25158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 25167988ea8f0c067cf3757e798b473b1ae4d34b6dfdt if (stcb->asoc.scope.ipv6_addr_legal) { 25178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in6 *sin6; 25188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 25198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) { 25208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 25218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 2523bfb1bf7e665a02b48026482bf33d05c83dfad73bt sin6 = &sctp_ifa->address.sin6; 25248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 25258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* we skip unspecifed addresses */ 25268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 25278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2528998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__) 2529998635733088fde643e6d807fa76679c4ceeaa00t if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred, 2530998635733088fde643e6d807fa76679c4ceeaa00t &sin6->sin6_addr) != 0) { 2531998635733088fde643e6d807fa76679c4ceeaa00t continue; 2532998635733088fde643e6d807fa76679c4ceeaa00t } 2533998635733088fde643e6d807fa76679c4ceeaa00t#endif 25347988ea8f0c067cf3757e798b473b1ae4d34b6dfdt if (stcb->asoc.scope.local_scope == 0 && 25358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 25368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 25377988ea8f0c067cf3757e798b473b1ae4d34b6dfdt if (stcb->asoc.scope.site_scope == 0 && 25388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) 25398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 25408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 25418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_is_addr_restricted(stcb, sctp_ifa) && 25428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (!sctp_is_addr_pending(stcb, sctp_ifa))) 25438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 25448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* found a valid local v6 address to use */ 25458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (addr_locked == SCTP_ADDR_NOT_LOCKED) 25468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ADDR_RUNLOCK(); 25478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (&sctp_ifa->address.sa); 25488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 25508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 25518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 25528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 25538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* no valid addresses found */ 25578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (addr_locked == SCTP_ADDR_NOT_LOCKED) 25588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ADDR_RUNLOCK(); 25598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 25608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 25618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 25628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic struct sockaddr * 25638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_find_valid_localaddr_ep(struct sctp_tcb *stcb) 25648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 25658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_laddr *laddr; 25668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 25678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) { 25688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (laddr->ifa == NULL) { 25698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 25708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* is the address restricted ? */ 25728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_is_addr_restricted(stcb, laddr->ifa) && 25738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (!sctp_is_addr_pending(stcb, laddr->ifa))) 25748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 25758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 25768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* found a valid local address to use */ 25778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (&laddr->ifa->address.sa); 25788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* no valid addresses found */ 25808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 25818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 25828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 25838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 25848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * builds an ASCONF chunk from queued ASCONF params. 25858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * returns NULL on error (no mbuf, no ASCONF params queued, etc). 25868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 25878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct mbuf * 25888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_compose_asconf(struct sctp_tcb *stcb, int *retlen, int addr_locked) 25898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 25908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *m_asconf, *m_asconf_chk; 25918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_asconf_addr *aa; 25928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_asconf_chunk *acp; 25938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_asconf_paramhdr *aph; 25948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_asconf_addr_param *aap; 25958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t p_length; 25968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t correlation_id = 1; /* 0 is reserved... */ 25978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen caddr_t ptr, lookup_ptr; 25988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint8_t lookup_used = 0; 25998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 26008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* are there any asconf params to send? */ 26018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) { 26028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (aa->sent == 0) 26038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 26048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 26058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (aa == NULL) 26068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 26078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 26088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 26098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * get a chunk header mbuf and a cluster for the asconf params since 26108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * it's simpler to fill in the asconf chunk header lookup address on 26118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the fly 26128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 261368beeca578347438d9c434680197647ed551935ft m_asconf_chk = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_chunk), 0, M_NOWAIT, 1, MT_DATA); 26148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (m_asconf_chk == NULL) { 26158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* no mbuf's */ 26168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, 26178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "compose_asconf: couldn't get chunk mbuf!\n"); 26188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 26198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 262068beeca578347438d9c434680197647ed551935ft m_asconf = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA); 26218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (m_asconf == NULL) { 26228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* no mbuf's */ 26238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, 26248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "compose_asconf: couldn't get mbuf!\n"); 26258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(m_asconf_chk); 26268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 26278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 26288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BUF_LEN(m_asconf_chk) = sizeof(struct sctp_asconf_chunk); 26298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BUF_LEN(m_asconf) = 0; 26308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen acp = mtod(m_asconf_chk, struct sctp_asconf_chunk *); 26318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen bzero(acp, sizeof(struct sctp_asconf_chunk)); 26328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* save pointers to lookup address and asconf params */ 26338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen lookup_ptr = (caddr_t)(acp + 1); /* after the header */ 26348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ptr = mtod(m_asconf, caddr_t); /* beginning of cluster */ 26358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 26368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* fill in chunk header info */ 26378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen acp->ch.chunk_type = SCTP_ASCONF; 26388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen acp->ch.chunk_flags = 0; 26398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen acp->serial_number = htonl(stcb->asoc.asconf_seq_out); 26408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.asconf_seq_out++; 26418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 26428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* add parameters... up to smallest MTU allowed */ 26438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) { 26448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (aa->sent) 26458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 26468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* get the parameter length */ 26478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen p_length = SCTP_SIZE32(aa->ap.aph.ph.param_length); 26488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* will it fit in current chunk? */ 2649b48fc31e0eefd3b5593a363dd52d50c254a69f89t if ((SCTP_BUF_LEN(m_asconf) + p_length > stcb->asoc.smallest_mtu) || 2650b48fc31e0eefd3b5593a363dd52d50c254a69f89t (SCTP_BUF_LEN(m_asconf) + p_length > MCLBYTES)) { 26518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* won't fit, so we're done with this chunk */ 26528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 26538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 26548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* assign (and store) a correlation id */ 26558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->ap.aph.correlation_id = correlation_id++; 26568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 26578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 26588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * fill in address if we're doing a delete this is a simple 26598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * way for us to fill in the correlation address, which 26608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * should only be used by the peer if we're deleting our 26618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * source address and adding a new address (e.g. renumbering 26628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * case) 26638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 26648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (lookup_used == 0 && 26658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (aa->special_del == 0) && 26668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS) { 26678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ipv6addr_param *lookup; 26688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t p_size, addr_size; 26698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 26708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen lookup = (struct sctp_ipv6addr_param *)lookup_ptr; 26718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen lookup->ph.param_type = 26728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen htons(aa->ap.addrp.ph.param_type); 26738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (aa->ap.addrp.ph.param_type == SCTP_IPV6_ADDRESS) { 26748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* copy IPv6 address */ 26758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen p_size = sizeof(struct sctp_ipv6addr_param); 26768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen addr_size = sizeof(struct in6_addr); 26778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 26788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* copy IPv4 address */ 26798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen p_size = sizeof(struct sctp_ipv4addr_param); 26808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen addr_size = sizeof(struct in_addr); 26818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 26828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen lookup->ph.param_length = htons(SCTP_SIZE32(p_size)); 26838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memcpy(lookup->addr, &aa->ap.addrp.addr, addr_size); 26848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(p_size); 26858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen lookup_used = 1; 26868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 26878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* copy into current space */ 26888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memcpy(ptr, &aa->ap, p_length); 26898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 26908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* network elements and update lengths */ 26918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aph = (struct sctp_asconf_paramhdr *)ptr; 26928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aap = (struct sctp_asconf_addr_param *)ptr; 26938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* correlation_id is transparent to peer, no htonl needed */ 26948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aph->ph.param_type = htons(aph->ph.param_type); 26958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aph->ph.param_length = htons(aph->ph.param_length); 26968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aap->addrp.ph.param_type = htons(aap->addrp.ph.param_type); 26978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aap->addrp.ph.param_length = htons(aap->addrp.ph.param_length); 26988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 26998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BUF_LEN(m_asconf) += SCTP_SIZE32(p_length); 27008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ptr += SCTP_SIZE32(p_length); 27018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 27028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 27038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * these params are removed off the pending list upon 27048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * getting an ASCONF-ACK back from the peer, just set flag 27058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 27068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->sent = 1; 27078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* check to see if the lookup addr has been populated yet */ 27098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (lookup_used == 0) { 27108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* NOTE: if the address param is optional, can skip this... */ 27118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* add any valid (existing) address... */ 27128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ipv6addr_param *lookup; 27138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t p_size, addr_size; 27148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr *found_addr; 27158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen caddr_t addr_ptr; 27168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 27178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) 27188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen found_addr = sctp_find_valid_localaddr(stcb, 27198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen addr_locked); 27208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen else 27218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen found_addr = sctp_find_valid_localaddr_ep(stcb); 27228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 27238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen lookup = (struct sctp_ipv6addr_param *)lookup_ptr; 27248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (found_addr != NULL) { 27258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (found_addr->sa_family) { 27268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 27278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 27288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* copy IPv6 address */ 27298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen lookup->ph.param_type = 27308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen htons(SCTP_IPV6_ADDRESS); 27318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen p_size = sizeof(struct sctp_ipv6addr_param); 27328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen addr_size = sizeof(struct in6_addr); 27338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen addr_ptr = (caddr_t)&((struct sockaddr_in6 *) 27348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen found_addr)->sin6_addr; 27358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 27368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 27378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 27388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 27398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* copy IPv4 address */ 27408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen lookup->ph.param_type = 27418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen htons(SCTP_IPV4_ADDRESS); 27428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen p_size = sizeof(struct sctp_ipv4addr_param); 27438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen addr_size = sizeof(struct in_addr); 27448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen addr_ptr = (caddr_t)&((struct sockaddr_in *) 27458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen found_addr)->sin_addr; 27468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 27478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 27488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 27498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen p_size = 0; 27508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen addr_size = 0; 27518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen addr_ptr = NULL; 27528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 27538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen lookup->ph.param_length = htons(SCTP_SIZE32(p_size)); 27558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memcpy(lookup->addr, addr_ptr, addr_size); 27568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(p_size); 27578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 27588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* uh oh... don't have any address?? */ 27598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, 27608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "compose_asconf: no lookup addr!\n"); 27618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* XXX for now, we send a IPv4 address of 0.0.0.0 */ 27628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen lookup->ph.param_type = htons(SCTP_IPV4_ADDRESS); 27638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen lookup->ph.param_length = htons(SCTP_SIZE32(sizeof(struct sctp_ipv4addr_param))); 27648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen bzero(lookup->addr, sizeof(struct in_addr)); 27658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(sizeof(struct sctp_ipv4addr_param)); 27668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* chain it all together */ 27698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BUF_NEXT(m_asconf_chk) = m_asconf; 27708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *retlen = SCTP_BUF_LEN(m_asconf_chk) + SCTP_BUF_LEN(m_asconf); 27715310a647a74c51d125d106f350ff224bb017b0a5t acp->ch.chunk_length = htons(*retlen); 27728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 27738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (m_asconf_chk); 27748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 27758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 27768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 27778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * section to handle address changes before an association is up eg. changes 27788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * during INIT/INIT-ACK/COOKIE-ECHO handshake 27798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 27808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 27818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 27828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * processes the (local) addresses in the INIT-ACK chunk 27838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 27848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 27858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m, 27868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen unsigned int offset, unsigned int length) 27878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 27888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_paramhdr tmp_param, *ph; 27898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t plen, ptype; 27908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ifa *sctp_ifa; 27911b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t union sctp_sockstore store; 27928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 2793c5e505da69d2f4a94b68ccdf8fcbd336110ff77ctuexen struct sctp_ipv6addr_param addr6_store; 27948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 27958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 2796c5e505da69d2f4a94b68ccdf8fcbd336110ff77ctuexen struct sctp_ipv4addr_param addr4_store; 27978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 27988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t vrf_id; 27998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 28008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF2, "processing init-ack addresses\n"); 28018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb == NULL) /* Un-needed check for SA */ 28028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 28038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 28048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* convert to upper bound */ 28058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen length += offset; 28060ac02f34d6041cd0018437596a5a9a94685e6919tuexen 28078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((offset + sizeof(struct sctp_paramhdr)) > length) { 28088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 28098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 28108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* go through the addresses in the init-ack */ 28118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ph = (struct sctp_paramhdr *) 28128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr), 28138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (uint8_t *)&tmp_param); 28148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen while (ph != NULL) { 28158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ptype = ntohs(ph->param_type); 28168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen plen = ntohs(ph->param_length); 28178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (ptype) { 28188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 28198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_IPV6_ADDRESS: 28208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 28218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ipv6addr_param *a6p; 28228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 28238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* get the entire IPv6 address param */ 28248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen a6p = (struct sctp_ipv6addr_param *) 28258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_getptr(m, offset, 28268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_ipv6addr_param), 2827c5e505da69d2f4a94b68ccdf8fcbd336110ff77ctuexen (uint8_t *)&addr6_store); 28288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (plen != sizeof(struct sctp_ipv6addr_param) || 28298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen a6p == NULL) { 28308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 28318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 28321b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t memset(&store, 0, sizeof(union sctp_sockstore)); 28331b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t store.sin6.sin6_family = AF_INET6; 28341b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t#ifdef HAVE_SIN6_LEN 28351b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t store.sin6.sin6_len = sizeof(struct sockaddr_in6); 28361b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t#endif 28371b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t store.sin6.sin6_port = stcb->rport; 28381b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t memcpy(&store.sin6.sin6_addr, a6p->addr, sizeof(struct in6_addr)); 28398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 28408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 28418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 28428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 28438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_IPV4_ADDRESS: 28448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 28458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ipv4addr_param *a4p; 28468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 28478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* get the entire IPv4 address param */ 28488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen a4p = (struct sctp_ipv4addr_param *)sctp_m_getptr(m, offset, 28498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_ipv4addr_param), 2850c5e505da69d2f4a94b68ccdf8fcbd336110ff77ctuexen (uint8_t *)&addr4_store); 28518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (plen != sizeof(struct sctp_ipv4addr_param) || 28528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen a4p == NULL) { 28538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 28548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 28551b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t memset(&store, 0, sizeof(union sctp_sockstore)); 28561b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t store.sin.sin_family = AF_INET; 28571b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t#ifdef HAVE_SIN_LEN 28581b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t store.sin.sin_len = sizeof(struct sockaddr_in); 28591b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t#endif 28601b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t store.sin.sin_port = stcb->rport; 28611b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t store.sin.sin_addr.s_addr = a4p->addr; 28628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 28638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 28648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 28658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 28668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto next_addr; 28678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 28688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 28698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* see if this address really (still) exists */ 28708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb) { 28718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf_id = stcb->asoc.vrf_id; 28728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 28738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf_id = SCTP_DEFAULT_VRFID; 28748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 28751b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t sctp_ifa = sctp_find_ifa_by_addr(&store.sa, vrf_id, 28768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ADDR_NOT_LOCKED); 28778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_ifa == NULL) { 28788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* address doesn't exist anymore */ 28798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int status; 28808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 28818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* are ASCONFs allowed ? */ 28828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((sctp_is_feature_on(stcb->sctp_ep, 28838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PCB_FLAGS_DO_ASCONF)) && 2884fb3816eaffe5878bb1286adb120fd160da178a05t stcb->asoc.asconf_supported) { 28858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* queue an ASCONF DEL_IP_ADDRESS */ 28861b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t status = sctp_asconf_queue_sa_delete(stcb, &store.sa); 28878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 28888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * if queued ok, and in correct state, send 28898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * out the ASCONF. 28908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 28918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (status == 0 && 28928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_GET_STATE(&stcb->asoc) == 28938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STATE_OPEN) { 28948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_TIMER_BASED_ASCONF 28958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, 28968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep, stcb, 28978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.primary_destination); 28988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 28998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED); 29008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 29018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 29028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 29038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 29048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 29058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexennext_addr: 29068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 29078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Sanity check: Make sure the length isn't 0, otherwise 29088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we'll be stuck in this loop for a long time... 29098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 29108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_SIZE32(plen) == 0) { 29118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("process_initack_addrs: bad len (%d) type=%xh\n", 29128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen plen, ptype); 29138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 29148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 29158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* get next parameter */ 29168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen offset += SCTP_SIZE32(plen); 29178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((offset + sizeof(struct sctp_paramhdr)) > length) 29188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 29198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset, 29201b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t sizeof(struct sctp_paramhdr), (uint8_t *)&tmp_param); 29218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } /* while */ 29228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 29238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 29248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* FIX ME: need to verify return result for v6 address type if v6 disabled */ 29258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 29268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * checks to see if a specific address is in the initack address list returns 29278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 1 if found, 0 if not 29288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 29298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic uint32_t 29300ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_addr_in_initack(struct mbuf *m, uint32_t offset, uint32_t length, struct sockaddr *sa) 29318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 29328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_paramhdr tmp_param, *ph; 29338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t plen, ptype; 29348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 29358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in *sin; 29368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ipv4addr_param *a4p; 2937c5e505da69d2f4a94b68ccdf8fcbd336110ff77ctuexen struct sctp_ipv6addr_param addr4_store; 29388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 29398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 29408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in6 *sin6; 29418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ipv6addr_param *a6p; 2942c5e505da69d2f4a94b68ccdf8fcbd336110ff77ctuexen struct sctp_ipv6addr_param addr6_store; 29438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_EMBEDDED_V6_SCOPE 29448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in6 sin6_tmp; 29458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 29468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 29478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 29488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (sa->sa_family) { 29498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 29508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 29518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 29528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 29538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 29548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 29558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 29568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 29578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 29588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 29598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 29608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 29618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF2, "find_initack_addr: starting search for "); 29628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa); 29638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* convert to upper bound */ 29648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen length += offset; 29658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 29668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((offset + sizeof(struct sctp_paramhdr)) > length) { 29678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, 29688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "find_initack_addr: invalid offset?\n"); 29698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 29708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 29718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* go through the addresses in the init-ack */ 29728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset, 29738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_paramhdr), (uint8_t *) & tmp_param); 29748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen while (ph != NULL) { 29758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ptype = ntohs(ph->param_type); 29768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen plen = ntohs(ph->param_length); 29778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (ptype) { 29788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 29798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_IPV6_ADDRESS: 29808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sa->sa_family == AF_INET6) { 29818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* get the entire IPv6 address param */ 29828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (plen != sizeof(struct sctp_ipv6addr_param)) { 29838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 29848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 29858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* get the entire IPv6 address param */ 29868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen a6p = (struct sctp_ipv6addr_param *) 29878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_getptr(m, offset, 29888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_ipv6addr_param), 2989c5e505da69d2f4a94b68ccdf8fcbd336110ff77ctuexen (uint8_t *)&addr6_store); 29908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (a6p == NULL) { 29918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 29928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 29938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6 = (struct sockaddr_in6 *)sa; 29948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_EMBEDDED_V6_SCOPE 29958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) { 29968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* create a copy and clear scope */ 29978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memcpy(&sin6_tmp, sin6, 29988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sockaddr_in6)); 29998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6 = &sin6_tmp; 30008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen in6_clearscope(&sin6->sin6_addr); 30018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* SCTP_EMBEDDED_V6_SCOPE */ 30038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (memcmp(&sin6->sin6_addr, a6p->addr, 30048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct in6_addr)) == 0) { 30058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* found it */ 30068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (1); 30078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 30108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* INET6 */ 30118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 30128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_IPV4_ADDRESS: 30138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sa->sa_family == AF_INET) { 30148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (plen != sizeof(struct sctp_ipv4addr_param)) { 30158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 30168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* get the entire IPv4 address param */ 30188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen a4p = (struct sctp_ipv4addr_param *) 30198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_getptr(m, offset, 30208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_ipv4addr_param), 3021c5e505da69d2f4a94b68ccdf8fcbd336110ff77ctuexen (uint8_t *)&addr4_store); 30228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (a4p == NULL) { 30238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 30248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin = (struct sockaddr_in *)sa; 30268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sin->sin_addr.s_addr == a4p->addr) { 30278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* found it */ 30288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (1); 30298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 30328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 30338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 30348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 30358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* get next parameter */ 30378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen offset += SCTP_SIZE32(plen); 30388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (offset + sizeof(struct sctp_paramhdr) > length) { 30398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 30408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ph = (struct sctp_paramhdr *) 30428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr), 30438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (uint8_t *) & tmp_param); 30448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } /* while */ 30458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* not found! */ 30468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 30478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 30488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 30498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 30508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * makes sure that the current endpoint local addr list is consistent with 30518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the new association (eg. subset bound, asconf allowed) adds addresses as 30528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * necessary 30538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 30548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 30558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_check_address_list_ep(struct sctp_tcb *stcb, struct mbuf *m, int offset, 30568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int length, struct sockaddr *init_addr) 30578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 30588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_laddr *laddr; 30598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 30608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* go through the endpoint list */ 30618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) { 30628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* be paranoid and validate the laddr */ 30638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (laddr->ifa == NULL) { 30648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, 30658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "check_addr_list_ep: laddr->ifa is NULL"); 30668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 30678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (laddr->ifa == NULL) { 30698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "check_addr_list_ep: laddr->ifa->ifa_addr is NULL"); 30708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 30718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* do i have it implicitly? */ 30738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_cmpaddr(&laddr->ifa->address.sa, init_addr)) { 30748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 30758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* check to see if in the init-ack */ 30770ac02f34d6041cd0018437596a5a9a94685e6919tuexen if (!sctp_addr_in_initack(m, offset, length, &laddr->ifa->address.sa)) { 30788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* try to add it */ 30798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_addr_mgmt_assoc(stcb->sctp_ep, stcb, laddr->ifa, 30808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ADD_IP_ADDRESS, SCTP_ADDR_NOT_LOCKED); 30818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 30848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 30858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 30868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * makes sure that the current kernel address list is consistent with the new 30878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * association (with all addrs bound) adds addresses as necessary 30888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 30898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 30908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_check_address_list_all(struct sctp_tcb *stcb, struct mbuf *m, int offset, 30918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int length, struct sockaddr *init_addr, 30928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t local_scope, uint16_t site_scope, 30938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t ipv4_scope, uint16_t loopback_scope) 30948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 30958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_vrf *vrf = NULL; 30968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ifn *sctp_ifn; 30978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ifa *sctp_ifa; 30988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t vrf_id; 30990ac02f34d6041cd0018437596a5a9a94685e6919tuexen#ifdef INET 31000ac02f34d6041cd0018437596a5a9a94685e6919tuexen struct sockaddr_in *sin; 31010ac02f34d6041cd0018437596a5a9a94685e6919tuexen#endif 31020ac02f34d6041cd0018437596a5a9a94685e6919tuexen#ifdef INET6 31030ac02f34d6041cd0018437596a5a9a94685e6919tuexen struct sockaddr_in6 *sin6; 31040ac02f34d6041cd0018437596a5a9a94685e6919tuexen#endif 31058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 31068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb) { 31078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf_id = stcb->asoc.vrf_id; 31080ac02f34d6041cd0018437596a5a9a94685e6919tuexen } else { 31098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 31108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 31118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ADDR_RLOCK(); 31128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf = sctp_find_vrf(vrf_id); 31138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (vrf == NULL) { 31148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ADDR_RUNLOCK(); 31158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 31168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 31178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* go through all our known interfaces */ 31188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) { 31198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (loopback_scope == 0 && SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) { 31208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* skip loopback interface */ 31218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 31228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 31238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* go through each interface address */ 31248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) { 31258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* do i have it implicitly? */ 31268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_cmpaddr(&sctp_ifa->address.sa, init_addr)) { 31278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 31288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 31290ac02f34d6041cd0018437596a5a9a94685e6919tuexen switch (sctp_ifa->address.sa.sa_family) { 31300ac02f34d6041cd0018437596a5a9a94685e6919tuexen#ifdef INET 31310ac02f34d6041cd0018437596a5a9a94685e6919tuexen case AF_INET: 3132bfb1bf7e665a02b48026482bf33d05c83dfad73bt sin = &sctp_ifa->address.sin; 3133998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__) 3134998635733088fde643e6d807fa76679c4ceeaa00t if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred, 3135998635733088fde643e6d807fa76679c4ceeaa00t &sin->sin_addr) != 0) { 3136998635733088fde643e6d807fa76679c4ceeaa00t continue; 3137998635733088fde643e6d807fa76679c4ceeaa00t } 3138998635733088fde643e6d807fa76679c4ceeaa00t#endif 31390ac02f34d6041cd0018437596a5a9a94685e6919tuexen if ((ipv4_scope == 0) && 31400ac02f34d6041cd0018437596a5a9a94685e6919tuexen (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) { 31410ac02f34d6041cd0018437596a5a9a94685e6919tuexen /* private address not in scope */ 31420ac02f34d6041cd0018437596a5a9a94685e6919tuexen continue; 31430ac02f34d6041cd0018437596a5a9a94685e6919tuexen } 31440ac02f34d6041cd0018437596a5a9a94685e6919tuexen break; 31450ac02f34d6041cd0018437596a5a9a94685e6919tuexen#endif 31460ac02f34d6041cd0018437596a5a9a94685e6919tuexen#ifdef INET6 31470ac02f34d6041cd0018437596a5a9a94685e6919tuexen case AF_INET6: 3148bfb1bf7e665a02b48026482bf33d05c83dfad73bt sin6 = &sctp_ifa->address.sin6; 3149998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__) 3150998635733088fde643e6d807fa76679c4ceeaa00t if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred, 3151998635733088fde643e6d807fa76679c4ceeaa00t &sin6->sin6_addr) != 0) { 3152998635733088fde643e6d807fa76679c4ceeaa00t continue; 3153998635733088fde643e6d807fa76679c4ceeaa00t } 3154998635733088fde643e6d807fa76679c4ceeaa00t#endif 31550ac02f34d6041cd0018437596a5a9a94685e6919tuexen if ((local_scope == 0) && 31560ac02f34d6041cd0018437596a5a9a94685e6919tuexen (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))) { 31570ac02f34d6041cd0018437596a5a9a94685e6919tuexen continue; 31580ac02f34d6041cd0018437596a5a9a94685e6919tuexen } 31590ac02f34d6041cd0018437596a5a9a94685e6919tuexen if ((site_scope == 0) && 31600ac02f34d6041cd0018437596a5a9a94685e6919tuexen (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) { 31610ac02f34d6041cd0018437596a5a9a94685e6919tuexen continue; 31620ac02f34d6041cd0018437596a5a9a94685e6919tuexen } 31630ac02f34d6041cd0018437596a5a9a94685e6919tuexen break; 31640ac02f34d6041cd0018437596a5a9a94685e6919tuexen#endif 31650ac02f34d6041cd0018437596a5a9a94685e6919tuexen default: 31660ac02f34d6041cd0018437596a5a9a94685e6919tuexen break; 31670ac02f34d6041cd0018437596a5a9a94685e6919tuexen } 31688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* check to see if in the init-ack */ 31690ac02f34d6041cd0018437596a5a9a94685e6919tuexen if (!sctp_addr_in_initack(m, offset, length, &sctp_ifa->address.sa)) { 31708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* try to add it */ 31718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_addr_mgmt_assoc(stcb->sctp_ep, stcb, 31728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifa, SCTP_ADD_IP_ADDRESS, 31738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ADDR_LOCKED); 31748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 31758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } /* end foreach ifa */ 31768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } /* end foreach ifn */ 31778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ADDR_RUNLOCK(); 31788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 31798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 31808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 31818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * validates an init-ack chunk (from a cookie-echo) with current addresses 31828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * adds addresses from the init-ack into our local address list, if needed 31838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * queues asconf adds/deletes addresses as needed and makes appropriate list 31848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * changes for source address selection m, offset: points to the start of the 31858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * address list in an init-ack chunk length: total length of the address 31868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * params only init_addr: address where my INIT-ACK was sent from 31878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 31888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 31898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_check_address_list(struct sctp_tcb *stcb, struct mbuf *m, int offset, 31908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int length, struct sockaddr *init_addr, 31918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t local_scope, uint16_t site_scope, 31928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t ipv4_scope, uint16_t loopback_scope) 31938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 31948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* process the local addresses in the initack */ 31958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_process_initack_addresses(stcb, m, offset, length); 31968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 31978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { 31988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* bound all case */ 31998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_check_address_list_all(stcb, m, offset, length, init_addr, 32008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen local_scope, site_scope, ipv4_scope, loopback_scope); 32018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 32028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* subset bound case */ 32038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_is_feature_on(stcb->sctp_ep, 32048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PCB_FLAGS_DO_ASCONF)) { 32058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* asconf's allowed */ 32068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_check_address_list_ep(stcb, m, offset, length, 32078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen init_addr); 32088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* else, no asconfs allowed, so what we sent is what we get */ 32108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 32128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 32138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 32148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sctp_bindx() support 32158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 32168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenuint32_t 32178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_addr_mgmt_ep_sa(struct sctp_inpcb *inp, struct sockaddr *sa, 32188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t type, uint32_t vrf_id, struct sctp_ifa *sctp_ifap) 32198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 32208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ifa *ifa; 32218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_laddr *laddr, *nladdr; 32228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 3223f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN 32248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sa->sa_len == 0) { 32258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EINVAL); 32268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (EINVAL); 32278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 32298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_ifap) { 32308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ifa = sctp_ifap; 3231e2828360ea9cf8951730d46f5c14626c9425cb30t } else if (type == SCTP_ADD_IP_ADDRESS) { 32328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* For an add the address MUST be on the system */ 32338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED); 32348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (type == SCTP_DEL_IP_ADDRESS) { 32358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* For a delete we need to find it in the inp */ 32368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ifa = sctp_find_ifa_in_ep(inp, sa, SCTP_ADDR_NOT_LOCKED); 32378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 32388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ifa = NULL; 32398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ifa != NULL) { 32418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (type == SCTP_ADD_IP_ADDRESS) { 32428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_add_local_addr_ep(inp, ifa, type); 32438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (type == SCTP_DEL_IP_ADDRESS) { 32448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->laddr_count < 2) { 32458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* can't delete the last local address */ 32468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EINVAL); 32478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (EINVAL); 32488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(laddr, &inp->sctp_addr_list, 32508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_nxt_addr) { 32518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ifa == laddr->ifa) { 32528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Mark in the delete */ 32538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen laddr->action = type; 32548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (LIST_EMPTY(&inp->sctp_asoc_list)) { 32588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 32598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * There is no need to start the iterator if 32608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the inp has no associations. 32618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 32628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (type == SCTP_DEL_IP_ADDRESS) { 32638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH_SAFE(laddr, &inp->sctp_addr_list, sctp_nxt_addr, nladdr) { 32648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (laddr->ifa == ifa) { 32658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_del_local_addr_ep(inp, ifa); 32668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 32708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_asconf_iterator *asc; 32718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_laddr *wi; 3272000a5bac556b28e74e4e98c540f66b1743e9312dtuexen 32738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MALLOC(asc, struct sctp_asconf_iterator *, 32748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_asconf_iterator), 32758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_M_ASC_IT); 32768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asc == NULL) { 32778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, ENOMEM); 32788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (ENOMEM); 32798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen wi = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_laddr), struct sctp_laddr); 32818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (wi == NULL) { 32828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FREE(asc, SCTP_M_ASC_IT); 32838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, ENOMEM); 32848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (ENOMEM); 32858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INIT(&asc->list_of_work); 32878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asc->cnt = 1; 32888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INCR_LADDR_COUNT(); 32898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen wi->ifa = ifa; 32908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen wi->action = type; 32918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&ifa->refcount, 1); 32928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INSERT_HEAD(&asc->list_of_work, wi, sctp_nxt_addr); 32938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)sctp_initiate_iterator(sctp_asconf_iterator_ep, 32948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_asconf_iterator_stcb, 32958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_asconf_iterator_ep_end, 32968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PCB_ANY_FLAGS, 32978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PCB_ANY_FEATURES, 32988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ASOC_ANY_STATE, 32998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void *)asc, 0, 33008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_asconf_iterator_end, inp, 0); 33018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 33038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 33048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* invalid address! */ 33058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EADDRNOTAVAIL); 33068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (EADDRNOTAVAIL); 33078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 33098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 33108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 33118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_asconf_send_nat_state_update(struct sctp_tcb *stcb, 33128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net) 33138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 33148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_asconf_addr *aa; 33158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ifa *sctp_ifap; 33168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_asconf_tag_param *vtag; 33178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 33188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in *to; 33198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 33208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 33218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in6 *to6; 33228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 33238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net == NULL) { 33248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "sctp_asconf_send_nat_state_update: Missing net\n"); 33258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 33268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb == NULL) { 33288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "sctp_asconf_send_nat_state_update: Missing stcb\n"); 33298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 33308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Need to have in the asconf: 33328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * - vtagparam(my_vtag/peer_vtag) 33338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * - add(0.0.0.0) 33348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * - del(0.0.0.0) 33358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * - Any global addresses add(addr) 33368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 33378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa), 33388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_M_ASC_ADDR); 33398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (aa == NULL) { 33408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* didn't get memory */ 33418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, 33428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "sctp_asconf_send_nat_state_update: failed to get memory!\n"); 33438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 33448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->special_del = 0; 33468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* fill in asconf address parameter fields */ 33478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* top level elements are "networked" during send */ 33488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->ifa = NULL; 33498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->sent = 0; /* clear sent flag */ 33508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vtag = (struct sctp_asconf_tag_param *)&aa->ap.aph; 33518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vtag->aph.ph.param_type = SCTP_NAT_VTAGS; 33528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vtag->aph.ph.param_length = sizeof(struct sctp_asconf_tag_param); 33538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vtag->local_vtag = htonl(stcb->asoc.my_vtag); 33548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vtag->remote_vtag = htonl(stcb->asoc.peer_vtag); 33558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next); 33568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 33578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa), 33588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_M_ASC_ADDR); 33598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (aa == NULL) { 33608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* didn't get memory */ 33618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, 33628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "sctp_asconf_send_nat_state_update: failed to get memory!\n"); 33638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 33648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memset(aa, 0, sizeof(struct sctp_asconf_addr)); 33668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* fill in asconf address parameter fields */ 33678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* ADD(0.0.0.0) */ 33688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (net->ro._l_addr.sa.sa_family) { 33698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 33708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 33718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS; 33728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addrv4_param); 33738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS; 33748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->ap.addrp.ph.param_length = sizeof (struct sctp_ipv4addr_param); 33758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* No need to add an address, we are using 0.0.0.0 */ 33768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next); 33778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 33788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 33798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 33808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 33818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS; 33828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addr_param); 33838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS; 33848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->ap.addrp.ph.param_length = sizeof (struct sctp_ipv6addr_param); 33858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* No need to add an address, we are using 0.0.0.0 */ 33868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next); 33878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 33888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 33898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa), 33918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_M_ASC_ADDR); 33928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (aa == NULL) { 33938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* didn't get memory */ 33948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, 33958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "sctp_asconf_send_nat_state_update: failed to get memory!\n"); 33968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 33978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memset(aa, 0, sizeof(struct sctp_asconf_addr)); 33998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* fill in asconf address parameter fields */ 34008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* ADD(0.0.0.0) */ 34018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (net->ro._l_addr.sa.sa_family) { 34028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 34038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 34048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS; 34058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addrv4_param); 34068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS; 34078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->ap.addrp.ph.param_length = sizeof (struct sctp_ipv4addr_param); 34088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* No need to add an address, we are using 0.0.0.0 */ 34098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next); 34108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 34118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 34128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 34138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 34148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->ap.aph.ph.param_type = SCTP_DEL_IP_ADDRESS; 34158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addr_param); 34168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS; 34178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aa->ap.addrp.ph.param_length = sizeof (struct sctp_ipv6addr_param); 34188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* No need to add an address, we are using 0.0.0.0 */ 34198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next); 34208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 34218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 34228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now we must hunt the addresses and add all global addresses */ 34248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { 34258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_vrf *vrf = NULL; 34268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ifn *sctp_ifnp; 34278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t vrf_id; 34288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 34298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf_id = stcb->sctp_ep->def_vrf_id; 34308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf = sctp_find_vrf(vrf_id); 34318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (vrf == NULL) { 34328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto skip_rest; 34338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 34358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ADDR_RLOCK(); 34368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(sctp_ifnp, &vrf->ifnlist, next_ifn) { 34378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(sctp_ifap, &sctp_ifnp->ifalist, next_ifa) { 34388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (sctp_ifap->address.sa.sa_family) { 34398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 34408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 34418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen to = &sctp_ifap->address.sin; 3442998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__) 3443998635733088fde643e6d807fa76679c4ceeaa00t if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred, 3444998635733088fde643e6d807fa76679c4ceeaa00t &to->sin_addr) != 0) { 3445998635733088fde643e6d807fa76679c4ceeaa00t continue; 3446998635733088fde643e6d807fa76679c4ceeaa00t } 3447998635733088fde643e6d807fa76679c4ceeaa00t#endif 34488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (IN4_ISPRIVATE_ADDRESS(&to->sin_addr)) { 34498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 34508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (IN4_ISLOOPBACK_ADDRESS(&to->sin_addr)) { 34528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 34538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 34558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 34568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 34578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 34588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen to6 = &sctp_ifap->address.sin6; 3459998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__) 3460998635733088fde643e6d807fa76679c4ceeaa00t if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred, 3461998635733088fde643e6d807fa76679c4ceeaa00t &to6->sin6_addr) != 0) { 3462998635733088fde643e6d807fa76679c4ceeaa00t continue; 3463998635733088fde643e6d807fa76679c4ceeaa00t } 3464998635733088fde643e6d807fa76679c4ceeaa00t#endif 34658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (IN6_IS_ADDR_LOOPBACK(&to6->sin6_addr)) { 34668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 34678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (IN6_IS_ADDR_LINKLOCAL(&to6->sin6_addr)) { 34698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 34708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 34728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 34738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 34748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 34758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_asconf_queue_mgmt(stcb, sctp_ifap, SCTP_ADD_IP_ADDRESS); 34778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ADDR_RUNLOCK(); 34808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 34818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_laddr *laddr; 34828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 34838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) { 34848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (laddr->ifa == NULL) { 34858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 34868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED) 34888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Address being deleted by the system, dont 34898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * list. 34908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 34918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 34928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (laddr->action == SCTP_DEL_IP_ADDRESS) { 34938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Address being deleted on this ep 34948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * don't list. 34958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 34968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 34978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap = laddr->ifa; 34998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (sctp_ifap->address.sa.sa_family) { 35008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 35018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 35028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen to = &sctp_ifap->address.sin; 35038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (IN4_ISPRIVATE_ADDRESS(&to->sin_addr)) { 35048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 35058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (IN4_ISLOOPBACK_ADDRESS(&to->sin_addr)) { 35078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 35088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 35108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 35118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 35128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 35138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen to6 = &sctp_ifap->address.sin6; 35148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (IN6_IS_ADDR_LOOPBACK(&to6->sin6_addr)) { 35158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 35168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (IN6_IS_ADDR_LINKLOCAL(&to6->sin6_addr)) { 35188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 35198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 35218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 35228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 35238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 35248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_asconf_queue_mgmt(stcb, sctp_ifap, SCTP_ADD_IP_ADDRESS); 35268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen skip_rest: 35298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now we must send the asconf into the queue */ 35308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_asconf(stcb, net, SCTP_ADDR_NOT_LOCKED); 35318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 3532