1163953Srrs/*- 2169382Srrs * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. 3235828Stuexen * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. 4235828Stuexen * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. 5163953Srrs * 6163953Srrs * Redistribution and use in source and binary forms, with or without 7163953Srrs * modification, are permitted provided that the following conditions are met: 8163953Srrs * 9163953Srrs * a) Redistributions of source code must retain the above copyright notice, 10228653Stuexen * this list of conditions and the following disclaimer. 11163953Srrs * 12163953Srrs * b) Redistributions in binary form must reproduce the above copyright 13163953Srrs * notice, this list of conditions and the following disclaimer in 14228653Stuexen * the documentation and/or other materials provided with the distribution. 15163953Srrs * 16163953Srrs * c) Neither the name of Cisco Systems, Inc. nor the names of its 17163953Srrs * contributors may be used to endorse or promote products derived 18163953Srrs * from this software without specific prior written permission. 19163953Srrs * 20163953Srrs * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21163953Srrs * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 22163953Srrs * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23163953Srrs * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24163953Srrs * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25163953Srrs * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26163953Srrs * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27163953Srrs * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28163953Srrs * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29163953Srrs * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30163953Srrs * THE POSSIBILITY OF SUCH DAMAGE. 31163953Srrs */ 32163953Srrs 33163953Srrs#include <sys/cdefs.h> 34163953Srrs__FBSDID("$FreeBSD$"); 35163953Srrs 36163953Srrs#include <netinet/sctp_os.h> 37163953Srrs#include <netinet/sctp_var.h> 38163953Srrs#include <netinet/sctp_pcb.h> 39163953Srrs#include <netinet/sctp_header.h> 40163953Srrs#include <netinet/sctputil.h> 41163953Srrs#include <netinet/sctp_output.h> 42163953Srrs#include <netinet/sctp_bsd_addr.h> 43163953Srrs#include <netinet/sctp_uio.h> 44163953Srrs#include <netinet/sctputil.h> 45163953Srrs#include <netinet/sctp_timer.h> 46163953Srrs#include <netinet/sctp_asconf.h> 47169208Srrs#include <netinet/sctp_sysctl.h> 48163953Srrs#include <netinet/sctp_indata.h> 49167598Srrs#include <sys/unistd.h> 50163953Srrs 51170091Srrs/* Declare all of our malloc named types */ 52170091SrrsMALLOC_DEFINE(SCTP_M_MAP, "sctp_map", "sctp asoc map descriptor"); 53170091SrrsMALLOC_DEFINE(SCTP_M_STRMI, "sctp_stri", "sctp stream in array"); 54170091SrrsMALLOC_DEFINE(SCTP_M_STRMO, "sctp_stro", "sctp stream out array"); 55170091SrrsMALLOC_DEFINE(SCTP_M_ASC_ADDR, "sctp_aadr", "sctp asconf address"); 56170091SrrsMALLOC_DEFINE(SCTP_M_ASC_IT, "sctp_a_it", "sctp asconf iterator"); 57170091SrrsMALLOC_DEFINE(SCTP_M_AUTH_CL, "sctp_atcl", "sctp auth chunklist"); 58170091SrrsMALLOC_DEFINE(SCTP_M_AUTH_KY, "sctp_atky", "sctp auth key"); 59170091SrrsMALLOC_DEFINE(SCTP_M_AUTH_HL, "sctp_athm", "sctp auth hmac list"); 60170091SrrsMALLOC_DEFINE(SCTP_M_AUTH_IF, "sctp_athi", "sctp auth info"); 61170091SrrsMALLOC_DEFINE(SCTP_M_STRESET, "sctp_stre", "sctp stream reset"); 62170091SrrsMALLOC_DEFINE(SCTP_M_CMSG, "sctp_cmsg", "sctp CMSG buffer"); 63170091SrrsMALLOC_DEFINE(SCTP_M_COPYAL, "sctp_cpal", "sctp copy all"); 64170091SrrsMALLOC_DEFINE(SCTP_M_VRF, "sctp_vrf", "sctp vrf struct"); 65170091SrrsMALLOC_DEFINE(SCTP_M_IFA, "sctp_ifa", "sctp ifa struct"); 66170091SrrsMALLOC_DEFINE(SCTP_M_IFN, "sctp_ifn", "sctp ifn struct"); 67170091SrrsMALLOC_DEFINE(SCTP_M_TIMW, "sctp_timw", "sctp time block"); 68170091SrrsMALLOC_DEFINE(SCTP_M_MVRF, "sctp_mvrf", "sctp mvrf pcb list"); 69170091SrrsMALLOC_DEFINE(SCTP_M_ITER, "sctp_iter", "sctp iterator control"); 70170091SrrsMALLOC_DEFINE(SCTP_M_SOCKOPT, "sctp_socko", "sctp socket option"); 71218211SrrsMALLOC_DEFINE(SCTP_M_MCORE, "sctp_mcore", "sctp mcore queue"); 72170091Srrs 73208160Srrs/* Global NON-VNET structure that controls the iterator */ 74208160Srrsstruct iterator_control sctp_it_ctl; 75208160Srrs 76208160Srrs 77167598Srrsvoid 78167598Srrssctp_wakeup_iterator(void) 79163953Srrs{ 80208160Srrs wakeup(&sctp_it_ctl.iterator_running); 81163953Srrs} 82163953Srrs 83167598Srrsstatic void 84228653Stuexensctp_iterator_thread(void *v SCTP_UNUSED) 85163953Srrs{ 86167598Srrs SCTP_IPI_ITERATOR_WQ_LOCK(); 87225676Stuexen /* In FreeBSD this thread never terminates. */ 88228653Stuexen for (;;) { 89208160Srrs msleep(&sctp_it_ctl.iterator_running, 90208160Srrs &sctp_it_ctl.ipi_iterator_wq_mtx, 91175751Srrs 0, "waiting_for_work", 0); 92167598Srrs sctp_iterator_worker(); 93163953Srrs } 94163953Srrs} 95163953Srrs 96167598Srrsvoid 97167598Srrssctp_startup_iterator(void) 98163953Srrs{ 99258454Stuexen if (sctp_it_ctl.thread_proc) { 100208160Srrs /* You only get one */ 101208160Srrs return; 102208160Srrs } 103258890Stuexen /* Initialize global locks here, thus only once. */ 104258890Stuexen SCTP_ITERATOR_LOCK_INIT(); 105258890Stuexen SCTP_IPI_ITERATOR_WQ_INIT(); 106208160Srrs TAILQ_INIT(&sctp_it_ctl.iteratorhead); 107258454Stuexen kproc_create(sctp_iterator_thread, 108208160Srrs (void *)NULL, 109208160Srrs &sctp_it_ctl.thread_proc, 110167598Srrs RFPROC, 111167598Srrs SCTP_KTHREAD_PAGES, 112167598Srrs SCTP_KTRHEAD_NAME); 113163953Srrs} 114163953Srrs 115178251Srrs#ifdef INET6 116180387Srrs 117167598Srrsvoid 118167598Srrssctp_gather_internal_ifa_flags(struct sctp_ifa *ifa) 119163953Srrs{ 120167598Srrs struct in6_ifaddr *ifa6; 121163953Srrs 122167598Srrs ifa6 = (struct in6_ifaddr *)ifa->ifa; 123167598Srrs ifa->flags = ifa6->ia6_flags; 124197288Srrs if (!MODULE_GLOBAL(ip6_use_deprecated)) { 125167598Srrs if (ifa->flags & 126167598Srrs IN6_IFF_DEPRECATED) { 127167598Srrs ifa->localifa_flags |= SCTP_ADDR_IFA_UNUSEABLE; 128167598Srrs } else { 129167598Srrs ifa->localifa_flags &= ~SCTP_ADDR_IFA_UNUSEABLE; 130163953Srrs } 131163953Srrs } else { 132167598Srrs ifa->localifa_flags &= ~SCTP_ADDR_IFA_UNUSEABLE; 133163953Srrs } 134167598Srrs if (ifa->flags & 135167598Srrs (IN6_IFF_DETACHED | 136167598Srrs IN6_IFF_ANYCAST | 137167598Srrs IN6_IFF_NOTREADY)) { 138167598Srrs ifa->localifa_flags |= SCTP_ADDR_IFA_UNUSEABLE; 139163953Srrs } else { 140167598Srrs ifa->localifa_flags &= ~SCTP_ADDR_IFA_UNUSEABLE; 141163953Srrs } 142163953Srrs} 143163953Srrs 144180387Srrs#endif /* INET6 */ 145163953Srrs 146163953Srrs 147167598Srrsstatic uint32_t 148239035Stuexensctp_is_desired_interface_type(struct ifnet *ifn) 149163953Srrs{ 150167598Srrs int result; 151163953Srrs 152167598Srrs /* check the interface type to see if it's one we care about */ 153239035Stuexen switch (ifn->if_type) { 154167598Srrs case IFT_ETHER: 155167598Srrs case IFT_ISO88023: 156167598Srrs case IFT_ISO88024: 157167598Srrs case IFT_ISO88025: 158167598Srrs case IFT_ISO88026: 159167598Srrs case IFT_STARLAN: 160167598Srrs case IFT_P10: 161167598Srrs case IFT_P80: 162167598Srrs case IFT_HY: 163167598Srrs case IFT_FDDI: 164167598Srrs case IFT_XETHER: 165167598Srrs case IFT_ISDNBASIC: 166167598Srrs case IFT_ISDNPRIMARY: 167167598Srrs case IFT_PTPSERIAL: 168172091Srrs case IFT_OTHER: 169167598Srrs case IFT_PPP: 170167598Srrs case IFT_LOOP: 171167598Srrs case IFT_SLIP: 172179783Srrs case IFT_GIF: 173196610Stuexen case IFT_L2VLAN: 174232724Stuexen case IFT_STF: 175167598Srrs case IFT_IP: 176167598Srrs case IFT_IPOVERCDLC: 177167598Srrs case IFT_IPOVERCLAW: 178232866Srrs case IFT_PROPVIRTUAL: /* NetGraph Virtual too */ 179167598Srrs case IFT_VIRTUALIPADDRESS: 180167598Srrs result = 1; 181167598Srrs break; 182167598Srrs default: 183167598Srrs result = 0; 184163953Srrs } 185163953Srrs 186167598Srrs return (result); 187163953Srrs} 188163953Srrs 189179783Srrs 190191073Srrs 191191073Srrs 192167598Srrsstatic void 193167598Srrssctp_init_ifns_for_vrf(int vrfid) 194163953Srrs{ 195163953Srrs /* 196167598Srrs * Here we must apply ANY locks needed by the IFN we access and also 197167598Srrs * make sure we lock any IFA that exists as we float through the 198167598Srrs * list of IFA's 199163953Srrs */ 200163953Srrs struct ifnet *ifn; 201163953Srrs struct ifaddr *ifa; 202167598Srrs struct sctp_ifa *sctp_ifa; 203167598Srrs uint32_t ifa_flags; 204163953Srrs 205221249Stuexen#ifdef INET6 206221249Stuexen struct in6_ifaddr *ifa6; 207221249Stuexen 208221249Stuexen#endif 209221249Stuexen 210197326Stuexen IFNET_RLOCK(); 211197288Srrs TAILQ_FOREACH(ifn, &MODULE_GLOBAL(ifnet), if_list) { 212239035Stuexen if (sctp_is_desired_interface_type(ifn) == 0) { 213239035Stuexen /* non desired type */ 214239035Stuexen continue; 215239035Stuexen } 216229621Sjhb IF_ADDR_RLOCK(ifn); 217167598Srrs TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list) { 218167598Srrs if (ifa->ifa_addr == NULL) { 219163953Srrs continue; 220163953Srrs } 221221249Stuexen switch (ifa->ifa_addr->sa_family) { 222221249Stuexen#ifdef INET 223221249Stuexen case AF_INET: 224221249Stuexen if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) { 225221249Stuexen continue; 226221249Stuexen } 227221249Stuexen break; 228221249Stuexen#endif 229221249Stuexen#ifdef INET6 230221249Stuexen case AF_INET6: 231167598Srrs if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) { 232167598Srrs /* skip unspecifed addresses */ 233167598Srrs continue; 234167598Srrs } 235221249Stuexen break; 236221249Stuexen#endif 237221249Stuexen default: 238221249Stuexen continue; 239163953Srrs } 240221249Stuexen switch (ifa->ifa_addr->sa_family) { 241221249Stuexen#ifdef INET 242221249Stuexen case AF_INET: 243221249Stuexen ifa_flags = 0; 244221249Stuexen break; 245221249Stuexen#endif 246221249Stuexen#ifdef INET6 247221249Stuexen case AF_INET6: 248179783Srrs ifa6 = (struct in6_ifaddr *)ifa; 249179783Srrs ifa_flags = ifa6->ia6_flags; 250221249Stuexen break; 251221249Stuexen#endif 252221249Stuexen default: 253179783Srrs ifa_flags = 0; 254221249Stuexen break; 255163953Srrs } 256179783Srrs sctp_ifa = sctp_add_addr_to_vrf(vrfid, 257179783Srrs (void *)ifn, 258179783Srrs ifn->if_index, 259179783Srrs ifn->if_type, 260179783Srrs ifn->if_xname, 261179783Srrs (void *)ifa, 262179783Srrs ifa->ifa_addr, 263179783Srrs ifa_flags, 264179783Srrs 0); 265179783Srrs if (sctp_ifa) { 266179783Srrs sctp_ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE; 267179783Srrs } 268163953Srrs } 269229621Sjhb IF_ADDR_RUNLOCK(ifn); 270163953Srrs } 271197326Stuexen IFNET_RUNLOCK(); 272163953Srrs} 273163953Srrs 274167598Srrsvoid 275167598Srrssctp_init_vrf_list(int vrfid) 276163953Srrs{ 277167598Srrs if (vrfid > SCTP_MAX_VRF_ID) 278167598Srrs /* can't do that */ 279167598Srrs return; 280163953Srrs 281167598Srrs /* Don't care about return here */ 282167598Srrs (void)sctp_allocate_vrf(vrfid); 283163953Srrs 284163953Srrs /* 285167598Srrs * Now we need to build all the ifn's for this vrf and there 286167598Srrs * addresses 287163953Srrs */ 288167598Srrs sctp_init_ifns_for_vrf(vrfid); 289163953Srrs} 290163953Srrs 291167598Srrsvoid 292167598Srrssctp_addr_change(struct ifaddr *ifa, int cmd) 293163953Srrs{ 294167598Srrs uint32_t ifa_flags = 0; 295163953Srrs 296296052Stuexen if (SCTP_BASE_VAR(sctp_pcb_initialized) == 0) { 297296052Stuexen return; 298296052Stuexen } 299163953Srrs /* 300167598Srrs * BSD only has one VRF, if this changes we will need to hook in the 301167598Srrs * right things here to get the id to pass to the address managment 302167598Srrs * routine. 303163953Srrs */ 304179783Srrs if (SCTP_BASE_VAR(first_time) == 0) { 305167598Srrs /* Special test to see if my ::1 will showup with this */ 306179783Srrs SCTP_BASE_VAR(first_time) = 1; 307167598Srrs sctp_init_ifns_for_vrf(SCTP_DEFAULT_VRFID); 308163953Srrs } 309167598Srrs if ((cmd != RTM_ADD) && (cmd != RTM_DELETE)) { 310167598Srrs /* don't know what to do with this */ 311167598Srrs return; 312163953Srrs } 313167598Srrs if (ifa->ifa_addr == NULL) { 314167598Srrs return; 315163953Srrs } 316239035Stuexen if (sctp_is_desired_interface_type(ifa->ifa_ifp) == 0) { 317239035Stuexen /* non desired type */ 318239035Stuexen return; 319239035Stuexen } 320221249Stuexen switch (ifa->ifa_addr->sa_family) { 321221249Stuexen#ifdef INET 322221249Stuexen case AF_INET: 323221249Stuexen if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) { 324221249Stuexen return; 325221249Stuexen } 326221249Stuexen break; 327221249Stuexen#endif 328221249Stuexen#ifdef INET6 329221249Stuexen case AF_INET6: 330179783Srrs ifa_flags = ((struct in6_ifaddr *)ifa)->ia6_flags; 331167598Srrs if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) { 332167598Srrs /* skip unspecifed addresses */ 333167598Srrs return; 334163953Srrs } 335221249Stuexen break; 336221249Stuexen#endif 337221249Stuexen default: 338221249Stuexen /* non inet/inet6 skip */ 339221249Stuexen return; 340163953Srrs } 341167598Srrs if (cmd == RTM_ADD) { 342212707Stuexen (void)sctp_add_addr_to_vrf(SCTP_DEFAULT_VRFID, (void *)ifa->ifa_ifp, 343239035Stuexen ifa->ifa_ifp->if_index, ifa->ifa_ifp->if_type, ifa->ifa_ifp->if_xname, 344169208Srrs (void *)ifa, ifa->ifa_addr, ifa_flags, 1); 345179783Srrs } else { 346167598Srrs 347172091Srrs sctp_del_addr_from_vrf(SCTP_DEFAULT_VRFID, ifa->ifa_addr, 348172091Srrs ifa->ifa_ifp->if_index, 349239035Stuexen ifa->ifa_ifp->if_xname); 350239035Stuexen 351163953Srrs /* 352167598Srrs * We don't bump refcount here so when it completes the 353167598Srrs * final delete will happen. 354163953Srrs */ 355163953Srrs } 356169208Srrs} 357167598Srrs 358179783Srrsvoid 359179783Srrs sctp_add_or_del_interfaces(int (*pred) (struct ifnet *), int add){ 360179783Srrs struct ifnet *ifn; 361179783Srrs struct ifaddr *ifa; 362179783Srrs 363197326Stuexen IFNET_RLOCK(); 364197288Srrs TAILQ_FOREACH(ifn, &MODULE_GLOBAL(ifnet), if_list) { 365179783Srrs if (!(*pred) (ifn)) { 366179783Srrs continue; 367179783Srrs } 368179783Srrs TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list) { 369179783Srrs sctp_addr_change(ifa, add ? RTM_ADD : RTM_DELETE); 370179783Srrs } 371179783Srrs } 372197326Stuexen IFNET_RUNLOCK(); 373179783Srrs} 374179783Srrs 375169208Srrsstruct mbuf * 376169208Srrssctp_get_mbuf_for_msg(unsigned int space_needed, int want_header, 377169208Srrs int how, int allonebuf, int type) 378169208Srrs{ 379169208Srrs struct mbuf *m = NULL; 380163953Srrs 381169208Srrs m = m_getm2(NULL, space_needed, how, type, want_header ? M_PKTHDR : 0); 382169208Srrs if (m == NULL) { 383169208Srrs /* bad, no memory */ 384169208Srrs return (m); 385163953Srrs } 386169208Srrs if (allonebuf) { 387169208Srrs int siz; 388169208Srrs 389169208Srrs if (SCTP_BUF_IS_EXTENDED(m)) { 390169208Srrs siz = SCTP_BUF_EXTEND_SIZE(m); 391169208Srrs } else { 392169208Srrs if (want_header) 393169208Srrs siz = MHLEN; 394169208Srrs else 395169208Srrs siz = MLEN; 396169208Srrs } 397169208Srrs if (siz < space_needed) { 398169208Srrs m_freem(m); 399169208Srrs return (NULL); 400169208Srrs } 401163953Srrs } 402169208Srrs if (SCTP_BUF_NEXT(m)) { 403169208Srrs sctp_m_freem(SCTP_BUF_NEXT(m)); 404169208Srrs SCTP_BUF_NEXT(m) = NULL; 405169208Srrs } 406169208Srrs#ifdef SCTP_MBUF_LOGGING 407179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { 408283708Stuexen sctp_log_mb(m, SCTP_MBUF_IALLOC); 409169208Srrs } 410169208Srrs#endif 411169208Srrs return (m); 412163953Srrs} 413170091Srrs 414170091Srrs 415170091Srrs#ifdef SCTP_PACKET_LOGGING 416170091Srrsvoid 417237540Stuexensctp_packet_log(struct mbuf *m) 418170091Srrs{ 419170138Srrs int *lenat, thisone; 420170091Srrs void *copyto; 421170091Srrs uint32_t *tick_tock; 422237540Stuexen int length; 423170138Srrs int total_len; 424170138Srrs int grabbed_lock = 0; 425170138Srrs int value, newval, thisend, thisbegin; 426170091Srrs 427170138Srrs /* 428170138Srrs * Buffer layout. -sizeof this entry (total_len) -previous end 429170138Srrs * (value) -ticks of log (ticks) o -ip packet o -as logged - 430170138Srrs * where this started (thisbegin) x <--end points here 431170138Srrs */ 432237540Stuexen length = SCTP_HEADER_LEN(m); 433170138Srrs total_len = SCTP_SIZE32((length + (4 * sizeof(int)))); 434170091Srrs /* Log a packet to the buffer. */ 435170091Srrs if (total_len > SCTP_PACKET_LOG_SIZE) { 436170091Srrs /* Can't log this packet I have not a buffer big enough */ 437170091Srrs return; 438170091Srrs } 439179783Srrs if (length < (int)(SCTP_MIN_V4_OVERHEAD + sizeof(struct sctp_cookie_ack_chunk))) { 440170091Srrs return; 441170091Srrs } 442179783Srrs atomic_add_int(&SCTP_BASE_VAR(packet_log_writers), 1); 443170138Srrstry_again: 444179783Srrs if (SCTP_BASE_VAR(packet_log_writers) > SCTP_PKTLOG_WRITERS_NEED_LOCK) { 445170138Srrs SCTP_IP_PKTLOG_LOCK(); 446170138Srrs grabbed_lock = 1; 447170138Srrsagain_locked: 448179783Srrs value = SCTP_BASE_VAR(packet_log_end); 449179783Srrs newval = SCTP_BASE_VAR(packet_log_end) + total_len; 450170138Srrs if (newval >= SCTP_PACKET_LOG_SIZE) { 451170138Srrs /* we wrapped */ 452170138Srrs thisbegin = 0; 453170138Srrs thisend = total_len; 454170091Srrs } else { 455179783Srrs thisbegin = SCTP_BASE_VAR(packet_log_end); 456170138Srrs thisend = newval; 457170091Srrs } 458179783Srrs if (!(atomic_cmpset_int(&SCTP_BASE_VAR(packet_log_end), value, thisend))) { 459170138Srrs goto again_locked; 460170091Srrs } 461170091Srrs } else { 462179783Srrs value = SCTP_BASE_VAR(packet_log_end); 463179783Srrs newval = SCTP_BASE_VAR(packet_log_end) + total_len; 464170138Srrs if (newval >= SCTP_PACKET_LOG_SIZE) { 465170138Srrs /* we wrapped */ 466170138Srrs thisbegin = 0; 467170138Srrs thisend = total_len; 468170138Srrs } else { 469179783Srrs thisbegin = SCTP_BASE_VAR(packet_log_end); 470170138Srrs thisend = newval; 471170091Srrs } 472179783Srrs if (!(atomic_cmpset_int(&SCTP_BASE_VAR(packet_log_end), value, thisend))) { 473170138Srrs goto try_again; 474170138Srrs } 475170091Srrs } 476170138Srrs /* Sanity check */ 477170138Srrs if (thisend >= SCTP_PACKET_LOG_SIZE) { 478234995Stuexen SCTP_PRINTF("Insanity stops a log thisbegin:%d thisend:%d writers:%d lock:%d end:%d\n", 479170138Srrs thisbegin, 480170138Srrs thisend, 481179783Srrs SCTP_BASE_VAR(packet_log_writers), 482170138Srrs grabbed_lock, 483179783Srrs SCTP_BASE_VAR(packet_log_end)); 484179783Srrs SCTP_BASE_VAR(packet_log_end) = 0; 485170138Srrs goto no_log; 486170138Srrs 487170091Srrs } 488179783Srrs lenat = (int *)&SCTP_BASE_VAR(packet_log_buffer)[thisbegin]; 489170091Srrs *lenat = total_len; 490170091Srrs lenat++; 491170138Srrs *lenat = value; 492170138Srrs lenat++; 493170091Srrs tick_tock = (uint32_t *) lenat; 494170091Srrs lenat++; 495170091Srrs *tick_tock = sctp_get_tick_count(); 496170091Srrs copyto = (void *)lenat; 497170138Srrs thisone = thisend - sizeof(int); 498179783Srrs lenat = (int *)&SCTP_BASE_VAR(packet_log_buffer)[thisone]; 499170138Srrs *lenat = thisbegin; 500170138Srrs if (grabbed_lock) { 501170138Srrs SCTP_IP_PKTLOG_UNLOCK(); 502170138Srrs grabbed_lock = 0; 503170138Srrs } 504170091Srrs m_copydata(m, 0, length, (caddr_t)copyto); 505170138Srrsno_log: 506170138Srrs if (grabbed_lock) { 507170138Srrs SCTP_IP_PKTLOG_UNLOCK(); 508170138Srrs } 509179783Srrs atomic_subtract_int(&SCTP_BASE_VAR(packet_log_writers), 1); 510170091Srrs} 511170091Srrs 512170091Srrs 513170091Srrsint 514170091Srrssctp_copy_out_packet_log(uint8_t * target, int length) 515170091Srrs{ 516170091Srrs /* 517170091Srrs * We wind through the packet log starting at start copying up to 518170091Srrs * length bytes out. We return the number of bytes copied. 519170091Srrs */ 520170138Srrs int tocopy, this_copy; 521170138Srrs int *lenat; 522170138Srrs int did_delay = 0; 523170091Srrs 524170091Srrs tocopy = length; 525179783Srrs if (length < (int)(2 * sizeof(int))) { 526170138Srrs /* not enough room */ 527170091Srrs return (0); 528170091Srrs } 529170138Srrs if (SCTP_PKTLOG_WRITERS_NEED_LOCK) { 530179783Srrs atomic_add_int(&SCTP_BASE_VAR(packet_log_writers), SCTP_PKTLOG_WRITERS_NEED_LOCK); 531170138Srrsagain: 532179783Srrs if ((did_delay == 0) && (SCTP_BASE_VAR(packet_log_writers) != SCTP_PKTLOG_WRITERS_NEED_LOCK)) { 533170138Srrs /* 534170138Srrs * we delay here for just a moment hoping the 535170138Srrs * writer(s) that were present when we entered will 536170138Srrs * have left and we only have locking ones that will 537170138Srrs * contend with us for the lock. This does not 538170138Srrs * assure 100% access, but its good enough for a 539170138Srrs * logging facility like this. 540170138Srrs */ 541170138Srrs did_delay = 1; 542170138Srrs DELAY(10); 543170138Srrs goto again; 544170091Srrs } 545170091Srrs } 546170138Srrs SCTP_IP_PKTLOG_LOCK(); 547170138Srrs lenat = (int *)target; 548179783Srrs *lenat = SCTP_BASE_VAR(packet_log_end); 549170138Srrs lenat++; 550170899Srrs this_copy = min((length - sizeof(int)), SCTP_PACKET_LOG_SIZE); 551179783Srrs memcpy((void *)lenat, (void *)SCTP_BASE_VAR(packet_log_buffer), this_copy); 552170138Srrs if (SCTP_PKTLOG_WRITERS_NEED_LOCK) { 553179783Srrs atomic_subtract_int(&SCTP_BASE_VAR(packet_log_writers), 554170899Srrs SCTP_PKTLOG_WRITERS_NEED_LOCK); 555170138Srrs } 556170138Srrs SCTP_IP_PKTLOG_UNLOCK(); 557170138Srrs return (this_copy + sizeof(int)); 558170091Srrs} 559170091Srrs 560170091Srrs#endif 561