1163953Srrs/*- 2169382Srrs * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. 3235828Stuexen * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. 4235828Stuexen * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. 5163953Srrs * 6163953Srrs * Redistribution and use in source and binary forms, with or without 7163953Srrs * modification, are permitted provided that the following conditions are met: 8163953Srrs * 9163953Srrs * a) Redistributions of source code must retain the above copyright notice, 10228653Stuexen * this list of conditions and the following disclaimer. 11163953Srrs * 12163953Srrs * b) Redistributions in binary form must reproduce the above copyright 13163953Srrs * notice, this list of conditions and the following disclaimer in 14228653Stuexen * the documentation and/or other materials provided with the distribution. 15163953Srrs * 16163953Srrs * c) Neither the name of Cisco Systems, Inc. nor the names of its 17163953Srrs * contributors may be used to endorse or promote products derived 18163953Srrs * from this software without specific prior written permission. 19163953Srrs * 20163953Srrs * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21163953Srrs * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 22163953Srrs * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23163953Srrs * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24163953Srrs * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25163953Srrs * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26163953Srrs * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27163953Srrs * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28163953Srrs * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29163953Srrs * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30163953Srrs * THE POSSIBILITY OF SUCH DAMAGE. 31163953Srrs */ 32163953Srrs 33163953Srrs#include <sys/cdefs.h> 34163957Srrs__FBSDID("$FreeBSD$"); 35235828Stuexen 36163953Srrs#include <netinet/sctp_os.h> 37163953Srrs#include <netinet/sctp_var.h> 38167598Srrs#include <netinet/sctp_sysctl.h> 39163953Srrs#include <netinet/sctp_pcb.h> 40163953Srrs#include <netinet/sctp_header.h> 41163953Srrs#include <netinet/sctputil.h> 42163953Srrs#include <netinet/sctp_output.h> 43163953Srrs#include <netinet/sctp_asconf.h> 44172091Srrs#include <netinet/sctp_timer.h> 45163953Srrs 46163953Srrs/* 47163953Srrs * debug flags: 48163953Srrs * SCTP_DEBUG_ASCONF1: protocol info, general info and errors 49163953Srrs * SCTP_DEBUG_ASCONF2: detailed info 50163953Srrs */ 51163953Srrs 52163953Srrs 53163953Srrs/* 54237715Stuexen * RFC 5061 55163953Srrs * 56163953Srrs * An ASCONF parameter queue exists per asoc which holds the pending address 57163953Srrs * operations. Lists are updated upon receipt of ASCONF-ACK. 58163953Srrs * 59171477Srrs * A restricted_addrs list exists per assoc to hold local addresses that are 60171477Srrs * not (yet) usable by the assoc as a source address. These addresses are 61171477Srrs * either pending an ASCONF operation (and exist on the ASCONF parameter 62171477Srrs * queue), or they are permanently restricted (the peer has returned an 63171477Srrs * ERROR indication to an ASCONF(ADD), or the peer does not support ASCONF). 64171477Srrs * 65163953Srrs * Deleted addresses are always immediately removed from the lists as they will 66163953Srrs * (shortly) no longer exist in the kernel. We send ASCONFs as a courtesy, 67163953Srrs * only if allowed. 68163953Srrs */ 69163953Srrs 70163953Srrs/* 71171477Srrs * ASCONF parameter processing. 72171477Srrs * response_required: set if a reply is required (eg. SUCCESS_REPORT). 73171477Srrs * returns a mbuf to an "error" response parameter or NULL/"success" if ok. 74171477Srrs * FIX: allocating this many mbufs on the fly is pretty inefficient... 75163953Srrs */ 76163953Srrsstatic struct mbuf * 77163953Srrssctp_asconf_success_response(uint32_t id) 78163953Srrs{ 79163953Srrs struct mbuf *m_reply = NULL; 80163953Srrs struct sctp_asconf_paramhdr *aph; 81163953Srrs 82163953Srrs m_reply = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_paramhdr), 83243882Sglebius 0, M_NOWAIT, 1, MT_DATA); 84163953Srrs if (m_reply == NULL) { 85169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 86169420Srrs "asconf_success_response: couldn't get mbuf!\n"); 87228907Stuexen return (NULL); 88163953Srrs } 89163953Srrs aph = mtod(m_reply, struct sctp_asconf_paramhdr *); 90163953Srrs aph->correlation_id = id; 91163953Srrs aph->ph.param_type = htons(SCTP_SUCCESS_REPORT); 92163953Srrs aph->ph.param_length = sizeof(struct sctp_asconf_paramhdr); 93165647Srrs SCTP_BUF_LEN(m_reply) = aph->ph.param_length; 94163953Srrs aph->ph.param_length = htons(aph->ph.param_length); 95163953Srrs 96228907Stuexen return (m_reply); 97163953Srrs} 98163953Srrs 99163953Srrsstatic struct mbuf * 100163953Srrssctp_asconf_error_response(uint32_t id, uint16_t cause, uint8_t * error_tlv, 101163953Srrs uint16_t tlv_length) 102163953Srrs{ 103163953Srrs struct mbuf *m_reply = NULL; 104163953Srrs struct sctp_asconf_paramhdr *aph; 105163953Srrs struct sctp_error_cause *error; 106163953Srrs uint8_t *tlv; 107163953Srrs 108163953Srrs m_reply = sctp_get_mbuf_for_msg((sizeof(struct sctp_asconf_paramhdr) + 109163953Srrs tlv_length + 110163953Srrs sizeof(struct sctp_error_cause)), 111243882Sglebius 0, M_NOWAIT, 1, MT_DATA); 112163953Srrs if (m_reply == NULL) { 113169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 114169420Srrs "asconf_error_response: couldn't get mbuf!\n"); 115228907Stuexen return (NULL); 116163953Srrs } 117163953Srrs aph = mtod(m_reply, struct sctp_asconf_paramhdr *); 118163953Srrs error = (struct sctp_error_cause *)(aph + 1); 119163953Srrs 120163953Srrs aph->correlation_id = id; 121163953Srrs aph->ph.param_type = htons(SCTP_ERROR_CAUSE_IND); 122163953Srrs error->code = htons(cause); 123163953Srrs error->length = tlv_length + sizeof(struct sctp_error_cause); 124163953Srrs aph->ph.param_length = error->length + 125163953Srrs sizeof(struct sctp_asconf_paramhdr); 126163953Srrs 127163953Srrs if (aph->ph.param_length > MLEN) { 128169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 129169420Srrs "asconf_error_response: tlv_length (%xh) too big\n", 130169420Srrs tlv_length); 131163953Srrs sctp_m_freem(m_reply); /* discard */ 132228907Stuexen return (NULL); 133163953Srrs } 134163953Srrs if (error_tlv != NULL) { 135163953Srrs tlv = (uint8_t *) (error + 1); 136163953Srrs memcpy(tlv, error_tlv, tlv_length); 137163953Srrs } 138165647Srrs SCTP_BUF_LEN(m_reply) = aph->ph.param_length; 139163953Srrs error->length = htons(error->length); 140163953Srrs aph->ph.param_length = htons(aph->ph.param_length); 141163953Srrs 142228907Stuexen return (m_reply); 143163953Srrs} 144163953Srrs 145163953Srrsstatic struct mbuf * 146237715Stuexensctp_process_asconf_add_ip(struct sockaddr *src, struct sctp_asconf_paramhdr *aph, 147224641Stuexen struct sctp_tcb *stcb, int send_hb, int response_required) 148163953Srrs{ 149224641Stuexen struct sctp_nets *net; 150163953Srrs struct mbuf *m_reply = NULL; 151271746Stuexen union sctp_sockstore store; 152221249Stuexen struct sctp_paramhdr *ph; 153258454Stuexen uint16_t param_type, aparam_length; 154258454Stuexen 155258454Stuexen#if defined(INET) || defined(INET6) 156258454Stuexen uint16_t param_length; 157258454Stuexen 158258454Stuexen#endif 159163953Srrs struct sockaddr *sa; 160163953Srrs int zero_address = 0; 161225571Stuexen int bad_address = 0; 162163953Srrs 163221249Stuexen#ifdef INET 164221249Stuexen struct sockaddr_in *sin; 165221249Stuexen struct sctp_ipv4addr_param *v4addr; 166221249Stuexen 167221249Stuexen#endif 168163953Srrs#ifdef INET6 169163953Srrs struct sockaddr_in6 *sin6; 170163953Srrs struct sctp_ipv6addr_param *v6addr; 171163953Srrs 172221249Stuexen#endif 173163953Srrs 174163953Srrs aparam_length = ntohs(aph->ph.param_length); 175221249Stuexen ph = (struct sctp_paramhdr *)(aph + 1); 176221249Stuexen param_type = ntohs(ph->param_type); 177258454Stuexen#if defined(INET) || defined(INET6) 178221249Stuexen param_length = ntohs(ph->param_length); 179258454Stuexen#endif 180271746Stuexen sa = &store.sa; 181163953Srrs switch (param_type) { 182221249Stuexen#ifdef INET 183163953Srrs case SCTP_IPV4_ADDRESS: 184163953Srrs if (param_length != sizeof(struct sctp_ipv4addr_param)) { 185163953Srrs /* invalid param size */ 186228907Stuexen return (NULL); 187163953Srrs } 188221249Stuexen v4addr = (struct sctp_ipv4addr_param *)ph; 189271746Stuexen sin = &store.sin; 190163953Srrs bzero(sin, sizeof(*sin)); 191163953Srrs sin->sin_family = AF_INET; 192163953Srrs sin->sin_len = sizeof(struct sockaddr_in); 193163953Srrs sin->sin_port = stcb->rport; 194163953Srrs sin->sin_addr.s_addr = v4addr->addr; 195225571Stuexen if ((sin->sin_addr.s_addr == INADDR_BROADCAST) || 196225571Stuexen IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) { 197225584Stuexen bad_address = 1; 198225571Stuexen } 199163953Srrs if (sin->sin_addr.s_addr == INADDR_ANY) 200163953Srrs zero_address = 1; 201169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_add_ip: adding "); 202169420Srrs SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); 203163953Srrs break; 204221249Stuexen#endif 205221249Stuexen#ifdef INET6 206163953Srrs case SCTP_IPV6_ADDRESS: 207163953Srrs if (param_length != sizeof(struct sctp_ipv6addr_param)) { 208163953Srrs /* invalid param size */ 209228907Stuexen return (NULL); 210163953Srrs } 211221249Stuexen v6addr = (struct sctp_ipv6addr_param *)ph; 212271746Stuexen sin6 = &store.sin6; 213163953Srrs bzero(sin6, sizeof(*sin6)); 214163953Srrs sin6->sin6_family = AF_INET6; 215163953Srrs sin6->sin6_len = sizeof(struct sockaddr_in6); 216163953Srrs sin6->sin6_port = stcb->rport; 217163953Srrs memcpy((caddr_t)&sin6->sin6_addr, v6addr->addr, 218163953Srrs sizeof(struct in6_addr)); 219225571Stuexen if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { 220225571Stuexen bad_address = 1; 221225571Stuexen } 222163953Srrs if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) 223163953Srrs zero_address = 1; 224169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_add_ip: adding "); 225169420Srrs SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); 226221249Stuexen break; 227169420Srrs#endif 228163953Srrs default: 229163953Srrs m_reply = sctp_asconf_error_response(aph->correlation_id, 230225571Stuexen SCTP_CAUSE_INVALID_PARAM, (uint8_t *) aph, 231163953Srrs aparam_length); 232228907Stuexen return (m_reply); 233163953Srrs } /* end switch */ 234163953Srrs 235163953Srrs /* if 0.0.0.0/::0, add the source address instead */ 236179783Srrs if (zero_address && SCTP_BASE_SYSCTL(sctp_nat_friendly)) { 237237715Stuexen sa = src; 238169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 239169420Srrs "process_asconf_add_ip: using source addr "); 240237715Stuexen SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, src); 241163953Srrs } 242163953Srrs /* add the address */ 243225571Stuexen if (bad_address) { 244225571Stuexen m_reply = sctp_asconf_error_response(aph->correlation_id, 245225571Stuexen SCTP_CAUSE_INVALID_PARAM, (uint8_t *) aph, 246225571Stuexen aparam_length); 247225571Stuexen } else if (sctp_add_remote_addr(stcb, sa, &net, SCTP_DONOT_SETSCOPE, 248165220Srrs SCTP_ADDR_DYNAMIC_ADDED) != 0) { 249169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 250169420Srrs "process_asconf_add_ip: error adding address\n"); 251163953Srrs m_reply = sctp_asconf_error_response(aph->correlation_id, 252163953Srrs SCTP_CAUSE_RESOURCE_SHORTAGE, (uint8_t *) aph, 253163953Srrs aparam_length); 254163953Srrs } else { 255163953Srrs /* notify upper layer */ 256172090Srrs sctp_ulp_notify(SCTP_NOTIFY_ASCONF_ADD_IP, stcb, 0, sa, SCTP_SO_NOT_LOCKED); 257163953Srrs if (response_required) { 258163953Srrs m_reply = 259163953Srrs sctp_asconf_success_response(aph->correlation_id); 260163953Srrs } 261224641Stuexen sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, stcb->sctp_ep, stcb, net); 262169655Srrs sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, 263224641Stuexen stcb, net); 264224641Stuexen if (send_hb) { 265224641Stuexen sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED); 266224641Stuexen } 267163953Srrs } 268228907Stuexen return (m_reply); 269163953Srrs} 270163953Srrs 271163953Srrsstatic int 272171572Srrssctp_asconf_del_remote_addrs_except(struct sctp_tcb *stcb, struct sockaddr *src) 273163953Srrs{ 274163953Srrs struct sctp_nets *src_net, *net; 275163953Srrs 276163953Srrs /* make sure the source address exists as a destination net */ 277163953Srrs src_net = sctp_findnet(stcb, src); 278163953Srrs if (src_net == NULL) { 279163953Srrs /* not found */ 280228907Stuexen return (-1); 281163953Srrs } 282163953Srrs /* delete all destination addresses except the source */ 283163953Srrs TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 284163953Srrs if (net != src_net) { 285163953Srrs /* delete this address */ 286163953Srrs sctp_remove_net(stcb, net); 287169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 288169420Srrs "asconf_del_remote_addrs_except: deleting "); 289169420Srrs SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, 290169420Srrs (struct sockaddr *)&net->ro._l_addr); 291163953Srrs /* notify upper layer */ 292163953Srrs sctp_ulp_notify(SCTP_NOTIFY_ASCONF_DELETE_IP, stcb, 0, 293172090Srrs (struct sockaddr *)&net->ro._l_addr, SCTP_SO_NOT_LOCKED); 294163953Srrs } 295163953Srrs } 296228907Stuexen return (0); 297163953Srrs} 298163953Srrs 299163953Srrsstatic struct mbuf * 300237715Stuexensctp_process_asconf_delete_ip(struct sockaddr *src, 301237715Stuexen struct sctp_asconf_paramhdr *aph, 302163953Srrs struct sctp_tcb *stcb, int response_required) 303163953Srrs{ 304163953Srrs struct mbuf *m_reply = NULL; 305271746Stuexen union sctp_sockstore store; 306221249Stuexen struct sctp_paramhdr *ph; 307258454Stuexen uint16_t param_type, aparam_length; 308258454Stuexen 309258454Stuexen#if defined(INET) || defined(INET6) 310258454Stuexen uint16_t param_length; 311258454Stuexen 312258454Stuexen#endif 313163953Srrs struct sockaddr *sa; 314163953Srrs int zero_address = 0; 315163953Srrs int result; 316163953Srrs 317221249Stuexen#ifdef INET 318221249Stuexen struct sockaddr_in *sin; 319221249Stuexen struct sctp_ipv4addr_param *v4addr; 320221249Stuexen 321221249Stuexen#endif 322163953Srrs#ifdef INET6 323163953Srrs struct sockaddr_in6 *sin6; 324163953Srrs struct sctp_ipv6addr_param *v6addr; 325163953Srrs 326221249Stuexen#endif 327163953Srrs 328163953Srrs aparam_length = ntohs(aph->ph.param_length); 329221249Stuexen ph = (struct sctp_paramhdr *)(aph + 1); 330221249Stuexen param_type = ntohs(ph->param_type); 331258454Stuexen#if defined(INET) || defined(INET6) 332221249Stuexen param_length = ntohs(ph->param_length); 333258454Stuexen#endif 334271746Stuexen sa = &store.sa; 335163953Srrs switch (param_type) { 336221249Stuexen#ifdef INET 337163953Srrs case SCTP_IPV4_ADDRESS: 338163953Srrs if (param_length != sizeof(struct sctp_ipv4addr_param)) { 339163953Srrs /* invalid param size */ 340228907Stuexen return (NULL); 341163953Srrs } 342221249Stuexen v4addr = (struct sctp_ipv4addr_param *)ph; 343271746Stuexen sin = &store.sin; 344163953Srrs bzero(sin, sizeof(*sin)); 345163953Srrs sin->sin_family = AF_INET; 346163953Srrs sin->sin_len = sizeof(struct sockaddr_in); 347163953Srrs sin->sin_port = stcb->rport; 348163953Srrs sin->sin_addr.s_addr = v4addr->addr; 349163953Srrs if (sin->sin_addr.s_addr == INADDR_ANY) 350163953Srrs zero_address = 1; 351169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 352169420Srrs "process_asconf_delete_ip: deleting "); 353169420Srrs SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); 354163953Srrs break; 355221249Stuexen#endif 356221249Stuexen#ifdef INET6 357163953Srrs case SCTP_IPV6_ADDRESS: 358163953Srrs if (param_length != sizeof(struct sctp_ipv6addr_param)) { 359163953Srrs /* invalid param size */ 360228907Stuexen return (NULL); 361163953Srrs } 362221249Stuexen v6addr = (struct sctp_ipv6addr_param *)ph; 363271746Stuexen sin6 = &store.sin6; 364163953Srrs bzero(sin6, sizeof(*sin6)); 365163953Srrs sin6->sin6_family = AF_INET6; 366163953Srrs sin6->sin6_len = sizeof(struct sockaddr_in6); 367163953Srrs sin6->sin6_port = stcb->rport; 368163953Srrs memcpy(&sin6->sin6_addr, v6addr->addr, 369163953Srrs sizeof(struct in6_addr)); 370163953Srrs if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) 371163953Srrs zero_address = 1; 372169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 373169420Srrs "process_asconf_delete_ip: deleting "); 374169420Srrs SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); 375221249Stuexen break; 376169420Srrs#endif 377163953Srrs default: 378163953Srrs m_reply = sctp_asconf_error_response(aph->correlation_id, 379163953Srrs SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph, 380163953Srrs aparam_length); 381228907Stuexen return (m_reply); 382163953Srrs } 383163953Srrs 384163953Srrs /* make sure the source address is not being deleted */ 385237715Stuexen if (sctp_cmpaddr(sa, src)) { 386163953Srrs /* trying to delete the source address! */ 387169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_delete_ip: tried to delete source addr\n"); 388163953Srrs m_reply = sctp_asconf_error_response(aph->correlation_id, 389163953Srrs SCTP_CAUSE_DELETING_SRC_ADDR, (uint8_t *) aph, 390163953Srrs aparam_length); 391228907Stuexen return (m_reply); 392163953Srrs } 393163953Srrs /* if deleting 0.0.0.0/::0, delete all addresses except src addr */ 394179783Srrs if (zero_address && SCTP_BASE_SYSCTL(sctp_nat_friendly)) { 395237715Stuexen result = sctp_asconf_del_remote_addrs_except(stcb, src); 396163953Srrs 397163953Srrs if (result) { 398163953Srrs /* src address did not exist? */ 399169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_delete_ip: src addr does not exist?\n"); 400163953Srrs /* what error to reply with?? */ 401163953Srrs m_reply = 402163953Srrs sctp_asconf_error_response(aph->correlation_id, 403163953Srrs SCTP_CAUSE_REQUEST_REFUSED, (uint8_t *) aph, 404163953Srrs aparam_length); 405163953Srrs } else if (response_required) { 406163953Srrs m_reply = 407163953Srrs sctp_asconf_success_response(aph->correlation_id); 408163953Srrs } 409228907Stuexen return (m_reply); 410163953Srrs } 411163953Srrs /* delete the address */ 412163953Srrs result = sctp_del_remote_addr(stcb, sa); 413163953Srrs /* 414163953Srrs * note if result == -2, the address doesn't exist in the asoc but 415163953Srrs * since it's being deleted anyways, we just ack the delete -- but 416163953Srrs * this probably means something has already gone awry 417163953Srrs */ 418163953Srrs if (result == -1) { 419163953Srrs /* only one address in the asoc */ 420169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_delete_ip: tried to delete last IP addr!\n"); 421163953Srrs m_reply = sctp_asconf_error_response(aph->correlation_id, 422163953Srrs SCTP_CAUSE_DELETING_LAST_ADDR, (uint8_t *) aph, 423163953Srrs aparam_length); 424163953Srrs } else { 425163953Srrs if (response_required) { 426163953Srrs m_reply = sctp_asconf_success_response(aph->correlation_id); 427163953Srrs } 428163953Srrs /* notify upper layer */ 429172090Srrs sctp_ulp_notify(SCTP_NOTIFY_ASCONF_DELETE_IP, stcb, 0, sa, SCTP_SO_NOT_LOCKED); 430163953Srrs } 431228907Stuexen return (m_reply); 432163953Srrs} 433163953Srrs 434163953Srrsstatic struct mbuf * 435237715Stuexensctp_process_asconf_set_primary(struct sockaddr *src, 436171572Srrs struct sctp_asconf_paramhdr *aph, 437171572Srrs struct sctp_tcb *stcb, int response_required) 438163953Srrs{ 439163953Srrs struct mbuf *m_reply = NULL; 440271746Stuexen union sctp_sockstore store; 441221249Stuexen struct sctp_paramhdr *ph; 442258454Stuexen uint16_t param_type, aparam_length; 443258454Stuexen 444258454Stuexen#if defined(INET) || defined(INET6) 445258454Stuexen uint16_t param_length; 446258454Stuexen 447258454Stuexen#endif 448163953Srrs struct sockaddr *sa; 449163953Srrs int zero_address = 0; 450163953Srrs 451221249Stuexen#ifdef INET 452221249Stuexen struct sockaddr_in *sin; 453221249Stuexen struct sctp_ipv4addr_param *v4addr; 454221249Stuexen 455221249Stuexen#endif 456163953Srrs#ifdef INET6 457163953Srrs struct sockaddr_in6 *sin6; 458163953Srrs struct sctp_ipv6addr_param *v6addr; 459163953Srrs 460221249Stuexen#endif 461163953Srrs 462163953Srrs aparam_length = ntohs(aph->ph.param_length); 463221249Stuexen ph = (struct sctp_paramhdr *)(aph + 1); 464221249Stuexen param_type = ntohs(ph->param_type); 465258454Stuexen#if defined(INET) || defined(INET6) 466221249Stuexen param_length = ntohs(ph->param_length); 467258454Stuexen#endif 468271746Stuexen sa = &store.sa; 469163953Srrs switch (param_type) { 470221249Stuexen#ifdef INET 471163953Srrs case SCTP_IPV4_ADDRESS: 472163953Srrs if (param_length != sizeof(struct sctp_ipv4addr_param)) { 473163953Srrs /* invalid param size */ 474228907Stuexen return (NULL); 475163953Srrs } 476221249Stuexen v4addr = (struct sctp_ipv4addr_param *)ph; 477271746Stuexen sin = &store.sin; 478163953Srrs bzero(sin, sizeof(*sin)); 479163953Srrs sin->sin_family = AF_INET; 480163953Srrs sin->sin_len = sizeof(struct sockaddr_in); 481163953Srrs sin->sin_addr.s_addr = v4addr->addr; 482163953Srrs if (sin->sin_addr.s_addr == INADDR_ANY) 483163953Srrs zero_address = 1; 484169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_set_primary: "); 485169420Srrs SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); 486163953Srrs break; 487221249Stuexen#endif 488221249Stuexen#ifdef INET6 489163953Srrs case SCTP_IPV6_ADDRESS: 490163953Srrs if (param_length != sizeof(struct sctp_ipv6addr_param)) { 491163953Srrs /* invalid param size */ 492228907Stuexen return (NULL); 493163953Srrs } 494221249Stuexen v6addr = (struct sctp_ipv6addr_param *)ph; 495271746Stuexen sin6 = &store.sin6; 496163953Srrs bzero(sin6, sizeof(*sin6)); 497163953Srrs sin6->sin6_family = AF_INET6; 498163953Srrs sin6->sin6_len = sizeof(struct sockaddr_in6); 499163953Srrs memcpy((caddr_t)&sin6->sin6_addr, v6addr->addr, 500163953Srrs sizeof(struct in6_addr)); 501163953Srrs if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) 502163953Srrs zero_address = 1; 503169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_set_primary: "); 504169420Srrs SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); 505221249Stuexen break; 506169420Srrs#endif 507163953Srrs default: 508163953Srrs m_reply = sctp_asconf_error_response(aph->correlation_id, 509163953Srrs SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph, 510163953Srrs aparam_length); 511228907Stuexen return (m_reply); 512163953Srrs } 513163953Srrs 514163953Srrs /* if 0.0.0.0/::0, use the source address instead */ 515179783Srrs if (zero_address && SCTP_BASE_SYSCTL(sctp_nat_friendly)) { 516237715Stuexen sa = src; 517169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 518169420Srrs "process_asconf_set_primary: using source addr "); 519237715Stuexen SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, src); 520163953Srrs } 521163953Srrs /* set the primary address */ 522163953Srrs if (sctp_set_primary_addr(stcb, sa, NULL) == 0) { 523169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 524169420Srrs "process_asconf_set_primary: primary address set\n"); 525163953Srrs /* notify upper layer */ 526172090Srrs sctp_ulp_notify(SCTP_NOTIFY_ASCONF_SET_PRIMARY, stcb, 0, sa, SCTP_SO_NOT_LOCKED); 527224641Stuexen if ((stcb->asoc.primary_destination->dest_state & SCTP_ADDR_REACHABLE) && 528224641Stuexen (!(stcb->asoc.primary_destination->dest_state & SCTP_ADDR_PF)) && 529224641Stuexen (stcb->asoc.alternate)) { 530224641Stuexen sctp_free_remote_addr(stcb->asoc.alternate); 531224641Stuexen stcb->asoc.alternate = NULL; 532224641Stuexen } 533163953Srrs if (response_required) { 534163953Srrs m_reply = sctp_asconf_success_response(aph->correlation_id); 535163953Srrs } 536172091Srrs /* 537172091Srrs * Mobility adaptation. Ideally, when the reception of SET 538172091Srrs * PRIMARY with DELETE IP ADDRESS of the previous primary 539172091Srrs * destination, unacknowledged DATA are retransmitted 540172091Srrs * immediately to the new primary destination for seamless 541206137Stuexen * handover. If the destination is UNCONFIRMED and marked to 542206137Stuexen * REQ_PRIM, The retransmission occur when reception of the 543206137Stuexen * HEARTBEAT-ACK. (See sctp_handle_heartbeat_ack in 544172091Srrs * sctp_input.c) Also, when change of the primary 545172091Srrs * destination, it is better that all subsequent new DATA 546172091Srrs * containing already queued DATA are transmitted to the new 547172091Srrs * primary destination. (by micchie) 548172091Srrs */ 549172091Srrs if ((sctp_is_mobility_feature_on(stcb->sctp_ep, 550172091Srrs SCTP_MOBILITY_BASE) || 551172091Srrs sctp_is_mobility_feature_on(stcb->sctp_ep, 552172091Srrs SCTP_MOBILITY_FASTHANDOFF)) && 553172091Srrs sctp_is_mobility_feature_on(stcb->sctp_ep, 554172091Srrs SCTP_MOBILITY_PRIM_DELETED) && 555172091Srrs (stcb->asoc.primary_destination->dest_state & 556172091Srrs SCTP_ADDR_UNCONFIRMED) == 0) { 557172091Srrs 558283822Stuexen sctp_timer_stop(SCTP_TIMER_TYPE_PRIM_DELETED, 559283822Stuexen stcb->sctp_ep, stcb, NULL, 560283822Stuexen SCTP_FROM_SCTP_ASCONF + SCTP_LOC_1); 561172091Srrs if (sctp_is_mobility_feature_on(stcb->sctp_ep, 562172091Srrs SCTP_MOBILITY_FASTHANDOFF)) { 563172091Srrs sctp_assoc_immediate_retrans(stcb, 564172091Srrs stcb->asoc.primary_destination); 565172091Srrs } 566172091Srrs if (sctp_is_mobility_feature_on(stcb->sctp_ep, 567172091Srrs SCTP_MOBILITY_BASE)) { 568212712Stuexen sctp_move_chunks_from_net(stcb, 569212712Stuexen stcb->asoc.deleted_primary); 570172091Srrs } 571172091Srrs sctp_delete_prim_timer(stcb->sctp_ep, stcb, 572172091Srrs stcb->asoc.deleted_primary); 573172091Srrs } 574163953Srrs } else { 575163953Srrs /* couldn't set the requested primary address! */ 576169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 577169420Srrs "process_asconf_set_primary: set primary failed!\n"); 578163953Srrs /* must have been an invalid address, so report */ 579163953Srrs m_reply = sctp_asconf_error_response(aph->correlation_id, 580163953Srrs SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph, 581163953Srrs aparam_length); 582163953Srrs } 583163953Srrs 584228907Stuexen return (m_reply); 585163953Srrs} 586163953Srrs 587163953Srrs/* 588163953Srrs * handles an ASCONF chunk. 589163953Srrs * if all parameters are processed ok, send a plain (empty) ASCONF-ACK 590163953Srrs */ 591163953Srrsvoid 592163953Srrssctp_handle_asconf(struct mbuf *m, unsigned int offset, 593237715Stuexen struct sockaddr *src, 594171990Srrs struct sctp_asconf_chunk *cp, struct sctp_tcb *stcb, 595171990Srrs int first) 596163953Srrs{ 597163953Srrs struct sctp_association *asoc; 598163953Srrs uint32_t serial_num; 599171990Srrs struct mbuf *n, *m_ack, *m_result, *m_tail; 600163953Srrs struct sctp_asconf_ack_chunk *ack_cp; 601283713Stuexen struct sctp_asconf_paramhdr *aph; 602163953Srrs struct sctp_ipv6addr_param *p_addr; 603224641Stuexen unsigned int asconf_limit, cnt; 604163953Srrs int error = 0; /* did an error occur? */ 605163953Srrs 606163953Srrs /* asconf param buffer */ 607166675Srrs uint8_t aparam_buf[SCTP_PARAM_BUFFER_SIZE]; 608171990Srrs struct sctp_asconf_ack *ack, *ack_next; 609163953Srrs 610163953Srrs /* verify minimum length */ 611163953Srrs if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_asconf_chunk)) { 612169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 613169420Srrs "handle_asconf: chunk too small = %xh\n", 614169420Srrs ntohs(cp->ch.chunk_length)); 615163953Srrs return; 616163953Srrs } 617163953Srrs asoc = &stcb->asoc; 618163953Srrs serial_num = ntohl(cp->serial_number); 619163953Srrs 620216825Stuexen if (SCTP_TSN_GE(asoc->asconf_seq_in, serial_num)) { 621163953Srrs /* got a duplicate ASCONF */ 622169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 623169420Srrs "handle_asconf: got duplicate serial number = %xh\n", 624169420Srrs serial_num); 625163953Srrs return; 626163953Srrs } else if (serial_num != (asoc->asconf_seq_in + 1)) { 627169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: incorrect serial number = %xh (expected next = %xh)\n", 628169420Srrs serial_num, asoc->asconf_seq_in + 1); 629163953Srrs return; 630163953Srrs } 631163953Srrs /* it's the expected "next" sequence number, so process it */ 632163953Srrs asoc->asconf_seq_in = serial_num; /* update sequence */ 633163953Srrs /* get length of all the param's in the ASCONF */ 634163953Srrs asconf_limit = offset + ntohs(cp->ch.chunk_length); 635169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 636169420Srrs "handle_asconf: asconf_limit=%u, sequence=%xh\n", 637169420Srrs asconf_limit, serial_num); 638171990Srrs 639171990Srrs if (first) { 640171990Srrs /* delete old cache */ 641221249Stuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: Now processing first ASCONF. Try to delete old cache\n"); 642171990Srrs 643216822Stuexen TAILQ_FOREACH_SAFE(ack, &asoc->asconf_ack_sent, next, ack_next) { 644171990Srrs if (ack->serial_number == serial_num) 645171990Srrs break; 646171990Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: delete old(%u) < first(%u)\n", 647171990Srrs ack->serial_number, serial_num); 648216822Stuexen TAILQ_REMOVE(&asoc->asconf_ack_sent, ack, next); 649171990Srrs if (ack->data != NULL) { 650171990Srrs sctp_m_freem(ack->data); 651171990Srrs } 652179783Srrs SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asconf_ack), ack); 653171990Srrs } 654163953Srrs } 655165647Srrs m_ack = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_ack_chunk), 0, 656243882Sglebius M_NOWAIT, 1, MT_DATA); 657163953Srrs if (m_ack == NULL) { 658169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 659169420Srrs "handle_asconf: couldn't get mbuf!\n"); 660163953Srrs return; 661163953Srrs } 662163953Srrs m_tail = m_ack; /* current reply chain's tail */ 663163953Srrs 664163953Srrs /* fill in ASCONF-ACK header */ 665163953Srrs ack_cp = mtod(m_ack, struct sctp_asconf_ack_chunk *); 666163953Srrs ack_cp->ch.chunk_type = SCTP_ASCONF_ACK; 667163953Srrs ack_cp->ch.chunk_flags = 0; 668163953Srrs ack_cp->serial_number = htonl(serial_num); 669163953Srrs /* set initial lengths (eg. just an ASCONF-ACK), ntohx at the end! */ 670165647Srrs SCTP_BUF_LEN(m_ack) = sizeof(struct sctp_asconf_ack_chunk); 671163953Srrs ack_cp->ch.chunk_length = sizeof(struct sctp_asconf_ack_chunk); 672163953Srrs 673163953Srrs /* skip the lookup address parameter */ 674163953Srrs offset += sizeof(struct sctp_asconf_chunk); 675163953Srrs p_addr = (struct sctp_ipv6addr_param *)sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr), (uint8_t *) & aparam_buf); 676163953Srrs if (p_addr == NULL) { 677169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 678169420Srrs "handle_asconf: couldn't get lookup addr!\n"); 679163953Srrs /* respond with a missing/invalid mandatory parameter error */ 680163953Srrs return; 681163953Srrs } 682163953Srrs /* param_length is already validated in process_control... */ 683163953Srrs offset += ntohs(p_addr->ph.param_length); /* skip lookup addr */ 684163953Srrs /* get pointer to first asconf param in ASCONF */ 685163953Srrs aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, sizeof(struct sctp_asconf_paramhdr), (uint8_t *) & aparam_buf); 686163953Srrs if (aph == NULL) { 687169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "Empty ASCONF received?\n"); 688163953Srrs goto send_reply; 689163953Srrs } 690163953Srrs /* process through all parameters */ 691224641Stuexen cnt = 0; 692163953Srrs while (aph != NULL) { 693163953Srrs unsigned int param_length, param_type; 694163953Srrs 695163953Srrs param_type = ntohs(aph->ph.param_type); 696163953Srrs param_length = ntohs(aph->ph.param_length); 697163953Srrs if (offset + param_length > asconf_limit) { 698163953Srrs /* parameter goes beyond end of chunk! */ 699163953Srrs sctp_m_freem(m_ack); 700163953Srrs return; 701163953Srrs } 702163953Srrs m_result = NULL; 703163953Srrs 704163953Srrs if (param_length > sizeof(aparam_buf)) { 705169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: param length (%u) larger than buffer size!\n", param_length); 706163953Srrs sctp_m_freem(m_ack); 707163953Srrs return; 708163953Srrs } 709163953Srrs if (param_length <= sizeof(struct sctp_paramhdr)) { 710169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: param length (%u) too short\n", param_length); 711163953Srrs sctp_m_freem(m_ack); 712163953Srrs } 713163953Srrs /* get the entire parameter */ 714163953Srrs aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, param_length, aparam_buf); 715163953Srrs if (aph == NULL) { 716169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: couldn't get entire param\n"); 717163953Srrs sctp_m_freem(m_ack); 718163953Srrs return; 719163953Srrs } 720163953Srrs switch (param_type) { 721163953Srrs case SCTP_ADD_IP_ADDRESS: 722237715Stuexen m_result = sctp_process_asconf_add_ip(src, aph, stcb, 723224641Stuexen (cnt < SCTP_BASE_SYSCTL(sctp_hb_maxburst)), error); 724224641Stuexen cnt++; 725163953Srrs break; 726163953Srrs case SCTP_DEL_IP_ADDRESS: 727237715Stuexen m_result = sctp_process_asconf_delete_ip(src, aph, stcb, 728163953Srrs error); 729163953Srrs break; 730163953Srrs case SCTP_ERROR_CAUSE_IND: 731163953Srrs /* not valid in an ASCONF chunk */ 732163953Srrs break; 733163953Srrs case SCTP_SET_PRIM_ADDR: 734237715Stuexen m_result = sctp_process_asconf_set_primary(src, aph, 735163953Srrs stcb, error); 736163953Srrs break; 737185694Srrs case SCTP_NAT_VTAGS: 738185694Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: sees a NAT VTAG state parameter\n"); 739185694Srrs break; 740163953Srrs case SCTP_SUCCESS_REPORT: 741163953Srrs /* not valid in an ASCONF chunk */ 742163953Srrs break; 743163953Srrs case SCTP_ULP_ADAPTATION: 744163953Srrs /* FIX */ 745163953Srrs break; 746163953Srrs default: 747163953Srrs if ((param_type & 0x8000) == 0) { 748163953Srrs /* Been told to STOP at this param */ 749163953Srrs asconf_limit = offset; 750163953Srrs /* 751163953Srrs * FIX FIX - We need to call 752163953Srrs * sctp_arethere_unrecognized_parameters() 753163953Srrs * to get a operr and send it for any 754163953Srrs * param's with the 0x4000 bit set OR do it 755163953Srrs * here ourselves... note we still must STOP 756163953Srrs * if the 0x8000 bit is clear. 757163953Srrs */ 758163953Srrs } 759163953Srrs /* unknown/invalid param type */ 760163953Srrs break; 761163953Srrs } /* switch */ 762163953Srrs 763163953Srrs /* add any (error) result to the reply mbuf chain */ 764163953Srrs if (m_result != NULL) { 765165647Srrs SCTP_BUF_NEXT(m_tail) = m_result; 766163953Srrs m_tail = m_result; 767163953Srrs /* update lengths, make sure it's aligned too */ 768165647Srrs SCTP_BUF_LEN(m_result) = SCTP_SIZE32(SCTP_BUF_LEN(m_result)); 769165647Srrs ack_cp->ch.chunk_length += SCTP_BUF_LEN(m_result); 770163953Srrs /* set flag to force success reports */ 771163953Srrs error = 1; 772163953Srrs } 773163953Srrs offset += SCTP_SIZE32(param_length); 774163953Srrs /* update remaining ASCONF message length to process */ 775163953Srrs if (offset >= asconf_limit) { 776163953Srrs /* no more data in the mbuf chain */ 777163953Srrs break; 778163953Srrs } 779163953Srrs /* get pointer to next asconf param */ 780163953Srrs aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, 781163953Srrs sizeof(struct sctp_asconf_paramhdr), 782163953Srrs (uint8_t *) & aparam_buf); 783163953Srrs if (aph == NULL) { 784163953Srrs /* can't get an asconf paramhdr */ 785169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: can't get asconf param hdr!\n"); 786163953Srrs /* FIX ME - add error here... */ 787163953Srrs } 788169420Srrs } 789163953Srrs 790163953Srrssend_reply: 791163953Srrs ack_cp->ch.chunk_length = htons(ack_cp->ch.chunk_length); 792163953Srrs /* save the ASCONF-ACK reply */ 793179783Srrs ack = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_asconf_ack), 794171990Srrs struct sctp_asconf_ack); 795171990Srrs if (ack == NULL) { 796171990Srrs sctp_m_freem(m_ack); 797171990Srrs return; 798171990Srrs } 799171990Srrs ack->serial_number = serial_num; 800171990Srrs ack->last_sent_to = NULL; 801171990Srrs ack->data = m_ack; 802209178Stuexen ack->len = 0; 803221249Stuexen for (n = m_ack; n != NULL; n = SCTP_BUF_NEXT(n)) { 804171990Srrs ack->len += SCTP_BUF_LEN(n); 805171990Srrs } 806171990Srrs TAILQ_INSERT_TAIL(&stcb->asoc.asconf_ack_sent, ack, next); 807163953Srrs 808163953Srrs /* see if last_control_chunk_from is set properly (use IP src addr) */ 809163953Srrs if (stcb->asoc.last_control_chunk_from == NULL) { 810163953Srrs /* 811163953Srrs * this could happen if the source address was just newly 812163953Srrs * added 813163953Srrs */ 814169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: looking up net for IP source address\n"); 815236515Stuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "Looking for IP source: "); 816236515Stuexen SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, src); 817236515Stuexen /* look up the from address */ 818236515Stuexen stcb->asoc.last_control_chunk_from = sctp_findnet(stcb, src); 819236515Stuexen#ifdef SCTP_DEBUG 820236515Stuexen if (stcb->asoc.last_control_chunk_from == NULL) { 821236515Stuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: IP source address not found?!\n"); 822163953Srrs } 823169420Srrs#endif 824163953Srrs } 825163953Srrs} 826163953Srrs 827163953Srrs/* 828163953Srrs * does the address match? returns 0 if not, 1 if so 829163953Srrs */ 830163953Srrsstatic uint32_t 831163953Srrssctp_asconf_addr_match(struct sctp_asconf_addr *aa, struct sockaddr *sa) 832163953Srrs{ 833221249Stuexen switch (sa->sa_family) { 834163953Srrs#ifdef INET6 835221249Stuexen case AF_INET6: 836221249Stuexen { 837221249Stuexen /* XXX scopeid */ 838221249Stuexen struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; 839163953Srrs 840221249Stuexen if ((aa->ap.addrp.ph.param_type == SCTP_IPV6_ADDRESS) && 841221249Stuexen (memcmp(&aa->ap.addrp.addr, &sin6->sin6_addr, 842221249Stuexen sizeof(struct in6_addr)) == 0)) { 843221249Stuexen return (1); 844221249Stuexen } 845221249Stuexen break; 846163953Srrs } 847221249Stuexen#endif 848221249Stuexen#ifdef INET 849221249Stuexen case AF_INET: 850221249Stuexen { 851221249Stuexen struct sockaddr_in *sin = (struct sockaddr_in *)sa; 852163953Srrs 853221249Stuexen if ((aa->ap.addrp.ph.param_type == SCTP_IPV4_ADDRESS) && 854221249Stuexen (memcmp(&aa->ap.addrp.addr, &sin->sin_addr, 855221249Stuexen sizeof(struct in_addr)) == 0)) { 856221249Stuexen return (1); 857221249Stuexen } 858221249Stuexen break; 859163953Srrs } 860221249Stuexen#endif 861221249Stuexen default: 862221249Stuexen break; 863163953Srrs } 864163953Srrs return (0); 865163953Srrs} 866163953Srrs 867163953Srrs/* 868179157Srrs * does the address match? returns 0 if not, 1 if so 869179157Srrs */ 870179157Srrsstatic uint32_t 871221249Stuexensctp_addr_match(struct sctp_paramhdr *ph, struct sockaddr *sa) 872179157Srrs{ 873258454Stuexen#if defined(INET) || defined(INET6) 874179157Srrs uint16_t param_type, param_length; 875179157Srrs 876221249Stuexen param_type = ntohs(ph->param_type); 877221249Stuexen param_length = ntohs(ph->param_length); 878258454Stuexen#endif 879221249Stuexen switch (sa->sa_family) { 880179157Srrs#ifdef INET6 881221249Stuexen case AF_INET6: 882221249Stuexen { 883221249Stuexen /* XXX scopeid */ 884221249Stuexen struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; 885221249Stuexen struct sctp_ipv6addr_param *v6addr; 886179157Srrs 887221249Stuexen v6addr = (struct sctp_ipv6addr_param *)ph; 888221249Stuexen if ((param_type == SCTP_IPV6_ADDRESS) && 889258454Stuexen (param_length == sizeof(struct sctp_ipv6addr_param)) && 890221249Stuexen (memcmp(&v6addr->addr, &sin6->sin6_addr, 891221249Stuexen sizeof(struct in6_addr)) == 0)) { 892221249Stuexen return (1); 893221249Stuexen } 894221249Stuexen break; 895179157Srrs } 896180955Srrs#endif 897221249Stuexen#ifdef INET 898221249Stuexen case AF_INET: 899221249Stuexen { 900221249Stuexen struct sockaddr_in *sin = (struct sockaddr_in *)sa; 901221249Stuexen struct sctp_ipv4addr_param *v4addr; 902179157Srrs 903221249Stuexen v4addr = (struct sctp_ipv4addr_param *)ph; 904221249Stuexen if ((param_type == SCTP_IPV4_ADDRESS) && 905258454Stuexen (param_length == sizeof(struct sctp_ipv4addr_param)) && 906221249Stuexen (memcmp(&v4addr->addr, &sin->sin_addr, 907221249Stuexen sizeof(struct in_addr)) == 0)) { 908221249Stuexen return (1); 909221249Stuexen } 910221249Stuexen break; 911179157Srrs } 912221249Stuexen#endif 913221249Stuexen default: 914221249Stuexen break; 915179157Srrs } 916179157Srrs return (0); 917179157Srrs} 918179157Srrs 919179157Srrs/* 920163953Srrs * Cleanup for non-responded/OP ERR'd ASCONF 921163953Srrs */ 922163953Srrsvoid 923163953Srrssctp_asconf_cleanup(struct sctp_tcb *stcb, struct sctp_nets *net) 924163953Srrs{ 925163953Srrs /* 926163953Srrs * clear out any existing asconfs going out 927163953Srrs */ 928169655Srrs sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net, 929169655Srrs SCTP_FROM_SCTP_ASCONF + SCTP_LOC_2); 930179157Srrs stcb->asoc.asconf_seq_out_acked = stcb->asoc.asconf_seq_out; 931163953Srrs /* remove the old ASCONF on our outbound queue */ 932163953Srrs sctp_toss_old_asconf(stcb); 933163953Srrs} 934163953Srrs 935163953Srrs/* 936171858Srrs * cleanup any cached source addresses that may be topologically 937171858Srrs * incorrect after a new address has been added to this interface. 938171858Srrs */ 939171858Srrsstatic void 940171858Srrssctp_asconf_nets_cleanup(struct sctp_tcb *stcb, struct sctp_ifn *ifn) 941171858Srrs{ 942171858Srrs struct sctp_nets *net; 943171858Srrs 944171858Srrs /* 945171858Srrs * Ideally, we want to only clear cached routes and source addresses 946171858Srrs * that are topologically incorrect. But since there is no easy way 947171858Srrs * to know whether the newly added address on the ifn would cause a 948171858Srrs * routing change (i.e. a new egress interface would be chosen) 949171858Srrs * without doing a new routing lookup and source address selection, 950171858Srrs * we will (for now) just flush any cached route using a different 951171858Srrs * ifn (and cached source addrs) and let output re-choose them 952171858Srrs * during the next send on that net. 953171858Srrs */ 954171858Srrs TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 955171858Srrs /* 956171858Srrs * clear any cached route (and cached source address) if the 957171858Srrs * route's interface is NOT the same as the address change. 958171858Srrs * If it's the same interface, just clear the cached source 959171858Srrs * address. 960171858Srrs */ 961171858Srrs if (SCTP_ROUTE_HAS_VALID_IFN(&net->ro) && 962209178Stuexen ((ifn == NULL) || 963209178Stuexen (SCTP_GET_IF_INDEX_FROM_ROUTE(&net->ro) != ifn->ifn_index))) { 964171858Srrs /* clear any cached route */ 965171858Srrs RTFREE(net->ro.ro_rt); 966171858Srrs net->ro.ro_rt = NULL; 967171858Srrs } 968171858Srrs /* clear any cached source address */ 969171858Srrs if (net->src_addr_selected) { 970171858Srrs sctp_free_ifa(net->ro._s_addr); 971171858Srrs net->ro._s_addr = NULL; 972171858Srrs net->src_addr_selected = 0; 973171858Srrs } 974171858Srrs } 975171858Srrs} 976171858Srrs 977172091Srrs 978172091Srrsvoid 979172091Srrssctp_assoc_immediate_retrans(struct sctp_tcb *stcb, struct sctp_nets *dstnet) 980172091Srrs{ 981172091Srrs int error; 982172091Srrs 983172118Srrs if (dstnet->dest_state & SCTP_ADDR_UNCONFIRMED) { 984172118Srrs return; 985172118Srrs } 986172091Srrs if (stcb->asoc.deleted_primary == NULL) { 987172091Srrs return; 988172091Srrs } 989172091Srrs if (!TAILQ_EMPTY(&stcb->asoc.sent_queue)) { 990172157Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "assoc_immediate_retrans: Deleted primary is "); 991172091Srrs SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &stcb->asoc.deleted_primary->ro._l_addr.sa); 992172091Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "Current Primary is "); 993172091Srrs SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &stcb->asoc.primary_destination->ro._l_addr.sa); 994172091Srrs sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, 995172091Srrs stcb->asoc.deleted_primary, 996283822Stuexen SCTP_FROM_SCTP_ASCONF + SCTP_LOC_3); 997172091Srrs stcb->asoc.num_send_timers_up--; 998172091Srrs if (stcb->asoc.num_send_timers_up < 0) { 999172091Srrs stcb->asoc.num_send_timers_up = 0; 1000172091Srrs } 1001172091Srrs SCTP_TCB_LOCK_ASSERT(stcb); 1002172091Srrs error = sctp_t3rxt_timer(stcb->sctp_ep, stcb, 1003172091Srrs stcb->asoc.deleted_primary); 1004172091Srrs if (error) { 1005172091Srrs SCTP_INP_DECR_REF(stcb->sctp_ep); 1006172091Srrs return; 1007172091Srrs } 1008172091Srrs SCTP_TCB_LOCK_ASSERT(stcb); 1009172091Srrs#ifdef SCTP_AUDITING_ENABLED 1010207099Stuexen sctp_auditing(4, stcb->sctp_ep, stcb, stcb->asoc.deleted_primary); 1011172091Srrs#endif 1012172091Srrs sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED); 1013172091Srrs if ((stcb->asoc.num_send_timers_up == 0) && 1014172091Srrs (stcb->asoc.sent_queue_cnt > 0)) { 1015172091Srrs struct sctp_tmit_chunk *chk; 1016172091Srrs 1017172091Srrs chk = TAILQ_FIRST(&stcb->asoc.sent_queue); 1018172091Srrs sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, 1019172091Srrs stcb, chk->whoTo); 1020172091Srrs } 1021172091Srrs } 1022172091Srrs return; 1023172091Srrs} 1024172091Srrs 1025171990Srrsstatic int 1026171990Srrs sctp_asconf_queue_mgmt(struct sctp_tcb *, struct sctp_ifa *, uint16_t); 1027171990Srrs 1028172091Srrsvoid 1029171990Srrssctp_net_immediate_retrans(struct sctp_tcb *stcb, struct sctp_nets *net) 1030171990Srrs{ 1031171990Srrs struct sctp_tmit_chunk *chk; 1032171990Srrs 1033172157Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "net_immediate_retrans: RTO is %d\n", net->RTO); 1034171990Srrs sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net, 1035283822Stuexen SCTP_FROM_SCTP_ASCONF + SCTP_LOC_4); 1036171990Srrs stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net); 1037171990Srrs net->error_count = 0; 1038171990Srrs TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) { 1039171990Srrs if (chk->whoTo == net) { 1040172091Srrs if (chk->sent < SCTP_DATAGRAM_RESEND) { 1041172091Srrs chk->sent = SCTP_DATAGRAM_RESEND; 1042172091Srrs sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 1043172396Srrs sctp_flight_size_decrease(chk); 1044172396Srrs sctp_total_flight_decrease(stcb, chk); 1045172396Srrs net->marked_retrans++; 1046172396Srrs stcb->asoc.marked_retrans++; 1047172091Srrs } 1048171990Srrs } 1049171990Srrs } 1050172396Srrs if (net->marked_retrans) { 1051172396Srrs sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED); 1052172396Srrs } 1053171990Srrs} 1054171990Srrs 1055171990Srrsstatic void 1056171990Srrssctp_path_check_and_react(struct sctp_tcb *stcb, struct sctp_ifa *newifa) 1057171990Srrs{ 1058171990Srrs struct sctp_nets *net; 1059171990Srrs int addrnum, changed; 1060171990Srrs 1061171990Srrs /* 1062171990Srrs * If number of local valid addresses is 1, the valid address is 1063206137Stuexen * probably newly added address. Several valid addresses in this 1064171990Srrs * association. A source address may not be changed. Additionally, 1065171990Srrs * they can be configured on a same interface as "alias" addresses. 1066171990Srrs * (by micchie) 1067171990Srrs */ 1068171990Srrs addrnum = sctp_local_addr_count(stcb); 1069171990Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "p_check_react(): %d local addresses\n", 1070171990Srrs addrnum); 1071171990Srrs if (addrnum == 1) { 1072171990Srrs TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 1073171990Srrs /* clear any cached route and source address */ 1074171990Srrs if (net->ro.ro_rt) { 1075171990Srrs RTFREE(net->ro.ro_rt); 1076171990Srrs net->ro.ro_rt = NULL; 1077171990Srrs } 1078171990Srrs if (net->src_addr_selected) { 1079171990Srrs sctp_free_ifa(net->ro._s_addr); 1080171990Srrs net->ro._s_addr = NULL; 1081171990Srrs net->src_addr_selected = 0; 1082171990Srrs } 1083171990Srrs /* Retransmit unacknowledged DATA chunks immediately */ 1084171990Srrs if (sctp_is_mobility_feature_on(stcb->sctp_ep, 1085171990Srrs SCTP_MOBILITY_FASTHANDOFF)) { 1086171990Srrs sctp_net_immediate_retrans(stcb, net); 1087171990Srrs } 1088171990Srrs /* also, SET PRIMARY is maybe already sent */ 1089171990Srrs } 1090171990Srrs return; 1091171990Srrs } 1092171990Srrs /* Multiple local addresses exsist in the association. */ 1093171990Srrs TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 1094171990Srrs /* clear any cached route and source address */ 1095171990Srrs if (net->ro.ro_rt) { 1096171990Srrs RTFREE(net->ro.ro_rt); 1097171990Srrs net->ro.ro_rt = NULL; 1098171990Srrs } 1099171990Srrs if (net->src_addr_selected) { 1100171990Srrs sctp_free_ifa(net->ro._s_addr); 1101171990Srrs net->ro._s_addr = NULL; 1102171990Srrs net->src_addr_selected = 0; 1103171990Srrs } 1104171990Srrs /* 1105171990Srrs * Check if the nexthop is corresponding to the new address. 1106171990Srrs * If the new address is corresponding to the current 1107206137Stuexen * nexthop, the path will be changed. If the new address is 1108171990Srrs * NOT corresponding to the current nexthop, the path will 1109171990Srrs * not be changed. 1110171990Srrs */ 1111171990Srrs SCTP_RTALLOC((sctp_route_t *) & net->ro, 1112284633Stuexen stcb->sctp_ep->def_vrf_id, 1113284633Stuexen stcb->sctp_ep->fibnum); 1114171990Srrs if (net->ro.ro_rt == NULL) 1115171990Srrs continue; 1116171990Srrs 1117172137Srrs changed = 0; 1118221249Stuexen switch (net->ro._l_addr.sa.sa_family) { 1119221249Stuexen#ifdef INET 1120221249Stuexen case AF_INET: 1121221249Stuexen if (sctp_v4src_match_nexthop(newifa, (sctp_route_t *) & net->ro)) { 1122171990Srrs changed = 1; 1123221249Stuexen } 1124221249Stuexen break; 1125221249Stuexen#endif 1126178251Srrs#ifdef INET6 1127221249Stuexen case AF_INET6: 1128171990Srrs if (sctp_v6src_match_nexthop( 1129221249Stuexen &newifa->address.sin6, (sctp_route_t *) & net->ro)) { 1130171990Srrs changed = 1; 1131221249Stuexen } 1132221249Stuexen break; 1133221249Stuexen#endif 1134221249Stuexen default: 1135221249Stuexen break; 1136171990Srrs } 1137171990Srrs /* 1138171990Srrs * if the newly added address does not relate routing 1139171990Srrs * information, we skip. 1140171990Srrs */ 1141171990Srrs if (changed == 0) 1142171990Srrs continue; 1143171990Srrs /* Retransmit unacknowledged DATA chunks immediately */ 1144171990Srrs if (sctp_is_mobility_feature_on(stcb->sctp_ep, 1145171990Srrs SCTP_MOBILITY_FASTHANDOFF)) { 1146171990Srrs sctp_net_immediate_retrans(stcb, net); 1147171990Srrs } 1148171990Srrs /* Send SET PRIMARY for this new address */ 1149171990Srrs if (net == stcb->asoc.primary_destination) { 1150171990Srrs (void)sctp_asconf_queue_mgmt(stcb, newifa, 1151171990Srrs SCTP_SET_PRIM_ADDR); 1152171990Srrs } 1153171990Srrs } 1154171990Srrs} 1155171990Srrs 1156171858Srrs/* 1157163953Srrs * process an ADD/DELETE IP ack from peer. 1158171572Srrs * addr: corresponding sctp_ifa to the address being added/deleted. 1159163953Srrs * type: SCTP_ADD_IP_ADDRESS or SCTP_DEL_IP_ADDRESS. 1160163953Srrs * flag: 1=success, 0=failure. 1161163953Srrs */ 1162163953Srrsstatic void 1163228653Stuexensctp_asconf_addr_mgmt_ack(struct sctp_tcb *stcb, struct sctp_ifa *addr, uint32_t flag) 1164163953Srrs{ 1165163953Srrs /* 1166163953Srrs * do the necessary asoc list work- if we get a failure indication, 1167171858Srrs * leave the address on the assoc's restricted list. If we get a 1168171858Srrs * success indication, remove the address from the restricted list. 1169163953Srrs */ 1170163953Srrs /* 1171163953Srrs * Note: this will only occur for ADD_IP_ADDRESS, since 1172163953Srrs * DEL_IP_ADDRESS is never actually added to the list... 1173163953Srrs */ 1174163953Srrs if (flag) { 1175171572Srrs /* success case, so remove from the restricted list */ 1176171572Srrs sctp_del_local_addr_restricted(stcb, addr); 1177171858Srrs 1178172190Srrs if (sctp_is_mobility_feature_on(stcb->sctp_ep, 1179172396Srrs SCTP_MOBILITY_BASE) || 1180172396Srrs sctp_is_mobility_feature_on(stcb->sctp_ep, 1181172396Srrs SCTP_MOBILITY_FASTHANDOFF)) { 1182171990Srrs sctp_path_check_and_react(stcb, addr); 1183171990Srrs return; 1184171990Srrs } 1185172190Srrs /* clear any cached/topologically incorrect source addresses */ 1186171858Srrs sctp_asconf_nets_cleanup(stcb, addr->ifn_p); 1187163953Srrs } 1188163953Srrs /* else, leave it on the list */ 1189163953Srrs} 1190163953Srrs 1191163953Srrs/* 1192171572Srrs * add an asconf add/delete/set primary IP address parameter to the queue. 1193163953Srrs * type = SCTP_ADD_IP_ADDRESS, SCTP_DEL_IP_ADDRESS, SCTP_SET_PRIM_ADDR. 1194171572Srrs * returns 0 if queued, -1 if not queued/removed. 1195171572Srrs * NOTE: if adding, but a delete for the same address is already scheduled 1196171572Srrs * (and not yet sent out), simply remove it from queue. Same for deleting 1197171572Srrs * an address already scheduled for add. If a duplicate operation is found, 1198171572Srrs * ignore the new one. 1199163953Srrs */ 1200171572Srrsstatic int 1201171572Srrssctp_asconf_queue_mgmt(struct sctp_tcb *stcb, struct sctp_ifa *ifa, 1202171477Srrs uint16_t type) 1203163953Srrs{ 1204163953Srrs struct sctp_asconf_addr *aa, *aa_next; 1205163953Srrs 1206163953Srrs /* make sure the request isn't already in the queue */ 1207216822Stuexen TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) { 1208163953Srrs /* address match? */ 1209167598Srrs if (sctp_asconf_addr_match(aa, &ifa->address.sa) == 0) 1210163953Srrs continue; 1211179157Srrs /* 1212179157Srrs * is the request already in queue but not sent? pass the 1213179157Srrs * request already sent in order to resolve the following 1214179157Srrs * case: 1. arrival of ADD, then sent 2. arrival of DEL. we 1215179157Srrs * can't remove the ADD request already sent 3. arrival of 1216179157Srrs * ADD 1217179157Srrs */ 1218179157Srrs if (aa->ap.aph.ph.param_type == type && aa->sent == 0) { 1219163953Srrs return (-1); 1220163953Srrs } 1221163953Srrs /* is the negative request already in queue, and not sent */ 1222171572Srrs if ((aa->sent == 0) && (type == SCTP_ADD_IP_ADDRESS) && 1223171572Srrs (aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS)) { 1224171572Srrs /* add requested, delete already queued */ 1225163953Srrs TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next); 1226171572Srrs /* remove the ifa from the restricted list */ 1227171572Srrs sctp_del_local_addr_restricted(stcb, ifa); 1228171572Srrs /* free the asconf param */ 1229170091Srrs SCTP_FREE(aa, SCTP_M_ASC_ADDR); 1230171572Srrs SCTPDBG(SCTP_DEBUG_ASCONF2, "asconf_queue_mgmt: add removes queued entry\n"); 1231163953Srrs return (-1); 1232163953Srrs } 1233171572Srrs if ((aa->sent == 0) && (type == SCTP_DEL_IP_ADDRESS) && 1234171572Srrs (aa->ap.aph.ph.param_type == SCTP_ADD_IP_ADDRESS)) { 1235171572Srrs /* delete requested, add already queued */ 1236171572Srrs TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next); 1237171572Srrs /* remove the aa->ifa from the restricted list */ 1238171572Srrs sctp_del_local_addr_restricted(stcb, aa->ifa); 1239171572Srrs /* free the asconf param */ 1240171572Srrs SCTP_FREE(aa, SCTP_M_ASC_ADDR); 1241171572Srrs SCTPDBG(SCTP_DEBUG_ASCONF2, "asconf_queue_mgmt: delete removes queued entry\n"); 1242171572Srrs return (-1); 1243171572Srrs } 1244163953Srrs } /* for each aa */ 1245163953Srrs 1246163953Srrs /* adding new request to the queue */ 1247171572Srrs SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa), 1248171572Srrs SCTP_M_ASC_ADDR); 1249163953Srrs if (aa == NULL) { 1250163953Srrs /* didn't get memory */ 1251171572Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "asconf_queue_mgmt: failed to get memory!\n"); 1252163953Srrs return (-1); 1253163953Srrs } 1254185694Srrs aa->special_del = 0; 1255163953Srrs /* fill in asconf address parameter fields */ 1256163953Srrs /* top level elements are "networked" during send */ 1257163953Srrs aa->ap.aph.ph.param_type = type; 1258163953Srrs aa->ifa = ifa; 1259168299Srrs atomic_add_int(&ifa->refcount, 1); 1260163953Srrs /* correlation_id filled in during send routine later... */ 1261221249Stuexen switch (ifa->address.sa.sa_family) { 1262221249Stuexen#ifdef INET6 1263221249Stuexen case AF_INET6: 1264221249Stuexen { 1265221249Stuexen struct sockaddr_in6 *sin6; 1266163953Srrs 1267271746Stuexen sin6 = &ifa->address.sin6; 1268221249Stuexen aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS; 1269221249Stuexen aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param)); 1270221249Stuexen aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + 1271221249Stuexen sizeof(struct sctp_ipv6addr_param); 1272221249Stuexen memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr, 1273221249Stuexen sizeof(struct in6_addr)); 1274221249Stuexen break; 1275221249Stuexen } 1276221249Stuexen#endif 1277221249Stuexen#ifdef INET 1278221249Stuexen case AF_INET: 1279221249Stuexen { 1280221249Stuexen struct sockaddr_in *sin; 1281163953Srrs 1282271746Stuexen sin = &ifa->address.sin; 1283221249Stuexen aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS; 1284221249Stuexen aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param)); 1285221249Stuexen aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + 1286221249Stuexen sizeof(struct sctp_ipv4addr_param); 1287221249Stuexen memcpy(&aa->ap.addrp.addr, &sin->sin_addr, 1288221249Stuexen sizeof(struct in_addr)); 1289221249Stuexen break; 1290221249Stuexen } 1291221249Stuexen#endif 1292221249Stuexen default: 1293163953Srrs /* invalid family! */ 1294170091Srrs SCTP_FREE(aa, SCTP_M_ASC_ADDR); 1295172190Srrs sctp_free_ifa(ifa); 1296163953Srrs return (-1); 1297163953Srrs } 1298163953Srrs aa->sent = 0; /* clear sent flag */ 1299163953Srrs 1300179157Srrs TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next); 1301163953Srrs#ifdef SCTP_DEBUG 1302218232Srrs if (SCTP_BASE_SYSCTL(sctp_debug_on) & SCTP_DEBUG_ASCONF2) { 1303179157Srrs if (type == SCTP_ADD_IP_ADDRESS) { 1304179157Srrs SCTP_PRINTF("asconf_queue_mgmt: inserted asconf ADD_IP_ADDRESS: "); 1305253493Stuexen SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, &ifa->address.sa); 1306179157Srrs } else if (type == SCTP_DEL_IP_ADDRESS) { 1307179157Srrs SCTP_PRINTF("asconf_queue_mgmt: appended asconf DEL_IP_ADDRESS: "); 1308253493Stuexen SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, &ifa->address.sa); 1309179157Srrs } else { 1310179157Srrs SCTP_PRINTF("asconf_queue_mgmt: appended asconf SET_PRIM_ADDR: "); 1311253493Stuexen SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, &ifa->address.sa); 1312163953Srrs } 1313179157Srrs } 1314169420Srrs#endif 1315163953Srrs 1316163953Srrs return (0); 1317163953Srrs} 1318163953Srrs 1319171572Srrs 1320163953Srrs/* 1321171572Srrs * add an asconf operation for the given ifa and type. 1322171572Srrs * type = SCTP_ADD_IP_ADDRESS, SCTP_DEL_IP_ADDRESS, SCTP_SET_PRIM_ADDR. 1323171572Srrs * returns 0 if completed, -1 if not completed, 1 if immediate send is 1324171572Srrs * advisable. 1325171572Srrs */ 1326171572Srrsstatic int 1327171572Srrssctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa, 1328171572Srrs uint16_t type) 1329171572Srrs{ 1330171572Srrs uint32_t status; 1331171572Srrs int pending_delete_queued = 0; 1332284507Stuexen int last; 1333171572Srrs 1334171572Srrs /* see if peer supports ASCONF */ 1335270362Stuexen if (stcb->asoc.asconf_supported == 0) { 1336171572Srrs return (-1); 1337171572Srrs } 1338171572Srrs /* 1339171572Srrs * if this is deleting the last address from the assoc, mark it as 1340171572Srrs * pending. 1341171572Srrs */ 1342284507Stuexen if ((type == SCTP_DEL_IP_ADDRESS) && !stcb->asoc.asconf_del_pending) { 1343284507Stuexen if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { 1344284507Stuexen last = (sctp_local_addr_count(stcb) == 0); 1345284507Stuexen } else { 1346284507Stuexen last = (sctp_local_addr_count(stcb) == 1); 1347284507Stuexen } 1348284507Stuexen if (last) { 1349284507Stuexen /* set the pending delete info only */ 1350284507Stuexen stcb->asoc.asconf_del_pending = 1; 1351284507Stuexen stcb->asoc.asconf_addr_del_pending = ifa; 1352284507Stuexen atomic_add_int(&ifa->refcount, 1); 1353284507Stuexen SCTPDBG(SCTP_DEBUG_ASCONF2, 1354284507Stuexen "asconf_queue_add: mark delete last address pending\n"); 1355284507Stuexen return (-1); 1356284507Stuexen } 1357171572Srrs } 1358179157Srrs /* queue an asconf parameter */ 1359179157Srrs status = sctp_asconf_queue_mgmt(stcb, ifa, type); 1360179157Srrs 1361171572Srrs /* 1362171572Srrs * if this is an add, and there is a delete also pending (i.e. the 1363171572Srrs * last local address is being changed), queue the pending delete 1364171572Srrs * too. 1365171572Srrs */ 1366179157Srrs if ((type == SCTP_ADD_IP_ADDRESS) && stcb->asoc.asconf_del_pending && (status == 0)) { 1367171572Srrs /* queue in the pending delete */ 1368171572Srrs if (sctp_asconf_queue_mgmt(stcb, 1369171572Srrs stcb->asoc.asconf_addr_del_pending, 1370171572Srrs SCTP_DEL_IP_ADDRESS) == 0) { 1371171572Srrs SCTPDBG(SCTP_DEBUG_ASCONF2, "asconf_queue_add: queing pending delete\n"); 1372171572Srrs pending_delete_queued = 1; 1373171572Srrs /* clear out the pending delete info */ 1374171572Srrs stcb->asoc.asconf_del_pending = 0; 1375171572Srrs sctp_free_ifa(stcb->asoc.asconf_addr_del_pending); 1376171572Srrs stcb->asoc.asconf_addr_del_pending = NULL; 1377171572Srrs } 1378171572Srrs } 1379179157Srrs if (pending_delete_queued) { 1380171572Srrs struct sctp_nets *net; 1381171572Srrs 1382171572Srrs /* 1383171572Srrs * since we know that the only/last address is now being 1384171572Srrs * changed in this case, reset the cwnd/rto on all nets to 1385171572Srrs * start as a new address and path. Also clear the error 1386171572Srrs * counts to give the assoc the best chance to complete the 1387171572Srrs * address change. 1388171572Srrs */ 1389171572Srrs TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 1390171572Srrs stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, 1391171572Srrs net); 1392171572Srrs net->RTO = 0; 1393171572Srrs net->error_count = 0; 1394171572Srrs } 1395171572Srrs stcb->asoc.overall_error_count = 0; 1396179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 1397171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 1398171943Srrs stcb->asoc.overall_error_count, 1399171943Srrs 0, 1400171943Srrs SCTP_FROM_SCTP_ASCONF, 1401171943Srrs __LINE__); 1402171943Srrs } 1403171572Srrs /* queue in an advisory set primary too */ 1404171572Srrs (void)sctp_asconf_queue_mgmt(stcb, ifa, SCTP_SET_PRIM_ADDR); 1405171572Srrs /* let caller know we should send this out immediately */ 1406171572Srrs status = 1; 1407171572Srrs } 1408171572Srrs return (status); 1409171572Srrs} 1410171572Srrs 1411172190Srrs/*- 1412172190Srrs * add an asconf delete IP address parameter to the queue by sockaddr and 1413172190Srrs * possibly with no sctp_ifa available. This is only called by the routine 1414172190Srrs * that checks the addresses in an INIT-ACK against the current address list. 1415163953Srrs * returns 0 if completed, non-zero if not completed. 1416172190Srrs * NOTE: if an add is already scheduled (and not yet sent out), simply 1417172190Srrs * remove it from queue. If a duplicate operation is found, ignore the 1418172190Srrs * new one. 1419163953Srrs */ 1420171572Srrsstatic int 1421172190Srrssctp_asconf_queue_sa_delete(struct sctp_tcb *stcb, struct sockaddr *sa) 1422163953Srrs{ 1423168299Srrs struct sctp_ifa *ifa; 1424163953Srrs struct sctp_asconf_addr *aa, *aa_next; 1425163953Srrs 1426169420Srrs if (stcb == NULL) { 1427169420Srrs return (-1); 1428169420Srrs } 1429163953Srrs /* see if peer supports ASCONF */ 1430270362Stuexen if (stcb->asoc.asconf_supported == 0) { 1431163953Srrs return (-1); 1432163953Srrs } 1433163953Srrs /* make sure the request isn't already in the queue */ 1434216822Stuexen TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) { 1435163953Srrs /* address match? */ 1436163953Srrs if (sctp_asconf_addr_match(aa, sa) == 0) 1437163953Srrs continue; 1438163953Srrs /* is the request already in queue (sent or not) */ 1439172190Srrs if (aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS) { 1440163953Srrs return (-1); 1441163953Srrs } 1442163953Srrs /* is the negative request already in queue, and not sent */ 1443163953Srrs if (aa->sent == 1) 1444163953Srrs continue; 1445172190Srrs if (aa->ap.aph.ph.param_type == SCTP_ADD_IP_ADDRESS) { 1446172190Srrs /* add already queued, so remove existing entry */ 1447163953Srrs TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next); 1448171572Srrs sctp_del_local_addr_restricted(stcb, aa->ifa); 1449163953Srrs /* free the entry */ 1450170091Srrs SCTP_FREE(aa, SCTP_M_ASC_ADDR); 1451163953Srrs return (-1); 1452163953Srrs } 1453163953Srrs } /* for each aa */ 1454172190Srrs 1455172190Srrs /* find any existing ifa-- NOTE ifa CAN be allowed to be NULL */ 1456283711Stuexen ifa = sctp_find_ifa_by_addr(sa, stcb->asoc.vrf_id, SCTP_ADDR_NOT_LOCKED); 1457163953Srrs 1458163953Srrs /* adding new request to the queue */ 1459171572Srrs SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa), 1460171572Srrs SCTP_M_ASC_ADDR); 1461163953Srrs if (aa == NULL) { 1462163953Srrs /* didn't get memory */ 1463169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 1464172190Srrs "sctp_asconf_queue_sa_delete: failed to get memory!\n"); 1465163953Srrs return (-1); 1466163953Srrs } 1467185694Srrs aa->special_del = 0; 1468163953Srrs /* fill in asconf address parameter fields */ 1469163953Srrs /* top level elements are "networked" during send */ 1470172190Srrs aa->ap.aph.ph.param_type = SCTP_DEL_IP_ADDRESS; 1471168299Srrs aa->ifa = ifa; 1472172190Srrs if (ifa) 1473172190Srrs atomic_add_int(&ifa->refcount, 1); 1474163953Srrs /* correlation_id filled in during send routine later... */ 1475221249Stuexen switch (sa->sa_family) { 1476221249Stuexen#ifdef INET6 1477221249Stuexen case AF_INET6: 1478221249Stuexen { 1479221249Stuexen /* IPv6 address */ 1480221249Stuexen struct sockaddr_in6 *sin6; 1481163953Srrs 1482221249Stuexen sin6 = (struct sockaddr_in6 *)sa; 1483221249Stuexen aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS; 1484221249Stuexen aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param)); 1485221249Stuexen aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv6addr_param); 1486221249Stuexen memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr, 1487221249Stuexen sizeof(struct in6_addr)); 1488221249Stuexen break; 1489221249Stuexen } 1490221249Stuexen#endif 1491221249Stuexen#ifdef INET 1492221249Stuexen case AF_INET: 1493221249Stuexen { 1494221249Stuexen /* IPv4 address */ 1495221249Stuexen struct sockaddr_in *sin = (struct sockaddr_in *)sa; 1496163953Srrs 1497221249Stuexen aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS; 1498221249Stuexen aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param)); 1499221249Stuexen aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv4addr_param); 1500221249Stuexen memcpy(&aa->ap.addrp.addr, &sin->sin_addr, 1501221249Stuexen sizeof(struct in_addr)); 1502221249Stuexen break; 1503221249Stuexen } 1504221249Stuexen#endif 1505221249Stuexen default: 1506163953Srrs /* invalid family! */ 1507170091Srrs SCTP_FREE(aa, SCTP_M_ASC_ADDR); 1508172190Srrs if (ifa) 1509172190Srrs sctp_free_ifa(ifa); 1510163953Srrs return (-1); 1511163953Srrs } 1512163953Srrs aa->sent = 0; /* clear sent flag */ 1513163953Srrs 1514172190Srrs /* delete goes to the back of the queue */ 1515172190Srrs TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next); 1516163953Srrs 1517172218Srrs /* sa_ignore MEMLEAK {memory is put on the tailq} */ 1518163953Srrs return (0); 1519163953Srrs} 1520163953Srrs 1521163953Srrs/* 1522163953Srrs * find a specific asconf param on our "sent" queue 1523163953Srrs */ 1524163953Srrsstatic struct sctp_asconf_addr * 1525163953Srrssctp_asconf_find_param(struct sctp_tcb *stcb, uint32_t correlation_id) 1526163953Srrs{ 1527163953Srrs struct sctp_asconf_addr *aa; 1528163953Srrs 1529163953Srrs TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) { 1530163953Srrs if (aa->ap.aph.correlation_id == correlation_id && 1531163953Srrs aa->sent == 1) { 1532163953Srrs /* found it */ 1533163953Srrs return (aa); 1534163953Srrs } 1535163953Srrs } 1536163953Srrs /* didn't find it */ 1537163953Srrs return (NULL); 1538163953Srrs} 1539163953Srrs 1540163953Srrs/* 1541163953Srrs * process an SCTP_ERROR_CAUSE_IND for a ASCONF-ACK parameter and do 1542163953Srrs * notifications based on the error response 1543163953Srrs */ 1544163953Srrsstatic void 1545270362Stuexensctp_asconf_process_error(struct sctp_tcb *stcb SCTP_UNUSED, 1546163953Srrs struct sctp_asconf_paramhdr *aph) 1547163953Srrs{ 1548163953Srrs struct sctp_error_cause *eh; 1549163953Srrs struct sctp_paramhdr *ph; 1550163953Srrs uint16_t param_type; 1551163953Srrs uint16_t error_code; 1552163953Srrs 1553163953Srrs eh = (struct sctp_error_cause *)(aph + 1); 1554163953Srrs ph = (struct sctp_paramhdr *)(eh + 1); 1555163953Srrs /* validate lengths */ 1556163953Srrs if (htons(eh->length) + sizeof(struct sctp_error_cause) > 1557163953Srrs htons(aph->ph.param_length)) { 1558163953Srrs /* invalid error cause length */ 1559169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 1560169420Srrs "asconf_process_error: cause element too long\n"); 1561163953Srrs return; 1562163953Srrs } 1563163953Srrs if (htons(ph->param_length) + sizeof(struct sctp_paramhdr) > 1564163953Srrs htons(eh->length)) { 1565163953Srrs /* invalid included TLV length */ 1566169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 1567169420Srrs "asconf_process_error: included TLV too long\n"); 1568163953Srrs return; 1569163953Srrs } 1570163953Srrs /* which error code ? */ 1571163953Srrs error_code = ntohs(eh->code); 1572163953Srrs param_type = ntohs(aph->ph.param_type); 1573163953Srrs /* FIX: this should go back up the REMOTE_ERROR ULP notify */ 1574163953Srrs switch (error_code) { 1575163953Srrs case SCTP_CAUSE_RESOURCE_SHORTAGE: 1576163953Srrs /* we allow ourselves to "try again" for this error */ 1577163953Srrs break; 1578163953Srrs default: 1579163953Srrs /* peer can't handle it... */ 1580163953Srrs switch (param_type) { 1581163953Srrs case SCTP_ADD_IP_ADDRESS: 1582163953Srrs case SCTP_DEL_IP_ADDRESS: 1583163953Srrs case SCTP_SET_PRIM_ADDR: 1584163953Srrs break; 1585163953Srrs default: 1586163953Srrs break; 1587163953Srrs } 1588163953Srrs } 1589163953Srrs} 1590163953Srrs 1591163953Srrs/* 1592171477Srrs * process an asconf queue param. 1593171477Srrs * aparam: parameter to process, will be removed from the queue. 1594171477Srrs * flag: 1=success case, 0=failure case 1595163953Srrs */ 1596163953Srrsstatic void 1597163953Srrssctp_asconf_process_param_ack(struct sctp_tcb *stcb, 1598163953Srrs struct sctp_asconf_addr *aparam, uint32_t flag) 1599163953Srrs{ 1600163953Srrs uint16_t param_type; 1601163953Srrs 1602163953Srrs /* process this param */ 1603163953Srrs param_type = aparam->ap.aph.ph.param_type; 1604163953Srrs switch (param_type) { 1605163953Srrs case SCTP_ADD_IP_ADDRESS: 1606169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 1607169420Srrs "process_param_ack: added IP address\n"); 1608228653Stuexen sctp_asconf_addr_mgmt_ack(stcb, aparam->ifa, flag); 1609163953Srrs break; 1610163953Srrs case SCTP_DEL_IP_ADDRESS: 1611169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 1612169420Srrs "process_param_ack: deleted IP address\n"); 1613163953Srrs /* nothing really to do... lists already updated */ 1614163953Srrs break; 1615163953Srrs case SCTP_SET_PRIM_ADDR: 1616179157Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 1617179157Srrs "process_param_ack: set primary IP address\n"); 1618163953Srrs /* nothing to do... peer may start using this addr */ 1619163953Srrs break; 1620163953Srrs default: 1621163953Srrs /* should NEVER happen */ 1622163953Srrs break; 1623163953Srrs } 1624163953Srrs 1625163953Srrs /* remove the param and free it */ 1626163953Srrs TAILQ_REMOVE(&stcb->asoc.asconf_queue, aparam, next); 1627172190Srrs if (aparam->ifa) 1628172190Srrs sctp_free_ifa(aparam->ifa); 1629170091Srrs SCTP_FREE(aparam, SCTP_M_ASC_ADDR); 1630163953Srrs} 1631163953Srrs 1632163953Srrs/* 1633163953Srrs * cleanup from a bad asconf ack parameter 1634163953Srrs */ 1635163953Srrsstatic void 1636270362Stuexensctp_asconf_ack_clear(struct sctp_tcb *stcb SCTP_UNUSED) 1637163953Srrs{ 1638163953Srrs /* assume peer doesn't really know how to do asconfs */ 1639163953Srrs /* XXX we could free the pending queue here */ 1640270362Stuexen 1641163953Srrs} 1642163953Srrs 1643163953Srrsvoid 1644163953Srrssctp_handle_asconf_ack(struct mbuf *m, int offset, 1645163953Srrs struct sctp_asconf_ack_chunk *cp, struct sctp_tcb *stcb, 1646172190Srrs struct sctp_nets *net, int *abort_no_unlock) 1647163953Srrs{ 1648163953Srrs struct sctp_association *asoc; 1649163953Srrs uint32_t serial_num; 1650163953Srrs uint16_t ack_length; 1651163953Srrs struct sctp_asconf_paramhdr *aph; 1652163953Srrs struct sctp_asconf_addr *aa, *aa_next; 1653163953Srrs uint32_t last_error_id = 0; /* last error correlation id */ 1654163953Srrs uint32_t id; 1655163953Srrs struct sctp_asconf_addr *ap; 1656163953Srrs 1657163953Srrs /* asconf param buffer */ 1658166675Srrs uint8_t aparam_buf[SCTP_PARAM_BUFFER_SIZE]; 1659163953Srrs 1660163953Srrs /* verify minimum length */ 1661163953Srrs if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_asconf_ack_chunk)) { 1662169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 1663169420Srrs "handle_asconf_ack: chunk too small = %xh\n", 1664169420Srrs ntohs(cp->ch.chunk_length)); 1665163953Srrs return; 1666163953Srrs } 1667163953Srrs asoc = &stcb->asoc; 1668163953Srrs serial_num = ntohl(cp->serial_number); 1669163953Srrs 1670163953Srrs /* 1671163953Srrs * NOTE: we may want to handle this differently- currently, we will 1672163953Srrs * abort when we get an ack for the expected serial number + 1 (eg. 1673163953Srrs * we didn't send it), process an ack normally if it is the expected 1674163953Srrs * serial number, and re-send the previous ack for *ALL* other 1675163953Srrs * serial numbers 1676163953Srrs */ 1677163953Srrs 1678163953Srrs /* 1679163953Srrs * if the serial number is the next expected, but I didn't send it, 1680163953Srrs * abort the asoc, since someone probably just hijacked us... 1681163953Srrs */ 1682163953Srrs if (serial_num == (asoc->asconf_seq_out + 1)) { 1683294145Stuexen struct mbuf *op_err; 1684294145Stuexen char msg[SCTP_DIAG_INFO_LEN]; 1685294145Stuexen 1686169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf_ack: got unexpected next serial number! Aborting asoc!\n"); 1687294145Stuexen snprintf(msg, sizeof(msg), "Never sent serial number %8.8x", 1688294145Stuexen serial_num); 1689294145Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); 1690294145Stuexen sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); 1691172190Srrs *abort_no_unlock = 1; 1692163953Srrs return; 1693163953Srrs } 1694179157Srrs if (serial_num != asoc->asconf_seq_out_acked + 1) { 1695163953Srrs /* got a duplicate/unexpected ASCONF-ACK */ 1696169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf_ack: got duplicate/unexpected serial number = %xh (expected = %xh)\n", 1697179157Srrs serial_num, asoc->asconf_seq_out_acked + 1); 1698163953Srrs return; 1699163953Srrs } 1700179157Srrs if (serial_num == asoc->asconf_seq_out - 1) { 1701179157Srrs /* stop our timer */ 1702179157Srrs sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net, 1703283822Stuexen SCTP_FROM_SCTP_ASCONF + SCTP_LOC_5); 1704163953Srrs } 1705163953Srrs /* process the ASCONF-ACK contents */ 1706163953Srrs ack_length = ntohs(cp->ch.chunk_length) - 1707163953Srrs sizeof(struct sctp_asconf_ack_chunk); 1708163953Srrs offset += sizeof(struct sctp_asconf_ack_chunk); 1709163953Srrs /* process through all parameters */ 1710163953Srrs while (ack_length >= sizeof(struct sctp_asconf_paramhdr)) { 1711163953Srrs unsigned int param_length, param_type; 1712163953Srrs 1713163953Srrs /* get pointer to next asconf parameter */ 1714163953Srrs aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, 1715163953Srrs sizeof(struct sctp_asconf_paramhdr), aparam_buf); 1716163953Srrs if (aph == NULL) { 1717163953Srrs /* can't get an asconf paramhdr */ 1718163953Srrs sctp_asconf_ack_clear(stcb); 1719163953Srrs return; 1720163953Srrs } 1721163953Srrs param_type = ntohs(aph->ph.param_type); 1722163953Srrs param_length = ntohs(aph->ph.param_length); 1723163953Srrs if (param_length > ack_length) { 1724163953Srrs sctp_asconf_ack_clear(stcb); 1725163953Srrs return; 1726163953Srrs } 1727163953Srrs if (param_length < sizeof(struct sctp_paramhdr)) { 1728163953Srrs sctp_asconf_ack_clear(stcb); 1729163953Srrs return; 1730163953Srrs } 1731163953Srrs /* get the complete parameter... */ 1732163953Srrs if (param_length > sizeof(aparam_buf)) { 1733169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 1734169420Srrs "param length (%u) larger than buffer size!\n", param_length); 1735163953Srrs sctp_asconf_ack_clear(stcb); 1736163953Srrs return; 1737163953Srrs } 1738163953Srrs aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, param_length, aparam_buf); 1739163953Srrs if (aph == NULL) { 1740163953Srrs sctp_asconf_ack_clear(stcb); 1741163953Srrs return; 1742163953Srrs } 1743163953Srrs /* correlation_id is transparent to peer, no ntohl needed */ 1744163953Srrs id = aph->correlation_id; 1745163953Srrs 1746163953Srrs switch (param_type) { 1747163953Srrs case SCTP_ERROR_CAUSE_IND: 1748163953Srrs last_error_id = id; 1749163953Srrs /* find the corresponding asconf param in our queue */ 1750163953Srrs ap = sctp_asconf_find_param(stcb, id); 1751163953Srrs if (ap == NULL) { 1752163953Srrs /* hmm... can't find this in our queue! */ 1753163953Srrs break; 1754163953Srrs } 1755163953Srrs /* process the parameter, failed flag */ 1756163953Srrs sctp_asconf_process_param_ack(stcb, ap, 0); 1757163953Srrs /* process the error response */ 1758163953Srrs sctp_asconf_process_error(stcb, aph); 1759163953Srrs break; 1760163953Srrs case SCTP_SUCCESS_REPORT: 1761163953Srrs /* find the corresponding asconf param in our queue */ 1762163953Srrs ap = sctp_asconf_find_param(stcb, id); 1763163953Srrs if (ap == NULL) { 1764163953Srrs /* hmm... can't find this in our queue! */ 1765163953Srrs break; 1766163953Srrs } 1767163953Srrs /* process the parameter, success flag */ 1768163953Srrs sctp_asconf_process_param_ack(stcb, ap, 1); 1769163953Srrs break; 1770163953Srrs default: 1771163953Srrs break; 1772163953Srrs } /* switch */ 1773163953Srrs 1774163953Srrs /* update remaining ASCONF-ACK message length to process */ 1775163953Srrs ack_length -= SCTP_SIZE32(param_length); 1776163953Srrs if (ack_length <= 0) { 1777163953Srrs /* no more data in the mbuf chain */ 1778163953Srrs break; 1779163953Srrs } 1780163953Srrs offset += SCTP_SIZE32(param_length); 1781163953Srrs } /* while */ 1782163953Srrs 1783163953Srrs /* 1784163953Srrs * if there are any "sent" params still on the queue, these are 1785163953Srrs * implicitly "success", or "failed" (if we got an error back) ... 1786163953Srrs * so process these appropriately 1787163953Srrs * 1788163953Srrs * we assume that the correlation_id's are monotonically increasing 1789163953Srrs * beginning from 1 and that we don't have *that* many outstanding 1790163953Srrs * at any given time 1791163953Srrs */ 1792163953Srrs if (last_error_id == 0) 1793163953Srrs last_error_id--;/* set to "max" value */ 1794216822Stuexen TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) { 1795163953Srrs if (aa->sent == 1) { 1796163953Srrs /* 1797163953Srrs * implicitly successful or failed if correlation_id 1798163953Srrs * < last_error_id, then success else, failure 1799163953Srrs */ 1800163953Srrs if (aa->ap.aph.correlation_id < last_error_id) 1801171477Srrs sctp_asconf_process_param_ack(stcb, aa, 1); 1802163953Srrs else 1803171477Srrs sctp_asconf_process_param_ack(stcb, aa, 0); 1804163953Srrs } else { 1805163953Srrs /* 1806163953Srrs * since we always process in order (FIFO queue) if 1807163953Srrs * we reach one that hasn't been sent, the rest 1808163953Srrs * should not have been sent either. so, we're 1809163953Srrs * done... 1810163953Srrs */ 1811163953Srrs break; 1812163953Srrs } 1813163953Srrs } 1814163953Srrs 1815163953Srrs /* update the next sequence number to use */ 1816179157Srrs asoc->asconf_seq_out_acked++; 1817163953Srrs /* remove the old ASCONF on our outbound queue */ 1818163953Srrs sctp_toss_old_asconf(stcb); 1819163953Srrs if (!TAILQ_EMPTY(&stcb->asoc.asconf_queue)) { 1820171572Srrs#ifdef SCTP_TIMER_BASED_ASCONF 1821163953Srrs /* we have more params, so restart our timer */ 1822163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, 1823163953Srrs stcb, net); 1824171572Srrs#else 1825171572Srrs /* we have more params, so send out more */ 1826172190Srrs sctp_send_asconf(stcb, net, SCTP_ADDR_NOT_LOCKED); 1827171572Srrs#endif 1828163953Srrs } 1829163953Srrs} 1830163953Srrs 1831178251Srrs#ifdef INET6 1832163953Srrsstatic uint32_t 1833163953Srrssctp_is_scopeid_in_nets(struct sctp_tcb *stcb, struct sockaddr *sa) 1834163953Srrs{ 1835163953Srrs struct sockaddr_in6 *sin6, *net6; 1836163953Srrs struct sctp_nets *net; 1837163953Srrs 1838163953Srrs if (sa->sa_family != AF_INET6) { 1839163953Srrs /* wrong family */ 1840163953Srrs return (0); 1841163953Srrs } 1842163953Srrs sin6 = (struct sockaddr_in6 *)sa; 1843163953Srrs if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) == 0) { 1844163953Srrs /* not link local address */ 1845163953Srrs return (0); 1846163953Srrs } 1847163953Srrs /* hunt through our destination nets list for this scope_id */ 1848163953Srrs TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 1849163953Srrs if (((struct sockaddr *)(&net->ro._l_addr))->sa_family != 1850163953Srrs AF_INET6) 1851163953Srrs continue; 1852163953Srrs net6 = (struct sockaddr_in6 *)&net->ro._l_addr; 1853163953Srrs if (IN6_IS_ADDR_LINKLOCAL(&net6->sin6_addr) == 0) 1854163953Srrs continue; 1855163953Srrs if (sctp_is_same_scope(sin6, net6)) { 1856163953Srrs /* found one */ 1857163953Srrs return (1); 1858163953Srrs } 1859163953Srrs } 1860163953Srrs /* didn't find one */ 1861163953Srrs return (0); 1862163953Srrs} 1863163953Srrs 1864178251Srrs#endif 1865178251Srrs 1866163953Srrs/* 1867163953Srrs * address management functions 1868163953Srrs */ 1869163953Srrsstatic void 1870163953Srrssctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 1871172190Srrs struct sctp_ifa *ifa, uint16_t type, int addr_locked) 1872163953Srrs{ 1873163953Srrs int status; 1874163953Srrs 1875224641Stuexen if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0 || 1876163953Srrs sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_ASCONF)) { 1877163953Srrs /* subset bound, no ASCONF allowed case, so ignore */ 1878163953Srrs return; 1879163953Srrs } 1880163953Srrs /* 1881163953Srrs * note: we know this is not the subset bound, no ASCONF case eg. 1882163953Srrs * this is boundall or subset bound w/ASCONF allowed 1883163953Srrs */ 1884163953Srrs 1885267769Stuexen /* first, make sure that the address is IPv4 or IPv6 and not jailed */ 1886221249Stuexen switch (ifa->address.sa.sa_family) { 1887221249Stuexen#ifdef INET6 1888221249Stuexen case AF_INET6: 1889267769Stuexen if (prison_check_ip6(inp->ip_inp.inp.inp_cred, 1890267769Stuexen &ifa->address.sin6.sin6_addr) != 0) { 1891267769Stuexen return; 1892267769Stuexen } 1893221249Stuexen break; 1894221249Stuexen#endif 1895221249Stuexen#ifdef INET 1896221249Stuexen case AF_INET: 1897267769Stuexen if (prison_check_ip4(inp->ip_inp.inp.inp_cred, 1898267769Stuexen &ifa->address.sin.sin_addr) != 0) { 1899267769Stuexen return; 1900267769Stuexen } 1901221249Stuexen break; 1902221249Stuexen#endif 1903221249Stuexen default: 1904163953Srrs return; 1905163953Srrs } 1906221249Stuexen#ifdef INET6 1907163953Srrs /* make sure we're "allowed" to add this type of addr */ 1908167598Srrs if (ifa->address.sa.sa_family == AF_INET6) { 1909163953Srrs /* invalid if we're not a v6 endpoint */ 1910163953Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) 1911163953Srrs return; 1912163953Srrs /* is the v6 addr really valid ? */ 1913167598Srrs if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) { 1914163953Srrs return; 1915163953Srrs } 1916163953Srrs } 1917221249Stuexen#endif 1918163953Srrs /* put this address on the "pending/do not use yet" list */ 1919171572Srrs sctp_add_local_addr_restricted(stcb, ifa); 1920163953Srrs /* 1921163953Srrs * check address scope if address is out of scope, don't queue 1922163953Srrs * anything... note: this would leave the address on both inp and 1923163953Srrs * asoc lists 1924163953Srrs */ 1925178251Srrs switch (ifa->address.sa.sa_family) { 1926178251Srrs#ifdef INET6 1927178251Srrs case AF_INET6: 1928178251Srrs { 1929178251Srrs struct sockaddr_in6 *sin6; 1930163953Srrs 1931271746Stuexen sin6 = &ifa->address.sin6; 1932178251Srrs if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 1933178251Srrs /* we skip unspecifed addresses */ 1934163953Srrs return; 1935163953Srrs } 1936178251Srrs if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 1937246595Stuexen if (stcb->asoc.scope.local_scope == 0) { 1938178251Srrs return; 1939178251Srrs } 1940178251Srrs /* is it the right link local scope? */ 1941178251Srrs if (sctp_is_scopeid_in_nets(stcb, &ifa->address.sa) == 0) { 1942178251Srrs return; 1943178251Srrs } 1944178251Srrs } 1945246595Stuexen if (stcb->asoc.scope.site_scope == 0 && 1946178251Srrs IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) { 1947163953Srrs return; 1948163953Srrs } 1949178251Srrs break; 1950163953Srrs } 1951178251Srrs#endif 1952221249Stuexen#ifdef INET 1953178251Srrs case AF_INET: 1954178251Srrs { 1955178251Srrs struct sockaddr_in *sin; 1956178251Srrs struct in6pcb *inp6; 1957163953Srrs 1958178251Srrs inp6 = (struct in6pcb *)&inp->ip_inp.inp; 1959178251Srrs /* invalid if we are a v6 only endpoint */ 1960178251Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && 1961178251Srrs SCTP_IPV6_V6ONLY(inp6)) 1962178251Srrs return; 1963163953Srrs 1964271746Stuexen sin = &ifa->address.sin; 1965178251Srrs if (sin->sin_addr.s_addr == 0) { 1966178251Srrs /* we skip unspecifed addresses */ 1967178251Srrs return; 1968178251Srrs } 1969246595Stuexen if (stcb->asoc.scope.ipv4_local_scope == 0 && 1970178251Srrs IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) { 1971178251Srrs return; 1972178251Srrs } 1973178251Srrs break; 1974163953Srrs } 1975221249Stuexen#endif 1976178251Srrs default: 1977163953Srrs /* else, not AF_INET or AF_INET6, so skip */ 1978163953Srrs return; 1979163953Srrs } 1980163953Srrs 1981163953Srrs /* queue an asconf for this address add/delete */ 1982163953Srrs if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF)) { 1983163953Srrs /* does the peer do asconf? */ 1984270362Stuexen if (stcb->asoc.asconf_supported) { 1985163953Srrs /* queue an asconf for this addr */ 1986163953Srrs status = sctp_asconf_queue_add(stcb, ifa, type); 1987171572Srrs 1988163953Srrs /* 1989171572Srrs * if queued ok, and in the open state, send out the 1990171572Srrs * ASCONF. If in the non-open state, these will be 1991171572Srrs * sent when the state goes open. 1992163953Srrs */ 1993163953Srrs if (status == 0 && 1994283826Stuexen ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) || 1995283826Stuexen (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED))) { 1996171572Srrs#ifdef SCTP_TIMER_BASED_ASCONF 1997163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, inp, 1998163953Srrs stcb, stcb->asoc.primary_destination); 1999171572Srrs#else 2000224641Stuexen sctp_send_asconf(stcb, NULL, addr_locked); 2001171572Srrs#endif 2002163953Srrs } 2003163953Srrs } 2004163953Srrs } 2005163953Srrs} 2006163953Srrs 2007167598Srrs 2008167598Srrsint 2009228653Stuexensctp_asconf_iterator_ep(struct sctp_inpcb *inp, void *ptr, uint32_t val SCTP_UNUSED) 2010163953Srrs{ 2011167598Srrs struct sctp_asconf_iterator *asc; 2012167598Srrs struct sctp_ifa *ifa; 2013167598Srrs struct sctp_laddr *l; 2014167598Srrs int cnt_invalid = 0; 2015163953Srrs 2016167598Srrs asc = (struct sctp_asconf_iterator *)ptr; 2017167598Srrs LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) { 2018167598Srrs ifa = l->ifa; 2019221249Stuexen switch (ifa->address.sa.sa_family) { 2020221249Stuexen#ifdef INET6 2021221249Stuexen case AF_INET6: 2022167598Srrs /* invalid if we're not a v6 endpoint */ 2023167598Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) { 2024167598Srrs cnt_invalid++; 2025167598Srrs if (asc->cnt == cnt_invalid) 2026167598Srrs return (1); 2027167598Srrs } 2028221249Stuexen break; 2029221249Stuexen#endif 2030221249Stuexen#ifdef INET 2031221249Stuexen case AF_INET: 2032221249Stuexen { 2033221249Stuexen /* invalid if we are a v6 only endpoint */ 2034221249Stuexen struct in6pcb *inp6; 2035163953Srrs 2036221249Stuexen inp6 = (struct in6pcb *)&inp->ip_inp.inp; 2037221249Stuexen if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && 2038221249Stuexen SCTP_IPV6_V6ONLY(inp6)) { 2039221249Stuexen cnt_invalid++; 2040221249Stuexen if (asc->cnt == cnt_invalid) 2041221249Stuexen return (1); 2042221249Stuexen } 2043221249Stuexen break; 2044163953Srrs } 2045221249Stuexen#endif 2046221249Stuexen default: 2047167598Srrs /* invalid address family */ 2048167598Srrs cnt_invalid++; 2049167598Srrs if (asc->cnt == cnt_invalid) 2050167598Srrs return (1); 2051163953Srrs } 2052163953Srrs } 2053167598Srrs return (0); 2054163953Srrs} 2055163953Srrs 2056171572Srrsstatic int 2057228653Stuexensctp_asconf_iterator_ep_end(struct sctp_inpcb *inp, void *ptr, uint32_t val SCTP_UNUSED) 2058163953Srrs{ 2059167598Srrs struct sctp_ifa *ifa; 2060167598Srrs struct sctp_asconf_iterator *asc; 2061167598Srrs struct sctp_laddr *laddr, *nladdr, *l; 2062163953Srrs 2063167598Srrs /* Only for specific case not bound all */ 2064167598Srrs asc = (struct sctp_asconf_iterator *)ptr; 2065167598Srrs LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) { 2066167598Srrs ifa = l->ifa; 2067167598Srrs if (l->action == SCTP_ADD_IP_ADDRESS) { 2068169655Srrs LIST_FOREACH(laddr, &inp->sctp_addr_list, 2069169655Srrs sctp_nxt_addr) { 2070167598Srrs if (laddr->ifa == ifa) { 2071167598Srrs laddr->action = 0; 2072167598Srrs break; 2073167598Srrs } 2074167598Srrs } 2075167598Srrs } else if (l->action == SCTP_DEL_IP_ADDRESS) { 2076216822Stuexen LIST_FOREACH_SAFE(laddr, &inp->sctp_addr_list, sctp_nxt_addr, nladdr) { 2077167598Srrs /* remove only after all guys are done */ 2078167598Srrs if (laddr->ifa == ifa) { 2079167598Srrs sctp_del_local_addr_ep(inp, ifa); 2080167598Srrs } 2081167598Srrs } 2082167598Srrs } 2083163953Srrs } 2084167598Srrs return (0); 2085163953Srrs} 2086163953Srrs 2087167598Srrsvoid 2088171572Srrssctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 2089228653Stuexen void *ptr, uint32_t val SCTP_UNUSED) 2090163953Srrs{ 2091167598Srrs struct sctp_asconf_iterator *asc; 2092167598Srrs struct sctp_ifa *ifa; 2093167598Srrs struct sctp_laddr *l; 2094167598Srrs int cnt_invalid = 0; 2095167598Srrs int type, status; 2096171572Srrs int num_queued = 0; 2097163953Srrs 2098167598Srrs asc = (struct sctp_asconf_iterator *)ptr; 2099167598Srrs LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) { 2100167598Srrs ifa = l->ifa; 2101167598Srrs type = l->action; 2102170751Srrs 2103170751Srrs /* address's vrf_id must be the vrf_id of the assoc */ 2104170751Srrs if (ifa->vrf_id != stcb->asoc.vrf_id) { 2105170751Srrs continue; 2106170751Srrs } 2107167598Srrs /* Same checks again for assoc */ 2108178251Srrs switch (ifa->address.sa.sa_family) { 2109178251Srrs#ifdef INET6 2110178251Srrs case AF_INET6: 2111178251Srrs { 2112178251Srrs /* invalid if we're not a v6 endpoint */ 2113178251Srrs struct sockaddr_in6 *sin6; 2114163953Srrs 2115178251Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) { 2116178251Srrs cnt_invalid++; 2117178251Srrs if (asc->cnt == cnt_invalid) 2118178251Srrs return; 2119178251Srrs else 2120178251Srrs continue; 2121167598Srrs } 2122271746Stuexen sin6 = &ifa->address.sin6; 2123178251Srrs if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 2124178251Srrs /* we skip unspecifed addresses */ 2125167598Srrs continue; 2126167598Srrs } 2127267769Stuexen if (prison_check_ip6(inp->ip_inp.inp.inp_cred, 2128267769Stuexen &sin6->sin6_addr) != 0) { 2129267769Stuexen continue; 2130267769Stuexen } 2131178251Srrs if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 2132246595Stuexen if (stcb->asoc.scope.local_scope == 0) { 2133178251Srrs continue; 2134178251Srrs } 2135178251Srrs /* is it the right link local scope? */ 2136178251Srrs if (sctp_is_scopeid_in_nets(stcb, &ifa->address.sa) == 0) { 2137178251Srrs continue; 2138178251Srrs } 2139178251Srrs } 2140178251Srrs break; 2141167598Srrs } 2142178251Srrs#endif 2143221249Stuexen#ifdef INET 2144178251Srrs case AF_INET: 2145178251Srrs { 2146178251Srrs /* invalid if we are a v6 only endpoint */ 2147178251Srrs struct in6pcb *inp6; 2148178251Srrs struct sockaddr_in *sin; 2149163953Srrs 2150178251Srrs inp6 = (struct in6pcb *)&inp->ip_inp.inp; 2151178251Srrs /* invalid if we are a v6 only endpoint */ 2152178251Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && 2153178251Srrs SCTP_IPV6_V6ONLY(inp6)) 2154178251Srrs continue; 2155167598Srrs 2156271746Stuexen sin = &ifa->address.sin; 2157178251Srrs if (sin->sin_addr.s_addr == 0) { 2158178251Srrs /* we skip unspecifed addresses */ 2159167598Srrs continue; 2160178251Srrs } 2161267769Stuexen if (prison_check_ip4(inp->ip_inp.inp.inp_cred, 2162267769Stuexen &sin->sin_addr) != 0) { 2163267769Stuexen continue; 2164267769Stuexen } 2165246595Stuexen if (stcb->asoc.scope.ipv4_local_scope == 0 && 2166178251Srrs IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) { 2167201758Smbr continue; 2168178251Srrs } 2169178251Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && 2170178251Srrs SCTP_IPV6_V6ONLY(inp6)) { 2171178251Srrs cnt_invalid++; 2172178251Srrs if (asc->cnt == cnt_invalid) 2173178251Srrs return; 2174178251Srrs else 2175178251Srrs continue; 2176178251Srrs } 2177178251Srrs break; 2178167598Srrs } 2179221249Stuexen#endif 2180178251Srrs default: 2181167598Srrs /* invalid address family */ 2182167598Srrs cnt_invalid++; 2183167598Srrs if (asc->cnt == cnt_invalid) 2184163953Srrs return; 2185167598Srrs else 2186167598Srrs continue; 2187178251Srrs break; 2188163953Srrs } 2189163953Srrs 2190167598Srrs if (type == SCTP_ADD_IP_ADDRESS) { 2191171572Srrs /* prevent this address from being used as a source */ 2192171572Srrs sctp_add_local_addr_restricted(stcb, ifa); 2193167598Srrs } else if (type == SCTP_DEL_IP_ADDRESS) { 2194163953Srrs struct sctp_nets *net; 2195163953Srrs 2196163953Srrs TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 2197169352Srrs sctp_rtentry_t *rt; 2198163953Srrs 2199163953Srrs /* delete this address if cached */ 2200172091Srrs if (net->ro._s_addr == ifa) { 2201167598Srrs sctp_free_ifa(net->ro._s_addr); 2202167598Srrs net->ro._s_addr = NULL; 2203167598Srrs net->src_addr_selected = 0; 2204167598Srrs rt = net->ro.ro_rt; 2205167598Srrs if (rt) { 2206167598Srrs RTFREE(rt); 2207167598Srrs net->ro.ro_rt = NULL; 2208167598Srrs } 2209167598Srrs /* 2210167598Srrs * Now we deleted our src address, 2211167598Srrs * should we not also now reset the 2212167598Srrs * cwnd/rto to start as if its a new 2213167598Srrs * address? 2214167598Srrs */ 2215171440Srrs stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net); 2216170428Srrs net->RTO = 0; 2217167598Srrs 2218163953Srrs } 2219167598Srrs } 2220167598Srrs } else if (type == SCTP_SET_PRIM_ADDR) { 2221167598Srrs if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) { 2222171572Srrs /* must validate the ifa is in the ep */ 2223167598Srrs if (sctp_is_addr_in_ep(stcb->sctp_ep, ifa) == 0) { 2224167598Srrs continue; 2225163953Srrs } 2226167598Srrs } else { 2227167598Srrs /* Need to check scopes for this guy */ 2228246595Stuexen if (sctp_is_address_in_scope(ifa, &stcb->asoc.scope, 0) == 0) { 2229167598Srrs continue; 2230167598Srrs } 2231163953Srrs } 2232163953Srrs } 2233167598Srrs /* queue an asconf for this address add/delete */ 2234171572Srrs if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF) && 2235270362Stuexen stcb->asoc.asconf_supported == 1) { 2236171572Srrs /* queue an asconf for this addr */ 2237171572Srrs status = sctp_asconf_queue_add(stcb, ifa, type); 2238171572Srrs /* 2239171572Srrs * if queued ok, and in the open state, update the 2240171572Srrs * count of queued params. If in the non-open 2241171572Srrs * state, these get sent when the assoc goes open. 2242171572Srrs */ 2243283826Stuexen if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) || 2244283826Stuexen (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { 2245171572Srrs if (status >= 0) { 2246171572Srrs num_queued++; 2247167598Srrs } 2248167598Srrs } 2249167598Srrs } 2250163953Srrs } 2251171572Srrs /* 2252171572Srrs * If we have queued params in the open state, send out an ASCONF. 2253171572Srrs */ 2254171572Srrs if (num_queued > 0) { 2255224641Stuexen sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED); 2256171572Srrs } 2257163953Srrs} 2258163953Srrs 2259171572Srrsvoid 2260228653Stuexensctp_asconf_iterator_end(void *ptr, uint32_t val SCTP_UNUSED) 2261167598Srrs{ 2262167598Srrs struct sctp_asconf_iterator *asc; 2263167598Srrs struct sctp_ifa *ifa; 2264216822Stuexen struct sctp_laddr *l, *nl; 2265167598Srrs 2266167598Srrs asc = (struct sctp_asconf_iterator *)ptr; 2267216822Stuexen LIST_FOREACH_SAFE(l, &asc->list_of_work, sctp_nxt_addr, nl) { 2268167598Srrs ifa = l->ifa; 2269167598Srrs if (l->action == SCTP_ADD_IP_ADDRESS) { 2270167598Srrs /* Clear the defer use flag */ 2271167598Srrs ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE; 2272167598Srrs } 2273167598Srrs sctp_free_ifa(ifa); 2274179783Srrs SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_laddr), l); 2275167598Srrs SCTP_DECR_LADDR_COUNT(); 2276167598Srrs } 2277170091Srrs SCTP_FREE(asc, SCTP_M_ASC_IT); 2278167598Srrs} 2279167598Srrs 2280163953Srrs/* 2281171572Srrs * sa is the sockaddr to ask the peer to set primary to. 2282171572Srrs * returns: 0 = completed, -1 = error 2283163953Srrs */ 2284171943Srrsint32_t 2285163953Srrssctp_set_primary_ip_address_sa(struct sctp_tcb *stcb, struct sockaddr *sa) 2286163953Srrs{ 2287172190Srrs uint32_t vrf_id; 2288172190Srrs struct sctp_ifa *ifa; 2289163953Srrs 2290172190Srrs /* find the ifa for the desired set primary */ 2291172218Srrs vrf_id = stcb->asoc.vrf_id; 2292172190Srrs ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED); 2293172190Srrs if (ifa == NULL) { 2294172190Srrs /* Invalid address */ 2295172190Srrs return (-1); 2296172190Srrs } 2297163953Srrs /* queue an ASCONF:SET_PRIM_ADDR to be sent */ 2298172190Srrs if (!sctp_asconf_queue_add(stcb, ifa, SCTP_SET_PRIM_ADDR)) { 2299163953Srrs /* set primary queuing succeeded */ 2300171572Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 2301171572Srrs "set_primary_ip_address_sa: queued on tcb=%p, ", 2302240148Stuexen (void *)stcb); 2303171572Srrs SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); 2304283826Stuexen if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) || 2305283826Stuexen (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { 2306171572Srrs#ifdef SCTP_TIMER_BASED_ASCONF 2307163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, 2308163953Srrs stcb->sctp_ep, stcb, 2309163953Srrs stcb->asoc.primary_destination); 2310171572Srrs#else 2311224641Stuexen sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED); 2312171572Srrs#endif 2313163953Srrs } 2314163953Srrs } else { 2315169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "set_primary_ip_address_sa: failed to add to queue on tcb=%p, ", 2316240148Stuexen (void *)stcb); 2317169420Srrs SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); 2318163953Srrs return (-1); 2319163953Srrs } 2320163953Srrs return (0); 2321163953Srrs} 2322163953Srrs 2323163953Srrsvoid 2324167598Srrssctp_set_primary_ip_address(struct sctp_ifa *ifa) 2325163953Srrs{ 2326163953Srrs struct sctp_inpcb *inp; 2327163953Srrs 2328163953Srrs /* go through all our PCB's */ 2329179783Srrs LIST_FOREACH(inp, &SCTP_BASE_INFO(listhead), sctp_list) { 2330163953Srrs struct sctp_tcb *stcb; 2331163953Srrs 2332163953Srrs /* process for all associations for this endpoint */ 2333163953Srrs LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { 2334163953Srrs /* queue an ASCONF:SET_PRIM_ADDR to be sent */ 2335163953Srrs if (!sctp_asconf_queue_add(stcb, ifa, 2336163953Srrs SCTP_SET_PRIM_ADDR)) { 2337163953Srrs /* set primary queuing succeeded */ 2338172090Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "set_primary_ip_address: queued on stcb=%p, ", 2339240148Stuexen (void *)stcb); 2340171572Srrs SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &ifa->address.sa); 2341283826Stuexen if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) || 2342283826Stuexen (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { 2343171572Srrs#ifdef SCTP_TIMER_BASED_ASCONF 2344163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, 2345163953Srrs stcb->sctp_ep, stcb, 2346163953Srrs stcb->asoc.primary_destination); 2347171572Srrs#else 2348224641Stuexen sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED); 2349171572Srrs#endif 2350163953Srrs } 2351163953Srrs } 2352163953Srrs } /* for each stcb */ 2353163953Srrs } /* for each inp */ 2354163953Srrs} 2355163953Srrs 2356179157Srrsint 2357179157Srrssctp_is_addr_pending(struct sctp_tcb *stcb, struct sctp_ifa *sctp_ifa) 2358179157Srrs{ 2359179157Srrs struct sctp_tmit_chunk *chk, *nchk; 2360179157Srrs unsigned int offset, asconf_limit; 2361179157Srrs struct sctp_asconf_chunk *acp; 2362179157Srrs struct sctp_asconf_paramhdr *aph; 2363179157Srrs uint8_t aparam_buf[SCTP_PARAM_BUFFER_SIZE]; 2364221249Stuexen struct sctp_paramhdr *ph; 2365179157Srrs int add_cnt, del_cnt; 2366179157Srrs uint16_t last_param_type; 2367179157Srrs 2368179157Srrs add_cnt = del_cnt = 0; 2369179157Srrs last_param_type = 0; 2370216822Stuexen TAILQ_FOREACH_SAFE(chk, &stcb->asoc.asconf_send_queue, sctp_next, nchk) { 2371179157Srrs if (chk->data == NULL) { 2372179157Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: No mbuf data?\n"); 2373179157Srrs continue; 2374179157Srrs } 2375179157Srrs offset = 0; 2376179157Srrs acp = mtod(chk->data, struct sctp_asconf_chunk *); 2377179157Srrs offset += sizeof(struct sctp_asconf_chunk); 2378179157Srrs asconf_limit = ntohs(acp->ch.chunk_length); 2379221249Stuexen ph = (struct sctp_paramhdr *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_paramhdr), aparam_buf); 2380221249Stuexen if (ph == NULL) { 2381179157Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: couldn't get lookup addr!\n"); 2382179157Srrs continue; 2383179157Srrs } 2384221249Stuexen offset += ntohs(ph->param_length); 2385179157Srrs 2386179157Srrs aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_asconf_paramhdr), aparam_buf); 2387179157Srrs if (aph == NULL) { 2388179157Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: Empty ASCONF will be sent?\n"); 2389179157Srrs continue; 2390179157Srrs } 2391179157Srrs while (aph != NULL) { 2392179157Srrs unsigned int param_length, param_type; 2393179157Srrs 2394179157Srrs param_type = ntohs(aph->ph.param_type); 2395179157Srrs param_length = ntohs(aph->ph.param_length); 2396179157Srrs if (offset + param_length > asconf_limit) { 2397179157Srrs /* parameter goes beyond end of chunk! */ 2398179157Srrs break; 2399179157Srrs } 2400179157Srrs if (param_length > sizeof(aparam_buf)) { 2401179157Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: param length (%u) larger than buffer size!\n", param_length); 2402179157Srrs break; 2403179157Srrs } 2404179157Srrs if (param_length <= sizeof(struct sctp_paramhdr)) { 2405179157Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: param length(%u) too short\n", param_length); 2406179157Srrs break; 2407179157Srrs } 2408179157Srrs aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(chk->data, offset, param_length, aparam_buf); 2409179157Srrs if (aph == NULL) { 2410179157Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: couldn't get entire param\n"); 2411179157Srrs break; 2412179157Srrs } 2413221249Stuexen ph = (struct sctp_paramhdr *)(aph + 1); 2414221249Stuexen if (sctp_addr_match(ph, &sctp_ifa->address.sa) != 0) { 2415179157Srrs switch (param_type) { 2416179157Srrs case SCTP_ADD_IP_ADDRESS: 2417179157Srrs add_cnt++; 2418179157Srrs break; 2419179157Srrs case SCTP_DEL_IP_ADDRESS: 2420179157Srrs del_cnt++; 2421179157Srrs break; 2422179157Srrs default: 2423179157Srrs break; 2424179157Srrs } 2425179157Srrs last_param_type = param_type; 2426179157Srrs } 2427179157Srrs offset += SCTP_SIZE32(param_length); 2428179157Srrs if (offset >= asconf_limit) { 2429179157Srrs /* no more data in the mbuf chain */ 2430179157Srrs break; 2431179157Srrs } 2432179157Srrs /* get pointer to next asconf param */ 2433179157Srrs aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_asconf_paramhdr), aparam_buf); 2434179157Srrs } 2435179157Srrs } 2436179157Srrs 2437179157Srrs /* 2438179157Srrs * we want to find the sequences which consist of ADD -> DEL -> ADD 2439179157Srrs * or DEL -> ADD 2440179157Srrs */ 2441179157Srrs if (add_cnt > del_cnt || 2442179157Srrs (add_cnt == del_cnt && last_param_type == SCTP_ADD_IP_ADDRESS)) { 2443228907Stuexen return (1); 2444179157Srrs } 2445228907Stuexen return (0); 2446179157Srrs} 2447179157Srrs 2448163953Srrsstatic struct sockaddr * 2449172190Srrssctp_find_valid_localaddr(struct sctp_tcb *stcb, int addr_locked) 2450163953Srrs{ 2451167598Srrs struct sctp_vrf *vrf = NULL; 2452167598Srrs struct sctp_ifn *sctp_ifn; 2453167598Srrs struct sctp_ifa *sctp_ifa; 2454163953Srrs 2455172190Srrs if (addr_locked == SCTP_ADDR_NOT_LOCKED) 2456172218Srrs SCTP_IPI_ADDR_RLOCK(); 2457167598Srrs vrf = sctp_find_vrf(stcb->asoc.vrf_id); 2458169420Srrs if (vrf == NULL) { 2459172190Srrs if (addr_locked == SCTP_ADDR_NOT_LOCKED) 2460172218Srrs SCTP_IPI_ADDR_RUNLOCK(); 2461169420Srrs return (NULL); 2462169420Srrs } 2463167598Srrs LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) { 2464246595Stuexen if (stcb->asoc.scope.loopback_scope == 0 && 2465167598Srrs SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) { 2466163953Srrs /* Skip if loopback_scope not set */ 2467163953Srrs continue; 2468163953Srrs } 2469167598Srrs LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) { 2470221249Stuexen switch (sctp_ifa->address.sa.sa_family) { 2471221249Stuexen#ifdef INET 2472221249Stuexen case AF_INET: 2473246595Stuexen if (stcb->asoc.scope.ipv4_addr_legal) { 2474221249Stuexen struct sockaddr_in *sin; 2475163953Srrs 2476271746Stuexen sin = &sctp_ifa->address.sin; 2477221249Stuexen if (sin->sin_addr.s_addr == 0) { 2478221249Stuexen /* skip unspecifed addresses */ 2479221249Stuexen continue; 2480221249Stuexen } 2481267769Stuexen if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred, 2482267769Stuexen &sin->sin_addr) != 0) { 2483267769Stuexen continue; 2484267769Stuexen } 2485246595Stuexen if (stcb->asoc.scope.ipv4_local_scope == 0 && 2486221249Stuexen IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) 2487221249Stuexen continue; 2488221249Stuexen 2489221249Stuexen if (sctp_is_addr_restricted(stcb, sctp_ifa) && 2490221249Stuexen (!sctp_is_addr_pending(stcb, sctp_ifa))) 2491221249Stuexen continue; 2492221249Stuexen /* 2493221249Stuexen * found a valid local v4 address to 2494221249Stuexen * use 2495221249Stuexen */ 2496221249Stuexen if (addr_locked == SCTP_ADDR_NOT_LOCKED) 2497221249Stuexen SCTP_IPI_ADDR_RUNLOCK(); 2498221249Stuexen return (&sctp_ifa->address.sa); 2499163953Srrs } 2500221249Stuexen break; 2501221249Stuexen#endif 2502221249Stuexen#ifdef INET6 2503221249Stuexen case AF_INET6: 2504246595Stuexen if (stcb->asoc.scope.ipv6_addr_legal) { 2505221249Stuexen struct sockaddr_in6 *sin6; 2506163953Srrs 2507221249Stuexen if (sctp_ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) { 2508221249Stuexen continue; 2509221249Stuexen } 2510271746Stuexen sin6 = &sctp_ifa->address.sin6; 2511221249Stuexen if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 2512221249Stuexen /* 2513221249Stuexen * we skip unspecifed 2514221249Stuexen * addresses 2515221249Stuexen */ 2516221249Stuexen continue; 2517221249Stuexen } 2518267769Stuexen if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred, 2519267769Stuexen &sin6->sin6_addr) != 0) { 2520267769Stuexen continue; 2521267769Stuexen } 2522246595Stuexen if (stcb->asoc.scope.local_scope == 0 && 2523221249Stuexen IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 2524221249Stuexen continue; 2525246595Stuexen if (stcb->asoc.scope.site_scope == 0 && 2526221249Stuexen IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) 2527221249Stuexen continue; 2528163953Srrs 2529221249Stuexen if (sctp_is_addr_restricted(stcb, sctp_ifa) && 2530221249Stuexen (!sctp_is_addr_pending(stcb, sctp_ifa))) 2531221249Stuexen continue; 2532221249Stuexen /* 2533221249Stuexen * found a valid local v6 address to 2534221249Stuexen * use 2535221249Stuexen */ 2536221249Stuexen if (addr_locked == SCTP_ADDR_NOT_LOCKED) 2537221249Stuexen SCTP_IPI_ADDR_RUNLOCK(); 2538221249Stuexen return (&sctp_ifa->address.sa); 2539167598Srrs } 2540221249Stuexen break; 2541221249Stuexen#endif 2542221249Stuexen default: 2543221249Stuexen break; 2544163953Srrs } 2545163953Srrs } 2546163953Srrs } 2547163953Srrs /* no valid addresses found */ 2548172190Srrs if (addr_locked == SCTP_ADDR_NOT_LOCKED) 2549172218Srrs SCTP_IPI_ADDR_RUNLOCK(); 2550163953Srrs return (NULL); 2551163953Srrs} 2552163953Srrs 2553163953Srrsstatic struct sockaddr * 2554163953Srrssctp_find_valid_localaddr_ep(struct sctp_tcb *stcb) 2555163953Srrs{ 2556163953Srrs struct sctp_laddr *laddr; 2557163953Srrs 2558163953Srrs LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) { 2559163953Srrs if (laddr->ifa == NULL) { 2560163953Srrs continue; 2561163953Srrs } 2562163953Srrs /* is the address restricted ? */ 2563179157Srrs if (sctp_is_addr_restricted(stcb, laddr->ifa) && 2564179157Srrs (!sctp_is_addr_pending(stcb, laddr->ifa))) 2565163953Srrs continue; 2566163953Srrs 2567163953Srrs /* found a valid local address to use */ 2568167598Srrs return (&laddr->ifa->address.sa); 2569163953Srrs } 2570163953Srrs /* no valid addresses found */ 2571163953Srrs return (NULL); 2572163953Srrs} 2573163953Srrs 2574163953Srrs/* 2575171477Srrs * builds an ASCONF chunk from queued ASCONF params. 2576171477Srrs * returns NULL on error (no mbuf, no ASCONF params queued, etc). 2577163953Srrs */ 2578163953Srrsstruct mbuf * 2579172190Srrssctp_compose_asconf(struct sctp_tcb *stcb, int *retlen, int addr_locked) 2580163953Srrs{ 2581163953Srrs struct mbuf *m_asconf, *m_asconf_chk; 2582163953Srrs struct sctp_asconf_addr *aa; 2583163953Srrs struct sctp_asconf_chunk *acp; 2584163953Srrs struct sctp_asconf_paramhdr *aph; 2585163953Srrs struct sctp_asconf_addr_param *aap; 2586163953Srrs uint32_t p_length; 2587163953Srrs uint32_t correlation_id = 1; /* 0 is reserved... */ 2588163953Srrs caddr_t ptr, lookup_ptr; 2589163953Srrs uint8_t lookup_used = 0; 2590163953Srrs 2591163953Srrs /* are there any asconf params to send? */ 2592179157Srrs TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) { 2593179157Srrs if (aa->sent == 0) 2594179157Srrs break; 2595163953Srrs } 2596179157Srrs if (aa == NULL) 2597171572Srrs return (NULL); 2598179157Srrs 2599163953Srrs /* 2600163953Srrs * get a chunk header mbuf and a cluster for the asconf params since 2601163953Srrs * it's simpler to fill in the asconf chunk header lookup address on 2602163953Srrs * the fly 2603163953Srrs */ 2604243882Sglebius m_asconf_chk = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_chunk), 0, M_NOWAIT, 1, MT_DATA); 2605163953Srrs if (m_asconf_chk == NULL) { 2606163953Srrs /* no mbuf's */ 2607169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 2608169420Srrs "compose_asconf: couldn't get chunk mbuf!\n"); 2609163953Srrs return (NULL); 2610163953Srrs } 2611243882Sglebius m_asconf = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA); 2612163953Srrs if (m_asconf == NULL) { 2613163953Srrs /* no mbuf's */ 2614169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 2615169420Srrs "compose_asconf: couldn't get mbuf!\n"); 2616163953Srrs sctp_m_freem(m_asconf_chk); 2617163953Srrs return (NULL); 2618163953Srrs } 2619165647Srrs SCTP_BUF_LEN(m_asconf_chk) = sizeof(struct sctp_asconf_chunk); 2620165647Srrs SCTP_BUF_LEN(m_asconf) = 0; 2621163953Srrs acp = mtod(m_asconf_chk, struct sctp_asconf_chunk *); 2622163953Srrs bzero(acp, sizeof(struct sctp_asconf_chunk)); 2623163953Srrs /* save pointers to lookup address and asconf params */ 2624163953Srrs lookup_ptr = (caddr_t)(acp + 1); /* after the header */ 2625163953Srrs ptr = mtod(m_asconf, caddr_t); /* beginning of cluster */ 2626163953Srrs 2627163953Srrs /* fill in chunk header info */ 2628163953Srrs acp->ch.chunk_type = SCTP_ASCONF; 2629163953Srrs acp->ch.chunk_flags = 0; 2630163953Srrs acp->serial_number = htonl(stcb->asoc.asconf_seq_out); 2631179157Srrs stcb->asoc.asconf_seq_out++; 2632163953Srrs 2633163953Srrs /* add parameters... up to smallest MTU allowed */ 2634163953Srrs TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) { 2635179157Srrs if (aa->sent) 2636179157Srrs continue; 2637163953Srrs /* get the parameter length */ 2638163953Srrs p_length = SCTP_SIZE32(aa->ap.aph.ph.param_length); 2639163953Srrs /* will it fit in current chunk? */ 2640258454Stuexen if ((SCTP_BUF_LEN(m_asconf) + p_length > stcb->asoc.smallest_mtu) || 2641258454Stuexen (SCTP_BUF_LEN(m_asconf) + p_length > MCLBYTES)) { 2642163953Srrs /* won't fit, so we're done with this chunk */ 2643163953Srrs break; 2644163953Srrs } 2645163953Srrs /* assign (and store) a correlation id */ 2646163953Srrs aa->ap.aph.correlation_id = correlation_id++; 2647163953Srrs 2648163953Srrs /* 2649163953Srrs * fill in address if we're doing a delete this is a simple 2650163953Srrs * way for us to fill in the correlation address, which 2651163953Srrs * should only be used by the peer if we're deleting our 2652163953Srrs * source address and adding a new address (e.g. renumbering 2653163953Srrs * case) 2654163953Srrs */ 2655163953Srrs if (lookup_used == 0 && 2656185694Srrs (aa->special_del == 0) && 2657163953Srrs aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS) { 2658163953Srrs struct sctp_ipv6addr_param *lookup; 2659163953Srrs uint16_t p_size, addr_size; 2660163953Srrs 2661163953Srrs lookup = (struct sctp_ipv6addr_param *)lookup_ptr; 2662163953Srrs lookup->ph.param_type = 2663163953Srrs htons(aa->ap.addrp.ph.param_type); 2664163953Srrs if (aa->ap.addrp.ph.param_type == SCTP_IPV6_ADDRESS) { 2665163953Srrs /* copy IPv6 address */ 2666163953Srrs p_size = sizeof(struct sctp_ipv6addr_param); 2667163953Srrs addr_size = sizeof(struct in6_addr); 2668163953Srrs } else { 2669163953Srrs /* copy IPv4 address */ 2670163953Srrs p_size = sizeof(struct sctp_ipv4addr_param); 2671163953Srrs addr_size = sizeof(struct in_addr); 2672163953Srrs } 2673163953Srrs lookup->ph.param_length = htons(SCTP_SIZE32(p_size)); 2674163953Srrs memcpy(lookup->addr, &aa->ap.addrp.addr, addr_size); 2675165647Srrs SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(p_size); 2676163953Srrs lookup_used = 1; 2677163953Srrs } 2678163953Srrs /* copy into current space */ 2679163953Srrs memcpy(ptr, &aa->ap, p_length); 2680163953Srrs 2681163953Srrs /* network elements and update lengths */ 2682163953Srrs aph = (struct sctp_asconf_paramhdr *)ptr; 2683163953Srrs aap = (struct sctp_asconf_addr_param *)ptr; 2684163953Srrs /* correlation_id is transparent to peer, no htonl needed */ 2685163953Srrs aph->ph.param_type = htons(aph->ph.param_type); 2686163953Srrs aph->ph.param_length = htons(aph->ph.param_length); 2687163953Srrs aap->addrp.ph.param_type = htons(aap->addrp.ph.param_type); 2688163953Srrs aap->addrp.ph.param_length = htons(aap->addrp.ph.param_length); 2689163953Srrs 2690165647Srrs SCTP_BUF_LEN(m_asconf) += SCTP_SIZE32(p_length); 2691163953Srrs ptr += SCTP_SIZE32(p_length); 2692163953Srrs 2693163953Srrs /* 2694163953Srrs * these params are removed off the pending list upon 2695163953Srrs * getting an ASCONF-ACK back from the peer, just set flag 2696163953Srrs */ 2697163953Srrs aa->sent = 1; 2698163953Srrs } 2699163953Srrs /* check to see if the lookup addr has been populated yet */ 2700163953Srrs if (lookup_used == 0) { 2701163953Srrs /* NOTE: if the address param is optional, can skip this... */ 2702163953Srrs /* add any valid (existing) address... */ 2703163953Srrs struct sctp_ipv6addr_param *lookup; 2704163953Srrs uint16_t p_size, addr_size; 2705163953Srrs struct sockaddr *found_addr; 2706163953Srrs caddr_t addr_ptr; 2707163953Srrs 2708163953Srrs if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) 2709172190Srrs found_addr = sctp_find_valid_localaddr(stcb, 2710172190Srrs addr_locked); 2711163953Srrs else 2712163953Srrs found_addr = sctp_find_valid_localaddr_ep(stcb); 2713163953Srrs 2714163953Srrs lookup = (struct sctp_ipv6addr_param *)lookup_ptr; 2715163953Srrs if (found_addr != NULL) { 2716221249Stuexen switch (found_addr->sa_family) { 2717221249Stuexen#ifdef INET6 2718221249Stuexen case AF_INET6: 2719163953Srrs /* copy IPv6 address */ 2720163953Srrs lookup->ph.param_type = 2721163953Srrs htons(SCTP_IPV6_ADDRESS); 2722163953Srrs p_size = sizeof(struct sctp_ipv6addr_param); 2723163953Srrs addr_size = sizeof(struct in6_addr); 2724163953Srrs addr_ptr = (caddr_t)&((struct sockaddr_in6 *) 2725163953Srrs found_addr)->sin6_addr; 2726221249Stuexen break; 2727221249Stuexen#endif 2728221249Stuexen#ifdef INET 2729221249Stuexen case AF_INET: 2730163953Srrs /* copy IPv4 address */ 2731163953Srrs lookup->ph.param_type = 2732163953Srrs htons(SCTP_IPV4_ADDRESS); 2733163953Srrs p_size = sizeof(struct sctp_ipv4addr_param); 2734163953Srrs addr_size = sizeof(struct in_addr); 2735163953Srrs addr_ptr = (caddr_t)&((struct sockaddr_in *) 2736163953Srrs found_addr)->sin_addr; 2737221249Stuexen break; 2738221249Stuexen#endif 2739221249Stuexen default: 2740221249Stuexen p_size = 0; 2741221249Stuexen addr_size = 0; 2742221249Stuexen addr_ptr = NULL; 2743221249Stuexen break; 2744163953Srrs } 2745163953Srrs lookup->ph.param_length = htons(SCTP_SIZE32(p_size)); 2746163953Srrs memcpy(lookup->addr, addr_ptr, addr_size); 2747165647Srrs SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(p_size); 2748163953Srrs } else { 2749163953Srrs /* uh oh... don't have any address?? */ 2750169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 2751169420Srrs "compose_asconf: no lookup addr!\n"); 2752221249Stuexen /* XXX for now, we send a IPv4 address of 0.0.0.0 */ 2753163953Srrs lookup->ph.param_type = htons(SCTP_IPV4_ADDRESS); 2754163953Srrs lookup->ph.param_length = htons(SCTP_SIZE32(sizeof(struct sctp_ipv4addr_param))); 2755163953Srrs bzero(lookup->addr, sizeof(struct in_addr)); 2756165647Srrs SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(sizeof(struct sctp_ipv4addr_param)); 2757163953Srrs } 2758163953Srrs } 2759163953Srrs /* chain it all together */ 2760165647Srrs SCTP_BUF_NEXT(m_asconf_chk) = m_asconf; 2761169655Srrs *retlen = SCTP_BUF_LEN(m_asconf_chk) + SCTP_BUF_LEN(m_asconf); 2762258454Stuexen acp->ch.chunk_length = htons(*retlen); 2763163953Srrs 2764163953Srrs return (m_asconf_chk); 2765163953Srrs} 2766163953Srrs 2767163953Srrs/* 2768163953Srrs * section to handle address changes before an association is up eg. changes 2769163953Srrs * during INIT/INIT-ACK/COOKIE-ECHO handshake 2770163953Srrs */ 2771163953Srrs 2772163953Srrs/* 2773163953Srrs * processes the (local) addresses in the INIT-ACK chunk 2774163953Srrs */ 2775163953Srrsstatic void 2776163953Srrssctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m, 2777163953Srrs unsigned int offset, unsigned int length) 2778163953Srrs{ 2779163953Srrs struct sctp_paramhdr tmp_param, *ph; 2780163953Srrs uint16_t plen, ptype; 2781167598Srrs struct sctp_ifa *sctp_ifa; 2782271746Stuexen union sctp_sockstore store; 2783221249Stuexen 2784221249Stuexen#ifdef INET6 2785238501Stuexen struct sctp_ipv6addr_param addr6_store; 2786221249Stuexen 2787221249Stuexen#endif 2788221249Stuexen#ifdef INET 2789238501Stuexen struct sctp_ipv4addr_param addr4_store; 2790221249Stuexen 2791221249Stuexen#endif 2792163953Srrs 2793169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF2, "processing init-ack addresses\n"); 2794169420Srrs if (stcb == NULL) /* Un-needed check for SA */ 2795169420Srrs return; 2796163953Srrs 2797163953Srrs /* convert to upper bound */ 2798163953Srrs length += offset; 2799163953Srrs 2800163953Srrs if ((offset + sizeof(struct sctp_paramhdr)) > length) { 2801163953Srrs return; 2802163953Srrs } 2803163953Srrs /* go through the addresses in the init-ack */ 2804221249Stuexen ph = (struct sctp_paramhdr *) 2805221249Stuexen sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr), 2806221249Stuexen (uint8_t *) & tmp_param); 2807163953Srrs while (ph != NULL) { 2808163953Srrs ptype = ntohs(ph->param_type); 2809163953Srrs plen = ntohs(ph->param_length); 2810221249Stuexen switch (ptype) { 2811221249Stuexen#ifdef INET6 2812221249Stuexen case SCTP_IPV6_ADDRESS: 2813221249Stuexen { 2814221249Stuexen struct sctp_ipv6addr_param *a6p; 2815163953Srrs 2816221249Stuexen /* get the entire IPv6 address param */ 2817221249Stuexen a6p = (struct sctp_ipv6addr_param *) 2818221249Stuexen sctp_m_getptr(m, offset, 2819221249Stuexen sizeof(struct sctp_ipv6addr_param), 2820238501Stuexen (uint8_t *) & addr6_store); 2821221249Stuexen if (plen != sizeof(struct sctp_ipv6addr_param) || 2822221249Stuexen a6p == NULL) { 2823221249Stuexen return; 2824221249Stuexen } 2825271746Stuexen memset(&store, 0, sizeof(union sctp_sockstore)); 2826271746Stuexen store.sin6.sin6_family = AF_INET6; 2827271746Stuexen store.sin6.sin6_len = sizeof(struct sockaddr_in6); 2828271746Stuexen store.sin6.sin6_port = stcb->rport; 2829271746Stuexen memcpy(&store.sin6.sin6_addr, a6p->addr, sizeof(struct in6_addr)); 2830221249Stuexen break; 2831163953Srrs } 2832221249Stuexen#endif 2833221249Stuexen#ifdef INET 2834221249Stuexen case SCTP_IPV4_ADDRESS: 2835221249Stuexen { 2836221249Stuexen struct sctp_ipv4addr_param *a4p; 2837163953Srrs 2838221249Stuexen /* get the entire IPv4 address param */ 2839221249Stuexen a4p = (struct sctp_ipv4addr_param *)sctp_m_getptr(m, offset, 2840221249Stuexen sizeof(struct sctp_ipv4addr_param), 2841238501Stuexen (uint8_t *) & addr4_store); 2842221249Stuexen if (plen != sizeof(struct sctp_ipv4addr_param) || 2843221249Stuexen a4p == NULL) { 2844221249Stuexen return; 2845221249Stuexen } 2846271746Stuexen memset(&store, 0, sizeof(union sctp_sockstore)); 2847271746Stuexen store.sin.sin_family = AF_INET; 2848271746Stuexen store.sin.sin_len = sizeof(struct sockaddr_in); 2849271746Stuexen store.sin.sin_port = stcb->rport; 2850271746Stuexen store.sin.sin_addr.s_addr = a4p->addr; 2851221410Stuexen break; 2852163953Srrs } 2853221249Stuexen#endif 2854221249Stuexen default: 2855163953Srrs goto next_addr; 2856163953Srrs } 2857163953Srrs 2858163953Srrs /* see if this address really (still) exists */ 2859283711Stuexen sctp_ifa = sctp_find_ifa_by_addr(&store.sa, stcb->asoc.vrf_id, 2860172190Srrs SCTP_ADDR_NOT_LOCKED); 2861167598Srrs if (sctp_ifa == NULL) { 2862163953Srrs /* address doesn't exist anymore */ 2863163953Srrs int status; 2864163953Srrs 2865163953Srrs /* are ASCONFs allowed ? */ 2866163953Srrs if ((sctp_is_feature_on(stcb->sctp_ep, 2867163953Srrs SCTP_PCB_FLAGS_DO_ASCONF)) && 2868270362Stuexen stcb->asoc.asconf_supported) { 2869163953Srrs /* queue an ASCONF DEL_IP_ADDRESS */ 2870271746Stuexen status = sctp_asconf_queue_sa_delete(stcb, &store.sa); 2871163953Srrs /* 2872171572Srrs * if queued ok, and in correct state, send 2873171572Srrs * out the ASCONF. 2874163953Srrs */ 2875163953Srrs if (status == 0 && 2876163953Srrs SCTP_GET_STATE(&stcb->asoc) == 2877163953Srrs SCTP_STATE_OPEN) { 2878171572Srrs#ifdef SCTP_TIMER_BASED_ASCONF 2879163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, 2880163953Srrs stcb->sctp_ep, stcb, 2881163953Srrs stcb->asoc.primary_destination); 2882171572Srrs#else 2883224641Stuexen sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED); 2884171572Srrs#endif 2885163953Srrs } 2886163953Srrs } 2887163953Srrs } 2888163953Srrsnext_addr: 2889163953Srrs /* 2890163953Srrs * Sanity check: Make sure the length isn't 0, otherwise 2891163953Srrs * we'll be stuck in this loop for a long time... 2892163953Srrs */ 2893163953Srrs if (SCTP_SIZE32(plen) == 0) { 2894169420Srrs SCTP_PRINTF("process_initack_addrs: bad len (%d) type=%xh\n", 2895163953Srrs plen, ptype); 2896163953Srrs return; 2897163953Srrs } 2898163953Srrs /* get next parameter */ 2899163953Srrs offset += SCTP_SIZE32(plen); 2900163953Srrs if ((offset + sizeof(struct sctp_paramhdr)) > length) 2901163953Srrs return; 2902163953Srrs ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset, 2903163953Srrs sizeof(struct sctp_paramhdr), (uint8_t *) & tmp_param); 2904163953Srrs } /* while */ 2905163953Srrs} 2906163953Srrs 2907163953Srrs/* FIX ME: need to verify return result for v6 address type if v6 disabled */ 2908163953Srrs/* 2909163953Srrs * checks to see if a specific address is in the initack address list returns 2910163953Srrs * 1 if found, 0 if not 2911163953Srrs */ 2912163953Srrsstatic uint32_t 2913228653Stuexensctp_addr_in_initack(struct mbuf *m, uint32_t offset, uint32_t length, struct sockaddr *sa) 2914163953Srrs{ 2915163953Srrs struct sctp_paramhdr tmp_param, *ph; 2916163953Srrs uint16_t plen, ptype; 2917221249Stuexen 2918221249Stuexen#ifdef INET 2919163953Srrs struct sockaddr_in *sin; 2920163953Srrs struct sctp_ipv4addr_param *a4p; 2921238501Stuexen struct sctp_ipv6addr_param addr4_store; 2922163953Srrs 2923221249Stuexen#endif 2924163953Srrs#ifdef INET6 2925167598Srrs struct sockaddr_in6 *sin6; 2926163953Srrs struct sctp_ipv6addr_param *a6p; 2927238501Stuexen struct sctp_ipv6addr_param addr6_store; 2928167598Srrs struct sockaddr_in6 sin6_tmp; 2929163953Srrs 2930221249Stuexen#endif 2931163953Srrs 2932221249Stuexen switch (sa->sa_family) { 2933221249Stuexen#ifdef INET 2934221249Stuexen case AF_INET: 2935221249Stuexen break; 2936221249Stuexen#endif 2937163953Srrs#ifdef INET6 2938221249Stuexen case AF_INET6: 2939221249Stuexen break; 2940221249Stuexen#endif 2941221249Stuexen default: 2942163953Srrs return (0); 2943221249Stuexen } 2944163953Srrs 2945169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF2, "find_initack_addr: starting search for "); 2946169420Srrs SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa); 2947163953Srrs /* convert to upper bound */ 2948163953Srrs length += offset; 2949163953Srrs 2950163953Srrs if ((offset + sizeof(struct sctp_paramhdr)) > length) { 2951169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 2952169420Srrs "find_initack_addr: invalid offset?\n"); 2953163953Srrs return (0); 2954163953Srrs } 2955163953Srrs /* go through the addresses in the init-ack */ 2956163953Srrs ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset, 2957163953Srrs sizeof(struct sctp_paramhdr), (uint8_t *) & tmp_param); 2958163953Srrs while (ph != NULL) { 2959163953Srrs ptype = ntohs(ph->param_type); 2960163953Srrs plen = ntohs(ph->param_length); 2961221249Stuexen switch (ptype) { 2962163953Srrs#ifdef INET6 2963221249Stuexen case SCTP_IPV6_ADDRESS: 2964221249Stuexen if (sa->sa_family == AF_INET6) { 2965221249Stuexen /* get the entire IPv6 address param */ 2966221249Stuexen if (plen != sizeof(struct sctp_ipv6addr_param)) { 2967221249Stuexen break; 2968221249Stuexen } 2969221249Stuexen /* get the entire IPv6 address param */ 2970221249Stuexen a6p = (struct sctp_ipv6addr_param *) 2971221249Stuexen sctp_m_getptr(m, offset, 2972221249Stuexen sizeof(struct sctp_ipv6addr_param), 2973238501Stuexen (uint8_t *) & addr6_store); 2974221249Stuexen if (a6p == NULL) { 2975221249Stuexen return (0); 2976221249Stuexen } 2977221249Stuexen sin6 = (struct sockaddr_in6 *)sa; 2978221249Stuexen if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) { 2979221249Stuexen /* create a copy and clear scope */ 2980221249Stuexen memcpy(&sin6_tmp, sin6, 2981221249Stuexen sizeof(struct sockaddr_in6)); 2982221249Stuexen sin6 = &sin6_tmp; 2983221249Stuexen in6_clearscope(&sin6->sin6_addr); 2984221249Stuexen } 2985221249Stuexen if (memcmp(&sin6->sin6_addr, a6p->addr, 2986221249Stuexen sizeof(struct in6_addr)) == 0) { 2987221249Stuexen /* found it */ 2988221249Stuexen return (1); 2989221249Stuexen } 2990163953Srrs } 2991221249Stuexen break; 2992163953Srrs#endif /* INET6 */ 2993221249Stuexen#ifdef INET 2994221249Stuexen case SCTP_IPV4_ADDRESS: 2995221249Stuexen if (sa->sa_family == AF_INET) { 2996221249Stuexen if (plen != sizeof(struct sctp_ipv4addr_param)) { 2997221249Stuexen break; 2998221249Stuexen } 2999221249Stuexen /* get the entire IPv4 address param */ 3000221249Stuexen a4p = (struct sctp_ipv4addr_param *) 3001221249Stuexen sctp_m_getptr(m, offset, 3002221249Stuexen sizeof(struct sctp_ipv4addr_param), 3003238501Stuexen (uint8_t *) & addr4_store); 3004221249Stuexen if (a4p == NULL) { 3005221249Stuexen return (0); 3006221249Stuexen } 3007221249Stuexen sin = (struct sockaddr_in *)sa; 3008221249Stuexen if (sin->sin_addr.s_addr == a4p->addr) { 3009221249Stuexen /* found it */ 3010221249Stuexen return (1); 3011221249Stuexen } 3012163953Srrs } 3013221249Stuexen break; 3014221249Stuexen#endif 3015221249Stuexen default: 3016221249Stuexen break; 3017163953Srrs } 3018163953Srrs /* get next parameter */ 3019163953Srrs offset += SCTP_SIZE32(plen); 3020221249Stuexen if (offset + sizeof(struct sctp_paramhdr) > length) { 3021163953Srrs return (0); 3022221249Stuexen } 3023163953Srrs ph = (struct sctp_paramhdr *) 3024163953Srrs sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr), 3025163953Srrs (uint8_t *) & tmp_param); 3026163953Srrs } /* while */ 3027163953Srrs /* not found! */ 3028163953Srrs return (0); 3029163953Srrs} 3030163953Srrs 3031163953Srrs/* 3032163953Srrs * makes sure that the current endpoint local addr list is consistent with 3033163953Srrs * the new association (eg. subset bound, asconf allowed) adds addresses as 3034163953Srrs * necessary 3035163953Srrs */ 3036163953Srrsstatic void 3037163953Srrssctp_check_address_list_ep(struct sctp_tcb *stcb, struct mbuf *m, int offset, 3038163953Srrs int length, struct sockaddr *init_addr) 3039163953Srrs{ 3040163953Srrs struct sctp_laddr *laddr; 3041163953Srrs 3042163953Srrs /* go through the endpoint list */ 3043163953Srrs LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) { 3044163953Srrs /* be paranoid and validate the laddr */ 3045163953Srrs if (laddr->ifa == NULL) { 3046169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 3047169420Srrs "check_addr_list_ep: laddr->ifa is NULL"); 3048163953Srrs continue; 3049163953Srrs } 3050167598Srrs if (laddr->ifa == NULL) { 3051169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "check_addr_list_ep: laddr->ifa->ifa_addr is NULL"); 3052163953Srrs continue; 3053163953Srrs } 3054163953Srrs /* do i have it implicitly? */ 3055167598Srrs if (sctp_cmpaddr(&laddr->ifa->address.sa, init_addr)) { 3056163953Srrs continue; 3057163953Srrs } 3058163953Srrs /* check to see if in the init-ack */ 3059228653Stuexen if (!sctp_addr_in_initack(m, offset, length, &laddr->ifa->address.sa)) { 3060163953Srrs /* try to add it */ 3061163953Srrs sctp_addr_mgmt_assoc(stcb->sctp_ep, stcb, laddr->ifa, 3062172190Srrs SCTP_ADD_IP_ADDRESS, SCTP_ADDR_NOT_LOCKED); 3063163953Srrs } 3064163953Srrs } 3065163953Srrs} 3066163953Srrs 3067163953Srrs/* 3068163953Srrs * makes sure that the current kernel address list is consistent with the new 3069163953Srrs * association (with all addrs bound) adds addresses as necessary 3070163953Srrs */ 3071163953Srrsstatic void 3072163953Srrssctp_check_address_list_all(struct sctp_tcb *stcb, struct mbuf *m, int offset, 3073163953Srrs int length, struct sockaddr *init_addr, 3074163953Srrs uint16_t local_scope, uint16_t site_scope, 3075163953Srrs uint16_t ipv4_scope, uint16_t loopback_scope) 3076163953Srrs{ 3077167598Srrs struct sctp_vrf *vrf = NULL; 3078167598Srrs struct sctp_ifn *sctp_ifn; 3079167598Srrs struct sctp_ifa *sctp_ifa; 3080167598Srrs uint32_t vrf_id; 3081163953Srrs 3082228653Stuexen#ifdef INET 3083228653Stuexen struct sockaddr_in *sin; 3084228653Stuexen 3085228653Stuexen#endif 3086228653Stuexen#ifdef INET6 3087228653Stuexen struct sockaddr_in6 *sin6; 3088228653Stuexen 3089228653Stuexen#endif 3090228653Stuexen 3091168299Srrs if (stcb) { 3092168299Srrs vrf_id = stcb->asoc.vrf_id; 3093168299Srrs } else { 3094169420Srrs return; 3095168299Srrs } 3096172218Srrs SCTP_IPI_ADDR_RLOCK(); 3097167598Srrs vrf = sctp_find_vrf(vrf_id); 3098167598Srrs if (vrf == NULL) { 3099172218Srrs SCTP_IPI_ADDR_RUNLOCK(); 3100167598Srrs return; 3101167598Srrs } 3102163953Srrs /* go through all our known interfaces */ 3103167598Srrs LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) { 3104167598Srrs if (loopback_scope == 0 && SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) { 3105163953Srrs /* skip loopback interface */ 3106163953Srrs continue; 3107163953Srrs } 3108163953Srrs /* go through each interface address */ 3109167598Srrs LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) { 3110163953Srrs /* do i have it implicitly? */ 3111167598Srrs if (sctp_cmpaddr(&sctp_ifa->address.sa, init_addr)) { 3112163953Srrs continue; 3113163953Srrs } 3114228653Stuexen switch (sctp_ifa->address.sa.sa_family) { 3115228653Stuexen#ifdef INET 3116228653Stuexen case AF_INET: 3117271746Stuexen sin = &sctp_ifa->address.sin; 3118267769Stuexen if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred, 3119267769Stuexen &sin->sin_addr) != 0) { 3120267769Stuexen continue; 3121267769Stuexen } 3122228653Stuexen if ((ipv4_scope == 0) && 3123228653Stuexen (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) { 3124228653Stuexen /* private address not in scope */ 3125228653Stuexen continue; 3126228653Stuexen } 3127228653Stuexen break; 3128228653Stuexen#endif 3129228653Stuexen#ifdef INET6 3130228653Stuexen case AF_INET6: 3131271746Stuexen sin6 = &sctp_ifa->address.sin6; 3132267769Stuexen if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred, 3133267769Stuexen &sin6->sin6_addr) != 0) { 3134267769Stuexen continue; 3135267769Stuexen } 3136228653Stuexen if ((local_scope == 0) && 3137228653Stuexen (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))) { 3138228653Stuexen continue; 3139228653Stuexen } 3140228653Stuexen if ((site_scope == 0) && 3141228653Stuexen (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) { 3142228653Stuexen continue; 3143228653Stuexen } 3144228653Stuexen break; 3145228653Stuexen#endif 3146228653Stuexen default: 3147228653Stuexen break; 3148228653Stuexen } 3149163953Srrs /* check to see if in the init-ack */ 3150228653Stuexen if (!sctp_addr_in_initack(m, offset, length, &sctp_ifa->address.sa)) { 3151163953Srrs /* try to add it */ 3152163953Srrs sctp_addr_mgmt_assoc(stcb->sctp_ep, stcb, 3153172190Srrs sctp_ifa, SCTP_ADD_IP_ADDRESS, 3154172190Srrs SCTP_ADDR_LOCKED); 3155163953Srrs } 3156163953Srrs } /* end foreach ifa */ 3157163953Srrs } /* end foreach ifn */ 3158172218Srrs SCTP_IPI_ADDR_RUNLOCK(); 3159163953Srrs} 3160163953Srrs 3161163953Srrs/* 3162163953Srrs * validates an init-ack chunk (from a cookie-echo) with current addresses 3163163953Srrs * adds addresses from the init-ack into our local address list, if needed 3164163953Srrs * queues asconf adds/deletes addresses as needed and makes appropriate list 3165163953Srrs * changes for source address selection m, offset: points to the start of the 3166163953Srrs * address list in an init-ack chunk length: total length of the address 3167163953Srrs * params only init_addr: address where my INIT-ACK was sent from 3168163953Srrs */ 3169163953Srrsvoid 3170163953Srrssctp_check_address_list(struct sctp_tcb *stcb, struct mbuf *m, int offset, 3171163953Srrs int length, struct sockaddr *init_addr, 3172163953Srrs uint16_t local_scope, uint16_t site_scope, 3173163953Srrs uint16_t ipv4_scope, uint16_t loopback_scope) 3174163953Srrs{ 3175163953Srrs /* process the local addresses in the initack */ 3176163953Srrs sctp_process_initack_addresses(stcb, m, offset, length); 3177163953Srrs 3178163953Srrs if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { 3179163953Srrs /* bound all case */ 3180163953Srrs sctp_check_address_list_all(stcb, m, offset, length, init_addr, 3181163953Srrs local_scope, site_scope, ipv4_scope, loopback_scope); 3182163953Srrs } else { 3183163953Srrs /* subset bound case */ 3184163953Srrs if (sctp_is_feature_on(stcb->sctp_ep, 3185163953Srrs SCTP_PCB_FLAGS_DO_ASCONF)) { 3186163953Srrs /* asconf's allowed */ 3187163953Srrs sctp_check_address_list_ep(stcb, m, offset, length, 3188163953Srrs init_addr); 3189163953Srrs } 3190163953Srrs /* else, no asconfs allowed, so what we sent is what we get */ 3191163953Srrs } 3192163953Srrs} 3193163953Srrs 3194163953Srrs/* 3195163953Srrs * sctp_bindx() support 3196163953Srrs */ 3197163953Srrsuint32_t 3198169655Srrssctp_addr_mgmt_ep_sa(struct sctp_inpcb *inp, struct sockaddr *sa, 3199170744Srrs uint32_t type, uint32_t vrf_id, struct sctp_ifa *sctp_ifap) 3200163953Srrs{ 3201167598Srrs struct sctp_ifa *ifa; 3202218521Stuexen struct sctp_laddr *laddr, *nladdr; 3203163953Srrs 3204167598Srrs if (sa->sa_len == 0) { 3205171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EINVAL); 3206163953Srrs return (EINVAL); 3207167598Srrs } 3208170744Srrs if (sctp_ifap) { 3209170744Srrs ifa = sctp_ifap; 3210170744Srrs } else if (type == SCTP_ADD_IP_ADDRESS) { 3211167598Srrs /* For an add the address MUST be on the system */ 3212172091Srrs ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED); 3213167598Srrs } else if (type == SCTP_DEL_IP_ADDRESS) { 3214167598Srrs /* For a delete we need to find it in the inp */ 3215172091Srrs ifa = sctp_find_ifa_in_ep(inp, sa, SCTP_ADDR_NOT_LOCKED); 3216167598Srrs } else { 3217167598Srrs ifa = NULL; 3218167598Srrs } 3219163953Srrs if (ifa != NULL) { 3220167598Srrs if (type == SCTP_ADD_IP_ADDRESS) { 3221167598Srrs sctp_add_local_addr_ep(inp, ifa, type); 3222167598Srrs } else if (type == SCTP_DEL_IP_ADDRESS) { 3223169655Srrs if (inp->laddr_count < 2) { 3224169655Srrs /* can't delete the last local address */ 3225171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EINVAL); 3226169655Srrs return (EINVAL); 3227169655Srrs } 3228169655Srrs LIST_FOREACH(laddr, &inp->sctp_addr_list, 3229169655Srrs sctp_nxt_addr) { 3230167598Srrs if (ifa == laddr->ifa) { 3231167598Srrs /* Mark in the delete */ 3232167598Srrs laddr->action = type; 3233167598Srrs } 3234163953Srrs } 3235163953Srrs } 3236218521Stuexen if (LIST_EMPTY(&inp->sctp_asoc_list)) { 3237199372Stuexen /* 3238199372Stuexen * There is no need to start the iterator if the inp 3239199372Stuexen * has no associations. 3240199372Stuexen */ 3241218521Stuexen if (type == SCTP_DEL_IP_ADDRESS) { 3242218521Stuexen LIST_FOREACH_SAFE(laddr, &inp->sctp_addr_list, sctp_nxt_addr, nladdr) { 3243218521Stuexen if (laddr->ifa == ifa) { 3244218521Stuexen sctp_del_local_addr_ep(inp, ifa); 3245218521Stuexen } 3246218521Stuexen } 3247218521Stuexen } 3248218521Stuexen } else { 3249199372Stuexen struct sctp_asconf_iterator *asc; 3250199372Stuexen struct sctp_laddr *wi; 3251296052Stuexen int ret; 3252199372Stuexen 3253199372Stuexen SCTP_MALLOC(asc, struct sctp_asconf_iterator *, 3254199372Stuexen sizeof(struct sctp_asconf_iterator), 3255199372Stuexen SCTP_M_ASC_IT); 3256199372Stuexen if (asc == NULL) { 3257199372Stuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, ENOMEM); 3258199372Stuexen return (ENOMEM); 3259199372Stuexen } 3260199372Stuexen wi = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_laddr), struct sctp_laddr); 3261199372Stuexen if (wi == NULL) { 3262199372Stuexen SCTP_FREE(asc, SCTP_M_ASC_IT); 3263199372Stuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, ENOMEM); 3264199372Stuexen return (ENOMEM); 3265199372Stuexen } 3266199372Stuexen LIST_INIT(&asc->list_of_work); 3267199372Stuexen asc->cnt = 1; 3268199372Stuexen SCTP_INCR_LADDR_COUNT(); 3269199372Stuexen wi->ifa = ifa; 3270199372Stuexen wi->action = type; 3271199372Stuexen atomic_add_int(&ifa->refcount, 1); 3272199372Stuexen LIST_INSERT_HEAD(&asc->list_of_work, wi, sctp_nxt_addr); 3273296052Stuexen ret = sctp_initiate_iterator(sctp_asconf_iterator_ep, 3274199372Stuexen sctp_asconf_iterator_stcb, 3275199372Stuexen sctp_asconf_iterator_ep_end, 3276199372Stuexen SCTP_PCB_ANY_FLAGS, 3277199372Stuexen SCTP_PCB_ANY_FEATURES, 3278199372Stuexen SCTP_ASOC_ANY_STATE, 3279199372Stuexen (void *)asc, 0, 3280199372Stuexen sctp_asconf_iterator_end, inp, 0); 3281296052Stuexen if (ret) { 3282296052Stuexen SCTP_PRINTF("Failed to initiate iterator for addr_mgmt_ep_sa\n"); 3283296052Stuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EFAULT); 3284296052Stuexen sctp_asconf_iterator_end(asc, 0); 3285296052Stuexen return (EFAULT); 3286296052Stuexen } 3287199372Stuexen } 3288199372Stuexen return (0); 3289163953Srrs } else { 3290163953Srrs /* invalid address! */ 3291171943Srrs SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EADDRNOTAVAIL); 3292163953Srrs return (EADDRNOTAVAIL); 3293163953Srrs } 3294163953Srrs} 3295185694Srrs 3296185694Srrsvoid 3297185694Srrssctp_asconf_send_nat_state_update(struct sctp_tcb *stcb, 3298185694Srrs struct sctp_nets *net) 3299185694Srrs{ 3300185694Srrs struct sctp_asconf_addr *aa; 3301185694Srrs struct sctp_ifa *sctp_ifap; 3302185694Srrs struct sctp_asconf_tag_param *vtag; 3303221249Stuexen 3304221249Stuexen#ifdef INET 3305185694Srrs struct sockaddr_in *to; 3306185694Srrs 3307221249Stuexen#endif 3308185694Srrs#ifdef INET6 3309185694Srrs struct sockaddr_in6 *to6; 3310185694Srrs 3311185694Srrs#endif 3312185694Srrs if (net == NULL) { 3313185694Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "sctp_asconf_send_nat_state_update: Missing net\n"); 3314185694Srrs return; 3315185694Srrs } 3316185694Srrs if (stcb == NULL) { 3317185694Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "sctp_asconf_send_nat_state_update: Missing stcb\n"); 3318185694Srrs return; 3319185694Srrs } 3320185694Srrs /* 3321185694Srrs * Need to have in the asconf: - vtagparam(my_vtag/peer_vtag) - 3322185694Srrs * add(0.0.0.0) - del(0.0.0.0) - Any global addresses add(addr) 3323185694Srrs */ 3324185694Srrs SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa), 3325185694Srrs SCTP_M_ASC_ADDR); 3326185694Srrs if (aa == NULL) { 3327185694Srrs /* didn't get memory */ 3328185694Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 3329185694Srrs "sctp_asconf_send_nat_state_update: failed to get memory!\n"); 3330185694Srrs return; 3331185694Srrs } 3332185694Srrs aa->special_del = 0; 3333185694Srrs /* fill in asconf address parameter fields */ 3334185694Srrs /* top level elements are "networked" during send */ 3335185694Srrs aa->ifa = NULL; 3336185694Srrs aa->sent = 0; /* clear sent flag */ 3337185694Srrs vtag = (struct sctp_asconf_tag_param *)&aa->ap.aph; 3338185694Srrs vtag->aph.ph.param_type = SCTP_NAT_VTAGS; 3339185694Srrs vtag->aph.ph.param_length = sizeof(struct sctp_asconf_tag_param); 3340185694Srrs vtag->local_vtag = htonl(stcb->asoc.my_vtag); 3341185694Srrs vtag->remote_vtag = htonl(stcb->asoc.peer_vtag); 3342185694Srrs TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next); 3343185694Srrs 3344185694Srrs SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa), 3345185694Srrs SCTP_M_ASC_ADDR); 3346185694Srrs if (aa == NULL) { 3347185694Srrs /* didn't get memory */ 3348185694Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 3349185694Srrs "sctp_asconf_send_nat_state_update: failed to get memory!\n"); 3350185694Srrs return; 3351185694Srrs } 3352185694Srrs memset(aa, 0, sizeof(struct sctp_asconf_addr)); 3353185694Srrs /* fill in asconf address parameter fields */ 3354185694Srrs /* ADD(0.0.0.0) */ 3355221249Stuexen switch (net->ro._l_addr.sa.sa_family) { 3356221249Stuexen#ifdef INET 3357221249Stuexen case AF_INET: 3358185694Srrs aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS; 3359185694Srrs aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addrv4_param); 3360185694Srrs aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS; 3361185694Srrs aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv4addr_param); 3362185694Srrs /* No need to add an address, we are using 0.0.0.0 */ 3363185694Srrs TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next); 3364221249Stuexen break; 3365221249Stuexen#endif 3366185694Srrs#ifdef INET6 3367221249Stuexen case AF_INET6: 3368185694Srrs aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS; 3369185694Srrs aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addr_param); 3370185694Srrs aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS; 3371185694Srrs aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv6addr_param); 3372185694Srrs /* No need to add an address, we are using 0.0.0.0 */ 3373185694Srrs TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next); 3374221249Stuexen break; 3375221249Stuexen#endif 3376283717Stuexen default: 3377283717Stuexen SCTPDBG(SCTP_DEBUG_ASCONF1, 3378283717Stuexen "sctp_asconf_send_nat_state_update: unknown address family\n"); 3379283717Stuexen SCTP_FREE(aa, SCTP_M_ASC_ADDR); 3380283717Stuexen return; 3381185694Srrs } 3382185694Srrs SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa), 3383185694Srrs SCTP_M_ASC_ADDR); 3384185694Srrs if (aa == NULL) { 3385185694Srrs /* didn't get memory */ 3386185694Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 3387185694Srrs "sctp_asconf_send_nat_state_update: failed to get memory!\n"); 3388185694Srrs return; 3389185694Srrs } 3390185694Srrs memset(aa, 0, sizeof(struct sctp_asconf_addr)); 3391185694Srrs /* fill in asconf address parameter fields */ 3392185694Srrs /* ADD(0.0.0.0) */ 3393221249Stuexen switch (net->ro._l_addr.sa.sa_family) { 3394221249Stuexen#ifdef INET 3395221249Stuexen case AF_INET: 3396185694Srrs aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS; 3397185694Srrs aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addrv4_param); 3398185694Srrs aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS; 3399185694Srrs aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv4addr_param); 3400185694Srrs /* No need to add an address, we are using 0.0.0.0 */ 3401185694Srrs TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next); 3402221249Stuexen break; 3403221249Stuexen#endif 3404185694Srrs#ifdef INET6 3405221249Stuexen case AF_INET6: 3406185694Srrs aa->ap.aph.ph.param_type = SCTP_DEL_IP_ADDRESS; 3407185694Srrs aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addr_param); 3408185694Srrs aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS; 3409185694Srrs aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv6addr_param); 3410185694Srrs /* No need to add an address, we are using 0.0.0.0 */ 3411185694Srrs TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next); 3412221249Stuexen break; 3413221249Stuexen#endif 3414283717Stuexen default: 3415283717Stuexen SCTPDBG(SCTP_DEBUG_ASCONF1, 3416283717Stuexen "sctp_asconf_send_nat_state_update: unknown address family\n"); 3417283717Stuexen SCTP_FREE(aa, SCTP_M_ASC_ADDR); 3418283717Stuexen return; 3419185694Srrs } 3420185694Srrs /* Now we must hunt the addresses and add all global addresses */ 3421185694Srrs if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { 3422185694Srrs struct sctp_vrf *vrf = NULL; 3423185694Srrs struct sctp_ifn *sctp_ifnp; 3424185694Srrs uint32_t vrf_id; 3425185694Srrs 3426185694Srrs vrf_id = stcb->sctp_ep->def_vrf_id; 3427185694Srrs vrf = sctp_find_vrf(vrf_id); 3428185694Srrs if (vrf == NULL) { 3429185694Srrs goto skip_rest; 3430185694Srrs } 3431185694Srrs SCTP_IPI_ADDR_RLOCK(); 3432185694Srrs LIST_FOREACH(sctp_ifnp, &vrf->ifnlist, next_ifn) { 3433185694Srrs LIST_FOREACH(sctp_ifap, &sctp_ifnp->ifalist, next_ifa) { 3434221249Stuexen switch (sctp_ifap->address.sa.sa_family) { 3435221249Stuexen#ifdef INET 3436221249Stuexen case AF_INET: 3437185694Srrs to = &sctp_ifap->address.sin; 3438267769Stuexen if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred, 3439267769Stuexen &to->sin_addr) != 0) { 3440267769Stuexen continue; 3441267769Stuexen } 3442185694Srrs if (IN4_ISPRIVATE_ADDRESS(&to->sin_addr)) { 3443185694Srrs continue; 3444185694Srrs } 3445185694Srrs if (IN4_ISLOOPBACK_ADDRESS(&to->sin_addr)) { 3446185694Srrs continue; 3447185694Srrs } 3448221249Stuexen break; 3449221249Stuexen#endif 3450185694Srrs#ifdef INET6 3451221249Stuexen case AF_INET6: 3452185694Srrs to6 = &sctp_ifap->address.sin6; 3453267769Stuexen if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred, 3454267769Stuexen &to6->sin6_addr) != 0) { 3455267769Stuexen continue; 3456267769Stuexen } 3457185694Srrs if (IN6_IS_ADDR_LOOPBACK(&to6->sin6_addr)) { 3458185694Srrs continue; 3459185694Srrs } 3460185694Srrs if (IN6_IS_ADDR_LINKLOCAL(&to6->sin6_addr)) { 3461185694Srrs continue; 3462185694Srrs } 3463221249Stuexen break; 3464221249Stuexen#endif 3465221249Stuexen default: 3466221249Stuexen continue; 3467185694Srrs } 3468185694Srrs sctp_asconf_queue_mgmt(stcb, sctp_ifap, SCTP_ADD_IP_ADDRESS); 3469185694Srrs } 3470185694Srrs } 3471185694Srrs SCTP_IPI_ADDR_RUNLOCK(); 3472185694Srrs } else { 3473185694Srrs struct sctp_laddr *laddr; 3474185694Srrs 3475185694Srrs LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) { 3476185694Srrs if (laddr->ifa == NULL) { 3477185694Srrs continue; 3478185694Srrs } 3479185694Srrs if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED) 3480185694Srrs /* 3481185694Srrs * Address being deleted by the system, dont 3482185694Srrs * list. 3483185694Srrs */ 3484185694Srrs continue; 3485185694Srrs if (laddr->action == SCTP_DEL_IP_ADDRESS) { 3486185694Srrs /* 3487185694Srrs * Address being deleted on this ep don't 3488185694Srrs * list. 3489185694Srrs */ 3490185694Srrs continue; 3491185694Srrs } 3492185694Srrs sctp_ifap = laddr->ifa; 3493221249Stuexen switch (sctp_ifap->address.sa.sa_family) { 3494221249Stuexen#ifdef INET 3495221249Stuexen case AF_INET: 3496185694Srrs to = &sctp_ifap->address.sin; 3497185694Srrs if (IN4_ISPRIVATE_ADDRESS(&to->sin_addr)) { 3498185694Srrs continue; 3499185694Srrs } 3500185694Srrs if (IN4_ISLOOPBACK_ADDRESS(&to->sin_addr)) { 3501185694Srrs continue; 3502185694Srrs } 3503221249Stuexen break; 3504221249Stuexen#endif 3505185694Srrs#ifdef INET6 3506221249Stuexen case AF_INET6: 3507185694Srrs to6 = &sctp_ifap->address.sin6; 3508185694Srrs if (IN6_IS_ADDR_LOOPBACK(&to6->sin6_addr)) { 3509185694Srrs continue; 3510185694Srrs } 3511185694Srrs if (IN6_IS_ADDR_LINKLOCAL(&to6->sin6_addr)) { 3512185694Srrs continue; 3513185694Srrs } 3514221249Stuexen break; 3515221249Stuexen#endif 3516221249Stuexen default: 3517221249Stuexen continue; 3518185694Srrs } 3519185694Srrs sctp_asconf_queue_mgmt(stcb, sctp_ifap, SCTP_ADD_IP_ADDRESS); 3520185694Srrs } 3521185694Srrs } 3522185694Srrsskip_rest: 3523185694Srrs /* Now we must send the asconf into the queue */ 3524224641Stuexen sctp_send_asconf(stcb, net, SCTP_ADDR_NOT_LOCKED); 3525185694Srrs} 3526