1163953Srrs/*- 2185694Srrs * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved. 3235828Stuexen * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. 4235828Stuexen * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. 5163953Srrs * 6163953Srrs * Redistribution and use in source and binary forms, with or without 7163953Srrs * modification, are permitted provided that the following conditions are met: 8163953Srrs * 9163953Srrs * a) Redistributions of source code must retain the above copyright notice, 10228653Stuexen * this list of conditions and the following disclaimer. 11163953Srrs * 12163953Srrs * b) Redistributions in binary form must reproduce the above copyright 13163953Srrs * notice, this list of conditions and the following disclaimer in 14228653Stuexen * the documentation and/or other materials provided with the distribution. 15163953Srrs * 16163953Srrs * c) Neither the name of Cisco Systems, Inc. nor the names of its 17163953Srrs * contributors may be used to endorse or promote products derived 18163953Srrs * from this software without specific prior written permission. 19163953Srrs * 20163953Srrs * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21163953Srrs * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 22163953Srrs * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23163953Srrs * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24163953Srrs * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25163953Srrs * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26163953Srrs * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27163953Srrs * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28163953Srrs * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29163953Srrs * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30163953Srrs * THE POSSIBILITY OF SUCH DAMAGE. 31163953Srrs */ 32163953Srrs 33163953Srrs#include <sys/cdefs.h> 34163953Srrs__FBSDID("$FreeBSD$"); 35163953Srrs 36166086Srrs#include <netinet/sctp_os.h> 37163953Srrs#include <sys/proc.h> 38163953Srrs#include <netinet/sctp_var.h> 39167598Srrs#include <netinet/sctp_sysctl.h> 40163953Srrs#include <netinet/sctp_pcb.h> 41163953Srrs#include <netinet/sctputil.h> 42163953Srrs#include <netinet/sctp.h> 43163953Srrs#include <netinet/sctp_header.h> 44163953Srrs#include <netinet/sctp_asconf.h> 45163953Srrs#include <netinet/sctp_output.h> 46163953Srrs#include <netinet/sctp_timer.h> 47167598Srrs#include <netinet/sctp_bsd_addr.h> 48215817Srrs#include <netinet/sctp_dtrace_define.h> 49270350Stuexen#if defined(INET) || defined(INET6) 50179157Srrs#include <netinet/udp.h> 51270350Stuexen#endif 52225549Stuexen#ifdef INET6 53225549Stuexen#include <netinet6/ip6_var.h> 54225549Stuexen#endif 55218211Srrs#include <sys/sched.h> 56218211Srrs#include <sys/smp.h> 57218211Srrs#include <sys/unistd.h> 58163953Srrs 59163953Srrs 60197288SrrsVNET_DEFINE(struct sctp_base_info, system_base_info); 61179157Srrs 62163953Srrs/* FIX: we don't handle multiple link local scopes */ 63163953Srrs/* "scopeless" replacement IN6_ARE_ADDR_EQUAL */ 64178251Srrs#ifdef INET6 65163953Srrsint 66179157SrrsSCTP6_ARE_ADDR_EQUAL(struct sockaddr_in6 *a, struct sockaddr_in6 *b) 67163953Srrs{ 68179157Srrs struct sockaddr_in6 tmp_a, tmp_b; 69163953Srrs 70179157Srrs memcpy(&tmp_a, a, sizeof(struct sockaddr_in6)); 71197288Srrs if (sa6_embedscope(&tmp_a, MODULE_GLOBAL(ip6_use_defzone)) != 0) { 72228907Stuexen return (0); 73179157Srrs } 74179157Srrs memcpy(&tmp_b, b, sizeof(struct sockaddr_in6)); 75197288Srrs if (sa6_embedscope(&tmp_b, MODULE_GLOBAL(ip6_use_defzone)) != 0) { 76228907Stuexen return (0); 77179157Srrs } 78179157Srrs return (IN6_ARE_ADDR_EQUAL(&tmp_a.sin6_addr, &tmp_b.sin6_addr)); 79163953Srrs} 80163953Srrs 81178251Srrs#endif 82178251Srrs 83163953Srrsvoid 84163953Srrssctp_fill_pcbinfo(struct sctp_pcbinfo *spcb) 85163953Srrs{ 86163953Srrs /* 87163953Srrs * We really don't need to lock this, but I will just because it 88163953Srrs * does not hurt. 89163953Srrs */ 90163953Srrs SCTP_INP_INFO_RLOCK(); 91179783Srrs spcb->ep_count = SCTP_BASE_INFO(ipi_count_ep); 92179783Srrs spcb->asoc_count = SCTP_BASE_INFO(ipi_count_asoc); 93179783Srrs spcb->laddr_count = SCTP_BASE_INFO(ipi_count_laddr); 94179783Srrs spcb->raddr_count = SCTP_BASE_INFO(ipi_count_raddr); 95179783Srrs spcb->chk_count = SCTP_BASE_INFO(ipi_count_chunk); 96179783Srrs spcb->readq_count = SCTP_BASE_INFO(ipi_count_readq); 97179783Srrs spcb->stream_oque = SCTP_BASE_INFO(ipi_count_strmoq); 98179783Srrs spcb->free_chunks = SCTP_BASE_INFO(ipi_free_chunks); 99163953Srrs SCTP_INP_INFO_RUNLOCK(); 100163953Srrs} 101163953Srrs 102246595Stuexen/*- 103167598Srrs * Addresses are added to VRF's (Virtual Router's). For BSD we 104167598Srrs * have only the default VRF 0. We maintain a hash list of 105167598Srrs * VRF's. Each VRF has its own list of sctp_ifn's. Each of 106167598Srrs * these has a list of addresses. When we add a new address 107167598Srrs * to a VRF we lookup the ifn/ifn_index, if the ifn does 108167598Srrs * not exist we create it and add it to the list of IFN's 109167598Srrs * within the VRF. Once we have the sctp_ifn, we add the 110167598Srrs * address to the list. So we look something like: 111167598Srrs * 112167598Srrs * hash-vrf-table 113167598Srrs * vrf-> ifn-> ifn -> ifn 114167598Srrs * vrf | 115167598Srrs * ... +--ifa-> ifa -> ifa 116167598Srrs * vrf 117167598Srrs * 118215034Sbrucec * We keep these separate lists since the SCTP subsystem will 119167598Srrs * point to these from its source address selection nets structure. 120167598Srrs * When an address is deleted it does not happen right away on 121167598Srrs * the SCTP side, it gets scheduled. What we do when a 122167598Srrs * delete happens is immediately remove the address from 123167598Srrs * the master list and decrement the refcount. As our 124167598Srrs * addip iterator works through and frees the src address 125167598Srrs * selection pointing to the sctp_ifa, eventually the refcount 126167598Srrs * will reach 0 and we will delete it. Note that it is assumed 127167598Srrs * that any locking on system level ifn/ifa is done at the 128167598Srrs * caller of these functions and these routines will only 129167598Srrs * lock the SCTP structures as they add or delete things. 130167598Srrs * 131167598Srrs * Other notes on VRF concepts. 132167598Srrs * - An endpoint can be in multiple VRF's 133167598Srrs * - An association lives within a VRF and only one VRF. 134167598Srrs * - Any incoming packet we can deduce the VRF for by 135167598Srrs * looking at the mbuf/pak inbound (for BSD its VRF=0 :D) 136167598Srrs * - Any downward send call or connect call must supply the 137167598Srrs * VRF via ancillary data or via some sort of set default 138167598Srrs * VRF socket option call (again for BSD no brainer since 139167598Srrs * the VRF is always 0). 140167598Srrs * - An endpoint may add multiple VRF's to it. 141167598Srrs * - Listening sockets can accept associations in any 142167598Srrs * of the VRF's they are in but the assoc will end up 143167598Srrs * in only one VRF (gotten from the packet or connect/send). 144167598Srrs * 145167598Srrs */ 146163953Srrs 147167598Srrsstruct sctp_vrf * 148169352Srrssctp_allocate_vrf(int vrf_id) 149167598Srrs{ 150167598Srrs struct sctp_vrf *vrf = NULL; 151167598Srrs struct sctp_vrflist *bucket; 152167598Srrs 153167598Srrs /* First allocate the VRF structure */ 154169352Srrs vrf = sctp_find_vrf(vrf_id); 155167598Srrs if (vrf) { 156167598Srrs /* Already allocated */ 157167598Srrs return (vrf); 158167598Srrs } 159167598Srrs SCTP_MALLOC(vrf, struct sctp_vrf *, sizeof(struct sctp_vrf), 160170091Srrs SCTP_M_VRF); 161167598Srrs if (vrf == NULL) { 162167598Srrs /* No memory */ 163167598Srrs#ifdef INVARIANTS 164169352Srrs panic("No memory for VRF:%d", vrf_id); 165167598Srrs#endif 166167598Srrs return (NULL); 167167598Srrs } 168167598Srrs /* setup the VRF */ 169167598Srrs memset(vrf, 0, sizeof(struct sctp_vrf)); 170169352Srrs vrf->vrf_id = vrf_id; 171167598Srrs LIST_INIT(&vrf->ifnlist); 172167598Srrs vrf->total_ifa_count = 0; 173170744Srrs vrf->refcount = 0; 174170205Srrs /* now also setup table ids */ 175170205Srrs SCTP_INIT_VRF_TABLEID(vrf); 176167698Srrs /* Init the HASH of addresses */ 177169352Srrs vrf->vrf_addr_hash = SCTP_HASH_INIT(SCTP_VRF_ADDR_HASH_SIZE, 178169352Srrs &vrf->vrf_addr_hashmark); 179167698Srrs if (vrf->vrf_addr_hash == NULL) { 180167698Srrs /* No memory */ 181167698Srrs#ifdef INVARIANTS 182169352Srrs panic("No memory for VRF:%d", vrf_id); 183167698Srrs#endif 184170091Srrs SCTP_FREE(vrf, SCTP_M_VRF); 185167698Srrs return (NULL); 186167698Srrs } 187167598Srrs /* Add it to the hash table */ 188179783Srrs bucket = &SCTP_BASE_INFO(sctp_vrfhash)[(vrf_id & SCTP_BASE_INFO(hashvrfmark))]; 189167598Srrs LIST_INSERT_HEAD(bucket, vrf, next_vrf); 190179783Srrs atomic_add_int(&SCTP_BASE_INFO(ipi_count_vrfs), 1); 191167598Srrs return (vrf); 192167598Srrs} 193167598Srrs 194167598Srrs 195167598Srrsstruct sctp_ifn * 196170205Srrssctp_find_ifn(void *ifn, uint32_t ifn_index) 197167598Srrs{ 198167598Srrs struct sctp_ifn *sctp_ifnp; 199169352Srrs struct sctp_ifnlist *hash_ifn_head; 200167598Srrs 201167598Srrs /* 202215034Sbrucec * We assume the lock is held for the addresses if that's wrong 203167598Srrs * problems could occur :-) 204167598Srrs */ 205179783Srrs hash_ifn_head = &SCTP_BASE_INFO(vrf_ifn_hash)[(ifn_index & SCTP_BASE_INFO(vrf_ifn_hashmark))]; 206169352Srrs LIST_FOREACH(sctp_ifnp, hash_ifn_head, next_bucket) { 207167598Srrs if (sctp_ifnp->ifn_index == ifn_index) { 208167598Srrs return (sctp_ifnp); 209167598Srrs } 210167598Srrs if (sctp_ifnp->ifn_p && ifn && (sctp_ifnp->ifn_p == ifn)) { 211167598Srrs return (sctp_ifnp); 212167598Srrs } 213167598Srrs } 214167598Srrs return (NULL); 215167598Srrs} 216167598Srrs 217169352Srrs 218167598Srrsstruct sctp_vrf * 219169352Srrssctp_find_vrf(uint32_t vrf_id) 220167598Srrs{ 221167598Srrs struct sctp_vrflist *bucket; 222167598Srrs struct sctp_vrf *liste; 223167598Srrs 224179783Srrs bucket = &SCTP_BASE_INFO(sctp_vrfhash)[(vrf_id & SCTP_BASE_INFO(hashvrfmark))]; 225167598Srrs LIST_FOREACH(liste, bucket, next_vrf) { 226169352Srrs if (vrf_id == liste->vrf_id) { 227167598Srrs return (liste); 228167598Srrs } 229167598Srrs } 230167598Srrs return (NULL); 231167598Srrs} 232167598Srrs 233246595Stuexen 234170744Srrsvoid 235170744Srrssctp_free_vrf(struct sctp_vrf *vrf) 236170744Srrs{ 237185694Srrs if (SCTP_DECREMENT_AND_CHECK_REFCOUNT(&vrf->refcount)) { 238176464Srrs if (vrf->vrf_addr_hash) { 239176464Srrs SCTP_HASH_FREE(vrf->vrf_addr_hash, vrf->vrf_addr_hashmark); 240176464Srrs vrf->vrf_addr_hash = NULL; 241176464Srrs } 242170744Srrs /* We zero'd the count */ 243170744Srrs LIST_REMOVE(vrf, next_vrf); 244170744Srrs SCTP_FREE(vrf, SCTP_M_VRF); 245179783Srrs atomic_subtract_int(&SCTP_BASE_INFO(ipi_count_vrfs), 1); 246170744Srrs } 247170744Srrs} 248170744Srrs 249246595Stuexen 250167598Srrsvoid 251169352Srrssctp_free_ifn(struct sctp_ifn *sctp_ifnp) 252169352Srrs{ 253185694Srrs if (SCTP_DECREMENT_AND_CHECK_REFCOUNT(&sctp_ifnp->refcount)) { 254169352Srrs /* We zero'd the count */ 255170744Srrs if (sctp_ifnp->vrf) { 256170744Srrs sctp_free_vrf(sctp_ifnp->vrf); 257170744Srrs } 258170091Srrs SCTP_FREE(sctp_ifnp, SCTP_M_IFN); 259179783Srrs atomic_subtract_int(&SCTP_BASE_INFO(ipi_count_ifns), 1); 260169352Srrs } 261169352Srrs} 262169352Srrs 263246595Stuexen 264169352Srrsvoid 265170205Srrssctp_update_ifn_mtu(uint32_t ifn_index, uint32_t mtu) 266169352Srrs{ 267169352Srrs struct sctp_ifn *sctp_ifnp; 268169352Srrs 269170205Srrs sctp_ifnp = sctp_find_ifn((void *)NULL, ifn_index); 270169352Srrs if (sctp_ifnp != NULL) { 271169352Srrs sctp_ifnp->ifn_mtu = mtu; 272169352Srrs } 273169352Srrs} 274169352Srrs 275169352Srrs 276169352Srrsvoid 277167598Srrssctp_free_ifa(struct sctp_ifa *sctp_ifap) 278167598Srrs{ 279185694Srrs if (SCTP_DECREMENT_AND_CHECK_REFCOUNT(&sctp_ifap->refcount)) { 280167598Srrs /* We zero'd the count */ 281170744Srrs if (sctp_ifap->ifn_p) { 282170744Srrs sctp_free_ifn(sctp_ifap->ifn_p); 283170744Srrs } 284170091Srrs SCTP_FREE(sctp_ifap, SCTP_M_IFA); 285179783Srrs atomic_subtract_int(&SCTP_BASE_INFO(ipi_count_ifas), 1); 286167598Srrs } 287167598Srrs} 288167598Srrs 289246595Stuexen 290169352Srrsstatic void 291169352Srrssctp_delete_ifn(struct sctp_ifn *sctp_ifnp, int hold_addr_lock) 292169352Srrs{ 293169352Srrs struct sctp_ifn *found; 294169352Srrs 295170205Srrs found = sctp_find_ifn(sctp_ifnp->ifn_p, sctp_ifnp->ifn_index); 296169352Srrs if (found == NULL) { 297169352Srrs /* Not in the list.. sorry */ 298169352Srrs return; 299169352Srrs } 300169352Srrs if (hold_addr_lock == 0) 301172218Srrs SCTP_IPI_ADDR_WLOCK(); 302169352Srrs LIST_REMOVE(sctp_ifnp, next_bucket); 303169352Srrs LIST_REMOVE(sctp_ifnp, next_ifn); 304170181Srrs SCTP_DEREGISTER_INTERFACE(sctp_ifnp->ifn_index, 305170181Srrs sctp_ifnp->registered_af); 306169352Srrs if (hold_addr_lock == 0) 307172218Srrs SCTP_IPI_ADDR_WUNLOCK(); 308169352Srrs /* Take away the reference, and possibly free it */ 309169352Srrs sctp_free_ifn(sctp_ifnp); 310169352Srrs} 311169352Srrs 312246595Stuexen 313172091Srrsvoid 314172266Srrssctp_mark_ifa_addr_down(uint32_t vrf_id, struct sockaddr *addr, 315172266Srrs const char *if_name, uint32_t ifn_index) 316172091Srrs{ 317172091Srrs struct sctp_vrf *vrf; 318246595Stuexen struct sctp_ifa *sctp_ifap; 319169352Srrs 320172218Srrs SCTP_IPI_ADDR_RLOCK(); 321172091Srrs vrf = sctp_find_vrf(vrf_id); 322172091Srrs if (vrf == NULL) { 323172266Srrs SCTPDBG(SCTP_DEBUG_PCB4, "Can't find vrf_id 0x%x\n", vrf_id); 324172091Srrs goto out; 325172091Srrs 326172091Srrs } 327172091Srrs sctp_ifap = sctp_find_ifa_by_addr(addr, vrf->vrf_id, SCTP_ADDR_LOCKED); 328172091Srrs if (sctp_ifap == NULL) { 329172266Srrs SCTPDBG(SCTP_DEBUG_PCB4, "Can't find sctp_ifap for address\n"); 330172091Srrs goto out; 331172091Srrs } 332172091Srrs if (sctp_ifap->ifn_p == NULL) { 333172266Srrs SCTPDBG(SCTP_DEBUG_PCB4, "IFA has no IFN - can't mark unuseable\n"); 334172091Srrs goto out; 335172091Srrs } 336172091Srrs if (if_name) { 337227655Stuexen if (strncmp(if_name, sctp_ifap->ifn_p->ifn_name, SCTP_IFNAMSIZ) != 0) { 338172266Srrs SCTPDBG(SCTP_DEBUG_PCB4, "IFN %s of IFA not the same as %s\n", 339227655Stuexen sctp_ifap->ifn_p->ifn_name, if_name); 340172091Srrs goto out; 341172091Srrs } 342172091Srrs } else { 343172091Srrs if (sctp_ifap->ifn_p->ifn_index != ifn_index) { 344172266Srrs SCTPDBG(SCTP_DEBUG_PCB4, "IFA owned by ifn_index:%d down command for ifn_index:%d - ignored\n", 345172091Srrs sctp_ifap->ifn_p->ifn_index, ifn_index); 346172091Srrs goto out; 347172091Srrs } 348172091Srrs } 349172091Srrs 350172091Srrs sctp_ifap->localifa_flags &= (~SCTP_ADDR_VALID); 351172091Srrs sctp_ifap->localifa_flags |= SCTP_ADDR_IFA_UNUSEABLE; 352172091Srrsout: 353172218Srrs SCTP_IPI_ADDR_RUNLOCK(); 354172091Srrs} 355172091Srrs 356246595Stuexen 357172091Srrsvoid 358172266Srrssctp_mark_ifa_addr_up(uint32_t vrf_id, struct sockaddr *addr, 359172266Srrs const char *if_name, uint32_t ifn_index) 360172091Srrs{ 361172091Srrs struct sctp_vrf *vrf; 362246595Stuexen struct sctp_ifa *sctp_ifap; 363172091Srrs 364172218Srrs SCTP_IPI_ADDR_RLOCK(); 365172091Srrs vrf = sctp_find_vrf(vrf_id); 366172091Srrs if (vrf == NULL) { 367172266Srrs SCTPDBG(SCTP_DEBUG_PCB4, "Can't find vrf_id 0x%x\n", vrf_id); 368172091Srrs goto out; 369172091Srrs 370172091Srrs } 371172091Srrs sctp_ifap = sctp_find_ifa_by_addr(addr, vrf->vrf_id, SCTP_ADDR_LOCKED); 372172091Srrs if (sctp_ifap == NULL) { 373172266Srrs SCTPDBG(SCTP_DEBUG_PCB4, "Can't find sctp_ifap for address\n"); 374172091Srrs goto out; 375172091Srrs } 376172091Srrs if (sctp_ifap->ifn_p == NULL) { 377172266Srrs SCTPDBG(SCTP_DEBUG_PCB4, "IFA has no IFN - can't mark unuseable\n"); 378172091Srrs goto out; 379172091Srrs } 380172091Srrs if (if_name) { 381227655Stuexen if (strncmp(if_name, sctp_ifap->ifn_p->ifn_name, SCTP_IFNAMSIZ) != 0) { 382172266Srrs SCTPDBG(SCTP_DEBUG_PCB4, "IFN %s of IFA not the same as %s\n", 383227655Stuexen sctp_ifap->ifn_p->ifn_name, if_name); 384172091Srrs goto out; 385172091Srrs } 386172091Srrs } else { 387172091Srrs if (sctp_ifap->ifn_p->ifn_index != ifn_index) { 388172266Srrs SCTPDBG(SCTP_DEBUG_PCB4, "IFA owned by ifn_index:%d down command for ifn_index:%d - ignored\n", 389172091Srrs sctp_ifap->ifn_p->ifn_index, ifn_index); 390172091Srrs goto out; 391172091Srrs } 392172091Srrs } 393172091Srrs 394172091Srrs sctp_ifap->localifa_flags &= (~SCTP_ADDR_IFA_UNUSEABLE); 395172091Srrs sctp_ifap->localifa_flags |= SCTP_ADDR_VALID; 396172091Srrsout: 397172218Srrs SCTP_IPI_ADDR_RUNLOCK(); 398172091Srrs} 399172091Srrs 400246595Stuexen 401172266Srrs/*- 402172266Srrs * Add an ifa to an ifn. 403172266Srrs * Register the interface as necessary. 404172266Srrs * NOTE: ADDR write lock MUST be held. 405172266Srrs */ 406172266Srrsstatic void 407172266Srrssctp_add_ifa_to_ifn(struct sctp_ifn *sctp_ifnp, struct sctp_ifa *sctp_ifap) 408172266Srrs{ 409172266Srrs int ifa_af; 410172091Srrs 411172266Srrs LIST_INSERT_HEAD(&sctp_ifnp->ifalist, sctp_ifap, next_ifa); 412172266Srrs sctp_ifap->ifn_p = sctp_ifnp; 413172266Srrs atomic_add_int(&sctp_ifap->ifn_p->refcount, 1); 414172266Srrs /* update address counts */ 415172266Srrs sctp_ifnp->ifa_count++; 416172266Srrs ifa_af = sctp_ifap->address.sa.sa_family; 417221249Stuexen switch (ifa_af) { 418221249Stuexen#ifdef INET 419221249Stuexen case AF_INET: 420172266Srrs sctp_ifnp->num_v4++; 421221249Stuexen break; 422221249Stuexen#endif 423221249Stuexen#ifdef INET6 424221249Stuexen case AF_INET6: 425172266Srrs sctp_ifnp->num_v6++; 426221249Stuexen break; 427221249Stuexen#endif 428221249Stuexen default: 429221249Stuexen break; 430221249Stuexen } 431172266Srrs if (sctp_ifnp->ifa_count == 1) { 432172266Srrs /* register the new interface */ 433172266Srrs SCTP_REGISTER_INTERFACE(sctp_ifnp->ifn_index, ifa_af); 434172266Srrs sctp_ifnp->registered_af = ifa_af; 435172266Srrs } 436172266Srrs} 437172266Srrs 438246595Stuexen 439172266Srrs/*- 440172266Srrs * Remove an ifa from its ifn. 441172266Srrs * If no more addresses exist, remove the ifn too. Otherwise, re-register 442172266Srrs * the interface based on the remaining address families left. 443172266Srrs * NOTE: ADDR write lock MUST be held. 444172266Srrs */ 445172266Srrsstatic void 446172266Srrssctp_remove_ifa_from_ifn(struct sctp_ifa *sctp_ifap) 447172266Srrs{ 448172266Srrs LIST_REMOVE(sctp_ifap, next_ifa); 449172266Srrs if (sctp_ifap->ifn_p) { 450172266Srrs /* update address counts */ 451172266Srrs sctp_ifap->ifn_p->ifa_count--; 452221249Stuexen switch (sctp_ifap->address.sa.sa_family) { 453221249Stuexen#ifdef INET 454221249Stuexen case AF_INET: 455221249Stuexen sctp_ifap->ifn_p->num_v4--; 456221249Stuexen break; 457221249Stuexen#endif 458221249Stuexen#ifdef INET6 459221249Stuexen case AF_INET6: 460172266Srrs sctp_ifap->ifn_p->num_v6--; 461221249Stuexen break; 462221249Stuexen#endif 463221249Stuexen default: 464221249Stuexen break; 465221249Stuexen } 466172266Srrs 467199437Stuexen if (LIST_EMPTY(&sctp_ifap->ifn_p->ifalist)) { 468172266Srrs /* remove the ifn, possibly freeing it */ 469172266Srrs sctp_delete_ifn(sctp_ifap->ifn_p, SCTP_ADDR_LOCKED); 470172266Srrs } else { 471172266Srrs /* re-register address family type, if needed */ 472172266Srrs if ((sctp_ifap->ifn_p->num_v6 == 0) && 473172266Srrs (sctp_ifap->ifn_p->registered_af == AF_INET6)) { 474228907Stuexen SCTP_DEREGISTER_INTERFACE(sctp_ifap->ifn_p->ifn_index, AF_INET6); 475228907Stuexen SCTP_REGISTER_INTERFACE(sctp_ifap->ifn_p->ifn_index, AF_INET); 476172266Srrs sctp_ifap->ifn_p->registered_af = AF_INET; 477172266Srrs } else if ((sctp_ifap->ifn_p->num_v4 == 0) && 478172266Srrs (sctp_ifap->ifn_p->registered_af == AF_INET)) { 479228907Stuexen SCTP_DEREGISTER_INTERFACE(sctp_ifap->ifn_p->ifn_index, AF_INET); 480228907Stuexen SCTP_REGISTER_INTERFACE(sctp_ifap->ifn_p->ifn_index, AF_INET6); 481172266Srrs sctp_ifap->ifn_p->registered_af = AF_INET6; 482172266Srrs } 483172266Srrs /* free the ifn refcount */ 484172266Srrs sctp_free_ifn(sctp_ifap->ifn_p); 485172266Srrs } 486172266Srrs sctp_ifap->ifn_p = NULL; 487172266Srrs } 488172266Srrs} 489172266Srrs 490246595Stuexen 491167598Srrsstruct sctp_ifa * 492169352Srrssctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index, 493172266Srrs uint32_t ifn_type, const char *if_name, void *ifa, 494172266Srrs struct sockaddr *addr, uint32_t ifa_flags, 495169352Srrs int dynamic_add) 496167598Srrs{ 497167598Srrs struct sctp_vrf *vrf; 498167598Srrs struct sctp_ifn *sctp_ifnp = NULL; 499167598Srrs struct sctp_ifa *sctp_ifap = NULL; 500169352Srrs struct sctp_ifalist *hash_addr_head; 501169352Srrs struct sctp_ifnlist *hash_ifn_head; 502167698Srrs uint32_t hash_of_addr; 503170181Srrs int new_ifn_af = 0; 504167598Srrs 505172266Srrs#ifdef SCTP_DEBUG 506172266Srrs SCTPDBG(SCTP_DEBUG_PCB4, "vrf_id 0x%x: adding address: ", vrf_id); 507172266Srrs SCTPDBG_ADDR(SCTP_DEBUG_PCB4, addr); 508172266Srrs#endif 509172218Srrs SCTP_IPI_ADDR_WLOCK(); 510170744Srrs sctp_ifnp = sctp_find_ifn(ifn, ifn_index); 511170744Srrs if (sctp_ifnp) { 512170744Srrs vrf = sctp_ifnp->vrf; 513170744Srrs } else { 514170744Srrs vrf = sctp_find_vrf(vrf_id); 515167598Srrs if (vrf == NULL) { 516170744Srrs vrf = sctp_allocate_vrf(vrf_id); 517170744Srrs if (vrf == NULL) { 518172218Srrs SCTP_IPI_ADDR_WUNLOCK(); 519170744Srrs return (NULL); 520170744Srrs } 521167598Srrs } 522167598Srrs } 523167598Srrs if (sctp_ifnp == NULL) { 524167598Srrs /* 525167598Srrs * build one and add it, can't hold lock until after malloc 526167598Srrs * done though. 527167598Srrs */ 528172218Srrs SCTP_IPI_ADDR_WUNLOCK(); 529172266Srrs SCTP_MALLOC(sctp_ifnp, struct sctp_ifn *, 530172266Srrs sizeof(struct sctp_ifn), SCTP_M_IFN); 531167598Srrs if (sctp_ifnp == NULL) { 532167598Srrs#ifdef INVARIANTS 533212225Srrs panic("No memory for IFN"); 534167598Srrs#endif 535167598Srrs return (NULL); 536167598Srrs } 537170931Srrs memset(sctp_ifnp, 0, sizeof(struct sctp_ifn)); 538167598Srrs sctp_ifnp->ifn_index = ifn_index; 539167598Srrs sctp_ifnp->ifn_p = ifn; 540167598Srrs sctp_ifnp->ifn_type = ifn_type; 541172703Srrs sctp_ifnp->refcount = 0; 542167598Srrs sctp_ifnp->vrf = vrf; 543170744Srrs atomic_add_int(&vrf->refcount, 1); 544170181Srrs sctp_ifnp->ifn_mtu = SCTP_GATHER_MTU_FROM_IFN_INFO(ifn, ifn_index, addr->sa_family); 545169352Srrs if (if_name != NULL) { 546227486Stuexen snprintf(sctp_ifnp->ifn_name, SCTP_IFNAMSIZ, "%s", if_name); 547169352Srrs } else { 548227486Stuexen snprintf(sctp_ifnp->ifn_name, SCTP_IFNAMSIZ, "%s", "unknown"); 549169352Srrs } 550179783Srrs hash_ifn_head = &SCTP_BASE_INFO(vrf_ifn_hash)[(ifn_index & SCTP_BASE_INFO(vrf_ifn_hashmark))]; 551167598Srrs LIST_INIT(&sctp_ifnp->ifalist); 552172218Srrs SCTP_IPI_ADDR_WLOCK(); 553169352Srrs LIST_INSERT_HEAD(hash_ifn_head, sctp_ifnp, next_bucket); 554167598Srrs LIST_INSERT_HEAD(&vrf->ifnlist, sctp_ifnp, next_ifn); 555179783Srrs atomic_add_int(&SCTP_BASE_INFO(ipi_count_ifns), 1); 556170181Srrs new_ifn_af = 1; 557167598Srrs } 558172091Srrs sctp_ifap = sctp_find_ifa_by_addr(addr, vrf->vrf_id, SCTP_ADDR_LOCKED); 559167598Srrs if (sctp_ifap) { 560167598Srrs /* Hmm, it already exists? */ 561167598Srrs if ((sctp_ifap->ifn_p) && 562167598Srrs (sctp_ifap->ifn_p->ifn_index == ifn_index)) { 563172266Srrs SCTPDBG(SCTP_DEBUG_PCB4, "Using existing ifn %s (0x%x) for ifa %p\n", 564172266Srrs sctp_ifap->ifn_p->ifn_name, ifn_index, 565240148Stuexen (void *)sctp_ifap); 566170744Srrs if (new_ifn_af) { 567170744Srrs /* Remove the created one that we don't want */ 568172266Srrs sctp_delete_ifn(sctp_ifnp, SCTP_ADDR_LOCKED); 569170744Srrs } 570167598Srrs if (sctp_ifap->localifa_flags & SCTP_BEING_DELETED) { 571167598Srrs /* easy to solve, just switch back to active */ 572172266Srrs SCTPDBG(SCTP_DEBUG_PCB4, "Clearing deleted ifa flag\n"); 573167598Srrs sctp_ifap->localifa_flags = SCTP_ADDR_VALID; 574167598Srrs sctp_ifap->ifn_p = sctp_ifnp; 575170744Srrs atomic_add_int(&sctp_ifap->ifn_p->refcount, 1); 576167598Srrs } 577172266Srrs exit_stage_left: 578172266Srrs SCTP_IPI_ADDR_WUNLOCK(); 579172266Srrs return (sctp_ifap); 580167598Srrs } else { 581167598Srrs if (sctp_ifap->ifn_p) { 582167598Srrs /* 583215039Stuexen * The last IFN gets the address, remove the 584215039Stuexen * old one 585167598Srrs */ 586172266Srrs SCTPDBG(SCTP_DEBUG_PCB4, "Moving ifa %p from %s (0x%x) to %s (0x%x)\n", 587240148Stuexen (void *)sctp_ifap, sctp_ifap->ifn_p->ifn_name, 588172266Srrs sctp_ifap->ifn_p->ifn_index, if_name, 589172266Srrs ifn_index); 590172266Srrs /* remove the address from the old ifn */ 591172266Srrs sctp_remove_ifa_from_ifn(sctp_ifap); 592172266Srrs /* move the address over to the new ifn */ 593172266Srrs sctp_add_ifa_to_ifn(sctp_ifnp, sctp_ifap); 594167598Srrs goto exit_stage_left; 595167598Srrs } else { 596167598Srrs /* repair ifnp which was NULL ? */ 597167598Srrs sctp_ifap->localifa_flags = SCTP_ADDR_VALID; 598172266Srrs SCTPDBG(SCTP_DEBUG_PCB4, "Repairing ifn %p for ifa %p\n", 599240148Stuexen (void *)sctp_ifnp, (void *)sctp_ifap); 600172266Srrs sctp_add_ifa_to_ifn(sctp_ifnp, sctp_ifap); 601167598Srrs } 602167598Srrs goto exit_stage_left; 603167598Srrs } 604167598Srrs } 605172218Srrs SCTP_IPI_ADDR_WUNLOCK(); 606170091Srrs SCTP_MALLOC(sctp_ifap, struct sctp_ifa *, sizeof(struct sctp_ifa), SCTP_M_IFA); 607167598Srrs if (sctp_ifap == NULL) { 608167598Srrs#ifdef INVARIANTS 609167598Srrs panic("No memory for IFA"); 610167598Srrs#endif 611167598Srrs return (NULL); 612167598Srrs } 613167695Srrs memset(sctp_ifap, 0, sizeof(struct sctp_ifa)); 614167598Srrs sctp_ifap->ifn_p = sctp_ifnp; 615167598Srrs atomic_add_int(&sctp_ifnp->refcount, 1); 616170751Srrs sctp_ifap->vrf_id = vrf_id; 617167598Srrs sctp_ifap->ifa = ifa; 618167598Srrs memcpy(&sctp_ifap->address, addr, addr->sa_len); 619167598Srrs sctp_ifap->localifa_flags = SCTP_ADDR_VALID | SCTP_ADDR_DEFER_USE; 620167598Srrs sctp_ifap->flags = ifa_flags; 621167598Srrs /* Set scope */ 622178251Srrs switch (sctp_ifap->address.sa.sa_family) { 623221249Stuexen#ifdef INET 624178251Srrs case AF_INET: 625178251Srrs { 626178251Srrs struct sockaddr_in *sin; 627167598Srrs 628271746Stuexen sin = &sctp_ifap->address.sin; 629178251Srrs if (SCTP_IFN_IS_IFT_LOOP(sctp_ifap->ifn_p) || 630178251Srrs (IN4_ISLOOPBACK_ADDRESS(&sin->sin_addr))) { 631178251Srrs sctp_ifap->src_is_loop = 1; 632178251Srrs } 633178251Srrs if ((IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) { 634178251Srrs sctp_ifap->src_is_priv = 1; 635178251Srrs } 636178251Srrs sctp_ifnp->num_v4++; 637178251Srrs if (new_ifn_af) 638178251Srrs new_ifn_af = AF_INET; 639178251Srrs break; 640167598Srrs } 641221249Stuexen#endif 642178251Srrs#ifdef INET6 643178251Srrs case AF_INET6: 644178251Srrs { 645178251Srrs /* ok to use deprecated addresses? */ 646178251Srrs struct sockaddr_in6 *sin6; 647167598Srrs 648271746Stuexen sin6 = &sctp_ifap->address.sin6; 649178251Srrs if (SCTP_IFN_IS_IFT_LOOP(sctp_ifap->ifn_p) || 650178251Srrs (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))) { 651178251Srrs sctp_ifap->src_is_loop = 1; 652178251Srrs } 653178251Srrs if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 654178251Srrs sctp_ifap->src_is_priv = 1; 655178251Srrs } 656178251Srrs sctp_ifnp->num_v6++; 657178251Srrs if (new_ifn_af) 658178251Srrs new_ifn_af = AF_INET6; 659178251Srrs break; 660167598Srrs } 661178251Srrs#endif 662178251Srrs default: 663170181Srrs new_ifn_af = 0; 664178251Srrs break; 665167598Srrs } 666167698Srrs hash_of_addr = sctp_get_ifa_hash_val(&sctp_ifap->address.sa); 667167698Srrs 668167598Srrs if ((sctp_ifap->src_is_priv == 0) && 669167598Srrs (sctp_ifap->src_is_loop == 0)) { 670167598Srrs sctp_ifap->src_is_glob = 1; 671167598Srrs } 672172218Srrs SCTP_IPI_ADDR_WLOCK(); 673169352Srrs hash_addr_head = &vrf->vrf_addr_hash[(hash_of_addr & vrf->vrf_addr_hashmark)]; 674169352Srrs LIST_INSERT_HEAD(hash_addr_head, sctp_ifap, next_bucket); 675167598Srrs sctp_ifap->refcount = 1; 676167598Srrs LIST_INSERT_HEAD(&sctp_ifnp->ifalist, sctp_ifap, next_ifa); 677167598Srrs sctp_ifnp->ifa_count++; 678167598Srrs vrf->total_ifa_count++; 679179783Srrs atomic_add_int(&SCTP_BASE_INFO(ipi_count_ifas), 1); 680170181Srrs if (new_ifn_af) { 681170181Srrs SCTP_REGISTER_INTERFACE(ifn_index, new_ifn_af); 682170181Srrs sctp_ifnp->registered_af = new_ifn_af; 683170181Srrs } 684172218Srrs SCTP_IPI_ADDR_WUNLOCK(); 685169208Srrs if (dynamic_add) { 686169208Srrs /* 687169208Srrs * Bump up the refcount so that when the timer completes it 688169208Srrs * will drop back down. 689169208Srrs */ 690169208Srrs struct sctp_laddr *wi; 691169208Srrs 692169208Srrs atomic_add_int(&sctp_ifap->refcount, 1); 693179783Srrs wi = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_laddr), struct sctp_laddr); 694169208Srrs if (wi == NULL) { 695169208Srrs /* 696169208Srrs * Gak, what can we do? We have lost an address 697169208Srrs * change can you say HOSED? 698169208Srrs */ 699172266Srrs SCTPDBG(SCTP_DEBUG_PCB4, "Lost an address change?\n"); 700169208Srrs /* Opps, must decrement the count */ 701172266Srrs sctp_del_addr_from_vrf(vrf_id, addr, ifn_index, 702172266Srrs if_name); 703169208Srrs return (NULL); 704169208Srrs } 705169208Srrs SCTP_INCR_LADDR_COUNT(); 706169208Srrs bzero(wi, sizeof(*wi)); 707170056Srrs (void)SCTP_GETTIME_TIMEVAL(&wi->start_time); 708169208Srrs wi->ifa = sctp_ifap; 709169208Srrs wi->action = SCTP_ADD_IP_ADDRESS; 710208160Srrs 711208160Srrs SCTP_WQ_ADDR_LOCK(); 712179783Srrs LIST_INSERT_HEAD(&SCTP_BASE_INFO(addr_wq), wi, sctp_nxt_addr); 713208160Srrs SCTP_WQ_ADDR_UNLOCK(); 714208160Srrs 715169208Srrs sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ, 716169208Srrs (struct sctp_inpcb *)NULL, 717169208Srrs (struct sctp_tcb *)NULL, 718169208Srrs (struct sctp_nets *)NULL); 719169352Srrs } else { 720169352Srrs /* it's ready for use */ 721169352Srrs sctp_ifap->localifa_flags &= ~SCTP_ADDR_DEFER_USE; 722169208Srrs } 723167598Srrs return (sctp_ifap); 724167598Srrs} 725167598Srrs 726169208Srrsvoid 727169352Srrssctp_del_addr_from_vrf(uint32_t vrf_id, struct sockaddr *addr, 728172091Srrs uint32_t ifn_index, const char *if_name) 729167598Srrs{ 730167598Srrs struct sctp_vrf *vrf; 731167598Srrs struct sctp_ifa *sctp_ifap = NULL; 732167598Srrs 733172218Srrs SCTP_IPI_ADDR_WLOCK(); 734169352Srrs vrf = sctp_find_vrf(vrf_id); 735167598Srrs if (vrf == NULL) { 736172266Srrs SCTPDBG(SCTP_DEBUG_PCB4, "Can't find vrf_id 0x%x\n", vrf_id); 737167598Srrs goto out_now; 738167598Srrs } 739172266Srrs#ifdef SCTP_DEBUG 740172266Srrs SCTPDBG(SCTP_DEBUG_PCB4, "vrf_id 0x%x: deleting address:", vrf_id); 741172266Srrs SCTPDBG_ADDR(SCTP_DEBUG_PCB4, addr); 742172266Srrs#endif 743172091Srrs sctp_ifap = sctp_find_ifa_by_addr(addr, vrf->vrf_id, SCTP_ADDR_LOCKED); 744167598Srrs if (sctp_ifap) { 745172091Srrs /* Validate the delete */ 746172091Srrs if (sctp_ifap->ifn_p) { 747172091Srrs int valid = 0; 748172091Srrs 749172091Srrs /*- 750172091Srrs * The name has priority over the ifn_index 751172091Srrs * if its given. We do this especially for 752172091Srrs * panda who might recycle indexes fast. 753172091Srrs */ 754172091Srrs if (if_name) { 755227486Stuexen if (strncmp(if_name, sctp_ifap->ifn_p->ifn_name, SCTP_IFNAMSIZ) == 0) { 756227486Stuexen /* They match its a correct delete */ 757227486Stuexen valid = 1; 758172091Srrs } 759172091Srrs } 760172091Srrs if (!valid) { 761172091Srrs /* last ditch check ifn_index */ 762172091Srrs if (ifn_index == sctp_ifap->ifn_p->ifn_index) { 763172091Srrs valid = 1; 764172091Srrs } 765172091Srrs } 766172091Srrs if (!valid) { 767172266Srrs SCTPDBG(SCTP_DEBUG_PCB4, "ifn:%d ifname:%s does not match addresses\n", 768172091Srrs ifn_index, ((if_name == NULL) ? "NULL" : if_name)); 769172266Srrs SCTPDBG(SCTP_DEBUG_PCB4, "ifn:%d ifname:%s - ignoring delete\n", 770172091Srrs sctp_ifap->ifn_p->ifn_index, sctp_ifap->ifn_p->ifn_name); 771172218Srrs SCTP_IPI_ADDR_WUNLOCK(); 772172091Srrs return; 773172091Srrs } 774172091Srrs } 775240148Stuexen SCTPDBG(SCTP_DEBUG_PCB4, "Deleting ifa %p\n", (void *)sctp_ifap); 776167598Srrs sctp_ifap->localifa_flags &= SCTP_ADDR_VALID; 777267725Stuexen /* 778267725Stuexen * We don't set the flag. This means that the structure will 779267725Stuexen * hang around in EP's that have bound specific to it until 780267725Stuexen * they close. This gives us TCP like behavior if someone 781267725Stuexen * removes an address (or for that matter adds it right 782267725Stuexen * back). 783267725Stuexen */ 784267725Stuexen /* sctp_ifap->localifa_flags |= SCTP_BEING_DELETED; */ 785167598Srrs vrf->total_ifa_count--; 786167698Srrs LIST_REMOVE(sctp_ifap, next_bucket); 787172266Srrs sctp_remove_ifa_from_ifn(sctp_ifap); 788169352Srrs } 789169352Srrs#ifdef SCTP_DEBUG 790169352Srrs else { 791172266Srrs SCTPDBG(SCTP_DEBUG_PCB4, "Del Addr-ifn:%d Could not find address:", 792167598Srrs ifn_index); 793169420Srrs SCTPDBG_ADDR(SCTP_DEBUG_PCB1, addr); 794167598Srrs } 795169352Srrs#endif 796169420Srrs 797167598Srrsout_now: 798172218Srrs SCTP_IPI_ADDR_WUNLOCK(); 799169208Srrs if (sctp_ifap) { 800169208Srrs struct sctp_laddr *wi; 801169208Srrs 802179783Srrs wi = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_laddr), struct sctp_laddr); 803169208Srrs if (wi == NULL) { 804169208Srrs /* 805169208Srrs * Gak, what can we do? We have lost an address 806169208Srrs * change can you say HOSED? 807169208Srrs */ 808172266Srrs SCTPDBG(SCTP_DEBUG_PCB4, "Lost an address change?\n"); 809169208Srrs 810172218Srrs /* Oops, must decrement the count */ 811169208Srrs sctp_free_ifa(sctp_ifap); 812169208Srrs return; 813169208Srrs } 814169208Srrs SCTP_INCR_LADDR_COUNT(); 815169208Srrs bzero(wi, sizeof(*wi)); 816170056Srrs (void)SCTP_GETTIME_TIMEVAL(&wi->start_time); 817169208Srrs wi->ifa = sctp_ifap; 818169208Srrs wi->action = SCTP_DEL_IP_ADDRESS; 819208160Srrs SCTP_WQ_ADDR_LOCK(); 820169208Srrs /* 821169208Srrs * Should this really be a tailq? As it is we will process 822169208Srrs * the newest first :-0 823169208Srrs */ 824179783Srrs LIST_INSERT_HEAD(&SCTP_BASE_INFO(addr_wq), wi, sctp_nxt_addr); 825208160Srrs SCTP_WQ_ADDR_UNLOCK(); 826170091Srrs 827169208Srrs sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ, 828169208Srrs (struct sctp_inpcb *)NULL, 829169208Srrs (struct sctp_tcb *)NULL, 830169208Srrs (struct sctp_nets *)NULL); 831169208Srrs } 832169208Srrs return; 833167598Srrs} 834167598Srrs 835163953Srrs 836246635Stuexenstatic int 837246635Stuexensctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to) 838246635Stuexen{ 839258454Stuexen int loopback_scope; 840258454Stuexen 841258454Stuexen#if defined(INET) 842258454Stuexen int ipv4_local_scope, ipv4_addr_legal; 843258454Stuexen 844258454Stuexen#endif 845258454Stuexen#if defined(INET6) 846258454Stuexen int local_scope, site_scope, ipv6_addr_legal; 847258454Stuexen 848258454Stuexen#endif 849246635Stuexen struct sctp_vrf *vrf; 850246635Stuexen struct sctp_ifn *sctp_ifn; 851246635Stuexen struct sctp_ifa *sctp_ifa; 852246635Stuexen 853246635Stuexen loopback_scope = stcb->asoc.scope.loopback_scope; 854258454Stuexen#if defined(INET) 855246635Stuexen ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope; 856258454Stuexen ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal; 857258454Stuexen#endif 858258454Stuexen#if defined(INET6) 859246635Stuexen local_scope = stcb->asoc.scope.local_scope; 860246635Stuexen site_scope = stcb->asoc.scope.site_scope; 861246635Stuexen ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal; 862258454Stuexen#endif 863246635Stuexen 864246635Stuexen SCTP_IPI_ADDR_RLOCK(); 865246635Stuexen vrf = sctp_find_vrf(stcb->asoc.vrf_id); 866246635Stuexen if (vrf == NULL) { 867246635Stuexen /* no vrf, no addresses */ 868246635Stuexen SCTP_IPI_ADDR_RUNLOCK(); 869246635Stuexen return (0); 870246635Stuexen } 871246635Stuexen if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { 872246635Stuexen LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) { 873246635Stuexen if ((loopback_scope == 0) && 874246635Stuexen SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) { 875246635Stuexen continue; 876246635Stuexen } 877246635Stuexen LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) { 878246635Stuexen if (sctp_is_addr_restricted(stcb, sctp_ifa) && 879246635Stuexen (!sctp_is_addr_pending(stcb, sctp_ifa))) { 880246635Stuexen /* 881246635Stuexen * We allow pending addresses, where 882246635Stuexen * we have sent an asconf-add to be 883246635Stuexen * considered valid. 884246635Stuexen */ 885246635Stuexen continue; 886246635Stuexen } 887258454Stuexen if (sctp_ifa->address.sa.sa_family != to->sa_family) { 888258454Stuexen continue; 889258454Stuexen } 890246635Stuexen switch (sctp_ifa->address.sa.sa_family) { 891246635Stuexen#ifdef INET 892246635Stuexen case AF_INET: 893246635Stuexen if (ipv4_addr_legal) { 894246635Stuexen struct sockaddr_in *sin, 895246635Stuexen *rsin; 896246635Stuexen 897246635Stuexen sin = &sctp_ifa->address.sin; 898246635Stuexen rsin = (struct sockaddr_in *)to; 899246635Stuexen if ((ipv4_local_scope == 0) && 900246635Stuexen IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) { 901246635Stuexen continue; 902246635Stuexen } 903267769Stuexen if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred, 904267769Stuexen &sin->sin_addr) != 0) { 905267769Stuexen continue; 906267769Stuexen } 907246635Stuexen if (sin->sin_addr.s_addr == rsin->sin_addr.s_addr) { 908246635Stuexen SCTP_IPI_ADDR_RUNLOCK(); 909246635Stuexen return (1); 910246635Stuexen } 911246635Stuexen } 912246635Stuexen break; 913246635Stuexen#endif 914246635Stuexen#ifdef INET6 915246635Stuexen case AF_INET6: 916246635Stuexen if (ipv6_addr_legal) { 917246635Stuexen struct sockaddr_in6 *sin6, 918246635Stuexen *rsin6; 919246635Stuexen 920246635Stuexen sin6 = &sctp_ifa->address.sin6; 921246635Stuexen rsin6 = (struct sockaddr_in6 *)to; 922267769Stuexen if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred, 923267769Stuexen &sin6->sin6_addr) != 0) { 924267769Stuexen continue; 925267769Stuexen } 926246635Stuexen if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 927246635Stuexen if (local_scope == 0) 928246635Stuexen continue; 929246635Stuexen if (sin6->sin6_scope_id == 0) { 930246635Stuexen if (sa6_recoverscope(sin6) != 0) 931246635Stuexen continue; 932246635Stuexen } 933246635Stuexen } 934246635Stuexen if ((site_scope == 0) && 935246635Stuexen (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) { 936246635Stuexen continue; 937246635Stuexen } 938246635Stuexen if (SCTP6_ARE_ADDR_EQUAL(sin6, rsin6)) { 939246635Stuexen SCTP_IPI_ADDR_RUNLOCK(); 940246635Stuexen return (1); 941246635Stuexen } 942246635Stuexen } 943246635Stuexen break; 944246635Stuexen#endif 945246635Stuexen default: 946246635Stuexen /* TSNH */ 947246635Stuexen break; 948246635Stuexen } 949246635Stuexen } 950246635Stuexen } 951246635Stuexen } else { 952246635Stuexen struct sctp_laddr *laddr; 953246635Stuexen 954246635Stuexen LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) { 955246635Stuexen if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED) { 956246635Stuexen SCTPDBG(SCTP_DEBUG_PCB1, "ifa being deleted\n"); 957246635Stuexen continue; 958246635Stuexen } 959246635Stuexen if (sctp_is_addr_restricted(stcb, laddr->ifa) && 960246635Stuexen (!sctp_is_addr_pending(stcb, laddr->ifa))) { 961246635Stuexen /* 962246635Stuexen * We allow pending addresses, where we have 963246635Stuexen * sent an asconf-add to be considered 964246635Stuexen * valid. 965246635Stuexen */ 966246635Stuexen continue; 967246635Stuexen } 968246635Stuexen if (laddr->ifa->address.sa.sa_family != to->sa_family) { 969246635Stuexen continue; 970246635Stuexen } 971246635Stuexen switch (to->sa_family) { 972246635Stuexen#ifdef INET 973246635Stuexen case AF_INET: 974246635Stuexen { 975246635Stuexen struct sockaddr_in *sin, *rsin; 976246635Stuexen 977271746Stuexen sin = &laddr->ifa->address.sin; 978246635Stuexen rsin = (struct sockaddr_in *)to; 979246635Stuexen if (sin->sin_addr.s_addr == rsin->sin_addr.s_addr) { 980246635Stuexen SCTP_IPI_ADDR_RUNLOCK(); 981246635Stuexen return (1); 982246635Stuexen } 983246635Stuexen break; 984246635Stuexen } 985246635Stuexen#endif 986246635Stuexen#ifdef INET6 987246635Stuexen case AF_INET6: 988246635Stuexen { 989246635Stuexen struct sockaddr_in6 *sin6, *rsin6; 990246635Stuexen 991271746Stuexen sin6 = &laddr->ifa->address.sin6; 992246635Stuexen rsin6 = (struct sockaddr_in6 *)to; 993246635Stuexen if (SCTP6_ARE_ADDR_EQUAL(sin6, rsin6)) { 994246635Stuexen SCTP_IPI_ADDR_RUNLOCK(); 995246635Stuexen return (1); 996246635Stuexen } 997246635Stuexen break; 998246635Stuexen } 999246635Stuexen 1000246635Stuexen#endif 1001246635Stuexen default: 1002246635Stuexen /* TSNH */ 1003246635Stuexen break; 1004246635Stuexen } 1005246635Stuexen 1006246635Stuexen } 1007246635Stuexen } 1008246635Stuexen SCTP_IPI_ADDR_RUNLOCK(); 1009246635Stuexen return (0); 1010246635Stuexen} 1011246635Stuexen 1012246635Stuexen 1013163953Srrsstatic struct sctp_tcb * 1014163953Srrssctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from, 1015168299Srrs struct sockaddr *to, struct sctp_nets **netp, uint32_t vrf_id) 1016163953Srrs{ 1017172266Srrs /**** ASSUMES THE CALLER holds the INP_INFO_RLOCK */ 1018163953Srrs /* 1019163953Srrs * If we support the TCP model, then we must now dig through to see 1020163953Srrs * if we can find our endpoint in the list of tcp ep's. 1021163953Srrs */ 1022163953Srrs uint16_t lport, rport; 1023163953Srrs struct sctppcbhead *ephead; 1024163953Srrs struct sctp_inpcb *inp; 1025163953Srrs struct sctp_laddr *laddr; 1026163953Srrs struct sctp_tcb *stcb; 1027163953Srrs struct sctp_nets *net; 1028163953Srrs 1029163953Srrs if ((to == NULL) || (from == NULL)) { 1030163953Srrs return (NULL); 1031163953Srrs } 1032221249Stuexen switch (to->sa_family) { 1033221249Stuexen#ifdef INET 1034221249Stuexen case AF_INET: 1035221249Stuexen if (from->sa_family == AF_INET) { 1036221249Stuexen lport = ((struct sockaddr_in *)to)->sin_port; 1037221249Stuexen rport = ((struct sockaddr_in *)from)->sin_port; 1038221249Stuexen } else { 1039221249Stuexen return (NULL); 1040221249Stuexen } 1041221249Stuexen break; 1042221249Stuexen#endif 1043221249Stuexen#ifdef INET6 1044221249Stuexen case AF_INET6: 1045221249Stuexen if (from->sa_family == AF_INET6) { 1046221249Stuexen lport = ((struct sockaddr_in6 *)to)->sin6_port; 1047221249Stuexen rport = ((struct sockaddr_in6 *)from)->sin6_port; 1048221249Stuexen } else { 1049221249Stuexen return (NULL); 1050221249Stuexen } 1051221249Stuexen break; 1052221249Stuexen#endif 1053221249Stuexen default: 1054221249Stuexen return (NULL); 1055163953Srrs } 1056215039Stuexen ephead = &SCTP_BASE_INFO(sctp_tcpephash)[SCTP_PCBHASH_ALLADDR((lport | rport), SCTP_BASE_INFO(hashtcpmark))]; 1057163953Srrs /* 1058163953Srrs * Ok now for each of the guys in this bucket we must look and see: 1059163953Srrs * - Does the remote port match. - Does there single association's 1060163953Srrs * addresses match this address (to). If so we update p_ep to point 1061163953Srrs * to this ep and return the tcb from it. 1062163953Srrs */ 1063163953Srrs LIST_FOREACH(inp, ephead, sctp_hash) { 1064163953Srrs SCTP_INP_RLOCK(inp); 1065163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) { 1066163953Srrs SCTP_INP_RUNLOCK(inp); 1067163953Srrs continue; 1068163953Srrs } 1069169208Srrs if (lport != inp->sctp_lport) { 1070169352Srrs SCTP_INP_RUNLOCK(inp); 1071169208Srrs continue; 1072169208Srrs } 1073267769Stuexen switch (to->sa_family) { 1074267769Stuexen#ifdef INET 1075267769Stuexen case AF_INET: 1076267769Stuexen { 1077267769Stuexen struct sockaddr_in *sin; 1078267769Stuexen 1079267769Stuexen sin = (struct sockaddr_in *)to; 1080267769Stuexen if (prison_check_ip4(inp->ip_inp.inp.inp_cred, 1081267769Stuexen &sin->sin_addr) != 0) { 1082267769Stuexen SCTP_INP_RUNLOCK(inp); 1083267769Stuexen continue; 1084267769Stuexen } 1085267769Stuexen break; 1086267769Stuexen } 1087267769Stuexen#endif 1088267769Stuexen#ifdef INET6 1089267769Stuexen case AF_INET6: 1090267769Stuexen { 1091267769Stuexen struct sockaddr_in6 *sin6; 1092267769Stuexen 1093267769Stuexen sin6 = (struct sockaddr_in6 *)to; 1094267769Stuexen if (prison_check_ip6(inp->ip_inp.inp.inp_cred, 1095267769Stuexen &sin6->sin6_addr) != 0) { 1096267769Stuexen SCTP_INP_RUNLOCK(inp); 1097267769Stuexen continue; 1098267769Stuexen } 1099267769Stuexen break; 1100267769Stuexen } 1101267769Stuexen#endif 1102267769Stuexen default: 1103267769Stuexen SCTP_INP_RUNLOCK(inp); 1104267769Stuexen continue; 1105267769Stuexen } 1106168709Srrs if (inp->def_vrf_id != vrf_id) { 1107168299Srrs SCTP_INP_RUNLOCK(inp); 1108168299Srrs continue; 1109168299Srrs } 1110163953Srrs /* check to see if the ep has one of the addresses */ 1111163953Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) { 1112163953Srrs /* We are NOT bound all, so look further */ 1113163953Srrs int match = 0; 1114163953Srrs 1115163953Srrs LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { 1116163953Srrs 1117163953Srrs if (laddr->ifa == NULL) { 1118294174Stuexen SCTPDBG(SCTP_DEBUG_PCB1, "%s: NULL ifa\n", __func__); 1119163953Srrs continue; 1120163953Srrs } 1121167598Srrs if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED) { 1122169420Srrs SCTPDBG(SCTP_DEBUG_PCB1, "ifa being deleted\n"); 1123163953Srrs continue; 1124163953Srrs } 1125167598Srrs if (laddr->ifa->address.sa.sa_family == 1126163953Srrs to->sa_family) { 1127163953Srrs /* see if it matches */ 1128221249Stuexen#ifdef INET 1129163953Srrs if (from->sa_family == AF_INET) { 1130221249Stuexen struct sockaddr_in *intf_addr, 1131221249Stuexen *sin; 1132221249Stuexen 1133221249Stuexen intf_addr = &laddr->ifa->address.sin; 1134221249Stuexen sin = (struct sockaddr_in *)to; 1135163953Srrs if (sin->sin_addr.s_addr == 1136163953Srrs intf_addr->sin_addr.s_addr) { 1137163953Srrs match = 1; 1138163953Srrs break; 1139163953Srrs } 1140178251Srrs } 1141221249Stuexen#endif 1142178251Srrs#ifdef INET6 1143178251Srrs if (from->sa_family == AF_INET6) { 1144163953Srrs struct sockaddr_in6 *intf_addr6; 1145163953Srrs struct sockaddr_in6 *sin6; 1146163953Srrs 1147163953Srrs sin6 = (struct sockaddr_in6 *) 1148163953Srrs to; 1149167598Srrs intf_addr6 = &laddr->ifa->address.sin6; 1150163953Srrs 1151179157Srrs if (SCTP6_ARE_ADDR_EQUAL(sin6, 1152179157Srrs intf_addr6)) { 1153163953Srrs match = 1; 1154163953Srrs break; 1155163953Srrs } 1156163953Srrs } 1157178251Srrs#endif 1158163953Srrs } 1159163953Srrs } 1160163953Srrs if (match == 0) { 1161163953Srrs /* This endpoint does not have this address */ 1162163953Srrs SCTP_INP_RUNLOCK(inp); 1163163953Srrs continue; 1164163953Srrs } 1165163953Srrs } 1166163953Srrs /* 1167163953Srrs * Ok if we hit here the ep has the address, does it hold 1168163953Srrs * the tcb? 1169163953Srrs */ 1170246635Stuexen /* XXX: Why don't we TAILQ_FOREACH through sctp_asoc_list? */ 1171163953Srrs stcb = LIST_FIRST(&inp->sctp_asoc_list); 1172163953Srrs if (stcb == NULL) { 1173163953Srrs SCTP_INP_RUNLOCK(inp); 1174163953Srrs continue; 1175163953Srrs } 1176163953Srrs SCTP_TCB_LOCK(stcb); 1177246635Stuexen if (!sctp_does_stcb_own_this_addr(stcb, to)) { 1178246635Stuexen SCTP_TCB_UNLOCK(stcb); 1179246635Stuexen SCTP_INP_RUNLOCK(inp); 1180246635Stuexen continue; 1181246635Stuexen } 1182163953Srrs if (stcb->rport != rport) { 1183163953Srrs /* remote port does not match. */ 1184163953Srrs SCTP_TCB_UNLOCK(stcb); 1185163953Srrs SCTP_INP_RUNLOCK(inp); 1186163953Srrs continue; 1187163953Srrs } 1188173179Srrs if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { 1189173179Srrs SCTP_TCB_UNLOCK(stcb); 1190173179Srrs SCTP_INP_RUNLOCK(inp); 1191173179Srrs continue; 1192173179Srrs } 1193246635Stuexen if (!sctp_does_stcb_own_this_addr(stcb, to)) { 1194246635Stuexen SCTP_TCB_UNLOCK(stcb); 1195246635Stuexen SCTP_INP_RUNLOCK(inp); 1196246635Stuexen continue; 1197246635Stuexen } 1198163953Srrs /* Does this TCB have a matching address? */ 1199163953Srrs TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 1200163953Srrs 1201163953Srrs if (net->ro._l_addr.sa.sa_family != from->sa_family) { 1202163953Srrs /* not the same family, can't be a match */ 1203163953Srrs continue; 1204163953Srrs } 1205178251Srrs switch (from->sa_family) { 1206221249Stuexen#ifdef INET 1207178251Srrs case AF_INET: 1208178251Srrs { 1209178251Srrs struct sockaddr_in *sin, *rsin; 1210163953Srrs 1211178251Srrs sin = (struct sockaddr_in *)&net->ro._l_addr; 1212178251Srrs rsin = (struct sockaddr_in *)from; 1213178251Srrs if (sin->sin_addr.s_addr == 1214178251Srrs rsin->sin_addr.s_addr) { 1215178251Srrs /* found it */ 1216178251Srrs if (netp != NULL) { 1217178251Srrs *netp = net; 1218178251Srrs } 1219178251Srrs /* 1220178251Srrs * Update the endpoint 1221178251Srrs * pointer 1222178251Srrs */ 1223178251Srrs *inp_p = inp; 1224178251Srrs SCTP_INP_RUNLOCK(inp); 1225178251Srrs return (stcb); 1226163953Srrs } 1227178251Srrs break; 1228163953Srrs } 1229221249Stuexen#endif 1230178251Srrs#ifdef INET6 1231178251Srrs case AF_INET6: 1232178251Srrs { 1233178251Srrs struct sockaddr_in6 *sin6, *rsin6; 1234163953Srrs 1235178251Srrs sin6 = (struct sockaddr_in6 *)&net->ro._l_addr; 1236178251Srrs rsin6 = (struct sockaddr_in6 *)from; 1237179157Srrs if (SCTP6_ARE_ADDR_EQUAL(sin6, 1238179157Srrs rsin6)) { 1239178251Srrs /* found it */ 1240178251Srrs if (netp != NULL) { 1241178251Srrs *netp = net; 1242178251Srrs } 1243178251Srrs /* 1244178251Srrs * Update the endpoint 1245178251Srrs * pointer 1246178251Srrs */ 1247178251Srrs *inp_p = inp; 1248178251Srrs SCTP_INP_RUNLOCK(inp); 1249178251Srrs return (stcb); 1250163953Srrs } 1251178251Srrs break; 1252163953Srrs } 1253178251Srrs#endif 1254178251Srrs default: 1255178251Srrs /* TSNH */ 1256178251Srrs break; 1257163953Srrs } 1258163953Srrs } 1259163953Srrs SCTP_TCB_UNLOCK(stcb); 1260163953Srrs SCTP_INP_RUNLOCK(inp); 1261163953Srrs } 1262163953Srrs return (NULL); 1263163953Srrs} 1264163953Srrs 1265246595Stuexen 1266163953Srrs/* 1267163953Srrs * rules for use 1268163953Srrs * 1269163953Srrs * 1) If I return a NULL you must decrement any INP ref cnt. 2) If I find an 1270163953Srrs * stcb, both will be locked (locked_tcb and stcb) but decrement will be done 1271163953Srrs * (if locked == NULL). 3) Decrement happens on return ONLY if locked == 1272163953Srrs * NULL. 1273163953Srrs */ 1274163953Srrs 1275163953Srrsstruct sctp_tcb * 1276163953Srrssctp_findassociation_ep_addr(struct sctp_inpcb **inp_p, struct sockaddr *remote, 1277163953Srrs struct sctp_nets **netp, struct sockaddr *local, struct sctp_tcb *locked_tcb) 1278163953Srrs{ 1279163953Srrs struct sctpasochead *head; 1280163953Srrs struct sctp_inpcb *inp; 1281168299Srrs struct sctp_tcb *stcb = NULL; 1282163953Srrs struct sctp_nets *net; 1283163953Srrs uint16_t rport; 1284163953Srrs 1285163953Srrs inp = *inp_p; 1286238455Stuexen switch (remote->sa_family) { 1287238455Stuexen#ifdef INET 1288238455Stuexen case AF_INET: 1289163953Srrs rport = (((struct sockaddr_in *)remote)->sin_port); 1290238455Stuexen break; 1291238455Stuexen#endif 1292238455Stuexen#ifdef INET6 1293238455Stuexen case AF_INET6: 1294163953Srrs rport = (((struct sockaddr_in6 *)remote)->sin6_port); 1295238455Stuexen break; 1296238455Stuexen#endif 1297238455Stuexen default: 1298163953Srrs return (NULL); 1299163953Srrs } 1300163953Srrs if (locked_tcb) { 1301163953Srrs /* 1302163953Srrs * UN-lock so we can do proper locking here this occurs when 1303163953Srrs * called from load_addresses_from_init. 1304163953Srrs */ 1305171943Srrs atomic_add_int(&locked_tcb->asoc.refcnt, 1); 1306163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 1307163953Srrs } 1308163953Srrs SCTP_INP_INFO_RLOCK(); 1309243564Stuexen if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 1310243564Stuexen (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { 1311168299Srrs /*- 1312163953Srrs * Now either this guy is our listener or it's the 1313163953Srrs * connector. If it is the one that issued the connect, then 1314163953Srrs * it's only chance is to be the first TCB in the list. If 1315163953Srrs * it is the acceptor, then do the special_lookup to hash 1316163953Srrs * and find the real inp. 1317163953Srrs */ 1318163953Srrs if ((inp->sctp_socket) && (inp->sctp_socket->so_qlimit)) { 1319163953Srrs /* to is peer addr, from is my addr */ 1320163953Srrs stcb = sctp_tcb_special_locate(inp_p, remote, local, 1321168299Srrs netp, inp->def_vrf_id); 1322163953Srrs if ((stcb != NULL) && (locked_tcb == NULL)) { 1323163953Srrs /* we have a locked tcb, lower refcount */ 1324163953Srrs SCTP_INP_DECR_REF(inp); 1325163953Srrs } 1326163953Srrs if ((locked_tcb != NULL) && (locked_tcb != stcb)) { 1327163953Srrs SCTP_INP_RLOCK(locked_tcb->sctp_ep); 1328163953Srrs SCTP_TCB_LOCK(locked_tcb); 1329171943Srrs atomic_subtract_int(&locked_tcb->asoc.refcnt, 1); 1330163953Srrs SCTP_INP_RUNLOCK(locked_tcb->sctp_ep); 1331163953Srrs } 1332163953Srrs SCTP_INP_INFO_RUNLOCK(); 1333163953Srrs return (stcb); 1334163953Srrs } else { 1335163953Srrs SCTP_INP_WLOCK(inp); 1336163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) { 1337163953Srrs goto null_return; 1338163953Srrs } 1339163953Srrs stcb = LIST_FIRST(&inp->sctp_asoc_list); 1340163953Srrs if (stcb == NULL) { 1341163953Srrs goto null_return; 1342163953Srrs } 1343163953Srrs SCTP_TCB_LOCK(stcb); 1344173179Srrs 1345163953Srrs if (stcb->rport != rport) { 1346163953Srrs /* remote port does not match. */ 1347163953Srrs SCTP_TCB_UNLOCK(stcb); 1348163953Srrs goto null_return; 1349163953Srrs } 1350173179Srrs if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { 1351173179Srrs SCTP_TCB_UNLOCK(stcb); 1352173179Srrs goto null_return; 1353173179Srrs } 1354209499Stuexen if (local && !sctp_does_stcb_own_this_addr(stcb, local)) { 1355209470Stuexen SCTP_TCB_UNLOCK(stcb); 1356209470Stuexen goto null_return; 1357209470Stuexen } 1358163953Srrs /* now look at the list of remote addresses */ 1359163953Srrs TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 1360165220Srrs#ifdef INVARIANTS 1361163953Srrs if (net == (TAILQ_NEXT(net, sctp_next))) { 1362163953Srrs panic("Corrupt net list"); 1363163953Srrs } 1364163953Srrs#endif 1365163953Srrs if (net->ro._l_addr.sa.sa_family != 1366163953Srrs remote->sa_family) { 1367163953Srrs /* not the same family */ 1368163953Srrs continue; 1369163953Srrs } 1370178251Srrs switch (remote->sa_family) { 1371221249Stuexen#ifdef INET 1372178251Srrs case AF_INET: 1373178251Srrs { 1374178251Srrs struct sockaddr_in *sin, 1375178251Srrs *rsin; 1376163953Srrs 1377178251Srrs sin = (struct sockaddr_in *) 1378178251Srrs &net->ro._l_addr; 1379178251Srrs rsin = (struct sockaddr_in *)remote; 1380178251Srrs if (sin->sin_addr.s_addr == 1381178251Srrs rsin->sin_addr.s_addr) { 1382178251Srrs /* found it */ 1383178251Srrs if (netp != NULL) { 1384178251Srrs *netp = net; 1385178251Srrs } 1386178251Srrs if (locked_tcb == NULL) { 1387178251Srrs SCTP_INP_DECR_REF(inp); 1388178251Srrs } else if (locked_tcb != stcb) { 1389178251Srrs SCTP_TCB_LOCK(locked_tcb); 1390178251Srrs } 1391178251Srrs if (locked_tcb) { 1392178251Srrs atomic_subtract_int(&locked_tcb->asoc.refcnt, 1); 1393178251Srrs } 1394178251Srrs SCTP_INP_WUNLOCK(inp); 1395178251Srrs SCTP_INP_INFO_RUNLOCK(); 1396178251Srrs return (stcb); 1397163953Srrs } 1398178251Srrs break; 1399163953Srrs } 1400221249Stuexen#endif 1401178251Srrs#ifdef INET6 1402178251Srrs case AF_INET6: 1403178251Srrs { 1404178251Srrs struct sockaddr_in6 *sin6, 1405178251Srrs *rsin6; 1406163953Srrs 1407178251Srrs sin6 = (struct sockaddr_in6 *)&net->ro._l_addr; 1408178251Srrs rsin6 = (struct sockaddr_in6 *)remote; 1409179157Srrs if (SCTP6_ARE_ADDR_EQUAL(sin6, 1410179157Srrs rsin6)) { 1411178251Srrs /* found it */ 1412178251Srrs if (netp != NULL) { 1413178251Srrs *netp = net; 1414178251Srrs } 1415178251Srrs if (locked_tcb == NULL) { 1416178251Srrs SCTP_INP_DECR_REF(inp); 1417178251Srrs } else if (locked_tcb != stcb) { 1418178251Srrs SCTP_TCB_LOCK(locked_tcb); 1419178251Srrs } 1420178251Srrs if (locked_tcb) { 1421178251Srrs atomic_subtract_int(&locked_tcb->asoc.refcnt, 1); 1422178251Srrs } 1423178251Srrs SCTP_INP_WUNLOCK(inp); 1424178251Srrs SCTP_INP_INFO_RUNLOCK(); 1425178251Srrs return (stcb); 1426163953Srrs } 1427178251Srrs break; 1428163953Srrs } 1429178251Srrs#endif 1430178251Srrs default: 1431178251Srrs /* TSNH */ 1432178251Srrs break; 1433163953Srrs } 1434163953Srrs } 1435163953Srrs SCTP_TCB_UNLOCK(stcb); 1436163953Srrs } 1437163953Srrs } else { 1438163953Srrs SCTP_INP_WLOCK(inp); 1439163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) { 1440163953Srrs goto null_return; 1441163953Srrs } 1442163953Srrs head = &inp->sctp_tcbhash[SCTP_PCBHASH_ALLADDR(rport, 1443163953Srrs inp->sctp_hashmark)]; 1444163953Srrs LIST_FOREACH(stcb, head, sctp_tcbhash) { 1445163953Srrs if (stcb->rport != rport) { 1446163953Srrs /* remote port does not match */ 1447163953Srrs continue; 1448163953Srrs } 1449173179Srrs SCTP_TCB_LOCK(stcb); 1450173179Srrs if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { 1451173179Srrs SCTP_TCB_UNLOCK(stcb); 1452173179Srrs continue; 1453173179Srrs } 1454209499Stuexen if (local && !sctp_does_stcb_own_this_addr(stcb, local)) { 1455209470Stuexen SCTP_TCB_UNLOCK(stcb); 1456209470Stuexen continue; 1457209470Stuexen } 1458163953Srrs /* now look at the list of remote addresses */ 1459163953Srrs TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 1460165220Srrs#ifdef INVARIANTS 1461163953Srrs if (net == (TAILQ_NEXT(net, sctp_next))) { 1462163953Srrs panic("Corrupt net list"); 1463163953Srrs } 1464163953Srrs#endif 1465163953Srrs if (net->ro._l_addr.sa.sa_family != 1466163953Srrs remote->sa_family) { 1467163953Srrs /* not the same family */ 1468163953Srrs continue; 1469163953Srrs } 1470178251Srrs switch (remote->sa_family) { 1471221249Stuexen#ifdef INET 1472178251Srrs case AF_INET: 1473178251Srrs { 1474178251Srrs struct sockaddr_in *sin, 1475178251Srrs *rsin; 1476163953Srrs 1477178251Srrs sin = (struct sockaddr_in *) 1478178251Srrs &net->ro._l_addr; 1479178251Srrs rsin = (struct sockaddr_in *)remote; 1480178251Srrs if (sin->sin_addr.s_addr == 1481178251Srrs rsin->sin_addr.s_addr) { 1482178251Srrs /* found it */ 1483178251Srrs if (netp != NULL) { 1484178251Srrs *netp = net; 1485178251Srrs } 1486178251Srrs if (locked_tcb == NULL) { 1487178251Srrs SCTP_INP_DECR_REF(inp); 1488178251Srrs } else if (locked_tcb != stcb) { 1489178251Srrs SCTP_TCB_LOCK(locked_tcb); 1490178251Srrs } 1491178251Srrs if (locked_tcb) { 1492178251Srrs atomic_subtract_int(&locked_tcb->asoc.refcnt, 1); 1493178251Srrs } 1494178251Srrs SCTP_INP_WUNLOCK(inp); 1495178251Srrs SCTP_INP_INFO_RUNLOCK(); 1496178251Srrs return (stcb); 1497163953Srrs } 1498178251Srrs break; 1499163953Srrs } 1500221249Stuexen#endif 1501178251Srrs#ifdef INET6 1502178251Srrs case AF_INET6: 1503178251Srrs { 1504178251Srrs struct sockaddr_in6 *sin6, 1505178251Srrs *rsin6; 1506163953Srrs 1507178251Srrs sin6 = (struct sockaddr_in6 *) 1508178251Srrs &net->ro._l_addr; 1509178251Srrs rsin6 = (struct sockaddr_in6 *)remote; 1510179157Srrs if (SCTP6_ARE_ADDR_EQUAL(sin6, 1511179157Srrs rsin6)) { 1512178251Srrs /* found it */ 1513178251Srrs if (netp != NULL) { 1514178251Srrs *netp = net; 1515178251Srrs } 1516178251Srrs if (locked_tcb == NULL) { 1517178251Srrs SCTP_INP_DECR_REF(inp); 1518178251Srrs } else if (locked_tcb != stcb) { 1519178251Srrs SCTP_TCB_LOCK(locked_tcb); 1520178251Srrs } 1521178251Srrs if (locked_tcb) { 1522178251Srrs atomic_subtract_int(&locked_tcb->asoc.refcnt, 1); 1523178251Srrs } 1524178251Srrs SCTP_INP_WUNLOCK(inp); 1525178251Srrs SCTP_INP_INFO_RUNLOCK(); 1526178251Srrs return (stcb); 1527163953Srrs } 1528178251Srrs break; 1529163953Srrs } 1530178251Srrs#endif 1531178251Srrs default: 1532178251Srrs /* TSNH */ 1533178251Srrs break; 1534163953Srrs } 1535163953Srrs } 1536163953Srrs SCTP_TCB_UNLOCK(stcb); 1537163953Srrs } 1538163953Srrs } 1539163953Srrsnull_return: 1540163953Srrs /* clean up for returning null */ 1541163953Srrs if (locked_tcb) { 1542163953Srrs SCTP_TCB_LOCK(locked_tcb); 1543171943Srrs atomic_subtract_int(&locked_tcb->asoc.refcnt, 1); 1544163953Srrs } 1545163953Srrs SCTP_INP_WUNLOCK(inp); 1546163953Srrs SCTP_INP_INFO_RUNLOCK(); 1547163953Srrs /* not found */ 1548163953Srrs return (NULL); 1549163953Srrs} 1550163953Srrs 1551246595Stuexen 1552163953Srrs/* 1553163953Srrs * Find an association for a specific endpoint using the association id given 1554163953Srrs * out in the COMM_UP notification 1555163953Srrs */ 1556163953Srrsstruct sctp_tcb * 1557185694Srrssctp_findasoc_ep_asocid_locked(struct sctp_inpcb *inp, sctp_assoc_t asoc_id, int want_lock) 1558163953Srrs{ 1559163953Srrs /* 1560163953Srrs * Use my the assoc_id to find a endpoint 1561163953Srrs */ 1562163953Srrs struct sctpasochead *head; 1563163953Srrs struct sctp_tcb *stcb; 1564163953Srrs uint32_t id; 1565163953Srrs 1566185694Srrs if (inp == NULL) { 1567185694Srrs SCTP_PRINTF("TSNH ep_associd\n"); 1568163953Srrs return (NULL); 1569163953Srrs } 1570185694Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) { 1571185694Srrs SCTP_PRINTF("TSNH ep_associd0\n"); 1572185694Srrs return (NULL); 1573185694Srrs } 1574163953Srrs id = (uint32_t) asoc_id; 1575185694Srrs head = &inp->sctp_asocidhash[SCTP_PCBHASH_ASOC(id, inp->hashasocidmark)]; 1576163953Srrs if (head == NULL) { 1577163953Srrs /* invalid id TSNH */ 1578185694Srrs SCTP_PRINTF("TSNH ep_associd1\n"); 1579163953Srrs return (NULL); 1580163953Srrs } 1581185694Srrs LIST_FOREACH(stcb, head, sctp_tcbasocidhash) { 1582163953Srrs if (stcb->asoc.assoc_id == id) { 1583163953Srrs if (inp != stcb->sctp_ep) { 1584163953Srrs /* 1585163953Srrs * some other guy has the same id active (id 1586163953Srrs * collision ??). 1587163953Srrs */ 1588185694Srrs SCTP_PRINTF("TSNH ep_associd2\n"); 1589163953Srrs continue; 1590163953Srrs } 1591173179Srrs if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { 1592173179Srrs continue; 1593173179Srrs } 1594163953Srrs if (want_lock) { 1595163953Srrs SCTP_TCB_LOCK(stcb); 1596163953Srrs } 1597163953Srrs return (stcb); 1598163953Srrs } 1599163953Srrs } 1600163953Srrs return (NULL); 1601163953Srrs} 1602163953Srrs 1603163953Srrs 1604185694Srrsstruct sctp_tcb * 1605185694Srrssctp_findassociation_ep_asocid(struct sctp_inpcb *inp, sctp_assoc_t asoc_id, int want_lock) 1606185694Srrs{ 1607185694Srrs struct sctp_tcb *stcb; 1608185694Srrs 1609185694Srrs SCTP_INP_RLOCK(inp); 1610185694Srrs stcb = sctp_findasoc_ep_asocid_locked(inp, asoc_id, want_lock); 1611185694Srrs SCTP_INP_RUNLOCK(inp); 1612185694Srrs return (stcb); 1613185694Srrs} 1614185694Srrs 1615185694Srrs 1616246595Stuexen/* 1617246595Stuexen * Endpoint probe expects that the INP_INFO is locked. 1618246595Stuexen */ 1619163953Srrsstatic struct sctp_inpcb * 1620163953Srrssctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head, 1621167598Srrs uint16_t lport, uint32_t vrf_id) 1622163953Srrs{ 1623163953Srrs struct sctp_inpcb *inp; 1624221249Stuexen struct sctp_laddr *laddr; 1625221249Stuexen 1626221249Stuexen#ifdef INET 1627163953Srrs struct sockaddr_in *sin; 1628178251Srrs 1629221249Stuexen#endif 1630178251Srrs#ifdef INET6 1631163953Srrs struct sockaddr_in6 *sin6; 1632178251Srrs struct sockaddr_in6 *intf_addr6; 1633178251Srrs 1634178251Srrs#endif 1635167598Srrs int fnd; 1636163953Srrs 1637221249Stuexen#ifdef INET 1638178251Srrs sin = NULL; 1639221249Stuexen#endif 1640178251Srrs#ifdef INET6 1641178251Srrs sin6 = NULL; 1642178251Srrs#endif 1643178251Srrs switch (nam->sa_family) { 1644221249Stuexen#ifdef INET 1645178251Srrs case AF_INET: 1646163953Srrs sin = (struct sockaddr_in *)nam; 1647178251Srrs break; 1648221249Stuexen#endif 1649178251Srrs#ifdef INET6 1650178251Srrs case AF_INET6: 1651163953Srrs sin6 = (struct sockaddr_in6 *)nam; 1652178251Srrs break; 1653178251Srrs#endif 1654178251Srrs default: 1655163953Srrs /* unsupported family */ 1656163953Srrs return (NULL); 1657163953Srrs } 1658181054Srrs 1659163953Srrs if (head == NULL) 1660163953Srrs return (NULL); 1661185694Srrs 1662163953Srrs LIST_FOREACH(inp, head, sctp_hash) { 1663163953Srrs SCTP_INP_RLOCK(inp); 1664163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) { 1665163953Srrs SCTP_INP_RUNLOCK(inp); 1666163953Srrs continue; 1667163953Srrs } 1668163953Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) && 1669163953Srrs (inp->sctp_lport == lport)) { 1670163953Srrs /* got it */ 1671267769Stuexen switch (nam->sa_family) { 1672221249Stuexen#ifdef INET 1673267769Stuexen case AF_INET: 1674267769Stuexen if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && 1675267769Stuexen SCTP_IPV6_V6ONLY(inp)) { 1676267769Stuexen /* 1677267769Stuexen * IPv4 on a IPv6 socket with ONLY 1678267769Stuexen * IPv6 set 1679267769Stuexen */ 1680267769Stuexen SCTP_INP_RUNLOCK(inp); 1681267769Stuexen continue; 1682267769Stuexen } 1683267769Stuexen if (prison_check_ip4(inp->ip_inp.inp.inp_cred, 1684267769Stuexen &sin->sin_addr) != 0) { 1685267769Stuexen SCTP_INP_RUNLOCK(inp); 1686267769Stuexen continue; 1687267769Stuexen } 1688267769Stuexen break; 1689221249Stuexen#endif 1690221249Stuexen#ifdef INET6 1691267769Stuexen case AF_INET6: 1692267769Stuexen /* 1693267769Stuexen * A V6 address and the endpoint is NOT 1694267769Stuexen * bound V6 1695267769Stuexen */ 1696267769Stuexen if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) { 1697267769Stuexen SCTP_INP_RUNLOCK(inp); 1698267769Stuexen continue; 1699267769Stuexen } 1700267769Stuexen if (prison_check_ip6(inp->ip_inp.inp.inp_cred, 1701267769Stuexen &sin6->sin6_addr) != 0) { 1702267769Stuexen SCTP_INP_RUNLOCK(inp); 1703267769Stuexen continue; 1704267769Stuexen } 1705267769Stuexen break; 1706267769Stuexen#endif 1707267769Stuexen default: 1708267769Stuexen break; 1709163953Srrs } 1710167598Srrs /* does a VRF id match? */ 1711167598Srrs fnd = 0; 1712167598Srrs if (inp->def_vrf_id == vrf_id) 1713167598Srrs fnd = 1; 1714167598Srrs 1715163953Srrs SCTP_INP_RUNLOCK(inp); 1716167598Srrs if (!fnd) 1717167598Srrs continue; 1718163953Srrs return (inp); 1719163953Srrs } 1720163953Srrs SCTP_INP_RUNLOCK(inp); 1721163953Srrs } 1722221249Stuexen switch (nam->sa_family) { 1723221249Stuexen#ifdef INET 1724221249Stuexen case AF_INET: 1725221249Stuexen if (sin->sin_addr.s_addr == INADDR_ANY) { 1726221249Stuexen /* Can't hunt for one that has no address specified */ 1727221249Stuexen return (NULL); 1728221249Stuexen } 1729221249Stuexen break; 1730221249Stuexen#endif 1731178251Srrs#ifdef INET6 1732221249Stuexen case AF_INET6: 1733221249Stuexen if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 1734221249Stuexen /* Can't hunt for one that has no address specified */ 1735221249Stuexen return (NULL); 1736221249Stuexen } 1737221249Stuexen break; 1738221249Stuexen#endif 1739221249Stuexen default: 1740221249Stuexen break; 1741163953Srrs } 1742163953Srrs /* 1743163953Srrs * ok, not bound to all so see if we can find a EP bound to this 1744163953Srrs * address. 1745163953Srrs */ 1746163953Srrs LIST_FOREACH(inp, head, sctp_hash) { 1747163953Srrs SCTP_INP_RLOCK(inp); 1748163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) { 1749163953Srrs SCTP_INP_RUNLOCK(inp); 1750163953Srrs continue; 1751163953Srrs } 1752163953Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL)) { 1753163953Srrs SCTP_INP_RUNLOCK(inp); 1754163953Srrs continue; 1755163953Srrs } 1756163953Srrs /* 1757163953Srrs * Ok this could be a likely candidate, look at all of its 1758163953Srrs * addresses 1759163953Srrs */ 1760163953Srrs if (inp->sctp_lport != lport) { 1761163953Srrs SCTP_INP_RUNLOCK(inp); 1762163953Srrs continue; 1763163953Srrs } 1764167598Srrs /* does a VRF id match? */ 1765167598Srrs fnd = 0; 1766167598Srrs if (inp->def_vrf_id == vrf_id) 1767167598Srrs fnd = 1; 1768167598Srrs 1769167598Srrs if (!fnd) { 1770167598Srrs SCTP_INP_RUNLOCK(inp); 1771167598Srrs continue; 1772167598Srrs } 1773163953Srrs LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { 1774163953Srrs if (laddr->ifa == NULL) { 1775169420Srrs SCTPDBG(SCTP_DEBUG_PCB1, "%s: NULL ifa\n", 1776294174Stuexen __func__); 1777163953Srrs continue; 1778163953Srrs } 1779169420Srrs SCTPDBG(SCTP_DEBUG_PCB1, "Ok laddr->ifa:%p is possible, ", 1780240148Stuexen (void *)laddr->ifa); 1781167598Srrs if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED) { 1782169420Srrs SCTPDBG(SCTP_DEBUG_PCB1, "Huh IFA being deleted\n"); 1783163953Srrs continue; 1784163953Srrs } 1785167598Srrs if (laddr->ifa->address.sa.sa_family == nam->sa_family) { 1786163953Srrs /* possible, see if it matches */ 1787178251Srrs switch (nam->sa_family) { 1788221249Stuexen#ifdef INET 1789178251Srrs case AF_INET: 1790163953Srrs if (sin->sin_addr.s_addr == 1791221249Stuexen laddr->ifa->address.sin.sin_addr.s_addr) { 1792163953Srrs SCTP_INP_RUNLOCK(inp); 1793163953Srrs return (inp); 1794163953Srrs } 1795178251Srrs break; 1796221249Stuexen#endif 1797178251Srrs#ifdef INET6 1798178251Srrs case AF_INET6: 1799167598Srrs intf_addr6 = &laddr->ifa->address.sin6; 1800179157Srrs if (SCTP6_ARE_ADDR_EQUAL(sin6, 1801179157Srrs intf_addr6)) { 1802163953Srrs SCTP_INP_RUNLOCK(inp); 1803163953Srrs return (inp); 1804163953Srrs } 1805178251Srrs break; 1806178251Srrs#endif 1807163953Srrs } 1808163953Srrs } 1809163953Srrs } 1810163953Srrs SCTP_INP_RUNLOCK(inp); 1811163953Srrs } 1812163953Srrs return (NULL); 1813163953Srrs} 1814163953Srrs 1815181054Srrs 1816181054Srrsstatic struct sctp_inpcb * 1817181054Srrssctp_isport_inuse(struct sctp_inpcb *inp, uint16_t lport, uint32_t vrf_id) 1818181054Srrs{ 1819181054Srrs struct sctppcbhead *head; 1820181054Srrs struct sctp_inpcb *t_inp; 1821181054Srrs int fnd; 1822181054Srrs 1823181054Srrs head = &SCTP_BASE_INFO(sctp_ephash)[SCTP_PCBHASH_ALLADDR(lport, 1824181054Srrs SCTP_BASE_INFO(hashmark))]; 1825181054Srrs LIST_FOREACH(t_inp, head, sctp_hash) { 1826181054Srrs if (t_inp->sctp_lport != lport) { 1827181054Srrs continue; 1828181054Srrs } 1829181054Srrs /* is it in the VRF in question */ 1830181054Srrs fnd = 0; 1831181054Srrs if (t_inp->def_vrf_id == vrf_id) 1832181054Srrs fnd = 1; 1833181054Srrs if (!fnd) 1834181054Srrs continue; 1835181054Srrs 1836181054Srrs /* This one is in use. */ 1837181054Srrs /* check the v6/v4 binding issue */ 1838181054Srrs if ((t_inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && 1839181054Srrs SCTP_IPV6_V6ONLY(t_inp)) { 1840181054Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { 1841181054Srrs /* collision in V6 space */ 1842181054Srrs return (t_inp); 1843181054Srrs } else { 1844181054Srrs /* inp is BOUND_V4 no conflict */ 1845181054Srrs continue; 1846181054Srrs } 1847181054Srrs } else if (t_inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { 1848181054Srrs /* t_inp is bound v4 and v6, conflict always */ 1849181054Srrs return (t_inp); 1850181054Srrs } else { 1851181054Srrs /* t_inp is bound only V4 */ 1852181054Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && 1853181054Srrs SCTP_IPV6_V6ONLY(inp)) { 1854181054Srrs /* no conflict */ 1855181054Srrs continue; 1856181054Srrs } 1857181054Srrs /* else fall through to conflict */ 1858181054Srrs } 1859181054Srrs return (t_inp); 1860181054Srrs } 1861181054Srrs return (NULL); 1862181054Srrs} 1863181054Srrs 1864181054Srrs 1865181054Srrsint 1866181054Srrssctp_swap_inpcb_for_listen(struct sctp_inpcb *inp) 1867181054Srrs{ 1868181054Srrs /* For 1-2-1 with port reuse */ 1869181054Srrs struct sctppcbhead *head; 1870283732Stuexen struct sctp_inpcb *tinp, *ninp; 1871181054Srrs 1872181054Srrs if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE)) { 1873181054Srrs /* only works with port reuse on */ 1874181054Srrs return (-1); 1875181054Srrs } 1876181054Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) { 1877181054Srrs return (0); 1878181054Srrs } 1879181054Srrs SCTP_INP_RUNLOCK(inp); 1880283732Stuexen SCTP_INP_INFO_WLOCK(); 1881181054Srrs head = &SCTP_BASE_INFO(sctp_ephash)[SCTP_PCBHASH_ALLADDR(inp->sctp_lport, 1882181054Srrs SCTP_BASE_INFO(hashmark))]; 1883181054Srrs /* Kick out all non-listeners to the TCP hash */ 1884283732Stuexen LIST_FOREACH_SAFE(tinp, head, sctp_hash, ninp) { 1885181054Srrs if (tinp->sctp_lport != inp->sctp_lport) { 1886181054Srrs continue; 1887181054Srrs } 1888181054Srrs if (tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) { 1889181054Srrs continue; 1890181054Srrs } 1891181054Srrs if (tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 1892181054Srrs continue; 1893181054Srrs } 1894181054Srrs if (tinp->sctp_socket->so_qlimit) { 1895181054Srrs continue; 1896181054Srrs } 1897181054Srrs SCTP_INP_WLOCK(tinp); 1898181054Srrs LIST_REMOVE(tinp, sctp_hash); 1899181054Srrs head = &SCTP_BASE_INFO(sctp_tcpephash)[SCTP_PCBHASH_ALLADDR(tinp->sctp_lport, SCTP_BASE_INFO(hashtcpmark))]; 1900181054Srrs tinp->sctp_flags |= SCTP_PCB_FLAGS_IN_TCPPOOL; 1901181054Srrs LIST_INSERT_HEAD(head, tinp, sctp_hash); 1902181054Srrs SCTP_INP_WUNLOCK(tinp); 1903181054Srrs } 1904181054Srrs SCTP_INP_WLOCK(inp); 1905181054Srrs /* Pull from where he was */ 1906181054Srrs LIST_REMOVE(inp, sctp_hash); 1907181054Srrs inp->sctp_flags &= ~SCTP_PCB_FLAGS_IN_TCPPOOL; 1908181054Srrs head = &SCTP_BASE_INFO(sctp_ephash)[SCTP_PCBHASH_ALLADDR(inp->sctp_lport, SCTP_BASE_INFO(hashmark))]; 1909181054Srrs LIST_INSERT_HEAD(head, inp, sctp_hash); 1910181054Srrs SCTP_INP_WUNLOCK(inp); 1911181054Srrs SCTP_INP_RLOCK(inp); 1912283732Stuexen SCTP_INP_INFO_WUNLOCK(); 1913181054Srrs return (0); 1914181054Srrs} 1915181054Srrs 1916181054Srrs 1917163953Srrsstruct sctp_inpcb * 1918169420Srrssctp_pcb_findep(struct sockaddr *nam, int find_tcp_pool, int have_lock, 1919169420Srrs uint32_t vrf_id) 1920163953Srrs{ 1921163953Srrs /* 1922163953Srrs * First we check the hash table to see if someone has this port 1923163953Srrs * bound with just the port. 1924163953Srrs */ 1925163953Srrs struct sctp_inpcb *inp; 1926163953Srrs struct sctppcbhead *head; 1927163953Srrs int lport; 1928215039Stuexen unsigned int i; 1929163953Srrs 1930221249Stuexen#ifdef INET 1931221249Stuexen struct sockaddr_in *sin; 1932221249Stuexen 1933221249Stuexen#endif 1934221249Stuexen#ifdef INET6 1935221249Stuexen struct sockaddr_in6 *sin6; 1936221249Stuexen 1937221249Stuexen#endif 1938221249Stuexen 1939221249Stuexen switch (nam->sa_family) { 1940221249Stuexen#ifdef INET 1941221249Stuexen case AF_INET: 1942163953Srrs sin = (struct sockaddr_in *)nam; 1943228907Stuexen lport = sin->sin_port; 1944221249Stuexen break; 1945221249Stuexen#endif 1946221249Stuexen#ifdef INET6 1947221249Stuexen case AF_INET6: 1948163953Srrs sin6 = (struct sockaddr_in6 *)nam; 1949228907Stuexen lport = sin6->sin6_port; 1950221249Stuexen break; 1951221249Stuexen#endif 1952221249Stuexen default: 1953163953Srrs return (NULL); 1954163953Srrs } 1955163953Srrs /* 1956163953Srrs * I could cheat here and just cast to one of the types but we will 1957163953Srrs * do it right. It also provides the check against an Unsupported 1958163953Srrs * type too. 1959163953Srrs */ 1960163953Srrs /* Find the head of the ALLADDR chain */ 1961163953Srrs if (have_lock == 0) { 1962163953Srrs SCTP_INP_INFO_RLOCK(); 1963163953Srrs } 1964179783Srrs head = &SCTP_BASE_INFO(sctp_ephash)[SCTP_PCBHASH_ALLADDR(lport, 1965179783Srrs SCTP_BASE_INFO(hashmark))]; 1966167598Srrs inp = sctp_endpoint_probe(nam, head, lport, vrf_id); 1967163953Srrs 1968163953Srrs /* 1969163953Srrs * If the TCP model exists it could be that the main listening 1970215039Stuexen * endpoint is gone but there still exists a connected socket for 1971215039Stuexen * this guy. If so we can return the first one that we find. This 1972215039Stuexen * may NOT be the correct one so the caller should be wary on the 1973215039Stuexen * returned INP. Currently the only caller that sets find_tcp_pool 1974215039Stuexen * is in bindx where we are verifying that a user CAN bind the 1975215039Stuexen * address. He either has bound it already, or someone else has, or 1976215039Stuexen * its open to bind, so this is good enough. 1977163953Srrs */ 1978163953Srrs if (inp == NULL && find_tcp_pool) { 1979215039Stuexen for (i = 0; i < SCTP_BASE_INFO(hashtcpmark) + 1; i++) { 1980215039Stuexen head = &SCTP_BASE_INFO(sctp_tcpephash)[i]; 1981215039Stuexen inp = sctp_endpoint_probe(nam, head, lport, vrf_id); 1982215039Stuexen if (inp) { 1983215039Stuexen break; 1984215039Stuexen } 1985215039Stuexen } 1986163953Srrs } 1987163953Srrs if (inp) { 1988163953Srrs SCTP_INP_INCR_REF(inp); 1989163953Srrs } 1990163953Srrs if (have_lock == 0) { 1991163953Srrs SCTP_INP_INFO_RUNLOCK(); 1992163953Srrs } 1993163953Srrs return (inp); 1994163953Srrs} 1995163953Srrs 1996246595Stuexen 1997163953Srrs/* 1998163953Srrs * Find an association for an endpoint with the pointer to whom you want to 1999163953Srrs * send to and the endpoint pointer. The address can be IPv4 or IPv6. We may 2000163953Srrs * need to change the *to to some other struct like a mbuf... 2001163953Srrs */ 2002163953Srrsstruct sctp_tcb * 2003237715Stuexensctp_findassociation_addr_sa(struct sockaddr *from, struct sockaddr *to, 2004170642Srrs struct sctp_inpcb **inp_p, struct sctp_nets **netp, int find_tcp_pool, 2005170642Srrs uint32_t vrf_id) 2006163953Srrs{ 2007168709Srrs struct sctp_inpcb *inp = NULL; 2008246635Stuexen struct sctp_tcb *stcb; 2009163953Srrs 2010163953Srrs SCTP_INP_INFO_RLOCK(); 2011163953Srrs if (find_tcp_pool) { 2012163953Srrs if (inp_p != NULL) { 2013246635Stuexen stcb = sctp_tcb_special_locate(inp_p, from, to, netp, 2014170642Srrs vrf_id); 2015163953Srrs } else { 2016246635Stuexen stcb = sctp_tcb_special_locate(&inp, from, to, netp, 2017170642Srrs vrf_id); 2018163953Srrs } 2019246635Stuexen if (stcb != NULL) { 2020163953Srrs SCTP_INP_INFO_RUNLOCK(); 2021246635Stuexen return (stcb); 2022163953Srrs } 2023163953Srrs } 2024167598Srrs inp = sctp_pcb_findep(to, 0, 1, vrf_id); 2025163953Srrs if (inp_p != NULL) { 2026163953Srrs *inp_p = inp; 2027163953Srrs } 2028163953Srrs SCTP_INP_INFO_RUNLOCK(); 2029163953Srrs if (inp == NULL) { 2030163953Srrs return (NULL); 2031163953Srrs } 2032163953Srrs /* 2033163953Srrs * ok, we have an endpoint, now lets find the assoc for it (if any) 2034163953Srrs * we now place the source address or from in the to of the find 2035163953Srrs * endpoint call. Since in reality this chain is used from the 2036163953Srrs * inbound packet side. 2037163953Srrs */ 2038163953Srrs if (inp_p != NULL) { 2039246635Stuexen stcb = sctp_findassociation_ep_addr(inp_p, from, netp, to, 2040170642Srrs NULL); 2041163953Srrs } else { 2042246635Stuexen stcb = sctp_findassociation_ep_addr(&inp, from, netp, to, 2043170642Srrs NULL); 2044163953Srrs } 2045246635Stuexen return (stcb); 2046163953Srrs} 2047163953Srrs 2048163953Srrs 2049163953Srrs/* 2050163953Srrs * This routine will grub through the mbuf that is a INIT or INIT-ACK and 2051163953Srrs * find all addresses that the sender has specified in any address list. Each 2052163953Srrs * address will be used to lookup the TCB and see if one exits. 2053163953Srrs */ 2054163953Srrsstatic struct sctp_tcb * 2055228653Stuexensctp_findassociation_special_addr(struct mbuf *m, int offset, 2056163953Srrs struct sctphdr *sh, struct sctp_inpcb **inp_p, struct sctp_nets **netp, 2057237715Stuexen struct sockaddr *dst) 2058163953Srrs{ 2059163953Srrs struct sctp_paramhdr *phdr, parm_buf; 2060258454Stuexen 2061258454Stuexen#if defined(INET) || defined(INET6) 2062246635Stuexen struct sctp_tcb *stcb; 2063258454Stuexen uint16_t ptype; 2064163953Srrs 2065258454Stuexen#endif 2066258454Stuexen uint16_t plen; 2067258454Stuexen 2068221249Stuexen#ifdef INET 2069221249Stuexen struct sockaddr_in sin4; 2070221249Stuexen 2071221249Stuexen#endif 2072221249Stuexen#ifdef INET6 2073221249Stuexen struct sockaddr_in6 sin6; 2074221249Stuexen 2075221249Stuexen#endif 2076221249Stuexen 2077221249Stuexen#ifdef INET 2078163953Srrs memset(&sin4, 0, sizeof(sin4)); 2079163953Srrs sin4.sin_len = sizeof(sin4); 2080163953Srrs sin4.sin_family = AF_INET; 2081163953Srrs sin4.sin_port = sh->src_port; 2082221249Stuexen#endif 2083221249Stuexen#ifdef INET6 2084221249Stuexen memset(&sin6, 0, sizeof(sin6)); 2085163953Srrs sin6.sin6_len = sizeof(sin6); 2086163953Srrs sin6.sin6_family = AF_INET6; 2087163953Srrs sin6.sin6_port = sh->src_port; 2088221249Stuexen#endif 2089163953Srrs 2090163953Srrs offset += sizeof(struct sctp_init_chunk); 2091163953Srrs 2092163953Srrs phdr = sctp_get_next_param(m, offset, &parm_buf, sizeof(parm_buf)); 2093163953Srrs while (phdr != NULL) { 2094163953Srrs /* now we must see if we want the parameter */ 2095258454Stuexen#if defined(INET) || defined(INET6) 2096163953Srrs ptype = ntohs(phdr->param_type); 2097258454Stuexen#endif 2098163953Srrs plen = ntohs(phdr->param_length); 2099163953Srrs if (plen == 0) { 2100163953Srrs break; 2101163953Srrs } 2102221249Stuexen#ifdef INET 2103163953Srrs if (ptype == SCTP_IPV4_ADDRESS && 2104163953Srrs plen == sizeof(struct sctp_ipv4addr_param)) { 2105163953Srrs /* Get the rest of the address */ 2106163953Srrs struct sctp_ipv4addr_param ip4_parm, *p4; 2107163953Srrs 2108163953Srrs phdr = sctp_get_next_param(m, offset, 2109169208Srrs (struct sctp_paramhdr *)&ip4_parm, min(plen, sizeof(ip4_parm))); 2110163953Srrs if (phdr == NULL) { 2111163953Srrs return (NULL); 2112163953Srrs } 2113163953Srrs p4 = (struct sctp_ipv4addr_param *)phdr; 2114163953Srrs memcpy(&sin4.sin_addr, &p4->addr, sizeof(p4->addr)); 2115163953Srrs /* look it up */ 2116246635Stuexen stcb = sctp_findassociation_ep_addr(inp_p, 2117237715Stuexen (struct sockaddr *)&sin4, netp, dst, NULL); 2118246635Stuexen if (stcb != NULL) { 2119246635Stuexen return (stcb); 2120163953Srrs } 2121221249Stuexen } 2122221249Stuexen#endif 2123221249Stuexen#ifdef INET6 2124221249Stuexen if (ptype == SCTP_IPV6_ADDRESS && 2125163953Srrs plen == sizeof(struct sctp_ipv6addr_param)) { 2126163953Srrs /* Get the rest of the address */ 2127163953Srrs struct sctp_ipv6addr_param ip6_parm, *p6; 2128163953Srrs 2129163953Srrs phdr = sctp_get_next_param(m, offset, 2130169208Srrs (struct sctp_paramhdr *)&ip6_parm, min(plen, sizeof(ip6_parm))); 2131163953Srrs if (phdr == NULL) { 2132163953Srrs return (NULL); 2133163953Srrs } 2134163953Srrs p6 = (struct sctp_ipv6addr_param *)phdr; 2135163953Srrs memcpy(&sin6.sin6_addr, &p6->addr, sizeof(p6->addr)); 2136163953Srrs /* look it up */ 2137246635Stuexen stcb = sctp_findassociation_ep_addr(inp_p, 2138237715Stuexen (struct sockaddr *)&sin6, netp, dst, NULL); 2139246635Stuexen if (stcb != NULL) { 2140246635Stuexen return (stcb); 2141163953Srrs } 2142163953Srrs } 2143221249Stuexen#endif 2144163953Srrs offset += SCTP_SIZE32(plen); 2145163953Srrs phdr = sctp_get_next_param(m, offset, &parm_buf, 2146163953Srrs sizeof(parm_buf)); 2147163953Srrs } 2148163953Srrs return (NULL); 2149163953Srrs} 2150163953Srrs 2151163953Srrsstatic struct sctp_tcb * 2152185694Srrssctp_findassoc_by_vtag(struct sockaddr *from, struct sockaddr *to, uint32_t vtag, 2153163953Srrs struct sctp_inpcb **inp_p, struct sctp_nets **netp, uint16_t rport, 2154185694Srrs uint16_t lport, int skip_src_check, uint32_t vrf_id, uint32_t remote_tag) 2155163953Srrs{ 2156163953Srrs /* 2157163953Srrs * Use my vtag to hash. If we find it we then verify the source addr 2158163953Srrs * is in the assoc. If all goes well we save a bit on rec of a 2159163953Srrs * packet. 2160163953Srrs */ 2161163953Srrs struct sctpasochead *head; 2162163953Srrs struct sctp_nets *net; 2163163953Srrs struct sctp_tcb *stcb; 2164163953Srrs 2165163953Srrs SCTP_INP_INFO_RLOCK(); 2166179783Srrs head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(vtag, 2167179783Srrs SCTP_BASE_INFO(hashasocmark))]; 2168163953Srrs LIST_FOREACH(stcb, head, sctp_asocs) { 2169163953Srrs SCTP_INP_RLOCK(stcb->sctp_ep); 2170163953Srrs if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) { 2171163953Srrs SCTP_INP_RUNLOCK(stcb->sctp_ep); 2172169208Srrs continue; 2173163953Srrs } 2174228653Stuexen if (stcb->sctp_ep->def_vrf_id != vrf_id) { 2175228653Stuexen SCTP_INP_RUNLOCK(stcb->sctp_ep); 2176228653Stuexen continue; 2177228653Stuexen } 2178163953Srrs SCTP_TCB_LOCK(stcb); 2179163953Srrs SCTP_INP_RUNLOCK(stcb->sctp_ep); 2180163953Srrs if (stcb->asoc.my_vtag == vtag) { 2181163953Srrs /* candidate */ 2182163953Srrs if (stcb->rport != rport) { 2183163953Srrs SCTP_TCB_UNLOCK(stcb); 2184163953Srrs continue; 2185163953Srrs } 2186163953Srrs if (stcb->sctp_ep->sctp_lport != lport) { 2187163953Srrs SCTP_TCB_UNLOCK(stcb); 2188163953Srrs continue; 2189163953Srrs } 2190173179Srrs if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { 2191173179Srrs SCTP_TCB_UNLOCK(stcb); 2192173179Srrs continue; 2193173179Srrs } 2194185694Srrs /* RRS:Need toaddr check here */ 2195185694Srrs if (sctp_does_stcb_own_this_addr(stcb, to) == 0) { 2196185694Srrs /* Endpoint does not own this address */ 2197185694Srrs SCTP_TCB_UNLOCK(stcb); 2198185694Srrs continue; 2199185694Srrs } 2200185694Srrs if (remote_tag) { 2201185694Srrs /* 2202215034Sbrucec * If we have both vtags that's all we match 2203185694Srrs * on 2204185694Srrs */ 2205185694Srrs if (stcb->asoc.peer_vtag == remote_tag) { 2206185694Srrs /* 2207185694Srrs * If both tags match we consider it 2208185694Srrs * conclusive and check NO 2209185694Srrs * source/destination addresses 2210185694Srrs */ 2211185694Srrs goto conclusive; 2212185694Srrs } 2213185694Srrs } 2214163953Srrs if (skip_src_check) { 2215185694Srrs conclusive: 2216185694Srrs if (from) { 2217228907Stuexen *netp = sctp_findnet(stcb, from); 2218185694Srrs } else { 2219185694Srrs *netp = NULL; /* unknown */ 2220185694Srrs } 2221169420Srrs if (inp_p) 2222169420Srrs *inp_p = stcb->sctp_ep; 2223163953Srrs SCTP_INP_INFO_RUNLOCK(); 2224163953Srrs return (stcb); 2225163953Srrs } 2226163953Srrs net = sctp_findnet(stcb, from); 2227163953Srrs if (net) { 2228163953Srrs /* yep its him. */ 2229163953Srrs *netp = net; 2230163953Srrs SCTP_STAT_INCR(sctps_vtagexpress); 2231163953Srrs *inp_p = stcb->sctp_ep; 2232163953Srrs SCTP_INP_INFO_RUNLOCK(); 2233163953Srrs return (stcb); 2234163953Srrs } else { 2235163953Srrs /* 2236163953Srrs * not him, this should only happen in rare 2237163953Srrs * cases so I peg it. 2238163953Srrs */ 2239163953Srrs SCTP_STAT_INCR(sctps_vtagbogus); 2240163953Srrs } 2241163953Srrs } 2242163953Srrs SCTP_TCB_UNLOCK(stcb); 2243163953Srrs } 2244163953Srrs SCTP_INP_INFO_RUNLOCK(); 2245163953Srrs return (NULL); 2246163953Srrs} 2247163953Srrs 2248246595Stuexen 2249163953Srrs/* 2250163953Srrs * Find an association with the pointer to the inbound IP packet. This can be 2251163953Srrs * a IPv4 or IPv6 packet. 2252163953Srrs */ 2253163953Srrsstruct sctp_tcb * 2254228653Stuexensctp_findassociation_addr(struct mbuf *m, int offset, 2255237715Stuexen struct sockaddr *src, struct sockaddr *dst, 2256163953Srrs struct sctphdr *sh, struct sctp_chunkhdr *ch, 2257168299Srrs struct sctp_inpcb **inp_p, struct sctp_nets **netp, uint32_t vrf_id) 2258163953Srrs{ 2259246635Stuexen struct sctp_tcb *stcb; 2260163953Srrs struct sctp_inpcb *inp; 2261163953Srrs 2262185694Srrs if (sh->v_tag) { 2263185694Srrs /* we only go down this path if vtag is non-zero */ 2264246635Stuexen stcb = sctp_findassoc_by_vtag(src, dst, ntohl(sh->v_tag), 2265185694Srrs inp_p, netp, sh->src_port, sh->dest_port, 0, vrf_id, 0); 2266246635Stuexen if (stcb) { 2267246635Stuexen return (stcb); 2268185694Srrs } 2269185694Srrs } 2270163953Srrs if (inp_p) { 2271246635Stuexen stcb = sctp_findassociation_addr_sa(src, dst, inp_p, netp, 2272295208Stuexen 1, vrf_id); 2273163953Srrs inp = *inp_p; 2274163953Srrs } else { 2275246635Stuexen stcb = sctp_findassociation_addr_sa(src, dst, &inp, netp, 2276295208Stuexen 1, vrf_id); 2277163953Srrs } 2278246635Stuexen SCTPDBG(SCTP_DEBUG_PCB1, "stcb:%p inp:%p\n", (void *)stcb, (void *)inp); 2279246635Stuexen if (stcb == NULL && inp) { 2280163953Srrs /* Found a EP but not this address */ 2281163953Srrs if ((ch->chunk_type == SCTP_INITIATION) || 2282163953Srrs (ch->chunk_type == SCTP_INITIATION_ACK)) { 2283169208Srrs /*- 2284163953Srrs * special hook, we do NOT return linp or an 2285163953Srrs * association that is linked to an existing 2286163953Srrs * association that is under the TCP pool (i.e. no 2287163953Srrs * listener exists). The endpoint finding routine 2288215034Sbrucec * will always find a listener before examining the 2289163953Srrs * TCP pool. 2290163953Srrs */ 2291163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) { 2292163953Srrs if (inp_p) { 2293163953Srrs *inp_p = NULL; 2294163953Srrs } 2295163953Srrs return (NULL); 2296163953Srrs } 2297246635Stuexen stcb = sctp_findassociation_special_addr(m, 2298237715Stuexen offset, sh, &inp, netp, dst); 2299163953Srrs if (inp_p != NULL) { 2300163953Srrs *inp_p = inp; 2301163953Srrs } 2302163953Srrs } 2303163953Srrs } 2304246635Stuexen SCTPDBG(SCTP_DEBUG_PCB1, "stcb is %p\n", (void *)stcb); 2305246635Stuexen return (stcb); 2306163953Srrs} 2307163953Srrs 2308163953Srrs/* 2309163953Srrs * lookup an association by an ASCONF lookup address. 2310163953Srrs * if the lookup address is 0.0.0.0 or ::0, use the vtag to do the lookup 2311163953Srrs */ 2312163953Srrsstruct sctp_tcb * 2313228653Stuexensctp_findassociation_ep_asconf(struct mbuf *m, int offset, 2314237715Stuexen struct sockaddr *dst, struct sctphdr *sh, 2315237715Stuexen struct sctp_inpcb **inp_p, struct sctp_nets **netp, uint32_t vrf_id) 2316163953Srrs{ 2317163953Srrs struct sctp_tcb *stcb; 2318271746Stuexen union sctp_sockstore remote_store; 2319221249Stuexen struct sctp_paramhdr parm_buf, *phdr; 2320221249Stuexen int ptype; 2321221249Stuexen int zero_address = 0; 2322178251Srrs 2323221249Stuexen#ifdef INET 2324221249Stuexen struct sockaddr_in *sin; 2325221249Stuexen 2326221249Stuexen#endif 2327178251Srrs#ifdef INET6 2328221249Stuexen struct sockaddr_in6 *sin6; 2329178251Srrs 2330178251Srrs#endif 2331163953Srrs 2332163953Srrs memset(&remote_store, 0, sizeof(remote_store)); 2333163953Srrs phdr = sctp_get_next_param(m, offset + sizeof(struct sctp_asconf_chunk), 2334163953Srrs &parm_buf, sizeof(struct sctp_paramhdr)); 2335163953Srrs if (phdr == NULL) { 2336169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "%s: failed to get asconf lookup addr\n", 2337294174Stuexen __func__); 2338163953Srrs return NULL; 2339163953Srrs } 2340163953Srrs ptype = (int)((uint32_t) ntohs(phdr->param_type)); 2341163953Srrs /* get the correlation address */ 2342178251Srrs switch (ptype) { 2343178251Srrs#ifdef INET6 2344178251Srrs case SCTP_IPV6_ADDRESS: 2345178251Srrs { 2346178251Srrs /* ipv6 address param */ 2347178251Srrs struct sctp_ipv6addr_param *p6, p6_buf; 2348163953Srrs 2349178251Srrs if (ntohs(phdr->param_length) != sizeof(struct sctp_ipv6addr_param)) { 2350178251Srrs return NULL; 2351178251Srrs } 2352178251Srrs p6 = (struct sctp_ipv6addr_param *)sctp_get_next_param(m, 2353178251Srrs offset + sizeof(struct sctp_asconf_chunk), 2354178251Srrs &p6_buf.ph, sizeof(*p6)); 2355178251Srrs if (p6 == NULL) { 2356178251Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "%s: failed to get asconf v6 lookup addr\n", 2357294174Stuexen __func__); 2358178251Srrs return (NULL); 2359178251Srrs } 2360271746Stuexen sin6 = &remote_store.sin6; 2361178251Srrs sin6->sin6_family = AF_INET6; 2362178251Srrs sin6->sin6_len = sizeof(*sin6); 2363178251Srrs sin6->sin6_port = sh->src_port; 2364178251Srrs memcpy(&sin6->sin6_addr, &p6->addr, sizeof(struct in6_addr)); 2365178251Srrs if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) 2366178251Srrs zero_address = 1; 2367178251Srrs break; 2368163953Srrs } 2369178251Srrs#endif 2370221249Stuexen#ifdef INET 2371178251Srrs case SCTP_IPV4_ADDRESS: 2372178251Srrs { 2373178251Srrs /* ipv4 address param */ 2374178251Srrs struct sctp_ipv4addr_param *p4, p4_buf; 2375163953Srrs 2376178251Srrs if (ntohs(phdr->param_length) != sizeof(struct sctp_ipv4addr_param)) { 2377178251Srrs return NULL; 2378178251Srrs } 2379178251Srrs p4 = (struct sctp_ipv4addr_param *)sctp_get_next_param(m, 2380178251Srrs offset + sizeof(struct sctp_asconf_chunk), 2381178251Srrs &p4_buf.ph, sizeof(*p4)); 2382178251Srrs if (p4 == NULL) { 2383178251Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "%s: failed to get asconf v4 lookup addr\n", 2384294174Stuexen __func__); 2385178251Srrs return (NULL); 2386178251Srrs } 2387271746Stuexen sin = &remote_store.sin; 2388178251Srrs sin->sin_family = AF_INET; 2389178251Srrs sin->sin_len = sizeof(*sin); 2390178251Srrs sin->sin_port = sh->src_port; 2391178251Srrs memcpy(&sin->sin_addr, &p4->addr, sizeof(struct in_addr)); 2392178251Srrs if (sin->sin_addr.s_addr == INADDR_ANY) 2393178251Srrs zero_address = 1; 2394178251Srrs break; 2395163953Srrs } 2396221249Stuexen#endif 2397178251Srrs default: 2398163953Srrs /* invalid address param type */ 2399163953Srrs return NULL; 2400163953Srrs } 2401163953Srrs 2402163953Srrs if (zero_address) { 2403237715Stuexen stcb = sctp_findassoc_by_vtag(NULL, dst, ntohl(sh->v_tag), inp_p, 2404185694Srrs netp, sh->src_port, sh->dest_port, 1, vrf_id, 0); 2405239052Stuexen if (stcb != NULL) { 2406239052Stuexen SCTP_INP_DECR_REF(*inp_p); 2407239052Stuexen } 2408163953Srrs } else { 2409163953Srrs stcb = sctp_findassociation_ep_addr(inp_p, 2410271746Stuexen &remote_store.sa, netp, 2411237715Stuexen dst, NULL); 2412163953Srrs } 2413163953Srrs return (stcb); 2414163953Srrs} 2415163953Srrs 2416163953Srrs 2417163953Srrs/* 2418163953Srrs * allocate a sctp_inpcb and setup a temporary binding to a port/all 2419163953Srrs * addresses. This way if we don't get a bind we by default pick a ephemeral 2420163953Srrs * port with all addresses bound. 2421163953Srrs */ 2422163953Srrsint 2423170205Srrssctp_inpcb_alloc(struct socket *so, uint32_t vrf_id) 2424163953Srrs{ 2425163953Srrs /* 2426163953Srrs * we get called when a new endpoint starts up. We need to allocate 2427163953Srrs * the sctp_inpcb structure from the zone and init it. Mark it as 2428163953Srrs * unbound and find a port that we can use as an ephemeral with 2429163953Srrs * INADDR_ANY. If the user binds later no problem we can then add in 2430163953Srrs * the specific addresses. And setup the default parameters for the 2431163953Srrs * EP. 2432163953Srrs */ 2433163953Srrs int i, error; 2434163953Srrs struct sctp_inpcb *inp; 2435163953Srrs struct sctp_pcb *m; 2436163953Srrs struct timeval time; 2437163953Srrs sctp_sharedkey_t *null_key; 2438163953Srrs 2439163953Srrs error = 0; 2440163953Srrs 2441163953Srrs SCTP_INP_INFO_WLOCK(); 2442179783Srrs inp = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_ep), struct sctp_inpcb); 2443163953Srrs if (inp == NULL) { 2444169420Srrs SCTP_PRINTF("Out of SCTP-INPCB structures - no resources\n"); 2445163953Srrs SCTP_INP_INFO_WUNLOCK(); 2446171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOBUFS); 2447163953Srrs return (ENOBUFS); 2448163953Srrs } 2449163953Srrs /* zap it */ 2450163953Srrs bzero(inp, sizeof(*inp)); 2451163953Srrs 2452163953Srrs /* bump generations */ 2453163953Srrs /* setup socket pointers */ 2454163953Srrs inp->sctp_socket = so; 2455163953Srrs inp->ip_inp.inp.inp_socket = so; 2456267769Stuexen inp->ip_inp.inp.inp_cred = crhold(so->so_cred); 2457225549Stuexen#ifdef INET6 2458250466Stuexen if (INP_SOCKAF(so) == AF_INET6) { 2459250466Stuexen if (MODULE_GLOBAL(ip6_auto_flowlabel)) { 2460250466Stuexen inp->ip_inp.inp.inp_flags |= IN6P_AUTOFLOWLABEL; 2461250466Stuexen } 2462250466Stuexen if (MODULE_GLOBAL(ip6_v6only)) { 2463250466Stuexen inp->ip_inp.inp.inp_flags |= IN6P_IPV6_V6ONLY; 2464250466Stuexen } 2465225549Stuexen } 2466225549Stuexen#endif 2467185694Srrs inp->sctp_associd_counter = 1; 2468167736Srrs inp->partial_delivery_point = SCTP_SB_LIMIT_RCV(so) >> SCTP_PARTIAL_DELIVERY_SHIFT; 2469163953Srrs inp->sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT; 2470283724Stuexen inp->max_cwnd = 0; 2471211944Stuexen inp->sctp_cmt_on_off = SCTP_BASE_SYSCTL(sctp_cmt_on_off); 2472270356Stuexen inp->ecn_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_ecn_enable); 2473270357Stuexen inp->prsctp_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_pr_enable); 2474270362Stuexen if (SCTP_BASE_SYSCTL(sctp_auth_disable)) { 2475270362Stuexen inp->auth_supported = 0; 2476270362Stuexen } else { 2477270362Stuexen inp->auth_supported = 1; 2478270362Stuexen } 2479270362Stuexen inp->asconf_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_asconf_enable); 2480270361Stuexen inp->reconfig_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_reconfig_enable); 2481270359Stuexen inp->nrsack_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_nrsack_enable); 2482270360Stuexen inp->pktdrop_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_pktdrop_enable); 2483284633Stuexen inp->fibnum = so->so_fibnum; 2484185694Srrs /* init the small hash table we use to track asocid <-> tcb */ 2485185694Srrs inp->sctp_asocidhash = SCTP_HASH_INIT(SCTP_STACK_VTAG_HASH_SIZE, &inp->hashasocidmark); 2486185694Srrs if (inp->sctp_asocidhash == NULL) { 2487267769Stuexen crfree(inp->ip_inp.inp.inp_cred); 2488185694Srrs SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp); 2489185694Srrs SCTP_INP_INFO_WUNLOCK(); 2490208864Srrs return (ENOBUFS); 2491185694Srrs } 2492171167Sgnn#ifdef IPSEC 2493294187Stuexen error = ipsec_init_policy(so, &inp->ip_inp.inp.inp_sp); 2494163953Srrs if (error != 0) { 2495267769Stuexen crfree(inp->ip_inp.inp.inp_cred); 2496179783Srrs SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp); 2497163953Srrs SCTP_INP_INFO_WUNLOCK(); 2498163953Srrs return error; 2499163953Srrs } 2500171167Sgnn#endif /* IPSEC */ 2501163953Srrs SCTP_INCR_EP_COUNT(); 2502197288Srrs inp->ip_inp.inp.inp_ip_ttl = MODULE_GLOBAL(ip_defttl); 2503163953Srrs SCTP_INP_INFO_WUNLOCK(); 2504163953Srrs 2505163953Srrs so->so_pcb = (caddr_t)inp; 2506163953Srrs 2507223965Stuexen if (SCTP_SO_TYPE(so) == SOCK_SEQPACKET) { 2508163953Srrs /* UDP style socket */ 2509163953Srrs inp->sctp_flags = (SCTP_PCB_FLAGS_UDPTYPE | 2510163953Srrs SCTP_PCB_FLAGS_UNBOUND); 2511163953Srrs /* Be sure it is NON-BLOCKING IO for UDP */ 2512167598Srrs /* SCTP_SET_SO_NBIO(so); */ 2513167598Srrs } else if (SCTP_SO_TYPE(so) == SOCK_STREAM) { 2514163953Srrs /* TCP style socket */ 2515163953Srrs inp->sctp_flags = (SCTP_PCB_FLAGS_TCPTYPE | 2516163953Srrs SCTP_PCB_FLAGS_UNBOUND); 2517163953Srrs /* Be sure we have blocking IO by default */ 2518167598Srrs SCTP_CLEAR_SO_NBIO(so); 2519163953Srrs } else { 2520163953Srrs /* 2521163953Srrs * unsupported socket type (RAW, etc)- in case we missed it 2522163953Srrs * in protosw 2523163953Srrs */ 2524172091Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EOPNOTSUPP); 2525208970Srrs so->so_pcb = NULL; 2526267769Stuexen crfree(inp->ip_inp.inp.inp_cred); 2527294187Stuexen#ifdef IPSEC 2528294187Stuexen ipsec_delete_pcbpolicy(&inp->ip_inp.inp); 2529294187Stuexen#endif 2530179783Srrs SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp); 2531163953Srrs return (EOPNOTSUPP); 2532163953Srrs } 2533179783Srrs if (SCTP_BASE_SYSCTL(sctp_default_frag_interleave) == SCTP_FRAG_LEVEL_1) { 2534171943Srrs sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE); 2535171943Srrs sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS); 2536179783Srrs } else if (SCTP_BASE_SYSCTL(sctp_default_frag_interleave) == SCTP_FRAG_LEVEL_2) { 2537171943Srrs sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE); 2538171943Srrs sctp_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS); 2539179783Srrs } else if (SCTP_BASE_SYSCTL(sctp_default_frag_interleave) == SCTP_FRAG_LEVEL_0) { 2540171943Srrs sctp_feature_off(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE); 2541171943Srrs sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS); 2542171943Srrs } 2543179783Srrs inp->sctp_tcbhash = SCTP_HASH_INIT(SCTP_BASE_SYSCTL(sctp_pcbtblsize), 2544163953Srrs &inp->sctp_hashmark); 2545163953Srrs if (inp->sctp_tcbhash == NULL) { 2546169420Srrs SCTP_PRINTF("Out of SCTP-INPCB->hashinit - no resources\n"); 2547172091Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOBUFS); 2548208970Srrs so->so_pcb = NULL; 2549267769Stuexen crfree(inp->ip_inp.inp.inp_cred); 2550294187Stuexen#ifdef IPSEC 2551294187Stuexen ipsec_delete_pcbpolicy(&inp->ip_inp.inp); 2552294187Stuexen#endif 2553179783Srrs SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp); 2554163953Srrs return (ENOBUFS); 2555163953Srrs } 2556170205Srrs inp->def_vrf_id = vrf_id; 2557167598Srrs 2558163953Srrs SCTP_INP_INFO_WLOCK(); 2559163953Srrs SCTP_INP_LOCK_INIT(inp); 2560170786Srrs INP_LOCK_INIT(&inp->ip_inp.inp, "inp", "sctpinp"); 2561163953Srrs SCTP_INP_READ_INIT(inp); 2562163953Srrs SCTP_ASOC_CREATE_LOCK_INIT(inp); 2563163953Srrs /* lock the new ep */ 2564163953Srrs SCTP_INP_WLOCK(inp); 2565163953Srrs 2566163953Srrs /* add it to the info area */ 2567179783Srrs LIST_INSERT_HEAD(&SCTP_BASE_INFO(listhead), inp, sctp_list); 2568163953Srrs SCTP_INP_INFO_WUNLOCK(); 2569163953Srrs 2570163953Srrs TAILQ_INIT(&inp->read_queue); 2571163953Srrs LIST_INIT(&inp->sctp_addr_list); 2572167598Srrs 2573163953Srrs LIST_INIT(&inp->sctp_asoc_list); 2574163953Srrs 2575165220Srrs#ifdef SCTP_TRACK_FREED_ASOCS 2576165220Srrs /* TEMP CODE */ 2577165220Srrs LIST_INIT(&inp->sctp_asoc_free_list); 2578165220Srrs#endif 2579163953Srrs /* Init the timer structure for signature change */ 2580165647Srrs SCTP_OS_TIMER_INIT(&inp->sctp_ep.signature_change.timer); 2581163953Srrs inp->sctp_ep.signature_change.type = SCTP_TIMER_TYPE_NEWCOOKIE; 2582163953Srrs 2583163953Srrs /* now init the actual endpoint default data */ 2584163953Srrs m = &inp->sctp_ep; 2585163953Srrs 2586163953Srrs /* setup the base timeout information */ 2587163953Srrs m->sctp_timeoutticks[SCTP_TIMER_SEND] = SEC_TO_TICKS(SCTP_SEND_SEC); /* needed ? */ 2588163953Srrs m->sctp_timeoutticks[SCTP_TIMER_INIT] = SEC_TO_TICKS(SCTP_INIT_SEC); /* needed ? */ 2589179783Srrs m->sctp_timeoutticks[SCTP_TIMER_RECV] = MSEC_TO_TICKS(SCTP_BASE_SYSCTL(sctp_delayed_sack_time_default)); 2590179783Srrs m->sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(SCTP_BASE_SYSCTL(sctp_heartbeat_interval_default)); 2591179783Srrs m->sctp_timeoutticks[SCTP_TIMER_PMTU] = SEC_TO_TICKS(SCTP_BASE_SYSCTL(sctp_pmtu_raise_time_default)); 2592179783Srrs m->sctp_timeoutticks[SCTP_TIMER_MAXSHUTDOWN] = SEC_TO_TICKS(SCTP_BASE_SYSCTL(sctp_shutdown_guard_time_default)); 2593179783Srrs m->sctp_timeoutticks[SCTP_TIMER_SIGNATURE] = SEC_TO_TICKS(SCTP_BASE_SYSCTL(sctp_secret_lifetime_default)); 2594163953Srrs /* all max/min max are in ms */ 2595179783Srrs m->sctp_maxrto = SCTP_BASE_SYSCTL(sctp_rto_max_default); 2596179783Srrs m->sctp_minrto = SCTP_BASE_SYSCTL(sctp_rto_min_default); 2597179783Srrs m->initial_rto = SCTP_BASE_SYSCTL(sctp_rto_initial_default); 2598179783Srrs m->initial_init_rto_max = SCTP_BASE_SYSCTL(sctp_init_rto_max_default); 2599179783Srrs m->sctp_sack_freq = SCTP_BASE_SYSCTL(sctp_sack_freq_default); 2600179783Srrs m->max_init_times = SCTP_BASE_SYSCTL(sctp_init_rtx_max_default); 2601179783Srrs m->max_send_times = SCTP_BASE_SYSCTL(sctp_assoc_rtx_max_default); 2602179783Srrs m->def_net_failure = SCTP_BASE_SYSCTL(sctp_path_rtx_max_default); 2603224641Stuexen m->def_net_pf_threshold = SCTP_BASE_SYSCTL(sctp_path_pf_threshold); 2604163953Srrs m->sctp_sws_sender = SCTP_SWS_SENDER_DEF; 2605163953Srrs m->sctp_sws_receiver = SCTP_SWS_RECEIVER_DEF; 2606179783Srrs m->max_burst = SCTP_BASE_SYSCTL(sctp_max_burst_default); 2607218186Srrs m->fr_max_burst = SCTP_BASE_SYSCTL(sctp_fr_max_burst_default); 2608218186Srrs 2609217611Stuexen m->sctp_default_cc_module = SCTP_BASE_SYSCTL(sctp_default_cc_module); 2610217760Stuexen m->sctp_default_ss_module = SCTP_BASE_SYSCTL(sctp_default_ss_module); 2611252779Stuexen m->max_open_streams_intome = SCTP_BASE_SYSCTL(sctp_nr_incoming_streams_default); 2612163953Srrs /* number of streams to pre-open on a association */ 2613179783Srrs m->pre_open_stream_count = SCTP_BASE_SYSCTL(sctp_nr_outgoing_streams_default); 2614163953Srrs 2615163953Srrs /* Add adaptation cookie */ 2616246687Stuexen m->adaptation_layer_indicator = 0; 2617246687Stuexen m->adaptation_layer_indicator_provided = 0; 2618163953Srrs 2619163953Srrs /* seed random number generator */ 2620163953Srrs m->random_counter = 1; 2621163953Srrs m->store_at = SCTP_SIGNATURE_SIZE; 2622165647Srrs SCTP_READ_RANDOM(m->random_numbers, sizeof(m->random_numbers)); 2623163953Srrs sctp_fill_random_store(m); 2624163953Srrs 2625163953Srrs /* Minimum cookie size */ 2626163953Srrs m->size_of_a_cookie = (sizeof(struct sctp_init_msg) * 2) + 2627163953Srrs sizeof(struct sctp_state_cookie); 2628163953Srrs m->size_of_a_cookie += SCTP_SIGNATURE_SIZE; 2629163953Srrs 2630163953Srrs /* Setup the initial secret */ 2631169378Srrs (void)SCTP_GETTIME_TIMEVAL(&time); 2632163953Srrs m->time_of_secret_change = time.tv_sec; 2633163953Srrs 2634163953Srrs for (i = 0; i < SCTP_NUMBER_OF_SECRETS; i++) { 2635163953Srrs m->secret_key[0][i] = sctp_select_initial_TSN(m); 2636163953Srrs } 2637163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_NEWCOOKIE, inp, NULL, NULL); 2638163953Srrs 2639163953Srrs /* How long is a cookie good for ? */ 2640179783Srrs m->def_cookie_life = MSEC_TO_TICKS(SCTP_BASE_SYSCTL(sctp_valid_cookie_life_default)); 2641163953Srrs /* 2642163953Srrs * Initialize authentication parameters 2643163953Srrs */ 2644163953Srrs m->local_hmacs = sctp_default_supported_hmaclist(); 2645163953Srrs m->local_auth_chunks = sctp_alloc_chunklist(); 2646270362Stuexen if (inp->asconf_supported) { 2647270362Stuexen sctp_auth_add_chunk(SCTP_ASCONF, m->local_auth_chunks); 2648270362Stuexen sctp_auth_add_chunk(SCTP_ASCONF_ACK, m->local_auth_chunks); 2649270362Stuexen } 2650225549Stuexen m->default_dscp = 0; 2651225549Stuexen#ifdef INET6 2652225549Stuexen m->default_flowlabel = 0; 2653225549Stuexen#endif 2654227755Stuexen m->port = 0; /* encapsulation disabled by default */ 2655163953Srrs LIST_INIT(&m->shared_keys); 2656163953Srrs /* add default NULL key as key id 0 */ 2657163953Srrs null_key = sctp_alloc_sharedkey(); 2658163953Srrs sctp_insert_sharedkey(&m->shared_keys, null_key); 2659163953Srrs SCTP_INP_WUNLOCK(inp); 2660163953Srrs#ifdef SCTP_LOG_CLOSING 2661163953Srrs sctp_log_closing(inp, NULL, 12); 2662163953Srrs#endif 2663163953Srrs return (error); 2664163953Srrs} 2665163953Srrs 2666163953Srrs 2667163953Srrsvoid 2668163953Srrssctp_move_pcb_and_assoc(struct sctp_inpcb *old_inp, struct sctp_inpcb *new_inp, 2669163953Srrs struct sctp_tcb *stcb) 2670163953Srrs{ 2671163953Srrs struct sctp_nets *net; 2672163953Srrs uint16_t lport, rport; 2673163953Srrs struct sctppcbhead *head; 2674163953Srrs struct sctp_laddr *laddr, *oladdr; 2675163953Srrs 2676171990Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 2677163953Srrs SCTP_TCB_UNLOCK(stcb); 2678163953Srrs SCTP_INP_INFO_WLOCK(); 2679163953Srrs SCTP_INP_WLOCK(old_inp); 2680163953Srrs SCTP_INP_WLOCK(new_inp); 2681163953Srrs SCTP_TCB_LOCK(stcb); 2682171990Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 2683163953Srrs 2684163953Srrs new_inp->sctp_ep.time_of_secret_change = 2685163953Srrs old_inp->sctp_ep.time_of_secret_change; 2686163953Srrs memcpy(new_inp->sctp_ep.secret_key, old_inp->sctp_ep.secret_key, 2687163953Srrs sizeof(old_inp->sctp_ep.secret_key)); 2688163953Srrs new_inp->sctp_ep.current_secret_number = 2689163953Srrs old_inp->sctp_ep.current_secret_number; 2690163953Srrs new_inp->sctp_ep.last_secret_number = 2691163953Srrs old_inp->sctp_ep.last_secret_number; 2692163953Srrs new_inp->sctp_ep.size_of_a_cookie = old_inp->sctp_ep.size_of_a_cookie; 2693163953Srrs 2694163953Srrs /* make it so new data pours into the new socket */ 2695163953Srrs stcb->sctp_socket = new_inp->sctp_socket; 2696163953Srrs stcb->sctp_ep = new_inp; 2697163953Srrs 2698163953Srrs /* Copy the port across */ 2699163953Srrs lport = new_inp->sctp_lport = old_inp->sctp_lport; 2700163953Srrs rport = stcb->rport; 2701163953Srrs /* Pull the tcb from the old association */ 2702163953Srrs LIST_REMOVE(stcb, sctp_tcbhash); 2703163953Srrs LIST_REMOVE(stcb, sctp_tcblist); 2704188067Srrs if (stcb->asoc.in_asocid_hash) { 2705188067Srrs LIST_REMOVE(stcb, sctp_tcbasocidhash); 2706188067Srrs } 2707163953Srrs /* Now insert the new_inp into the TCP connected hash */ 2708215039Stuexen head = &SCTP_BASE_INFO(sctp_tcpephash)[SCTP_PCBHASH_ALLADDR((lport | rport), SCTP_BASE_INFO(hashtcpmark))]; 2709163953Srrs 2710163953Srrs LIST_INSERT_HEAD(head, new_inp, sctp_hash); 2711166086Srrs /* Its safe to access */ 2712166086Srrs new_inp->sctp_flags &= ~SCTP_PCB_FLAGS_UNBOUND; 2713163953Srrs 2714163953Srrs /* Now move the tcb into the endpoint list */ 2715163953Srrs LIST_INSERT_HEAD(&new_inp->sctp_asoc_list, stcb, sctp_tcblist); 2716163953Srrs /* 2717163953Srrs * Question, do we even need to worry about the ep-hash since we 2718163953Srrs * only have one connection? Probably not :> so lets get rid of it 2719163953Srrs * and not suck up any kernel memory in that. 2720163953Srrs */ 2721188067Srrs if (stcb->asoc.in_asocid_hash) { 2722188067Srrs struct sctpasochead *lhd; 2723163953Srrs 2724188067Srrs lhd = &new_inp->sctp_asocidhash[SCTP_PCBHASH_ASOC(stcb->asoc.assoc_id, 2725188067Srrs new_inp->hashasocidmark)]; 2726188067Srrs LIST_INSERT_HEAD(lhd, stcb, sctp_tcbasocidhash); 2727188067Srrs } 2728163953Srrs /* Ok. Let's restart timer. */ 2729163953Srrs TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 2730163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, new_inp, 2731163953Srrs stcb, net); 2732163953Srrs } 2733163953Srrs 2734163953Srrs SCTP_INP_INFO_WUNLOCK(); 2735163953Srrs if (new_inp->sctp_tcbhash != NULL) { 2736166023Srrs SCTP_HASH_FREE(new_inp->sctp_tcbhash, new_inp->sctp_hashmark); 2737163953Srrs new_inp->sctp_tcbhash = NULL; 2738163953Srrs } 2739163953Srrs if ((new_inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) { 2740163953Srrs /* Subset bound, so copy in the laddr list from the old_inp */ 2741163953Srrs LIST_FOREACH(oladdr, &old_inp->sctp_addr_list, sctp_nxt_addr) { 2742179783Srrs laddr = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_laddr), struct sctp_laddr); 2743163953Srrs if (laddr == NULL) { 2744163953Srrs /* 2745163953Srrs * Gak, what can we do? This assoc is really 2746163953Srrs * HOSED. We probably should send an abort 2747163953Srrs * here. 2748163953Srrs */ 2749169420Srrs SCTPDBG(SCTP_DEBUG_PCB1, "Association hosed in TCP model, out of laddr memory\n"); 2750163953Srrs continue; 2751163953Srrs } 2752163953Srrs SCTP_INCR_LADDR_COUNT(); 2753163953Srrs bzero(laddr, sizeof(*laddr)); 2754170056Srrs (void)SCTP_GETTIME_TIMEVAL(&laddr->start_time); 2755163953Srrs laddr->ifa = oladdr->ifa; 2756168299Srrs atomic_add_int(&laddr->ifa->refcount, 1); 2757163953Srrs LIST_INSERT_HEAD(&new_inp->sctp_addr_list, laddr, 2758163953Srrs sctp_nxt_addr); 2759163953Srrs new_inp->laddr_count++; 2760226203Stuexen if (oladdr == stcb->asoc.last_used_address) { 2761226203Stuexen stcb->asoc.last_used_address = laddr; 2762226203Stuexen } 2763163953Srrs } 2764163953Srrs } 2765163953Srrs /* 2766163953Srrs * Now any running timers need to be adjusted since we really don't 2767163953Srrs * care if they are running or not just blast in the new_inp into 2768163953Srrs * all of them. 2769163953Srrs */ 2770163953Srrs 2771163953Srrs stcb->asoc.dack_timer.ep = (void *)new_inp; 2772163953Srrs stcb->asoc.asconf_timer.ep = (void *)new_inp; 2773163953Srrs stcb->asoc.strreset_timer.ep = (void *)new_inp; 2774163953Srrs stcb->asoc.shut_guard_timer.ep = (void *)new_inp; 2775163953Srrs stcb->asoc.autoclose_timer.ep = (void *)new_inp; 2776163953Srrs stcb->asoc.delayed_event_timer.ep = (void *)new_inp; 2777172091Srrs stcb->asoc.delete_prim_timer.ep = (void *)new_inp; 2778163953Srrs /* now what about the nets? */ 2779163953Srrs TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 2780163953Srrs net->pmtu_timer.ep = (void *)new_inp; 2781226168Stuexen net->hb_timer.ep = (void *)new_inp; 2782163953Srrs net->rxt_timer.ep = (void *)new_inp; 2783163953Srrs } 2784163953Srrs SCTP_INP_WUNLOCK(new_inp); 2785163953Srrs SCTP_INP_WUNLOCK(old_inp); 2786163953Srrs} 2787163953Srrs 2788296052Stuexen/* 2789296052Stuexen * insert an laddr entry with the given ifa for the desired list 2790296052Stuexen */ 2791296052Stuexenstatic int 2792296052Stuexensctp_insert_laddr(struct sctpladdr *list, struct sctp_ifa *ifa, uint32_t act) 2793296052Stuexen{ 2794296052Stuexen struct sctp_laddr *laddr; 2795163953Srrs 2796296052Stuexen laddr = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_laddr), struct sctp_laddr); 2797296052Stuexen if (laddr == NULL) { 2798296052Stuexen /* out of memory? */ 2799296052Stuexen SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); 2800296052Stuexen return (EINVAL); 2801296052Stuexen } 2802296052Stuexen SCTP_INCR_LADDR_COUNT(); 2803296052Stuexen bzero(laddr, sizeof(*laddr)); 2804296052Stuexen (void)SCTP_GETTIME_TIMEVAL(&laddr->start_time); 2805296052Stuexen laddr->ifa = ifa; 2806296052Stuexen laddr->action = act; 2807296052Stuexen atomic_add_int(&ifa->refcount, 1); 2808296052Stuexen /* insert it */ 2809296052Stuexen LIST_INSERT_HEAD(list, laddr, sctp_nxt_addr); 2810167598Srrs 2811296052Stuexen return (0); 2812296052Stuexen} 2813163953Srrs 2814296052Stuexen/* 2815296052Stuexen * Remove an laddr entry from the local address list (on an assoc) 2816296052Stuexen */ 2817296052Stuexenstatic void 2818296052Stuexensctp_remove_laddr(struct sctp_laddr *laddr) 2819296052Stuexen{ 2820296052Stuexen 2821296052Stuexen /* remove from the list */ 2822296052Stuexen LIST_REMOVE(laddr, sctp_nxt_addr); 2823296052Stuexen sctp_free_ifa(laddr->ifa); 2824296052Stuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_laddr), laddr); 2825296052Stuexen SCTP_DECR_LADDR_COUNT(); 2826296052Stuexen} 2827296052Stuexen 2828296052Stuexen 2829296052Stuexen 2830171572Srrs/* sctp_ifap is used to bypass normal local address validation checks */ 2831163953Srrsint 2832170744Srrssctp_inpcb_bind(struct socket *so, struct sockaddr *addr, 2833171572Srrs struct sctp_ifa *sctp_ifap, struct thread *p) 2834163953Srrs{ 2835163953Srrs /* bind a ep to a socket address */ 2836163953Srrs struct sctppcbhead *head; 2837163953Srrs struct sctp_inpcb *inp, *inp_tmp; 2838163953Srrs struct inpcb *ip_inp; 2839181054Srrs int port_reuse_active = 0; 2840163953Srrs int bindall; 2841163953Srrs uint16_t lport; 2842163953Srrs int error; 2843167598Srrs uint32_t vrf_id; 2844163953Srrs 2845163953Srrs lport = 0; 2846163953Srrs bindall = 1; 2847163953Srrs inp = (struct sctp_inpcb *)so->so_pcb; 2848163953Srrs ip_inp = (struct inpcb *)so->so_pcb; 2849163953Srrs#ifdef SCTP_DEBUG 2850169420Srrs if (addr) { 2851244729Stuexen SCTPDBG(SCTP_DEBUG_PCB1, "Bind called port: %d\n", 2852169420Srrs ntohs(((struct sockaddr_in *)addr)->sin_port)); 2853244729Stuexen SCTPDBG(SCTP_DEBUG_PCB1, "Addr: "); 2854169420Srrs SCTPDBG_ADDR(SCTP_DEBUG_PCB1, addr); 2855163953Srrs } 2856169420Srrs#endif 2857163953Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) { 2858163953Srrs /* already did a bind, subsequent binds NOT allowed ! */ 2859171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); 2860163953Srrs return (EINVAL); 2861163953Srrs } 2862171531Srrs#ifdef INVARIANTS 2863171531Srrs if (p == NULL) 2864171531Srrs panic("null proc/thread"); 2865171531Srrs#endif 2866163953Srrs if (addr != NULL) { 2867178251Srrs switch (addr->sa_family) { 2868221249Stuexen#ifdef INET 2869178251Srrs case AF_INET: 2870178251Srrs { 2871178251Srrs struct sockaddr_in *sin; 2872163953Srrs 2873178251Srrs /* IPV6_V6ONLY socket? */ 2874178251Srrs if (SCTP_IPV6_V6ONLY(ip_inp)) { 2875171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); 2876171477Srrs return (EINVAL); 2877171943Srrs } 2878178251Srrs if (addr->sa_len != sizeof(*sin)) { 2879178251Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); 2880178251Srrs return (EINVAL); 2881178251Srrs } 2882178251Srrs sin = (struct sockaddr_in *)addr; 2883178251Srrs lport = sin->sin_port; 2884185435Sbz /* 2885185694Srrs * For LOOPBACK the prison_local_ip4() call 2886185694Srrs * will transmute the ip address to the 2887185694Srrs * proper value. 2888185435Sbz */ 2889188590Srrs if (p && (error = prison_local_ip4(p->td_ucred, &sin->sin_addr)) != 0) { 2890188590Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error); 2891188590Srrs return (error); 2892178251Srrs } 2893178251Srrs if (sin->sin_addr.s_addr != INADDR_ANY) { 2894178251Srrs bindall = 0; 2895178251Srrs } 2896178251Srrs break; 2897171477Srrs } 2898221249Stuexen#endif 2899178251Srrs#ifdef INET6 2900178251Srrs case AF_INET6: 2901178251Srrs { 2902178251Srrs /* 2903178251Srrs * Only for pure IPv6 Address. (No IPv4 2904178251Srrs * Mapped!) 2905178251Srrs */ 2906178251Srrs struct sockaddr_in6 *sin6; 2907163953Srrs 2908178251Srrs sin6 = (struct sockaddr_in6 *)addr; 2909163953Srrs 2910178251Srrs if (addr->sa_len != sizeof(*sin6)) { 2911171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); 2912163953Srrs return (EINVAL); 2913171943Srrs } 2914178251Srrs lport = sin6->sin6_port; 2915178251Srrs /* 2916185694Srrs * For LOOPBACK the prison_local_ip6() call 2917185694Srrs * will transmute the ipv6 address to the 2918185694Srrs * proper value. 2919178251Srrs */ 2920188590Srrs if (p && (error = prison_local_ip6(p->td_ucred, &sin6->sin6_addr, 2921188590Srrs (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) { 2922188590Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error); 2923188590Srrs return (error); 2924185435Sbz } 2925178251Srrs if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 2926178251Srrs bindall = 0; 2927178251Srrs /* KAME hack: embed scopeid */ 2928197288Srrs if (sa6_embedscope(sin6, MODULE_GLOBAL(ip6_use_defzone)) != 0) { 2929178251Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); 2930178251Srrs return (EINVAL); 2931178251Srrs } 2932178251Srrs } 2933178251Srrs /* this must be cleared for ifa_ifwithaddr() */ 2934178251Srrs sin6->sin6_scope_id = 0; 2935178251Srrs break; 2936163953Srrs } 2937178251Srrs#endif 2938178251Srrs default: 2939171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EAFNOSUPPORT); 2940163953Srrs return (EAFNOSUPPORT); 2941163953Srrs } 2942163953Srrs } 2943175752Srrs SCTP_INP_INFO_WLOCK(); 2944175752Srrs SCTP_INP_WLOCK(inp); 2945169655Srrs /* Setup a vrf_id to be the default for the non-bind-all case. */ 2946167598Srrs vrf_id = inp->def_vrf_id; 2947167598Srrs 2948163953Srrs /* increase our count due to the unlock we do */ 2949163953Srrs SCTP_INP_INCR_REF(inp); 2950163953Srrs if (lport) { 2951163953Srrs /* 2952240263Stuexen * Did the caller specify a port? if so we must see if an ep 2953163953Srrs * already has this one bound. 2954163953Srrs */ 2955163953Srrs /* got to be root to get at low ports */ 2956163953Srrs if (ntohs(lport) < IPPORT_RESERVED) { 2957164085Srrs if (p && (error = 2958170587Srwatson priv_check(p, PRIV_NETINET_RESERVEDPORT) 2959164085Srrs )) { 2960163953Srrs SCTP_INP_DECR_REF(inp); 2961163953Srrs SCTP_INP_WUNLOCK(inp); 2962163953Srrs SCTP_INP_INFO_WUNLOCK(); 2963163953Srrs return (error); 2964163953Srrs } 2965163953Srrs } 2966163953Srrs SCTP_INP_WUNLOCK(inp); 2967167598Srrs if (bindall) { 2968167598Srrs vrf_id = inp->def_vrf_id; 2969167598Srrs inp_tmp = sctp_pcb_findep(addr, 0, 1, vrf_id); 2970167598Srrs if (inp_tmp != NULL) { 2971167598Srrs /* 2972167598Srrs * lock guy returned and lower count note 2973167598Srrs * that we are not bound so inp_tmp should 2974167598Srrs * NEVER be inp. And it is this inp 2975167598Srrs * (inp_tmp) that gets the reference bump, 2976167598Srrs * so we must lower it. 2977167598Srrs */ 2978167598Srrs SCTP_INP_DECR_REF(inp_tmp); 2979181054Srrs /* unlock info */ 2980181054Srrs if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) && 2981181054Srrs (sctp_is_feature_on(inp_tmp, SCTP_PCB_FLAGS_PORTREUSE))) { 2982181054Srrs /* 2983181054Srrs * Ok, must be one-2-one and 2984181054Srrs * allowing port re-use 2985181054Srrs */ 2986181054Srrs port_reuse_active = 1; 2987181054Srrs goto continue_anyway; 2988181054Srrs } 2989167598Srrs SCTP_INP_DECR_REF(inp); 2990167598Srrs SCTP_INP_INFO_WUNLOCK(); 2991171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EADDRINUSE); 2992170091Srrs return (EADDRINUSE); 2993167598Srrs } 2994167598Srrs } else { 2995167598Srrs inp_tmp = sctp_pcb_findep(addr, 0, 1, vrf_id); 2996167598Srrs if (inp_tmp != NULL) { 2997167598Srrs /* 2998167598Srrs * lock guy returned and lower count note 2999167598Srrs * that we are not bound so inp_tmp should 3000167598Srrs * NEVER be inp. And it is this inp 3001167598Srrs * (inp_tmp) that gets the reference bump, 3002167598Srrs * so we must lower it. 3003167598Srrs */ 3004167598Srrs SCTP_INP_DECR_REF(inp_tmp); 3005181054Srrs /* unlock info */ 3006181054Srrs if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) && 3007181054Srrs (sctp_is_feature_on(inp_tmp, SCTP_PCB_FLAGS_PORTREUSE))) { 3008181054Srrs /* 3009181054Srrs * Ok, must be one-2-one and 3010181054Srrs * allowing port re-use 3011181054Srrs */ 3012181054Srrs port_reuse_active = 1; 3013181054Srrs goto continue_anyway; 3014181054Srrs } 3015167598Srrs SCTP_INP_DECR_REF(inp); 3016167598Srrs SCTP_INP_INFO_WUNLOCK(); 3017171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EADDRINUSE); 3018170091Srrs return (EADDRINUSE); 3019167598Srrs } 3020163953Srrs } 3021181054Srrscontinue_anyway: 3022163953Srrs SCTP_INP_WLOCK(inp); 3023163953Srrs if (bindall) { 3024163953Srrs /* verify that no lport is not used by a singleton */ 3025181054Srrs if ((port_reuse_active == 0) && 3026240263Stuexen (inp_tmp = sctp_isport_inuse(inp, lport, vrf_id))) { 3027163953Srrs /* Sorry someone already has this one bound */ 3028181054Srrs if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) && 3029181054Srrs (sctp_is_feature_on(inp_tmp, SCTP_PCB_FLAGS_PORTREUSE))) { 3030181054Srrs port_reuse_active = 1; 3031181054Srrs } else { 3032181054Srrs SCTP_INP_DECR_REF(inp); 3033181054Srrs SCTP_INP_WUNLOCK(inp); 3034181054Srrs SCTP_INP_INFO_WUNLOCK(); 3035181054Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EADDRINUSE); 3036181054Srrs return (EADDRINUSE); 3037181054Srrs } 3038163953Srrs } 3039163953Srrs } 3040163953Srrs } else { 3041170642Srrs uint16_t first, last, candidate; 3042170056Srrs uint16_t count; 3043170056Srrs int done; 3044163953Srrs 3045170056Srrs if (ip_inp->inp_flags & INP_HIGHPORT) { 3046197288Srrs first = MODULE_GLOBAL(ipport_hifirstauto); 3047197288Srrs last = MODULE_GLOBAL(ipport_hilastauto); 3048170056Srrs } else if (ip_inp->inp_flags & INP_LOWPORT) { 3049170056Srrs if (p && (error = 3050170587Srwatson priv_check(p, PRIV_NETINET_RESERVEDPORT) 3051170056Srrs )) { 3052170056Srrs SCTP_INP_DECR_REF(inp); 3053170056Srrs SCTP_INP_WUNLOCK(inp); 3054170056Srrs SCTP_INP_INFO_WUNLOCK(); 3055171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error); 3056170056Srrs return (error); 3057163953Srrs } 3058197288Srrs first = MODULE_GLOBAL(ipport_lowfirstauto); 3059197288Srrs last = MODULE_GLOBAL(ipport_lowlastauto); 3060170056Srrs } else { 3061197288Srrs first = MODULE_GLOBAL(ipport_firstauto); 3062197288Srrs last = MODULE_GLOBAL(ipport_lastauto); 3063170056Srrs } 3064170056Srrs if (first > last) { 3065170056Srrs uint16_t temp; 3066169655Srrs 3067170056Srrs temp = first; 3068170056Srrs first = last; 3069170056Srrs last = temp; 3070170056Srrs } 3071170056Srrs count = last - first + 1; /* number of candidates */ 3072170642Srrs candidate = first + sctp_select_initial_TSN(&inp->sctp_ep) % (count); 3073170056Srrs 3074170056Srrs done = 0; 3075170056Srrs while (!done) { 3076181054Srrs if (sctp_isport_inuse(inp, htons(candidate), inp->def_vrf_id) == NULL) { 3077170056Srrs done = 1; 3078163953Srrs } 3079170056Srrs if (!done) { 3080170056Srrs if (--count == 0) { 3081170056Srrs SCTP_INP_DECR_REF(inp); 3082170056Srrs SCTP_INP_WUNLOCK(inp); 3083170056Srrs SCTP_INP_INFO_WUNLOCK(); 3084171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EADDRINUSE); 3085170091Srrs return (EADDRINUSE); 3086170056Srrs } 3087170642Srrs if (candidate == last) 3088170642Srrs candidate = first; 3089170056Srrs else 3090170642Srrs candidate = candidate + 1; 3091163953Srrs } 3092163953Srrs } 3093170642Srrs lport = htons(candidate); 3094163953Srrs } 3095163953Srrs SCTP_INP_DECR_REF(inp); 3096163953Srrs if (inp->sctp_flags & (SCTP_PCB_FLAGS_SOCKET_GONE | 3097163953Srrs SCTP_PCB_FLAGS_SOCKET_ALLGONE)) { 3098163953Srrs /* 3099163953Srrs * this really should not happen. The guy did a non-blocking 3100163953Srrs * bind and then did a close at the same time. 3101163953Srrs */ 3102163953Srrs SCTP_INP_WUNLOCK(inp); 3103163953Srrs SCTP_INP_INFO_WUNLOCK(); 3104171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); 3105163953Srrs return (EINVAL); 3106163953Srrs } 3107163953Srrs /* ok we look clear to give out this port, so lets setup the binding */ 3108163953Srrs if (bindall) { 3109163953Srrs /* binding to all addresses, so just set in the proper flags */ 3110163953Srrs inp->sctp_flags |= SCTP_PCB_FLAGS_BOUNDALL; 3111163953Srrs /* set the automatic addr changes from kernel flag */ 3112179783Srrs if (SCTP_BASE_SYSCTL(sctp_auto_asconf) == 0) { 3113171943Srrs sctp_feature_off(inp, SCTP_PCB_FLAGS_DO_ASCONF); 3114163953Srrs sctp_feature_off(inp, SCTP_PCB_FLAGS_AUTO_ASCONF); 3115163953Srrs } else { 3116171943Srrs sctp_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF); 3117163953Srrs sctp_feature_on(inp, SCTP_PCB_FLAGS_AUTO_ASCONF); 3118163953Srrs } 3119179783Srrs if (SCTP_BASE_SYSCTL(sctp_multiple_asconfs) == 0) { 3120179157Srrs sctp_feature_off(inp, SCTP_PCB_FLAGS_MULTIPLE_ASCONFS); 3121179157Srrs } else { 3122179157Srrs sctp_feature_on(inp, SCTP_PCB_FLAGS_MULTIPLE_ASCONFS); 3123179157Srrs } 3124171990Srrs /* 3125171990Srrs * set the automatic mobility_base from kernel flag (by 3126171990Srrs * micchie) 3127171990Srrs */ 3128179783Srrs if (SCTP_BASE_SYSCTL(sctp_mobility_base) == 0) { 3129171990Srrs sctp_mobility_feature_off(inp, SCTP_MOBILITY_BASE); 3130172091Srrs sctp_mobility_feature_off(inp, SCTP_MOBILITY_PRIM_DELETED); 3131171990Srrs } else { 3132171990Srrs sctp_mobility_feature_on(inp, SCTP_MOBILITY_BASE); 3133172091Srrs sctp_mobility_feature_off(inp, SCTP_MOBILITY_PRIM_DELETED); 3134171990Srrs } 3135171990Srrs /* 3136171990Srrs * set the automatic mobility_fasthandoff from kernel flag 3137171990Srrs * (by micchie) 3138171990Srrs */ 3139179783Srrs if (SCTP_BASE_SYSCTL(sctp_mobility_fasthandoff) == 0) { 3140171990Srrs sctp_mobility_feature_off(inp, SCTP_MOBILITY_FASTHANDOFF); 3141172091Srrs sctp_mobility_feature_off(inp, SCTP_MOBILITY_PRIM_DELETED); 3142171990Srrs } else { 3143171990Srrs sctp_mobility_feature_on(inp, SCTP_MOBILITY_FASTHANDOFF); 3144172091Srrs sctp_mobility_feature_off(inp, SCTP_MOBILITY_PRIM_DELETED); 3145171990Srrs } 3146163953Srrs } else { 3147163953Srrs /* 3148163953Srrs * bind specific, make sure flags is off and add a new 3149163953Srrs * address structure to the sctp_addr_list inside the ep 3150163953Srrs * structure. 3151163953Srrs * 3152163953Srrs * We will need to allocate one and insert it at the head. The 3153163953Srrs * socketopt call can just insert new addresses in there as 3154163953Srrs * well. It will also have to do the embed scope kame hack 3155163953Srrs * too (before adding). 3156163953Srrs */ 3157167598Srrs struct sctp_ifa *ifa; 3158271746Stuexen union sctp_sockstore store; 3159163953Srrs 3160271746Stuexen memset(&store, 0, sizeof(store)); 3161221249Stuexen switch (addr->sa_family) { 3162238475Stuexen#ifdef INET 3163221249Stuexen case AF_INET: 3164271746Stuexen memcpy(&store.sin, addr, sizeof(struct sockaddr_in)); 3165271746Stuexen store.sin.sin_port = 0; 3166271746Stuexen break; 3167238475Stuexen#endif 3168238475Stuexen#ifdef INET6 3169221249Stuexen case AF_INET6: 3170271746Stuexen memcpy(&store.sin6, addr, sizeof(struct sockaddr_in6)); 3171271746Stuexen store.sin6.sin6_port = 0; 3172271746Stuexen break; 3173238475Stuexen#endif 3174221249Stuexen default: 3175221249Stuexen break; 3176163953Srrs } 3177163953Srrs /* 3178163953Srrs * first find the interface with the bound address need to 3179163953Srrs * zero out the port to find the address! yuck! can't do 3180163953Srrs * this earlier since need port for sctp_pcb_findep() 3181163953Srrs */ 3182240263Stuexen if (sctp_ifap != NULL) { 3183171572Srrs ifa = sctp_ifap; 3184240263Stuexen } else { 3185171572Srrs /* 3186171572Srrs * Note for BSD we hit here always other O/S's will 3187171572Srrs * pass things in via the sctp_ifap argument 3188171572Srrs * (Panda). 3189171572Srrs */ 3190271746Stuexen ifa = sctp_find_ifa_by_addr(&store.sa, 3191172091Srrs vrf_id, SCTP_ADDR_NOT_LOCKED); 3192171572Srrs } 3193163953Srrs if (ifa == NULL) { 3194163953Srrs /* Can't find an interface with that address */ 3195163953Srrs SCTP_INP_WUNLOCK(inp); 3196163953Srrs SCTP_INP_INFO_WUNLOCK(); 3197171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EADDRNOTAVAIL); 3198163953Srrs return (EADDRNOTAVAIL); 3199163953Srrs } 3200221249Stuexen#ifdef INET6 3201163953Srrs if (addr->sa_family == AF_INET6) { 3202167598Srrs /* GAK, more FIXME IFA lock? */ 3203167598Srrs if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) { 3204163953Srrs /* Can't bind a non-existent addr. */ 3205163953Srrs SCTP_INP_WUNLOCK(inp); 3206163953Srrs SCTP_INP_INFO_WUNLOCK(); 3207171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); 3208163953Srrs return (EINVAL); 3209163953Srrs } 3210163953Srrs } 3211221249Stuexen#endif 3212163953Srrs /* we're not bound all */ 3213163953Srrs inp->sctp_flags &= ~SCTP_PCB_FLAGS_BOUNDALL; 3214169655Srrs /* allow bindx() to send ASCONF's for binding changes */ 3215169655Srrs sctp_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF); 3216170744Srrs /* clear automatic addr changes from kernel flag */ 3217170744Srrs sctp_feature_off(inp, SCTP_PCB_FLAGS_AUTO_ASCONF); 3218167598Srrs 3219163953Srrs /* add this address to the endpoint list */ 3220167598Srrs error = sctp_insert_laddr(&inp->sctp_addr_list, ifa, 0); 3221163953Srrs if (error != 0) { 3222163953Srrs SCTP_INP_WUNLOCK(inp); 3223163953Srrs SCTP_INP_INFO_WUNLOCK(); 3224163953Srrs return (error); 3225163953Srrs } 3226163953Srrs inp->laddr_count++; 3227163953Srrs } 3228163953Srrs /* find the bucket */ 3229181054Srrs if (port_reuse_active) { 3230181054Srrs /* Put it into tcp 1-2-1 hash */ 3231215039Stuexen head = &SCTP_BASE_INFO(sctp_tcpephash)[SCTP_PCBHASH_ALLADDR(lport, SCTP_BASE_INFO(hashtcpmark))]; 3232181054Srrs inp->sctp_flags |= SCTP_PCB_FLAGS_IN_TCPPOOL; 3233181054Srrs } else { 3234215039Stuexen head = &SCTP_BASE_INFO(sctp_ephash)[SCTP_PCBHASH_ALLADDR(lport, SCTP_BASE_INFO(hashmark))]; 3235181054Srrs } 3236163953Srrs /* put it in the bucket */ 3237163953Srrs LIST_INSERT_HEAD(head, inp, sctp_hash); 3238181054Srrs SCTPDBG(SCTP_DEBUG_PCB1, "Main hash to bind at head:%p, bound port:%d - in tcp_pool=%d\n", 3239240148Stuexen (void *)head, ntohs(lport), port_reuse_active); 3240163953Srrs /* set in the port */ 3241163953Srrs inp->sctp_lport = lport; 3242163953Srrs 3243163953Srrs /* turn off just the unbound flag */ 3244163953Srrs inp->sctp_flags &= ~SCTP_PCB_FLAGS_UNBOUND; 3245163953Srrs SCTP_INP_WUNLOCK(inp); 3246163953Srrs SCTP_INP_INFO_WUNLOCK(); 3247163953Srrs return (0); 3248163953Srrs} 3249163953Srrs 3250163953Srrs 3251163953Srrsstatic void 3252208160Srrssctp_iterator_inp_being_freed(struct sctp_inpcb *inp) 3253163953Srrs{ 3254208160Srrs struct sctp_iterator *it, *nit; 3255163953Srrs 3256163953Srrs /* 3257163953Srrs * We enter with the only the ITERATOR_LOCK in place and a write 3258163953Srrs * lock on the inp_info stuff. 3259163953Srrs */ 3260208160Srrs it = sctp_it_ctl.cur_it; 3261208160Srrs if (it && (it->vn != curvnet)) { 3262208160Srrs /* Its not looking at our VNET */ 3263208160Srrs return; 3264208160Srrs } 3265208160Srrs if (it && (it->inp == inp)) { 3266208160Srrs /* 3267208160Srrs * This is tricky and we hold the iterator lock, but when it 3268208160Srrs * returns and gets the lock (when we release it) the 3269208160Srrs * iterator will try to operate on inp. We need to stop that 3270208160Srrs * from happening. But of course the iterator has a 3271208160Srrs * reference on the stcb and inp. We can mark it and it will 3272208160Srrs * stop. 3273208160Srrs * 3274208160Srrs * If its a single iterator situation, we set the end iterator 3275208160Srrs * flag. Otherwise we set the iterator to go to the next 3276208160Srrs * inp. 3277208160Srrs * 3278208160Srrs */ 3279208160Srrs if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) { 3280208160Srrs sctp_it_ctl.iterator_flags |= SCTP_ITERATOR_STOP_CUR_IT; 3281208160Srrs } else { 3282208160Srrs sctp_it_ctl.iterator_flags |= SCTP_ITERATOR_STOP_CUR_INP; 3283208160Srrs } 3284208160Srrs } 3285163953Srrs /* 3286208160Srrs * Now go through and remove any single reference to our inp that 3287208160Srrs * may be still pending on the list 3288163953Srrs */ 3289208160Srrs SCTP_IPI_ITERATOR_WQ_LOCK(); 3290216822Stuexen TAILQ_FOREACH_SAFE(it, &sctp_it_ctl.iteratorhead, sctp_nxt_itr, nit) { 3291208160Srrs if (it->vn != curvnet) { 3292163953Srrs continue; 3293208160Srrs } 3294163953Srrs if (it->inp == inp) { 3295208160Srrs /* This one points to me is it inp specific? */ 3296163953Srrs if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) { 3297208160Srrs /* Remove and free this one */ 3298208160Srrs TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, 3299208160Srrs it, sctp_nxt_itr); 3300208160Srrs if (it->function_atend != NULL) { 3301208160Srrs (*it->function_atend) (it->pointer, it->val); 3302208160Srrs } 3303208160Srrs SCTP_FREE(it, SCTP_M_ITER); 3304163953Srrs } else { 3305208160Srrs it->inp = LIST_NEXT(it->inp, sctp_list); 3306209178Stuexen if (it->inp) { 3307209178Stuexen SCTP_INP_INCR_REF(it->inp); 3308209178Stuexen } 3309163953Srrs } 3310209029Srrs /* 3311209029Srrs * When its put in the refcnt is incremented so decr 3312209029Srrs * it 3313209029Srrs */ 3314209029Srrs SCTP_INP_DECR_REF(inp); 3315163953Srrs } 3316163953Srrs } 3317208160Srrs SCTP_IPI_ITERATOR_WQ_UNLOCK(); 3318163953Srrs} 3319163953Srrs 3320163953Srrs/* release sctp_inpcb unbind the port */ 3321163953Srrsvoid 3322163953Srrssctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) 3323163953Srrs{ 3324163953Srrs /* 3325163953Srrs * Here we free a endpoint. We must find it (if it is in the Hash 3326163953Srrs * table) and remove it from there. Then we must also find it in the 3327163953Srrs * overall list and remove it from there. After all removals are 3328163953Srrs * complete then any timer has to be stopped. Then start the actual 3329163953Srrs * freeing. a) Any local lists. b) Any associations. c) The hash of 3330163953Srrs * all associations. d) finally the ep itself. 3331163953Srrs */ 3332163953Srrs struct sctp_tcb *asoc, *nasoc; 3333163953Srrs struct sctp_laddr *laddr, *nladdr; 3334163953Srrs struct inpcb *ip_pcb; 3335163953Srrs struct socket *so; 3336208879Srrs int being_refed = 0; 3337216822Stuexen struct sctp_queued_to_read *sq, *nsq; 3338166086Srrs int cnt; 3339216822Stuexen sctp_sharedkey_t *shared_key, *nshared_key; 3340163953Srrs 3341163953Srrs 3342163953Srrs#ifdef SCTP_LOG_CLOSING 3343163953Srrs sctp_log_closing(inp, NULL, 0); 3344163953Srrs#endif 3345209178Stuexen SCTP_ITERATOR_LOCK(); 3346209178Stuexen /* mark any iterators on the list or being processed */ 3347209178Stuexen sctp_iterator_inp_being_freed(inp); 3348209178Stuexen SCTP_ITERATOR_UNLOCK(); 3349163953Srrs so = inp->sctp_socket; 3350163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) { 3351163953Srrs /* been here before.. eeks.. get out of here */ 3352170091Srrs SCTP_PRINTF("This conflict in free SHOULD not be happening! from %d, imm %d\n", from, immediate); 3353163953Srrs#ifdef SCTP_LOG_CLOSING 3354163953Srrs sctp_log_closing(inp, NULL, 1); 3355163953Srrs#endif 3356163953Srrs return; 3357163953Srrs } 3358163953Srrs SCTP_ASOC_CREATE_LOCK(inp); 3359163953Srrs SCTP_INP_INFO_WLOCK(); 3360163953Srrs 3361163953Srrs SCTP_INP_WLOCK(inp); 3362208953Srrs if (from == SCTP_CALLED_AFTER_CMPSET_OFCLOSE) { 3363208953Srrs inp->sctp_flags &= ~SCTP_PCB_FLAGS_CLOSE_IP; 3364208953Srrs /* socket is gone, so no more wakeups allowed */ 3365208953Srrs inp->sctp_flags |= SCTP_PCB_FLAGS_DONT_WAKE; 3366208953Srrs inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEINPUT; 3367208953Srrs inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEOUTPUT; 3368208953Srrs 3369208953Srrs } 3370169420Srrs /* First time through we have the socket lock, after that no more. */ 3371165220Srrs sctp_timer_stop(SCTP_TIMER_TYPE_NEWCOOKIE, inp, NULL, NULL, 3372165220Srrs SCTP_FROM_SCTP_PCB + SCTP_LOC_1); 3373163953Srrs 3374163953Srrs if (inp->control) { 3375163953Srrs sctp_m_freem(inp->control); 3376163953Srrs inp->control = NULL; 3377163953Srrs } 3378163953Srrs if (inp->pkt) { 3379163953Srrs sctp_m_freem(inp->pkt); 3380163953Srrs inp->pkt = NULL; 3381163953Srrs } 3382163953Srrs ip_pcb = &inp->ip_inp.inp; /* we could just cast the main pointer 3383163953Srrs * here but I will be nice :> (i.e. 3384163953Srrs * ip_pcb = ep;) */ 3385169380Srrs if (immediate == SCTP_FREE_SHOULD_USE_GRACEFUL_CLOSE) { 3386163953Srrs int cnt_in_sd; 3387163953Srrs 3388163953Srrs cnt_in_sd = 0; 3389216822Stuexen LIST_FOREACH_SAFE(asoc, &inp->sctp_asoc_list, sctp_tcblist, nasoc) { 3390172090Srrs SCTP_TCB_LOCK(asoc); 3391163953Srrs if (asoc->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { 3392163953Srrs /* Skip guys being freed */ 3393163953Srrs cnt_in_sd++; 3394208852Srrs if (asoc->asoc.state & SCTP_STATE_IN_ACCEPT_QUEUE) { 3395208852Srrs /* 3396208852Srrs * Special case - we did not start a 3397208852Srrs * kill timer on the asoc due to it 3398208852Srrs * was not closed. So go ahead and 3399208852Srrs * start it now. 3400208852Srrs */ 3401208852Srrs asoc->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE; 3402208852Srrs sctp_timer_start(SCTP_TIMER_TYPE_ASOCKILL, inp, asoc, NULL); 3403208852Srrs } 3404171943Srrs SCTP_TCB_UNLOCK(asoc); 3405163953Srrs continue; 3406163953Srrs } 3407190689Srrs if (((SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_COOKIE_WAIT) || 3408190689Srrs (SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_COOKIE_ECHOED)) && 3409190689Srrs (asoc->asoc.total_output_queue_size == 0)) { 3410170894Srrs /* 3411170894Srrs * If we have data in queue, we don't want 3412170894Srrs * to just free since the app may have done, 3413170894Srrs * send()/close or connect/send/close. And 3414170894Srrs * it wants the data to get across first. 3415170894Srrs */ 3416171990Srrs /* Just abandon things in the front states */ 3417171990Srrs if (sctp_free_assoc(inp, asoc, SCTP_PCBFREE_NOFORCE, 3418171990Srrs SCTP_FROM_SCTP_PCB + SCTP_LOC_2) == 0) { 3419171990Srrs cnt_in_sd++; 3420170894Srrs } 3421171990Srrs continue; 3422163953Srrs } 3423163953Srrs /* Disconnect the socket please */ 3424163953Srrs asoc->sctp_socket = NULL; 3425163953Srrs asoc->asoc.state |= SCTP_STATE_CLOSED_SOCKET; 3426163953Srrs if ((asoc->asoc.size_on_reasm_queue > 0) || 3427163953Srrs (asoc->asoc.control_pdapi) || 3428163953Srrs (asoc->asoc.size_on_all_streams > 0) || 3429228907Stuexen (so && (so->so_rcv.sb_cc > 0))) { 3430163953Srrs /* Left with Data unread */ 3431163953Srrs struct mbuf *op_err; 3432163953Srrs 3433267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, ""); 3434165220Srrs asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB + SCTP_LOC_3; 3435172090Srrs sctp_send_abort_tcb(asoc, op_err, SCTP_SO_LOCKED); 3436163953Srrs SCTP_STAT_INCR_COUNTER32(sctps_aborted); 3437163953Srrs if ((SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_OPEN) || 3438163953Srrs (SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { 3439163953Srrs SCTP_STAT_DECR_GAUGE32(sctps_currestab); 3440163953Srrs } 3441171943Srrs if (sctp_free_assoc(inp, asoc, 3442171943Srrs SCTP_PCBFREE_NOFORCE, SCTP_FROM_SCTP_PCB + SCTP_LOC_4) == 0) { 3443171943Srrs cnt_in_sd++; 3444171943Srrs } 3445163953Srrs continue; 3446163953Srrs } else if (TAILQ_EMPTY(&asoc->asoc.send_queue) && 3447163953Srrs TAILQ_EMPTY(&asoc->asoc.sent_queue) && 3448240849Stuexen (asoc->asoc.stream_queue_cnt == 0)) { 3449163953Srrs if (asoc->asoc.locked_on_sending) { 3450163953Srrs goto abort_anyway; 3451163953Srrs } 3452163953Srrs if ((SCTP_GET_STATE(&asoc->asoc) != SCTP_STATE_SHUTDOWN_SENT) && 3453163953Srrs (SCTP_GET_STATE(&asoc->asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) { 3454224641Stuexen struct sctp_nets *netp; 3455224641Stuexen 3456163953Srrs /* 3457163953Srrs * there is nothing queued to send, 3458163953Srrs * so I send shutdown 3459163953Srrs */ 3460166675Srrs if ((SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_OPEN) || 3461166675Srrs (SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { 3462166675Srrs SCTP_STAT_DECR_GAUGE32(sctps_currestab); 3463166675Srrs } 3464171943Srrs SCTP_SET_STATE(&asoc->asoc, SCTP_STATE_SHUTDOWN_SENT); 3465172703Srrs SCTP_CLEAR_SUBSTATE(&asoc->asoc, SCTP_STATE_SHUTDOWN_PENDING); 3466246588Stuexen sctp_stop_timers_for_shutdown(asoc); 3467246588Stuexen if (asoc->asoc.alternate) { 3468246588Stuexen netp = asoc->asoc.alternate; 3469246588Stuexen } else { 3470246588Stuexen netp = asoc->asoc.primary_destination; 3471246588Stuexen } 3472246588Stuexen sctp_send_shutdown(asoc, netp); 3473163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, asoc->sctp_ep, asoc, 3474224641Stuexen netp); 3475163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, asoc->sctp_ep, asoc, 3476163953Srrs asoc->asoc.primary_destination); 3477172090Srrs sctp_chunk_output(inp, asoc, SCTP_OUTPUT_FROM_SHUT_TMR, SCTP_SO_LOCKED); 3478163953Srrs } 3479163953Srrs } else { 3480163953Srrs /* mark into shutdown pending */ 3481163953Srrs struct sctp_stream_queue_pending *sp; 3482163953Srrs 3483163953Srrs asoc->asoc.state |= SCTP_STATE_SHUTDOWN_PENDING; 3484163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, asoc->sctp_ep, asoc, 3485163953Srrs asoc->asoc.primary_destination); 3486163953Srrs if (asoc->asoc.locked_on_sending) { 3487163953Srrs sp = TAILQ_LAST(&((asoc->asoc.locked_on_sending)->outqueue), 3488163953Srrs sctp_streamhead); 3489163953Srrs if (sp == NULL) { 3490169420Srrs SCTP_PRINTF("Error, sp is NULL, locked on sending is %p strm:%d\n", 3491240148Stuexen (void *)asoc->asoc.locked_on_sending, 3492163953Srrs asoc->asoc.locked_on_sending->stream_no); 3493163953Srrs } else { 3494163953Srrs if ((sp->length == 0) && (sp->msg_is_complete == 0)) 3495163953Srrs asoc->asoc.state |= SCTP_STATE_PARTIAL_MSG_LEFT; 3496163953Srrs } 3497163953Srrs } 3498163953Srrs if (TAILQ_EMPTY(&asoc->asoc.send_queue) && 3499163953Srrs TAILQ_EMPTY(&asoc->asoc.sent_queue) && 3500163953Srrs (asoc->asoc.state & SCTP_STATE_PARTIAL_MSG_LEFT)) { 3501163953Srrs struct mbuf *op_err; 3502163953Srrs 3503163953Srrs abort_anyway: 3504267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, ""); 3505165220Srrs asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB + SCTP_LOC_5; 3506172090Srrs sctp_send_abort_tcb(asoc, op_err, SCTP_SO_LOCKED); 3507163953Srrs SCTP_STAT_INCR_COUNTER32(sctps_aborted); 3508163953Srrs if ((SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_OPEN) || 3509163953Srrs (SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { 3510163953Srrs SCTP_STAT_DECR_GAUGE32(sctps_currestab); 3511163953Srrs } 3512171943Srrs if (sctp_free_assoc(inp, asoc, 3513171943Srrs SCTP_PCBFREE_NOFORCE, 3514171943Srrs SCTP_FROM_SCTP_PCB + SCTP_LOC_6) == 0) { 3515171943Srrs cnt_in_sd++; 3516171943Srrs } 3517163953Srrs continue; 3518171990Srrs } else { 3519172090Srrs sctp_chunk_output(inp, asoc, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED); 3520163953Srrs } 3521163953Srrs } 3522163953Srrs cnt_in_sd++; 3523163953Srrs SCTP_TCB_UNLOCK(asoc); 3524163953Srrs } 3525163953Srrs /* now is there some left in our SHUTDOWN state? */ 3526163953Srrs if (cnt_in_sd) { 3527163953Srrs#ifdef SCTP_LOG_CLOSING 3528163953Srrs sctp_log_closing(inp, NULL, 2); 3529163953Srrs#endif 3530182268Srrs inp->sctp_socket = NULL; 3531208953Srrs SCTP_INP_WUNLOCK(inp); 3532208953Srrs SCTP_ASOC_CREATE_UNLOCK(inp); 3533208953Srrs SCTP_INP_INFO_WUNLOCK(); 3534163953Srrs return; 3535163953Srrs } 3536163953Srrs } 3537163953Srrs inp->sctp_socket = NULL; 3538163953Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) != 3539163953Srrs SCTP_PCB_FLAGS_UNBOUND) { 3540163953Srrs /* 3541163953Srrs * ok, this guy has been bound. It's port is somewhere in 3542179783Srrs * the SCTP_BASE_INFO(hash table). Remove it! 3543163953Srrs */ 3544163953Srrs LIST_REMOVE(inp, sctp_hash); 3545163953Srrs inp->sctp_flags |= SCTP_PCB_FLAGS_UNBOUND; 3546163953Srrs } 3547163953Srrs /* 3548163953Srrs * If there is a timer running to kill us, forget it, since it may 3549163953Srrs * have a contest on the INP lock.. which would cause us to die ... 3550163953Srrs */ 3551163953Srrs cnt = 0; 3552216822Stuexen LIST_FOREACH_SAFE(asoc, &inp->sctp_asoc_list, sctp_tcblist, nasoc) { 3553215241Stuexen SCTP_TCB_LOCK(asoc); 3554163953Srrs if (asoc->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { 3555208875Srrs if (asoc->asoc.state & SCTP_STATE_IN_ACCEPT_QUEUE) { 3556208875Srrs asoc->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE; 3557208875Srrs sctp_timer_start(SCTP_TIMER_TYPE_ASOCKILL, inp, asoc, NULL); 3558208875Srrs } 3559163953Srrs cnt++; 3560215241Stuexen SCTP_TCB_UNLOCK(asoc); 3561163953Srrs continue; 3562163953Srrs } 3563163953Srrs /* Free associations that are NOT killing us */ 3564163953Srrs if ((SCTP_GET_STATE(&asoc->asoc) != SCTP_STATE_COOKIE_WAIT) && 3565163953Srrs ((asoc->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) == 0)) { 3566163953Srrs struct mbuf *op_err; 3567163953Srrs 3568267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, ""); 3569165220Srrs asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB + SCTP_LOC_7; 3570172090Srrs sctp_send_abort_tcb(asoc, op_err, SCTP_SO_LOCKED); 3571163953Srrs SCTP_STAT_INCR_COUNTER32(sctps_aborted); 3572163953Srrs } else if (asoc->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { 3573163953Srrs cnt++; 3574163953Srrs SCTP_TCB_UNLOCK(asoc); 3575163953Srrs continue; 3576163953Srrs } 3577163953Srrs if ((SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_OPEN) || 3578163953Srrs (SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { 3579163953Srrs SCTP_STAT_DECR_GAUGE32(sctps_currestab); 3580163953Srrs } 3581283822Stuexen if (sctp_free_assoc(inp, asoc, SCTP_PCBFREE_FORCE, 3582283822Stuexen SCTP_FROM_SCTP_PCB + SCTP_LOC_8) == 0) { 3583171943Srrs cnt++; 3584171943Srrs } 3585163953Srrs } 3586163953Srrs if (cnt) { 3587163953Srrs /* Ok we have someone out there that will kill us */ 3588169378Srrs (void)SCTP_OS_TIMER_STOP(&inp->sctp_ep.signature_change.timer); 3589208953Srrs#ifdef SCTP_LOG_CLOSING 3590208953Srrs sctp_log_closing(inp, NULL, 3); 3591208953Srrs#endif 3592163953Srrs SCTP_INP_WUNLOCK(inp); 3593163953Srrs SCTP_ASOC_CREATE_UNLOCK(inp); 3594163953Srrs SCTP_INP_INFO_WUNLOCK(); 3595163953Srrs return; 3596163953Srrs } 3597208879Srrs if (SCTP_INP_LOCK_CONTENDED(inp)) 3598208879Srrs being_refed++; 3599208879Srrs if (SCTP_INP_READ_CONTENDED(inp)) 3600208879Srrs being_refed++; 3601208879Srrs if (SCTP_ASOC_CREATE_LOCK_CONTENDED(inp)) 3602208879Srrs being_refed++; 3603208879Srrs 3604208878Srrs if ((inp->refcount) || 3605208879Srrs (being_refed) || 3606208879Srrs (inp->sctp_flags & SCTP_PCB_FLAGS_CLOSE_IP)) { 3607169378Srrs (void)SCTP_OS_TIMER_STOP(&inp->sctp_ep.signature_change.timer); 3608208953Srrs#ifdef SCTP_LOG_CLOSING 3609208953Srrs sctp_log_closing(inp, NULL, 4); 3610208953Srrs#endif 3611163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_INPKILL, inp, NULL, NULL); 3612163953Srrs SCTP_INP_WUNLOCK(inp); 3613163953Srrs SCTP_ASOC_CREATE_UNLOCK(inp); 3614163953Srrs SCTP_INP_INFO_WUNLOCK(); 3615163953Srrs return; 3616163953Srrs } 3617163953Srrs inp->sctp_ep.signature_change.type = 0; 3618163953Srrs inp->sctp_flags |= SCTP_PCB_FLAGS_SOCKET_ALLGONE; 3619208953Srrs /* 3620208953Srrs * Remove it from the list .. last thing we need a lock for. 3621208953Srrs */ 3622208953Srrs LIST_REMOVE(inp, sctp_list); 3623208953Srrs SCTP_INP_WUNLOCK(inp); 3624208953Srrs SCTP_ASOC_CREATE_UNLOCK(inp); 3625208953Srrs SCTP_INP_INFO_WUNLOCK(); 3626208953Srrs /* 3627208953Srrs * Now we release all locks. Since this INP cannot be found anymore 3628215034Sbrucec * except possibly by the kill timer that might be running. We call 3629208953Srrs * the drain function here. It should hit the case were it sees the 3630208953Srrs * ACTIVE flag cleared and exit out freeing us to proceed and 3631208953Srrs * destroy everything. 3632208953Srrs */ 3633208953Srrs if (from != SCTP_CALLED_FROM_INPKILL_TIMER) { 3634208953Srrs (void)SCTP_OS_TIMER_STOP_DRAIN(&inp->sctp_ep.signature_change.timer); 3635208953Srrs } else { 3636208953Srrs /* Probably un-needed */ 3637208953Srrs (void)SCTP_OS_TIMER_STOP(&inp->sctp_ep.signature_change.timer); 3638208953Srrs } 3639163953Srrs 3640163953Srrs#ifdef SCTP_LOG_CLOSING 3641163953Srrs sctp_log_closing(inp, NULL, 5); 3642163953Srrs#endif 3643163953Srrs 3644208953Srrs 3645185694Srrs if ((inp->sctp_asocidhash) != NULL) { 3646185694Srrs SCTP_HASH_FREE(inp->sctp_asocidhash, inp->hashasocidmark); 3647185694Srrs inp->sctp_asocidhash = NULL; 3648185694Srrs } 3649169655Srrs /* sa_ignore FREED_MEMORY */ 3650216822Stuexen TAILQ_FOREACH_SAFE(sq, &inp->read_queue, next, nsq) { 3651168859Srrs /* Its only abandoned if it had data left */ 3652168859Srrs if (sq->length) 3653168859Srrs SCTP_STAT_INCR(sctps_left_abandon); 3654168859Srrs 3655163953Srrs TAILQ_REMOVE(&inp->read_queue, sq, next); 3656163953Srrs sctp_free_remote_addr(sq->whoFrom); 3657163953Srrs if (so) 3658163953Srrs so->so_rcv.sb_cc -= sq->length; 3659163953Srrs if (sq->data) { 3660163953Srrs sctp_m_freem(sq->data); 3661163953Srrs sq->data = NULL; 3662163953Srrs } 3663163953Srrs /* 3664163953Srrs * no need to free the net count, since at this point all 3665163953Srrs * assoc's are gone. 3666163953Srrs */ 3667179783Srrs SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), sq); 3668163953Srrs SCTP_DECR_READQ_COUNT(); 3669163953Srrs } 3670163953Srrs /* Now the sctp_pcb things */ 3671163953Srrs /* 3672163953Srrs * free each asoc if it is not already closed/free. we can't use the 3673163953Srrs * macro here since le_next will get freed as part of the 3674163953Srrs * sctp_free_assoc() call. 3675163953Srrs */ 3676171167Sgnn#ifdef IPSEC 3677294187Stuexen ipsec_delete_pcbpolicy(ip_pcb); 3678294187Stuexen#endif 3679163953Srrs if (ip_pcb->inp_options) { 3680163953Srrs (void)sctp_m_free(ip_pcb->inp_options); 3681163953Srrs ip_pcb->inp_options = 0; 3682163953Srrs } 3683163953Srrs#ifdef INET6 3684163953Srrs if (ip_pcb->inp_vflag & INP_IPV6) { 3685163953Srrs struct in6pcb *in6p; 3686163953Srrs 3687163953Srrs in6p = (struct in6pcb *)inp; 3688163953Srrs ip6_freepcbopts(in6p->in6p_outputopts); 3689163953Srrs } 3690163953Srrs#endif /* INET6 */ 3691163953Srrs ip_pcb->inp_vflag = 0; 3692163953Srrs /* free up authentication fields */ 3693163953Srrs if (inp->sctp_ep.local_auth_chunks != NULL) 3694163953Srrs sctp_free_chunklist(inp->sctp_ep.local_auth_chunks); 3695163953Srrs if (inp->sctp_ep.local_hmacs != NULL) 3696163953Srrs sctp_free_hmaclist(inp->sctp_ep.local_hmacs); 3697163953Srrs 3698216822Stuexen LIST_FOREACH_SAFE(shared_key, &inp->sctp_ep.shared_keys, next, nshared_key) { 3699163953Srrs LIST_REMOVE(shared_key, next); 3700163953Srrs sctp_free_sharedkey(shared_key); 3701169655Srrs /* sa_ignore FREED_MEMORY */ 3702163953Srrs } 3703163953Srrs 3704163953Srrs /* 3705163953Srrs * if we have an address list the following will free the list of 3706163953Srrs * ifaddr's that are set into this ep. Again macro limitations here, 3707163953Srrs * since the LIST_FOREACH could be a bad idea. 3708163953Srrs */ 3709216822Stuexen LIST_FOREACH_SAFE(laddr, &inp->sctp_addr_list, sctp_nxt_addr, nladdr) { 3710167598Srrs sctp_remove_laddr(laddr); 3711163953Srrs } 3712165220Srrs 3713165220Srrs#ifdef SCTP_TRACK_FREED_ASOCS 3714165220Srrs /* TEMP CODE */ 3715216822Stuexen LIST_FOREACH_SAFE(asoc, &inp->sctp_asoc_free_list, sctp_tcblist, nasoc) { 3716165220Srrs LIST_REMOVE(asoc, sctp_tcblist); 3717179783Srrs SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asoc), asoc); 3718165220Srrs SCTP_DECR_ASOC_COUNT(); 3719165220Srrs } 3720165220Srrs /* *** END TEMP CODE *** */ 3721165220Srrs#endif 3722163953Srrs /* Now lets see about freeing the EP hash table. */ 3723163953Srrs if (inp->sctp_tcbhash != NULL) { 3724166023Srrs SCTP_HASH_FREE(inp->sctp_tcbhash, inp->sctp_hashmark); 3725166023Srrs inp->sctp_tcbhash = NULL; 3726163953Srrs } 3727163953Srrs /* Now we must put the ep memory back into the zone pool */ 3728267769Stuexen crfree(inp->ip_inp.inp.inp_cred); 3729170786Srrs INP_LOCK_DESTROY(&inp->ip_inp.inp); 3730163953Srrs SCTP_INP_LOCK_DESTROY(inp); 3731163953Srrs SCTP_INP_READ_DESTROY(inp); 3732163953Srrs SCTP_ASOC_CREATE_LOCK_DESTROY(inp); 3733179783Srrs SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp); 3734163953Srrs SCTP_DECR_EP_COUNT(); 3735163953Srrs} 3736163953Srrs 3737163953Srrs 3738163953Srrsstruct sctp_nets * 3739163953Srrssctp_findnet(struct sctp_tcb *stcb, struct sockaddr *addr) 3740163953Srrs{ 3741163953Srrs struct sctp_nets *net; 3742163953Srrs 3743163953Srrs /* locate the address */ 3744163953Srrs TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 3745163953Srrs if (sctp_cmpaddr(addr, (struct sockaddr *)&net->ro._l_addr)) 3746163953Srrs return (net); 3747163953Srrs } 3748163953Srrs return (NULL); 3749163953Srrs} 3750163953Srrs 3751163953Srrs 3752163953Srrsint 3753167598Srrssctp_is_address_on_local_host(struct sockaddr *addr, uint32_t vrf_id) 3754163953Srrs{ 3755167598Srrs struct sctp_ifa *sctp_ifa; 3756163953Srrs 3757172091Srrs sctp_ifa = sctp_find_ifa_by_addr(addr, vrf_id, SCTP_ADDR_NOT_LOCKED); 3758167598Srrs if (sctp_ifa) { 3759167598Srrs return (1); 3760167598Srrs } else { 3761167598Srrs return (0); 3762167598Srrs } 3763167598Srrs} 3764163953Srrs 3765169420Srrs/* 3766169420Srrs * add's a remote endpoint address, done with the INIT/INIT-ACK as well as 3767169420Srrs * when a ASCONF arrives that adds it. It will also initialize all the cwnd 3768169420Srrs * stats of stuff. 3769169420Srrs */ 3770163953Srrsint 3771163953Srrssctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr, 3772224641Stuexen struct sctp_nets **netp, int set_scope, int from) 3773163953Srrs{ 3774163953Srrs /* 3775163953Srrs * The following is redundant to the same lines in the 3776215039Stuexen * sctp_aloc_assoc() but is needed since others call the add address 3777215039Stuexen * function 3778163953Srrs */ 3779163953Srrs struct sctp_nets *net, *netfirst; 3780163953Srrs int addr_inscope; 3781163953Srrs 3782169420Srrs SCTPDBG(SCTP_DEBUG_PCB1, "Adding an address (from:%d) to the peer: ", 3783169420Srrs from); 3784169420Srrs SCTPDBG_ADDR(SCTP_DEBUG_PCB1, newaddr); 3785163953Srrs 3786163953Srrs netfirst = sctp_findnet(stcb, newaddr); 3787163953Srrs if (netfirst) { 3788163953Srrs /* 3789163953Srrs * Lie and return ok, we don't want to make the association 3790163953Srrs * go away for this behavior. It will happen in the TCP 3791163953Srrs * model in a connected socket. It does not reach the hash 3792163953Srrs * table until after the association is built so it can't be 3793163953Srrs * found. Mark as reachable, since the initial creation will 3794163953Srrs * have been cleared and the NOT_IN_ASSOC flag will have 3795163953Srrs * been added... and we don't want to end up removing it 3796163953Srrs * back out. 3797163953Srrs */ 3798163953Srrs if (netfirst->dest_state & SCTP_ADDR_UNCONFIRMED) { 3799163953Srrs netfirst->dest_state = (SCTP_ADDR_REACHABLE | 3800163953Srrs SCTP_ADDR_UNCONFIRMED); 3801163953Srrs } else { 3802163953Srrs netfirst->dest_state = SCTP_ADDR_REACHABLE; 3803163953Srrs } 3804163953Srrs 3805163953Srrs return (0); 3806163953Srrs } 3807163953Srrs addr_inscope = 1; 3808221249Stuexen switch (newaddr->sa_family) { 3809221249Stuexen#ifdef INET 3810221249Stuexen case AF_INET: 3811221249Stuexen { 3812221249Stuexen struct sockaddr_in *sin; 3813163953Srrs 3814221249Stuexen sin = (struct sockaddr_in *)newaddr; 3815221249Stuexen if (sin->sin_addr.s_addr == 0) { 3816221249Stuexen /* Invalid address */ 3817221249Stuexen return (-1); 3818221249Stuexen } 3819221249Stuexen /* zero out the bzero area */ 3820221249Stuexen memset(&sin->sin_zero, 0, sizeof(sin->sin_zero)); 3821163953Srrs 3822221249Stuexen /* assure len is set */ 3823221249Stuexen sin->sin_len = sizeof(struct sockaddr_in); 3824221249Stuexen if (set_scope) { 3825221249Stuexen if (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) { 3826246595Stuexen stcb->asoc.scope.ipv4_local_scope = 1; 3827221249Stuexen } 3828221249Stuexen } else { 3829221249Stuexen /* Validate the address is in scope */ 3830221249Stuexen if ((IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) && 3831246595Stuexen (stcb->asoc.scope.ipv4_local_scope == 0)) { 3832221249Stuexen addr_inscope = 0; 3833221249Stuexen } 3834163953Srrs } 3835221249Stuexen break; 3836163953Srrs } 3837221249Stuexen#endif 3838179157Srrs#ifdef INET6 3839221249Stuexen case AF_INET6: 3840221249Stuexen { 3841221249Stuexen struct sockaddr_in6 *sin6; 3842163953Srrs 3843221249Stuexen sin6 = (struct sockaddr_in6 *)newaddr; 3844221249Stuexen if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 3845221249Stuexen /* Invalid address */ 3846221249Stuexen return (-1); 3847163953Srrs } 3848221249Stuexen /* assure len is set */ 3849221249Stuexen sin6->sin6_len = sizeof(struct sockaddr_in6); 3850221249Stuexen if (set_scope) { 3851221249Stuexen if (sctp_is_address_on_local_host(newaddr, stcb->asoc.vrf_id)) { 3852246595Stuexen stcb->asoc.scope.loopback_scope = 1; 3853246595Stuexen stcb->asoc.scope.local_scope = 0; 3854246595Stuexen stcb->asoc.scope.ipv4_local_scope = 1; 3855246595Stuexen stcb->asoc.scope.site_scope = 1; 3856221249Stuexen } else if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 3857221249Stuexen /* 3858221249Stuexen * If the new destination is a 3859221249Stuexen * LINK_LOCAL we must have common 3860221249Stuexen * site scope. Don't set the local 3861221249Stuexen * scope since we may not share all 3862221249Stuexen * links, only loopback can do this. 3863221249Stuexen * Links on the local network would 3864221249Stuexen * also be on our private network 3865221249Stuexen * for v4 too. 3866221249Stuexen */ 3867246595Stuexen stcb->asoc.scope.ipv4_local_scope = 1; 3868246595Stuexen stcb->asoc.scope.site_scope = 1; 3869221249Stuexen } else if (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) { 3870221249Stuexen /* 3871221249Stuexen * If the new destination is 3872221249Stuexen * SITE_LOCAL then we must have site 3873221249Stuexen * scope in common. 3874221249Stuexen */ 3875246595Stuexen stcb->asoc.scope.site_scope = 1; 3876221249Stuexen } 3877221249Stuexen } else { 3878221249Stuexen /* Validate the address is in scope */ 3879221249Stuexen if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr) && 3880246595Stuexen (stcb->asoc.scope.loopback_scope == 0)) { 3881221249Stuexen addr_inscope = 0; 3882221249Stuexen } else if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && 3883246595Stuexen (stcb->asoc.scope.local_scope == 0)) { 3884221249Stuexen addr_inscope = 0; 3885221249Stuexen } else if (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) && 3886246595Stuexen (stcb->asoc.scope.site_scope == 0)) { 3887221249Stuexen addr_inscope = 0; 3888221249Stuexen } 3889163953Srrs } 3890221249Stuexen break; 3891163953Srrs } 3892179157Srrs#endif 3893221249Stuexen default: 3894163953Srrs /* not supported family type */ 3895163953Srrs return (-1); 3896163953Srrs } 3897179783Srrs net = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_net), struct sctp_nets); 3898163953Srrs if (net == NULL) { 3899163953Srrs return (-1); 3900163953Srrs } 3901163953Srrs SCTP_INCR_RADDR_COUNT(); 3902224641Stuexen bzero(net, sizeof(struct sctp_nets)); 3903169378Srrs (void)SCTP_GETTIME_TIMEVAL(&net->start_time); 3904163953Srrs memcpy(&net->ro._l_addr, newaddr, newaddr->sa_len); 3905221249Stuexen switch (newaddr->sa_family) { 3906221249Stuexen#ifdef INET 3907221249Stuexen case AF_INET: 3908163953Srrs ((struct sockaddr_in *)&net->ro._l_addr)->sin_port = stcb->rport; 3909221249Stuexen break; 3910221249Stuexen#endif 3911221249Stuexen#ifdef INET6 3912221249Stuexen case AF_INET6: 3913163953Srrs ((struct sockaddr_in6 *)&net->ro._l_addr)->sin6_port = stcb->rport; 3914221249Stuexen break; 3915221249Stuexen#endif 3916221249Stuexen default: 3917221249Stuexen break; 3918163953Srrs } 3919167598Srrs net->addr_is_local = sctp_is_address_on_local_host(newaddr, stcb->asoc.vrf_id); 3920167598Srrs if (net->addr_is_local && ((set_scope || (from == SCTP_ADDR_IS_CONFIRMED)))) { 3921246595Stuexen stcb->asoc.scope.loopback_scope = 1; 3922246595Stuexen stcb->asoc.scope.ipv4_local_scope = 1; 3923246595Stuexen stcb->asoc.scope.local_scope = 0; 3924246595Stuexen stcb->asoc.scope.site_scope = 1; 3925167598Srrs addr_inscope = 1; 3926167598Srrs } 3927163953Srrs net->failure_threshold = stcb->asoc.def_net_failure; 3928224641Stuexen net->pf_threshold = stcb->asoc.def_net_pf_threshold; 3929163953Srrs if (addr_inscope == 0) { 3930163953Srrs net->dest_state = (SCTP_ADDR_REACHABLE | 3931163953Srrs SCTP_ADDR_OUT_OF_SCOPE); 3932163953Srrs } else { 3933165220Srrs if (from == SCTP_ADDR_IS_CONFIRMED) 3934165220Srrs /* SCTP_ADDR_IS_CONFIRMED is passed by connect_x */ 3935163953Srrs net->dest_state = SCTP_ADDR_REACHABLE; 3936163953Srrs else 3937163953Srrs net->dest_state = SCTP_ADDR_REACHABLE | 3938163953Srrs SCTP_ADDR_UNCONFIRMED; 3939163953Srrs } 3940170428Srrs /* 3941170428Srrs * We set this to 0, the timer code knows that this means its an 3942170428Srrs * initial value 3943170428Srrs */ 3944219397Srrs net->rto_needed = 1; 3945170428Srrs net->RTO = 0; 3946170642Srrs net->RTO_measured = 0; 3947163953Srrs stcb->asoc.numnets++; 3948227755Stuexen net->ref_count = 1; 3949218072Srrs net->cwr_window_tsn = net->last_cwr_tsn = stcb->asoc.sending_seq - 1; 3950227755Stuexen net->port = stcb->asoc.port; 3951224870Stuexen net->dscp = stcb->asoc.default_dscp; 3952225549Stuexen#ifdef INET6 3953224870Stuexen net->flowlabel = stcb->asoc.default_flowlabel; 3954225549Stuexen#endif 3955225635Stuexen if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) { 3956224641Stuexen net->dest_state |= SCTP_ADDR_NOHB; 3957224641Stuexen } else { 3958224641Stuexen net->dest_state &= ~SCTP_ADDR_NOHB; 3959224641Stuexen } 3960225635Stuexen if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD)) { 3961225635Stuexen net->dest_state |= SCTP_ADDR_NO_PMTUD; 3962225635Stuexen } else { 3963225635Stuexen net->dest_state &= ~SCTP_ADDR_NO_PMTUD; 3964225635Stuexen } 3965224641Stuexen net->heart_beat_delay = stcb->asoc.heart_beat_delay; 3966163953Srrs /* Init the timer structure */ 3967165647Srrs SCTP_OS_TIMER_INIT(&net->rxt_timer.timer); 3968165647Srrs SCTP_OS_TIMER_INIT(&net->pmtu_timer.timer); 3969224641Stuexen SCTP_OS_TIMER_INIT(&net->hb_timer.timer); 3970163953Srrs 3971163953Srrs /* Now generate a route for this guy */ 3972178251Srrs#ifdef INET6 3973163953Srrs /* KAME hack: embed scopeid */ 3974163953Srrs if (newaddr->sa_family == AF_INET6) { 3975163953Srrs struct sockaddr_in6 *sin6; 3976163953Srrs 3977163953Srrs sin6 = (struct sockaddr_in6 *)&net->ro._l_addr; 3978197288Srrs (void)sa6_embedscope(sin6, MODULE_GLOBAL(ip6_use_defzone)); 3979163953Srrs sin6->sin6_scope_id = 0; 3980163953Srrs } 3981178251Srrs#endif 3982284633Stuexen SCTP_RTALLOC((sctp_route_t *) & net->ro, 3983284633Stuexen stcb->asoc.vrf_id, 3984284633Stuexen stcb->sctp_ep->fibnum); 3985168299Srrs 3986169352Srrs if (SCTP_ROUTE_HAS_VALID_IFN(&net->ro)) { 3987169352Srrs /* Get source address */ 3988169352Srrs net->ro._s_addr = sctp_source_address_selection(stcb->sctp_ep, 3989169352Srrs stcb, 3990169352Srrs (sctp_route_t *) & net->ro, 3991169352Srrs net, 3992169352Srrs 0, 3993169352Srrs stcb->asoc.vrf_id); 3994270351Stuexen if (net->ro._s_addr != NULL) { 3995270351Stuexen net->src_addr_selected = 1; 3996270351Stuexen /* Now get the interface MTU */ 3997270351Stuexen if (net->ro._s_addr->ifn_p != NULL) { 3998270351Stuexen net->mtu = SCTP_GATHER_MTU_FROM_INTFC(net->ro._s_addr->ifn_p); 3999270351Stuexen } 4000270351Stuexen } else { 4001270351Stuexen net->src_addr_selected = 0; 4002169352Srrs } 4003227540Stuexen if (net->mtu > 0) { 4004169352Srrs uint32_t rmtu; 4005169352Srrs 4006169352Srrs rmtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._l_addr.sa, net->ro.ro_rt); 4007169352Srrs if (rmtu == 0) { 4008169352Srrs /* 4009169352Srrs * Start things off to match mtu of 4010169352Srrs * interface please. 4011169352Srrs */ 4012169352Srrs SCTP_SET_MTU_OF_ROUTE(&net->ro._l_addr.sa, 4013169352Srrs net->ro.ro_rt, net->mtu); 4014169352Srrs } else { 4015169352Srrs /* 4016169352Srrs * we take the route mtu over the interface, 4017169352Srrs * since the route may be leading out the 4018169352Srrs * loopback, or a different interface. 4019169352Srrs */ 4020169352Srrs net->mtu = rmtu; 4021169352Srrs } 4022169352Srrs } 4023270351Stuexen } else { 4024270351Stuexen net->src_addr_selected = 0; 4025227540Stuexen } 4026227540Stuexen if (net->mtu == 0) { 4027227540Stuexen switch (newaddr->sa_family) { 4028227540Stuexen#ifdef INET 4029227540Stuexen case AF_INET: 4030227540Stuexen net->mtu = SCTP_DEFAULT_MTU; 4031227540Stuexen break; 4032227540Stuexen#endif 4033227540Stuexen#ifdef INET6 4034227540Stuexen case AF_INET6: 4035227540Stuexen net->mtu = 1280; 4036227540Stuexen break; 4037227540Stuexen#endif 4038227540Stuexen default: 4039227540Stuexen break; 4040163953Srrs } 4041163953Srrs } 4042270350Stuexen#if defined(INET) || defined(INET6) 4043227540Stuexen if (net->port) { 4044227540Stuexen net->mtu -= (uint32_t) sizeof(struct udphdr); 4045227540Stuexen } 4046270350Stuexen#endif 4047227540Stuexen if (from == SCTP_ALLOC_ASOC) { 4048227540Stuexen stcb->asoc.smallest_mtu = net->mtu; 4049227540Stuexen } 4050227540Stuexen if (stcb->asoc.smallest_mtu > net->mtu) { 4051227540Stuexen stcb->asoc.smallest_mtu = net->mtu; 4052227540Stuexen } 4053179157Srrs#ifdef INET6 4054179157Srrs if (newaddr->sa_family == AF_INET6) { 4055179157Srrs struct sockaddr_in6 *sin6; 4056179157Srrs 4057179157Srrs sin6 = (struct sockaddr_in6 *)&net->ro._l_addr; 4058179157Srrs (void)sa6_recoverscope(sin6); 4059179157Srrs } 4060179157Srrs#endif 4061227540Stuexen 4062171440Srrs /* JRS - Use the congestion control given in the CC module */ 4063219057Srrs if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) 4064219057Srrs (*stcb->asoc.cc_functions.sctp_set_initial_cc_param) (stcb, net); 4065163953Srrs 4066163953Srrs /* 4067163953Srrs * CMT: CUC algo - set find_pseudo_cumack to TRUE (1) at beginning 4068163953Srrs * of assoc (2005/06/27, iyengar@cis.udel.edu) 4069163953Srrs */ 4070163953Srrs net->find_pseudo_cumack = 1; 4071163953Srrs net->find_rtx_pseudo_cumack = 1; 4072218400Stuexen /* Choose an initial flowid. */ 4073218400Stuexen net->flowid = stcb->asoc.my_vtag ^ 4074218400Stuexen ntohs(stcb->rport) ^ 4075218400Stuexen ntohs(stcb->sctp_ep->sctp_lport); 4076281955Shiren net->flowtype = M_HASHTYPE_OPAQUE; 4077226869Stuexen if (netp) { 4078226869Stuexen *netp = net; 4079226869Stuexen } 4080163953Srrs netfirst = TAILQ_FIRST(&stcb->asoc.nets); 4081163953Srrs if (net->ro.ro_rt == NULL) { 4082163953Srrs /* Since we have no route put it at the back */ 4083163953Srrs TAILQ_INSERT_TAIL(&stcb->asoc.nets, net, sctp_next); 4084163953Srrs } else if (netfirst == NULL) { 4085163953Srrs /* We are the first one in the pool. */ 4086163953Srrs TAILQ_INSERT_HEAD(&stcb->asoc.nets, net, sctp_next); 4087163953Srrs } else if (netfirst->ro.ro_rt == NULL) { 4088163953Srrs /* 4089163953Srrs * First one has NO route. Place this one ahead of the first 4090163953Srrs * one. 4091163953Srrs */ 4092163953Srrs TAILQ_INSERT_HEAD(&stcb->asoc.nets, net, sctp_next); 4093163953Srrs } else if (net->ro.ro_rt->rt_ifp != netfirst->ro.ro_rt->rt_ifp) { 4094163953Srrs /* 4095163953Srrs * This one has a different interface than the one at the 4096163953Srrs * top of the list. Place it ahead. 4097163953Srrs */ 4098163953Srrs TAILQ_INSERT_HEAD(&stcb->asoc.nets, net, sctp_next); 4099163953Srrs } else { 4100163953Srrs /* 4101163953Srrs * Ok we have the same interface as the first one. Move 4102163953Srrs * forward until we find either a) one with a NULL route... 4103163953Srrs * insert ahead of that b) one with a different ifp.. insert 4104163953Srrs * after that. c) end of the list.. insert at the tail. 4105163953Srrs */ 4106163953Srrs struct sctp_nets *netlook; 4107163953Srrs 4108163953Srrs do { 4109163953Srrs netlook = TAILQ_NEXT(netfirst, sctp_next); 4110163953Srrs if (netlook == NULL) { 4111163953Srrs /* End of the list */ 4112168299Srrs TAILQ_INSERT_TAIL(&stcb->asoc.nets, net, sctp_next); 4113163953Srrs break; 4114163953Srrs } else if (netlook->ro.ro_rt == NULL) { 4115163953Srrs /* next one has NO route */ 4116163953Srrs TAILQ_INSERT_BEFORE(netfirst, net, sctp_next); 4117163953Srrs break; 4118168299Srrs } else if (netlook->ro.ro_rt->rt_ifp != net->ro.ro_rt->rt_ifp) { 4119163953Srrs TAILQ_INSERT_AFTER(&stcb->asoc.nets, netlook, 4120163953Srrs net, sctp_next); 4121163953Srrs break; 4122163953Srrs } 4123163953Srrs /* Shift forward */ 4124163953Srrs netfirst = netlook; 4125163953Srrs } while (netlook != NULL); 4126163953Srrs } 4127163953Srrs 4128163953Srrs /* got to have a primary set */ 4129163953Srrs if (stcb->asoc.primary_destination == 0) { 4130163953Srrs stcb->asoc.primary_destination = net; 4131163953Srrs } else if ((stcb->asoc.primary_destination->ro.ro_rt == NULL) && 4132163953Srrs (net->ro.ro_rt) && 4133163953Srrs ((net->dest_state & SCTP_ADDR_UNCONFIRMED) == 0)) { 4134163953Srrs /* No route to current primary adopt new primary */ 4135163953Srrs stcb->asoc.primary_destination = net; 4136163953Srrs } 4137163953Srrs /* Validate primary is first */ 4138163953Srrs net = TAILQ_FIRST(&stcb->asoc.nets); 4139163953Srrs if ((net != stcb->asoc.primary_destination) && 4140163953Srrs (stcb->asoc.primary_destination)) { 4141163953Srrs /* 4142163953Srrs * first one on the list is NOT the primary sctp_cmpaddr() 4143215034Sbrucec * is much more efficient if the primary is the first on the 4144163953Srrs * list, make it so. 4145163953Srrs */ 4146163953Srrs TAILQ_REMOVE(&stcb->asoc.nets, 4147163953Srrs stcb->asoc.primary_destination, sctp_next); 4148163953Srrs TAILQ_INSERT_HEAD(&stcb->asoc.nets, 4149163953Srrs stcb->asoc.primary_destination, sctp_next); 4150163953Srrs } 4151163953Srrs return (0); 4152163953Srrs} 4153163953Srrs 4154163953Srrs 4155185694Srrsstatic uint32_t 4156185694Srrssctp_aloc_a_assoc_id(struct sctp_inpcb *inp, struct sctp_tcb *stcb) 4157185694Srrs{ 4158185694Srrs uint32_t id; 4159185694Srrs struct sctpasochead *head; 4160185694Srrs struct sctp_tcb *lstcb; 4161185694Srrs 4162197173Srrs SCTP_INP_WLOCK(inp); 4163185694Srrstry_again: 4164185694Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) { 4165185694Srrs /* TSNH */ 4166197173Srrs SCTP_INP_WUNLOCK(inp); 4167185694Srrs return (0); 4168185694Srrs } 4169197173Srrs /* 4170223132Stuexen * We don't allow assoc id to be one of SCTP_FUTURE_ASSOC, 4171223132Stuexen * SCTP_CURRENT_ASSOC and SCTP_ALL_ASSOC. 4172197173Srrs */ 4173223132Stuexen if (inp->sctp_associd_counter <= SCTP_ALL_ASSOC) { 4174223132Stuexen inp->sctp_associd_counter = SCTP_ALL_ASSOC + 1; 4175197173Srrs } 4176185694Srrs id = inp->sctp_associd_counter; 4177185694Srrs inp->sctp_associd_counter++; 4178185694Srrs lstcb = sctp_findasoc_ep_asocid_locked(inp, (sctp_assoc_t) id, 0); 4179185694Srrs if (lstcb) { 4180185694Srrs goto try_again; 4181185694Srrs } 4182185694Srrs head = &inp->sctp_asocidhash[SCTP_PCBHASH_ASOC(id, inp->hashasocidmark)]; 4183185694Srrs LIST_INSERT_HEAD(head, stcb, sctp_tcbasocidhash); 4184185694Srrs stcb->asoc.in_asocid_hash = 1; 4185185694Srrs SCTP_INP_WUNLOCK(inp); 4186185694Srrs return id; 4187185694Srrs} 4188185694Srrs 4189163953Srrs/* 4190163953Srrs * allocate an association and add it to the endpoint. The caller must be 4191163953Srrs * careful to add all additional addresses once they are know right away or 4192163953Srrs * else the assoc will be may experience a blackout scenario. 4193163953Srrs */ 4194163953Srrsstruct sctp_tcb * 4195163953Srrssctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr, 4196206137Stuexen int *error, uint32_t override_tag, uint32_t vrf_id, 4197294215Stuexen uint16_t o_streams, 4198171531Srrs struct thread *p 4199171531Srrs) 4200163953Srrs{ 4201171531Srrs /* note the p argument is only valid in unbound sockets */ 4202171531Srrs 4203163953Srrs struct sctp_tcb *stcb; 4204163953Srrs struct sctp_association *asoc; 4205163953Srrs struct sctpasochead *head; 4206163953Srrs uint16_t rport; 4207163953Srrs int err; 4208163953Srrs 4209163953Srrs /* 4210163953Srrs * Assumption made here: Caller has done a 4211163953Srrs * sctp_findassociation_ep_addr(ep, addr's); to make sure the 4212163953Srrs * address does not exist already. 4213163953Srrs */ 4214179783Srrs if (SCTP_BASE_INFO(ipi_count_asoc) >= SCTP_MAX_NUM_OF_ASOC) { 4215163953Srrs /* Hit max assoc, sorry no more */ 4216171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOBUFS); 4217163953Srrs *error = ENOBUFS; 4218163953Srrs return (NULL); 4219163953Srrs } 4220169420Srrs if (firstaddr == NULL) { 4221171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); 4222169420Srrs *error = EINVAL; 4223169420Srrs return (NULL); 4224169420Srrs } 4225163953Srrs SCTP_INP_RLOCK(inp); 4226181054Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) && 4227181054Srrs ((sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE)) || 4228181054Srrs (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED))) { 4229163953Srrs /* 4230163953Srrs * If its in the TCP pool, its NOT allowed to create an 4231163953Srrs * association. The parent listener needs to call 4232163953Srrs * sctp_aloc_assoc.. or the one-2-many socket. If a peeled 4233163953Srrs * off, or connected one does this.. its an error. 4234163953Srrs */ 4235163953Srrs SCTP_INP_RUNLOCK(inp); 4236171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); 4237163953Srrs *error = EINVAL; 4238163953Srrs return (NULL); 4239163953Srrs } 4240225559Stuexen if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 4241225559Stuexen (inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE)) { 4242225559Stuexen if ((inp->sctp_flags & SCTP_PCB_FLAGS_WAS_CONNECTED) || 4243225559Stuexen (inp->sctp_flags & SCTP_PCB_FLAGS_WAS_ABORTED)) { 4244225559Stuexen SCTP_INP_RUNLOCK(inp); 4245225559Stuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); 4246225559Stuexen *error = EINVAL; 4247225559Stuexen return (NULL); 4248225559Stuexen } 4249225559Stuexen } 4250169420Srrs SCTPDBG(SCTP_DEBUG_PCB3, "Allocate an association for peer:"); 4251163953Srrs#ifdef SCTP_DEBUG 4252169420Srrs if (firstaddr) { 4253169420Srrs SCTPDBG_ADDR(SCTP_DEBUG_PCB3, firstaddr); 4254221249Stuexen switch (firstaddr->sa_family) { 4255221249Stuexen#ifdef INET 4256221249Stuexen case AF_INET: 4257221249Stuexen SCTPDBG(SCTP_DEBUG_PCB3, "Port:%d\n", 4258221249Stuexen ntohs(((struct sockaddr_in *)firstaddr)->sin_port)); 4259221249Stuexen break; 4260221249Stuexen#endif 4261221249Stuexen#ifdef INET6 4262221249Stuexen case AF_INET6: 4263221249Stuexen SCTPDBG(SCTP_DEBUG_PCB3, "Port:%d\n", 4264221249Stuexen ntohs(((struct sockaddr_in6 *)firstaddr)->sin6_port)); 4265221249Stuexen break; 4266221249Stuexen#endif 4267221249Stuexen default: 4268221249Stuexen break; 4269221249Stuexen } 4270169420Srrs } else { 4271169420Srrs SCTPDBG(SCTP_DEBUG_PCB3, "None\n"); 4272163953Srrs } 4273163953Srrs#endif /* SCTP_DEBUG */ 4274221249Stuexen switch (firstaddr->sa_family) { 4275221249Stuexen#ifdef INET 4276221249Stuexen case AF_INET: 4277221249Stuexen { 4278221249Stuexen struct sockaddr_in *sin; 4279163953Srrs 4280221249Stuexen sin = (struct sockaddr_in *)firstaddr; 4281225571Stuexen if ((ntohs(sin->sin_port) == 0) || 4282225571Stuexen (sin->sin_addr.s_addr == INADDR_ANY) || 4283225571Stuexen (sin->sin_addr.s_addr == INADDR_BROADCAST) || 4284225571Stuexen IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) { 4285221249Stuexen /* Invalid address */ 4286221249Stuexen SCTP_INP_RUNLOCK(inp); 4287221249Stuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); 4288221249Stuexen *error = EINVAL; 4289221249Stuexen return (NULL); 4290221249Stuexen } 4291221249Stuexen rport = sin->sin_port; 4292221249Stuexen break; 4293163953Srrs } 4294221249Stuexen#endif 4295221249Stuexen#ifdef INET6 4296221249Stuexen case AF_INET6: 4297221249Stuexen { 4298221249Stuexen struct sockaddr_in6 *sin6; 4299163953Srrs 4300221249Stuexen sin6 = (struct sockaddr_in6 *)firstaddr; 4301225571Stuexen if ((ntohs(sin6->sin6_port) == 0) || 4302225571Stuexen IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) || 4303225571Stuexen IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { 4304221249Stuexen /* Invalid address */ 4305221249Stuexen SCTP_INP_RUNLOCK(inp); 4306221249Stuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); 4307221249Stuexen *error = EINVAL; 4308221249Stuexen return (NULL); 4309221249Stuexen } 4310221249Stuexen rport = sin6->sin6_port; 4311221249Stuexen break; 4312163953Srrs } 4313221249Stuexen#endif 4314221249Stuexen default: 4315163953Srrs /* not supported family type */ 4316163953Srrs SCTP_INP_RUNLOCK(inp); 4317171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); 4318163953Srrs *error = EINVAL; 4319163953Srrs return (NULL); 4320163953Srrs } 4321163953Srrs SCTP_INP_RUNLOCK(inp); 4322163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) { 4323163953Srrs /* 4324163953Srrs * If you have not performed a bind, then we need to do the 4325215034Sbrucec * ephemeral bind for you. 4326163953Srrs */ 4327163953Srrs if ((err = sctp_inpcb_bind(inp->sctp_socket, 4328171477Srrs (struct sockaddr *)NULL, 4329171572Srrs (struct sctp_ifa *)NULL, 4330171531Srrs p 4331163953Srrs ))) { 4332163953Srrs /* bind error, probably perm */ 4333163953Srrs *error = err; 4334163953Srrs return (NULL); 4335163953Srrs } 4336163953Srrs } 4337179783Srrs stcb = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_asoc), struct sctp_tcb); 4338163953Srrs if (stcb == NULL) { 4339163953Srrs /* out of memory? */ 4340171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOMEM); 4341163953Srrs *error = ENOMEM; 4342163953Srrs return (NULL); 4343163953Srrs } 4344163953Srrs SCTP_INCR_ASOC_COUNT(); 4345163953Srrs 4346163953Srrs bzero(stcb, sizeof(*stcb)); 4347163953Srrs asoc = &stcb->asoc; 4348185694Srrs 4349185694Srrs asoc->assoc_id = sctp_aloc_a_assoc_id(inp, stcb); 4350163953Srrs SCTP_TCB_LOCK_INIT(stcb); 4351163953Srrs SCTP_TCB_SEND_LOCK_INIT(stcb); 4352185694Srrs stcb->rport = rport; 4353163953Srrs /* setup back pointer's */ 4354163953Srrs stcb->sctp_ep = inp; 4355163953Srrs stcb->sctp_socket = inp->sctp_socket; 4356294215Stuexen if ((err = sctp_init_asoc(inp, stcb, override_tag, vrf_id, o_streams))) { 4357163953Srrs /* failed */ 4358163953Srrs SCTP_TCB_LOCK_DESTROY(stcb); 4359163953Srrs SCTP_TCB_SEND_LOCK_DESTROY(stcb); 4360185694Srrs LIST_REMOVE(stcb, sctp_tcbasocidhash); 4361179783Srrs SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asoc), stcb); 4362163953Srrs SCTP_DECR_ASOC_COUNT(); 4363163953Srrs *error = err; 4364163953Srrs return (NULL); 4365163953Srrs } 4366163953Srrs /* and the port */ 4367163953Srrs SCTP_INP_INFO_WLOCK(); 4368163953Srrs SCTP_INP_WLOCK(inp); 4369163953Srrs if (inp->sctp_flags & (SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_SOCKET_ALLGONE)) { 4370163953Srrs /* inpcb freed while alloc going on */ 4371163953Srrs SCTP_TCB_LOCK_DESTROY(stcb); 4372163953Srrs SCTP_TCB_SEND_LOCK_DESTROY(stcb); 4373185694Srrs LIST_REMOVE(stcb, sctp_tcbasocidhash); 4374179783Srrs SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asoc), stcb); 4375163953Srrs SCTP_INP_WUNLOCK(inp); 4376163953Srrs SCTP_INP_INFO_WUNLOCK(); 4377163953Srrs SCTP_DECR_ASOC_COUNT(); 4378171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); 4379163953Srrs *error = EINVAL; 4380163953Srrs return (NULL); 4381163953Srrs } 4382163953Srrs SCTP_TCB_LOCK(stcb); 4383163953Srrs 4384163953Srrs /* now that my_vtag is set, add it to the hash */ 4385185694Srrs head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(stcb->asoc.my_vtag, SCTP_BASE_INFO(hashasocmark))]; 4386163953Srrs /* put it in the bucket in the vtag hash of assoc's for the system */ 4387163953Srrs LIST_INSERT_HEAD(head, stcb, sctp_asocs); 4388163953Srrs SCTP_INP_INFO_WUNLOCK(); 4389163953Srrs 4390224641Stuexen if ((err = sctp_add_remote_addr(stcb, firstaddr, NULL, SCTP_DO_SETSCOPE, SCTP_ALLOC_ASOC))) { 4391163953Srrs /* failure.. memory error? */ 4392170091Srrs if (asoc->strmout) { 4393170091Srrs SCTP_FREE(asoc->strmout, SCTP_M_STRMO); 4394170091Srrs asoc->strmout = NULL; 4395170091Srrs } 4396170091Srrs if (asoc->mapping_array) { 4397170091Srrs SCTP_FREE(asoc->mapping_array, SCTP_M_MAP); 4398170091Srrs asoc->mapping_array = NULL; 4399170091Srrs } 4400193089Srrs if (asoc->nr_mapping_array) { 4401193089Srrs SCTP_FREE(asoc->nr_mapping_array, SCTP_M_MAP); 4402193089Srrs asoc->nr_mapping_array = NULL; 4403193089Srrs } 4404163953Srrs SCTP_DECR_ASOC_COUNT(); 4405258454Stuexen SCTP_TCB_UNLOCK(stcb); 4406163953Srrs SCTP_TCB_LOCK_DESTROY(stcb); 4407163953Srrs SCTP_TCB_SEND_LOCK_DESTROY(stcb); 4408185694Srrs LIST_REMOVE(stcb, sctp_tcbasocidhash); 4409179783Srrs SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asoc), stcb); 4410168299Srrs SCTP_INP_WUNLOCK(inp); 4411171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOBUFS); 4412163953Srrs *error = ENOBUFS; 4413163953Srrs return (NULL); 4414163953Srrs } 4415163953Srrs /* Init all the timers */ 4416165647Srrs SCTP_OS_TIMER_INIT(&asoc->dack_timer.timer); 4417165647Srrs SCTP_OS_TIMER_INIT(&asoc->strreset_timer.timer); 4418165647Srrs SCTP_OS_TIMER_INIT(&asoc->asconf_timer.timer); 4419165647Srrs SCTP_OS_TIMER_INIT(&asoc->shut_guard_timer.timer); 4420165647Srrs SCTP_OS_TIMER_INIT(&asoc->autoclose_timer.timer); 4421165647Srrs SCTP_OS_TIMER_INIT(&asoc->delayed_event_timer.timer); 4422172091Srrs SCTP_OS_TIMER_INIT(&asoc->delete_prim_timer.timer); 4423165647Srrs 4424163953Srrs LIST_INSERT_HEAD(&inp->sctp_asoc_list, stcb, sctp_tcblist); 4425163953Srrs /* now file the port under the hash as well */ 4426163953Srrs if (inp->sctp_tcbhash != NULL) { 4427163953Srrs head = &inp->sctp_tcbhash[SCTP_PCBHASH_ALLADDR(stcb->rport, 4428163953Srrs inp->sctp_hashmark)]; 4429163953Srrs LIST_INSERT_HEAD(head, stcb, sctp_tcbhash); 4430163953Srrs } 4431163953Srrs SCTP_INP_WUNLOCK(inp); 4432240148Stuexen SCTPDBG(SCTP_DEBUG_PCB1, "Association %p now allocated\n", (void *)stcb); 4433163953Srrs return (stcb); 4434163953Srrs} 4435163953Srrs 4436163953Srrs 4437163953Srrsvoid 4438163953Srrssctp_remove_net(struct sctp_tcb *stcb, struct sctp_nets *net) 4439163953Srrs{ 4440163953Srrs struct sctp_association *asoc; 4441163953Srrs 4442163953Srrs asoc = &stcb->asoc; 4443163953Srrs asoc->numnets--; 4444163953Srrs TAILQ_REMOVE(&asoc->nets, net, sctp_next); 4445163953Srrs if (net == asoc->primary_destination) { 4446163953Srrs /* Reset primary */ 4447163953Srrs struct sctp_nets *lnet; 4448163953Srrs 4449163953Srrs lnet = TAILQ_FIRST(&asoc->nets); 4450172091Srrs /* 4451172091Srrs * Mobility adaptation Ideally, if deleted destination is 4452172091Srrs * the primary, it becomes a fast retransmission trigger by 4453172091Srrs * the subsequent SET PRIMARY. (by micchie) 4454172091Srrs */ 4455172091Srrs if (sctp_is_mobility_feature_on(stcb->sctp_ep, 4456172703Srrs SCTP_MOBILITY_BASE) || 4457172703Srrs sctp_is_mobility_feature_on(stcb->sctp_ep, 4458172091Srrs SCTP_MOBILITY_FASTHANDOFF)) { 4459172091Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "remove_net: primary dst is deleting\n"); 4460172091Srrs if (asoc->deleted_primary != NULL) { 4461172091Srrs SCTPDBG(SCTP_DEBUG_ASCONF1, "remove_net: deleted primary may be already stored\n"); 4462179157Srrs goto out; 4463172091Srrs } 4464172091Srrs asoc->deleted_primary = net; 4465172091Srrs atomic_add_int(&net->ref_count, 1); 4466172396Srrs memset(&net->lastsa, 0, sizeof(net->lastsa)); 4467172396Srrs memset(&net->lastsv, 0, sizeof(net->lastsv)); 4468172091Srrs sctp_mobility_feature_on(stcb->sctp_ep, 4469172091Srrs SCTP_MOBILITY_PRIM_DELETED); 4470172091Srrs sctp_timer_start(SCTP_TIMER_TYPE_PRIM_DELETED, 4471172091Srrs stcb->sctp_ep, stcb, NULL); 4472172091Srrs } 4473179157Srrsout: 4474163953Srrs /* Try to find a confirmed primary */ 4475167598Srrs asoc->primary_destination = sctp_find_alternate_net(stcb, lnet, 0); 4476163953Srrs } 4477163953Srrs if (net == asoc->last_data_chunk_from) { 4478163953Srrs /* Reset primary */ 4479163953Srrs asoc->last_data_chunk_from = TAILQ_FIRST(&asoc->nets); 4480163953Srrs } 4481163953Srrs if (net == asoc->last_control_chunk_from) { 4482163953Srrs /* Clear net */ 4483163953Srrs asoc->last_control_chunk_from = NULL; 4484163953Srrs } 4485224641Stuexen if (net == stcb->asoc.alternate) { 4486224641Stuexen sctp_free_remote_addr(stcb->asoc.alternate); 4487224641Stuexen stcb->asoc.alternate = NULL; 4488224641Stuexen } 4489167598Srrs sctp_free_remote_addr(net); 4490163953Srrs} 4491163953Srrs 4492163953Srrs/* 4493163953Srrs * remove a remote endpoint address from an association, it will fail if the 4494163953Srrs * address does not exist. 4495163953Srrs */ 4496163953Srrsint 4497163953Srrssctp_del_remote_addr(struct sctp_tcb *stcb, struct sockaddr *remaddr) 4498163953Srrs{ 4499163953Srrs /* 4500163953Srrs * Here we need to remove a remote address. This is quite simple, we 4501163953Srrs * first find it in the list of address for the association 4502163953Srrs * (tasoc->asoc.nets) and then if it is there, we do a LIST_REMOVE 4503163953Srrs * on that item. Note we do not allow it to be removed if there are 4504163953Srrs * no other addresses. 4505163953Srrs */ 4506163953Srrs struct sctp_association *asoc; 4507216822Stuexen struct sctp_nets *net, *nnet; 4508163953Srrs 4509163953Srrs asoc = &stcb->asoc; 4510163953Srrs 4511163953Srrs /* locate the address */ 4512216822Stuexen TAILQ_FOREACH_SAFE(net, &asoc->nets, sctp_next, nnet) { 4513163953Srrs if (net->ro._l_addr.sa.sa_family != remaddr->sa_family) { 4514163953Srrs continue; 4515163953Srrs } 4516163953Srrs if (sctp_cmpaddr((struct sockaddr *)&net->ro._l_addr, 4517163953Srrs remaddr)) { 4518163953Srrs /* we found the guy */ 4519163953Srrs if (asoc->numnets < 2) { 4520163953Srrs /* Must have at LEAST two remote addresses */ 4521163953Srrs return (-1); 4522163953Srrs } else { 4523163953Srrs sctp_remove_net(stcb, net); 4524163953Srrs return (0); 4525163953Srrs } 4526163953Srrs } 4527163953Srrs } 4528163953Srrs /* not found. */ 4529163953Srrs return (-2); 4530163953Srrs} 4531163953Srrs 4532172091Srrsvoid 4533185694Srrssctp_delete_from_timewait(uint32_t tag, uint16_t lport, uint16_t rport) 4534172091Srrs{ 4535172091Srrs struct sctpvtaghead *chain; 4536172091Srrs struct sctp_tagblock *twait_block; 4537172091Srrs int found = 0; 4538172091Srrs int i; 4539163953Srrs 4540179783Srrs chain = &SCTP_BASE_INFO(vtag_timewait)[(tag % SCTP_STACK_VTAG_HASH_SIZE)]; 4541252585Stuexen LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) { 4542252585Stuexen for (i = 0; i < SCTP_NUMBER_IN_VTAG_BLOCK; i++) { 4543252585Stuexen if ((twait_block->vtag_block[i].v_tag == tag) && 4544252585Stuexen (twait_block->vtag_block[i].lport == lport) && 4545252585Stuexen (twait_block->vtag_block[i].rport == rport)) { 4546252585Stuexen twait_block->vtag_block[i].tv_sec_at_expire = 0; 4547252585Stuexen twait_block->vtag_block[i].v_tag = 0; 4548252585Stuexen twait_block->vtag_block[i].lport = 0; 4549252585Stuexen twait_block->vtag_block[i].rport = 0; 4550252585Stuexen found = 1; 4551252585Stuexen break; 4552172091Srrs } 4553172091Srrs } 4554252585Stuexen if (found) 4555252585Stuexen break; 4556172091Srrs } 4557172091Srrs} 4558172091Srrs 4559173179Srrsint 4560185694Srrssctp_is_in_timewait(uint32_t tag, uint16_t lport, uint16_t rport) 4561173179Srrs{ 4562173179Srrs struct sctpvtaghead *chain; 4563173179Srrs struct sctp_tagblock *twait_block; 4564173179Srrs int found = 0; 4565173179Srrs int i; 4566173179Srrs 4567184883Srrs SCTP_INP_INFO_WLOCK(); 4568179783Srrs chain = &SCTP_BASE_INFO(vtag_timewait)[(tag % SCTP_STACK_VTAG_HASH_SIZE)]; 4569252585Stuexen LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) { 4570252585Stuexen for (i = 0; i < SCTP_NUMBER_IN_VTAG_BLOCK; i++) { 4571252585Stuexen if ((twait_block->vtag_block[i].v_tag == tag) && 4572252585Stuexen (twait_block->vtag_block[i].lport == lport) && 4573252585Stuexen (twait_block->vtag_block[i].rport == rport)) { 4574252585Stuexen found = 1; 4575252585Stuexen break; 4576173179Srrs } 4577173179Srrs } 4578252585Stuexen if (found) 4579252585Stuexen break; 4580173179Srrs } 4581184883Srrs SCTP_INP_INFO_WUNLOCK(); 4582173179Srrs return (found); 4583173179Srrs} 4584173179Srrs 4585173179Srrs 4586166023Srrsvoid 4587185694Srrssctp_add_vtag_to_timewait(uint32_t tag, uint32_t time, uint16_t lport, uint16_t rport) 4588163953Srrs{ 4589163953Srrs struct sctpvtaghead *chain; 4590163953Srrs struct sctp_tagblock *twait_block; 4591163953Srrs struct timeval now; 4592163953Srrs int set, i; 4593163953Srrs 4594193090Srrs if (time == 0) { 4595193090Srrs /* Its disabled */ 4596193090Srrs return; 4597193090Srrs } 4598169378Srrs (void)SCTP_GETTIME_TIMEVAL(&now); 4599179783Srrs chain = &SCTP_BASE_INFO(vtag_timewait)[(tag % SCTP_STACK_VTAG_HASH_SIZE)]; 4600163953Srrs set = 0; 4601252585Stuexen LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) { 4602163953Srrs /* Block(s) present, lets find space, and expire on the fly */ 4603252585Stuexen for (i = 0; i < SCTP_NUMBER_IN_VTAG_BLOCK; i++) { 4604252585Stuexen if ((twait_block->vtag_block[i].v_tag == 0) && 4605252585Stuexen !set) { 4606252585Stuexen twait_block->vtag_block[i].tv_sec_at_expire = 4607252585Stuexen now.tv_sec + time; 4608252585Stuexen twait_block->vtag_block[i].v_tag = tag; 4609252585Stuexen twait_block->vtag_block[i].lport = lport; 4610252585Stuexen twait_block->vtag_block[i].rport = rport; 4611252585Stuexen set = 1; 4612252585Stuexen } else if ((twait_block->vtag_block[i].v_tag) && 4613252585Stuexen ((long)twait_block->vtag_block[i].tv_sec_at_expire < now.tv_sec)) { 4614252585Stuexen /* Audit expires this guy */ 4615252585Stuexen twait_block->vtag_block[i].tv_sec_at_expire = 0; 4616252585Stuexen twait_block->vtag_block[i].v_tag = 0; 4617252585Stuexen twait_block->vtag_block[i].lport = 0; 4618252585Stuexen twait_block->vtag_block[i].rport = 0; 4619252585Stuexen if (set == 0) { 4620252585Stuexen /* Reuse it for my new tag */ 4621252585Stuexen twait_block->vtag_block[i].tv_sec_at_expire = now.tv_sec + time; 4622163953Srrs twait_block->vtag_block[i].v_tag = tag; 4623185694Srrs twait_block->vtag_block[i].lport = lport; 4624185694Srrs twait_block->vtag_block[i].rport = rport; 4625163953Srrs set = 1; 4626163953Srrs } 4627163953Srrs } 4628163953Srrs } 4629252585Stuexen if (set) { 4630252585Stuexen /* 4631252585Stuexen * We only do up to the block where we can place our 4632252585Stuexen * tag for audits 4633252585Stuexen */ 4634252585Stuexen break; 4635252585Stuexen } 4636163953Srrs } 4637163953Srrs /* Need to add a new block to chain */ 4638163953Srrs if (!set) { 4639163953Srrs SCTP_MALLOC(twait_block, struct sctp_tagblock *, 4640170091Srrs sizeof(struct sctp_tagblock), SCTP_M_TIMW); 4641163953Srrs if (twait_block == NULL) { 4642184883Srrs#ifdef INVARIANTS 4643184883Srrs panic("Can not alloc tagblock"); 4644184883Srrs#endif 4645163953Srrs return; 4646163953Srrs } 4647166023Srrs memset(twait_block, 0, sizeof(struct sctp_tagblock)); 4648163953Srrs LIST_INSERT_HEAD(chain, twait_block, sctp_nxt_tagblock); 4649173179Srrs twait_block->vtag_block[0].tv_sec_at_expire = now.tv_sec + time; 4650163953Srrs twait_block->vtag_block[0].v_tag = tag; 4651185694Srrs twait_block->vtag_block[0].lport = lport; 4652185694Srrs twait_block->vtag_block[0].rport = rport; 4653163953Srrs } 4654163953Srrs} 4655163953Srrs 4656163953Srrs 4657163953Srrs 4658171943Srrs/*- 4659171943Srrs * Free the association after un-hashing the remote port. This 4660171943Srrs * function ALWAYS returns holding NO LOCK on the stcb. It DOES 4661171943Srrs * expect that the input to this function IS a locked TCB. 4662171943Srrs * It will return 0, if it did NOT destroy the association (instead 4663171943Srrs * it unlocks it. It will return NON-zero if it either destroyed the 4664171943Srrs * association OR the association is already destroyed. 4665163953Srrs */ 4666163953Srrsint 4667165220Srrssctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfree, int from_location) 4668163953Srrs{ 4669163953Srrs int i; 4670163953Srrs struct sctp_association *asoc; 4671216822Stuexen struct sctp_nets *net, *nnet; 4672216822Stuexen struct sctp_laddr *laddr, *naddr; 4673216822Stuexen struct sctp_tmit_chunk *chk, *nchk; 4674216822Stuexen struct sctp_asconf_addr *aparam, *naparam; 4675216822Stuexen struct sctp_asconf_ack *aack, *naack; 4676216822Stuexen struct sctp_stream_reset_list *strrst, *nstrrst; 4677216822Stuexen struct sctp_queued_to_read *sq, *nsq; 4678216822Stuexen struct sctp_stream_queue_pending *sp, *nsp; 4679216822Stuexen sctp_sharedkey_t *shared_key, *nshared_key; 4680163953Srrs struct socket *so; 4681163953Srrs 4682163953Srrs /* first, lets purge the entry from the hash table. */ 4683163953Srrs 4684163953Srrs#ifdef SCTP_LOG_CLOSING 4685163953Srrs sctp_log_closing(inp, stcb, 6); 4686163953Srrs#endif 4687163953Srrs if (stcb->asoc.state == 0) { 4688163953Srrs#ifdef SCTP_LOG_CLOSING 4689163953Srrs sctp_log_closing(inp, NULL, 7); 4690163953Srrs#endif 4691163953Srrs /* there is no asoc, really TSNH :-0 */ 4692163953Srrs return (1); 4693163953Srrs } 4694224641Stuexen if (stcb->asoc.alternate) { 4695224641Stuexen sctp_free_remote_addr(stcb->asoc.alternate); 4696224641Stuexen stcb->asoc.alternate = NULL; 4697224641Stuexen } 4698165220Srrs /* TEMP CODE */ 4699165220Srrs if (stcb->freed_from_where == 0) { 4700165220Srrs /* Only record the first place free happened from */ 4701165220Srrs stcb->freed_from_where = from_location; 4702165220Srrs } 4703165220Srrs /* TEMP CODE */ 4704165220Srrs 4705163953Srrs asoc = &stcb->asoc; 4706163953Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) || 4707163953Srrs (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) 4708163953Srrs /* nothing around */ 4709163953Srrs so = NULL; 4710163953Srrs else 4711163953Srrs so = inp->sctp_socket; 4712163953Srrs 4713163953Srrs /* 4714163953Srrs * We used timer based freeing if a reader or writer is in the way. 4715163953Srrs * So we first check if we are actually being called from a timer, 4716163953Srrs * if so we abort early if a reader or writer is still in the way. 4717163953Srrs */ 4718163953Srrs if ((stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) && 4719165220Srrs (from_inpcbfree == SCTP_NORMAL_PROC)) { 4720163953Srrs /* 4721163953Srrs * is it the timer driving us? if so are the reader/writers 4722163953Srrs * gone? 4723163953Srrs */ 4724163953Srrs if (stcb->asoc.refcnt) { 4725163953Srrs /* nope, reader or writer in the way */ 4726163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL); 4727163953Srrs /* no asoc destroyed */ 4728163953Srrs SCTP_TCB_UNLOCK(stcb); 4729163953Srrs#ifdef SCTP_LOG_CLOSING 4730163953Srrs sctp_log_closing(inp, stcb, 8); 4731163953Srrs#endif 4732163953Srrs return (0); 4733163953Srrs } 4734163953Srrs } 4735163953Srrs /* now clean up any other timers */ 4736169378Srrs (void)SCTP_OS_TIMER_STOP(&asoc->dack_timer.timer); 4737168709Srrs asoc->dack_timer.self = NULL; 4738169378Srrs (void)SCTP_OS_TIMER_STOP(&asoc->strreset_timer.timer); 4739168709Srrs /*- 4740168709Srrs * For stream reset we don't blast this unless 4741168709Srrs * it is a str-reset timer, it might be the 4742168709Srrs * free-asoc timer which we DON'T want to 4743168709Srrs * disturb. 4744168709Srrs */ 4745168709Srrs if (asoc->strreset_timer.type == SCTP_TIMER_TYPE_STRRESET) 4746168709Srrs asoc->strreset_timer.self = NULL; 4747169378Srrs (void)SCTP_OS_TIMER_STOP(&asoc->asconf_timer.timer); 4748168709Srrs asoc->asconf_timer.self = NULL; 4749169378Srrs (void)SCTP_OS_TIMER_STOP(&asoc->autoclose_timer.timer); 4750168709Srrs asoc->autoclose_timer.self = NULL; 4751169378Srrs (void)SCTP_OS_TIMER_STOP(&asoc->shut_guard_timer.timer); 4752168709Srrs asoc->shut_guard_timer.self = NULL; 4753169378Srrs (void)SCTP_OS_TIMER_STOP(&asoc->delayed_event_timer.timer); 4754168709Srrs asoc->delayed_event_timer.self = NULL; 4755172091Srrs /* Mobility adaptation */ 4756172091Srrs (void)SCTP_OS_TIMER_STOP(&asoc->delete_prim_timer.timer); 4757172091Srrs asoc->delete_prim_timer.self = NULL; 4758163953Srrs TAILQ_FOREACH(net, &asoc->nets, sctp_next) { 4759169378Srrs (void)SCTP_OS_TIMER_STOP(&net->rxt_timer.timer); 4760168709Srrs net->rxt_timer.self = NULL; 4761169378Srrs (void)SCTP_OS_TIMER_STOP(&net->pmtu_timer.timer); 4762168709Srrs net->pmtu_timer.self = NULL; 4763224641Stuexen (void)SCTP_OS_TIMER_STOP(&net->hb_timer.timer); 4764224641Stuexen net->hb_timer.self = NULL; 4765163953Srrs } 4766164038Srrs /* Now the read queue needs to be cleaned up (only once) */ 4767164038Srrs if ((stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) == 0) { 4768169208Srrs stcb->asoc.state |= SCTP_STATE_ABOUT_TO_BE_FREED; 4769164038Srrs SCTP_INP_READ_LOCK(inp); 4770164038Srrs TAILQ_FOREACH(sq, &inp->read_queue, next) { 4771164038Srrs if (sq->stcb == stcb) { 4772164038Srrs sq->do_not_ref_stcb = 1; 4773164038Srrs sq->sinfo_cumtsn = stcb->asoc.cumulative_tsn; 4774164085Srrs /* 4775164085Srrs * If there is no end, there never will be 4776164085Srrs * now. 4777164085Srrs */ 4778164085Srrs if (sq->end_added == 0) { 4779164085Srrs /* Held for PD-API clear that. */ 4780164085Srrs sq->pdapi_aborted = 1; 4781164085Srrs sq->held_length = 0; 4782223132Stuexen if (sctp_stcb_is_feature_on(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT) && (so != NULL)) { 4783164085Srrs /* 4784164085Srrs * Need to add a PD-API 4785164085Srrs * aborted indication. 4786164085Srrs * Setting the control_pdapi 4787164085Srrs * assures that it will be 4788164085Srrs * added right after this 4789164085Srrs * msg. 4790164085Srrs */ 4791168943Srrs uint32_t strseq; 4792168943Srrs 4793164085Srrs stcb->asoc.control_pdapi = sq; 4794168943Srrs strseq = (sq->sinfo_stream << 16) | sq->sinfo_ssn; 4795196260Stuexen sctp_ulp_notify(SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION, 4796196260Stuexen stcb, 4797196260Stuexen SCTP_PARTIAL_DELIVERY_ABORTED, 4798196260Stuexen (void *)&strseq, 4799196260Stuexen SCTP_SO_LOCKED); 4800164085Srrs stcb->asoc.control_pdapi = NULL; 4801164038Srrs } 4802164038Srrs } 4803164085Srrs /* Add an end to wake them */ 4804164038Srrs sq->end_added = 1; 4805164038Srrs } 4806164038Srrs } 4807164038Srrs SCTP_INP_READ_UNLOCK(inp); 4808164038Srrs if (stcb->block_entry) { 4809171943Srrs SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_PCB, ECONNRESET); 4810164038Srrs stcb->block_entry->error = ECONNRESET; 4811164038Srrs stcb->block_entry = NULL; 4812164038Srrs } 4813164038Srrs } 4814207924Srrs if ((stcb->asoc.refcnt) || (stcb->asoc.state & SCTP_STATE_IN_ACCEPT_QUEUE)) { 4815164038Srrs /* 4816207924Srrs * Someone holds a reference OR the socket is unaccepted 4817207924Srrs * yet. 4818164038Srrs */ 4819208852Srrs if ((stcb->asoc.refcnt) || 4820208852Srrs (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) || 4821208852Srrs (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) { 4822208852Srrs stcb->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE; 4823207924Srrs sctp_timer_start(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL); 4824208852Srrs } 4825165220Srrs SCTP_TCB_UNLOCK(stcb); 4826171440Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) || 4827171440Srrs (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) 4828171440Srrs /* nothing around */ 4829171440Srrs so = NULL; 4830164038Srrs if (so) { 4831171440Srrs /* Wake any reader/writers */ 4832171440Srrs sctp_sorwakeup(inp, so); 4833171440Srrs sctp_sowwakeup(inp, so); 4834164038Srrs } 4835163953Srrs#ifdef SCTP_LOG_CLOSING 4836163953Srrs sctp_log_closing(inp, stcb, 9); 4837163953Srrs#endif 4838163953Srrs /* no asoc destroyed */ 4839163953Srrs return (0); 4840163953Srrs } 4841163953Srrs#ifdef SCTP_LOG_CLOSING 4842163953Srrs sctp_log_closing(inp, stcb, 10); 4843163953Srrs#endif 4844165220Srrs /* 4845165220Srrs * When I reach here, no others want to kill the assoc yet.. and I 4846165220Srrs * own the lock. Now its possible an abort comes in when I do the 4847165220Srrs * lock exchange below to grab all the locks to do the final take 4848165220Srrs * out. to prevent this we increment the count, which will start a 4849165220Srrs * timer and blow out above thus assuring us that we hold exclusive 4850165220Srrs * killing of the asoc. Note that after getting back the TCB lock we 4851165220Srrs * will go ahead and increment the counter back up and stop any 4852165220Srrs * timer a passing stranger may have started :-S 4853165220Srrs */ 4854165220Srrs if (from_inpcbfree == SCTP_NORMAL_PROC) { 4855165220Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 4856165220Srrs 4857165220Srrs SCTP_TCB_UNLOCK(stcb); 4858165220Srrs SCTP_INP_INFO_WLOCK(); 4859165220Srrs SCTP_INP_WLOCK(inp); 4860165220Srrs SCTP_TCB_LOCK(stcb); 4861163953Srrs } 4862165220Srrs /* Double check the GONE flag */ 4863165220Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) || 4864165220Srrs (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) 4865165220Srrs /* nothing around */ 4866165220Srrs so = NULL; 4867165220Srrs 4868163953Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 4869163953Srrs (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { 4870163953Srrs /* 4871163953Srrs * For TCP type we need special handling when we are 4872163953Srrs * connected. We also include the peel'ed off ones to. 4873163953Srrs */ 4874163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) { 4875163953Srrs inp->sctp_flags &= ~SCTP_PCB_FLAGS_CONNECTED; 4876163953Srrs inp->sctp_flags |= SCTP_PCB_FLAGS_WAS_CONNECTED; 4877163953Srrs if (so) { 4878163953Srrs SOCK_LOCK(so); 4879163953Srrs if (so->so_rcv.sb_cc == 0) { 4880163953Srrs so->so_state &= ~(SS_ISCONNECTING | 4881163953Srrs SS_ISDISCONNECTING | 4882163953Srrs SS_ISCONFIRMING | 4883163953Srrs SS_ISCONNECTED); 4884163953Srrs } 4885208883Srrs socantrcvmore_locked(so); 4886163953Srrs sctp_sowwakeup(inp, so); 4887163953Srrs sctp_sorwakeup(inp, so); 4888169352Srrs SCTP_SOWAKEUP(so); 4889163953Srrs } 4890163953Srrs } 4891163953Srrs } 4892163953Srrs /* 4893163953Srrs * Make it invalid too, that way if its about to run it will abort 4894163953Srrs * and return. 4895163953Srrs */ 4896163953Srrs /* re-increment the lock */ 4897165220Srrs if (from_inpcbfree == SCTP_NORMAL_PROC) { 4898163996Srrs atomic_add_int(&stcb->asoc.refcnt, -1); 4899163953Srrs } 4900209178Stuexen if (stcb->asoc.refcnt) { 4901209178Stuexen stcb->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE; 4902209178Stuexen sctp_timer_start(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL); 4903209178Stuexen if (from_inpcbfree == SCTP_NORMAL_PROC) { 4904209178Stuexen SCTP_INP_INFO_WUNLOCK(); 4905209178Stuexen SCTP_INP_WUNLOCK(inp); 4906209178Stuexen } 4907209178Stuexen SCTP_TCB_UNLOCK(stcb); 4908209178Stuexen return (0); 4909209178Stuexen } 4910163953Srrs asoc->state = 0; 4911163953Srrs if (inp->sctp_tcbhash) { 4912163953Srrs LIST_REMOVE(stcb, sctp_tcbhash); 4913163953Srrs } 4914185694Srrs if (stcb->asoc.in_asocid_hash) { 4915185694Srrs LIST_REMOVE(stcb, sctp_tcbasocidhash); 4916163953Srrs } 4917163953Srrs /* Now lets remove it from the list of ALL associations in the EP */ 4918163953Srrs LIST_REMOVE(stcb, sctp_tcblist); 4919165220Srrs if (from_inpcbfree == SCTP_NORMAL_PROC) { 4920163953Srrs SCTP_INP_INCR_REF(inp); 4921163953Srrs SCTP_INP_WUNLOCK(inp); 4922163953Srrs } 4923163953Srrs /* pull from vtag hash */ 4924163953Srrs LIST_REMOVE(stcb, sctp_asocs); 4925193090Srrs sctp_add_vtag_to_timewait(asoc->my_vtag, SCTP_BASE_SYSCTL(sctp_vtag_time_wait), 4926193090Srrs inp->sctp_lport, stcb->rport); 4927163953Srrs 4928166023Srrs /* 4929206137Stuexen * Now restop the timers to be sure this is paranoia at is finest! 4930166023Srrs */ 4931169378Srrs (void)SCTP_OS_TIMER_STOP(&asoc->strreset_timer.timer); 4932169378Srrs (void)SCTP_OS_TIMER_STOP(&asoc->dack_timer.timer); 4933169378Srrs (void)SCTP_OS_TIMER_STOP(&asoc->strreset_timer.timer); 4934169378Srrs (void)SCTP_OS_TIMER_STOP(&asoc->asconf_timer.timer); 4935169378Srrs (void)SCTP_OS_TIMER_STOP(&asoc->shut_guard_timer.timer); 4936169378Srrs (void)SCTP_OS_TIMER_STOP(&asoc->autoclose_timer.timer); 4937169378Srrs (void)SCTP_OS_TIMER_STOP(&asoc->delayed_event_timer.timer); 4938166023Srrs TAILQ_FOREACH(net, &asoc->nets, sctp_next) { 4939169378Srrs (void)SCTP_OS_TIMER_STOP(&net->rxt_timer.timer); 4940169378Srrs (void)SCTP_OS_TIMER_STOP(&net->pmtu_timer.timer); 4941224641Stuexen (void)SCTP_OS_TIMER_STOP(&net->hb_timer.timer); 4942166023Srrs } 4943166023Srrs 4944166023Srrs asoc->strreset_timer.type = SCTP_TIMER_TYPE_NONE; 4945163953Srrs /* 4946163953Srrs * The chunk lists and such SHOULD be empty but we check them just 4947163953Srrs * in case. 4948163953Srrs */ 4949163953Srrs /* anything on the wheel needs to be removed */ 4950163953Srrs for (i = 0; i < asoc->streamoutcnt; i++) { 4951163953Srrs struct sctp_stream_out *outs; 4952163953Srrs 4953163953Srrs outs = &asoc->strmout[i]; 4954163953Srrs /* now clean up any chunks here */ 4955216822Stuexen TAILQ_FOREACH_SAFE(sp, &outs->outqueue, next, nsp) { 4956163953Srrs TAILQ_REMOVE(&outs->outqueue, sp, next); 4957238550Stuexen sctp_free_spbufspace(stcb, asoc, sp); 4958163953Srrs if (sp->data) { 4959210494Srrs if (so) { 4960210494Srrs /* Still an open socket - report */ 4961210494Srrs sctp_ulp_notify(SCTP_NOTIFY_SPECIAL_SP_FAIL, stcb, 4962235416Stuexen 0, (void *)sp, SCTP_SO_LOCKED); 4963210494Srrs } 4964210494Srrs if (sp->data) { 4965210494Srrs sctp_m_freem(sp->data); 4966210494Srrs sp->data = NULL; 4967210494Srrs sp->tail_mbuf = NULL; 4968238550Stuexen sp->length = 0; 4969210494Srrs } 4970163953Srrs } 4971212712Stuexen if (sp->net) { 4972212712Stuexen sctp_free_remote_addr(sp->net); 4973212712Stuexen sp->net = NULL; 4974212712Stuexen } 4975238550Stuexen sctp_free_a_strmoq(stcb, sp, SCTP_SO_LOCKED); 4976163953Srrs } 4977163953Srrs } 4978169655Srrs /* sa_ignore FREED_MEMORY */ 4979216822Stuexen TAILQ_FOREACH_SAFE(strrst, &asoc->resetHead, next_resp, nstrrst) { 4980216822Stuexen TAILQ_REMOVE(&asoc->resetHead, strrst, next_resp); 4981216822Stuexen SCTP_FREE(strrst, SCTP_M_STRESET); 4982163953Srrs } 4983216822Stuexen TAILQ_FOREACH_SAFE(sq, &asoc->pending_reply_queue, next, nsq) { 4984163953Srrs TAILQ_REMOVE(&asoc->pending_reply_queue, sq, next); 4985163953Srrs if (sq->data) { 4986163953Srrs sctp_m_freem(sq->data); 4987163953Srrs sq->data = NULL; 4988163953Srrs } 4989163953Srrs sctp_free_remote_addr(sq->whoFrom); 4990163953Srrs sq->whoFrom = NULL; 4991163953Srrs sq->stcb = NULL; 4992163953Srrs /* Free the ctl entry */ 4993179783Srrs SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), sq); 4994163953Srrs SCTP_DECR_READQ_COUNT(); 4995169655Srrs /* sa_ignore FREED_MEMORY */ 4996163953Srrs } 4997216822Stuexen TAILQ_FOREACH_SAFE(chk, &asoc->free_chunks, sctp_next, nchk) { 4998163953Srrs TAILQ_REMOVE(&asoc->free_chunks, chk, sctp_next); 4999163953Srrs if (chk->data) { 5000163953Srrs sctp_m_freem(chk->data); 5001163953Srrs chk->data = NULL; 5002163953Srrs } 5003185694Srrs if (chk->holds_key_ref) 5004221627Stuexen sctp_auth_key_release(stcb, chk->auth_keyid, SCTP_SO_LOCKED); 5005179783Srrs SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk); 5006163953Srrs SCTP_DECR_CHK_COUNT(); 5007179783Srrs atomic_subtract_int(&SCTP_BASE_INFO(ipi_free_chunks), 1); 5008163953Srrs asoc->free_chunk_cnt--; 5009169655Srrs /* sa_ignore FREED_MEMORY */ 5010163953Srrs } 5011163953Srrs /* pending send queue SHOULD be empty */ 5012216822Stuexen TAILQ_FOREACH_SAFE(chk, &asoc->send_queue, sctp_next, nchk) { 5013243157Stuexen if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) { 5014243157Stuexen asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--; 5015243157Stuexen#ifdef INVARIANTS 5016243157Stuexen } else { 5017243157Stuexen panic("No chunks on the queues for sid %u.", chk->rec.data.stream_number); 5018243157Stuexen#endif 5019243157Stuexen } 5020216822Stuexen TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next); 5021216822Stuexen if (chk->data) { 5022216822Stuexen if (so) { 5023216822Stuexen /* Still a socket? */ 5024235416Stuexen sctp_ulp_notify(SCTP_NOTIFY_UNSENT_DG_FAIL, stcb, 5025235416Stuexen 0, chk, SCTP_SO_LOCKED); 5026216822Stuexen } 5027163953Srrs if (chk->data) { 5028216822Stuexen sctp_m_freem(chk->data); 5029216822Stuexen chk->data = NULL; 5030163953Srrs } 5031163953Srrs } 5032216822Stuexen if (chk->holds_key_ref) 5033221627Stuexen sctp_auth_key_release(stcb, chk->auth_keyid, SCTP_SO_LOCKED); 5034216822Stuexen if (chk->whoTo) { 5035216822Stuexen sctp_free_remote_addr(chk->whoTo); 5036216822Stuexen chk->whoTo = NULL; 5037216822Stuexen } 5038216822Stuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk); 5039216822Stuexen SCTP_DECR_CHK_COUNT(); 5040216822Stuexen /* sa_ignore FREED_MEMORY */ 5041163953Srrs } 5042163953Srrs /* sent queue SHOULD be empty */ 5043216822Stuexen TAILQ_FOREACH_SAFE(chk, &asoc->sent_queue, sctp_next, nchk) { 5044243157Stuexen if (chk->sent != SCTP_DATAGRAM_NR_ACKED) { 5045242714Stuexen if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) { 5046242714Stuexen asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--; 5047242714Stuexen#ifdef INVARIANTS 5048242714Stuexen } else { 5049242714Stuexen panic("No chunks on the queues for sid %u.", chk->rec.data.stream_number); 5050242714Stuexen#endif 5051242714Stuexen } 5052242714Stuexen } 5053216822Stuexen TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next); 5054216822Stuexen if (chk->data) { 5055216822Stuexen if (so) { 5056216822Stuexen /* Still a socket? */ 5057235416Stuexen sctp_ulp_notify(SCTP_NOTIFY_SENT_DG_FAIL, stcb, 5058235416Stuexen 0, chk, SCTP_SO_LOCKED); 5059163953Srrs } 5060163953Srrs if (chk->data) { 5061163953Srrs sctp_m_freem(chk->data); 5062163953Srrs chk->data = NULL; 5063163953Srrs } 5064163953Srrs } 5065216822Stuexen if (chk->holds_key_ref) 5066221627Stuexen sctp_auth_key_release(stcb, chk->auth_keyid, SCTP_SO_LOCKED); 5067216822Stuexen sctp_free_remote_addr(chk->whoTo); 5068216822Stuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk); 5069216822Stuexen SCTP_DECR_CHK_COUNT(); 5070216822Stuexen /* sa_ignore FREED_MEMORY */ 5071163953Srrs } 5072243157Stuexen#ifdef INVARIANTS 5073243157Stuexen for (i = 0; i < stcb->asoc.streamoutcnt; i++) { 5074243157Stuexen if (stcb->asoc.strmout[i].chunks_on_queues > 0) { 5075243157Stuexen panic("%u chunks left for stream %u.", stcb->asoc.strmout[i].chunks_on_queues, i); 5076243157Stuexen } 5077243157Stuexen } 5078243157Stuexen#endif 5079216822Stuexen /* control queue MAY not be empty */ 5080216822Stuexen TAILQ_FOREACH_SAFE(chk, &asoc->control_send_queue, sctp_next, nchk) { 5081216822Stuexen TAILQ_REMOVE(&asoc->control_send_queue, chk, sctp_next); 5082216822Stuexen if (chk->data) { 5083216822Stuexen sctp_m_freem(chk->data); 5084216822Stuexen chk->data = NULL; 5085216822Stuexen } 5086216822Stuexen if (chk->holds_key_ref) 5087221627Stuexen sctp_auth_key_release(stcb, chk->auth_keyid, SCTP_SO_LOCKED); 5088216822Stuexen sctp_free_remote_addr(chk->whoTo); 5089216822Stuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk); 5090216822Stuexen SCTP_DECR_CHK_COUNT(); 5091216822Stuexen /* sa_ignore FREED_MEMORY */ 5092216822Stuexen } 5093179157Srrs /* ASCONF queue MAY not be empty */ 5094216822Stuexen TAILQ_FOREACH_SAFE(chk, &asoc->asconf_send_queue, sctp_next, nchk) { 5095216822Stuexen TAILQ_REMOVE(&asoc->asconf_send_queue, chk, sctp_next); 5096216822Stuexen if (chk->data) { 5097216822Stuexen sctp_m_freem(chk->data); 5098216822Stuexen chk->data = NULL; 5099179157Srrs } 5100216822Stuexen if (chk->holds_key_ref) 5101221627Stuexen sctp_auth_key_release(stcb, chk->auth_keyid, SCTP_SO_LOCKED); 5102216822Stuexen sctp_free_remote_addr(chk->whoTo); 5103216822Stuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk); 5104216822Stuexen SCTP_DECR_CHK_COUNT(); 5105216822Stuexen /* sa_ignore FREED_MEMORY */ 5106179157Srrs } 5107216822Stuexen TAILQ_FOREACH_SAFE(chk, &asoc->reasmqueue, sctp_next, nchk) { 5108216822Stuexen TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next); 5109216822Stuexen if (chk->data) { 5110216822Stuexen sctp_m_freem(chk->data); 5111216822Stuexen chk->data = NULL; 5112163953Srrs } 5113216822Stuexen if (chk->holds_key_ref) 5114221627Stuexen sctp_auth_key_release(stcb, chk->auth_keyid, SCTP_SO_LOCKED); 5115216822Stuexen sctp_free_remote_addr(chk->whoTo); 5116216822Stuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk); 5117216822Stuexen SCTP_DECR_CHK_COUNT(); 5118216822Stuexen /* sa_ignore FREED_MEMORY */ 5119163953Srrs } 5120216822Stuexen 5121163953Srrs if (asoc->mapping_array) { 5122170091Srrs SCTP_FREE(asoc->mapping_array, SCTP_M_MAP); 5123163953Srrs asoc->mapping_array = NULL; 5124163953Srrs } 5125193089Srrs if (asoc->nr_mapping_array) { 5126193089Srrs SCTP_FREE(asoc->nr_mapping_array, SCTP_M_MAP); 5127193089Srrs asoc->nr_mapping_array = NULL; 5128193089Srrs } 5129163953Srrs /* the stream outs */ 5130163953Srrs if (asoc->strmout) { 5131170091Srrs SCTP_FREE(asoc->strmout, SCTP_M_STRMO); 5132163953Srrs asoc->strmout = NULL; 5133163953Srrs } 5134188854Srrs asoc->strm_realoutsize = asoc->streamoutcnt = 0; 5135163953Srrs if (asoc->strmin) { 5136216822Stuexen struct sctp_queued_to_read *ctl, *nctl; 5137163953Srrs 5138163953Srrs for (i = 0; i < asoc->streamincnt; i++) { 5139216822Stuexen TAILQ_FOREACH_SAFE(ctl, &asoc->strmin[i].inqueue, next, nctl) { 5140216822Stuexen TAILQ_REMOVE(&asoc->strmin[i].inqueue, ctl, next); 5141216822Stuexen sctp_free_remote_addr(ctl->whoFrom); 5142216822Stuexen if (ctl->data) { 5143216822Stuexen sctp_m_freem(ctl->data); 5144216822Stuexen ctl->data = NULL; 5145163953Srrs } 5146216822Stuexen /* 5147216822Stuexen * We don't free the address here since all 5148216822Stuexen * the net's were freed above. 5149216822Stuexen */ 5150216822Stuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), ctl); 5151216822Stuexen SCTP_DECR_READQ_COUNT(); 5152163953Srrs } 5153163953Srrs } 5154170091Srrs SCTP_FREE(asoc->strmin, SCTP_M_STRMI); 5155163953Srrs asoc->strmin = NULL; 5156163953Srrs } 5157163953Srrs asoc->streamincnt = 0; 5158216822Stuexen TAILQ_FOREACH_SAFE(net, &asoc->nets, sctp_next, nnet) { 5159165220Srrs#ifdef INVARIANTS 5160216822Stuexen if (SCTP_BASE_INFO(ipi_count_raddr) == 0) { 5161163953Srrs panic("no net's left alloc'ed, or list points to itself"); 5162216822Stuexen } 5163163953Srrs#endif 5164163953Srrs TAILQ_REMOVE(&asoc->nets, net, sctp_next); 5165163953Srrs sctp_free_remote_addr(net); 5166163953Srrs } 5167216822Stuexen LIST_FOREACH_SAFE(laddr, &asoc->sctp_restricted_addrs, sctp_nxt_addr, naddr) { 5168169655Srrs /* sa_ignore FREED_MEMORY */ 5169167598Srrs sctp_remove_laddr(laddr); 5170163953Srrs } 5171167598Srrs 5172163953Srrs /* pending asconf (address) parameters */ 5173216822Stuexen TAILQ_FOREACH_SAFE(aparam, &asoc->asconf_queue, next, naparam) { 5174169655Srrs /* sa_ignore FREED_MEMORY */ 5175163953Srrs TAILQ_REMOVE(&asoc->asconf_queue, aparam, next); 5176170091Srrs SCTP_FREE(aparam, SCTP_M_ASC_ADDR); 5177163953Srrs } 5178216822Stuexen TAILQ_FOREACH_SAFE(aack, &asoc->asconf_ack_sent, next, naack) { 5179172091Srrs /* sa_ignore FREED_MEMORY */ 5180171990Srrs TAILQ_REMOVE(&asoc->asconf_ack_sent, aack, next); 5181171990Srrs if (aack->data != NULL) { 5182171990Srrs sctp_m_freem(aack->data); 5183171990Srrs } 5184179783Srrs SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asconf_ack), aack); 5185163953Srrs } 5186163953Srrs /* clean up auth stuff */ 5187163953Srrs if (asoc->local_hmacs) 5188163953Srrs sctp_free_hmaclist(asoc->local_hmacs); 5189163953Srrs if (asoc->peer_hmacs) 5190163953Srrs sctp_free_hmaclist(asoc->peer_hmacs); 5191163953Srrs 5192163953Srrs if (asoc->local_auth_chunks) 5193163953Srrs sctp_free_chunklist(asoc->local_auth_chunks); 5194163953Srrs if (asoc->peer_auth_chunks) 5195163953Srrs sctp_free_chunklist(asoc->peer_auth_chunks); 5196163953Srrs 5197163953Srrs sctp_free_authinfo(&asoc->authinfo); 5198163953Srrs 5199216822Stuexen LIST_FOREACH_SAFE(shared_key, &asoc->shared_keys, next, nshared_key) { 5200163953Srrs LIST_REMOVE(shared_key, next); 5201163953Srrs sctp_free_sharedkey(shared_key); 5202169655Srrs /* sa_ignore FREED_MEMORY */ 5203163953Srrs } 5204163953Srrs 5205163953Srrs /* Insert new items here :> */ 5206163953Srrs 5207163953Srrs /* Get rid of LOCK */ 5208258454Stuexen SCTP_TCB_UNLOCK(stcb); 5209163953Srrs SCTP_TCB_LOCK_DESTROY(stcb); 5210163953Srrs SCTP_TCB_SEND_LOCK_DESTROY(stcb); 5211165220Srrs if (from_inpcbfree == SCTP_NORMAL_PROC) { 5212165220Srrs SCTP_INP_INFO_WUNLOCK(); 5213165220Srrs SCTP_INP_RLOCK(inp); 5214165220Srrs } 5215165220Srrs#ifdef SCTP_TRACK_FREED_ASOCS 5216165220Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 5217165220Srrs /* now clean up the tasoc itself */ 5218179783Srrs SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asoc), stcb); 5219165220Srrs SCTP_DECR_ASOC_COUNT(); 5220165220Srrs } else { 5221165220Srrs LIST_INSERT_HEAD(&inp->sctp_asoc_free_list, stcb, sctp_tcblist); 5222165220Srrs } 5223165220Srrs#else 5224179783Srrs SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asoc), stcb); 5225163953Srrs SCTP_DECR_ASOC_COUNT(); 5226165220Srrs#endif 5227165220Srrs if (from_inpcbfree == SCTP_NORMAL_PROC) { 5228163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 5229163953Srrs /* 5230163953Srrs * If its NOT the inp_free calling us AND sctp_close 5231163953Srrs * as been called, we call back... 5232163953Srrs */ 5233163953Srrs SCTP_INP_RUNLOCK(inp); 5234163953Srrs /* 5235163953Srrs * This will start the kill timer (if we are the 5236215039Stuexen * last one) since we hold an increment yet. But 5237215039Stuexen * this is the only safe way to do this since 5238215039Stuexen * otherwise if the socket closes at the same time 5239215039Stuexen * we are here we might collide in the cleanup. 5240163953Srrs */ 5241169380Srrs sctp_inpcb_free(inp, 5242169380Srrs SCTP_FREE_SHOULD_USE_GRACEFUL_CLOSE, 5243169380Srrs SCTP_CALLED_DIRECTLY_NOCMPSET); 5244163953Srrs SCTP_INP_DECR_REF(inp); 5245165220Srrs goto out_of; 5246163953Srrs } else { 5247163953Srrs /* The socket is still open. */ 5248163953Srrs SCTP_INP_DECR_REF(inp); 5249163953Srrs } 5250163953Srrs } 5251165220Srrs if (from_inpcbfree == SCTP_NORMAL_PROC) { 5252165220Srrs SCTP_INP_RUNLOCK(inp); 5253165220Srrs } 5254165220Srrsout_of: 5255163953Srrs /* destroyed the asoc */ 5256163953Srrs#ifdef SCTP_LOG_CLOSING 5257163953Srrs sctp_log_closing(inp, NULL, 11); 5258163953Srrs#endif 5259163953Srrs return (1); 5260163953Srrs} 5261163953Srrs 5262163953Srrs 5263163953Srrs 5264163953Srrs/* 5265163953Srrs * determine if a destination is "reachable" based upon the addresses bound 5266163953Srrs * to the current endpoint (e.g. only v4 or v6 currently bound) 5267163953Srrs */ 5268163953Srrs/* 5269163953Srrs * FIX: if we allow assoc-level bindx(), then this needs to be fixed to use 5270163953Srrs * assoc level v4/v6 flags, as the assoc *may* not have the same address 5271163953Srrs * types bound as its endpoint 5272163953Srrs */ 5273163953Srrsint 5274163953Srrssctp_destination_is_reachable(struct sctp_tcb *stcb, struct sockaddr *destaddr) 5275163953Srrs{ 5276163953Srrs struct sctp_inpcb *inp; 5277163953Srrs int answer; 5278163953Srrs 5279163953Srrs /* 5280163953Srrs * No locks here, the TCB, in all cases is already locked and an 5281163953Srrs * assoc is up. There is either a INP lock by the caller applied (in 5282163953Srrs * asconf case when deleting an address) or NOT in the HB case, 5283163953Srrs * however if HB then the INP increment is up and the INP will not 5284163953Srrs * be removed (on top of the fact that we have a TCB lock). So we 5285163953Srrs * only want to read the sctp_flags, which is either bound-all or 5286163953Srrs * not.. no protection needed since once an assoc is up you can't be 5287163953Srrs * changing your binding. 5288163953Srrs */ 5289163953Srrs inp = stcb->sctp_ep; 5290163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { 5291163953Srrs /* if bound all, destination is not restricted */ 5292163953Srrs /* 5293163953Srrs * RRS: Question during lock work: Is this correct? If you 5294163953Srrs * are bound-all you still might need to obey the V4--V6 5295163953Srrs * flags??? IMO this bound-all stuff needs to be removed! 5296163953Srrs */ 5297163953Srrs return (1); 5298163953Srrs } 5299163953Srrs /* NOTE: all "scope" checks are done when local addresses are added */ 5300221249Stuexen switch (destaddr->sa_family) { 5301238475Stuexen#ifdef INET6 5302221249Stuexen case AF_INET6: 5303163953Srrs answer = inp->ip_inp.inp.inp_vflag & INP_IPV6; 5304221249Stuexen break; 5305238475Stuexen#endif 5306238475Stuexen#ifdef INET 5307221249Stuexen case AF_INET: 5308163953Srrs answer = inp->ip_inp.inp.inp_vflag & INP_IPV4; 5309221249Stuexen break; 5310238475Stuexen#endif 5311221249Stuexen default: 5312163953Srrs /* invalid family, so it's unreachable */ 5313163953Srrs answer = 0; 5314221249Stuexen break; 5315163953Srrs } 5316163953Srrs return (answer); 5317163953Srrs} 5318163953Srrs 5319163953Srrs/* 5320163953Srrs * update the inp_vflags on an endpoint 5321163953Srrs */ 5322163953Srrsstatic void 5323163953Srrssctp_update_ep_vflag(struct sctp_inpcb *inp) 5324163953Srrs{ 5325163953Srrs struct sctp_laddr *laddr; 5326163953Srrs 5327163953Srrs /* first clear the flag */ 5328163953Srrs inp->ip_inp.inp.inp_vflag = 0; 5329163953Srrs /* set the flag based on addresses on the ep list */ 5330163953Srrs LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { 5331163953Srrs if (laddr->ifa == NULL) { 5332169420Srrs SCTPDBG(SCTP_DEBUG_PCB1, "%s: NULL ifa\n", 5333294174Stuexen __func__); 5334163953Srrs continue; 5335163953Srrs } 5336167598Srrs if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED) { 5337163953Srrs continue; 5338163953Srrs } 5339221249Stuexen switch (laddr->ifa->address.sa.sa_family) { 5340221249Stuexen#ifdef INET6 5341221249Stuexen case AF_INET6: 5342163953Srrs inp->ip_inp.inp.inp_vflag |= INP_IPV6; 5343221249Stuexen break; 5344221249Stuexen#endif 5345221249Stuexen#ifdef INET 5346221249Stuexen case AF_INET: 5347163953Srrs inp->ip_inp.inp.inp_vflag |= INP_IPV4; 5348221249Stuexen break; 5349221249Stuexen#endif 5350221249Stuexen default: 5351221249Stuexen break; 5352163953Srrs } 5353163953Srrs } 5354163953Srrs} 5355163953Srrs 5356163953Srrs/* 5357163953Srrs * Add the address to the endpoint local address list There is nothing to be 5358163953Srrs * done if we are bound to all addresses 5359163953Srrs */ 5360169420Srrsvoid 5361167598Srrssctp_add_local_addr_ep(struct sctp_inpcb *inp, struct sctp_ifa *ifa, uint32_t action) 5362163953Srrs{ 5363163953Srrs struct sctp_laddr *laddr; 5364169420Srrs int fnd, error = 0; 5365163953Srrs 5366163953Srrs fnd = 0; 5367163953Srrs 5368163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { 5369163953Srrs /* You are already bound to all. You have it already */ 5370169420Srrs return; 5371163953Srrs } 5372221249Stuexen#ifdef INET6 5373167598Srrs if (ifa->address.sa.sa_family == AF_INET6) { 5374167598Srrs if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) { 5375167598Srrs /* Can't bind a non-useable addr. */ 5376169420Srrs return; 5377167598Srrs } 5378163953Srrs } 5379221249Stuexen#endif 5380163953Srrs /* first, is it already present? */ 5381163953Srrs LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { 5382163953Srrs if (laddr->ifa == ifa) { 5383163953Srrs fnd = 1; 5384163953Srrs break; 5385163953Srrs } 5386163953Srrs } 5387163953Srrs 5388167598Srrs if (fnd == 0) { 5389167598Srrs /* Not in the ep list */ 5390167598Srrs error = sctp_insert_laddr(&inp->sctp_addr_list, ifa, action); 5391163953Srrs if (error != 0) 5392169420Srrs return; 5393163953Srrs inp->laddr_count++; 5394163953Srrs /* update inp_vflag flags */ 5395221249Stuexen switch (ifa->address.sa.sa_family) { 5396221249Stuexen#ifdef INET6 5397221249Stuexen case AF_INET6: 5398163953Srrs inp->ip_inp.inp.inp_vflag |= INP_IPV6; 5399221249Stuexen break; 5400221249Stuexen#endif 5401238475Stuexen#ifdef INET 5402221249Stuexen case AF_INET: 5403163953Srrs inp->ip_inp.inp.inp_vflag |= INP_IPV4; 5404221249Stuexen break; 5405221249Stuexen#endif 5406221249Stuexen default: 5407221249Stuexen break; 5408163953Srrs } 5409163953Srrs } 5410169420Srrs return; 5411163953Srrs} 5412163953Srrs 5413163953Srrs 5414163953Srrs/* 5415163953Srrs * select a new (hopefully reachable) destination net (should only be used 5416163953Srrs * when we deleted an ep addr that is the only usable source address to reach 5417163953Srrs * the destination net) 5418163953Srrs */ 5419163953Srrsstatic void 5420163953Srrssctp_select_primary_destination(struct sctp_tcb *stcb) 5421163953Srrs{ 5422163953Srrs struct sctp_nets *net; 5423163953Srrs 5424163953Srrs TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 5425163953Srrs /* for now, we'll just pick the first reachable one we find */ 5426163953Srrs if (net->dest_state & SCTP_ADDR_UNCONFIRMED) 5427163953Srrs continue; 5428163953Srrs if (sctp_destination_is_reachable(stcb, 5429163953Srrs (struct sockaddr *)&net->ro._l_addr)) { 5430163953Srrs /* found a reachable destination */ 5431163953Srrs stcb->asoc.primary_destination = net; 5432163953Srrs } 5433163953Srrs } 5434163953Srrs /* I can't there from here! ...we're gonna die shortly... */ 5435163953Srrs} 5436163953Srrs 5437163953Srrs 5438163953Srrs/* 5439296052Stuexen * Delete the address from the endpoint local address list. There is nothing 5440163953Srrs * to be done if we are bound to all addresses 5441163953Srrs */ 5442169420Srrsvoid 5443167598Srrssctp_del_local_addr_ep(struct sctp_inpcb *inp, struct sctp_ifa *ifa) 5444163953Srrs{ 5445163953Srrs struct sctp_laddr *laddr; 5446163953Srrs int fnd; 5447163953Srrs 5448163953Srrs fnd = 0; 5449163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { 5450163953Srrs /* You are already bound to all. You have it already */ 5451169420Srrs return; 5452163953Srrs } 5453163953Srrs LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { 5454163953Srrs if (laddr->ifa == ifa) { 5455163953Srrs fnd = 1; 5456163953Srrs break; 5457163953Srrs } 5458163953Srrs } 5459163953Srrs if (fnd && (inp->laddr_count < 2)) { 5460163953Srrs /* can't delete unless there are at LEAST 2 addresses */ 5461169420Srrs return; 5462163953Srrs } 5463167598Srrs if (fnd) { 5464163953Srrs /* 5465163953Srrs * clean up any use of this address go through our 5466163953Srrs * associations and clear any last_used_address that match 5467163953Srrs * this one for each assoc, see if a new primary_destination 5468163953Srrs * is needed 5469163953Srrs */ 5470163953Srrs struct sctp_tcb *stcb; 5471163953Srrs 5472163953Srrs /* clean up "next_addr_touse" */ 5473163953Srrs if (inp->next_addr_touse == laddr) 5474163953Srrs /* delete this address */ 5475163953Srrs inp->next_addr_touse = NULL; 5476163953Srrs 5477163953Srrs /* clean up "last_used_address" */ 5478163953Srrs LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { 5479167598Srrs struct sctp_nets *net; 5480167598Srrs 5481167598Srrs SCTP_TCB_LOCK(stcb); 5482163953Srrs if (stcb->asoc.last_used_address == laddr) 5483163953Srrs /* delete this address */ 5484163953Srrs stcb->asoc.last_used_address = NULL; 5485167598Srrs /* 5486167598Srrs * Now spin through all the nets and purge any ref 5487167598Srrs * to laddr 5488167598Srrs */ 5489167598Srrs TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 5490296052Stuexen if (net->ro._s_addr == laddr->ifa) { 5491167598Srrs /* Yep, purge src address selected */ 5492169352Srrs sctp_rtentry_t *rt; 5493167598Srrs 5494167598Srrs /* delete this address if cached */ 5495167598Srrs rt = net->ro.ro_rt; 5496167598Srrs if (rt != NULL) { 5497167598Srrs RTFREE(rt); 5498167598Srrs net->ro.ro_rt = NULL; 5499167598Srrs } 5500167598Srrs sctp_free_ifa(net->ro._s_addr); 5501167598Srrs net->ro._s_addr = NULL; 5502167598Srrs net->src_addr_selected = 0; 5503167598Srrs } 5504167598Srrs } 5505167598Srrs SCTP_TCB_UNLOCK(stcb); 5506163953Srrs } /* for each tcb */ 5507163953Srrs /* remove it from the ep list */ 5508163953Srrs sctp_remove_laddr(laddr); 5509163953Srrs inp->laddr_count--; 5510163953Srrs /* update inp_vflag flags */ 5511163953Srrs sctp_update_ep_vflag(inp); 5512163953Srrs } 5513169420Srrs return; 5514163953Srrs} 5515163953Srrs 5516163953Srrs/* 5517171572Srrs * Add the address to the TCB local address restricted list. 5518171572Srrs * This is a "pending" address list (eg. addresses waiting for an 5519171572Srrs * ASCONF-ACK response) and cannot be used as a valid source address. 5520163953Srrs */ 5521169420Srrsvoid 5522171572Srrssctp_add_local_addr_restricted(struct sctp_tcb *stcb, struct sctp_ifa *ifa) 5523163953Srrs{ 5524163953Srrs struct sctp_laddr *laddr; 5525167598Srrs struct sctpladdr *list; 5526163953Srrs 5527163953Srrs /* 5528167598Srrs * Assumes TCB is locked.. and possibly the INP. May need to 5529163953Srrs * confirm/fix that if we need it and is not the case. 5530163953Srrs */ 5531167598Srrs list = &stcb->asoc.sctp_restricted_addrs; 5532167598Srrs 5533221249Stuexen#ifdef INET6 5534167598Srrs if (ifa->address.sa.sa_family == AF_INET6) { 5535167598Srrs if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) { 5536163953Srrs /* Can't bind a non-existent addr. */ 5537169420Srrs return; 5538167598Srrs } 5539163953Srrs } 5540221249Stuexen#endif 5541163953Srrs /* does the address already exist? */ 5542167598Srrs LIST_FOREACH(laddr, list, sctp_nxt_addr) { 5543163953Srrs if (laddr->ifa == ifa) { 5544169420Srrs return; 5545163953Srrs } 5546163953Srrs } 5547163953Srrs 5548163953Srrs /* add to the list */ 5549169420Srrs (void)sctp_insert_laddr(list, ifa, 0); 5550169420Srrs return; 5551163953Srrs} 5552163953Srrs 5553163953Srrs/* 5554171572Srrs * Remove a local address from the TCB local address restricted list 5555163953Srrs */ 5556169420Srrsvoid 5557171572Srrssctp_del_local_addr_restricted(struct sctp_tcb *stcb, struct sctp_ifa *ifa) 5558163953Srrs{ 5559163953Srrs struct sctp_inpcb *inp; 5560163953Srrs struct sctp_laddr *laddr; 5561163953Srrs 5562163953Srrs /* 5563163953Srrs * This is called by asconf work. It is assumed that a) The TCB is 5564163953Srrs * locked and b) The INP is locked. This is true in as much as I can 5565163953Srrs * trace through the entry asconf code where I did these locks. 5566163953Srrs * Again, the ASCONF code is a bit different in that it does lock 5567163953Srrs * the INP during its work often times. This must be since we don't 5568163953Srrs * want other proc's looking up things while what they are looking 5569163953Srrs * up is changing :-D 5570163953Srrs */ 5571163953Srrs 5572163953Srrs inp = stcb->sctp_ep; 5573163953Srrs /* if subset bound and don't allow ASCONF's, can't delete last */ 5574163953Srrs if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) && 5575171477Srrs sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_ASCONF)) { 5576171477Srrs if (stcb->sctp_ep->laddr_count < 2) { 5577163953Srrs /* can't delete last address */ 5578169420Srrs return; 5579163953Srrs } 5580163953Srrs } 5581167598Srrs LIST_FOREACH(laddr, &stcb->asoc.sctp_restricted_addrs, sctp_nxt_addr) { 5582163953Srrs /* remove the address if it exists */ 5583163953Srrs if (laddr->ifa == NULL) 5584163953Srrs continue; 5585163953Srrs if (laddr->ifa == ifa) { 5586163953Srrs sctp_remove_laddr(laddr); 5587169420Srrs return; 5588163953Srrs } 5589163953Srrs } 5590163953Srrs 5591163953Srrs /* address not found! */ 5592169420Srrs return; 5593163953Srrs} 5594163953Srrs 5595163953Srrs/* 5596163953Srrs * Temporarily remove for __APPLE__ until we use the Tiger equivalents 5597163953Srrs */ 5598163953Srrs/* sysctl */ 5599163953Srrsstatic int sctp_max_number_of_assoc = SCTP_MAX_NUM_OF_ASOC; 5600163953Srrsstatic int sctp_scale_up_for_address = SCTP_SCALE_FOR_ADDR; 5601163953Srrs 5602218211Srrs 5603218211Srrs 5604218211Srrs#if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP) 5605218211Srrsstruct sctp_mcore_ctrl *sctp_mcore_workers = NULL; 5606218269Srrsint *sctp_cpuarry = NULL; 5607163953Srrsvoid 5608218211Srrssctp_queue_to_mcore(struct mbuf *m, int off, int cpu_to_use) 5609218211Srrs{ 5610218211Srrs /* Queue a packet to a processor for the specified core */ 5611218211Srrs struct sctp_mcore_queue *qent; 5612218211Srrs struct sctp_mcore_ctrl *wkq; 5613218211Srrs int need_wake = 0; 5614218211Srrs 5615218211Srrs if (sctp_mcore_workers == NULL) { 5616218211Srrs /* Something went way bad during setup */ 5617218211Srrs sctp_input_with_port(m, off, 0); 5618218211Srrs return; 5619218211Srrs } 5620218211Srrs SCTP_MALLOC(qent, struct sctp_mcore_queue *, 5621218211Srrs (sizeof(struct sctp_mcore_queue)), 5622218211Srrs SCTP_M_MCORE); 5623218211Srrs if (qent == NULL) { 5624218211Srrs /* This is trouble */ 5625218211Srrs sctp_input_with_port(m, off, 0); 5626218211Srrs return; 5627218211Srrs } 5628218211Srrs qent->vn = curvnet; 5629218211Srrs qent->m = m; 5630218211Srrs qent->off = off; 5631218211Srrs qent->v6 = 0; 5632218211Srrs wkq = &sctp_mcore_workers[cpu_to_use]; 5633218211Srrs SCTP_MCORE_QLOCK(wkq); 5634218211Srrs 5635218211Srrs TAILQ_INSERT_TAIL(&wkq->que, qent, next); 5636218211Srrs if (wkq->running == 0) { 5637218211Srrs need_wake = 1; 5638218211Srrs } 5639218211Srrs SCTP_MCORE_QUNLOCK(wkq); 5640218211Srrs if (need_wake) { 5641218211Srrs wakeup(&wkq->running); 5642218211Srrs } 5643218211Srrs} 5644218211Srrs 5645218211Srrsstatic void 5646218211Srrssctp_mcore_thread(void *arg) 5647218211Srrs{ 5648218211Srrs 5649218211Srrs struct sctp_mcore_ctrl *wkq; 5650218211Srrs struct sctp_mcore_queue *qent; 5651218211Srrs 5652218211Srrs wkq = (struct sctp_mcore_ctrl *)arg; 5653218211Srrs struct mbuf *m; 5654218211Srrs int off, v6; 5655218211Srrs 5656218211Srrs /* Wait for first tickle */ 5657218211Srrs SCTP_MCORE_LOCK(wkq); 5658218211Srrs wkq->running = 0; 5659218211Srrs msleep(&wkq->running, 5660218211Srrs &wkq->core_mtx, 5661218211Srrs 0, "wait for pkt", 0); 5662218211Srrs SCTP_MCORE_UNLOCK(wkq); 5663218211Srrs 5664218211Srrs /* Bind to our cpu */ 5665218211Srrs thread_lock(curthread); 5666218211Srrs sched_bind(curthread, wkq->cpuid); 5667218211Srrs thread_unlock(curthread); 5668218211Srrs 5669218211Srrs /* Now lets start working */ 5670218211Srrs SCTP_MCORE_LOCK(wkq); 5671218211Srrs /* Now grab lock and go */ 5672228653Stuexen for (;;) { 5673218211Srrs SCTP_MCORE_QLOCK(wkq); 5674218211Srrsskip_sleep: 5675218211Srrs wkq->running = 1; 5676218211Srrs qent = TAILQ_FIRST(&wkq->que); 5677218211Srrs if (qent) { 5678218211Srrs TAILQ_REMOVE(&wkq->que, qent, next); 5679218211Srrs SCTP_MCORE_QUNLOCK(wkq); 5680218211Srrs CURVNET_SET(qent->vn); 5681218211Srrs m = qent->m; 5682218211Srrs off = qent->off; 5683218211Srrs v6 = qent->v6; 5684218211Srrs SCTP_FREE(qent, SCTP_M_MCORE); 5685218211Srrs if (v6 == 0) { 5686218211Srrs sctp_input_with_port(m, off, 0); 5687218211Srrs } else { 5688234995Stuexen SCTP_PRINTF("V6 not yet supported\n"); 5689218211Srrs sctp_m_freem(m); 5690218211Srrs } 5691218211Srrs CURVNET_RESTORE(); 5692218211Srrs SCTP_MCORE_QLOCK(wkq); 5693218211Srrs } 5694218211Srrs wkq->running = 0; 5695218211Srrs if (!TAILQ_EMPTY(&wkq->que)) { 5696218211Srrs goto skip_sleep; 5697218211Srrs } 5698218211Srrs SCTP_MCORE_QUNLOCK(wkq); 5699218211Srrs msleep(&wkq->running, 5700218211Srrs &wkq->core_mtx, 5701218211Srrs 0, "wait for pkt", 0); 5702228907Stuexen } 5703218211Srrs} 5704218211Srrs 5705218211Srrsstatic void 5706218211Srrssctp_startup_mcore_threads(void) 5707218211Srrs{ 5708218269Srrs int i, cpu; 5709218211Srrs 5710218269Srrs if (mp_ncpus == 1) 5711218211Srrs return; 5712218211Srrs 5713218269Srrs if (sctp_mcore_workers != NULL) { 5714218269Srrs /* 5715218269Srrs * Already been here in some previous vnet? 5716218269Srrs */ 5717218269Srrs return; 5718218269Srrs } 5719218211Srrs SCTP_MALLOC(sctp_mcore_workers, struct sctp_mcore_ctrl *, 5720218269Srrs ((mp_maxid + 1) * sizeof(struct sctp_mcore_ctrl)), 5721218211Srrs SCTP_M_MCORE); 5722218211Srrs if (sctp_mcore_workers == NULL) { 5723218211Srrs /* TSNH I hope */ 5724218211Srrs return; 5725218211Srrs } 5726218269Srrs memset(sctp_mcore_workers, 0, ((mp_maxid + 1) * 5727218211Srrs sizeof(struct sctp_mcore_ctrl))); 5728218211Srrs /* Init the structures */ 5729218269Srrs for (i = 0; i <= mp_maxid; i++) { 5730218211Srrs TAILQ_INIT(&sctp_mcore_workers[i].que); 5731218211Srrs SCTP_MCORE_LOCK_INIT(&sctp_mcore_workers[i]); 5732218211Srrs SCTP_MCORE_QLOCK_INIT(&sctp_mcore_workers[i]); 5733218211Srrs sctp_mcore_workers[i].cpuid = i; 5734218211Srrs } 5735218269Srrs if (sctp_cpuarry == NULL) { 5736218269Srrs SCTP_MALLOC(sctp_cpuarry, int *, 5737218269Srrs (mp_ncpus * sizeof(int)), 5738218269Srrs SCTP_M_MCORE); 5739218269Srrs i = 0; 5740218269Srrs CPU_FOREACH(cpu) { 5741218269Srrs sctp_cpuarry[i] = cpu; 5742218269Srrs i++; 5743218269Srrs } 5744218269Srrs } 5745218211Srrs /* Now start them all */ 5746218269Srrs CPU_FOREACH(cpu) { 5747218211Srrs (void)kproc_create(sctp_mcore_thread, 5748218269Srrs (void *)&sctp_mcore_workers[cpu], 5749218269Srrs &sctp_mcore_workers[cpu].thread_proc, 5750218211Srrs RFPROC, 5751218211Srrs SCTP_KTHREAD_PAGES, 5752218211Srrs SCTP_MCORE_NAME); 5753218211Srrs 5754218211Srrs } 5755218211Srrs} 5756218211Srrs 5757218211Srrs#endif 5758218211Srrs 5759218211Srrsvoid 5760163953Srrssctp_pcb_init() 5761163953Srrs{ 5762163953Srrs /* 5763163953Srrs * SCTP initialization for the PCB structures should be called by 5764163953Srrs * the sctp_init() funciton. 5765163953Srrs */ 5766163953Srrs int i; 5767172091Srrs struct timeval tv; 5768163953Srrs 5769179783Srrs if (SCTP_BASE_VAR(sctp_pcb_initialized) != 0) { 5770163953Srrs /* error I was called twice */ 5771163953Srrs return; 5772163953Srrs } 5773179783Srrs SCTP_BASE_VAR(sctp_pcb_initialized) = 1; 5774163953Srrs 5775172157Srrs#if defined(SCTP_LOCAL_TRACE_BUF) 5776179783Srrs bzero(&SCTP_BASE_SYSCTL(sctp_log), sizeof(struct sctp_log)); 5777172157Srrs#endif 5778218219Srrs#if defined(__FreeBSD__) && defined(SMP) && defined(SCTP_USE_PERCPU_STAT) 5779218219Srrs SCTP_MALLOC(SCTP_BASE_STATS, struct sctpstat *, 5780218269Srrs ((mp_maxid + 1) * sizeof(struct sctpstat)), 5781218219Srrs SCTP_M_MCORE); 5782218219Srrs#endif 5783172091Srrs (void)SCTP_GETTIME_TIMEVAL(&tv); 5784205629Srrs#if defined(__FreeBSD__) && defined(SMP) && defined(SCTP_USE_PERCPU_STAT) 5785218269Srrs bzero(SCTP_BASE_STATS, (sizeof(struct sctpstat) * (mp_maxid + 1))); 5786205629Srrs SCTP_BASE_STATS[PCPU_GET(cpuid)].sctps_discontinuitytime.tv_sec = (uint32_t) tv.tv_sec; 5787205629Srrs SCTP_BASE_STATS[PCPU_GET(cpuid)].sctps_discontinuitytime.tv_usec = (uint32_t) tv.tv_usec; 5788205629Srrs#else 5789218219Srrs bzero(&SCTP_BASE_STATS, sizeof(struct sctpstat)); 5790179783Srrs SCTP_BASE_STAT(sctps_discontinuitytime).tv_sec = (uint32_t) tv.tv_sec; 5791179783Srrs SCTP_BASE_STAT(sctps_discontinuitytime).tv_usec = (uint32_t) tv.tv_usec; 5792205629Srrs#endif 5793163953Srrs /* init the empty list of (All) Endpoints */ 5794179783Srrs LIST_INIT(&SCTP_BASE_INFO(listhead)); 5795163953Srrs 5796163953Srrs 5797163953Srrs /* init the hash table of endpoints */ 5798179783Srrs TUNABLE_INT_FETCH("net.inet.sctp.tcbhashsize", &SCTP_BASE_SYSCTL(sctp_hashtblsize)); 5799179783Srrs TUNABLE_INT_FETCH("net.inet.sctp.pcbhashsize", &SCTP_BASE_SYSCTL(sctp_pcbtblsize)); 5800179783Srrs TUNABLE_INT_FETCH("net.inet.sctp.chunkscale", &SCTP_BASE_SYSCTL(sctp_chunkscale)); 5801179783Srrs SCTP_BASE_INFO(sctp_asochash) = SCTP_HASH_INIT((SCTP_BASE_SYSCTL(sctp_hashtblsize) * 31), 5802179783Srrs &SCTP_BASE_INFO(hashasocmark)); 5803179783Srrs SCTP_BASE_INFO(sctp_ephash) = SCTP_HASH_INIT(SCTP_BASE_SYSCTL(sctp_hashtblsize), 5804179783Srrs &SCTP_BASE_INFO(hashmark)); 5805179783Srrs SCTP_BASE_INFO(sctp_tcpephash) = SCTP_HASH_INIT(SCTP_BASE_SYSCTL(sctp_hashtblsize), 5806179783Srrs &SCTP_BASE_INFO(hashtcpmark)); 5807179783Srrs SCTP_BASE_INFO(hashtblsize) = SCTP_BASE_SYSCTL(sctp_hashtblsize); 5808163953Srrs 5809163953Srrs 5810179783Srrs SCTP_BASE_INFO(sctp_vrfhash) = SCTP_HASH_INIT(SCTP_SIZE_OF_VRF_HASH, 5811179783Srrs &SCTP_BASE_INFO(hashvrfmark)); 5812167598Srrs 5813179783Srrs SCTP_BASE_INFO(vrf_ifn_hash) = SCTP_HASH_INIT(SCTP_VRF_IFN_HASH_SIZE, 5814179783Srrs &SCTP_BASE_INFO(vrf_ifn_hashmark)); 5815163953Srrs /* init the zones */ 5816163953Srrs /* 5817163953Srrs * FIX ME: Should check for NULL returns, but if it does fail we are 5818163953Srrs * doomed to panic anyways... add later maybe. 5819163953Srrs */ 5820179783Srrs SCTP_ZONE_INIT(SCTP_BASE_INFO(ipi_zone_ep), "sctp_ep", 5821163953Srrs sizeof(struct sctp_inpcb), maxsockets); 5822163953Srrs 5823179783Srrs SCTP_ZONE_INIT(SCTP_BASE_INFO(ipi_zone_asoc), "sctp_asoc", 5824163953Srrs sizeof(struct sctp_tcb), sctp_max_number_of_assoc); 5825163953Srrs 5826179783Srrs SCTP_ZONE_INIT(SCTP_BASE_INFO(ipi_zone_laddr), "sctp_laddr", 5827163953Srrs sizeof(struct sctp_laddr), 5828163953Srrs (sctp_max_number_of_assoc * sctp_scale_up_for_address)); 5829163953Srrs 5830179783Srrs SCTP_ZONE_INIT(SCTP_BASE_INFO(ipi_zone_net), "sctp_raddr", 5831163953Srrs sizeof(struct sctp_nets), 5832163953Srrs (sctp_max_number_of_assoc * sctp_scale_up_for_address)); 5833163953Srrs 5834179783Srrs SCTP_ZONE_INIT(SCTP_BASE_INFO(ipi_zone_chunk), "sctp_chunk", 5835163953Srrs sizeof(struct sctp_tmit_chunk), 5836179783Srrs (sctp_max_number_of_assoc * SCTP_BASE_SYSCTL(sctp_chunkscale))); 5837163953Srrs 5838179783Srrs SCTP_ZONE_INIT(SCTP_BASE_INFO(ipi_zone_readq), "sctp_readq", 5839163953Srrs sizeof(struct sctp_queued_to_read), 5840179783Srrs (sctp_max_number_of_assoc * SCTP_BASE_SYSCTL(sctp_chunkscale))); 5841163953Srrs 5842179783Srrs SCTP_ZONE_INIT(SCTP_BASE_INFO(ipi_zone_strmoq), "sctp_stream_msg_out", 5843163953Srrs sizeof(struct sctp_stream_queue_pending), 5844179783Srrs (sctp_max_number_of_assoc * SCTP_BASE_SYSCTL(sctp_chunkscale))); 5845163953Srrs 5846179783Srrs SCTP_ZONE_INIT(SCTP_BASE_INFO(ipi_zone_asconf), "sctp_asconf", 5847179157Srrs sizeof(struct sctp_asconf), 5848179783Srrs (sctp_max_number_of_assoc * SCTP_BASE_SYSCTL(sctp_chunkscale))); 5849179157Srrs 5850179783Srrs SCTP_ZONE_INIT(SCTP_BASE_INFO(ipi_zone_asconf_ack), "sctp_asconf_ack", 5851171990Srrs sizeof(struct sctp_asconf_ack), 5852179783Srrs (sctp_max_number_of_assoc * SCTP_BASE_SYSCTL(sctp_chunkscale))); 5853171990Srrs 5854171990Srrs 5855163953Srrs /* Master Lock INIT for info structure */ 5856163953Srrs SCTP_INP_INFO_LOCK_INIT(); 5857163953Srrs SCTP_STATLOG_INIT_LOCK(); 5858165220Srrs 5859163953Srrs SCTP_IPI_COUNT_INIT(); 5860163953Srrs SCTP_IPI_ADDR_INIT(); 5861170091Srrs#ifdef SCTP_PACKET_LOGGING 5862170091Srrs SCTP_IP_PKTLOG_INIT(); 5863170091Srrs#endif 5864179783Srrs LIST_INIT(&SCTP_BASE_INFO(addr_wq)); 5865163953Srrs 5866208160Srrs SCTP_WQ_ADDR_INIT(); 5867163953Srrs /* not sure if we need all the counts */ 5868179783Srrs SCTP_BASE_INFO(ipi_count_ep) = 0; 5869163953Srrs /* assoc/tcb zone info */ 5870179783Srrs SCTP_BASE_INFO(ipi_count_asoc) = 0; 5871163953Srrs /* local addrlist zone info */ 5872179783Srrs SCTP_BASE_INFO(ipi_count_laddr) = 0; 5873163953Srrs /* remote addrlist zone info */ 5874179783Srrs SCTP_BASE_INFO(ipi_count_raddr) = 0; 5875163953Srrs /* chunk info */ 5876179783Srrs SCTP_BASE_INFO(ipi_count_chunk) = 0; 5877163953Srrs 5878163953Srrs /* socket queue zone info */ 5879179783Srrs SCTP_BASE_INFO(ipi_count_readq) = 0; 5880163953Srrs 5881163953Srrs /* stream out queue cont */ 5882179783Srrs SCTP_BASE_INFO(ipi_count_strmoq) = 0; 5883163953Srrs 5884179783Srrs SCTP_BASE_INFO(ipi_free_strmoq) = 0; 5885179783Srrs SCTP_BASE_INFO(ipi_free_chunks) = 0; 5886163953Srrs 5887179783Srrs SCTP_OS_TIMER_INIT(&SCTP_BASE_INFO(addr_wq_timer.timer)); 5888163953Srrs 5889163953Srrs /* Init the TIMEWAIT list */ 5890184883Srrs for (i = 0; i < SCTP_STACK_VTAG_HASH_SIZE; i++) { 5891201523Stuexen LIST_INIT(&SCTP_BASE_INFO(vtag_timewait)[i]); 5892163953Srrs } 5893167598Srrs sctp_startup_iterator(); 5894167598Srrs 5895218211Srrs#if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP) 5896218211Srrs sctp_startup_mcore_threads(); 5897218211Srrs#endif 5898218211Srrs 5899167598Srrs /* 5900167598Srrs * INIT the default VRF which for BSD is the only one, other O/S's 5901167598Srrs * may have more. But initially they must start with one and then 5902167598Srrs * add the VRF's as addresses are added. 5903167598Srrs */ 5904167598Srrs sctp_init_vrf_list(SCTP_DEFAULT_VRF); 5905163953Srrs} 5906163953Srrs 5907179157Srrs/* 5908179783Srrs * Assumes that the SCTP_BASE_INFO() lock is NOT held. 5909179157Srrs */ 5910179157Srrsvoid 5911179157Srrssctp_pcb_finish(void) 5912179157Srrs{ 5913179157Srrs struct sctp_vrflist *vrf_bucket; 5914216822Stuexen struct sctp_vrf *vrf, *nvrf; 5915216822Stuexen struct sctp_ifn *ifn, *nifn; 5916216822Stuexen struct sctp_ifa *ifa, *nifa; 5917179783Srrs struct sctpvtaghead *chain; 5918179783Srrs struct sctp_tagblock *twait_block, *prev_twait_block; 5919216822Stuexen struct sctp_laddr *wi, *nwi; 5920179783Srrs int i; 5921258454Stuexen struct sctp_iterator *it, *nit; 5922163953Srrs 5923296052Stuexen if (SCTP_BASE_VAR(sctp_pcb_initialized) == 0) { 5924296052Stuexen SCTP_PRINTF("%s: race condition on teardown.\n", __func__); 5925296052Stuexen return; 5926296052Stuexen } 5927296052Stuexen SCTP_BASE_VAR(sctp_pcb_initialized) = 0; 5928208160Srrs /* 5929258454Stuexen * In FreeBSD the iterator thread never exits but we do clean up. 5930258454Stuexen * The only way FreeBSD reaches here is if we have VRF's but we 5931258454Stuexen * still add the ifdef to make it compile on old versions. 5932208160Srrs */ 5933296052Stuexenretry: 5934258454Stuexen SCTP_IPI_ITERATOR_WQ_LOCK(); 5935296052Stuexen /* 5936296052Stuexen * sctp_iterator_worker() might be working on an it entry without 5937296052Stuexen * holding the lock. We won't find it on the list either and 5938296052Stuexen * continue and free/destroy it. While holding the lock, spin, to 5939296052Stuexen * avoid the race condition as sctp_iterator_worker() will have to 5940296052Stuexen * wait to re-aquire the lock. 5941296052Stuexen */ 5942296052Stuexen if (sctp_it_ctl.iterator_running != 0 || sctp_it_ctl.cur_it != NULL) { 5943296052Stuexen SCTP_IPI_ITERATOR_WQ_UNLOCK(); 5944296052Stuexen SCTP_PRINTF("%s: Iterator running while we held the lock. Retry. " 5945296052Stuexen "cur_it=%p\n", __func__, sctp_it_ctl.cur_it); 5946296052Stuexen DELAY(10); 5947296052Stuexen goto retry; 5948296052Stuexen } 5949258454Stuexen TAILQ_FOREACH_SAFE(it, &sctp_it_ctl.iteratorhead, sctp_nxt_itr, nit) { 5950258454Stuexen if (it->vn != curvnet) { 5951258454Stuexen continue; 5952208160Srrs } 5953258454Stuexen TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, it, sctp_nxt_itr); 5954258454Stuexen if (it->function_atend != NULL) { 5955258454Stuexen (*it->function_atend) (it->pointer, it->val); 5956208160Srrs } 5957258454Stuexen SCTP_FREE(it, SCTP_M_ITER); 5958208160Srrs } 5959258454Stuexen SCTP_IPI_ITERATOR_WQ_UNLOCK(); 5960258454Stuexen SCTP_ITERATOR_LOCK(); 5961258454Stuexen if ((sctp_it_ctl.cur_it) && 5962258454Stuexen (sctp_it_ctl.cur_it->vn == curvnet)) { 5963258454Stuexen sctp_it_ctl.iterator_flags |= SCTP_ITERATOR_STOP_CUR_IT; 5964258454Stuexen } 5965258454Stuexen SCTP_ITERATOR_UNLOCK(); 5966296052Stuexen SCTP_OS_TIMER_STOP_DRAIN(&SCTP_BASE_INFO(addr_wq_timer.timer)); 5967208160Srrs SCTP_WQ_ADDR_LOCK(); 5968216822Stuexen LIST_FOREACH_SAFE(wi, &SCTP_BASE_INFO(addr_wq), sctp_nxt_addr, nwi) { 5969199373Stuexen LIST_REMOVE(wi, sctp_nxt_addr); 5970199373Stuexen SCTP_DECR_LADDR_COUNT(); 5971271746Stuexen if (wi->action == SCTP_DEL_IP_ADDRESS) { 5972271746Stuexen SCTP_FREE(wi->ifa, SCTP_M_IFA); 5973271746Stuexen } 5974199373Stuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_laddr), wi); 5975199373Stuexen } 5976208160Srrs SCTP_WQ_ADDR_UNLOCK(); 5977199373Stuexen 5978179157Srrs /* 5979179157Srrs * free the vrf/ifn/ifa lists and hashes (be sure address monitor is 5980179157Srrs * destroyed first). 5981179157Srrs */ 5982179783Srrs vrf_bucket = &SCTP_BASE_INFO(sctp_vrfhash)[(SCTP_DEFAULT_VRFID & SCTP_BASE_INFO(hashvrfmark))]; 5983216822Stuexen LIST_FOREACH_SAFE(vrf, vrf_bucket, next_vrf, nvrf) { 5984216822Stuexen LIST_FOREACH_SAFE(ifn, &vrf->ifnlist, next_ifn, nifn) { 5985216822Stuexen LIST_FOREACH_SAFE(ifa, &ifn->ifalist, next_ifa, nifa) { 5986179157Srrs /* free the ifa */ 5987179157Srrs LIST_REMOVE(ifa, next_bucket); 5988179157Srrs LIST_REMOVE(ifa, next_ifa); 5989179157Srrs SCTP_FREE(ifa, SCTP_M_IFA); 5990179157Srrs } 5991179157Srrs /* free the ifn */ 5992179157Srrs LIST_REMOVE(ifn, next_bucket); 5993179157Srrs LIST_REMOVE(ifn, next_ifn); 5994179157Srrs SCTP_FREE(ifn, SCTP_M_IFN); 5995179157Srrs } 5996179157Srrs SCTP_HASH_FREE(vrf->vrf_addr_hash, vrf->vrf_addr_hashmark); 5997179157Srrs /* free the vrf */ 5998179157Srrs LIST_REMOVE(vrf, next_vrf); 5999179157Srrs SCTP_FREE(vrf, SCTP_M_VRF); 6000179157Srrs } 6001179157Srrs /* free the vrf hashes */ 6002179783Srrs SCTP_HASH_FREE(SCTP_BASE_INFO(sctp_vrfhash), SCTP_BASE_INFO(hashvrfmark)); 6003179783Srrs SCTP_HASH_FREE(SCTP_BASE_INFO(vrf_ifn_hash), SCTP_BASE_INFO(vrf_ifn_hashmark)); 6004179157Srrs 6005179783Srrs /* 6006179783Srrs * free the TIMEWAIT list elements malloc'd in the function 6007179783Srrs * sctp_add_vtag_to_timewait()... 6008179783Srrs */ 6009184883Srrs for (i = 0; i < SCTP_STACK_VTAG_HASH_SIZE; i++) { 6010179783Srrs chain = &SCTP_BASE_INFO(vtag_timewait)[i]; 6011199437Stuexen if (!LIST_EMPTY(chain)) { 6012179783Srrs prev_twait_block = NULL; 6013179783Srrs LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) { 6014179783Srrs if (prev_twait_block) { 6015179783Srrs SCTP_FREE(prev_twait_block, SCTP_M_TIMW); 6016179783Srrs } 6017179783Srrs prev_twait_block = twait_block; 6018179783Srrs } 6019179783Srrs SCTP_FREE(prev_twait_block, SCTP_M_TIMW); 6020179783Srrs } 6021179783Srrs } 6022179783Srrs 6023179157Srrs /* free the locks and mutexes */ 6024179157Srrs#ifdef SCTP_PACKET_LOGGING 6025179157Srrs SCTP_IP_PKTLOG_DESTROY(); 6026179157Srrs#endif 6027179157Srrs SCTP_IPI_ADDR_DESTROY(); 6028179157Srrs SCTP_STATLOG_DESTROY(); 6029179157Srrs SCTP_INP_INFO_LOCK_DESTROY(); 6030179157Srrs 6031208160Srrs SCTP_WQ_ADDR_DESTROY(); 6032208160Srrs 6033296052Stuexen /* Get rid of other stuff too. */ 6034296052Stuexen if (SCTP_BASE_INFO(sctp_asochash) != NULL) 6035296052Stuexen SCTP_HASH_FREE(SCTP_BASE_INFO(sctp_asochash), SCTP_BASE_INFO(hashasocmark)); 6036296052Stuexen if (SCTP_BASE_INFO(sctp_ephash) != NULL) 6037296052Stuexen SCTP_HASH_FREE(SCTP_BASE_INFO(sctp_ephash), SCTP_BASE_INFO(hashmark)); 6038296052Stuexen if (SCTP_BASE_INFO(sctp_tcpephash) != NULL) 6039296052Stuexen SCTP_HASH_FREE(SCTP_BASE_INFO(sctp_tcpephash), SCTP_BASE_INFO(hashtcpmark)); 6040296052Stuexen 6041179783Srrs SCTP_ZONE_DESTROY(SCTP_BASE_INFO(ipi_zone_ep)); 6042179783Srrs SCTP_ZONE_DESTROY(SCTP_BASE_INFO(ipi_zone_asoc)); 6043179783Srrs SCTP_ZONE_DESTROY(SCTP_BASE_INFO(ipi_zone_laddr)); 6044179783Srrs SCTP_ZONE_DESTROY(SCTP_BASE_INFO(ipi_zone_net)); 6045179783Srrs SCTP_ZONE_DESTROY(SCTP_BASE_INFO(ipi_zone_chunk)); 6046179783Srrs SCTP_ZONE_DESTROY(SCTP_BASE_INFO(ipi_zone_readq)); 6047179783Srrs SCTP_ZONE_DESTROY(SCTP_BASE_INFO(ipi_zone_strmoq)); 6048179783Srrs SCTP_ZONE_DESTROY(SCTP_BASE_INFO(ipi_zone_asconf)); 6049179783Srrs SCTP_ZONE_DESTROY(SCTP_BASE_INFO(ipi_zone_asconf_ack)); 6050218219Srrs#if defined(__FreeBSD__) && defined(SMP) && defined(SCTP_USE_PERCPU_STAT) 6051218219Srrs SCTP_FREE(SCTP_BASE_STATS, SCTP_M_MCORE); 6052218219Srrs#endif 6053179157Srrs} 6054179157Srrs 6055179157Srrs 6056163953Srrsint 6057163953Srrssctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, 6058237715Stuexen int offset, int limit, 6059237715Stuexen struct sockaddr *src, struct sockaddr *dst, 6060163953Srrs struct sockaddr *altsa) 6061163953Srrs{ 6062163953Srrs /* 6063163953Srrs * grub through the INIT pulling addresses and loading them to the 6064163953Srrs * nets structure in the asoc. The from address in the mbuf should 6065163953Srrs * also be loaded (if it is not already). This routine can be called 6066163953Srrs * with either INIT or INIT-ACK's as long as the m points to the IP 6067163953Srrs * packet and the offset points to the beginning of the parameters. 6068163953Srrs */ 6069228907Stuexen struct sctp_inpcb *inp; 6070216822Stuexen struct sctp_nets *net, *nnet, *net_tmp; 6071163953Srrs struct sctp_paramhdr *phdr, parm_buf; 6072163953Srrs struct sctp_tcb *stcb_tmp; 6073163953Srrs uint16_t ptype, plen; 6074163953Srrs struct sockaddr *sa; 6075166675Srrs uint8_t random_store[SCTP_PARAM_BUFFER_SIZE]; 6076168124Srrs struct sctp_auth_random *p_random = NULL; 6077163953Srrs uint16_t random_len = 0; 6078166675Srrs uint8_t hmacs_store[SCTP_PARAM_BUFFER_SIZE]; 6079163953Srrs struct sctp_auth_hmac_algo *hmacs = NULL; 6080163953Srrs uint16_t hmacs_len = 0; 6081171990Srrs uint8_t saw_asconf = 0; 6082171990Srrs uint8_t saw_asconf_ack = 0; 6083166675Srrs uint8_t chunks_store[SCTP_PARAM_BUFFER_SIZE]; 6084163953Srrs struct sctp_auth_chunk_list *chunks = NULL; 6085163953Srrs uint16_t num_chunks = 0; 6086163953Srrs sctp_key_t *new_key; 6087163953Srrs uint32_t keylen; 6088163953Srrs int got_random = 0, got_hmacs = 0, got_chklist = 0; 6089270362Stuexen uint8_t peer_supports_ecn; 6090270362Stuexen uint8_t peer_supports_prsctp; 6091270362Stuexen uint8_t peer_supports_auth; 6092270362Stuexen uint8_t peer_supports_asconf; 6093270362Stuexen uint8_t peer_supports_asconf_ack; 6094270362Stuexen uint8_t peer_supports_reconfig; 6095270362Stuexen uint8_t peer_supports_nrsack; 6096270362Stuexen uint8_t peer_supports_pktdrop; 6097163953Srrs 6098221249Stuexen#ifdef INET 6099221249Stuexen struct sockaddr_in sin; 6100221249Stuexen 6101221249Stuexen#endif 6102221249Stuexen#ifdef INET6 6103221249Stuexen struct sockaddr_in6 sin6; 6104221249Stuexen 6105221249Stuexen#endif 6106221249Stuexen 6107163953Srrs /* First get the destination address setup too. */ 6108221249Stuexen#ifdef INET 6109163953Srrs memset(&sin, 0, sizeof(sin)); 6110163953Srrs sin.sin_family = AF_INET; 6111163953Srrs sin.sin_len = sizeof(sin); 6112163953Srrs sin.sin_port = stcb->rport; 6113221249Stuexen#endif 6114221249Stuexen#ifdef INET6 6115221249Stuexen memset(&sin6, 0, sizeof(sin6)); 6116163953Srrs sin6.sin6_family = AF_INET6; 6117163953Srrs sin6.sin6_len = sizeof(struct sockaddr_in6); 6118163953Srrs sin6.sin6_port = stcb->rport; 6119221249Stuexen#endif 6120237715Stuexen if (altsa) { 6121237715Stuexen sa = altsa; 6122237715Stuexen } else { 6123237715Stuexen sa = src; 6124163953Srrs } 6125270362Stuexen peer_supports_ecn = 0; 6126270362Stuexen peer_supports_prsctp = 0; 6127270362Stuexen peer_supports_auth = 0; 6128270362Stuexen peer_supports_asconf = 0; 6129270362Stuexen peer_supports_reconfig = 0; 6130270362Stuexen peer_supports_nrsack = 0; 6131270362Stuexen peer_supports_pktdrop = 0; 6132163953Srrs TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 6133163953Srrs /* mark all addresses that we have currently on the list */ 6134163953Srrs net->dest_state |= SCTP_ADDR_NOT_IN_ASSOC; 6135163953Srrs } 6136163953Srrs /* does the source address already exist? if so skip it */ 6137228907Stuexen inp = stcb->sctp_ep; 6138163996Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 6139237715Stuexen stcb_tmp = sctp_findassociation_ep_addr(&inp, sa, &net_tmp, dst, stcb); 6140163996Srrs atomic_add_int(&stcb->asoc.refcnt, -1); 6141163953Srrs 6142163953Srrs if ((stcb_tmp == NULL && inp == stcb->sctp_ep) || inp == NULL) { 6143163953Srrs /* we must add the source address */ 6144163953Srrs /* no scope set here since we have a tcb already. */ 6145221249Stuexen switch (sa->sa_family) { 6146221249Stuexen#ifdef INET 6147221249Stuexen case AF_INET: 6148246595Stuexen if (stcb->asoc.scope.ipv4_addr_legal) { 6149224641Stuexen if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_2)) { 6150221249Stuexen return (-1); 6151221249Stuexen } 6152163953Srrs } 6153221249Stuexen break; 6154221249Stuexen#endif 6155221249Stuexen#ifdef INET6 6156221249Stuexen case AF_INET6: 6157246595Stuexen if (stcb->asoc.scope.ipv6_addr_legal) { 6158224641Stuexen if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_3)) { 6159221249Stuexen return (-2); 6160221249Stuexen } 6161163953Srrs } 6162221249Stuexen break; 6163221249Stuexen#endif 6164221249Stuexen default: 6165221249Stuexen break; 6166163953Srrs } 6167163953Srrs } else { 6168163953Srrs if (net_tmp != NULL && stcb_tmp == stcb) { 6169163953Srrs net_tmp->dest_state &= ~SCTP_ADDR_NOT_IN_ASSOC; 6170163953Srrs } else if (stcb_tmp != stcb) { 6171163953Srrs /* It belongs to another association? */ 6172170931Srrs if (stcb_tmp) 6173170931Srrs SCTP_TCB_UNLOCK(stcb_tmp); 6174163953Srrs return (-3); 6175163953Srrs } 6176163953Srrs } 6177163953Srrs if (stcb->asoc.state == 0) { 6178163953Srrs /* the assoc was freed? */ 6179163953Srrs return (-4); 6180163953Srrs } 6181163953Srrs /* now we must go through each of the params. */ 6182163953Srrs phdr = sctp_get_next_param(m, offset, &parm_buf, sizeof(parm_buf)); 6183163953Srrs while (phdr) { 6184163953Srrs ptype = ntohs(phdr->param_type); 6185163953Srrs plen = ntohs(phdr->param_length); 6186163953Srrs /* 6187234995Stuexen * SCTP_PRINTF("ptype => %0x, plen => %d\n", 6188234995Stuexen * (uint32_t)ptype, (int)plen); 6189163953Srrs */ 6190163953Srrs if (offset + plen > limit) { 6191163953Srrs break; 6192163953Srrs } 6193163953Srrs if (plen == 0) { 6194163953Srrs break; 6195163953Srrs } 6196221249Stuexen#ifdef INET 6197163953Srrs if (ptype == SCTP_IPV4_ADDRESS) { 6198246595Stuexen if (stcb->asoc.scope.ipv4_addr_legal) { 6199163953Srrs struct sctp_ipv4addr_param *p4, p4_buf; 6200163953Srrs 6201163953Srrs /* ok get the v4 address and check/add */ 6202163953Srrs phdr = sctp_get_next_param(m, offset, 6203188067Srrs (struct sctp_paramhdr *)&p4_buf, 6204188067Srrs sizeof(p4_buf)); 6205163953Srrs if (plen != sizeof(struct sctp_ipv4addr_param) || 6206163953Srrs phdr == NULL) { 6207163953Srrs return (-5); 6208163953Srrs } 6209163953Srrs p4 = (struct sctp_ipv4addr_param *)phdr; 6210163953Srrs sin.sin_addr.s_addr = p4->addr; 6211212099Stuexen if (IN_MULTICAST(ntohl(sin.sin_addr.s_addr))) { 6212169208Srrs /* Skip multi-cast addresses */ 6213169208Srrs goto next_param; 6214169208Srrs } 6215169352Srrs if ((sin.sin_addr.s_addr == INADDR_BROADCAST) || 6216169352Srrs (sin.sin_addr.s_addr == INADDR_ANY)) { 6217169352Srrs goto next_param; 6218169352Srrs } 6219163953Srrs sa = (struct sockaddr *)&sin; 6220163953Srrs inp = stcb->sctp_ep; 6221163996Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 6222163953Srrs stcb_tmp = sctp_findassociation_ep_addr(&inp, sa, &net, 6223237715Stuexen dst, stcb); 6224163996Srrs atomic_add_int(&stcb->asoc.refcnt, -1); 6225163953Srrs 6226163953Srrs if ((stcb_tmp == NULL && inp == stcb->sctp_ep) || 6227163953Srrs inp == NULL) { 6228163953Srrs /* we must add the source address */ 6229163953Srrs /* 6230163953Srrs * no scope set since we have a tcb 6231163953Srrs * already 6232163953Srrs */ 6233163953Srrs 6234163953Srrs /* 6235163953Srrs * we must validate the state again 6236163953Srrs * here 6237163953Srrs */ 6238181054Srrs add_it_now: 6239163953Srrs if (stcb->asoc.state == 0) { 6240163953Srrs /* the assoc was freed? */ 6241163953Srrs return (-7); 6242163953Srrs } 6243224641Stuexen if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_4)) { 6244163953Srrs return (-8); 6245163953Srrs } 6246163953Srrs } else if (stcb_tmp == stcb) { 6247163953Srrs if (stcb->asoc.state == 0) { 6248163953Srrs /* the assoc was freed? */ 6249163953Srrs return (-10); 6250163953Srrs } 6251163953Srrs if (net != NULL) { 6252163953Srrs /* clear flag */ 6253163953Srrs net->dest_state &= 6254163953Srrs ~SCTP_ADDR_NOT_IN_ASSOC; 6255163953Srrs } 6256163953Srrs } else { 6257163953Srrs /* 6258163953Srrs * strange, address is in another 6259163953Srrs * assoc? straighten out locks. 6260163953Srrs */ 6261181054Srrs if (stcb_tmp) { 6262181054Srrs if (SCTP_GET_STATE(&stcb_tmp->asoc) & SCTP_STATE_COOKIE_WAIT) { 6263294145Stuexen struct mbuf *op_err; 6264294145Stuexen char msg[SCTP_DIAG_INFO_LEN]; 6265294145Stuexen 6266181054Srrs /* 6267181054Srrs * in setup state we 6268181054Srrs * abort this guy 6269181054Srrs */ 6270294145Stuexen snprintf(msg, sizeof(msg), 6271294174Stuexen "%s:%d at %s", __FILE__, __LINE__, __func__); 6272294145Stuexen op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 6273294145Stuexen msg); 6274181054Srrs sctp_abort_an_association(stcb_tmp->sctp_ep, 6275294145Stuexen stcb_tmp, op_err, 6276294145Stuexen SCTP_SO_NOT_LOCKED); 6277181054Srrs goto add_it_now; 6278181054Srrs } 6279171531Srrs SCTP_TCB_UNLOCK(stcb_tmp); 6280181054Srrs } 6281163953Srrs if (stcb->asoc.state == 0) { 6282163953Srrs /* the assoc was freed? */ 6283163953Srrs return (-12); 6284163953Srrs } 6285163953Srrs return (-13); 6286163953Srrs } 6287163953Srrs } 6288221249Stuexen } else 6289221249Stuexen#endif 6290221249Stuexen#ifdef INET6 6291221249Stuexen if (ptype == SCTP_IPV6_ADDRESS) { 6292246595Stuexen if (stcb->asoc.scope.ipv6_addr_legal) { 6293163953Srrs /* ok get the v6 address and check/add */ 6294163953Srrs struct sctp_ipv6addr_param *p6, p6_buf; 6295163953Srrs 6296163953Srrs phdr = sctp_get_next_param(m, offset, 6297188067Srrs (struct sctp_paramhdr *)&p6_buf, 6298188067Srrs sizeof(p6_buf)); 6299163953Srrs if (plen != sizeof(struct sctp_ipv6addr_param) || 6300163953Srrs phdr == NULL) { 6301163953Srrs return (-14); 6302163953Srrs } 6303163953Srrs p6 = (struct sctp_ipv6addr_param *)phdr; 6304163953Srrs memcpy((caddr_t)&sin6.sin6_addr, p6->addr, 6305163953Srrs sizeof(p6->addr)); 6306169208Srrs if (IN6_IS_ADDR_MULTICAST(&sin6.sin6_addr)) { 6307169208Srrs /* Skip multi-cast addresses */ 6308169208Srrs goto next_param; 6309169208Srrs } 6310169208Srrs if (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr)) { 6311169208Srrs /* 6312169208Srrs * Link local make no sense without 6313169208Srrs * scope 6314169208Srrs */ 6315169208Srrs goto next_param; 6316169208Srrs } 6317163953Srrs sa = (struct sockaddr *)&sin6; 6318163953Srrs inp = stcb->sctp_ep; 6319163996Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 6320163953Srrs stcb_tmp = sctp_findassociation_ep_addr(&inp, sa, &net, 6321237715Stuexen dst, stcb); 6322163996Srrs atomic_add_int(&stcb->asoc.refcnt, -1); 6323188067Srrs if (stcb_tmp == NULL && 6324188067Srrs (inp == stcb->sctp_ep || inp == NULL)) { 6325163953Srrs /* 6326163953Srrs * we must validate the state again 6327163953Srrs * here 6328163953Srrs */ 6329181054Srrs add_it_now6: 6330163953Srrs if (stcb->asoc.state == 0) { 6331163953Srrs /* the assoc was freed? */ 6332163953Srrs return (-16); 6333163953Srrs } 6334163953Srrs /* 6335163953Srrs * we must add the address, no scope 6336163953Srrs * set 6337163953Srrs */ 6338224641Stuexen if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_5)) { 6339163953Srrs return (-17); 6340163953Srrs } 6341163953Srrs } else if (stcb_tmp == stcb) { 6342163953Srrs /* 6343163953Srrs * we must validate the state again 6344163953Srrs * here 6345163953Srrs */ 6346163953Srrs if (stcb->asoc.state == 0) { 6347163953Srrs /* the assoc was freed? */ 6348163953Srrs return (-19); 6349163953Srrs } 6350163953Srrs if (net != NULL) { 6351163953Srrs /* clear flag */ 6352163953Srrs net->dest_state &= 6353163953Srrs ~SCTP_ADDR_NOT_IN_ASSOC; 6354163953Srrs } 6355163953Srrs } else { 6356163953Srrs /* 6357163953Srrs * strange, address is in another 6358163953Srrs * assoc? straighten out locks. 6359163953Srrs */ 6360294145Stuexen if (stcb_tmp) { 6361181054Srrs if (SCTP_GET_STATE(&stcb_tmp->asoc) & SCTP_STATE_COOKIE_WAIT) { 6362294145Stuexen struct mbuf *op_err; 6363294145Stuexen char msg[SCTP_DIAG_INFO_LEN]; 6364294145Stuexen 6365181054Srrs /* 6366181054Srrs * in setup state we 6367181054Srrs * abort this guy 6368181054Srrs */ 6369294145Stuexen snprintf(msg, sizeof(msg), 6370294174Stuexen "%s:%d at %s", __FILE__, __LINE__, __func__); 6371294145Stuexen op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 6372294145Stuexen msg); 6373181054Srrs sctp_abort_an_association(stcb_tmp->sctp_ep, 6374294145Stuexen stcb_tmp, op_err, 6375294145Stuexen SCTP_SO_NOT_LOCKED); 6376181054Srrs goto add_it_now6; 6377181054Srrs } 6378294145Stuexen SCTP_TCB_UNLOCK(stcb_tmp); 6379294145Stuexen } 6380163953Srrs if (stcb->asoc.state == 0) { 6381163953Srrs /* the assoc was freed? */ 6382163953Srrs return (-21); 6383163953Srrs } 6384163953Srrs return (-22); 6385163953Srrs } 6386163953Srrs } 6387221249Stuexen } else 6388221249Stuexen#endif 6389221249Stuexen if (ptype == SCTP_ECN_CAPABLE) { 6390270362Stuexen peer_supports_ecn = 1; 6391163953Srrs } else if (ptype == SCTP_ULP_ADAPTATION) { 6392163953Srrs if (stcb->asoc.state != SCTP_STATE_OPEN) { 6393163953Srrs struct sctp_adaptation_layer_indication ai, 6394163953Srrs *aip; 6395163953Srrs 6396163953Srrs phdr = sctp_get_next_param(m, offset, 6397163953Srrs (struct sctp_paramhdr *)&ai, sizeof(ai)); 6398163953Srrs aip = (struct sctp_adaptation_layer_indication *)phdr; 6399169378Srrs if (aip) { 6400171990Srrs stcb->asoc.peers_adaptation = ntohl(aip->indication); 6401171990Srrs stcb->asoc.adaptation_needed = 1; 6402169378Srrs } 6403163953Srrs } 6404163953Srrs } else if (ptype == SCTP_SET_PRIM_ADDR) { 6405163953Srrs struct sctp_asconf_addr_param lstore, *fee; 6406163953Srrs int lptype; 6407163953Srrs struct sockaddr *lsa = NULL; 6408163953Srrs 6409221249Stuexen#ifdef INET 6410221249Stuexen struct sctp_asconf_addrv4_param *fii; 6411221249Stuexen 6412221249Stuexen#endif 6413221249Stuexen 6414270362Stuexen if (stcb->asoc.asconf_supported == 0) { 6415270362Stuexen return (-100); 6416270362Stuexen } 6417163953Srrs if (plen > sizeof(lstore)) { 6418163953Srrs return (-23); 6419163953Srrs } 6420163953Srrs phdr = sctp_get_next_param(m, offset, 6421188067Srrs (struct sctp_paramhdr *)&lstore, 6422188067Srrs min(plen, sizeof(lstore))); 6423163953Srrs if (phdr == NULL) { 6424163953Srrs return (-24); 6425163953Srrs } 6426163953Srrs fee = (struct sctp_asconf_addr_param *)phdr; 6427163953Srrs lptype = ntohs(fee->addrp.ph.param_type); 6428221249Stuexen switch (lptype) { 6429221249Stuexen#ifdef INET 6430221249Stuexen case SCTP_IPV4_ADDRESS: 6431163953Srrs if (plen != 6432163953Srrs sizeof(struct sctp_asconf_addrv4_param)) { 6433169420Srrs SCTP_PRINTF("Sizeof setprim in init/init ack not %d but %d - ignored\n", 6434163953Srrs (int)sizeof(struct sctp_asconf_addrv4_param), 6435163953Srrs plen); 6436163953Srrs } else { 6437163953Srrs fii = (struct sctp_asconf_addrv4_param *)fee; 6438163953Srrs sin.sin_addr.s_addr = fii->addrp.addr; 6439163953Srrs lsa = (struct sockaddr *)&sin; 6440163953Srrs } 6441221249Stuexen break; 6442221249Stuexen#endif 6443221249Stuexen#ifdef INET6 6444221249Stuexen case SCTP_IPV6_ADDRESS: 6445163953Srrs if (plen != 6446163953Srrs sizeof(struct sctp_asconf_addr_param)) { 6447169420Srrs SCTP_PRINTF("Sizeof setprim (v6) in init/init ack not %d but %d - ignored\n", 6448163953Srrs (int)sizeof(struct sctp_asconf_addr_param), 6449163953Srrs plen); 6450163953Srrs } else { 6451163953Srrs memcpy(sin6.sin6_addr.s6_addr, 6452163953Srrs fee->addrp.addr, 6453163953Srrs sizeof(fee->addrp.addr)); 6454163953Srrs lsa = (struct sockaddr *)&sin6; 6455163953Srrs } 6456221249Stuexen break; 6457221249Stuexen#endif 6458221249Stuexen default: 6459221249Stuexen break; 6460163953Srrs } 6461163953Srrs if (lsa) { 6462169420Srrs (void)sctp_set_primary_addr(stcb, sa, NULL); 6463163953Srrs } 6464185694Srrs } else if (ptype == SCTP_HAS_NAT_SUPPORT) { 6465185694Srrs stcb->asoc.peer_supports_nat = 1; 6466163953Srrs } else if (ptype == SCTP_PRSCTP_SUPPORTED) { 6467163953Srrs /* Peer supports pr-sctp */ 6468270362Stuexen peer_supports_prsctp = 1; 6469163953Srrs } else if (ptype == SCTP_SUPPORTED_CHUNK_EXT) { 6470163953Srrs /* A supported extension chunk */ 6471163953Srrs struct sctp_supported_chunk_types_param *pr_supported; 6472166675Srrs uint8_t local_store[SCTP_PARAM_BUFFER_SIZE]; 6473163953Srrs int num_ent, i; 6474163953Srrs 6475163953Srrs phdr = sctp_get_next_param(m, offset, 6476169208Srrs (struct sctp_paramhdr *)&local_store, min(sizeof(local_store), plen)); 6477163953Srrs if (phdr == NULL) { 6478163953Srrs return (-25); 6479163953Srrs } 6480163953Srrs pr_supported = (struct sctp_supported_chunk_types_param *)phdr; 6481163953Srrs num_ent = plen - sizeof(struct sctp_paramhdr); 6482163953Srrs for (i = 0; i < num_ent; i++) { 6483163953Srrs switch (pr_supported->chunk_types[i]) { 6484163953Srrs case SCTP_ASCONF: 6485270362Stuexen peer_supports_asconf = 1; 6486283704Stuexen break; 6487163953Srrs case SCTP_ASCONF_ACK: 6488270362Stuexen peer_supports_asconf_ack = 1; 6489163953Srrs break; 6490163953Srrs case SCTP_FORWARD_CUM_TSN: 6491270362Stuexen peer_supports_prsctp = 1; 6492163953Srrs break; 6493163953Srrs case SCTP_PACKET_DROPPED: 6494270362Stuexen peer_supports_pktdrop = 1; 6495163953Srrs break; 6496190689Srrs case SCTP_NR_SELECTIVE_ACK: 6497270362Stuexen peer_supports_nrsack = 1; 6498190689Srrs break; 6499163953Srrs case SCTP_STREAM_RESET: 6500270362Stuexen peer_supports_reconfig = 1; 6501163953Srrs break; 6502163953Srrs case SCTP_AUTHENTICATION: 6503270362Stuexen peer_supports_auth = 1; 6504163953Srrs break; 6505163953Srrs default: 6506163953Srrs /* one I have not learned yet */ 6507163953Srrs break; 6508163953Srrs 6509163953Srrs } 6510163953Srrs } 6511163953Srrs } else if (ptype == SCTP_RANDOM) { 6512166675Srrs if (plen > sizeof(random_store)) 6513163953Srrs break; 6514163953Srrs if (got_random) { 6515163953Srrs /* already processed a RANDOM */ 6516163953Srrs goto next_param; 6517163953Srrs } 6518163953Srrs phdr = sctp_get_next_param(m, offset, 6519166675Srrs (struct sctp_paramhdr *)random_store, 6520169208Srrs min(sizeof(random_store), plen)); 6521163953Srrs if (phdr == NULL) 6522163953Srrs return (-26); 6523168124Srrs p_random = (struct sctp_auth_random *)phdr; 6524168124Srrs random_len = plen - sizeof(*p_random); 6525163953Srrs /* enforce the random length */ 6526163953Srrs if (random_len != SCTP_AUTH_RANDOM_SIZE_REQUIRED) { 6527169420Srrs SCTPDBG(SCTP_DEBUG_AUTH1, "SCTP: invalid RANDOM len\n"); 6528163953Srrs return (-27); 6529163953Srrs } 6530163953Srrs got_random = 1; 6531163953Srrs } else if (ptype == SCTP_HMAC_LIST) { 6532271750Stuexen uint16_t num_hmacs; 6533271750Stuexen uint16_t i; 6534163953Srrs 6535166675Srrs if (plen > sizeof(hmacs_store)) 6536163953Srrs break; 6537163953Srrs if (got_hmacs) { 6538163953Srrs /* already processed a HMAC list */ 6539163953Srrs goto next_param; 6540163953Srrs } 6541163953Srrs phdr = sctp_get_next_param(m, offset, 6542166675Srrs (struct sctp_paramhdr *)hmacs_store, 6543169208Srrs min(plen, sizeof(hmacs_store))); 6544163953Srrs if (phdr == NULL) 6545163953Srrs return (-28); 6546163953Srrs hmacs = (struct sctp_auth_hmac_algo *)phdr; 6547163953Srrs hmacs_len = plen - sizeof(*hmacs); 6548163953Srrs num_hmacs = hmacs_len / sizeof(hmacs->hmac_ids[0]); 6549163953Srrs /* validate the hmac list */ 6550163953Srrs if (sctp_verify_hmac_param(hmacs, num_hmacs)) { 6551163953Srrs return (-29); 6552163953Srrs } 6553163953Srrs if (stcb->asoc.peer_hmacs != NULL) 6554163953Srrs sctp_free_hmaclist(stcb->asoc.peer_hmacs); 6555163953Srrs stcb->asoc.peer_hmacs = sctp_alloc_hmaclist(num_hmacs); 6556163953Srrs if (stcb->asoc.peer_hmacs != NULL) { 6557163953Srrs for (i = 0; i < num_hmacs; i++) { 6558169378Srrs (void)sctp_auth_add_hmacid(stcb->asoc.peer_hmacs, 6559163953Srrs ntohs(hmacs->hmac_ids[i])); 6560163953Srrs } 6561163953Srrs } 6562163953Srrs got_hmacs = 1; 6563163953Srrs } else if (ptype == SCTP_CHUNK_LIST) { 6564163953Srrs int i; 6565163953Srrs 6566166675Srrs if (plen > sizeof(chunks_store)) 6567163953Srrs break; 6568163953Srrs if (got_chklist) { 6569163953Srrs /* already processed a Chunks list */ 6570163953Srrs goto next_param; 6571163953Srrs } 6572163953Srrs phdr = sctp_get_next_param(m, offset, 6573166675Srrs (struct sctp_paramhdr *)chunks_store, 6574169208Srrs min(plen, sizeof(chunks_store))); 6575163953Srrs if (phdr == NULL) 6576163953Srrs return (-30); 6577163953Srrs chunks = (struct sctp_auth_chunk_list *)phdr; 6578163953Srrs num_chunks = plen - sizeof(*chunks); 6579163953Srrs if (stcb->asoc.peer_auth_chunks != NULL) 6580163953Srrs sctp_clear_chunklist(stcb->asoc.peer_auth_chunks); 6581163953Srrs else 6582163953Srrs stcb->asoc.peer_auth_chunks = sctp_alloc_chunklist(); 6583163953Srrs for (i = 0; i < num_chunks; i++) { 6584169378Srrs (void)sctp_auth_add_chunk(chunks->chunk_types[i], 6585163953Srrs stcb->asoc.peer_auth_chunks); 6586171990Srrs /* record asconf/asconf-ack if listed */ 6587171990Srrs if (chunks->chunk_types[i] == SCTP_ASCONF) 6588171990Srrs saw_asconf = 1; 6589171990Srrs if (chunks->chunk_types[i] == SCTP_ASCONF_ACK) 6590171990Srrs saw_asconf_ack = 1; 6591171990Srrs 6592163953Srrs } 6593163953Srrs got_chklist = 1; 6594163953Srrs } else if ((ptype == SCTP_HEARTBEAT_INFO) || 6595163953Srrs (ptype == SCTP_STATE_COOKIE) || 6596163953Srrs (ptype == SCTP_UNRECOG_PARAM) || 6597163953Srrs (ptype == SCTP_COOKIE_PRESERVE) || 6598163953Srrs (ptype == SCTP_SUPPORTED_ADDRTYPE) || 6599163953Srrs (ptype == SCTP_ADD_IP_ADDRESS) || 6600163953Srrs (ptype == SCTP_DEL_IP_ADDRESS) || 6601163953Srrs (ptype == SCTP_ERROR_CAUSE_IND) || 6602163953Srrs (ptype == SCTP_SUCCESS_REPORT)) { 6603163953Srrs /* don't care */ ; 6604163953Srrs } else { 6605163953Srrs if ((ptype & 0x8000) == 0x0000) { 6606163953Srrs /* 6607163953Srrs * must stop processing the rest of the 6608163953Srrs * param's. Any report bits were handled 6609163953Srrs * with the call to 6610163953Srrs * sctp_arethere_unrecognized_parameters() 6611163953Srrs * when the INIT or INIT-ACK was first seen. 6612163953Srrs */ 6613163953Srrs break; 6614163953Srrs } 6615163953Srrs } 6616188067Srrs 6617163953Srrsnext_param: 6618163953Srrs offset += SCTP_SIZE32(plen); 6619163953Srrs if (offset >= limit) { 6620163953Srrs break; 6621163953Srrs } 6622163953Srrs phdr = sctp_get_next_param(m, offset, &parm_buf, 6623163953Srrs sizeof(parm_buf)); 6624163953Srrs } 6625163953Srrs /* Now check to see if we need to purge any addresses */ 6626216822Stuexen TAILQ_FOREACH_SAFE(net, &stcb->asoc.nets, sctp_next, nnet) { 6627163953Srrs if ((net->dest_state & SCTP_ADDR_NOT_IN_ASSOC) == 6628163953Srrs SCTP_ADDR_NOT_IN_ASSOC) { 6629163953Srrs /* This address has been removed from the asoc */ 6630163953Srrs /* remove and free it */ 6631163953Srrs stcb->asoc.numnets--; 6632163953Srrs TAILQ_REMOVE(&stcb->asoc.nets, net, sctp_next); 6633163953Srrs sctp_free_remote_addr(net); 6634163953Srrs if (net == stcb->asoc.primary_destination) { 6635163953Srrs stcb->asoc.primary_destination = NULL; 6636163953Srrs sctp_select_primary_destination(stcb); 6637163953Srrs } 6638163953Srrs } 6639163953Srrs } 6640270362Stuexen if ((stcb->asoc.ecn_supported == 1) && 6641270362Stuexen (peer_supports_ecn == 0)) { 6642270362Stuexen stcb->asoc.ecn_supported = 0; 6643270362Stuexen } 6644270362Stuexen if ((stcb->asoc.prsctp_supported == 1) && 6645270362Stuexen (peer_supports_prsctp == 0)) { 6646270362Stuexen stcb->asoc.prsctp_supported = 0; 6647270362Stuexen } 6648270362Stuexen if ((stcb->asoc.auth_supported == 1) && 6649270362Stuexen ((peer_supports_auth == 0) || 6650270362Stuexen (got_random == 0) || (got_hmacs == 0))) { 6651270362Stuexen stcb->asoc.auth_supported = 0; 6652270362Stuexen } 6653270362Stuexen if ((stcb->asoc.asconf_supported == 1) && 6654270362Stuexen ((peer_supports_asconf == 0) || (peer_supports_asconf_ack == 0) || 6655270362Stuexen (stcb->asoc.auth_supported == 0) || 6656270362Stuexen (saw_asconf == 0) || (saw_asconf_ack == 0))) { 6657270362Stuexen stcb->asoc.asconf_supported = 0; 6658270362Stuexen } 6659270362Stuexen if ((stcb->asoc.reconfig_supported == 1) && 6660270362Stuexen (peer_supports_reconfig == 0)) { 6661270362Stuexen stcb->asoc.reconfig_supported = 0; 6662270362Stuexen } 6663270362Stuexen if ((stcb->asoc.nrsack_supported == 1) && 6664270362Stuexen (peer_supports_nrsack == 0)) { 6665270362Stuexen stcb->asoc.nrsack_supported = 0; 6666270362Stuexen } 6667270362Stuexen if ((stcb->asoc.pktdrop_supported == 1) && 6668270362Stuexen (peer_supports_pktdrop == 0)) { 6669270362Stuexen stcb->asoc.pktdrop_supported = 0; 6670270362Stuexen } 6671163953Srrs /* validate authentication required parameters */ 6672270362Stuexen if ((peer_supports_auth == 0) && (got_chklist == 1)) { 6673168124Srrs /* peer does not support auth but sent a chunks list? */ 6674168124Srrs return (-31); 6675168124Srrs } 6676270362Stuexen if ((peer_supports_asconf == 1) && (peer_supports_auth == 0)) { 6677168124Srrs /* peer supports asconf but not auth? */ 6678168124Srrs return (-32); 6679270362Stuexen } else if ((peer_supports_asconf == 1) && 6680270362Stuexen (peer_supports_auth == 1) && 6681171990Srrs ((saw_asconf == 0) || (saw_asconf_ack == 0))) { 6682171990Srrs return (-33); 6683163953Srrs } 6684163953Srrs /* concatenate the full random key */ 6685188067Srrs keylen = sizeof(*p_random) + random_len + sizeof(*hmacs) + hmacs_len; 6686188067Srrs if (chunks != NULL) { 6687188067Srrs keylen += sizeof(*chunks) + num_chunks; 6688188067Srrs } 6689166675Srrs new_key = sctp_alloc_key(keylen); 6690166675Srrs if (new_key != NULL) { 6691166675Srrs /* copy in the RANDOM */ 6692168124Srrs if (p_random != NULL) { 6693168124Srrs keylen = sizeof(*p_random) + random_len; 6694168124Srrs bcopy(p_random, new_key->key, keylen); 6695166675Srrs } 6696163953Srrs /* append in the AUTH chunks */ 6697166675Srrs if (chunks != NULL) { 6698166675Srrs bcopy(chunks, new_key->key + keylen, 6699166675Srrs sizeof(*chunks) + num_chunks); 6700166675Srrs keylen += sizeof(*chunks) + num_chunks; 6701166675Srrs } 6702163953Srrs /* append in the HMACs */ 6703166675Srrs if (hmacs != NULL) { 6704166675Srrs bcopy(hmacs, new_key->key + keylen, 6705166675Srrs sizeof(*hmacs) + hmacs_len); 6706166675Srrs } 6707202449Stuexen } else { 6708168124Srrs /* failed to get memory for the key */ 6709171990Srrs return (-34); 6710163953Srrs } 6711163953Srrs if (stcb->asoc.authinfo.peer_random != NULL) 6712163953Srrs sctp_free_key(stcb->asoc.authinfo.peer_random); 6713163953Srrs stcb->asoc.authinfo.peer_random = new_key; 6714163953Srrs sctp_clear_cachedkeys(stcb, stcb->asoc.authinfo.assoc_keyid); 6715163953Srrs sctp_clear_cachedkeys(stcb, stcb->asoc.authinfo.recv_keyid); 6716163953Srrs 6717163953Srrs return (0); 6718163953Srrs} 6719163953Srrs 6720163953Srrsint 6721163953Srrssctp_set_primary_addr(struct sctp_tcb *stcb, struct sockaddr *sa, 6722163953Srrs struct sctp_nets *net) 6723163953Srrs{ 6724163953Srrs /* make sure the requested primary address exists in the assoc */ 6725163953Srrs if (net == NULL && sa) 6726163953Srrs net = sctp_findnet(stcb, sa); 6727163953Srrs 6728163953Srrs if (net == NULL) { 6729163953Srrs /* didn't find the requested primary address! */ 6730163953Srrs return (-1); 6731163953Srrs } else { 6732163953Srrs /* set the primary address */ 6733163953Srrs if (net->dest_state & SCTP_ADDR_UNCONFIRMED) { 6734167598Srrs /* Must be confirmed, so queue to set */ 6735167598Srrs net->dest_state |= SCTP_ADDR_REQ_PRIMARY; 6736167598Srrs return (0); 6737163953Srrs } 6738163953Srrs stcb->asoc.primary_destination = net; 6739224641Stuexen if (!(net->dest_state & SCTP_ADDR_PF) && (stcb->asoc.alternate)) { 6740224641Stuexen sctp_free_remote_addr(stcb->asoc.alternate); 6741224641Stuexen stcb->asoc.alternate = NULL; 6742224641Stuexen } 6743163953Srrs net = TAILQ_FIRST(&stcb->asoc.nets); 6744163953Srrs if (net != stcb->asoc.primary_destination) { 6745163953Srrs /* 6746163953Srrs * first one on the list is NOT the primary 6747215034Sbrucec * sctp_cmpaddr() is much more efficient if the 6748163953Srrs * primary is the first on the list, make it so. 6749163953Srrs */ 6750163953Srrs TAILQ_REMOVE(&stcb->asoc.nets, stcb->asoc.primary_destination, sctp_next); 6751163953Srrs TAILQ_INSERT_HEAD(&stcb->asoc.nets, stcb->asoc.primary_destination, sctp_next); 6752163953Srrs } 6753163953Srrs return (0); 6754163953Srrs } 6755163953Srrs} 6756163953Srrs 6757163953Srrsint 6758228653Stuexensctp_is_vtag_good(uint32_t tag, uint16_t lport, uint16_t rport, struct timeval *now) 6759163953Srrs{ 6760163953Srrs /* 6761163953Srrs * This function serves two purposes. It will see if a TAG can be 6762163953Srrs * re-used and return 1 for yes it is ok and 0 for don't use that 6763163953Srrs * tag. A secondary function it will do is purge out old tags that 6764163953Srrs * can be removed. 6765163953Srrs */ 6766163953Srrs struct sctpvtaghead *chain; 6767163953Srrs struct sctp_tagblock *twait_block; 6768185694Srrs struct sctpasochead *head; 6769163953Srrs struct sctp_tcb *stcb; 6770163953Srrs int i; 6771163953Srrs 6772185694Srrs SCTP_INP_INFO_RLOCK(); 6773179783Srrs head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(tag, 6774179783Srrs SCTP_BASE_INFO(hashasocmark))]; 6775163953Srrs LIST_FOREACH(stcb, head, sctp_asocs) { 6776185694Srrs /* 6777185694Srrs * We choose not to lock anything here. TCB's can't be 6778185694Srrs * removed since we have the read lock, so they can't be 6779185694Srrs * freed on us, same thing for the INP. I may be wrong with 6780185694Srrs * this assumption, but we will go with it for now :-) 6781185694Srrs */ 6782185694Srrs if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) { 6783185694Srrs continue; 6784185694Srrs } 6785163953Srrs if (stcb->asoc.my_vtag == tag) { 6786163953Srrs /* candidate */ 6787185694Srrs if (stcb->rport != rport) { 6788185694Srrs continue; 6789163953Srrs } 6790185694Srrs if (stcb->sctp_ep->sctp_lport != lport) { 6791185694Srrs continue; 6792185694Srrs } 6793185694Srrs /* Its a used tag set */ 6794209644Srrs SCTP_INP_INFO_RUNLOCK(); 6795185694Srrs return (0); 6796163953Srrs } 6797163953Srrs } 6798201523Stuexen chain = &SCTP_BASE_INFO(vtag_timewait)[(tag % SCTP_STACK_VTAG_HASH_SIZE)]; 6799163953Srrs /* Now what about timed wait ? */ 6800252585Stuexen LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) { 6801163953Srrs /* 6802163953Srrs * Block(s) are present, lets see if we have this tag in the 6803163953Srrs * list 6804163953Srrs */ 6805252585Stuexen for (i = 0; i < SCTP_NUMBER_IN_VTAG_BLOCK; i++) { 6806252585Stuexen if (twait_block->vtag_block[i].v_tag == 0) { 6807252585Stuexen /* not used */ 6808252585Stuexen continue; 6809252585Stuexen } else if ((long)twait_block->vtag_block[i].tv_sec_at_expire < 6810252585Stuexen now->tv_sec) { 6811252585Stuexen /* Audit expires this guy */ 6812252585Stuexen twait_block->vtag_block[i].tv_sec_at_expire = 0; 6813252585Stuexen twait_block->vtag_block[i].v_tag = 0; 6814252585Stuexen twait_block->vtag_block[i].lport = 0; 6815252585Stuexen twait_block->vtag_block[i].rport = 0; 6816252585Stuexen } else if ((twait_block->vtag_block[i].v_tag == tag) && 6817252585Stuexen (twait_block->vtag_block[i].lport == lport) && 6818252585Stuexen (twait_block->vtag_block[i].rport == rport)) { 6819252585Stuexen /* Bad tag, sorry :< */ 6820252585Stuexen SCTP_INP_INFO_RUNLOCK(); 6821252585Stuexen return (0); 6822163953Srrs } 6823163953Srrs } 6824163953Srrs } 6825185694Srrs SCTP_INP_INFO_RUNLOCK(); 6826163953Srrs return (1); 6827163953Srrs} 6828163953Srrs 6829163953Srrsstatic void 6830228653Stuexensctp_drain_mbufs(struct sctp_tcb *stcb) 6831163953Srrs{ 6832163953Srrs /* 6833163953Srrs * We must hunt this association for MBUF's past the cumack (i.e. 6834163953Srrs * out of order data that we can renege on). 6835163953Srrs */ 6836163953Srrs struct sctp_association *asoc; 6837163953Srrs struct sctp_tmit_chunk *chk, *nchk; 6838206137Stuexen uint32_t cumulative_tsn_p1; 6839163953Srrs struct sctp_queued_to_read *ctl, *nctl; 6840206137Stuexen int cnt, strmat; 6841206137Stuexen uint32_t gap, i; 6842206137Stuexen int fnd = 0; 6843163953Srrs 6844163953Srrs /* We look for anything larger than the cum-ack + 1 */ 6845163953Srrs 6846163953Srrs asoc = &stcb->asoc; 6847163953Srrs if (asoc->cumulative_tsn == asoc->highest_tsn_inside_map) { 6848163953Srrs /* none we can reneg on. */ 6849163953Srrs return; 6850163953Srrs } 6851165220Srrs SCTP_STAT_INCR(sctps_protocol_drains_done); 6852163953Srrs cumulative_tsn_p1 = asoc->cumulative_tsn + 1; 6853163953Srrs cnt = 0; 6854163953Srrs /* First look in the re-assembly queue */ 6855216822Stuexen TAILQ_FOREACH_SAFE(chk, &asoc->reasmqueue, sctp_next, nchk) { 6856216825Stuexen if (SCTP_TSN_GT(chk->rec.data.TSN_seq, cumulative_tsn_p1)) { 6857163953Srrs /* Yep it is above cum-ack */ 6858163953Srrs cnt++; 6859206137Stuexen SCTP_CALC_TSN_TO_GAP(gap, chk->rec.data.TSN_seq, asoc->mapping_array_base_tsn); 6860163953Srrs asoc->size_on_reasm_queue = sctp_sbspace_sub(asoc->size_on_reasm_queue, chk->send_size); 6861163953Srrs sctp_ucount_decr(asoc->cnt_on_reasm_queue); 6862163953Srrs SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, gap); 6863163953Srrs TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next); 6864163953Srrs if (chk->data) { 6865163953Srrs sctp_m_freem(chk->data); 6866163953Srrs chk->data = NULL; 6867163953Srrs } 6868221627Stuexen sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); 6869163953Srrs } 6870163953Srrs } 6871163953Srrs /* Ok that was fun, now we will drain all the inbound streams? */ 6872163953Srrs for (strmat = 0; strmat < asoc->streamincnt; strmat++) { 6873216822Stuexen TAILQ_FOREACH_SAFE(ctl, &asoc->strmin[strmat].inqueue, next, nctl) { 6874216825Stuexen if (SCTP_TSN_GT(ctl->sinfo_tsn, cumulative_tsn_p1)) { 6875163953Srrs /* Yep it is above cum-ack */ 6876163953Srrs cnt++; 6877206137Stuexen SCTP_CALC_TSN_TO_GAP(gap, ctl->sinfo_tsn, asoc->mapping_array_base_tsn); 6878163953Srrs asoc->size_on_all_streams = sctp_sbspace_sub(asoc->size_on_all_streams, ctl->length); 6879163953Srrs sctp_ucount_decr(asoc->cnt_on_all_streams); 6880206137Stuexen SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, gap); 6881206137Stuexen TAILQ_REMOVE(&asoc->strmin[strmat].inqueue, ctl, next); 6882163953Srrs if (ctl->data) { 6883163953Srrs sctp_m_freem(ctl->data); 6884163953Srrs ctl->data = NULL; 6885163953Srrs } 6886163953Srrs sctp_free_remote_addr(ctl->whoFrom); 6887179783Srrs SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), ctl); 6888163953Srrs SCTP_DECR_READQ_COUNT(); 6889163953Srrs } 6890163953Srrs } 6891163953Srrs } 6892206137Stuexen if (cnt) { 6893206137Stuexen /* We must back down to see what the new highest is */ 6894216825Stuexen for (i = asoc->highest_tsn_inside_map; SCTP_TSN_GE(i, asoc->mapping_array_base_tsn); i--) { 6895206137Stuexen SCTP_CALC_TSN_TO_GAP(gap, i, asoc->mapping_array_base_tsn); 6896206137Stuexen if (SCTP_IS_TSN_PRESENT(asoc->mapping_array, gap)) { 6897206137Stuexen asoc->highest_tsn_inside_map = i; 6898206137Stuexen fnd = 1; 6899206137Stuexen break; 6900206137Stuexen } 6901206137Stuexen } 6902206137Stuexen if (!fnd) { 6903206137Stuexen asoc->highest_tsn_inside_map = asoc->mapping_array_base_tsn - 1; 6904206137Stuexen } 6905206137Stuexen /* 6906206137Stuexen * Question, should we go through the delivery queue? The 6907206137Stuexen * only reason things are on here is the app not reading OR 6908206137Stuexen * a p-d-api up. An attacker COULD send enough in to 6909206137Stuexen * initiate the PD-API and then send a bunch of stuff to 6910206137Stuexen * other streams... these would wind up on the delivery 6911206137Stuexen * queue.. and then we would not get to them. But in order 6912206137Stuexen * to do this I then have to back-track and un-deliver 6913206137Stuexen * sequence numbers in streams.. el-yucko. I think for now 6914206137Stuexen * we will NOT look at the delivery queue and leave it to be 6915206137Stuexen * something to consider later. An alternative would be to 6916206137Stuexen * abort the P-D-API with a notification and then deliver 6917206137Stuexen * the data.... Or another method might be to keep track of 6918206137Stuexen * how many times the situation occurs and if we see a 6919206137Stuexen * possible attack underway just abort the association. 6920206137Stuexen */ 6921163953Srrs#ifdef SCTP_DEBUG 6922169420Srrs SCTPDBG(SCTP_DEBUG_PCB1, "Freed %d chunks from reneg harvest\n", cnt); 6923169420Srrs#endif 6924163953Srrs /* 6925163953Srrs * Now do we need to find a new 6926163953Srrs * asoc->highest_tsn_inside_map? 6927163953Srrs */ 6928163953Srrs asoc->last_revoke_count = cnt; 6929169378Srrs (void)SCTP_OS_TIMER_STOP(&stcb->asoc.dack_timer.timer); 6930172156Srrs /* sa_ignore NO_NULL_CHK */ 6931221627Stuexen sctp_send_sack(stcb, SCTP_SO_NOT_LOCKED); 6932172090Srrs sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_DRAIN, SCTP_SO_NOT_LOCKED); 6933163953Srrs } 6934163953Srrs /* 6935163953Srrs * Another issue, in un-setting the TSN's in the mapping array we 6936215039Stuexen * DID NOT adjust the highest_tsn marker. This will cause one of 6937215039Stuexen * two things to occur. It may cause us to do extra work in checking 6938215039Stuexen * for our mapping array movement. More importantly it may cause us 6939215039Stuexen * to SACK every datagram. This may not be a bad thing though since 6940215039Stuexen * we will recover once we get our cum-ack above and all this stuff 6941215039Stuexen * we dumped recovered. 6942163953Srrs */ 6943163953Srrs} 6944163953Srrs 6945163953Srrsvoid 6946163953Srrssctp_drain() 6947163953Srrs{ 6948163953Srrs /* 6949163953Srrs * We must walk the PCB lists for ALL associations here. The system 6950163953Srrs * is LOW on MBUF's and needs help. This is where reneging will 6951163953Srrs * occur. We really hope this does NOT happen! 6952163953Srrs */ 6953197326Stuexen VNET_ITERATOR_DECL(vnet_iter); 6954197326Stuexen VNET_LIST_RLOCK_NOSLEEP(); 6955197326Stuexen VNET_FOREACH(vnet_iter) { 6956197326Stuexen CURVNET_SET(vnet_iter); 6957197326Stuexen struct sctp_inpcb *inp; 6958197326Stuexen struct sctp_tcb *stcb; 6959197326Stuexen 6960197342Stuexen SCTP_STAT_INCR(sctps_protocol_drain_calls); 6961197342Stuexen if (SCTP_BASE_SYSCTL(sctp_do_drain) == 0) { 6962197342Stuexen#ifdef VIMAGE 6963197342Stuexen continue; 6964197342Stuexen#else 6965197342Stuexen return; 6966197342Stuexen#endif 6967197342Stuexen } 6968197326Stuexen SCTP_INP_INFO_RLOCK(); 6969197326Stuexen LIST_FOREACH(inp, &SCTP_BASE_INFO(listhead), sctp_list) { 6970197326Stuexen /* For each endpoint */ 6971197326Stuexen SCTP_INP_RLOCK(inp); 6972197326Stuexen LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { 6973197326Stuexen /* For each association */ 6974197326Stuexen SCTP_TCB_LOCK(stcb); 6975228653Stuexen sctp_drain_mbufs(stcb); 6976197326Stuexen SCTP_TCB_UNLOCK(stcb); 6977197326Stuexen } 6978197326Stuexen SCTP_INP_RUNLOCK(inp); 6979163953Srrs } 6980197326Stuexen SCTP_INP_INFO_RUNLOCK(); 6981197326Stuexen CURVNET_RESTORE(); 6982163953Srrs } 6983197326Stuexen VNET_LIST_RUNLOCK_NOSLEEP(); 6984163953Srrs} 6985163953Srrs 6986163953Srrs/* 6987163953Srrs * start a new iterator 6988163953Srrs * iterates through all endpoints and associations based on the pcb_state 6989163953Srrs * flags and asoc_state. "af" (mandatory) is executed for all matching 6990163953Srrs * assocs and "ef" (optional) is executed when the iterator completes. 6991163953Srrs * "inpf" (optional) is executed for each new endpoint as it is being 6992168299Srrs * iterated through. inpe (optional) is called when the inp completes 6993168299Srrs * its way through all the stcbs. 6994163953Srrs */ 6995163953Srrsint 6996167598Srrssctp_initiate_iterator(inp_func inpf, 6997167598Srrs asoc_func af, 6998167598Srrs inp_func inpe, 6999167598Srrs uint32_t pcb_state, 7000167598Srrs uint32_t pcb_features, 7001167598Srrs uint32_t asoc_state, 7002167598Srrs void *argp, 7003167598Srrs uint32_t argi, 7004167598Srrs end_func ef, 7005167598Srrs struct sctp_inpcb *s_inp, 7006167598Srrs uint8_t chunk_output_off) 7007163953Srrs{ 7008163953Srrs struct sctp_iterator *it = NULL; 7009163953Srrs 7010163953Srrs if (af == NULL) { 7011163953Srrs return (-1); 7012163953Srrs } 7013296052Stuexen if (SCTP_BASE_VAR(sctp_pcb_initialized) == 0) { 7014296052Stuexen SCTP_PRINTF("%s: abort on initialize being %d\n", __func__, 7015296052Stuexen SCTP_BASE_VAR(sctp_pcb_initialized)); 7016296052Stuexen return (-1); 7017296052Stuexen } 7018163953Srrs SCTP_MALLOC(it, struct sctp_iterator *, sizeof(struct sctp_iterator), 7019170091Srrs SCTP_M_ITER); 7020163953Srrs if (it == NULL) { 7021171943Srrs SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOMEM); 7022163953Srrs return (ENOMEM); 7023163953Srrs } 7024163953Srrs memset(it, 0, sizeof(*it)); 7025163953Srrs it->function_assoc = af; 7026163953Srrs it->function_inp = inpf; 7027167598Srrs if (inpf) 7028167598Srrs it->done_current_ep = 0; 7029167598Srrs else 7030167598Srrs it->done_current_ep = 1; 7031163953Srrs it->function_atend = ef; 7032163953Srrs it->pointer = argp; 7033163953Srrs it->val = argi; 7034163953Srrs it->pcb_flags = pcb_state; 7035163953Srrs it->pcb_features = pcb_features; 7036163953Srrs it->asoc_state = asoc_state; 7037167598Srrs it->function_inp_end = inpe; 7038163953Srrs it->no_chunk_output = chunk_output_off; 7039208160Srrs it->vn = curvnet; 7040163953Srrs if (s_inp) { 7041209029Srrs /* Assume lock is held here */ 7042163953Srrs it->inp = s_inp; 7043209029Srrs SCTP_INP_INCR_REF(it->inp); 7044163953Srrs it->iterator_flags = SCTP_ITERATOR_DO_SINGLE_INP; 7045163953Srrs } else { 7046163953Srrs SCTP_INP_INFO_RLOCK(); 7047179783Srrs it->inp = LIST_FIRST(&SCTP_BASE_INFO(listhead)); 7048209029Srrs if (it->inp) { 7049209029Srrs SCTP_INP_INCR_REF(it->inp); 7050209029Srrs } 7051163953Srrs SCTP_INP_INFO_RUNLOCK(); 7052163953Srrs it->iterator_flags = SCTP_ITERATOR_DO_ALL_INP; 7053163953Srrs 7054163953Srrs } 7055167598Srrs SCTP_IPI_ITERATOR_WQ_LOCK(); 7056296052Stuexen if (SCTP_BASE_VAR(sctp_pcb_initialized) == 0) { 7057296052Stuexen SCTP_IPI_ITERATOR_WQ_UNLOCK(); 7058296052Stuexen SCTP_PRINTF("%s: rollback on initialize being %d it=%p\n", __func__, 7059296052Stuexen SCTP_BASE_VAR(sctp_pcb_initialized), it); 7060296052Stuexen SCTP_FREE(it, SCTP_M_ITER); 7061296052Stuexen return (-1); 7062296052Stuexen } 7063208160Srrs TAILQ_INSERT_TAIL(&sctp_it_ctl.iteratorhead, it, sctp_nxt_itr); 7064208160Srrs if (sctp_it_ctl.iterator_running == 0) { 7065167598Srrs sctp_wakeup_iterator(); 7066167598Srrs } 7067167598Srrs SCTP_IPI_ITERATOR_WQ_UNLOCK(); 7068169655Srrs /* sa_ignore MEMLEAK {memory is put on the tailq for the iterator} */ 7069163953Srrs return (0); 7070163953Srrs} 7071