sctp_asconf.c revision 228907
1163953Srrs/*- 2169382Srrs * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. 3218319Srrs * Copyright (c) 2008-2011, by Randall Stewart. All rights reserved. 4218319Srrs * Copyright (c) 2008-2011, 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/* $KAME: sctp_asconf.c,v 1.24 2005/03/06 16:04:16 itojun Exp $ */ 34163953Srrs 35163953Srrs#include <sys/cdefs.h> 36163957Srrs__FBSDID("$FreeBSD: head/sys/netinet/sctp_asconf.c 228907 2011-12-27 10:16:24Z tuexen $"); 37163953Srrs#include <netinet/sctp_os.h> 38163953Srrs#include <netinet/sctp_var.h> 39167598Srrs#include <netinet/sctp_sysctl.h> 40163953Srrs#include <netinet/sctp_pcb.h> 41163953Srrs#include <netinet/sctp_header.h> 42163953Srrs#include <netinet/sctputil.h> 43163953Srrs#include <netinet/sctp_output.h> 44163953Srrs#include <netinet/sctp_asconf.h> 45172091Srrs#include <netinet/sctp_timer.h> 46163953Srrs 47163953Srrs/* 48163953Srrs * debug flags: 49163953Srrs * SCTP_DEBUG_ASCONF1: protocol info, general info and errors 50163953Srrs * SCTP_DEBUG_ASCONF2: detailed info 51163953Srrs */ 52163953Srrs#ifdef SCTP_DEBUG 53163953Srrs#endif /* SCTP_DEBUG */ 54163953Srrs 55163953Srrs 56169420Srrsstatic void 57163953Srrssctp_asconf_get_source_ip(struct mbuf *m, struct sockaddr *sa) 58163953Srrs{ 59163953Srrs struct ip *iph; 60221249Stuexen 61221249Stuexen#ifdef INET 62163953Srrs struct sockaddr_in *sin; 63163953Srrs 64221249Stuexen#endif 65163953Srrs#ifdef INET6 66163953Srrs struct sockaddr_in6 *sin6; 67163953Srrs 68163953Srrs#endif 69163953Srrs 70163953Srrs iph = mtod(m, struct ip *); 71221249Stuexen switch (iph->ip_v) { 72221249Stuexen#ifdef INET 73221249Stuexen case IPVERSION: 74221249Stuexen { 75221249Stuexen /* IPv4 source */ 76221249Stuexen sin = (struct sockaddr_in *)sa; 77221249Stuexen bzero(sin, sizeof(*sin)); 78221249Stuexen sin->sin_family = AF_INET; 79221249Stuexen sin->sin_len = sizeof(struct sockaddr_in); 80221249Stuexen sin->sin_port = 0; 81221249Stuexen sin->sin_addr.s_addr = iph->ip_src.s_addr; 82221249Stuexen break; 83221249Stuexen } 84221249Stuexen#endif 85163953Srrs#ifdef INET6 86221249Stuexen case (IPV6_VERSION >> 4): 87221249Stuexen { 88221249Stuexen /* IPv6 source */ 89221249Stuexen struct ip6_hdr *ip6; 90163953Srrs 91221249Stuexen sin6 = (struct sockaddr_in6 *)sa; 92221249Stuexen bzero(sin6, sizeof(*sin6)); 93221249Stuexen sin6->sin6_family = AF_INET6; 94221249Stuexen sin6->sin6_len = sizeof(struct sockaddr_in6); 95221249Stuexen sin6->sin6_port = 0; 96221249Stuexen ip6 = mtod(m, struct ip6_hdr *); 97221249Stuexen sin6->sin6_addr = ip6->ip6_src; 98221249Stuexen break; 99221249Stuexen } 100221249Stuexen#endif /* INET6 */ 101221249Stuexen default: 102221249Stuexen break; 103163953Srrs } 104221249Stuexen return; 105163953Srrs} 106163953Srrs 107163953Srrs/* 108163953Srrs * draft-ietf-tsvwg-addip-sctp 109163953Srrs * 110163953Srrs * An ASCONF parameter queue exists per asoc which holds the pending address 111163953Srrs * operations. Lists are updated upon receipt of ASCONF-ACK. 112163953Srrs * 113171477Srrs * A restricted_addrs list exists per assoc to hold local addresses that are 114171477Srrs * not (yet) usable by the assoc as a source address. These addresses are 115171477Srrs * either pending an ASCONF operation (and exist on the ASCONF parameter 116171477Srrs * queue), or they are permanently restricted (the peer has returned an 117171477Srrs * ERROR indication to an ASCONF(ADD), or the peer does not support ASCONF). 118171477Srrs * 119163953Srrs * Deleted addresses are always immediately removed from the lists as they will 120163953Srrs * (shortly) no longer exist in the kernel. We send ASCONFs as a courtesy, 121163953Srrs * only if allowed. 122163953Srrs */ 123163953Srrs 124163953Srrs/* 125171477Srrs * ASCONF parameter processing. 126171477Srrs * response_required: set if a reply is required (eg. SUCCESS_REPORT). 127171477Srrs * returns a mbuf to an "error" response parameter or NULL/"success" if ok. 128171477Srrs * FIX: allocating this many mbufs on the fly is pretty inefficient... 129163953Srrs */ 130163953Srrsstatic struct mbuf * 131163953Srrssctp_asconf_success_response(uint32_t id) 132163953Srrs{ 133163953Srrs struct mbuf *m_reply = NULL; 134163953Srrs struct sctp_asconf_paramhdr *aph; 135163953Srrs 136163953Srrs m_reply = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_paramhdr), 137163953Srrs 0, M_DONTWAIT, 1, MT_DATA); 138163953Srrs if (m_reply == NULL) { 139169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 140169420Srrs "asconf_success_response: couldn't get mbuf!\n"); 141228907Stuexen return (NULL); 142163953Srrs } 143163953Srrs aph = mtod(m_reply, struct sctp_asconf_paramhdr *); 144163953Srrs aph->correlation_id = id; 145163953Srrs aph->ph.param_type = htons(SCTP_SUCCESS_REPORT); 146163953Srrs aph->ph.param_length = sizeof(struct sctp_asconf_paramhdr); 147165647Srrs SCTP_BUF_LEN(m_reply) = aph->ph.param_length; 148163953Srrs aph->ph.param_length = htons(aph->ph.param_length); 149163953Srrs 150228907Stuexen return (m_reply); 151163953Srrs} 152163953Srrs 153163953Srrsstatic struct mbuf * 154163953Srrssctp_asconf_error_response(uint32_t id, uint16_t cause, uint8_t * error_tlv, 155163953Srrs uint16_t tlv_length) 156163953Srrs{ 157163953Srrs struct mbuf *m_reply = NULL; 158163953Srrs struct sctp_asconf_paramhdr *aph; 159163953Srrs struct sctp_error_cause *error; 160163953Srrs uint8_t *tlv; 161163953Srrs 162163953Srrs m_reply = sctp_get_mbuf_for_msg((sizeof(struct sctp_asconf_paramhdr) + 163163953Srrs tlv_length + 164163953Srrs sizeof(struct sctp_error_cause)), 165163953Srrs 0, M_DONTWAIT, 1, MT_DATA); 166163953Srrs if (m_reply == NULL) { 167169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 168169420Srrs "asconf_error_response: couldn't get mbuf!\n"); 169228907Stuexen return (NULL); 170163953Srrs } 171163953Srrs aph = mtod(m_reply, struct sctp_asconf_paramhdr *); 172163953Srrs error = (struct sctp_error_cause *)(aph + 1); 173163953Srrs 174163953Srrs aph->correlation_id = id; 175163953Srrs aph->ph.param_type = htons(SCTP_ERROR_CAUSE_IND); 176163953Srrs error->code = htons(cause); 177163953Srrs error->length = tlv_length + sizeof(struct sctp_error_cause); 178163953Srrs aph->ph.param_length = error->length + 179163953Srrs sizeof(struct sctp_asconf_paramhdr); 180163953Srrs 181163953Srrs if (aph->ph.param_length > MLEN) { 182169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 183169420Srrs "asconf_error_response: tlv_length (%xh) too big\n", 184169420Srrs tlv_length); 185163953Srrs sctp_m_freem(m_reply); /* discard */ 186228907Stuexen return (NULL); 187163953Srrs } 188163953Srrs if (error_tlv != NULL) { 189163953Srrs tlv = (uint8_t *) (error + 1); 190163953Srrs memcpy(tlv, error_tlv, tlv_length); 191163953Srrs } 192165647Srrs SCTP_BUF_LEN(m_reply) = aph->ph.param_length; 193163953Srrs error->length = htons(error->length); 194163953Srrs aph->ph.param_length = htons(aph->ph.param_length); 195163953Srrs 196228907Stuexen return (m_reply); 197163953Srrs} 198163953Srrs 199163953Srrsstatic struct mbuf * 200163953Srrssctp_process_asconf_add_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph, 201224641Stuexen struct sctp_tcb *stcb, int send_hb, int response_required) 202163953Srrs{ 203224641Stuexen struct sctp_nets *net; 204163953Srrs struct mbuf *m_reply = NULL; 205163953Srrs struct sockaddr_storage sa_source, sa_store; 206221249Stuexen struct sctp_paramhdr *ph; 207163953Srrs uint16_t param_type, param_length, aparam_length; 208163953Srrs struct sockaddr *sa; 209163953Srrs int zero_address = 0; 210225571Stuexen int bad_address = 0; 211163953Srrs 212221249Stuexen#ifdef INET 213221249Stuexen struct sockaddr_in *sin; 214221249Stuexen struct sctp_ipv4addr_param *v4addr; 215221249Stuexen 216221249Stuexen#endif 217163953Srrs#ifdef INET6 218163953Srrs struct sockaddr_in6 *sin6; 219163953Srrs struct sctp_ipv6addr_param *v6addr; 220163953Srrs 221221249Stuexen#endif 222163953Srrs 223163953Srrs aparam_length = ntohs(aph->ph.param_length); 224221249Stuexen ph = (struct sctp_paramhdr *)(aph + 1); 225221249Stuexen param_type = ntohs(ph->param_type); 226221249Stuexen param_length = ntohs(ph->param_length); 227163953Srrs 228163953Srrs sa = (struct sockaddr *)&sa_store; 229163953Srrs switch (param_type) { 230221249Stuexen#ifdef INET 231163953Srrs case SCTP_IPV4_ADDRESS: 232163953Srrs if (param_length != sizeof(struct sctp_ipv4addr_param)) { 233163953Srrs /* invalid param size */ 234228907Stuexen return (NULL); 235163953Srrs } 236221249Stuexen v4addr = (struct sctp_ipv4addr_param *)ph; 237163953Srrs sin = (struct sockaddr_in *)&sa_store; 238163953Srrs bzero(sin, sizeof(*sin)); 239163953Srrs sin->sin_family = AF_INET; 240163953Srrs sin->sin_len = sizeof(struct sockaddr_in); 241163953Srrs sin->sin_port = stcb->rport; 242163953Srrs sin->sin_addr.s_addr = v4addr->addr; 243225571Stuexen if ((sin->sin_addr.s_addr == INADDR_BROADCAST) || 244225571Stuexen IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) { 245225584Stuexen bad_address = 1; 246225571Stuexen } 247163953Srrs if (sin->sin_addr.s_addr == INADDR_ANY) 248163953Srrs zero_address = 1; 249169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_add_ip: adding "); 250169420Srrs SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); 251163953Srrs break; 252221249Stuexen#endif 253221249Stuexen#ifdef INET6 254163953Srrs case SCTP_IPV6_ADDRESS: 255163953Srrs if (param_length != sizeof(struct sctp_ipv6addr_param)) { 256163953Srrs /* invalid param size */ 257228907Stuexen return (NULL); 258163953Srrs } 259221249Stuexen v6addr = (struct sctp_ipv6addr_param *)ph; 260163953Srrs sin6 = (struct sockaddr_in6 *)&sa_store; 261163953Srrs bzero(sin6, sizeof(*sin6)); 262163953Srrs sin6->sin6_family = AF_INET6; 263163953Srrs sin6->sin6_len = sizeof(struct sockaddr_in6); 264163953Srrs sin6->sin6_port = stcb->rport; 265163953Srrs memcpy((caddr_t)&sin6->sin6_addr, v6addr->addr, 266163953Srrs sizeof(struct in6_addr)); 267225571Stuexen if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { 268225571Stuexen bad_address = 1; 269225571Stuexen } 270163953Srrs if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) 271163953Srrs zero_address = 1; 272169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_add_ip: adding "); 273169420Srrs SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); 274221249Stuexen break; 275169420Srrs#endif 276163953Srrs default: 277163953Srrs m_reply = sctp_asconf_error_response(aph->correlation_id, 278225571Stuexen SCTP_CAUSE_INVALID_PARAM, (uint8_t *) aph, 279163953Srrs aparam_length); 280228907Stuexen return (m_reply); 281163953Srrs } /* end switch */ 282163953Srrs 283163953Srrs /* if 0.0.0.0/::0, add the source address instead */ 284179783Srrs if (zero_address && SCTP_BASE_SYSCTL(sctp_nat_friendly)) { 285163953Srrs sa = (struct sockaddr *)&sa_source; 286163953Srrs sctp_asconf_get_source_ip(m, sa); 287169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 288169420Srrs "process_asconf_add_ip: using source addr "); 289169420Srrs SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); 290163953Srrs } 291163953Srrs /* add the address */ 292225571Stuexen if (bad_address) { 293225571Stuexen m_reply = sctp_asconf_error_response(aph->correlation_id, 294225571Stuexen SCTP_CAUSE_INVALID_PARAM, (uint8_t *) aph, 295225571Stuexen aparam_length); 296225571Stuexen } else if (sctp_add_remote_addr(stcb, sa, &net, SCTP_DONOT_SETSCOPE, 297165220Srrs SCTP_ADDR_DYNAMIC_ADDED) != 0) { 298169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 299169420Srrs "process_asconf_add_ip: error adding address\n"); 300163953Srrs m_reply = sctp_asconf_error_response(aph->correlation_id, 301163953Srrs SCTP_CAUSE_RESOURCE_SHORTAGE, (uint8_t *) aph, 302163953Srrs aparam_length); 303163953Srrs } else { 304163953Srrs /* notify upper layer */ 305172090Srrs sctp_ulp_notify(SCTP_NOTIFY_ASCONF_ADD_IP, stcb, 0, sa, SCTP_SO_NOT_LOCKED); 306163953Srrs if (response_required) { 307163953Srrs m_reply = 308163953Srrs sctp_asconf_success_response(aph->correlation_id); 309163953Srrs } 310224641Stuexen sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, stcb->sctp_ep, stcb, net); 311169655Srrs sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, 312224641Stuexen stcb, net); 313224641Stuexen if (send_hb) { 314224641Stuexen sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED); 315224641Stuexen } 316163953Srrs } 317228907Stuexen return (m_reply); 318163953Srrs} 319163953Srrs 320163953Srrsstatic int 321171572Srrssctp_asconf_del_remote_addrs_except(struct sctp_tcb *stcb, struct sockaddr *src) 322163953Srrs{ 323163953Srrs struct sctp_nets *src_net, *net; 324163953Srrs 325163953Srrs /* make sure the source address exists as a destination net */ 326163953Srrs src_net = sctp_findnet(stcb, src); 327163953Srrs if (src_net == NULL) { 328163953Srrs /* not found */ 329228907Stuexen return (-1); 330163953Srrs } 331163953Srrs /* delete all destination addresses except the source */ 332163953Srrs TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 333163953Srrs if (net != src_net) { 334163953Srrs /* delete this address */ 335163953Srrs sctp_remove_net(stcb, net); 336169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 337169420Srrs "asconf_del_remote_addrs_except: deleting "); 338169420Srrs SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, 339169420Srrs (struct sockaddr *)&net->ro._l_addr); 340163953Srrs /* notify upper layer */ 341163953Srrs sctp_ulp_notify(SCTP_NOTIFY_ASCONF_DELETE_IP, stcb, 0, 342172090Srrs (struct sockaddr *)&net->ro._l_addr, SCTP_SO_NOT_LOCKED); 343163953Srrs } 344163953Srrs } 345228907Stuexen return (0); 346163953Srrs} 347163953Srrs 348163953Srrsstatic struct mbuf * 349163953Srrssctp_process_asconf_delete_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph, 350163953Srrs struct sctp_tcb *stcb, int response_required) 351163953Srrs{ 352163953Srrs struct mbuf *m_reply = NULL; 353163953Srrs struct sockaddr_storage sa_source, sa_store; 354221249Stuexen struct sctp_paramhdr *ph; 355163953Srrs uint16_t param_type, param_length, aparam_length; 356163953Srrs struct sockaddr *sa; 357163953Srrs int zero_address = 0; 358163953Srrs int result; 359163953Srrs 360221249Stuexen#ifdef INET 361221249Stuexen struct sockaddr_in *sin; 362221249Stuexen struct sctp_ipv4addr_param *v4addr; 363221249Stuexen 364221249Stuexen#endif 365163953Srrs#ifdef INET6 366163953Srrs struct sockaddr_in6 *sin6; 367163953Srrs struct sctp_ipv6addr_param *v6addr; 368163953Srrs 369221249Stuexen#endif 370163953Srrs 371163953Srrs /* get the source IP address for src and 0.0.0.0/::0 delete checks */ 372163953Srrs sctp_asconf_get_source_ip(m, (struct sockaddr *)&sa_source); 373163953Srrs 374163953Srrs aparam_length = ntohs(aph->ph.param_length); 375221249Stuexen ph = (struct sctp_paramhdr *)(aph + 1); 376221249Stuexen param_type = ntohs(ph->param_type); 377221249Stuexen param_length = ntohs(ph->param_length); 378163953Srrs 379163953Srrs sa = (struct sockaddr *)&sa_store; 380163953Srrs switch (param_type) { 381221249Stuexen#ifdef INET 382163953Srrs case SCTP_IPV4_ADDRESS: 383163953Srrs if (param_length != sizeof(struct sctp_ipv4addr_param)) { 384163953Srrs /* invalid param size */ 385228907Stuexen return (NULL); 386163953Srrs } 387221249Stuexen v4addr = (struct sctp_ipv4addr_param *)ph; 388163953Srrs sin = (struct sockaddr_in *)&sa_store; 389163953Srrs bzero(sin, sizeof(*sin)); 390163953Srrs sin->sin_family = AF_INET; 391163953Srrs sin->sin_len = sizeof(struct sockaddr_in); 392163953Srrs sin->sin_port = stcb->rport; 393163953Srrs sin->sin_addr.s_addr = v4addr->addr; 394163953Srrs if (sin->sin_addr.s_addr == INADDR_ANY) 395163953Srrs zero_address = 1; 396169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 397169420Srrs "process_asconf_delete_ip: deleting "); 398169420Srrs SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); 399163953Srrs break; 400221249Stuexen#endif 401221249Stuexen#ifdef INET6 402163953Srrs case SCTP_IPV6_ADDRESS: 403163953Srrs if (param_length != sizeof(struct sctp_ipv6addr_param)) { 404163953Srrs /* invalid param size */ 405228907Stuexen return (NULL); 406163953Srrs } 407221249Stuexen v6addr = (struct sctp_ipv6addr_param *)ph; 408163953Srrs sin6 = (struct sockaddr_in6 *)&sa_store; 409163953Srrs bzero(sin6, sizeof(*sin6)); 410163953Srrs sin6->sin6_family = AF_INET6; 411163953Srrs sin6->sin6_len = sizeof(struct sockaddr_in6); 412163953Srrs sin6->sin6_port = stcb->rport; 413163953Srrs memcpy(&sin6->sin6_addr, v6addr->addr, 414163953Srrs sizeof(struct in6_addr)); 415163953Srrs if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) 416163953Srrs zero_address = 1; 417169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 418169420Srrs "process_asconf_delete_ip: deleting "); 419169420Srrs SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); 420221249Stuexen break; 421169420Srrs#endif 422163953Srrs default: 423163953Srrs m_reply = sctp_asconf_error_response(aph->correlation_id, 424163953Srrs SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph, 425163953Srrs aparam_length); 426228907Stuexen return (m_reply); 427163953Srrs } 428163953Srrs 429163953Srrs /* make sure the source address is not being deleted */ 430163953Srrs if (sctp_cmpaddr(sa, (struct sockaddr *)&sa_source)) { 431163953Srrs /* trying to delete the source address! */ 432169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_delete_ip: tried to delete source addr\n"); 433163953Srrs m_reply = sctp_asconf_error_response(aph->correlation_id, 434163953Srrs SCTP_CAUSE_DELETING_SRC_ADDR, (uint8_t *) aph, 435163953Srrs aparam_length); 436228907Stuexen return (m_reply); 437163953Srrs } 438163953Srrs /* if deleting 0.0.0.0/::0, delete all addresses except src addr */ 439179783Srrs if (zero_address && SCTP_BASE_SYSCTL(sctp_nat_friendly)) { 440163953Srrs result = sctp_asconf_del_remote_addrs_except(stcb, 441163953Srrs (struct sockaddr *)&sa_source); 442163953Srrs 443163953Srrs if (result) { 444163953Srrs /* src address did not exist? */ 445169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_delete_ip: src addr does not exist?\n"); 446163953Srrs /* what error to reply with?? */ 447163953Srrs m_reply = 448163953Srrs sctp_asconf_error_response(aph->correlation_id, 449163953Srrs SCTP_CAUSE_REQUEST_REFUSED, (uint8_t *) aph, 450163953Srrs aparam_length); 451163953Srrs } else if (response_required) { 452163953Srrs m_reply = 453163953Srrs sctp_asconf_success_response(aph->correlation_id); 454163953Srrs } 455228907Stuexen return (m_reply); 456163953Srrs } 457163953Srrs /* delete the address */ 458163953Srrs result = sctp_del_remote_addr(stcb, sa); 459163953Srrs /* 460163953Srrs * note if result == -2, the address doesn't exist in the asoc but 461163953Srrs * since it's being deleted anyways, we just ack the delete -- but 462163953Srrs * this probably means something has already gone awry 463163953Srrs */ 464163953Srrs if (result == -1) { 465163953Srrs /* only one address in the asoc */ 466169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_delete_ip: tried to delete last IP addr!\n"); 467163953Srrs m_reply = sctp_asconf_error_response(aph->correlation_id, 468163953Srrs SCTP_CAUSE_DELETING_LAST_ADDR, (uint8_t *) aph, 469163953Srrs aparam_length); 470163953Srrs } else { 471163953Srrs if (response_required) { 472163953Srrs m_reply = sctp_asconf_success_response(aph->correlation_id); 473163953Srrs } 474163953Srrs /* notify upper layer */ 475172090Srrs sctp_ulp_notify(SCTP_NOTIFY_ASCONF_DELETE_IP, stcb, 0, sa, SCTP_SO_NOT_LOCKED); 476163953Srrs } 477228907Stuexen return (m_reply); 478163953Srrs} 479163953Srrs 480163953Srrsstatic struct mbuf * 481163953Srrssctp_process_asconf_set_primary(struct mbuf *m, 482171572Srrs struct sctp_asconf_paramhdr *aph, 483171572Srrs struct sctp_tcb *stcb, int response_required) 484163953Srrs{ 485163953Srrs struct mbuf *m_reply = NULL; 486163953Srrs struct sockaddr_storage sa_source, sa_store; 487221249Stuexen struct sctp_paramhdr *ph; 488163953Srrs uint16_t param_type, param_length, aparam_length; 489163953Srrs struct sockaddr *sa; 490163953Srrs int zero_address = 0; 491163953Srrs 492221249Stuexen#ifdef INET 493221249Stuexen struct sockaddr_in *sin; 494221249Stuexen struct sctp_ipv4addr_param *v4addr; 495221249Stuexen 496221249Stuexen#endif 497163953Srrs#ifdef INET6 498163953Srrs struct sockaddr_in6 *sin6; 499163953Srrs struct sctp_ipv6addr_param *v6addr; 500163953Srrs 501221249Stuexen#endif 502163953Srrs 503163953Srrs aparam_length = ntohs(aph->ph.param_length); 504221249Stuexen ph = (struct sctp_paramhdr *)(aph + 1); 505221249Stuexen param_type = ntohs(ph->param_type); 506221249Stuexen param_length = ntohs(ph->param_length); 507163953Srrs 508163953Srrs sa = (struct sockaddr *)&sa_store; 509163953Srrs switch (param_type) { 510221249Stuexen#ifdef INET 511163953Srrs case SCTP_IPV4_ADDRESS: 512163953Srrs if (param_length != sizeof(struct sctp_ipv4addr_param)) { 513163953Srrs /* invalid param size */ 514228907Stuexen return (NULL); 515163953Srrs } 516221249Stuexen v4addr = (struct sctp_ipv4addr_param *)ph; 517163953Srrs sin = (struct sockaddr_in *)&sa_store; 518163953Srrs bzero(sin, sizeof(*sin)); 519163953Srrs sin->sin_family = AF_INET; 520163953Srrs sin->sin_len = sizeof(struct sockaddr_in); 521163953Srrs sin->sin_addr.s_addr = v4addr->addr; 522163953Srrs if (sin->sin_addr.s_addr == INADDR_ANY) 523163953Srrs zero_address = 1; 524169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_set_primary: "); 525169420Srrs SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); 526163953Srrs break; 527221249Stuexen#endif 528221249Stuexen#ifdef INET6 529163953Srrs case SCTP_IPV6_ADDRESS: 530163953Srrs if (param_length != sizeof(struct sctp_ipv6addr_param)) { 531163953Srrs /* invalid param size */ 532228907Stuexen return (NULL); 533163953Srrs } 534221249Stuexen v6addr = (struct sctp_ipv6addr_param *)ph; 535163953Srrs sin6 = (struct sockaddr_in6 *)&sa_store; 536163953Srrs bzero(sin6, sizeof(*sin6)); 537163953Srrs sin6->sin6_family = AF_INET6; 538163953Srrs sin6->sin6_len = sizeof(struct sockaddr_in6); 539163953Srrs memcpy((caddr_t)&sin6->sin6_addr, v6addr->addr, 540163953Srrs sizeof(struct in6_addr)); 541163953Srrs if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) 542163953Srrs zero_address = 1; 543169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_set_primary: "); 544169420Srrs SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); 545221249Stuexen break; 546169420Srrs#endif 547163953Srrs default: 548163953Srrs m_reply = sctp_asconf_error_response(aph->correlation_id, 549163953Srrs SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph, 550163953Srrs aparam_length); 551228907Stuexen return (m_reply); 552163953Srrs } 553163953Srrs 554163953Srrs /* if 0.0.0.0/::0, use the source address instead */ 555179783Srrs if (zero_address && SCTP_BASE_SYSCTL(sctp_nat_friendly)) { 556163953Srrs sa = (struct sockaddr *)&sa_source; 557163953Srrs sctp_asconf_get_source_ip(m, sa); 558169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 559169420Srrs "process_asconf_set_primary: using source addr "); 560169420Srrs SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); 561163953Srrs } 562163953Srrs /* set the primary address */ 563163953Srrs if (sctp_set_primary_addr(stcb, sa, NULL) == 0) { 564169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 565169420Srrs "process_asconf_set_primary: primary address set\n"); 566163953Srrs /* notify upper layer */ 567172090Srrs sctp_ulp_notify(SCTP_NOTIFY_ASCONF_SET_PRIMARY, stcb, 0, sa, SCTP_SO_NOT_LOCKED); 568224641Stuexen if ((stcb->asoc.primary_destination->dest_state & SCTP_ADDR_REACHABLE) && 569224641Stuexen (!(stcb->asoc.primary_destination->dest_state & SCTP_ADDR_PF)) && 570224641Stuexen (stcb->asoc.alternate)) { 571224641Stuexen sctp_free_remote_addr(stcb->asoc.alternate); 572224641Stuexen stcb->asoc.alternate = NULL; 573224641Stuexen } 574163953Srrs if (response_required) { 575163953Srrs m_reply = sctp_asconf_success_response(aph->correlation_id); 576163953Srrs } 577172091Srrs /* 578172091Srrs * Mobility adaptation. Ideally, when the reception of SET 579172091Srrs * PRIMARY with DELETE IP ADDRESS of the previous primary 580172091Srrs * destination, unacknowledged DATA are retransmitted 581172091Srrs * immediately to the new primary destination for seamless 582206137Stuexen * handover. If the destination is UNCONFIRMED and marked to 583206137Stuexen * REQ_PRIM, The retransmission occur when reception of the 584206137Stuexen * HEARTBEAT-ACK. (See sctp_handle_heartbeat_ack in 585172091Srrs * sctp_input.c) Also, when change of the primary 586172091Srrs * destination, it is better that all subsequent new DATA 587172091Srrs * containing already queued DATA are transmitted to the new 588172091Srrs * primary destination. (by micchie) 589172091Srrs */ 590172091Srrs if ((sctp_is_mobility_feature_on(stcb->sctp_ep, 591172091Srrs SCTP_MOBILITY_BASE) || 592172091Srrs sctp_is_mobility_feature_on(stcb->sctp_ep, 593172091Srrs SCTP_MOBILITY_FASTHANDOFF)) && 594172091Srrs sctp_is_mobility_feature_on(stcb->sctp_ep, 595172091Srrs SCTP_MOBILITY_PRIM_DELETED) && 596172091Srrs (stcb->asoc.primary_destination->dest_state & 597172091Srrs SCTP_ADDR_UNCONFIRMED) == 0) { 598172091Srrs 599172091Srrs sctp_timer_stop(SCTP_TIMER_TYPE_PRIM_DELETED, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_TIMER + SCTP_LOC_7); 600172091Srrs if (sctp_is_mobility_feature_on(stcb->sctp_ep, 601172091Srrs SCTP_MOBILITY_FASTHANDOFF)) { 602172091Srrs sctp_assoc_immediate_retrans(stcb, 603172091Srrs stcb->asoc.primary_destination); 604172091Srrs } 605172091Srrs if (sctp_is_mobility_feature_on(stcb->sctp_ep, 606172091Srrs SCTP_MOBILITY_BASE)) { 607212712Stuexen sctp_move_chunks_from_net(stcb, 608212712Stuexen stcb->asoc.deleted_primary); 609172091Srrs } 610172091Srrs sctp_delete_prim_timer(stcb->sctp_ep, stcb, 611172091Srrs stcb->asoc.deleted_primary); 612172091Srrs } 613163953Srrs } else { 614163953Srrs /* couldn't set the requested primary address! */ 615169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 616169420Srrs "process_asconf_set_primary: set primary failed!\n"); 617163953Srrs /* must have been an invalid address, so report */ 618163953Srrs m_reply = sctp_asconf_error_response(aph->correlation_id, 619163953Srrs SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph, 620163953Srrs aparam_length); 621163953Srrs } 622163953Srrs 623228907Stuexen return (m_reply); 624163953Srrs} 625163953Srrs 626163953Srrs/* 627163953Srrs * handles an ASCONF chunk. 628163953Srrs * if all parameters are processed ok, send a plain (empty) ASCONF-ACK 629163953Srrs */ 630163953Srrsvoid 631163953Srrssctp_handle_asconf(struct mbuf *m, unsigned int offset, 632171990Srrs struct sctp_asconf_chunk *cp, struct sctp_tcb *stcb, 633171990Srrs int first) 634163953Srrs{ 635163953Srrs struct sctp_association *asoc; 636163953Srrs uint32_t serial_num; 637171990Srrs struct mbuf *n, *m_ack, *m_result, *m_tail; 638163953Srrs struct sctp_asconf_ack_chunk *ack_cp; 639163953Srrs struct sctp_asconf_paramhdr *aph, *ack_aph; 640163953Srrs struct sctp_ipv6addr_param *p_addr; 641224641Stuexen unsigned int asconf_limit, cnt; 642163953Srrs int error = 0; /* did an error occur? */ 643163953Srrs 644163953Srrs /* asconf param buffer */ 645166675Srrs uint8_t aparam_buf[SCTP_PARAM_BUFFER_SIZE]; 646171990Srrs struct sctp_asconf_ack *ack, *ack_next; 647163953Srrs 648163953Srrs /* verify minimum length */ 649163953Srrs if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_asconf_chunk)) { 650169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 651169420Srrs "handle_asconf: chunk too small = %xh\n", 652169420Srrs ntohs(cp->ch.chunk_length)); 653163953Srrs return; 654163953Srrs } 655163953Srrs asoc = &stcb->asoc; 656163953Srrs serial_num = ntohl(cp->serial_number); 657163953Srrs 658216825Stuexen if (SCTP_TSN_GE(asoc->asconf_seq_in, serial_num)) { 659163953Srrs /* got a duplicate ASCONF */ 660169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 661169420Srrs "handle_asconf: got duplicate serial number = %xh\n", 662169420Srrs serial_num); 663163953Srrs return; 664163953Srrs } else if (serial_num != (asoc->asconf_seq_in + 1)) { 665169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: incorrect serial number = %xh (expected next = %xh)\n", 666169420Srrs serial_num, asoc->asconf_seq_in + 1); 667163953Srrs return; 668163953Srrs } 669163953Srrs /* it's the expected "next" sequence number, so process it */ 670163953Srrs asoc->asconf_seq_in = serial_num; /* update sequence */ 671163953Srrs /* get length of all the param's in the ASCONF */ 672163953Srrs asconf_limit = offset + ntohs(cp->ch.chunk_length); 673169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 674169420Srrs "handle_asconf: asconf_limit=%u, sequence=%xh\n", 675169420Srrs asconf_limit, serial_num); 676171990Srrs 677171990Srrs if (first) { 678171990Srrs /* delete old cache */ 679221249Stuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: Now processing first ASCONF. Try to delete old cache\n"); 680171990Srrs 681216822Stuexen TAILQ_FOREACH_SAFE(ack, &asoc->asconf_ack_sent, next, ack_next) { 682171990Srrs if (ack->serial_number == serial_num) 683171990Srrs break; 684171990Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: delete old(%u) < first(%u)\n", 685171990Srrs ack->serial_number, serial_num); 686216822Stuexen TAILQ_REMOVE(&asoc->asconf_ack_sent, ack, next); 687171990Srrs if (ack->data != NULL) { 688171990Srrs sctp_m_freem(ack->data); 689171990Srrs } 690179783Srrs SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asconf_ack), ack); 691171990Srrs } 692163953Srrs } 693165647Srrs m_ack = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_ack_chunk), 0, 694163953Srrs M_DONTWAIT, 1, MT_DATA); 695163953Srrs if (m_ack == NULL) { 696169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 697169420Srrs "handle_asconf: couldn't get mbuf!\n"); 698163953Srrs return; 699163953Srrs } 700163953Srrs m_tail = m_ack; /* current reply chain's tail */ 701163953Srrs 702163953Srrs /* fill in ASCONF-ACK header */ 703163953Srrs ack_cp = mtod(m_ack, struct sctp_asconf_ack_chunk *); 704163953Srrs ack_cp->ch.chunk_type = SCTP_ASCONF_ACK; 705163953Srrs ack_cp->ch.chunk_flags = 0; 706163953Srrs ack_cp->serial_number = htonl(serial_num); 707163953Srrs /* set initial lengths (eg. just an ASCONF-ACK), ntohx at the end! */ 708165647Srrs SCTP_BUF_LEN(m_ack) = sizeof(struct sctp_asconf_ack_chunk); 709163953Srrs ack_cp->ch.chunk_length = sizeof(struct sctp_asconf_ack_chunk); 710163953Srrs 711163953Srrs /* skip the lookup address parameter */ 712163953Srrs offset += sizeof(struct sctp_asconf_chunk); 713163953Srrs p_addr = (struct sctp_ipv6addr_param *)sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr), (uint8_t *) & aparam_buf); 714163953Srrs if (p_addr == NULL) { 715169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 716169420Srrs "handle_asconf: couldn't get lookup addr!\n"); 717163953Srrs /* respond with a missing/invalid mandatory parameter error */ 718163953Srrs return; 719163953Srrs } 720163953Srrs /* param_length is already validated in process_control... */ 721163953Srrs offset += ntohs(p_addr->ph.param_length); /* skip lookup addr */ 722163953Srrs 723163953Srrs /* get pointer to first asconf param in ASCONF-ACK */ 724163953Srrs ack_aph = (struct sctp_asconf_paramhdr *)(mtod(m_ack, caddr_t)+sizeof(struct sctp_asconf_ack_chunk)); 725163953Srrs if (ack_aph == NULL) { 726169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "Gak in asconf2\n"); 727163953Srrs return; 728163953Srrs } 729163953Srrs /* get pointer to first asconf param in ASCONF */ 730163953Srrs aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, sizeof(struct sctp_asconf_paramhdr), (uint8_t *) & aparam_buf); 731163953Srrs if (aph == NULL) { 732169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "Empty ASCONF received?\n"); 733163953Srrs goto send_reply; 734163953Srrs } 735163953Srrs /* process through all parameters */ 736224641Stuexen cnt = 0; 737163953Srrs while (aph != NULL) { 738163953Srrs unsigned int param_length, param_type; 739163953Srrs 740163953Srrs param_type = ntohs(aph->ph.param_type); 741163953Srrs param_length = ntohs(aph->ph.param_length); 742163953Srrs if (offset + param_length > asconf_limit) { 743163953Srrs /* parameter goes beyond end of chunk! */ 744163953Srrs sctp_m_freem(m_ack); 745163953Srrs return; 746163953Srrs } 747163953Srrs m_result = NULL; 748163953Srrs 749163953Srrs if (param_length > sizeof(aparam_buf)) { 750169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: param length (%u) larger than buffer size!\n", param_length); 751163953Srrs sctp_m_freem(m_ack); 752163953Srrs return; 753163953Srrs } 754163953Srrs if (param_length <= sizeof(struct sctp_paramhdr)) { 755169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: param length (%u) too short\n", param_length); 756163953Srrs sctp_m_freem(m_ack); 757163953Srrs } 758163953Srrs /* get the entire parameter */ 759163953Srrs aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, param_length, aparam_buf); 760163953Srrs if (aph == NULL) { 761169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: couldn't get entire param\n"); 762163953Srrs sctp_m_freem(m_ack); 763163953Srrs return; 764163953Srrs } 765163953Srrs switch (param_type) { 766163953Srrs case SCTP_ADD_IP_ADDRESS: 767163953Srrs asoc->peer_supports_asconf = 1; 768163953Srrs m_result = sctp_process_asconf_add_ip(m, aph, stcb, 769224641Stuexen (cnt < SCTP_BASE_SYSCTL(sctp_hb_maxburst)), error); 770224641Stuexen cnt++; 771163953Srrs break; 772163953Srrs case SCTP_DEL_IP_ADDRESS: 773163953Srrs asoc->peer_supports_asconf = 1; 774163953Srrs m_result = sctp_process_asconf_delete_ip(m, aph, stcb, 775163953Srrs error); 776163953Srrs break; 777163953Srrs case SCTP_ERROR_CAUSE_IND: 778163953Srrs /* not valid in an ASCONF chunk */ 779163953Srrs break; 780163953Srrs case SCTP_SET_PRIM_ADDR: 781163953Srrs asoc->peer_supports_asconf = 1; 782163953Srrs m_result = sctp_process_asconf_set_primary(m, aph, 783163953Srrs stcb, error); 784163953Srrs break; 785185694Srrs case SCTP_NAT_VTAGS: 786185694Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: sees a NAT VTAG state parameter\n"); 787185694Srrs break; 788163953Srrs case SCTP_SUCCESS_REPORT: 789163953Srrs /* not valid in an ASCONF chunk */ 790163953Srrs break; 791163953Srrs case SCTP_ULP_ADAPTATION: 792163953Srrs /* FIX */ 793163953Srrs break; 794163953Srrs default: 795163953Srrs if ((param_type & 0x8000) == 0) { 796163953Srrs /* Been told to STOP at this param */ 797163953Srrs asconf_limit = offset; 798163953Srrs /* 799163953Srrs * FIX FIX - We need to call 800163953Srrs * sctp_arethere_unrecognized_parameters() 801163953Srrs * to get a operr and send it for any 802163953Srrs * param's with the 0x4000 bit set OR do it 803163953Srrs * here ourselves... note we still must STOP 804163953Srrs * if the 0x8000 bit is clear. 805163953Srrs */ 806163953Srrs } 807163953Srrs /* unknown/invalid param type */ 808163953Srrs break; 809163953Srrs } /* switch */ 810163953Srrs 811163953Srrs /* add any (error) result to the reply mbuf chain */ 812163953Srrs if (m_result != NULL) { 813165647Srrs SCTP_BUF_NEXT(m_tail) = m_result; 814163953Srrs m_tail = m_result; 815163953Srrs /* update lengths, make sure it's aligned too */ 816165647Srrs SCTP_BUF_LEN(m_result) = SCTP_SIZE32(SCTP_BUF_LEN(m_result)); 817165647Srrs ack_cp->ch.chunk_length += SCTP_BUF_LEN(m_result); 818163953Srrs /* set flag to force success reports */ 819163953Srrs error = 1; 820163953Srrs } 821163953Srrs offset += SCTP_SIZE32(param_length); 822163953Srrs /* update remaining ASCONF message length to process */ 823163953Srrs if (offset >= asconf_limit) { 824163953Srrs /* no more data in the mbuf chain */ 825163953Srrs break; 826163953Srrs } 827163953Srrs /* get pointer to next asconf param */ 828163953Srrs aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, 829163953Srrs sizeof(struct sctp_asconf_paramhdr), 830163953Srrs (uint8_t *) & aparam_buf); 831163953Srrs if (aph == NULL) { 832163953Srrs /* can't get an asconf paramhdr */ 833169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: can't get asconf param hdr!\n"); 834163953Srrs /* FIX ME - add error here... */ 835163953Srrs } 836169420Srrs } 837163953Srrs 838163953Srrssend_reply: 839163953Srrs ack_cp->ch.chunk_length = htons(ack_cp->ch.chunk_length); 840163953Srrs /* save the ASCONF-ACK reply */ 841179783Srrs ack = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_asconf_ack), 842171990Srrs struct sctp_asconf_ack); 843171990Srrs if (ack == NULL) { 844171990Srrs sctp_m_freem(m_ack); 845171990Srrs return; 846171990Srrs } 847171990Srrs ack->serial_number = serial_num; 848171990Srrs ack->last_sent_to = NULL; 849171990Srrs ack->data = m_ack; 850209178Stuexen ack->len = 0; 851221249Stuexen for (n = m_ack; n != NULL; n = SCTP_BUF_NEXT(n)) { 852171990Srrs ack->len += SCTP_BUF_LEN(n); 853171990Srrs } 854171990Srrs TAILQ_INSERT_TAIL(&stcb->asoc.asconf_ack_sent, ack, next); 855163953Srrs 856163953Srrs /* see if last_control_chunk_from is set properly (use IP src addr) */ 857163953Srrs if (stcb->asoc.last_control_chunk_from == NULL) { 858163953Srrs /* 859163953Srrs * this could happen if the source address was just newly 860163953Srrs * added 861163953Srrs */ 862163953Srrs struct ip *iph; 863163953Srrs struct sctphdr *sh; 864163953Srrs struct sockaddr_storage from_store; 865163953Srrs struct sockaddr *from = (struct sockaddr *)&from_store; 866163953Srrs 867169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: looking up net for IP source address\n"); 868163953Srrs /* pullup already done, IP options already stripped */ 869163953Srrs iph = mtod(m, struct ip *); 870178251Srrs switch (iph->ip_v) { 871221249Stuexen#ifdef INET 872178251Srrs case IPVERSION: 873178251Srrs { 874178251Srrs struct sockaddr_in *from4; 875163953Srrs 876221249Stuexen sh = (struct sctphdr *)((caddr_t)iph + sizeof(*iph)); 877178251Srrs from4 = (struct sockaddr_in *)&from_store; 878178251Srrs bzero(from4, sizeof(*from4)); 879178251Srrs from4->sin_family = AF_INET; 880178251Srrs from4->sin_len = sizeof(struct sockaddr_in); 881178251Srrs from4->sin_addr.s_addr = iph->ip_src.s_addr; 882178251Srrs from4->sin_port = sh->src_port; 883178251Srrs break; 884178251Srrs } 885221249Stuexen#endif 886178251Srrs#ifdef INET6 887178251Srrs case IPV6_VERSION >> 4: 888178251Srrs { 889178251Srrs struct ip6_hdr *ip6; 890178251Srrs struct sockaddr_in6 *from6; 891163953Srrs 892178251Srrs ip6 = mtod(m, struct ip6_hdr *); 893221249Stuexen sh = (struct sctphdr *)((caddr_t)ip6 + sizeof(*ip6)); 894178251Srrs from6 = (struct sockaddr_in6 *)&from_store; 895178251Srrs bzero(from6, sizeof(*from6)); 896178251Srrs from6->sin6_family = AF_INET6; 897178251Srrs from6->sin6_len = sizeof(struct sockaddr_in6); 898178251Srrs from6->sin6_addr = ip6->ip6_src; 899178251Srrs from6->sin6_port = sh->src_port; 900178251Srrs /* 901178251Srrs * Get the scopes in properly to the sin6 902178251Srrs * addr's 903178251Srrs */ 904178251Srrs /* we probably don't need these operations */ 905178251Srrs (void)sa6_recoverscope(from6); 906180387Srrs sa6_embedscope(from6, 907197288Srrs MODULE_GLOBAL(ip6_use_defzone)); 908180387Srrs 909178251Srrs break; 910178251Srrs } 911178251Srrs#endif 912178251Srrs default: 913163953Srrs /* unknown address type */ 914163953Srrs from = NULL; 915163953Srrs } 916163953Srrs if (from != NULL) { 917169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "Looking for IP source: "); 918169420Srrs SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, from); 919163953Srrs /* look up the from address */ 920163953Srrs stcb->asoc.last_control_chunk_from = sctp_findnet(stcb, from); 921163953Srrs#ifdef SCTP_DEBUG 922169420Srrs if (stcb->asoc.last_control_chunk_from == NULL) 923169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: IP source address not found?!\n"); 924169420Srrs#endif 925163953Srrs } 926163953Srrs } 927163953Srrs} 928163953Srrs 929163953Srrs/* 930163953Srrs * does the address match? returns 0 if not, 1 if so 931163953Srrs */ 932163953Srrsstatic uint32_t 933163953Srrssctp_asconf_addr_match(struct sctp_asconf_addr *aa, struct sockaddr *sa) 934163953Srrs{ 935221249Stuexen switch (sa->sa_family) { 936163953Srrs#ifdef INET6 937221249Stuexen case AF_INET6: 938221249Stuexen { 939221249Stuexen /* XXX scopeid */ 940221249Stuexen struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; 941163953Srrs 942221249Stuexen if ((aa->ap.addrp.ph.param_type == SCTP_IPV6_ADDRESS) && 943221249Stuexen (memcmp(&aa->ap.addrp.addr, &sin6->sin6_addr, 944221249Stuexen sizeof(struct in6_addr)) == 0)) { 945221249Stuexen return (1); 946221249Stuexen } 947221249Stuexen break; 948163953Srrs } 949221249Stuexen#endif 950221249Stuexen#ifdef INET 951221249Stuexen case AF_INET: 952221249Stuexen { 953221249Stuexen struct sockaddr_in *sin = (struct sockaddr_in *)sa; 954163953Srrs 955221249Stuexen if ((aa->ap.addrp.ph.param_type == SCTP_IPV4_ADDRESS) && 956221249Stuexen (memcmp(&aa->ap.addrp.addr, &sin->sin_addr, 957221249Stuexen sizeof(struct in_addr)) == 0)) { 958221249Stuexen return (1); 959221249Stuexen } 960221249Stuexen break; 961163953Srrs } 962221249Stuexen#endif 963221249Stuexen default: 964221249Stuexen break; 965163953Srrs } 966163953Srrs return (0); 967163953Srrs} 968163953Srrs 969163953Srrs/* 970179157Srrs * does the address match? returns 0 if not, 1 if so 971179157Srrs */ 972179157Srrsstatic uint32_t 973221249Stuexensctp_addr_match(struct sctp_paramhdr *ph, struct sockaddr *sa) 974179157Srrs{ 975179157Srrs uint16_t param_type, param_length; 976179157Srrs 977221249Stuexen param_type = ntohs(ph->param_type); 978221249Stuexen param_length = ntohs(ph->param_length); 979221249Stuexen switch (sa->sa_family) { 980179157Srrs#ifdef INET6 981221249Stuexen case AF_INET6: 982221249Stuexen { 983221249Stuexen /* XXX scopeid */ 984221249Stuexen struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; 985221249Stuexen struct sctp_ipv6addr_param *v6addr; 986179157Srrs 987221249Stuexen v6addr = (struct sctp_ipv6addr_param *)ph; 988221249Stuexen if ((param_type == SCTP_IPV6_ADDRESS) && 989221249Stuexen param_length == sizeof(struct sctp_ipv6addr_param) && 990221249Stuexen (memcmp(&v6addr->addr, &sin6->sin6_addr, 991221249Stuexen sizeof(struct in6_addr)) == 0)) { 992221249Stuexen return (1); 993221249Stuexen } 994221249Stuexen break; 995179157Srrs } 996180955Srrs#endif 997221249Stuexen#ifdef INET 998221249Stuexen case AF_INET: 999221249Stuexen { 1000221249Stuexen struct sockaddr_in *sin = (struct sockaddr_in *)sa; 1001221249Stuexen struct sctp_ipv4addr_param *v4addr; 1002179157Srrs 1003221249Stuexen v4addr = (struct sctp_ipv4addr_param *)ph; 1004221249Stuexen if ((param_type == SCTP_IPV4_ADDRESS) && 1005221249Stuexen param_length == sizeof(struct sctp_ipv4addr_param) && 1006221249Stuexen (memcmp(&v4addr->addr, &sin->sin_addr, 1007221249Stuexen sizeof(struct in_addr)) == 0)) { 1008221249Stuexen return (1); 1009221249Stuexen } 1010221249Stuexen break; 1011179157Srrs } 1012221249Stuexen#endif 1013221249Stuexen default: 1014221249Stuexen break; 1015179157Srrs } 1016179157Srrs return (0); 1017179157Srrs} 1018179157Srrs 1019179157Srrs/* 1020163953Srrs * Cleanup for non-responded/OP ERR'd ASCONF 1021163953Srrs */ 1022163953Srrsvoid 1023163953Srrssctp_asconf_cleanup(struct sctp_tcb *stcb, struct sctp_nets *net) 1024163953Srrs{ 1025163953Srrs /* mark peer as ASCONF incapable */ 1026163953Srrs stcb->asoc.peer_supports_asconf = 0; 1027163953Srrs /* 1028163953Srrs * clear out any existing asconfs going out 1029163953Srrs */ 1030169655Srrs sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net, 1031169655Srrs SCTP_FROM_SCTP_ASCONF + SCTP_LOC_2); 1032179157Srrs stcb->asoc.asconf_seq_out_acked = stcb->asoc.asconf_seq_out; 1033163953Srrs /* remove the old ASCONF on our outbound queue */ 1034163953Srrs sctp_toss_old_asconf(stcb); 1035163953Srrs} 1036163953Srrs 1037163953Srrs/* 1038171858Srrs * cleanup any cached source addresses that may be topologically 1039171858Srrs * incorrect after a new address has been added to this interface. 1040171858Srrs */ 1041171858Srrsstatic void 1042171858Srrssctp_asconf_nets_cleanup(struct sctp_tcb *stcb, struct sctp_ifn *ifn) 1043171858Srrs{ 1044171858Srrs struct sctp_nets *net; 1045171858Srrs 1046171858Srrs /* 1047171858Srrs * Ideally, we want to only clear cached routes and source addresses 1048171858Srrs * that are topologically incorrect. But since there is no easy way 1049171858Srrs * to know whether the newly added address on the ifn would cause a 1050171858Srrs * routing change (i.e. a new egress interface would be chosen) 1051171858Srrs * without doing a new routing lookup and source address selection, 1052171858Srrs * we will (for now) just flush any cached route using a different 1053171858Srrs * ifn (and cached source addrs) and let output re-choose them 1054171858Srrs * during the next send on that net. 1055171858Srrs */ 1056171858Srrs TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 1057171858Srrs /* 1058171858Srrs * clear any cached route (and cached source address) if the 1059171858Srrs * route's interface is NOT the same as the address change. 1060171858Srrs * If it's the same interface, just clear the cached source 1061171858Srrs * address. 1062171858Srrs */ 1063171858Srrs if (SCTP_ROUTE_HAS_VALID_IFN(&net->ro) && 1064209178Stuexen ((ifn == NULL) || 1065209178Stuexen (SCTP_GET_IF_INDEX_FROM_ROUTE(&net->ro) != ifn->ifn_index))) { 1066171858Srrs /* clear any cached route */ 1067171858Srrs RTFREE(net->ro.ro_rt); 1068171858Srrs net->ro.ro_rt = NULL; 1069171858Srrs } 1070171858Srrs /* clear any cached source address */ 1071171858Srrs if (net->src_addr_selected) { 1072171858Srrs sctp_free_ifa(net->ro._s_addr); 1073171858Srrs net->ro._s_addr = NULL; 1074171858Srrs net->src_addr_selected = 0; 1075171858Srrs } 1076171858Srrs } 1077171858Srrs} 1078171858Srrs 1079172091Srrs 1080172091Srrsvoid 1081172091Srrssctp_assoc_immediate_retrans(struct sctp_tcb *stcb, struct sctp_nets *dstnet) 1082172091Srrs{ 1083172091Srrs int error; 1084172091Srrs 1085172118Srrs if (dstnet->dest_state & SCTP_ADDR_UNCONFIRMED) { 1086172118Srrs return; 1087172118Srrs } 1088172091Srrs if (stcb->asoc.deleted_primary == NULL) { 1089172091Srrs return; 1090172091Srrs } 1091172091Srrs if (!TAILQ_EMPTY(&stcb->asoc.sent_queue)) { 1092172157Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "assoc_immediate_retrans: Deleted primary is "); 1093172091Srrs SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &stcb->asoc.deleted_primary->ro._l_addr.sa); 1094172091Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "Current Primary is "); 1095172091Srrs SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &stcb->asoc.primary_destination->ro._l_addr.sa); 1096172091Srrs sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, 1097172091Srrs stcb->asoc.deleted_primary, 1098172091Srrs SCTP_FROM_SCTP_TIMER + SCTP_LOC_8); 1099172091Srrs stcb->asoc.num_send_timers_up--; 1100172091Srrs if (stcb->asoc.num_send_timers_up < 0) { 1101172091Srrs stcb->asoc.num_send_timers_up = 0; 1102172091Srrs } 1103172091Srrs SCTP_TCB_LOCK_ASSERT(stcb); 1104172091Srrs error = sctp_t3rxt_timer(stcb->sctp_ep, stcb, 1105172091Srrs stcb->asoc.deleted_primary); 1106172091Srrs if (error) { 1107172091Srrs SCTP_INP_DECR_REF(stcb->sctp_ep); 1108172091Srrs return; 1109172091Srrs } 1110172091Srrs SCTP_TCB_LOCK_ASSERT(stcb); 1111172091Srrs#ifdef SCTP_AUDITING_ENABLED 1112207099Stuexen sctp_auditing(4, stcb->sctp_ep, stcb, stcb->asoc.deleted_primary); 1113172091Srrs#endif 1114172091Srrs sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED); 1115172091Srrs if ((stcb->asoc.num_send_timers_up == 0) && 1116172091Srrs (stcb->asoc.sent_queue_cnt > 0)) { 1117172091Srrs struct sctp_tmit_chunk *chk; 1118172091Srrs 1119172091Srrs chk = TAILQ_FIRST(&stcb->asoc.sent_queue); 1120172091Srrs sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, 1121172091Srrs stcb, chk->whoTo); 1122172091Srrs } 1123172091Srrs } 1124172091Srrs return; 1125172091Srrs} 1126172091Srrs 1127171990Srrsstatic int 1128171990Srrs sctp_asconf_queue_mgmt(struct sctp_tcb *, struct sctp_ifa *, uint16_t); 1129171990Srrs 1130172091Srrsvoid 1131171990Srrssctp_net_immediate_retrans(struct sctp_tcb *stcb, struct sctp_nets *net) 1132171990Srrs{ 1133171990Srrs struct sctp_tmit_chunk *chk; 1134171990Srrs 1135172157Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "net_immediate_retrans: RTO is %d\n", net->RTO); 1136171990Srrs sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net, 1137171990Srrs SCTP_FROM_SCTP_TIMER + SCTP_LOC_5); 1138171990Srrs stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net); 1139171990Srrs net->error_count = 0; 1140171990Srrs TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) { 1141171990Srrs if (chk->whoTo == net) { 1142172091Srrs if (chk->sent < SCTP_DATAGRAM_RESEND) { 1143172091Srrs chk->sent = SCTP_DATAGRAM_RESEND; 1144172091Srrs sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 1145172396Srrs sctp_flight_size_decrease(chk); 1146172396Srrs sctp_total_flight_decrease(stcb, chk); 1147172396Srrs net->marked_retrans++; 1148172396Srrs stcb->asoc.marked_retrans++; 1149172091Srrs } 1150171990Srrs } 1151171990Srrs } 1152172396Srrs if (net->marked_retrans) { 1153172396Srrs sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED); 1154172396Srrs } 1155171990Srrs} 1156171990Srrs 1157171990Srrsstatic void 1158171990Srrssctp_path_check_and_react(struct sctp_tcb *stcb, struct sctp_ifa *newifa) 1159171990Srrs{ 1160171990Srrs struct sctp_nets *net; 1161171990Srrs int addrnum, changed; 1162171990Srrs 1163171990Srrs /* 1164171990Srrs * If number of local valid addresses is 1, the valid address is 1165206137Stuexen * probably newly added address. Several valid addresses in this 1166171990Srrs * association. A source address may not be changed. Additionally, 1167171990Srrs * they can be configured on a same interface as "alias" addresses. 1168171990Srrs * (by micchie) 1169171990Srrs */ 1170171990Srrs addrnum = sctp_local_addr_count(stcb); 1171171990Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "p_check_react(): %d local addresses\n", 1172171990Srrs addrnum); 1173171990Srrs if (addrnum == 1) { 1174171990Srrs TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 1175171990Srrs /* clear any cached route and source address */ 1176171990Srrs if (net->ro.ro_rt) { 1177171990Srrs RTFREE(net->ro.ro_rt); 1178171990Srrs net->ro.ro_rt = NULL; 1179171990Srrs } 1180171990Srrs if (net->src_addr_selected) { 1181171990Srrs sctp_free_ifa(net->ro._s_addr); 1182171990Srrs net->ro._s_addr = NULL; 1183171990Srrs net->src_addr_selected = 0; 1184171990Srrs } 1185171990Srrs /* Retransmit unacknowledged DATA chunks immediately */ 1186171990Srrs if (sctp_is_mobility_feature_on(stcb->sctp_ep, 1187171990Srrs SCTP_MOBILITY_FASTHANDOFF)) { 1188171990Srrs sctp_net_immediate_retrans(stcb, net); 1189171990Srrs } 1190171990Srrs /* also, SET PRIMARY is maybe already sent */ 1191171990Srrs } 1192171990Srrs return; 1193171990Srrs } 1194171990Srrs /* Multiple local addresses exsist in the association. */ 1195171990Srrs TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 1196171990Srrs /* clear any cached route and source address */ 1197171990Srrs if (net->ro.ro_rt) { 1198171990Srrs RTFREE(net->ro.ro_rt); 1199171990Srrs net->ro.ro_rt = NULL; 1200171990Srrs } 1201171990Srrs if (net->src_addr_selected) { 1202171990Srrs sctp_free_ifa(net->ro._s_addr); 1203171990Srrs net->ro._s_addr = NULL; 1204171990Srrs net->src_addr_selected = 0; 1205171990Srrs } 1206171990Srrs /* 1207171990Srrs * Check if the nexthop is corresponding to the new address. 1208171990Srrs * If the new address is corresponding to the current 1209206137Stuexen * nexthop, the path will be changed. If the new address is 1210171990Srrs * NOT corresponding to the current nexthop, the path will 1211171990Srrs * not be changed. 1212171990Srrs */ 1213171990Srrs SCTP_RTALLOC((sctp_route_t *) & net->ro, 1214171990Srrs stcb->sctp_ep->def_vrf_id); 1215171990Srrs if (net->ro.ro_rt == NULL) 1216171990Srrs continue; 1217171990Srrs 1218172137Srrs changed = 0; 1219221249Stuexen switch (net->ro._l_addr.sa.sa_family) { 1220221249Stuexen#ifdef INET 1221221249Stuexen case AF_INET: 1222221249Stuexen if (sctp_v4src_match_nexthop(newifa, (sctp_route_t *) & net->ro)) { 1223171990Srrs changed = 1; 1224221249Stuexen } 1225221249Stuexen break; 1226221249Stuexen#endif 1227178251Srrs#ifdef INET6 1228221249Stuexen case AF_INET6: 1229171990Srrs if (sctp_v6src_match_nexthop( 1230221249Stuexen &newifa->address.sin6, (sctp_route_t *) & net->ro)) { 1231171990Srrs changed = 1; 1232221249Stuexen } 1233221249Stuexen break; 1234221249Stuexen#endif 1235221249Stuexen default: 1236221249Stuexen break; 1237171990Srrs } 1238171990Srrs /* 1239171990Srrs * if the newly added address does not relate routing 1240171990Srrs * information, we skip. 1241171990Srrs */ 1242171990Srrs if (changed == 0) 1243171990Srrs continue; 1244171990Srrs /* Retransmit unacknowledged DATA chunks immediately */ 1245171990Srrs if (sctp_is_mobility_feature_on(stcb->sctp_ep, 1246171990Srrs SCTP_MOBILITY_FASTHANDOFF)) { 1247171990Srrs sctp_net_immediate_retrans(stcb, net); 1248171990Srrs } 1249171990Srrs /* Send SET PRIMARY for this new address */ 1250171990Srrs if (net == stcb->asoc.primary_destination) { 1251171990Srrs (void)sctp_asconf_queue_mgmt(stcb, newifa, 1252171990Srrs SCTP_SET_PRIM_ADDR); 1253171990Srrs } 1254171990Srrs } 1255171990Srrs} 1256171990Srrs 1257171858Srrs/* 1258163953Srrs * process an ADD/DELETE IP ack from peer. 1259171572Srrs * addr: corresponding sctp_ifa to the address being added/deleted. 1260163953Srrs * type: SCTP_ADD_IP_ADDRESS or SCTP_DEL_IP_ADDRESS. 1261163953Srrs * flag: 1=success, 0=failure. 1262163953Srrs */ 1263163953Srrsstatic void 1264228653Stuexensctp_asconf_addr_mgmt_ack(struct sctp_tcb *stcb, struct sctp_ifa *addr, uint32_t flag) 1265163953Srrs{ 1266163953Srrs /* 1267163953Srrs * do the necessary asoc list work- if we get a failure indication, 1268171858Srrs * leave the address on the assoc's restricted list. If we get a 1269171858Srrs * success indication, remove the address from the restricted list. 1270163953Srrs */ 1271163953Srrs /* 1272163953Srrs * Note: this will only occur for ADD_IP_ADDRESS, since 1273163953Srrs * DEL_IP_ADDRESS is never actually added to the list... 1274163953Srrs */ 1275163953Srrs if (flag) { 1276171572Srrs /* success case, so remove from the restricted list */ 1277171572Srrs sctp_del_local_addr_restricted(stcb, addr); 1278171858Srrs 1279172190Srrs if (sctp_is_mobility_feature_on(stcb->sctp_ep, 1280172396Srrs SCTP_MOBILITY_BASE) || 1281172396Srrs sctp_is_mobility_feature_on(stcb->sctp_ep, 1282172396Srrs SCTP_MOBILITY_FASTHANDOFF)) { 1283171990Srrs sctp_path_check_and_react(stcb, addr); 1284171990Srrs return; 1285171990Srrs } 1286172190Srrs /* clear any cached/topologically incorrect source addresses */ 1287171858Srrs sctp_asconf_nets_cleanup(stcb, addr->ifn_p); 1288163953Srrs } 1289163953Srrs /* else, leave it on the list */ 1290163953Srrs} 1291163953Srrs 1292163953Srrs/* 1293171572Srrs * add an asconf add/delete/set primary IP address parameter to the queue. 1294163953Srrs * type = SCTP_ADD_IP_ADDRESS, SCTP_DEL_IP_ADDRESS, SCTP_SET_PRIM_ADDR. 1295171572Srrs * returns 0 if queued, -1 if not queued/removed. 1296171572Srrs * NOTE: if adding, but a delete for the same address is already scheduled 1297171572Srrs * (and not yet sent out), simply remove it from queue. Same for deleting 1298171572Srrs * an address already scheduled for add. If a duplicate operation is found, 1299171572Srrs * ignore the new one. 1300163953Srrs */ 1301171572Srrsstatic int 1302171572Srrssctp_asconf_queue_mgmt(struct sctp_tcb *stcb, struct sctp_ifa *ifa, 1303171477Srrs uint16_t type) 1304163953Srrs{ 1305163953Srrs struct sctp_asconf_addr *aa, *aa_next; 1306163953Srrs struct sockaddr *sa; 1307163953Srrs 1308163953Srrs /* make sure the request isn't already in the queue */ 1309216822Stuexen TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) { 1310163953Srrs /* address match? */ 1311167598Srrs if (sctp_asconf_addr_match(aa, &ifa->address.sa) == 0) 1312163953Srrs continue; 1313179157Srrs /* 1314179157Srrs * is the request already in queue but not sent? pass the 1315179157Srrs * request already sent in order to resolve the following 1316179157Srrs * case: 1. arrival of ADD, then sent 2. arrival of DEL. we 1317179157Srrs * can't remove the ADD request already sent 3. arrival of 1318179157Srrs * ADD 1319179157Srrs */ 1320179157Srrs if (aa->ap.aph.ph.param_type == type && aa->sent == 0) { 1321163953Srrs return (-1); 1322163953Srrs } 1323163953Srrs /* is the negative request already in queue, and not sent */ 1324171572Srrs if ((aa->sent == 0) && (type == SCTP_ADD_IP_ADDRESS) && 1325171572Srrs (aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS)) { 1326171572Srrs /* add requested, delete already queued */ 1327163953Srrs TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next); 1328171572Srrs /* remove the ifa from the restricted list */ 1329171572Srrs sctp_del_local_addr_restricted(stcb, ifa); 1330171572Srrs /* free the asconf param */ 1331170091Srrs SCTP_FREE(aa, SCTP_M_ASC_ADDR); 1332171572Srrs SCTPDBG(SCTP_DEBUG_ASCONF2, "asconf_queue_mgmt: add removes queued entry\n"); 1333163953Srrs return (-1); 1334163953Srrs } 1335171572Srrs if ((aa->sent == 0) && (type == SCTP_DEL_IP_ADDRESS) && 1336171572Srrs (aa->ap.aph.ph.param_type == SCTP_ADD_IP_ADDRESS)) { 1337171572Srrs /* delete requested, add already queued */ 1338171572Srrs TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next); 1339171572Srrs /* remove the aa->ifa from the restricted list */ 1340171572Srrs sctp_del_local_addr_restricted(stcb, aa->ifa); 1341171572Srrs /* free the asconf param */ 1342171572Srrs SCTP_FREE(aa, SCTP_M_ASC_ADDR); 1343171572Srrs SCTPDBG(SCTP_DEBUG_ASCONF2, "asconf_queue_mgmt: delete removes queued entry\n"); 1344171572Srrs return (-1); 1345171572Srrs } 1346163953Srrs } /* for each aa */ 1347163953Srrs 1348163953Srrs /* adding new request to the queue */ 1349171572Srrs SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa), 1350171572Srrs SCTP_M_ASC_ADDR); 1351163953Srrs if (aa == NULL) { 1352163953Srrs /* didn't get memory */ 1353171572Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "asconf_queue_mgmt: failed to get memory!\n"); 1354163953Srrs return (-1); 1355163953Srrs } 1356185694Srrs aa->special_del = 0; 1357163953Srrs /* fill in asconf address parameter fields */ 1358163953Srrs /* top level elements are "networked" during send */ 1359163953Srrs aa->ap.aph.ph.param_type = type; 1360163953Srrs aa->ifa = ifa; 1361168299Srrs atomic_add_int(&ifa->refcount, 1); 1362163953Srrs /* correlation_id filled in during send routine later... */ 1363221249Stuexen switch (ifa->address.sa.sa_family) { 1364221249Stuexen#ifdef INET6 1365221249Stuexen case AF_INET6: 1366221249Stuexen { 1367221249Stuexen struct sockaddr_in6 *sin6; 1368163953Srrs 1369221249Stuexen sin6 = (struct sockaddr_in6 *)&ifa->address.sa; 1370221249Stuexen sa = (struct sockaddr *)sin6; 1371221249Stuexen aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS; 1372221249Stuexen aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param)); 1373221249Stuexen aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + 1374221249Stuexen sizeof(struct sctp_ipv6addr_param); 1375221249Stuexen memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr, 1376221249Stuexen sizeof(struct in6_addr)); 1377221249Stuexen break; 1378221249Stuexen } 1379221249Stuexen#endif 1380221249Stuexen#ifdef INET 1381221249Stuexen case AF_INET: 1382221249Stuexen { 1383221249Stuexen struct sockaddr_in *sin; 1384163953Srrs 1385221249Stuexen sin = (struct sockaddr_in *)&ifa->address.sa; 1386221249Stuexen sa = (struct sockaddr *)sin; 1387221249Stuexen aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS; 1388221249Stuexen aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param)); 1389221249Stuexen aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + 1390221249Stuexen sizeof(struct sctp_ipv4addr_param); 1391221249Stuexen memcpy(&aa->ap.addrp.addr, &sin->sin_addr, 1392221249Stuexen sizeof(struct in_addr)); 1393221249Stuexen break; 1394221249Stuexen } 1395221249Stuexen#endif 1396221249Stuexen default: 1397163953Srrs /* invalid family! */ 1398170091Srrs SCTP_FREE(aa, SCTP_M_ASC_ADDR); 1399172190Srrs sctp_free_ifa(ifa); 1400163953Srrs return (-1); 1401163953Srrs } 1402163953Srrs aa->sent = 0; /* clear sent flag */ 1403163953Srrs 1404179157Srrs TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next); 1405163953Srrs#ifdef SCTP_DEBUG 1406218232Srrs if (SCTP_BASE_SYSCTL(sctp_debug_on) & SCTP_DEBUG_ASCONF2) { 1407179157Srrs if (type == SCTP_ADD_IP_ADDRESS) { 1408179157Srrs SCTP_PRINTF("asconf_queue_mgmt: inserted asconf ADD_IP_ADDRESS: "); 1409179157Srrs SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa); 1410179157Srrs } else if (type == SCTP_DEL_IP_ADDRESS) { 1411179157Srrs SCTP_PRINTF("asconf_queue_mgmt: appended asconf DEL_IP_ADDRESS: "); 1412179157Srrs SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa); 1413179157Srrs } else { 1414179157Srrs SCTP_PRINTF("asconf_queue_mgmt: appended asconf SET_PRIM_ADDR: "); 1415179157Srrs SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa); 1416163953Srrs } 1417179157Srrs } 1418169420Srrs#endif 1419163953Srrs 1420163953Srrs return (0); 1421163953Srrs} 1422163953Srrs 1423171572Srrs 1424163953Srrs/* 1425171572Srrs * add an asconf operation for the given ifa and type. 1426171572Srrs * type = SCTP_ADD_IP_ADDRESS, SCTP_DEL_IP_ADDRESS, SCTP_SET_PRIM_ADDR. 1427171572Srrs * returns 0 if completed, -1 if not completed, 1 if immediate send is 1428171572Srrs * advisable. 1429171572Srrs */ 1430171572Srrsstatic int 1431171572Srrssctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa, 1432171572Srrs uint16_t type) 1433171572Srrs{ 1434171572Srrs uint32_t status; 1435171572Srrs int pending_delete_queued = 0; 1436171572Srrs 1437171572Srrs /* see if peer supports ASCONF */ 1438171572Srrs if (stcb->asoc.peer_supports_asconf == 0) { 1439171572Srrs return (-1); 1440171572Srrs } 1441171572Srrs /* 1442171572Srrs * if this is deleting the last address from the assoc, mark it as 1443171572Srrs * pending. 1444171572Srrs */ 1445171572Srrs if ((type == SCTP_DEL_IP_ADDRESS) && !stcb->asoc.asconf_del_pending && 1446171572Srrs (sctp_local_addr_count(stcb) < 2)) { 1447171572Srrs /* set the pending delete info only */ 1448171572Srrs stcb->asoc.asconf_del_pending = 1; 1449171572Srrs stcb->asoc.asconf_addr_del_pending = ifa; 1450171572Srrs atomic_add_int(&ifa->refcount, 1); 1451171572Srrs SCTPDBG(SCTP_DEBUG_ASCONF2, 1452171572Srrs "asconf_queue_add: mark delete last address pending\n"); 1453171572Srrs return (-1); 1454171572Srrs } 1455179157Srrs /* queue an asconf parameter */ 1456179157Srrs status = sctp_asconf_queue_mgmt(stcb, ifa, type); 1457179157Srrs 1458171572Srrs /* 1459171572Srrs * if this is an add, and there is a delete also pending (i.e. the 1460171572Srrs * last local address is being changed), queue the pending delete 1461171572Srrs * too. 1462171572Srrs */ 1463179157Srrs if ((type == SCTP_ADD_IP_ADDRESS) && stcb->asoc.asconf_del_pending && (status == 0)) { 1464171572Srrs /* queue in the pending delete */ 1465171572Srrs if (sctp_asconf_queue_mgmt(stcb, 1466171572Srrs stcb->asoc.asconf_addr_del_pending, 1467171572Srrs SCTP_DEL_IP_ADDRESS) == 0) { 1468171572Srrs SCTPDBG(SCTP_DEBUG_ASCONF2, "asconf_queue_add: queing pending delete\n"); 1469171572Srrs pending_delete_queued = 1; 1470171572Srrs /* clear out the pending delete info */ 1471171572Srrs stcb->asoc.asconf_del_pending = 0; 1472171572Srrs sctp_free_ifa(stcb->asoc.asconf_addr_del_pending); 1473171572Srrs stcb->asoc.asconf_addr_del_pending = NULL; 1474171572Srrs } 1475171572Srrs } 1476179157Srrs if (pending_delete_queued) { 1477171572Srrs struct sctp_nets *net; 1478171572Srrs 1479171572Srrs /* 1480171572Srrs * since we know that the only/last address is now being 1481171572Srrs * changed in this case, reset the cwnd/rto on all nets to 1482171572Srrs * start as a new address and path. Also clear the error 1483171572Srrs * counts to give the assoc the best chance to complete the 1484171572Srrs * address change. 1485171572Srrs */ 1486171572Srrs TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 1487171572Srrs stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, 1488171572Srrs net); 1489171572Srrs net->RTO = 0; 1490171572Srrs net->error_count = 0; 1491171572Srrs } 1492171572Srrs stcb->asoc.overall_error_count = 0; 1493179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 1494171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 1495171943Srrs stcb->asoc.overall_error_count, 1496171943Srrs 0, 1497171943Srrs SCTP_FROM_SCTP_ASCONF, 1498171943Srrs __LINE__); 1499171943Srrs } 1500171572Srrs /* queue in an advisory set primary too */ 1501171572Srrs (void)sctp_asconf_queue_mgmt(stcb, ifa, SCTP_SET_PRIM_ADDR); 1502171572Srrs /* let caller know we should send this out immediately */ 1503171572Srrs status = 1; 1504171572Srrs } 1505171572Srrs return (status); 1506171572Srrs} 1507171572Srrs 1508172190Srrs/*- 1509172190Srrs * add an asconf delete IP address parameter to the queue by sockaddr and 1510172190Srrs * possibly with no sctp_ifa available. This is only called by the routine 1511172190Srrs * that checks the addresses in an INIT-ACK against the current address list. 1512163953Srrs * returns 0 if completed, non-zero if not completed. 1513172190Srrs * NOTE: if an add is already scheduled (and not yet sent out), simply 1514172190Srrs * remove it from queue. If a duplicate operation is found, ignore the 1515172190Srrs * new one. 1516163953Srrs */ 1517171572Srrsstatic int 1518172190Srrssctp_asconf_queue_sa_delete(struct sctp_tcb *stcb, struct sockaddr *sa) 1519163953Srrs{ 1520168299Srrs struct sctp_ifa *ifa; 1521163953Srrs struct sctp_asconf_addr *aa, *aa_next; 1522167598Srrs uint32_t vrf_id; 1523163953Srrs 1524169420Srrs if (stcb == NULL) { 1525169420Srrs return (-1); 1526169420Srrs } 1527163953Srrs /* see if peer supports ASCONF */ 1528163953Srrs if (stcb->asoc.peer_supports_asconf == 0) { 1529163953Srrs return (-1); 1530163953Srrs } 1531163953Srrs /* make sure the request isn't already in the queue */ 1532216822Stuexen TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) { 1533163953Srrs /* address match? */ 1534163953Srrs if (sctp_asconf_addr_match(aa, sa) == 0) 1535163953Srrs continue; 1536163953Srrs /* is the request already in queue (sent or not) */ 1537172190Srrs if (aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS) { 1538163953Srrs return (-1); 1539163953Srrs } 1540163953Srrs /* is the negative request already in queue, and not sent */ 1541163953Srrs if (aa->sent == 1) 1542163953Srrs continue; 1543172190Srrs if (aa->ap.aph.ph.param_type == SCTP_ADD_IP_ADDRESS) { 1544172190Srrs /* add already queued, so remove existing entry */ 1545163953Srrs TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next); 1546171572Srrs sctp_del_local_addr_restricted(stcb, aa->ifa); 1547163953Srrs /* free the entry */ 1548170091Srrs SCTP_FREE(aa, SCTP_M_ASC_ADDR); 1549163953Srrs return (-1); 1550163953Srrs } 1551163953Srrs } /* for each aa */ 1552172190Srrs 1553172190Srrs /* find any existing ifa-- NOTE ifa CAN be allowed to be NULL */ 1554168299Srrs if (stcb) { 1555168299Srrs vrf_id = stcb->asoc.vrf_id; 1556168299Srrs } else { 1557168299Srrs vrf_id = SCTP_DEFAULT_VRFID; 1558168299Srrs } 1559172190Srrs ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED); 1560163953Srrs 1561163953Srrs /* adding new request to the queue */ 1562171572Srrs SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa), 1563171572Srrs SCTP_M_ASC_ADDR); 1564163953Srrs if (aa == NULL) { 1565163953Srrs /* didn't get memory */ 1566169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 1567172190Srrs "sctp_asconf_queue_sa_delete: failed to get memory!\n"); 1568163953Srrs return (-1); 1569163953Srrs } 1570185694Srrs aa->special_del = 0; 1571163953Srrs /* fill in asconf address parameter fields */ 1572163953Srrs /* top level elements are "networked" during send */ 1573172190Srrs aa->ap.aph.ph.param_type = SCTP_DEL_IP_ADDRESS; 1574168299Srrs aa->ifa = ifa; 1575172190Srrs if (ifa) 1576172190Srrs atomic_add_int(&ifa->refcount, 1); 1577163953Srrs /* correlation_id filled in during send routine later... */ 1578221249Stuexen switch (sa->sa_family) { 1579221249Stuexen#ifdef INET6 1580221249Stuexen case AF_INET6: 1581221249Stuexen { 1582221249Stuexen /* IPv6 address */ 1583221249Stuexen struct sockaddr_in6 *sin6; 1584163953Srrs 1585221249Stuexen sin6 = (struct sockaddr_in6 *)sa; 1586221249Stuexen aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS; 1587221249Stuexen aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param)); 1588221249Stuexen aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv6addr_param); 1589221249Stuexen memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr, 1590221249Stuexen sizeof(struct in6_addr)); 1591221249Stuexen break; 1592221249Stuexen } 1593221249Stuexen#endif 1594221249Stuexen#ifdef INET 1595221249Stuexen case AF_INET: 1596221249Stuexen { 1597221249Stuexen /* IPv4 address */ 1598221249Stuexen struct sockaddr_in *sin = (struct sockaddr_in *)sa; 1599163953Srrs 1600221249Stuexen aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS; 1601221249Stuexen aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param)); 1602221249Stuexen aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv4addr_param); 1603221249Stuexen memcpy(&aa->ap.addrp.addr, &sin->sin_addr, 1604221249Stuexen sizeof(struct in_addr)); 1605221249Stuexen break; 1606221249Stuexen } 1607221249Stuexen#endif 1608221249Stuexen default: 1609163953Srrs /* invalid family! */ 1610170091Srrs SCTP_FREE(aa, SCTP_M_ASC_ADDR); 1611172190Srrs if (ifa) 1612172190Srrs sctp_free_ifa(ifa); 1613163953Srrs return (-1); 1614163953Srrs } 1615163953Srrs aa->sent = 0; /* clear sent flag */ 1616163953Srrs 1617172190Srrs /* delete goes to the back of the queue */ 1618172190Srrs TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next); 1619163953Srrs 1620172218Srrs /* sa_ignore MEMLEAK {memory is put on the tailq} */ 1621163953Srrs return (0); 1622163953Srrs} 1623163953Srrs 1624163953Srrs/* 1625163953Srrs * find a specific asconf param on our "sent" queue 1626163953Srrs */ 1627163953Srrsstatic struct sctp_asconf_addr * 1628163953Srrssctp_asconf_find_param(struct sctp_tcb *stcb, uint32_t correlation_id) 1629163953Srrs{ 1630163953Srrs struct sctp_asconf_addr *aa; 1631163953Srrs 1632163953Srrs TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) { 1633163953Srrs if (aa->ap.aph.correlation_id == correlation_id && 1634163953Srrs aa->sent == 1) { 1635163953Srrs /* found it */ 1636163953Srrs return (aa); 1637163953Srrs } 1638163953Srrs } 1639163953Srrs /* didn't find it */ 1640163953Srrs return (NULL); 1641163953Srrs} 1642163953Srrs 1643163953Srrs/* 1644163953Srrs * process an SCTP_ERROR_CAUSE_IND for a ASCONF-ACK parameter and do 1645163953Srrs * notifications based on the error response 1646163953Srrs */ 1647163953Srrsstatic void 1648163953Srrssctp_asconf_process_error(struct sctp_tcb *stcb, 1649163953Srrs struct sctp_asconf_paramhdr *aph) 1650163953Srrs{ 1651163953Srrs struct sctp_error_cause *eh; 1652163953Srrs struct sctp_paramhdr *ph; 1653163953Srrs uint16_t param_type; 1654163953Srrs uint16_t error_code; 1655163953Srrs 1656163953Srrs eh = (struct sctp_error_cause *)(aph + 1); 1657163953Srrs ph = (struct sctp_paramhdr *)(eh + 1); 1658163953Srrs /* validate lengths */ 1659163953Srrs if (htons(eh->length) + sizeof(struct sctp_error_cause) > 1660163953Srrs htons(aph->ph.param_length)) { 1661163953Srrs /* invalid error cause length */ 1662169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 1663169420Srrs "asconf_process_error: cause element too long\n"); 1664163953Srrs return; 1665163953Srrs } 1666163953Srrs if (htons(ph->param_length) + sizeof(struct sctp_paramhdr) > 1667163953Srrs htons(eh->length)) { 1668163953Srrs /* invalid included TLV length */ 1669169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 1670169420Srrs "asconf_process_error: included TLV too long\n"); 1671163953Srrs return; 1672163953Srrs } 1673163953Srrs /* which error code ? */ 1674163953Srrs error_code = ntohs(eh->code); 1675163953Srrs param_type = ntohs(aph->ph.param_type); 1676163953Srrs /* FIX: this should go back up the REMOTE_ERROR ULP notify */ 1677163953Srrs switch (error_code) { 1678163953Srrs case SCTP_CAUSE_RESOURCE_SHORTAGE: 1679163953Srrs /* we allow ourselves to "try again" for this error */ 1680163953Srrs break; 1681163953Srrs default: 1682163953Srrs /* peer can't handle it... */ 1683163953Srrs switch (param_type) { 1684163953Srrs case SCTP_ADD_IP_ADDRESS: 1685163953Srrs case SCTP_DEL_IP_ADDRESS: 1686163953Srrs stcb->asoc.peer_supports_asconf = 0; 1687163953Srrs break; 1688163953Srrs case SCTP_SET_PRIM_ADDR: 1689163953Srrs stcb->asoc.peer_supports_asconf = 0; 1690163953Srrs break; 1691163953Srrs default: 1692163953Srrs break; 1693163953Srrs } 1694163953Srrs } 1695163953Srrs} 1696163953Srrs 1697163953Srrs/* 1698171477Srrs * process an asconf queue param. 1699171477Srrs * aparam: parameter to process, will be removed from the queue. 1700171477Srrs * flag: 1=success case, 0=failure case 1701163953Srrs */ 1702163953Srrsstatic void 1703163953Srrssctp_asconf_process_param_ack(struct sctp_tcb *stcb, 1704163953Srrs struct sctp_asconf_addr *aparam, uint32_t flag) 1705163953Srrs{ 1706163953Srrs uint16_t param_type; 1707163953Srrs 1708163953Srrs /* process this param */ 1709163953Srrs param_type = aparam->ap.aph.ph.param_type; 1710163953Srrs switch (param_type) { 1711163953Srrs case SCTP_ADD_IP_ADDRESS: 1712169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 1713169420Srrs "process_param_ack: added IP address\n"); 1714228653Stuexen sctp_asconf_addr_mgmt_ack(stcb, aparam->ifa, flag); 1715163953Srrs break; 1716163953Srrs case SCTP_DEL_IP_ADDRESS: 1717169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 1718169420Srrs "process_param_ack: deleted IP address\n"); 1719163953Srrs /* nothing really to do... lists already updated */ 1720163953Srrs break; 1721163953Srrs case SCTP_SET_PRIM_ADDR: 1722179157Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 1723179157Srrs "process_param_ack: set primary IP address\n"); 1724163953Srrs /* nothing to do... peer may start using this addr */ 1725163953Srrs if (flag == 0) 1726163953Srrs stcb->asoc.peer_supports_asconf = 0; 1727163953Srrs break; 1728163953Srrs default: 1729163953Srrs /* should NEVER happen */ 1730163953Srrs break; 1731163953Srrs } 1732163953Srrs 1733163953Srrs /* remove the param and free it */ 1734163953Srrs TAILQ_REMOVE(&stcb->asoc.asconf_queue, aparam, next); 1735172190Srrs if (aparam->ifa) 1736172190Srrs sctp_free_ifa(aparam->ifa); 1737170091Srrs SCTP_FREE(aparam, SCTP_M_ASC_ADDR); 1738163953Srrs} 1739163953Srrs 1740163953Srrs/* 1741163953Srrs * cleanup from a bad asconf ack parameter 1742163953Srrs */ 1743163953Srrsstatic void 1744163953Srrssctp_asconf_ack_clear(struct sctp_tcb *stcb) 1745163953Srrs{ 1746163953Srrs /* assume peer doesn't really know how to do asconfs */ 1747163953Srrs stcb->asoc.peer_supports_asconf = 0; 1748163953Srrs /* XXX we could free the pending queue here */ 1749163953Srrs} 1750163953Srrs 1751163953Srrsvoid 1752163953Srrssctp_handle_asconf_ack(struct mbuf *m, int offset, 1753163953Srrs struct sctp_asconf_ack_chunk *cp, struct sctp_tcb *stcb, 1754172190Srrs struct sctp_nets *net, int *abort_no_unlock) 1755163953Srrs{ 1756163953Srrs struct sctp_association *asoc; 1757163953Srrs uint32_t serial_num; 1758163953Srrs uint16_t ack_length; 1759163953Srrs struct sctp_asconf_paramhdr *aph; 1760163953Srrs struct sctp_asconf_addr *aa, *aa_next; 1761163953Srrs uint32_t last_error_id = 0; /* last error correlation id */ 1762163953Srrs uint32_t id; 1763163953Srrs struct sctp_asconf_addr *ap; 1764163953Srrs 1765163953Srrs /* asconf param buffer */ 1766166675Srrs uint8_t aparam_buf[SCTP_PARAM_BUFFER_SIZE]; 1767163953Srrs 1768163953Srrs /* verify minimum length */ 1769163953Srrs if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_asconf_ack_chunk)) { 1770169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 1771169420Srrs "handle_asconf_ack: chunk too small = %xh\n", 1772169420Srrs ntohs(cp->ch.chunk_length)); 1773163953Srrs return; 1774163953Srrs } 1775163953Srrs asoc = &stcb->asoc; 1776163953Srrs serial_num = ntohl(cp->serial_number); 1777163953Srrs 1778163953Srrs /* 1779163953Srrs * NOTE: we may want to handle this differently- currently, we will 1780163953Srrs * abort when we get an ack for the expected serial number + 1 (eg. 1781163953Srrs * we didn't send it), process an ack normally if it is the expected 1782163953Srrs * serial number, and re-send the previous ack for *ALL* other 1783163953Srrs * serial numbers 1784163953Srrs */ 1785163953Srrs 1786163953Srrs /* 1787163953Srrs * if the serial number is the next expected, but I didn't send it, 1788163953Srrs * abort the asoc, since someone probably just hijacked us... 1789163953Srrs */ 1790163953Srrs if (serial_num == (asoc->asconf_seq_out + 1)) { 1791169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf_ack: got unexpected next serial number! Aborting asoc!\n"); 1792163953Srrs sctp_abort_an_association(stcb->sctp_ep, stcb, 1793172090Srrs SCTP_CAUSE_ILLEGAL_ASCONF_ACK, NULL, SCTP_SO_NOT_LOCKED); 1794172190Srrs *abort_no_unlock = 1; 1795163953Srrs return; 1796163953Srrs } 1797179157Srrs if (serial_num != asoc->asconf_seq_out_acked + 1) { 1798163953Srrs /* got a duplicate/unexpected ASCONF-ACK */ 1799169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf_ack: got duplicate/unexpected serial number = %xh (expected = %xh)\n", 1800179157Srrs serial_num, asoc->asconf_seq_out_acked + 1); 1801163953Srrs return; 1802163953Srrs } 1803179157Srrs if (serial_num == asoc->asconf_seq_out - 1) { 1804179157Srrs /* stop our timer */ 1805179157Srrs sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net, 1806179157Srrs SCTP_FROM_SCTP_ASCONF + SCTP_LOC_3); 1807163953Srrs } 1808163953Srrs /* process the ASCONF-ACK contents */ 1809163953Srrs ack_length = ntohs(cp->ch.chunk_length) - 1810163953Srrs sizeof(struct sctp_asconf_ack_chunk); 1811163953Srrs offset += sizeof(struct sctp_asconf_ack_chunk); 1812163953Srrs /* process through all parameters */ 1813163953Srrs while (ack_length >= sizeof(struct sctp_asconf_paramhdr)) { 1814163953Srrs unsigned int param_length, param_type; 1815163953Srrs 1816163953Srrs /* get pointer to next asconf parameter */ 1817163953Srrs aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, 1818163953Srrs sizeof(struct sctp_asconf_paramhdr), aparam_buf); 1819163953Srrs if (aph == NULL) { 1820163953Srrs /* can't get an asconf paramhdr */ 1821163953Srrs sctp_asconf_ack_clear(stcb); 1822163953Srrs return; 1823163953Srrs } 1824163953Srrs param_type = ntohs(aph->ph.param_type); 1825163953Srrs param_length = ntohs(aph->ph.param_length); 1826163953Srrs if (param_length > ack_length) { 1827163953Srrs sctp_asconf_ack_clear(stcb); 1828163953Srrs return; 1829163953Srrs } 1830163953Srrs if (param_length < sizeof(struct sctp_paramhdr)) { 1831163953Srrs sctp_asconf_ack_clear(stcb); 1832163953Srrs return; 1833163953Srrs } 1834163953Srrs /* get the complete parameter... */ 1835163953Srrs if (param_length > sizeof(aparam_buf)) { 1836169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 1837169420Srrs "param length (%u) larger than buffer size!\n", param_length); 1838163953Srrs sctp_asconf_ack_clear(stcb); 1839163953Srrs return; 1840163953Srrs } 1841163953Srrs aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, param_length, aparam_buf); 1842163953Srrs if (aph == NULL) { 1843163953Srrs sctp_asconf_ack_clear(stcb); 1844163953Srrs return; 1845163953Srrs } 1846163953Srrs /* correlation_id is transparent to peer, no ntohl needed */ 1847163953Srrs id = aph->correlation_id; 1848163953Srrs 1849163953Srrs switch (param_type) { 1850163953Srrs case SCTP_ERROR_CAUSE_IND: 1851163953Srrs last_error_id = id; 1852163953Srrs /* find the corresponding asconf param in our queue */ 1853163953Srrs ap = sctp_asconf_find_param(stcb, id); 1854163953Srrs if (ap == NULL) { 1855163953Srrs /* hmm... can't find this in our queue! */ 1856163953Srrs break; 1857163953Srrs } 1858163953Srrs /* process the parameter, failed flag */ 1859163953Srrs sctp_asconf_process_param_ack(stcb, ap, 0); 1860163953Srrs /* process the error response */ 1861163953Srrs sctp_asconf_process_error(stcb, aph); 1862163953Srrs break; 1863163953Srrs case SCTP_SUCCESS_REPORT: 1864163953Srrs /* find the corresponding asconf param in our queue */ 1865163953Srrs ap = sctp_asconf_find_param(stcb, id); 1866163953Srrs if (ap == NULL) { 1867163953Srrs /* hmm... can't find this in our queue! */ 1868163953Srrs break; 1869163953Srrs } 1870163953Srrs /* process the parameter, success flag */ 1871163953Srrs sctp_asconf_process_param_ack(stcb, ap, 1); 1872163953Srrs break; 1873163953Srrs default: 1874163953Srrs break; 1875163953Srrs } /* switch */ 1876163953Srrs 1877163953Srrs /* update remaining ASCONF-ACK message length to process */ 1878163953Srrs ack_length -= SCTP_SIZE32(param_length); 1879163953Srrs if (ack_length <= 0) { 1880163953Srrs /* no more data in the mbuf chain */ 1881163953Srrs break; 1882163953Srrs } 1883163953Srrs offset += SCTP_SIZE32(param_length); 1884163953Srrs } /* while */ 1885163953Srrs 1886163953Srrs /* 1887163953Srrs * if there are any "sent" params still on the queue, these are 1888163953Srrs * implicitly "success", or "failed" (if we got an error back) ... 1889163953Srrs * so process these appropriately 1890163953Srrs * 1891163953Srrs * we assume that the correlation_id's are monotonically increasing 1892163953Srrs * beginning from 1 and that we don't have *that* many outstanding 1893163953Srrs * at any given time 1894163953Srrs */ 1895163953Srrs if (last_error_id == 0) 1896163953Srrs last_error_id--;/* set to "max" value */ 1897216822Stuexen TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) { 1898163953Srrs if (aa->sent == 1) { 1899163953Srrs /* 1900163953Srrs * implicitly successful or failed if correlation_id 1901163953Srrs * < last_error_id, then success else, failure 1902163953Srrs */ 1903163953Srrs if (aa->ap.aph.correlation_id < last_error_id) 1904171477Srrs sctp_asconf_process_param_ack(stcb, aa, 1); 1905163953Srrs else 1906171477Srrs sctp_asconf_process_param_ack(stcb, aa, 0); 1907163953Srrs } else { 1908163953Srrs /* 1909163953Srrs * since we always process in order (FIFO queue) if 1910163953Srrs * we reach one that hasn't been sent, the rest 1911163953Srrs * should not have been sent either. so, we're 1912163953Srrs * done... 1913163953Srrs */ 1914163953Srrs break; 1915163953Srrs } 1916163953Srrs } 1917163953Srrs 1918163953Srrs /* update the next sequence number to use */ 1919179157Srrs asoc->asconf_seq_out_acked++; 1920163953Srrs /* remove the old ASCONF on our outbound queue */ 1921163953Srrs sctp_toss_old_asconf(stcb); 1922163953Srrs if (!TAILQ_EMPTY(&stcb->asoc.asconf_queue)) { 1923171572Srrs#ifdef SCTP_TIMER_BASED_ASCONF 1924163953Srrs /* we have more params, so restart our timer */ 1925163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, 1926163953Srrs stcb, net); 1927171572Srrs#else 1928171572Srrs /* we have more params, so send out more */ 1929172190Srrs sctp_send_asconf(stcb, net, SCTP_ADDR_NOT_LOCKED); 1930171572Srrs#endif 1931163953Srrs } 1932163953Srrs} 1933163953Srrs 1934178251Srrs#ifdef INET6 1935163953Srrsstatic uint32_t 1936163953Srrssctp_is_scopeid_in_nets(struct sctp_tcb *stcb, struct sockaddr *sa) 1937163953Srrs{ 1938163953Srrs struct sockaddr_in6 *sin6, *net6; 1939163953Srrs struct sctp_nets *net; 1940163953Srrs 1941163953Srrs if (sa->sa_family != AF_INET6) { 1942163953Srrs /* wrong family */ 1943163953Srrs return (0); 1944163953Srrs } 1945163953Srrs sin6 = (struct sockaddr_in6 *)sa; 1946163953Srrs if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) == 0) { 1947163953Srrs /* not link local address */ 1948163953Srrs return (0); 1949163953Srrs } 1950163953Srrs /* hunt through our destination nets list for this scope_id */ 1951163953Srrs TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 1952163953Srrs if (((struct sockaddr *)(&net->ro._l_addr))->sa_family != 1953163953Srrs AF_INET6) 1954163953Srrs continue; 1955163953Srrs net6 = (struct sockaddr_in6 *)&net->ro._l_addr; 1956163953Srrs if (IN6_IS_ADDR_LINKLOCAL(&net6->sin6_addr) == 0) 1957163953Srrs continue; 1958163953Srrs if (sctp_is_same_scope(sin6, net6)) { 1959163953Srrs /* found one */ 1960163953Srrs return (1); 1961163953Srrs } 1962163953Srrs } 1963163953Srrs /* didn't find one */ 1964163953Srrs return (0); 1965163953Srrs} 1966163953Srrs 1967178251Srrs#endif 1968178251Srrs 1969163953Srrs/* 1970163953Srrs * address management functions 1971163953Srrs */ 1972163953Srrsstatic void 1973163953Srrssctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 1974172190Srrs struct sctp_ifa *ifa, uint16_t type, int addr_locked) 1975163953Srrs{ 1976163953Srrs int status; 1977163953Srrs 1978163953Srrs 1979224641Stuexen if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0 || 1980163953Srrs sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_ASCONF)) { 1981163953Srrs /* subset bound, no ASCONF allowed case, so ignore */ 1982163953Srrs return; 1983163953Srrs } 1984163953Srrs /* 1985163953Srrs * note: we know this is not the subset bound, no ASCONF case eg. 1986163953Srrs * this is boundall or subset bound w/ASCONF allowed 1987163953Srrs */ 1988163953Srrs 1989163953Srrs /* first, make sure it's a good address family */ 1990221249Stuexen switch (ifa->address.sa.sa_family) { 1991221249Stuexen#ifdef INET6 1992221249Stuexen case AF_INET6: 1993221249Stuexen break; 1994221249Stuexen#endif 1995221249Stuexen#ifdef INET 1996221249Stuexen case AF_INET: 1997221249Stuexen break; 1998221249Stuexen#endif 1999221249Stuexen default: 2000163953Srrs return; 2001163953Srrs } 2002221249Stuexen#ifdef INET6 2003163953Srrs /* make sure we're "allowed" to add this type of addr */ 2004167598Srrs if (ifa->address.sa.sa_family == AF_INET6) { 2005163953Srrs /* invalid if we're not a v6 endpoint */ 2006163953Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) 2007163953Srrs return; 2008163953Srrs /* is the v6 addr really valid ? */ 2009167598Srrs if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) { 2010163953Srrs return; 2011163953Srrs } 2012163953Srrs } 2013221249Stuexen#endif 2014163953Srrs /* put this address on the "pending/do not use yet" list */ 2015171572Srrs sctp_add_local_addr_restricted(stcb, ifa); 2016163953Srrs /* 2017163953Srrs * check address scope if address is out of scope, don't queue 2018163953Srrs * anything... note: this would leave the address on both inp and 2019163953Srrs * asoc lists 2020163953Srrs */ 2021178251Srrs switch (ifa->address.sa.sa_family) { 2022178251Srrs#ifdef INET6 2023178251Srrs case AF_INET6: 2024178251Srrs { 2025178251Srrs struct sockaddr_in6 *sin6; 2026163953Srrs 2027178251Srrs sin6 = (struct sockaddr_in6 *)&ifa->address.sin6; 2028178251Srrs if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 2029178251Srrs /* we skip unspecifed addresses */ 2030163953Srrs return; 2031163953Srrs } 2032178251Srrs if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 2033178251Srrs if (stcb->asoc.local_scope == 0) { 2034178251Srrs return; 2035178251Srrs } 2036178251Srrs /* is it the right link local scope? */ 2037178251Srrs if (sctp_is_scopeid_in_nets(stcb, &ifa->address.sa) == 0) { 2038178251Srrs return; 2039178251Srrs } 2040178251Srrs } 2041178251Srrs if (stcb->asoc.site_scope == 0 && 2042178251Srrs IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) { 2043163953Srrs return; 2044163953Srrs } 2045178251Srrs break; 2046163953Srrs } 2047178251Srrs#endif 2048221249Stuexen#ifdef INET 2049178251Srrs case AF_INET: 2050178251Srrs { 2051178251Srrs struct sockaddr_in *sin; 2052178251Srrs struct in6pcb *inp6; 2053163953Srrs 2054178251Srrs inp6 = (struct in6pcb *)&inp->ip_inp.inp; 2055178251Srrs /* invalid if we are a v6 only endpoint */ 2056178251Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && 2057178251Srrs SCTP_IPV6_V6ONLY(inp6)) 2058178251Srrs return; 2059163953Srrs 2060178251Srrs sin = (struct sockaddr_in *)&ifa->address.sa; 2061178251Srrs if (sin->sin_addr.s_addr == 0) { 2062178251Srrs /* we skip unspecifed addresses */ 2063178251Srrs return; 2064178251Srrs } 2065178251Srrs if (stcb->asoc.ipv4_local_scope == 0 && 2066178251Srrs IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) { 2067178251Srrs return; 2068178251Srrs } 2069178251Srrs break; 2070163953Srrs } 2071221249Stuexen#endif 2072178251Srrs default: 2073163953Srrs /* else, not AF_INET or AF_INET6, so skip */ 2074163953Srrs return; 2075163953Srrs } 2076163953Srrs 2077163953Srrs /* queue an asconf for this address add/delete */ 2078163953Srrs if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF)) { 2079163953Srrs /* does the peer do asconf? */ 2080163953Srrs if (stcb->asoc.peer_supports_asconf) { 2081163953Srrs /* queue an asconf for this addr */ 2082163953Srrs status = sctp_asconf_queue_add(stcb, ifa, type); 2083171572Srrs 2084163953Srrs /* 2085171572Srrs * if queued ok, and in the open state, send out the 2086171572Srrs * ASCONF. If in the non-open state, these will be 2087171572Srrs * sent when the state goes open. 2088163953Srrs */ 2089163953Srrs if (status == 0 && 2090163953Srrs SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) { 2091171572Srrs#ifdef SCTP_TIMER_BASED_ASCONF 2092163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, inp, 2093163953Srrs stcb, stcb->asoc.primary_destination); 2094171572Srrs#else 2095224641Stuexen sctp_send_asconf(stcb, NULL, addr_locked); 2096171572Srrs#endif 2097163953Srrs } 2098163953Srrs } 2099163953Srrs } 2100163953Srrs} 2101163953Srrs 2102167598Srrs 2103167598Srrsint 2104228653Stuexensctp_asconf_iterator_ep(struct sctp_inpcb *inp, void *ptr, uint32_t val SCTP_UNUSED) 2105163953Srrs{ 2106167598Srrs struct sctp_asconf_iterator *asc; 2107167598Srrs struct sctp_ifa *ifa; 2108167598Srrs struct sctp_laddr *l; 2109167598Srrs int cnt_invalid = 0; 2110163953Srrs 2111167598Srrs asc = (struct sctp_asconf_iterator *)ptr; 2112167598Srrs LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) { 2113167598Srrs ifa = l->ifa; 2114221249Stuexen switch (ifa->address.sa.sa_family) { 2115221249Stuexen#ifdef INET6 2116221249Stuexen case AF_INET6: 2117167598Srrs /* invalid if we're not a v6 endpoint */ 2118167598Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) { 2119167598Srrs cnt_invalid++; 2120167598Srrs if (asc->cnt == cnt_invalid) 2121167598Srrs return (1); 2122167598Srrs } 2123221249Stuexen break; 2124221249Stuexen#endif 2125221249Stuexen#ifdef INET 2126221249Stuexen case AF_INET: 2127221249Stuexen { 2128221249Stuexen /* invalid if we are a v6 only endpoint */ 2129221249Stuexen struct in6pcb *inp6; 2130163953Srrs 2131221249Stuexen inp6 = (struct in6pcb *)&inp->ip_inp.inp; 2132221249Stuexen if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && 2133221249Stuexen SCTP_IPV6_V6ONLY(inp6)) { 2134221249Stuexen cnt_invalid++; 2135221249Stuexen if (asc->cnt == cnt_invalid) 2136221249Stuexen return (1); 2137221249Stuexen } 2138221249Stuexen break; 2139163953Srrs } 2140221249Stuexen#endif 2141221249Stuexen default: 2142167598Srrs /* invalid address family */ 2143167598Srrs cnt_invalid++; 2144167598Srrs if (asc->cnt == cnt_invalid) 2145167598Srrs return (1); 2146163953Srrs } 2147163953Srrs } 2148167598Srrs return (0); 2149163953Srrs} 2150163953Srrs 2151171572Srrsstatic int 2152228653Stuexensctp_asconf_iterator_ep_end(struct sctp_inpcb *inp, void *ptr, uint32_t val SCTP_UNUSED) 2153163953Srrs{ 2154167598Srrs struct sctp_ifa *ifa; 2155167598Srrs struct sctp_asconf_iterator *asc; 2156167598Srrs struct sctp_laddr *laddr, *nladdr, *l; 2157163953Srrs 2158167598Srrs /* Only for specific case not bound all */ 2159167598Srrs asc = (struct sctp_asconf_iterator *)ptr; 2160167598Srrs LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) { 2161167598Srrs ifa = l->ifa; 2162167598Srrs if (l->action == SCTP_ADD_IP_ADDRESS) { 2163169655Srrs LIST_FOREACH(laddr, &inp->sctp_addr_list, 2164169655Srrs sctp_nxt_addr) { 2165167598Srrs if (laddr->ifa == ifa) { 2166167598Srrs laddr->action = 0; 2167167598Srrs break; 2168167598Srrs } 2169167598Srrs } 2170167598Srrs } else if (l->action == SCTP_DEL_IP_ADDRESS) { 2171216822Stuexen LIST_FOREACH_SAFE(laddr, &inp->sctp_addr_list, sctp_nxt_addr, nladdr) { 2172167598Srrs /* remove only after all guys are done */ 2173167598Srrs if (laddr->ifa == ifa) { 2174167598Srrs sctp_del_local_addr_ep(inp, ifa); 2175167598Srrs } 2176167598Srrs } 2177167598Srrs } 2178163953Srrs } 2179167598Srrs return (0); 2180163953Srrs} 2181163953Srrs 2182167598Srrsvoid 2183171572Srrssctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 2184228653Stuexen void *ptr, uint32_t val SCTP_UNUSED) 2185163953Srrs{ 2186167598Srrs struct sctp_asconf_iterator *asc; 2187167598Srrs struct sctp_ifa *ifa; 2188167598Srrs struct sctp_laddr *l; 2189167598Srrs int cnt_invalid = 0; 2190167598Srrs int type, status; 2191171572Srrs int num_queued = 0; 2192163953Srrs 2193167598Srrs asc = (struct sctp_asconf_iterator *)ptr; 2194167598Srrs LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) { 2195167598Srrs ifa = l->ifa; 2196167598Srrs type = l->action; 2197170751Srrs 2198170751Srrs /* address's vrf_id must be the vrf_id of the assoc */ 2199170751Srrs if (ifa->vrf_id != stcb->asoc.vrf_id) { 2200170751Srrs continue; 2201170751Srrs } 2202167598Srrs /* Same checks again for assoc */ 2203178251Srrs switch (ifa->address.sa.sa_family) { 2204178251Srrs#ifdef INET6 2205178251Srrs case AF_INET6: 2206178251Srrs { 2207178251Srrs /* invalid if we're not a v6 endpoint */ 2208178251Srrs struct sockaddr_in6 *sin6; 2209163953Srrs 2210178251Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) { 2211178251Srrs cnt_invalid++; 2212178251Srrs if (asc->cnt == cnt_invalid) 2213178251Srrs return; 2214178251Srrs else 2215178251Srrs continue; 2216167598Srrs } 2217178251Srrs sin6 = (struct sockaddr_in6 *)&ifa->address.sin6; 2218178251Srrs if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 2219178251Srrs /* we skip unspecifed addresses */ 2220167598Srrs continue; 2221167598Srrs } 2222178251Srrs if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 2223178251Srrs if (stcb->asoc.local_scope == 0) { 2224178251Srrs continue; 2225178251Srrs } 2226178251Srrs /* is it the right link local scope? */ 2227178251Srrs if (sctp_is_scopeid_in_nets(stcb, &ifa->address.sa) == 0) { 2228178251Srrs continue; 2229178251Srrs } 2230178251Srrs } 2231178251Srrs break; 2232167598Srrs } 2233178251Srrs#endif 2234221249Stuexen#ifdef INET 2235178251Srrs case AF_INET: 2236178251Srrs { 2237178251Srrs /* invalid if we are a v6 only endpoint */ 2238178251Srrs struct in6pcb *inp6; 2239178251Srrs struct sockaddr_in *sin; 2240163953Srrs 2241178251Srrs inp6 = (struct in6pcb *)&inp->ip_inp.inp; 2242178251Srrs /* invalid if we are a v6 only endpoint */ 2243178251Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && 2244178251Srrs SCTP_IPV6_V6ONLY(inp6)) 2245178251Srrs continue; 2246167598Srrs 2247178251Srrs sin = (struct sockaddr_in *)&ifa->address.sa; 2248178251Srrs if (sin->sin_addr.s_addr == 0) { 2249178251Srrs /* we skip unspecifed addresses */ 2250167598Srrs continue; 2251178251Srrs } 2252178251Srrs if (stcb->asoc.ipv4_local_scope == 0 && 2253178251Srrs IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) { 2254201758Smbr continue; 2255178251Srrs } 2256178251Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && 2257178251Srrs SCTP_IPV6_V6ONLY(inp6)) { 2258178251Srrs cnt_invalid++; 2259178251Srrs if (asc->cnt == cnt_invalid) 2260178251Srrs return; 2261178251Srrs else 2262178251Srrs continue; 2263178251Srrs } 2264178251Srrs break; 2265167598Srrs } 2266221249Stuexen#endif 2267178251Srrs default: 2268167598Srrs /* invalid address family */ 2269167598Srrs cnt_invalid++; 2270167598Srrs if (asc->cnt == cnt_invalid) 2271163953Srrs return; 2272167598Srrs else 2273167598Srrs continue; 2274178251Srrs break; 2275163953Srrs } 2276163953Srrs 2277167598Srrs if (type == SCTP_ADD_IP_ADDRESS) { 2278171572Srrs /* prevent this address from being used as a source */ 2279171572Srrs sctp_add_local_addr_restricted(stcb, ifa); 2280167598Srrs } else if (type == SCTP_DEL_IP_ADDRESS) { 2281163953Srrs struct sctp_nets *net; 2282163953Srrs 2283163953Srrs TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 2284169352Srrs sctp_rtentry_t *rt; 2285163953Srrs 2286163953Srrs /* delete this address if cached */ 2287172091Srrs if (net->ro._s_addr == ifa) { 2288167598Srrs sctp_free_ifa(net->ro._s_addr); 2289167598Srrs net->ro._s_addr = NULL; 2290167598Srrs net->src_addr_selected = 0; 2291167598Srrs rt = net->ro.ro_rt; 2292167598Srrs if (rt) { 2293167598Srrs RTFREE(rt); 2294167598Srrs net->ro.ro_rt = NULL; 2295167598Srrs } 2296167598Srrs /* 2297167598Srrs * Now we deleted our src address, 2298167598Srrs * should we not also now reset the 2299167598Srrs * cwnd/rto to start as if its a new 2300167598Srrs * address? 2301167598Srrs */ 2302171440Srrs stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net); 2303170428Srrs net->RTO = 0; 2304167598Srrs 2305163953Srrs } 2306167598Srrs } 2307167598Srrs } else if (type == SCTP_SET_PRIM_ADDR) { 2308167598Srrs if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) { 2309171572Srrs /* must validate the ifa is in the ep */ 2310167598Srrs if (sctp_is_addr_in_ep(stcb->sctp_ep, ifa) == 0) { 2311167598Srrs continue; 2312163953Srrs } 2313167598Srrs } else { 2314167598Srrs /* Need to check scopes for this guy */ 2315167598Srrs if (sctp_is_address_in_scope(ifa, 2316167598Srrs stcb->asoc.ipv4_addr_legal, 2317167598Srrs stcb->asoc.ipv6_addr_legal, 2318167598Srrs stcb->asoc.loopback_scope, 2319167598Srrs stcb->asoc.ipv4_local_scope, 2320167598Srrs stcb->asoc.local_scope, 2321167598Srrs stcb->asoc.site_scope, 0) == 0) { 2322167598Srrs continue; 2323167598Srrs } 2324163953Srrs } 2325163953Srrs } 2326167598Srrs /* queue an asconf for this address add/delete */ 2327171572Srrs if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF) && 2328171572Srrs stcb->asoc.peer_supports_asconf) { 2329171572Srrs /* queue an asconf for this addr */ 2330171572Srrs status = sctp_asconf_queue_add(stcb, ifa, type); 2331171572Srrs /* 2332171572Srrs * if queued ok, and in the open state, update the 2333171572Srrs * count of queued params. If in the non-open 2334171572Srrs * state, these get sent when the assoc goes open. 2335171572Srrs */ 2336171572Srrs if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) { 2337171572Srrs if (status >= 0) { 2338171572Srrs num_queued++; 2339167598Srrs } 2340167598Srrs } 2341167598Srrs } 2342163953Srrs } 2343171572Srrs /* 2344171572Srrs * If we have queued params in the open state, send out an ASCONF. 2345171572Srrs */ 2346171572Srrs if (num_queued > 0) { 2347224641Stuexen sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED); 2348171572Srrs } 2349163953Srrs} 2350163953Srrs 2351171572Srrsvoid 2352228653Stuexensctp_asconf_iterator_end(void *ptr, uint32_t val SCTP_UNUSED) 2353167598Srrs{ 2354167598Srrs struct sctp_asconf_iterator *asc; 2355167598Srrs struct sctp_ifa *ifa; 2356216822Stuexen struct sctp_laddr *l, *nl; 2357167598Srrs 2358167598Srrs asc = (struct sctp_asconf_iterator *)ptr; 2359216822Stuexen LIST_FOREACH_SAFE(l, &asc->list_of_work, sctp_nxt_addr, nl) { 2360167598Srrs ifa = l->ifa; 2361167598Srrs if (l->action == SCTP_ADD_IP_ADDRESS) { 2362167598Srrs /* Clear the defer use flag */ 2363167598Srrs ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE; 2364167598Srrs } 2365167598Srrs sctp_free_ifa(ifa); 2366179783Srrs SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_laddr), l); 2367167598Srrs SCTP_DECR_LADDR_COUNT(); 2368167598Srrs } 2369170091Srrs SCTP_FREE(asc, SCTP_M_ASC_IT); 2370167598Srrs} 2371167598Srrs 2372163953Srrs/* 2373171572Srrs * sa is the sockaddr to ask the peer to set primary to. 2374171572Srrs * returns: 0 = completed, -1 = error 2375163953Srrs */ 2376171943Srrsint32_t 2377163953Srrssctp_set_primary_ip_address_sa(struct sctp_tcb *stcb, struct sockaddr *sa) 2378163953Srrs{ 2379172190Srrs uint32_t vrf_id; 2380172190Srrs struct sctp_ifa *ifa; 2381163953Srrs 2382172190Srrs /* find the ifa for the desired set primary */ 2383172218Srrs vrf_id = stcb->asoc.vrf_id; 2384172190Srrs ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED); 2385172190Srrs if (ifa == NULL) { 2386172190Srrs /* Invalid address */ 2387172190Srrs return (-1); 2388172190Srrs } 2389163953Srrs /* queue an ASCONF:SET_PRIM_ADDR to be sent */ 2390172190Srrs if (!sctp_asconf_queue_add(stcb, ifa, SCTP_SET_PRIM_ADDR)) { 2391163953Srrs /* set primary queuing succeeded */ 2392171572Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 2393171572Srrs "set_primary_ip_address_sa: queued on tcb=%p, ", 2394171572Srrs stcb); 2395171572Srrs SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); 2396163953Srrs if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) { 2397171572Srrs#ifdef SCTP_TIMER_BASED_ASCONF 2398163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, 2399163953Srrs stcb->sctp_ep, stcb, 2400163953Srrs stcb->asoc.primary_destination); 2401171572Srrs#else 2402224641Stuexen sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED); 2403171572Srrs#endif 2404163953Srrs } 2405163953Srrs } else { 2406169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "set_primary_ip_address_sa: failed to add to queue on tcb=%p, ", 2407169420Srrs stcb); 2408169420Srrs SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); 2409163953Srrs return (-1); 2410163953Srrs } 2411163953Srrs return (0); 2412163953Srrs} 2413163953Srrs 2414163953Srrsvoid 2415167598Srrssctp_set_primary_ip_address(struct sctp_ifa *ifa) 2416163953Srrs{ 2417163953Srrs struct sctp_inpcb *inp; 2418163953Srrs 2419163953Srrs /* go through all our PCB's */ 2420179783Srrs LIST_FOREACH(inp, &SCTP_BASE_INFO(listhead), sctp_list) { 2421163953Srrs struct sctp_tcb *stcb; 2422163953Srrs 2423163953Srrs /* process for all associations for this endpoint */ 2424163953Srrs LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { 2425163953Srrs /* queue an ASCONF:SET_PRIM_ADDR to be sent */ 2426163953Srrs if (!sctp_asconf_queue_add(stcb, ifa, 2427163953Srrs SCTP_SET_PRIM_ADDR)) { 2428163953Srrs /* set primary queuing succeeded */ 2429172090Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "set_primary_ip_address: queued on stcb=%p, ", 2430171572Srrs stcb); 2431171572Srrs SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &ifa->address.sa); 2432171572Srrs if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) { 2433171572Srrs#ifdef SCTP_TIMER_BASED_ASCONF 2434163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, 2435163953Srrs stcb->sctp_ep, stcb, 2436163953Srrs stcb->asoc.primary_destination); 2437171572Srrs#else 2438224641Stuexen sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED); 2439171572Srrs#endif 2440163953Srrs } 2441163953Srrs } 2442163953Srrs } /* for each stcb */ 2443163953Srrs } /* for each inp */ 2444163953Srrs} 2445163953Srrs 2446179157Srrsint 2447179157Srrssctp_is_addr_pending(struct sctp_tcb *stcb, struct sctp_ifa *sctp_ifa) 2448179157Srrs{ 2449179157Srrs struct sctp_tmit_chunk *chk, *nchk; 2450179157Srrs unsigned int offset, asconf_limit; 2451179157Srrs struct sctp_asconf_chunk *acp; 2452179157Srrs struct sctp_asconf_paramhdr *aph; 2453179157Srrs uint8_t aparam_buf[SCTP_PARAM_BUFFER_SIZE]; 2454221249Stuexen struct sctp_paramhdr *ph; 2455179157Srrs int add_cnt, del_cnt; 2456179157Srrs uint16_t last_param_type; 2457179157Srrs 2458179157Srrs add_cnt = del_cnt = 0; 2459179157Srrs last_param_type = 0; 2460216822Stuexen TAILQ_FOREACH_SAFE(chk, &stcb->asoc.asconf_send_queue, sctp_next, nchk) { 2461179157Srrs if (chk->data == NULL) { 2462179157Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: No mbuf data?\n"); 2463179157Srrs continue; 2464179157Srrs } 2465179157Srrs offset = 0; 2466179157Srrs acp = mtod(chk->data, struct sctp_asconf_chunk *); 2467179157Srrs offset += sizeof(struct sctp_asconf_chunk); 2468179157Srrs asconf_limit = ntohs(acp->ch.chunk_length); 2469221249Stuexen ph = (struct sctp_paramhdr *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_paramhdr), aparam_buf); 2470221249Stuexen if (ph == NULL) { 2471179157Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: couldn't get lookup addr!\n"); 2472179157Srrs continue; 2473179157Srrs } 2474221249Stuexen offset += ntohs(ph->param_length); 2475179157Srrs 2476179157Srrs aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_asconf_paramhdr), aparam_buf); 2477179157Srrs if (aph == NULL) { 2478179157Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: Empty ASCONF will be sent?\n"); 2479179157Srrs continue; 2480179157Srrs } 2481179157Srrs while (aph != NULL) { 2482179157Srrs unsigned int param_length, param_type; 2483179157Srrs 2484179157Srrs param_type = ntohs(aph->ph.param_type); 2485179157Srrs param_length = ntohs(aph->ph.param_length); 2486179157Srrs if (offset + param_length > asconf_limit) { 2487179157Srrs /* parameter goes beyond end of chunk! */ 2488179157Srrs break; 2489179157Srrs } 2490179157Srrs if (param_length > sizeof(aparam_buf)) { 2491179157Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: param length (%u) larger than buffer size!\n", param_length); 2492179157Srrs break; 2493179157Srrs } 2494179157Srrs if (param_length <= sizeof(struct sctp_paramhdr)) { 2495179157Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: param length(%u) too short\n", param_length); 2496179157Srrs break; 2497179157Srrs } 2498179157Srrs aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(chk->data, offset, param_length, aparam_buf); 2499179157Srrs if (aph == NULL) { 2500179157Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: couldn't get entire param\n"); 2501179157Srrs break; 2502179157Srrs } 2503221249Stuexen ph = (struct sctp_paramhdr *)(aph + 1); 2504221249Stuexen if (sctp_addr_match(ph, &sctp_ifa->address.sa) != 0) { 2505179157Srrs switch (param_type) { 2506179157Srrs case SCTP_ADD_IP_ADDRESS: 2507179157Srrs add_cnt++; 2508179157Srrs break; 2509179157Srrs case SCTP_DEL_IP_ADDRESS: 2510179157Srrs del_cnt++; 2511179157Srrs break; 2512179157Srrs default: 2513179157Srrs break; 2514179157Srrs } 2515179157Srrs last_param_type = param_type; 2516179157Srrs } 2517179157Srrs offset += SCTP_SIZE32(param_length); 2518179157Srrs if (offset >= asconf_limit) { 2519179157Srrs /* no more data in the mbuf chain */ 2520179157Srrs break; 2521179157Srrs } 2522179157Srrs /* get pointer to next asconf param */ 2523179157Srrs aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_asconf_paramhdr), aparam_buf); 2524179157Srrs } 2525179157Srrs } 2526179157Srrs 2527179157Srrs /* 2528179157Srrs * we want to find the sequences which consist of ADD -> DEL -> ADD 2529179157Srrs * or DEL -> ADD 2530179157Srrs */ 2531179157Srrs if (add_cnt > del_cnt || 2532179157Srrs (add_cnt == del_cnt && last_param_type == SCTP_ADD_IP_ADDRESS)) { 2533228907Stuexen return (1); 2534179157Srrs } 2535228907Stuexen return (0); 2536179157Srrs} 2537179157Srrs 2538163953Srrsstatic struct sockaddr * 2539172190Srrssctp_find_valid_localaddr(struct sctp_tcb *stcb, int addr_locked) 2540163953Srrs{ 2541167598Srrs struct sctp_vrf *vrf = NULL; 2542167598Srrs struct sctp_ifn *sctp_ifn; 2543167598Srrs struct sctp_ifa *sctp_ifa; 2544163953Srrs 2545172190Srrs if (addr_locked == SCTP_ADDR_NOT_LOCKED) 2546172218Srrs SCTP_IPI_ADDR_RLOCK(); 2547167598Srrs vrf = sctp_find_vrf(stcb->asoc.vrf_id); 2548169420Srrs if (vrf == NULL) { 2549172190Srrs if (addr_locked == SCTP_ADDR_NOT_LOCKED) 2550172218Srrs SCTP_IPI_ADDR_RUNLOCK(); 2551169420Srrs return (NULL); 2552169420Srrs } 2553167598Srrs LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) { 2554167598Srrs if (stcb->asoc.loopback_scope == 0 && 2555167598Srrs SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) { 2556163953Srrs /* Skip if loopback_scope not set */ 2557163953Srrs continue; 2558163953Srrs } 2559167598Srrs LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) { 2560221249Stuexen switch (sctp_ifa->address.sa.sa_family) { 2561221249Stuexen#ifdef INET 2562221249Stuexen case AF_INET: 2563221249Stuexen if (stcb->asoc.ipv4_addr_legal) { 2564221249Stuexen struct sockaddr_in *sin; 2565163953Srrs 2566221249Stuexen sin = (struct sockaddr_in *)&sctp_ifa->address.sa; 2567221249Stuexen if (sin->sin_addr.s_addr == 0) { 2568221249Stuexen /* skip unspecifed addresses */ 2569221249Stuexen continue; 2570221249Stuexen } 2571221249Stuexen if (stcb->asoc.ipv4_local_scope == 0 && 2572221249Stuexen IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) 2573221249Stuexen continue; 2574221249Stuexen 2575221249Stuexen if (sctp_is_addr_restricted(stcb, sctp_ifa) && 2576221249Stuexen (!sctp_is_addr_pending(stcb, sctp_ifa))) 2577221249Stuexen continue; 2578221249Stuexen /* 2579221249Stuexen * found a valid local v4 address to 2580221249Stuexen * use 2581221249Stuexen */ 2582221249Stuexen if (addr_locked == SCTP_ADDR_NOT_LOCKED) 2583221249Stuexen SCTP_IPI_ADDR_RUNLOCK(); 2584221249Stuexen return (&sctp_ifa->address.sa); 2585163953Srrs } 2586221249Stuexen break; 2587221249Stuexen#endif 2588221249Stuexen#ifdef INET6 2589221249Stuexen case AF_INET6: 2590221249Stuexen if (stcb->asoc.ipv6_addr_legal) { 2591221249Stuexen struct sockaddr_in6 *sin6; 2592163953Srrs 2593221249Stuexen if (sctp_ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) { 2594221249Stuexen continue; 2595221249Stuexen } 2596221249Stuexen sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa; 2597221249Stuexen if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 2598221249Stuexen /* 2599221249Stuexen * we skip unspecifed 2600221249Stuexen * addresses 2601221249Stuexen */ 2602221249Stuexen continue; 2603221249Stuexen } 2604221249Stuexen if (stcb->asoc.local_scope == 0 && 2605221249Stuexen IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 2606221249Stuexen continue; 2607221249Stuexen if (stcb->asoc.site_scope == 0 && 2608221249Stuexen IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) 2609221249Stuexen continue; 2610163953Srrs 2611221249Stuexen if (sctp_is_addr_restricted(stcb, sctp_ifa) && 2612221249Stuexen (!sctp_is_addr_pending(stcb, sctp_ifa))) 2613221249Stuexen continue; 2614221249Stuexen /* 2615221249Stuexen * found a valid local v6 address to 2616221249Stuexen * use 2617221249Stuexen */ 2618221249Stuexen if (addr_locked == SCTP_ADDR_NOT_LOCKED) 2619221249Stuexen SCTP_IPI_ADDR_RUNLOCK(); 2620221249Stuexen return (&sctp_ifa->address.sa); 2621167598Srrs } 2622221249Stuexen break; 2623221249Stuexen#endif 2624221249Stuexen default: 2625221249Stuexen break; 2626163953Srrs } 2627163953Srrs } 2628163953Srrs } 2629163953Srrs /* no valid addresses found */ 2630172190Srrs if (addr_locked == SCTP_ADDR_NOT_LOCKED) 2631172218Srrs SCTP_IPI_ADDR_RUNLOCK(); 2632163953Srrs return (NULL); 2633163953Srrs} 2634163953Srrs 2635163953Srrsstatic struct sockaddr * 2636163953Srrssctp_find_valid_localaddr_ep(struct sctp_tcb *stcb) 2637163953Srrs{ 2638163953Srrs struct sctp_laddr *laddr; 2639163953Srrs 2640163953Srrs LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) { 2641163953Srrs if (laddr->ifa == NULL) { 2642163953Srrs continue; 2643163953Srrs } 2644163953Srrs /* is the address restricted ? */ 2645179157Srrs if (sctp_is_addr_restricted(stcb, laddr->ifa) && 2646179157Srrs (!sctp_is_addr_pending(stcb, laddr->ifa))) 2647163953Srrs continue; 2648163953Srrs 2649163953Srrs /* found a valid local address to use */ 2650167598Srrs return (&laddr->ifa->address.sa); 2651163953Srrs } 2652163953Srrs /* no valid addresses found */ 2653163953Srrs return (NULL); 2654163953Srrs} 2655163953Srrs 2656163953Srrs/* 2657171477Srrs * builds an ASCONF chunk from queued ASCONF params. 2658171477Srrs * returns NULL on error (no mbuf, no ASCONF params queued, etc). 2659163953Srrs */ 2660163953Srrsstruct mbuf * 2661172190Srrssctp_compose_asconf(struct sctp_tcb *stcb, int *retlen, int addr_locked) 2662163953Srrs{ 2663163953Srrs struct mbuf *m_asconf, *m_asconf_chk; 2664163953Srrs struct sctp_asconf_addr *aa; 2665163953Srrs struct sctp_asconf_chunk *acp; 2666163953Srrs struct sctp_asconf_paramhdr *aph; 2667163953Srrs struct sctp_asconf_addr_param *aap; 2668163953Srrs uint32_t p_length; 2669163953Srrs uint32_t correlation_id = 1; /* 0 is reserved... */ 2670163953Srrs caddr_t ptr, lookup_ptr; 2671163953Srrs uint8_t lookup_used = 0; 2672163953Srrs 2673163953Srrs /* are there any asconf params to send? */ 2674179157Srrs TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) { 2675179157Srrs if (aa->sent == 0) 2676179157Srrs break; 2677163953Srrs } 2678179157Srrs if (aa == NULL) 2679171572Srrs return (NULL); 2680179157Srrs 2681163953Srrs /* 2682163953Srrs * get a chunk header mbuf and a cluster for the asconf params since 2683163953Srrs * it's simpler to fill in the asconf chunk header lookup address on 2684163953Srrs * the fly 2685163953Srrs */ 2686165647Srrs m_asconf_chk = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_chunk), 0, M_DONTWAIT, 1, MT_DATA); 2687163953Srrs if (m_asconf_chk == NULL) { 2688163953Srrs /* no mbuf's */ 2689169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 2690169420Srrs "compose_asconf: couldn't get chunk mbuf!\n"); 2691163953Srrs return (NULL); 2692163953Srrs } 2693165647Srrs m_asconf = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_DONTWAIT, 1, MT_DATA); 2694163953Srrs if (m_asconf == NULL) { 2695163953Srrs /* no mbuf's */ 2696169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 2697169420Srrs "compose_asconf: couldn't get mbuf!\n"); 2698163953Srrs sctp_m_freem(m_asconf_chk); 2699163953Srrs return (NULL); 2700163953Srrs } 2701165647Srrs SCTP_BUF_LEN(m_asconf_chk) = sizeof(struct sctp_asconf_chunk); 2702165647Srrs SCTP_BUF_LEN(m_asconf) = 0; 2703163953Srrs acp = mtod(m_asconf_chk, struct sctp_asconf_chunk *); 2704163953Srrs bzero(acp, sizeof(struct sctp_asconf_chunk)); 2705163953Srrs /* save pointers to lookup address and asconf params */ 2706163953Srrs lookup_ptr = (caddr_t)(acp + 1); /* after the header */ 2707163953Srrs ptr = mtod(m_asconf, caddr_t); /* beginning of cluster */ 2708163953Srrs 2709163953Srrs /* fill in chunk header info */ 2710163953Srrs acp->ch.chunk_type = SCTP_ASCONF; 2711163953Srrs acp->ch.chunk_flags = 0; 2712163953Srrs acp->serial_number = htonl(stcb->asoc.asconf_seq_out); 2713179157Srrs stcb->asoc.asconf_seq_out++; 2714163953Srrs 2715163953Srrs /* add parameters... up to smallest MTU allowed */ 2716163953Srrs TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) { 2717179157Srrs if (aa->sent) 2718179157Srrs continue; 2719163953Srrs /* get the parameter length */ 2720163953Srrs p_length = SCTP_SIZE32(aa->ap.aph.ph.param_length); 2721163953Srrs /* will it fit in current chunk? */ 2722165647Srrs if (SCTP_BUF_LEN(m_asconf) + p_length > stcb->asoc.smallest_mtu) { 2723163953Srrs /* won't fit, so we're done with this chunk */ 2724163953Srrs break; 2725163953Srrs } 2726163953Srrs /* assign (and store) a correlation id */ 2727163953Srrs aa->ap.aph.correlation_id = correlation_id++; 2728163953Srrs 2729163953Srrs /* 2730163953Srrs * fill in address if we're doing a delete this is a simple 2731163953Srrs * way for us to fill in the correlation address, which 2732163953Srrs * should only be used by the peer if we're deleting our 2733163953Srrs * source address and adding a new address (e.g. renumbering 2734163953Srrs * case) 2735163953Srrs */ 2736163953Srrs if (lookup_used == 0 && 2737185694Srrs (aa->special_del == 0) && 2738163953Srrs aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS) { 2739163953Srrs struct sctp_ipv6addr_param *lookup; 2740163953Srrs uint16_t p_size, addr_size; 2741163953Srrs 2742163953Srrs lookup = (struct sctp_ipv6addr_param *)lookup_ptr; 2743163953Srrs lookup->ph.param_type = 2744163953Srrs htons(aa->ap.addrp.ph.param_type); 2745163953Srrs if (aa->ap.addrp.ph.param_type == SCTP_IPV6_ADDRESS) { 2746163953Srrs /* copy IPv6 address */ 2747163953Srrs p_size = sizeof(struct sctp_ipv6addr_param); 2748163953Srrs addr_size = sizeof(struct in6_addr); 2749163953Srrs } else { 2750163953Srrs /* copy IPv4 address */ 2751163953Srrs p_size = sizeof(struct sctp_ipv4addr_param); 2752163953Srrs addr_size = sizeof(struct in_addr); 2753163953Srrs } 2754163953Srrs lookup->ph.param_length = htons(SCTP_SIZE32(p_size)); 2755163953Srrs memcpy(lookup->addr, &aa->ap.addrp.addr, addr_size); 2756165647Srrs SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(p_size); 2757163953Srrs lookup_used = 1; 2758163953Srrs } 2759163953Srrs /* copy into current space */ 2760163953Srrs memcpy(ptr, &aa->ap, p_length); 2761163953Srrs 2762163953Srrs /* network elements and update lengths */ 2763163953Srrs aph = (struct sctp_asconf_paramhdr *)ptr; 2764163953Srrs aap = (struct sctp_asconf_addr_param *)ptr; 2765163953Srrs /* correlation_id is transparent to peer, no htonl needed */ 2766163953Srrs aph->ph.param_type = htons(aph->ph.param_type); 2767163953Srrs aph->ph.param_length = htons(aph->ph.param_length); 2768163953Srrs aap->addrp.ph.param_type = htons(aap->addrp.ph.param_type); 2769163953Srrs aap->addrp.ph.param_length = htons(aap->addrp.ph.param_length); 2770163953Srrs 2771165647Srrs SCTP_BUF_LEN(m_asconf) += SCTP_SIZE32(p_length); 2772163953Srrs ptr += SCTP_SIZE32(p_length); 2773163953Srrs 2774163953Srrs /* 2775163953Srrs * these params are removed off the pending list upon 2776163953Srrs * getting an ASCONF-ACK back from the peer, just set flag 2777163953Srrs */ 2778163953Srrs aa->sent = 1; 2779163953Srrs } 2780163953Srrs /* check to see if the lookup addr has been populated yet */ 2781163953Srrs if (lookup_used == 0) { 2782163953Srrs /* NOTE: if the address param is optional, can skip this... */ 2783163953Srrs /* add any valid (existing) address... */ 2784163953Srrs struct sctp_ipv6addr_param *lookup; 2785163953Srrs uint16_t p_size, addr_size; 2786163953Srrs struct sockaddr *found_addr; 2787163953Srrs caddr_t addr_ptr; 2788163953Srrs 2789163953Srrs if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) 2790172190Srrs found_addr = sctp_find_valid_localaddr(stcb, 2791172190Srrs addr_locked); 2792163953Srrs else 2793163953Srrs found_addr = sctp_find_valid_localaddr_ep(stcb); 2794163953Srrs 2795163953Srrs lookup = (struct sctp_ipv6addr_param *)lookup_ptr; 2796163953Srrs if (found_addr != NULL) { 2797221249Stuexen switch (found_addr->sa_family) { 2798221249Stuexen#ifdef INET6 2799221249Stuexen case AF_INET6: 2800163953Srrs /* copy IPv6 address */ 2801163953Srrs lookup->ph.param_type = 2802163953Srrs htons(SCTP_IPV6_ADDRESS); 2803163953Srrs p_size = sizeof(struct sctp_ipv6addr_param); 2804163953Srrs addr_size = sizeof(struct in6_addr); 2805163953Srrs addr_ptr = (caddr_t)&((struct sockaddr_in6 *) 2806163953Srrs found_addr)->sin6_addr; 2807221249Stuexen break; 2808221249Stuexen#endif 2809221249Stuexen#ifdef INET 2810221249Stuexen case AF_INET: 2811163953Srrs /* copy IPv4 address */ 2812163953Srrs lookup->ph.param_type = 2813163953Srrs htons(SCTP_IPV4_ADDRESS); 2814163953Srrs p_size = sizeof(struct sctp_ipv4addr_param); 2815163953Srrs addr_size = sizeof(struct in_addr); 2816163953Srrs addr_ptr = (caddr_t)&((struct sockaddr_in *) 2817163953Srrs found_addr)->sin_addr; 2818221249Stuexen break; 2819221249Stuexen#endif 2820221249Stuexen default: 2821221249Stuexen p_size = 0; 2822221249Stuexen addr_size = 0; 2823221249Stuexen addr_ptr = NULL; 2824221249Stuexen break; 2825163953Srrs } 2826163953Srrs lookup->ph.param_length = htons(SCTP_SIZE32(p_size)); 2827163953Srrs memcpy(lookup->addr, addr_ptr, addr_size); 2828165647Srrs SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(p_size); 2829163953Srrs } else { 2830163953Srrs /* uh oh... don't have any address?? */ 2831169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 2832169420Srrs "compose_asconf: no lookup addr!\n"); 2833221249Stuexen /* XXX for now, we send a IPv4 address of 0.0.0.0 */ 2834163953Srrs lookup->ph.param_type = htons(SCTP_IPV4_ADDRESS); 2835163953Srrs lookup->ph.param_length = htons(SCTP_SIZE32(sizeof(struct sctp_ipv4addr_param))); 2836163953Srrs bzero(lookup->addr, sizeof(struct in_addr)); 2837165647Srrs SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(sizeof(struct sctp_ipv4addr_param)); 2838163953Srrs } 2839163953Srrs } 2840163953Srrs /* chain it all together */ 2841165647Srrs SCTP_BUF_NEXT(m_asconf_chk) = m_asconf; 2842169655Srrs *retlen = SCTP_BUF_LEN(m_asconf_chk) + SCTP_BUF_LEN(m_asconf); 2843169655Srrs acp->ch.chunk_length = ntohs(*retlen); 2844163953Srrs 2845163953Srrs return (m_asconf_chk); 2846163953Srrs} 2847163953Srrs 2848163953Srrs/* 2849163953Srrs * section to handle address changes before an association is up eg. changes 2850163953Srrs * during INIT/INIT-ACK/COOKIE-ECHO handshake 2851163953Srrs */ 2852163953Srrs 2853163953Srrs/* 2854163953Srrs * processes the (local) addresses in the INIT-ACK chunk 2855163953Srrs */ 2856163953Srrsstatic void 2857163953Srrssctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m, 2858163953Srrs unsigned int offset, unsigned int length) 2859163953Srrs{ 2860163953Srrs struct sctp_paramhdr tmp_param, *ph; 2861163953Srrs uint16_t plen, ptype; 2862167598Srrs struct sctp_ifa *sctp_ifa; 2863163953Srrs struct sctp_ipv6addr_param addr_store; 2864221249Stuexen 2865221249Stuexen#ifdef INET6 2866163953Srrs struct sockaddr_in6 sin6; 2867221249Stuexen 2868221249Stuexen#endif 2869221249Stuexen#ifdef INET 2870163953Srrs struct sockaddr_in sin; 2871221249Stuexen 2872221249Stuexen#endif 2873163953Srrs struct sockaddr *sa; 2874167598Srrs uint32_t vrf_id; 2875163953Srrs 2876169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF2, "processing init-ack addresses\n"); 2877169420Srrs if (stcb == NULL) /* Un-needed check for SA */ 2878169420Srrs return; 2879163953Srrs 2880163953Srrs /* convert to upper bound */ 2881163953Srrs length += offset; 2882163953Srrs 2883163953Srrs if ((offset + sizeof(struct sctp_paramhdr)) > length) { 2884163953Srrs return; 2885163953Srrs } 2886163953Srrs /* init the addresses */ 2887221249Stuexen#ifdef INET6 2888163953Srrs bzero(&sin6, sizeof(sin6)); 2889163953Srrs sin6.sin6_family = AF_INET6; 2890163953Srrs sin6.sin6_len = sizeof(sin6); 2891163953Srrs sin6.sin6_port = stcb->rport; 2892221249Stuexen#endif 2893163953Srrs 2894221249Stuexen#ifdef INET 2895163953Srrs bzero(&sin, sizeof(sin)); 2896221249Stuexen sin.sin_family = AF_INET; 2897163953Srrs sin.sin_len = sizeof(sin); 2898163953Srrs sin.sin_port = stcb->rport; 2899221249Stuexen#endif 2900163953Srrs 2901163953Srrs /* go through the addresses in the init-ack */ 2902221249Stuexen ph = (struct sctp_paramhdr *) 2903221249Stuexen sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr), 2904221249Stuexen (uint8_t *) & tmp_param); 2905163953Srrs while (ph != NULL) { 2906163953Srrs ptype = ntohs(ph->param_type); 2907163953Srrs plen = ntohs(ph->param_length); 2908221249Stuexen switch (ptype) { 2909221249Stuexen#ifdef INET6 2910221249Stuexen case SCTP_IPV6_ADDRESS: 2911221249Stuexen { 2912221249Stuexen struct sctp_ipv6addr_param *a6p; 2913163953Srrs 2914221249Stuexen /* get the entire IPv6 address param */ 2915221249Stuexen a6p = (struct sctp_ipv6addr_param *) 2916221249Stuexen sctp_m_getptr(m, offset, 2917221249Stuexen sizeof(struct sctp_ipv6addr_param), 2918221249Stuexen (uint8_t *) & addr_store); 2919221249Stuexen if (plen != sizeof(struct sctp_ipv6addr_param) || 2920221249Stuexen a6p == NULL) { 2921221249Stuexen return; 2922221249Stuexen } 2923221249Stuexen memcpy(&sin6.sin6_addr, a6p->addr, 2924221249Stuexen sizeof(struct in6_addr)); 2925221249Stuexen sa = (struct sockaddr *)&sin6; 2926221249Stuexen break; 2927163953Srrs } 2928221249Stuexen#endif 2929221249Stuexen#ifdef INET 2930221249Stuexen case SCTP_IPV4_ADDRESS: 2931221249Stuexen { 2932221249Stuexen struct sctp_ipv4addr_param *a4p; 2933163953Srrs 2934221249Stuexen /* get the entire IPv4 address param */ 2935221249Stuexen a4p = (struct sctp_ipv4addr_param *)sctp_m_getptr(m, offset, 2936221249Stuexen sizeof(struct sctp_ipv4addr_param), 2937221249Stuexen (uint8_t *) & addr_store); 2938221249Stuexen if (plen != sizeof(struct sctp_ipv4addr_param) || 2939221249Stuexen a4p == NULL) { 2940221249Stuexen return; 2941221249Stuexen } 2942221249Stuexen sin.sin_addr.s_addr = a4p->addr; 2943221249Stuexen sa = (struct sockaddr *)&sin; 2944221410Stuexen break; 2945163953Srrs } 2946221249Stuexen#endif 2947221249Stuexen default: 2948163953Srrs goto next_addr; 2949163953Srrs } 2950163953Srrs 2951163953Srrs /* see if this address really (still) exists */ 2952168299Srrs if (stcb) { 2953168299Srrs vrf_id = stcb->asoc.vrf_id; 2954168299Srrs } else { 2955168299Srrs vrf_id = SCTP_DEFAULT_VRFID; 2956168299Srrs } 2957172190Srrs sctp_ifa = sctp_find_ifa_by_addr(sa, vrf_id, 2958172190Srrs SCTP_ADDR_NOT_LOCKED); 2959167598Srrs if (sctp_ifa == NULL) { 2960163953Srrs /* address doesn't exist anymore */ 2961163953Srrs int status; 2962163953Srrs 2963163953Srrs /* are ASCONFs allowed ? */ 2964163953Srrs if ((sctp_is_feature_on(stcb->sctp_ep, 2965163953Srrs SCTP_PCB_FLAGS_DO_ASCONF)) && 2966163953Srrs stcb->asoc.peer_supports_asconf) { 2967163953Srrs /* queue an ASCONF DEL_IP_ADDRESS */ 2968172190Srrs status = sctp_asconf_queue_sa_delete(stcb, sa); 2969163953Srrs /* 2970171572Srrs * if queued ok, and in correct state, send 2971171572Srrs * out the ASCONF. 2972163953Srrs */ 2973163953Srrs if (status == 0 && 2974163953Srrs SCTP_GET_STATE(&stcb->asoc) == 2975163953Srrs SCTP_STATE_OPEN) { 2976171572Srrs#ifdef SCTP_TIMER_BASED_ASCONF 2977163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, 2978163953Srrs stcb->sctp_ep, stcb, 2979163953Srrs stcb->asoc.primary_destination); 2980171572Srrs#else 2981224641Stuexen sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED); 2982171572Srrs#endif 2983163953Srrs } 2984163953Srrs } 2985163953Srrs } 2986163953Srrsnext_addr: 2987163953Srrs /* 2988163953Srrs * Sanity check: Make sure the length isn't 0, otherwise 2989163953Srrs * we'll be stuck in this loop for a long time... 2990163953Srrs */ 2991163953Srrs if (SCTP_SIZE32(plen) == 0) { 2992169420Srrs SCTP_PRINTF("process_initack_addrs: bad len (%d) type=%xh\n", 2993163953Srrs plen, ptype); 2994163953Srrs return; 2995163953Srrs } 2996163953Srrs /* get next parameter */ 2997163953Srrs offset += SCTP_SIZE32(plen); 2998163953Srrs if ((offset + sizeof(struct sctp_paramhdr)) > length) 2999163953Srrs return; 3000163953Srrs ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset, 3001163953Srrs sizeof(struct sctp_paramhdr), (uint8_t *) & tmp_param); 3002163953Srrs } /* while */ 3003163953Srrs} 3004163953Srrs 3005163953Srrs/* FIX ME: need to verify return result for v6 address type if v6 disabled */ 3006163953Srrs/* 3007163953Srrs * checks to see if a specific address is in the initack address list returns 3008163953Srrs * 1 if found, 0 if not 3009163953Srrs */ 3010163953Srrsstatic uint32_t 3011228653Stuexensctp_addr_in_initack(struct mbuf *m, uint32_t offset, uint32_t length, struct sockaddr *sa) 3012163953Srrs{ 3013163953Srrs struct sctp_paramhdr tmp_param, *ph; 3014163953Srrs uint16_t plen, ptype; 3015163953Srrs struct sctp_ipv6addr_param addr_store; 3016221249Stuexen 3017221249Stuexen#ifdef INET 3018163953Srrs struct sockaddr_in *sin; 3019163953Srrs struct sctp_ipv4addr_param *a4p; 3020163953Srrs 3021221249Stuexen#endif 3022163953Srrs#ifdef INET6 3023167598Srrs struct sockaddr_in6 *sin6; 3024163953Srrs struct sctp_ipv6addr_param *a6p; 3025167598Srrs struct sockaddr_in6 sin6_tmp; 3026163953Srrs 3027221249Stuexen#endif 3028163953Srrs 3029221249Stuexen switch (sa->sa_family) { 3030221249Stuexen#ifdef INET 3031221249Stuexen case AF_INET: 3032221249Stuexen break; 3033221249Stuexen#endif 3034163953Srrs#ifdef INET6 3035221249Stuexen case AF_INET6: 3036221249Stuexen break; 3037221249Stuexen#endif 3038221249Stuexen default: 3039163953Srrs return (0); 3040221249Stuexen } 3041163953Srrs 3042169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF2, "find_initack_addr: starting search for "); 3043169420Srrs SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa); 3044163953Srrs /* convert to upper bound */ 3045163953Srrs length += offset; 3046163953Srrs 3047163953Srrs if ((offset + sizeof(struct sctp_paramhdr)) > length) { 3048169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 3049169420Srrs "find_initack_addr: invalid offset?\n"); 3050163953Srrs return (0); 3051163953Srrs } 3052163953Srrs /* go through the addresses in the init-ack */ 3053163953Srrs ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset, 3054163953Srrs sizeof(struct sctp_paramhdr), (uint8_t *) & tmp_param); 3055163953Srrs while (ph != NULL) { 3056163953Srrs ptype = ntohs(ph->param_type); 3057163953Srrs plen = ntohs(ph->param_length); 3058221249Stuexen switch (ptype) { 3059163953Srrs#ifdef INET6 3060221249Stuexen case SCTP_IPV6_ADDRESS: 3061221249Stuexen if (sa->sa_family == AF_INET6) { 3062221249Stuexen /* get the entire IPv6 address param */ 3063221249Stuexen if (plen != sizeof(struct sctp_ipv6addr_param)) { 3064221249Stuexen break; 3065221249Stuexen } 3066221249Stuexen /* get the entire IPv6 address param */ 3067221249Stuexen a6p = (struct sctp_ipv6addr_param *) 3068221249Stuexen sctp_m_getptr(m, offset, 3069221249Stuexen sizeof(struct sctp_ipv6addr_param), 3070221249Stuexen (uint8_t *) & addr_store); 3071221249Stuexen if (a6p == NULL) { 3072221249Stuexen return (0); 3073221249Stuexen } 3074221249Stuexen sin6 = (struct sockaddr_in6 *)sa; 3075221249Stuexen if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) { 3076221249Stuexen /* create a copy and clear scope */ 3077221249Stuexen memcpy(&sin6_tmp, sin6, 3078221249Stuexen sizeof(struct sockaddr_in6)); 3079221249Stuexen sin6 = &sin6_tmp; 3080221249Stuexen in6_clearscope(&sin6->sin6_addr); 3081221249Stuexen } 3082221249Stuexen if (memcmp(&sin6->sin6_addr, a6p->addr, 3083221249Stuexen sizeof(struct in6_addr)) == 0) { 3084221249Stuexen /* found it */ 3085221249Stuexen return (1); 3086221249Stuexen } 3087163953Srrs } 3088221249Stuexen break; 3089163953Srrs#endif /* INET6 */ 3090221249Stuexen#ifdef INET 3091221249Stuexen case SCTP_IPV4_ADDRESS: 3092221249Stuexen if (sa->sa_family == AF_INET) { 3093221249Stuexen if (plen != sizeof(struct sctp_ipv4addr_param)) { 3094221249Stuexen break; 3095221249Stuexen } 3096221249Stuexen /* get the entire IPv4 address param */ 3097221249Stuexen a4p = (struct sctp_ipv4addr_param *) 3098221249Stuexen sctp_m_getptr(m, offset, 3099221249Stuexen sizeof(struct sctp_ipv4addr_param), 3100221249Stuexen (uint8_t *) & addr_store); 3101221249Stuexen if (a4p == NULL) { 3102221249Stuexen return (0); 3103221249Stuexen } 3104221249Stuexen sin = (struct sockaddr_in *)sa; 3105221249Stuexen if (sin->sin_addr.s_addr == a4p->addr) { 3106221249Stuexen /* found it */ 3107221249Stuexen return (1); 3108221249Stuexen } 3109163953Srrs } 3110221249Stuexen break; 3111221249Stuexen#endif 3112221249Stuexen default: 3113221249Stuexen break; 3114163953Srrs } 3115163953Srrs /* get next parameter */ 3116163953Srrs offset += SCTP_SIZE32(plen); 3117221249Stuexen if (offset + sizeof(struct sctp_paramhdr) > length) { 3118163953Srrs return (0); 3119221249Stuexen } 3120163953Srrs ph = (struct sctp_paramhdr *) 3121163953Srrs sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr), 3122163953Srrs (uint8_t *) & tmp_param); 3123163953Srrs } /* while */ 3124163953Srrs /* not found! */ 3125163953Srrs return (0); 3126163953Srrs} 3127163953Srrs 3128163953Srrs/* 3129163953Srrs * makes sure that the current endpoint local addr list is consistent with 3130163953Srrs * the new association (eg. subset bound, asconf allowed) adds addresses as 3131163953Srrs * necessary 3132163953Srrs */ 3133163953Srrsstatic void 3134163953Srrssctp_check_address_list_ep(struct sctp_tcb *stcb, struct mbuf *m, int offset, 3135163953Srrs int length, struct sockaddr *init_addr) 3136163953Srrs{ 3137163953Srrs struct sctp_laddr *laddr; 3138163953Srrs 3139163953Srrs /* go through the endpoint list */ 3140163953Srrs LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) { 3141163953Srrs /* be paranoid and validate the laddr */ 3142163953Srrs if (laddr->ifa == NULL) { 3143169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 3144169420Srrs "check_addr_list_ep: laddr->ifa is NULL"); 3145163953Srrs continue; 3146163953Srrs } 3147167598Srrs if (laddr->ifa == NULL) { 3148169420Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "check_addr_list_ep: laddr->ifa->ifa_addr is NULL"); 3149163953Srrs continue; 3150163953Srrs } 3151163953Srrs /* do i have it implicitly? */ 3152167598Srrs if (sctp_cmpaddr(&laddr->ifa->address.sa, init_addr)) { 3153163953Srrs continue; 3154163953Srrs } 3155163953Srrs /* check to see if in the init-ack */ 3156228653Stuexen if (!sctp_addr_in_initack(m, offset, length, &laddr->ifa->address.sa)) { 3157163953Srrs /* try to add it */ 3158163953Srrs sctp_addr_mgmt_assoc(stcb->sctp_ep, stcb, laddr->ifa, 3159172190Srrs SCTP_ADD_IP_ADDRESS, SCTP_ADDR_NOT_LOCKED); 3160163953Srrs } 3161163953Srrs } 3162163953Srrs} 3163163953Srrs 3164163953Srrs/* 3165163953Srrs * makes sure that the current kernel address list is consistent with the new 3166163953Srrs * association (with all addrs bound) adds addresses as necessary 3167163953Srrs */ 3168163953Srrsstatic void 3169163953Srrssctp_check_address_list_all(struct sctp_tcb *stcb, struct mbuf *m, int offset, 3170163953Srrs int length, struct sockaddr *init_addr, 3171163953Srrs uint16_t local_scope, uint16_t site_scope, 3172163953Srrs uint16_t ipv4_scope, uint16_t loopback_scope) 3173163953Srrs{ 3174167598Srrs struct sctp_vrf *vrf = NULL; 3175167598Srrs struct sctp_ifn *sctp_ifn; 3176167598Srrs struct sctp_ifa *sctp_ifa; 3177167598Srrs uint32_t vrf_id; 3178163953Srrs 3179228653Stuexen#ifdef INET 3180228653Stuexen struct sockaddr_in *sin; 3181228653Stuexen 3182228653Stuexen#endif 3183228653Stuexen#ifdef INET6 3184228653Stuexen struct sockaddr_in6 *sin6; 3185228653Stuexen 3186228653Stuexen#endif 3187228653Stuexen 3188168299Srrs if (stcb) { 3189168299Srrs vrf_id = stcb->asoc.vrf_id; 3190168299Srrs } else { 3191169420Srrs return; 3192168299Srrs } 3193172218Srrs SCTP_IPI_ADDR_RLOCK(); 3194167598Srrs vrf = sctp_find_vrf(vrf_id); 3195167598Srrs if (vrf == NULL) { 3196172218Srrs SCTP_IPI_ADDR_RUNLOCK(); 3197167598Srrs return; 3198167598Srrs } 3199163953Srrs /* go through all our known interfaces */ 3200167598Srrs LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) { 3201167598Srrs if (loopback_scope == 0 && SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) { 3202163953Srrs /* skip loopback interface */ 3203163953Srrs continue; 3204163953Srrs } 3205163953Srrs /* go through each interface address */ 3206167598Srrs LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) { 3207163953Srrs /* do i have it implicitly? */ 3208167598Srrs if (sctp_cmpaddr(&sctp_ifa->address.sa, init_addr)) { 3209163953Srrs continue; 3210163953Srrs } 3211228653Stuexen switch (sctp_ifa->address.sa.sa_family) { 3212228653Stuexen#ifdef INET 3213228653Stuexen case AF_INET: 3214228653Stuexen sin = (struct sockaddr_in *)&sctp_ifa->address.sin; 3215228653Stuexen if ((ipv4_scope == 0) && 3216228653Stuexen (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) { 3217228653Stuexen /* private address not in scope */ 3218228653Stuexen continue; 3219228653Stuexen } 3220228653Stuexen break; 3221228653Stuexen#endif 3222228653Stuexen#ifdef INET6 3223228653Stuexen case AF_INET6: 3224228653Stuexen sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sin6; 3225228653Stuexen if ((local_scope == 0) && 3226228653Stuexen (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))) { 3227228653Stuexen continue; 3228228653Stuexen } 3229228653Stuexen if ((site_scope == 0) && 3230228653Stuexen (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) { 3231228653Stuexen continue; 3232228653Stuexen } 3233228653Stuexen break; 3234228653Stuexen#endif 3235228653Stuexen default: 3236228653Stuexen break; 3237228653Stuexen } 3238163953Srrs /* check to see if in the init-ack */ 3239228653Stuexen if (!sctp_addr_in_initack(m, offset, length, &sctp_ifa->address.sa)) { 3240163953Srrs /* try to add it */ 3241163953Srrs sctp_addr_mgmt_assoc(stcb->sctp_ep, stcb, 3242172190Srrs sctp_ifa, SCTP_ADD_IP_ADDRESS, 3243172190Srrs SCTP_ADDR_LOCKED); 3244163953Srrs } 3245163953Srrs } /* end foreach ifa */ 3246163953Srrs } /* end foreach ifn */ 3247172218Srrs SCTP_IPI_ADDR_RUNLOCK(); 3248163953Srrs} 3249163953Srrs 3250163953Srrs/* 3251163953Srrs * validates an init-ack chunk (from a cookie-echo) with current addresses 3252163953Srrs * adds addresses from the init-ack into our local address list, if needed 3253163953Srrs * queues asconf adds/deletes addresses as needed and makes appropriate list 3254163953Srrs * changes for source address selection m, offset: points to the start of the 3255163953Srrs * address list in an init-ack chunk length: total length of the address 3256163953Srrs * params only init_addr: address where my INIT-ACK was sent from 3257163953Srrs */ 3258163953Srrsvoid 3259163953Srrssctp_check_address_list(struct sctp_tcb *stcb, struct mbuf *m, int offset, 3260163953Srrs int length, struct sockaddr *init_addr, 3261163953Srrs uint16_t local_scope, uint16_t site_scope, 3262163953Srrs uint16_t ipv4_scope, uint16_t loopback_scope) 3263163953Srrs{ 3264163953Srrs /* process the local addresses in the initack */ 3265163953Srrs sctp_process_initack_addresses(stcb, m, offset, length); 3266163953Srrs 3267163953Srrs if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { 3268163953Srrs /* bound all case */ 3269163953Srrs sctp_check_address_list_all(stcb, m, offset, length, init_addr, 3270163953Srrs local_scope, site_scope, ipv4_scope, loopback_scope); 3271163953Srrs } else { 3272163953Srrs /* subset bound case */ 3273163953Srrs if (sctp_is_feature_on(stcb->sctp_ep, 3274163953Srrs SCTP_PCB_FLAGS_DO_ASCONF)) { 3275163953Srrs /* asconf's allowed */ 3276163953Srrs sctp_check_address_list_ep(stcb, m, offset, length, 3277163953Srrs init_addr); 3278163953Srrs } 3279163953Srrs /* else, no asconfs allowed, so what we sent is what we get */ 3280163953Srrs } 3281163953Srrs} 3282163953Srrs 3283163953Srrs/* 3284163953Srrs * sctp_bindx() support 3285163953Srrs */ 3286163953Srrsuint32_t 3287169655Srrssctp_addr_mgmt_ep_sa(struct sctp_inpcb *inp, struct sockaddr *sa, 3288170744Srrs uint32_t type, uint32_t vrf_id, struct sctp_ifa *sctp_ifap) 3289163953Srrs{ 3290167598Srrs struct sctp_ifa *ifa; 3291218521Stuexen struct sctp_laddr *laddr, *nladdr; 3292163953Srrs 3293167598Srrs if (sa->sa_len == 0) { 3294171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EINVAL); 3295163953Srrs return (EINVAL); 3296167598Srrs } 3297170744Srrs if (sctp_ifap) { 3298170744Srrs ifa = sctp_ifap; 3299170744Srrs } else if (type == SCTP_ADD_IP_ADDRESS) { 3300167598Srrs /* For an add the address MUST be on the system */ 3301172091Srrs ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED); 3302167598Srrs } else if (type == SCTP_DEL_IP_ADDRESS) { 3303167598Srrs /* For a delete we need to find it in the inp */ 3304172091Srrs ifa = sctp_find_ifa_in_ep(inp, sa, SCTP_ADDR_NOT_LOCKED); 3305167598Srrs } else { 3306167598Srrs ifa = NULL; 3307167598Srrs } 3308163953Srrs if (ifa != NULL) { 3309167598Srrs if (type == SCTP_ADD_IP_ADDRESS) { 3310167598Srrs sctp_add_local_addr_ep(inp, ifa, type); 3311167598Srrs } else if (type == SCTP_DEL_IP_ADDRESS) { 3312169655Srrs if (inp->laddr_count < 2) { 3313169655Srrs /* can't delete the last local address */ 3314171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EINVAL); 3315169655Srrs return (EINVAL); 3316169655Srrs } 3317169655Srrs LIST_FOREACH(laddr, &inp->sctp_addr_list, 3318169655Srrs sctp_nxt_addr) { 3319167598Srrs if (ifa == laddr->ifa) { 3320167598Srrs /* Mark in the delete */ 3321167598Srrs laddr->action = type; 3322167598Srrs } 3323163953Srrs } 3324163953Srrs } 3325218521Stuexen if (LIST_EMPTY(&inp->sctp_asoc_list)) { 3326199372Stuexen /* 3327199372Stuexen * There is no need to start the iterator if the inp 3328199372Stuexen * has no associations. 3329199372Stuexen */ 3330218521Stuexen if (type == SCTP_DEL_IP_ADDRESS) { 3331218521Stuexen LIST_FOREACH_SAFE(laddr, &inp->sctp_addr_list, sctp_nxt_addr, nladdr) { 3332218521Stuexen if (laddr->ifa == ifa) { 3333218521Stuexen sctp_del_local_addr_ep(inp, ifa); 3334218521Stuexen } 3335218521Stuexen } 3336218521Stuexen } 3337218521Stuexen } else { 3338199372Stuexen struct sctp_asconf_iterator *asc; 3339199372Stuexen struct sctp_laddr *wi; 3340199372Stuexen 3341199372Stuexen SCTP_MALLOC(asc, struct sctp_asconf_iterator *, 3342199372Stuexen sizeof(struct sctp_asconf_iterator), 3343199372Stuexen SCTP_M_ASC_IT); 3344199372Stuexen if (asc == NULL) { 3345199372Stuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, ENOMEM); 3346199372Stuexen return (ENOMEM); 3347199372Stuexen } 3348199372Stuexen wi = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_laddr), struct sctp_laddr); 3349199372Stuexen if (wi == NULL) { 3350199372Stuexen SCTP_FREE(asc, SCTP_M_ASC_IT); 3351199372Stuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, ENOMEM); 3352199372Stuexen return (ENOMEM); 3353199372Stuexen } 3354199372Stuexen LIST_INIT(&asc->list_of_work); 3355199372Stuexen asc->cnt = 1; 3356199372Stuexen SCTP_INCR_LADDR_COUNT(); 3357199372Stuexen wi->ifa = ifa; 3358199372Stuexen wi->action = type; 3359199372Stuexen atomic_add_int(&ifa->refcount, 1); 3360199372Stuexen LIST_INSERT_HEAD(&asc->list_of_work, wi, sctp_nxt_addr); 3361199372Stuexen (void)sctp_initiate_iterator(sctp_asconf_iterator_ep, 3362199372Stuexen sctp_asconf_iterator_stcb, 3363199372Stuexen sctp_asconf_iterator_ep_end, 3364199372Stuexen SCTP_PCB_ANY_FLAGS, 3365199372Stuexen SCTP_PCB_ANY_FEATURES, 3366199372Stuexen SCTP_ASOC_ANY_STATE, 3367199372Stuexen (void *)asc, 0, 3368199372Stuexen sctp_asconf_iterator_end, inp, 0); 3369199372Stuexen } 3370199372Stuexen return (0); 3371163953Srrs } else { 3372163953Srrs /* invalid address! */ 3373171943Srrs SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EADDRNOTAVAIL); 3374163953Srrs return (EADDRNOTAVAIL); 3375163953Srrs } 3376163953Srrs} 3377185694Srrs 3378185694Srrsvoid 3379185694Srrssctp_asconf_send_nat_state_update(struct sctp_tcb *stcb, 3380185694Srrs struct sctp_nets *net) 3381185694Srrs{ 3382185694Srrs struct sctp_asconf_addr *aa; 3383185694Srrs struct sctp_ifa *sctp_ifap; 3384185694Srrs struct sctp_asconf_tag_param *vtag; 3385221249Stuexen 3386221249Stuexen#ifdef INET 3387185694Srrs struct sockaddr_in *to; 3388185694Srrs 3389221249Stuexen#endif 3390185694Srrs#ifdef INET6 3391185694Srrs struct sockaddr_in6 *to6; 3392185694Srrs 3393185694Srrs#endif 3394185694Srrs if (net == NULL) { 3395185694Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "sctp_asconf_send_nat_state_update: Missing net\n"); 3396185694Srrs return; 3397185694Srrs } 3398185694Srrs if (stcb == NULL) { 3399185694Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "sctp_asconf_send_nat_state_update: Missing stcb\n"); 3400185694Srrs return; 3401185694Srrs } 3402185694Srrs /* 3403185694Srrs * Need to have in the asconf: - vtagparam(my_vtag/peer_vtag) - 3404185694Srrs * add(0.0.0.0) - del(0.0.0.0) - Any global addresses add(addr) 3405185694Srrs */ 3406185694Srrs SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa), 3407185694Srrs SCTP_M_ASC_ADDR); 3408185694Srrs if (aa == NULL) { 3409185694Srrs /* didn't get memory */ 3410185694Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 3411185694Srrs "sctp_asconf_send_nat_state_update: failed to get memory!\n"); 3412185694Srrs return; 3413185694Srrs } 3414185694Srrs aa->special_del = 0; 3415185694Srrs /* fill in asconf address parameter fields */ 3416185694Srrs /* top level elements are "networked" during send */ 3417185694Srrs aa->ifa = NULL; 3418185694Srrs aa->sent = 0; /* clear sent flag */ 3419185694Srrs vtag = (struct sctp_asconf_tag_param *)&aa->ap.aph; 3420185694Srrs vtag->aph.ph.param_type = SCTP_NAT_VTAGS; 3421185694Srrs vtag->aph.ph.param_length = sizeof(struct sctp_asconf_tag_param); 3422185694Srrs vtag->local_vtag = htonl(stcb->asoc.my_vtag); 3423185694Srrs vtag->remote_vtag = htonl(stcb->asoc.peer_vtag); 3424185694Srrs TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next); 3425185694Srrs 3426185694Srrs SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa), 3427185694Srrs SCTP_M_ASC_ADDR); 3428185694Srrs if (aa == NULL) { 3429185694Srrs /* didn't get memory */ 3430185694Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 3431185694Srrs "sctp_asconf_send_nat_state_update: failed to get memory!\n"); 3432185694Srrs return; 3433185694Srrs } 3434185694Srrs memset(aa, 0, sizeof(struct sctp_asconf_addr)); 3435185694Srrs /* fill in asconf address parameter fields */ 3436185694Srrs /* ADD(0.0.0.0) */ 3437221249Stuexen switch (net->ro._l_addr.sa.sa_family) { 3438221249Stuexen#ifdef INET 3439221249Stuexen case AF_INET: 3440185694Srrs aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS; 3441185694Srrs aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addrv4_param); 3442185694Srrs aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS; 3443185694Srrs aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv4addr_param); 3444185694Srrs /* No need to add an address, we are using 0.0.0.0 */ 3445185694Srrs TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next); 3446221249Stuexen break; 3447221249Stuexen#endif 3448185694Srrs#ifdef INET6 3449221249Stuexen case AF_INET6: 3450185694Srrs aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS; 3451185694Srrs aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addr_param); 3452185694Srrs aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS; 3453185694Srrs aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv6addr_param); 3454185694Srrs /* No need to add an address, we are using 0.0.0.0 */ 3455185694Srrs TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next); 3456221249Stuexen break; 3457221249Stuexen#endif 3458185694Srrs } 3459185694Srrs SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa), 3460185694Srrs SCTP_M_ASC_ADDR); 3461185694Srrs if (aa == NULL) { 3462185694Srrs /* didn't get memory */ 3463185694Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, 3464185694Srrs "sctp_asconf_send_nat_state_update: failed to get memory!\n"); 3465185694Srrs return; 3466185694Srrs } 3467185694Srrs memset(aa, 0, sizeof(struct sctp_asconf_addr)); 3468185694Srrs /* fill in asconf address parameter fields */ 3469185694Srrs /* ADD(0.0.0.0) */ 3470221249Stuexen switch (net->ro._l_addr.sa.sa_family) { 3471221249Stuexen#ifdef INET 3472221249Stuexen case AF_INET: 3473185694Srrs aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS; 3474185694Srrs aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addrv4_param); 3475185694Srrs aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS; 3476185694Srrs aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv4addr_param); 3477185694Srrs /* No need to add an address, we are using 0.0.0.0 */ 3478185694Srrs TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next); 3479221249Stuexen break; 3480221249Stuexen#endif 3481185694Srrs#ifdef INET6 3482221249Stuexen case AF_INET6: 3483185694Srrs aa->ap.aph.ph.param_type = SCTP_DEL_IP_ADDRESS; 3484185694Srrs aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addr_param); 3485185694Srrs aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS; 3486185694Srrs aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv6addr_param); 3487185694Srrs /* No need to add an address, we are using 0.0.0.0 */ 3488185694Srrs TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next); 3489221249Stuexen break; 3490221249Stuexen#endif 3491185694Srrs } 3492185694Srrs /* Now we must hunt the addresses and add all global addresses */ 3493185694Srrs if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { 3494185694Srrs struct sctp_vrf *vrf = NULL; 3495185694Srrs struct sctp_ifn *sctp_ifnp; 3496185694Srrs uint32_t vrf_id; 3497185694Srrs 3498185694Srrs vrf_id = stcb->sctp_ep->def_vrf_id; 3499185694Srrs vrf = sctp_find_vrf(vrf_id); 3500185694Srrs if (vrf == NULL) { 3501185694Srrs goto skip_rest; 3502185694Srrs } 3503185694Srrs SCTP_IPI_ADDR_RLOCK(); 3504185694Srrs LIST_FOREACH(sctp_ifnp, &vrf->ifnlist, next_ifn) { 3505185694Srrs LIST_FOREACH(sctp_ifap, &sctp_ifnp->ifalist, next_ifa) { 3506221249Stuexen switch (sctp_ifap->address.sa.sa_family) { 3507221249Stuexen#ifdef INET 3508221249Stuexen case AF_INET: 3509185694Srrs to = &sctp_ifap->address.sin; 3510185694Srrs if (IN4_ISPRIVATE_ADDRESS(&to->sin_addr)) { 3511185694Srrs continue; 3512185694Srrs } 3513185694Srrs if (IN4_ISLOOPBACK_ADDRESS(&to->sin_addr)) { 3514185694Srrs continue; 3515185694Srrs } 3516221249Stuexen break; 3517221249Stuexen#endif 3518185694Srrs#ifdef INET6 3519221249Stuexen case AF_INET6: 3520185694Srrs to6 = &sctp_ifap->address.sin6; 3521185694Srrs if (IN6_IS_ADDR_LOOPBACK(&to6->sin6_addr)) { 3522185694Srrs continue; 3523185694Srrs } 3524185694Srrs if (IN6_IS_ADDR_LINKLOCAL(&to6->sin6_addr)) { 3525185694Srrs continue; 3526185694Srrs } 3527221249Stuexen break; 3528221249Stuexen#endif 3529221249Stuexen default: 3530221249Stuexen continue; 3531185694Srrs } 3532185694Srrs sctp_asconf_queue_mgmt(stcb, sctp_ifap, SCTP_ADD_IP_ADDRESS); 3533185694Srrs } 3534185694Srrs } 3535185694Srrs SCTP_IPI_ADDR_RUNLOCK(); 3536185694Srrs } else { 3537185694Srrs struct sctp_laddr *laddr; 3538185694Srrs 3539185694Srrs LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) { 3540185694Srrs if (laddr->ifa == NULL) { 3541185694Srrs continue; 3542185694Srrs } 3543185694Srrs if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED) 3544185694Srrs /* 3545185694Srrs * Address being deleted by the system, dont 3546185694Srrs * list. 3547185694Srrs */ 3548185694Srrs continue; 3549185694Srrs if (laddr->action == SCTP_DEL_IP_ADDRESS) { 3550185694Srrs /* 3551185694Srrs * Address being deleted on this ep don't 3552185694Srrs * list. 3553185694Srrs */ 3554185694Srrs continue; 3555185694Srrs } 3556185694Srrs sctp_ifap = laddr->ifa; 3557221249Stuexen switch (sctp_ifap->address.sa.sa_family) { 3558221249Stuexen#ifdef INET 3559221249Stuexen case AF_INET: 3560185694Srrs to = &sctp_ifap->address.sin; 3561185694Srrs if (IN4_ISPRIVATE_ADDRESS(&to->sin_addr)) { 3562185694Srrs continue; 3563185694Srrs } 3564185694Srrs if (IN4_ISLOOPBACK_ADDRESS(&to->sin_addr)) { 3565185694Srrs continue; 3566185694Srrs } 3567221249Stuexen break; 3568221249Stuexen#endif 3569185694Srrs#ifdef INET6 3570221249Stuexen case AF_INET6: 3571185694Srrs to6 = &sctp_ifap->address.sin6; 3572185694Srrs if (IN6_IS_ADDR_LOOPBACK(&to6->sin6_addr)) { 3573185694Srrs continue; 3574185694Srrs } 3575185694Srrs if (IN6_IS_ADDR_LINKLOCAL(&to6->sin6_addr)) { 3576185694Srrs continue; 3577185694Srrs } 3578221249Stuexen break; 3579221249Stuexen#endif 3580221249Stuexen default: 3581221249Stuexen continue; 3582185694Srrs } 3583185694Srrs sctp_asconf_queue_mgmt(stcb, sctp_ifap, SCTP_ADD_IP_ADDRESS); 3584185694Srrs } 3585185694Srrs } 3586185694Srrsskip_rest: 3587185694Srrs /* Now we must send the asconf into the queue */ 3588224641Stuexen sctp_send_asconf(stcb, net, SCTP_ADDR_NOT_LOCKED); 3589185694Srrs} 3590