sctp_bsd_addr.c revision 197326
1139743Simp/*- 239213Sgibbs * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. 3111206Sken * 439213Sgibbs * Redistribution and use in source and binary forms, with or without 539213Sgibbs * modification, are permitted provided that the following conditions are met: 639213Sgibbs * 739213Sgibbs * a) Redistributions of source code must retain the above copyright notice, 839213Sgibbs * this list of conditions and the following disclaimer. 939213Sgibbs * 1039213Sgibbs * b) Redistributions in binary form must reproduce the above copyright 1139213Sgibbs * notice, this list of conditions and the following disclaimer in 1239213Sgibbs * the documentation and/or other materials provided with the distribution. 1339213Sgibbs * 1439213Sgibbs * c) Neither the name of Cisco Systems, Inc. nor the names of its 1539213Sgibbs * contributors may be used to endorse or promote products derived 1639213Sgibbs * from this software without specific prior written permission. 1739213Sgibbs * 1839213Sgibbs * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1939213Sgibbs * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 2039213Sgibbs * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2139213Sgibbs * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 2239213Sgibbs * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2339213Sgibbs * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2439213Sgibbs * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2539213Sgibbs * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2639213Sgibbs * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27116162Sobrien * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28139743Simp * THE POSSIBILITY OF SUCH DAMAGE. 2939213Sgibbs */ 3039213Sgibbs 3139213Sgibbs/* $KAME: sctp_output.c,v 1.46 2005/03/06 16:04:17 itojun Exp $ */ 3239213Sgibbs 3339213Sgibbs#include <sys/cdefs.h> 3439213Sgibbs__FBSDID("$FreeBSD: head/sys/netinet/sctp_bsd_addr.c 197326 2009-09-19 14:02:16Z tuexen $"); 3539213Sgibbs 3639213Sgibbs#include <netinet/sctp_os.h> 3739213Sgibbs#include <netinet/sctp_var.h> 3839213Sgibbs#include <netinet/sctp_pcb.h> 3939213Sgibbs#include <netinet/sctp_header.h> 4039213Sgibbs#include <netinet/sctputil.h> 4139213Sgibbs#include <netinet/sctp_output.h> 4239213Sgibbs#include <netinet/sctp_bsd_addr.h> 4339213Sgibbs#include <netinet/sctp_uio.h> 4439213Sgibbs#include <netinet/sctputil.h> 4539213Sgibbs#include <netinet/sctp_timer.h> 4639213Sgibbs#include <netinet/sctp_asconf.h> 4739213Sgibbs#include <netinet/sctp_sysctl.h> 48116162Sobrien#include <netinet/sctp_indata.h> 49116162Sobrien#include <sys/unistd.h> 50116162Sobrien 5140020Sken/* Declare all of our malloc named types */ 5239213Sgibbs 5339213Sgibbs/* Note to Michael/Peter for mac-os, 5439213Sgibbs * I think mac has this too since I 5539213Sgibbs * do see the M_PCB type, so I 5660041Sphk * will also put in the mac file the 5751836Sphk * MALLOC_DECLARE. If this does not 5851836Sphk * work for mac uncomment the defines for 5939213Sgibbs * the strings that we use in Panda, I put 6039213Sgibbs * them in comments in the mac-os file. 61105421Snjl */ 6260422SkenMALLOC_DEFINE(SCTP_M_MAP, "sctp_map", "sctp asoc map descriptor"); 6339213SgibbsMALLOC_DEFINE(SCTP_M_STRMI, "sctp_stri", "sctp stream in array"); 6439213SgibbsMALLOC_DEFINE(SCTP_M_STRMO, "sctp_stro", "sctp stream out array"); 65119708SkenMALLOC_DEFINE(SCTP_M_ASC_ADDR, "sctp_aadr", "sctp asconf address"); 66120599SphkMALLOC_DEFINE(SCTP_M_ASC_IT, "sctp_a_it", "sctp asconf iterator"); 6739213SgibbsMALLOC_DEFINE(SCTP_M_AUTH_CL, "sctp_atcl", "sctp auth chunklist"); 6839213SgibbsMALLOC_DEFINE(SCTP_M_AUTH_KY, "sctp_atky", "sctp auth key"); 6939213SgibbsMALLOC_DEFINE(SCTP_M_AUTH_HL, "sctp_athm", "sctp auth hmac list"); 7039213SgibbsMALLOC_DEFINE(SCTP_M_AUTH_IF, "sctp_athi", "sctp auth info"); 7139213SgibbsMALLOC_DEFINE(SCTP_M_STRESET, "sctp_stre", "sctp stream reset"); 7239213SgibbsMALLOC_DEFINE(SCTP_M_CMSG, "sctp_cmsg", "sctp CMSG buffer"); 73168752SscottlMALLOC_DEFINE(SCTP_M_COPYAL, "sctp_cpal", "sctp copy all"); 7439213SgibbsMALLOC_DEFINE(SCTP_M_VRF, "sctp_vrf", "sctp vrf struct"); 7539213SgibbsMALLOC_DEFINE(SCTP_M_IFA, "sctp_ifa", "sctp ifa struct"); 7639213SgibbsMALLOC_DEFINE(SCTP_M_IFN, "sctp_ifn", "sctp ifn struct"); 7739213SgibbsMALLOC_DEFINE(SCTP_M_TIMW, "sctp_timw", "sctp time block"); 7839213SgibbsMALLOC_DEFINE(SCTP_M_MVRF, "sctp_mvrf", "sctp mvrf pcb list"); 7939213SgibbsMALLOC_DEFINE(SCTP_M_ITER, "sctp_iter", "sctp iterator control"); 8039213SgibbsMALLOC_DEFINE(SCTP_M_SOCKOPT, "sctp_socko", "sctp socket option"); 8139213Sgibbs 8239213Sgibbs#if defined(SCTP_USE_THREAD_BASED_ITERATOR) 8339213Sgibbsvoid 8439213Sgibbssctp_wakeup_iterator(void) 8539213Sgibbs{ 8639213Sgibbs wakeup(&SCTP_BASE_INFO(iterator_running)); 87111206Sken} 88111206Sken 89111206Skenstatic void 90111206Skensctp_iterator_thread(void *v) 91111206Sken{ 92111206Sken CURVNET_SET((struct vnet *)v); 9339213Sgibbs SCTP_IPI_ITERATOR_WQ_LOCK(); 9439213Sgibbs SCTP_BASE_INFO(iterator_running) = 0; 9539213Sgibbs while (1) { 96120884Sthomas msleep(&SCTP_BASE_INFO(iterator_running), 97120884Sthomas &SCTP_BASE_INFO(ipi_iterator_wq_mtx), 98120884Sthomas 0, "waiting_for_work", 0); 99120884Sthomas if (SCTP_BASE_INFO(threads_must_exit)) { 100120884Sthomas kthread_exit(); 101120884Sthomas } 102120884Sthomas sctp_iterator_worker(); 103120884Sthomas } 104120884Sthomas CURVNET_RESTORE(); 105120884Sthomas} 106168752Sscottl 107168752Sscottlvoid 10839213Sgibbssctp_startup_iterator(void) 10939213Sgibbs{ 11039213Sgibbs int ret; 11139213Sgibbs 11239213Sgibbs ret = kproc_create(sctp_iterator_thread, 11339213Sgibbs (void *)curvnet, 11439213Sgibbs &SCTP_BASE_INFO(thread_proc), 11539213Sgibbs RFPROC, 11639213Sgibbs SCTP_KTHREAD_PAGES, 11739213Sgibbs SCTP_KTRHEAD_NAME); 11839213Sgibbs} 11939213Sgibbs 12039213Sgibbs#endif 12139213Sgibbs 12239213Sgibbs#ifdef INET6 12339213Sgibbs 12439213Sgibbsvoid 12539213Sgibbssctp_gather_internal_ifa_flags(struct sctp_ifa *ifa) 12639213Sgibbs{ 12739213Sgibbs struct in6_ifaddr *ifa6; 128111206Sken 129111206Sken ifa6 = (struct in6_ifaddr *)ifa->ifa; 130111206Sken ifa->flags = ifa6->ia6_flags; 131111206Sken if (!MODULE_GLOBAL(ip6_use_deprecated)) { 132111206Sken if (ifa->flags & 133111206Sken IN6_IFF_DEPRECATED) { 134111206Sken ifa->localifa_flags |= SCTP_ADDR_IFA_UNUSEABLE; 135111206Sken } else { 136111206Sken ifa->localifa_flags &= ~SCTP_ADDR_IFA_UNUSEABLE; 137111206Sken } 13839213Sgibbs } else { 13939213Sgibbs ifa->localifa_flags &= ~SCTP_ADDR_IFA_UNUSEABLE; 14039213Sgibbs } 14139213Sgibbs if (ifa->flags & 14239213Sgibbs (IN6_IFF_DETACHED | 14339213Sgibbs IN6_IFF_ANYCAST | 14439213Sgibbs IN6_IFF_NOTREADY)) { 14539213Sgibbs ifa->localifa_flags |= SCTP_ADDR_IFA_UNUSEABLE; 14646581Sken } else { 14759249Sphk ifa->localifa_flags &= ~SCTP_ADDR_IFA_UNUSEABLE; 14860938Sjake } 14939213Sgibbs} 15039213Sgibbs 15139213Sgibbs#endif /* INET6 */ 15260938Sjake 15339213Sgibbs 15439213Sgibbsstatic uint32_t 15539213Sgibbssctp_is_desired_interface_type(struct ifaddr *ifa) 156111206Sken{ 157112262Sphk int result; 158119708Sken 159111206Sken /* check the interface type to see if it's one we care about */ 160111206Sken switch (ifa->ifa_ifp->if_type) { 161111206Sken case IFT_ETHER: 162111206Sken case IFT_ISO88023: 163125975Sphk case IFT_ISO88024: 16439213Sgibbs case IFT_ISO88025: 16539213Sgibbs case IFT_ISO88026: 166111206Sken case IFT_STARLAN: 167111206Sken case IFT_P10: 168111206Sken case IFT_P80: 169111206Sken case IFT_HY: 170111206Sken case IFT_FDDI: 171111206Sken case IFT_XETHER: 172111206Sken case IFT_ISDNBASIC: 173111206Sken case IFT_ISDNPRIMARY: 174111206Sken case IFT_PTPSERIAL: 175111206Sken case IFT_OTHER: 17639213Sgibbs case IFT_PPP: 17739213Sgibbs case IFT_LOOP: 17839213Sgibbs case IFT_SLIP: 17939213Sgibbs case IFT_GIF: 18039213Sgibbs case IFT_L2VLAN: 18139213Sgibbs case IFT_IP: 182111206Sken case IFT_IPOVERCDLC: 183111206Sken case IFT_IPOVERCLAW: 184111206Sken case IFT_VIRTUALIPADDRESS: 185111206Sken result = 1; 186111206Sken break; 18739213Sgibbs default: 188111206Sken result = 0; 189111206Sken } 190111206Sken 191111206Sken return (result); 192111206Sken} 193111206Sken 194111206Sken 195111206Sken 196111206Sken 197111206Skenstatic void 19839213Sgibbssctp_init_ifns_for_vrf(int vrfid) 19939213Sgibbs{ 20039213Sgibbs /* 20139213Sgibbs * Here we must apply ANY locks needed by the IFN we access and also 20239213Sgibbs * make sure we lock any IFA that exists as we float through the 20339213Sgibbs * list of IFA's 20439213Sgibbs */ 20539213Sgibbs struct ifnet *ifn; 20654451Sken struct ifaddr *ifa; 20739213Sgibbs struct in6_ifaddr *ifa6; 20840262Sken struct sctp_ifa *sctp_ifa; 20940262Sken uint32_t ifa_flags; 21067752Sken 21167752Sken#if 0 21267752Sken IFNET_RLOCK(); 21367752Sken#endif 21440262Sken TAILQ_FOREACH(ifn, &MODULE_GLOBAL(ifnet), if_list) { 21540262Sken IF_ADDR_LOCK(ifn); 21639213Sgibbs TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list) { 21739213Sgibbs if (ifa->ifa_addr == NULL) { 21839213Sgibbs continue; 219120599Sphk } 220120599Sphk if ((ifa->ifa_addr->sa_family != AF_INET) && (ifa->ifa_addr->sa_family != AF_INET6)) { 221120599Sphk /* non inet/inet6 skip */ 222120599Sphk continue; 22339213Sgibbs } 22439213Sgibbs if (ifa->ifa_addr->sa_family == AF_INET6) { 22539213Sgibbs if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) { 22639213Sgibbs /* skip unspecifed addresses */ 22739213Sgibbs continue; 22840603Sken } 22939213Sgibbs } else { 23039213Sgibbs if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) { 231111206Sken continue; 23239213Sgibbs } 23339213Sgibbs } 23439213Sgibbs if (sctp_is_desired_interface_type(ifa) == 0) { 23539213Sgibbs /* non desired type */ 23639213Sgibbs continue; 23739213Sgibbs } 23839213Sgibbs if (ifa->ifa_addr->sa_family == AF_INET6) { 23939213Sgibbs ifa6 = (struct in6_ifaddr *)ifa; 24039213Sgibbs ifa_flags = ifa6->ia6_flags; 241111206Sken } else { 24239213Sgibbs ifa_flags = 0; 24339213Sgibbs } 24439213Sgibbs sctp_ifa = sctp_add_addr_to_vrf(vrfid, 245111206Sken (void *)ifn, 246111206Sken ifn->if_index, 247111206Sken ifn->if_type, 248111206Sken ifn->if_xname, 249111206Sken (void *)ifa, 250111206Sken ifa->ifa_addr, 25139213Sgibbs ifa_flags, 25239213Sgibbs 0); 25339213Sgibbs if (sctp_ifa) { 254111206Sken sctp_ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE; 255111206Sken } 25639213Sgibbs } 257111206Sken IF_ADDR_UNLOCK(ifn); 25839213Sgibbs } 259111206Sken#if 0 26039213Sgibbs IFNET_RUNLOCK(); 26139213Sgibbs#endif 26239213Sgibbs} 26339213Sgibbs 26439213Sgibbsvoid 26539213Sgibbssctp_init_vrf_list(int vrfid) 26639213Sgibbs{ 26739213Sgibbs if (vrfid > SCTP_MAX_VRF_ID) 26839213Sgibbs /* can't do that */ 26939213Sgibbs return; 27039213Sgibbs 27139213Sgibbs /* Don't care about return here */ 27239213Sgibbs (void)sctp_allocate_vrf(vrfid); 27339213Sgibbs 27439213Sgibbs /* 27539213Sgibbs * Now we need to build all the ifn's for this vrf and there 276111206Sken * addresses 277105421Snjl */ 278105421Snjl sctp_init_ifns_for_vrf(vrfid); 27960422Sken} 28060422Sken 28160422Skenvoid 28260422Skensctp_addr_change(struct ifaddr *ifa, int cmd) 28360422Sken{ 28460422Sken struct sctp_ifa *ifap = NULL; 28539213Sgibbs uint32_t ifa_flags = 0; 28639213Sgibbs 28739213Sgibbs /* 28839213Sgibbs * BSD only has one VRF, if this changes we will need to hook in the 28939213Sgibbs * right things here to get the id to pass to the address managment 29039213Sgibbs * routine. 29139213Sgibbs */ 29272119Speter if (SCTP_BASE_VAR(first_time) == 0) { 29339213Sgibbs /* Special test to see if my ::1 will showup with this */ 294186882Simp SCTP_BASE_VAR(first_time) = 1; 295186882Simp sctp_init_ifns_for_vrf(SCTP_DEFAULT_VRFID); 296186882Simp } 29739213Sgibbs if ((cmd != RTM_ADD) && (cmd != RTM_DELETE)) { 29846747Sken /* don't know what to do with this */ 29939213Sgibbs return; 30039213Sgibbs } 30146747Sken if (ifa->ifa_addr == NULL) { 30239213Sgibbs return; 30339213Sgibbs } 304186882Simp if ((ifa->ifa_addr->sa_family != AF_INET) && (ifa->ifa_addr->sa_family != AF_INET6)) { 30539213Sgibbs /* non inet/inet6 skip */ 30639213Sgibbs return; 30739213Sgibbs } 308227309Sed if (ifa->ifa_addr->sa_family == AF_INET6) { 309227309Sed ifa_flags = ((struct in6_ifaddr *)ifa)->ia6_flags; 310227309Sed if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) { 311186882Simp /* skip unspecifed addresses */ 312186882Simp return; 313186882Simp } 31439213Sgibbs } else { 31539213Sgibbs if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) { 316111206Sken return; 31739213Sgibbs } 31839213Sgibbs } 319111206Sken 32039213Sgibbs if (sctp_is_desired_interface_type(ifa) == 0) { 32139213Sgibbs /* non desired type */ 32239213Sgibbs return; 32339213Sgibbs } 32439213Sgibbs if (cmd == RTM_ADD) { 32539213Sgibbs ifap = sctp_add_addr_to_vrf(SCTP_DEFAULT_VRFID, (void *)ifa->ifa_ifp, 32639213Sgibbs ifa->ifa_ifp->if_index, ifa->ifa_ifp->if_type, 32739213Sgibbs ifa->ifa_ifp->if_xname, 328168752Sscottl (void *)ifa, ifa->ifa_addr, ifa_flags, 1); 329168752Sscottl } else { 33046581Sken 33160938Sjake sctp_del_addr_from_vrf(SCTP_DEFAULT_VRFID, ifa->ifa_addr, 33260938Sjake ifa->ifa_ifp->if_index, 33339213Sgibbs ifa->ifa_ifp->if_xname 33439213Sgibbs ); 335168752Sscottl /* 33660938Sjake * We don't bump refcount here so when it completes the 337168752Sscottl * final delete will happen. 33839213Sgibbs */ 339227293Sed } 340169562Sscottl} 341104880Sphk 34239213Sgibbsvoid 34339213Sgibbs sctp_add_or_del_interfaces(int (*pred) (struct ifnet *), int add){ 34439213Sgibbs struct ifnet *ifn; 34539213Sgibbs struct ifaddr *ifa; 346168752Sscottl 347168752Sscottl#if 0 348168752Sscottl IFNET_RLOCK(); 34939213Sgibbs#endif 35039213Sgibbs TAILQ_FOREACH(ifn, &MODULE_GLOBAL(ifnet), if_list) { 35139213Sgibbs if (!(*pred) (ifn)) { 35239213Sgibbs continue; 353169605Sscottl } 35439213Sgibbs TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list) { 35539213Sgibbs sctp_addr_change(ifa, add ? RTM_ADD : RTM_DELETE); 35639213Sgibbs } 35739213Sgibbs } 35839213Sgibbs#if 0 35939213Sgibbs IFNET_RUNLOCK(); 36039213Sgibbs#endif 36139213Sgibbs} 36240603Sken 36340603Skenstruct mbuf * 36440603Skensctp_get_mbuf_for_msg(unsigned int space_needed, int want_header, 36540603Sken int how, int allonebuf, int type) 36640603Sken{ 36740603Sken struct mbuf *m = NULL; 36840603Sken 36940603Sken m = m_getm2(NULL, space_needed, how, type, want_header ? M_PKTHDR : 0); 37040603Sken if (m == NULL) { 371169605Sscottl /* bad, no memory */ 37240603Sken return (m); 37340603Sken } 37440603Sken if (allonebuf) { 37540603Sken int siz; 37640603Sken 37740603Sken if (SCTP_BUF_IS_EXTENDED(m)) { 37840603Sken siz = SCTP_BUF_EXTEND_SIZE(m); 37940603Sken } else { 380112946Sphk if (want_header) 38140603Sken siz = MHLEN; 38240603Sken else 38340603Sken siz = MLEN; 38440603Sken } 38540603Sken if (siz < space_needed) { 38640603Sken m_freem(m); 38740603Sken return (NULL); 38840603Sken } 38940603Sken } 39040603Sken if (SCTP_BUF_NEXT(m)) { 391152565Sjdp sctp_m_freem(SCTP_BUF_NEXT(m)); 392164906Smjacob SCTP_BUF_NEXT(m) = NULL; 39340603Sken } 39440603Sken#ifdef SCTP_MBUF_LOGGING 39540603Sken if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { 39639213Sgibbs if (SCTP_BUF_IS_EXTENDED(m)) { 39739213Sgibbs sctp_log_mb(m, SCTP_MBUF_IALLOC); 39839213Sgibbs } 39939213Sgibbs } 40039213Sgibbs#endif 40139213Sgibbs return (m); 402164906Smjacob} 40340603Sken 40439213Sgibbs 40539213Sgibbs#ifdef SCTP_PACKET_LOGGING 40639213Sgibbsvoid 40739213Sgibbssctp_packet_log(struct mbuf *m, int length) 40839213Sgibbs{ 40939213Sgibbs int *lenat, thisone; 41039213Sgibbs void *copyto; 41139213Sgibbs uint32_t *tick_tock; 41239213Sgibbs int total_len; 41339213Sgibbs int grabbed_lock = 0; 41439213Sgibbs int value, newval, thisend, thisbegin; 41539213Sgibbs 41639213Sgibbs /* 41739213Sgibbs * Buffer layout. -sizeof this entry (total_len) -previous end 41839213Sgibbs * (value) -ticks of log (ticks) o -ip packet o -as logged - 41939213Sgibbs * where this started (thisbegin) x <--end points here 42039213Sgibbs */ 42139213Sgibbs total_len = SCTP_SIZE32((length + (4 * sizeof(int)))); 42239213Sgibbs /* Log a packet to the buffer. */ 42339213Sgibbs if (total_len > SCTP_PACKET_LOG_SIZE) { 42439213Sgibbs /* Can't log this packet I have not a buffer big enough */ 42539213Sgibbs return; 42639213Sgibbs } 42739213Sgibbs if (length < (int)(SCTP_MIN_V4_OVERHEAD + sizeof(struct sctp_cookie_ack_chunk))) { 42839213Sgibbs return; 42939213Sgibbs } 43039213Sgibbs atomic_add_int(&SCTP_BASE_VAR(packet_log_writers), 1); 43139213Sgibbstry_again: 43239213Sgibbs if (SCTP_BASE_VAR(packet_log_writers) > SCTP_PKTLOG_WRITERS_NEED_LOCK) { 433168752Sscottl SCTP_IP_PKTLOG_LOCK(); 43439213Sgibbs grabbed_lock = 1; 43539213Sgibbsagain_locked: 436203108Smav value = SCTP_BASE_VAR(packet_log_end); 43739213Sgibbs newval = SCTP_BASE_VAR(packet_log_end) + total_len; 43839213Sgibbs if (newval >= SCTP_PACKET_LOG_SIZE) { 43939213Sgibbs /* we wrapped */ 44039213Sgibbs thisbegin = 0; 44139213Sgibbs thisend = total_len; 44239213Sgibbs } else { 44339213Sgibbs thisbegin = SCTP_BASE_VAR(packet_log_end); 44439213Sgibbs thisend = newval; 44539213Sgibbs } 44639213Sgibbs if (!(atomic_cmpset_int(&SCTP_BASE_VAR(packet_log_end), value, thisend))) { 44739213Sgibbs goto again_locked; 44839213Sgibbs } 44939213Sgibbs } else { 45039213Sgibbs value = SCTP_BASE_VAR(packet_log_end); 45139213Sgibbs newval = SCTP_BASE_VAR(packet_log_end) + total_len; 45239213Sgibbs if (newval >= SCTP_PACKET_LOG_SIZE) { 45339213Sgibbs /* we wrapped */ 454168752Sscottl thisbegin = 0; 45539213Sgibbs thisend = total_len; 45639213Sgibbs } else { 45739213Sgibbs thisbegin = SCTP_BASE_VAR(packet_log_end); 45839213Sgibbs thisend = newval; 459168752Sscottl } 46039213Sgibbs if (!(atomic_cmpset_int(&SCTP_BASE_VAR(packet_log_end), value, thisend))) { 46139213Sgibbs goto try_again; 46239213Sgibbs } 463168752Sscottl } 46460938Sjake /* Sanity check */ 46539213Sgibbs if (thisend >= SCTP_PACKET_LOG_SIZE) { 466168752Sscottl printf("Insanity stops a log thisbegin:%d thisend:%d writers:%d lock:%d end:%d\n", 467168752Sscottl thisbegin, 468164906Smjacob thisend, 46939213Sgibbs SCTP_BASE_VAR(packet_log_writers), 47039213Sgibbs grabbed_lock, 471168786Sscottl SCTP_BASE_VAR(packet_log_end)); 472188503Sjhb SCTP_BASE_VAR(packet_log_end) = 0; 473188503Sjhb goto no_log; 474188503Sjhb 475188503Sjhb } 476188503Sjhb lenat = (int *)&SCTP_BASE_VAR(packet_log_buffer)[thisbegin]; 477125975Sphk *lenat = total_len; 478188503Sjhb lenat++; 479168786Sscottl *lenat = value; 48039213Sgibbs lenat++; 48139213Sgibbs tick_tock = (uint32_t *) lenat; 48239213Sgibbs lenat++; 48339213Sgibbs *tick_tock = sctp_get_tick_count(); 48439213Sgibbs copyto = (void *)lenat; 48539213Sgibbs thisone = thisend - sizeof(int); 48639213Sgibbs lenat = (int *)&SCTP_BASE_VAR(packet_log_buffer)[thisone]; 48739213Sgibbs *lenat = thisbegin; 48839213Sgibbs if (grabbed_lock) { 48939213Sgibbs SCTP_IP_PKTLOG_UNLOCK(); 49039213Sgibbs grabbed_lock = 0; 49139213Sgibbs } 49239213Sgibbs m_copydata(m, 0, length, (caddr_t)copyto); 49339213Sgibbsno_log: 49439213Sgibbs if (grabbed_lock) { 49539213Sgibbs SCTP_IP_PKTLOG_UNLOCK(); 49679177Smjacob } 49779177Smjacob atomic_subtract_int(&SCTP_BASE_VAR(packet_log_writers), 1); 49839213Sgibbs} 499195534Sscottl 500195534Sscottl 501195534Sscottlint 50256148Smjacobsctp_copy_out_packet_log(uint8_t * target, int length) 50356148Smjacob{ 50439213Sgibbs /* 50539213Sgibbs * We wind through the packet log starting at start copying up to 50639213Sgibbs * length bytes out. We return the number of bytes copied. 50739213Sgibbs */ 50839213Sgibbs int tocopy, this_copy; 50939213Sgibbs int *lenat; 51039213Sgibbs int did_delay = 0; 51140603Sken 51240603Sken tocopy = length; 51340603Sken if (length < (int)(2 * sizeof(int))) { 51440603Sken /* not enough room */ 51540603Sken return (0); 51639213Sgibbs } 51739213Sgibbs if (SCTP_PKTLOG_WRITERS_NEED_LOCK) { 51839213Sgibbs atomic_add_int(&SCTP_BASE_VAR(packet_log_writers), SCTP_PKTLOG_WRITERS_NEED_LOCK); 51939213Sgibbsagain: 52039213Sgibbs if ((did_delay == 0) && (SCTP_BASE_VAR(packet_log_writers) != SCTP_PKTLOG_WRITERS_NEED_LOCK)) { 52139213Sgibbs /* 52239213Sgibbs * we delay here for just a moment hoping the 52339213Sgibbs * writer(s) that were present when we entered will 52439213Sgibbs * have left and we only have locking ones that will 52539213Sgibbs * contend with us for the lock. This does not 52639213Sgibbs * assure 100% access, but its good enough for a 52739213Sgibbs * logging facility like this. 52839213Sgibbs */ 52939213Sgibbs did_delay = 1; 53039213Sgibbs DELAY(10); 53139213Sgibbs goto again; 53239213Sgibbs } 53339213Sgibbs } 53439213Sgibbs SCTP_IP_PKTLOG_LOCK(); 53539213Sgibbs lenat = (int *)target; 53671999Sphk *lenat = SCTP_BASE_VAR(packet_log_end); 53739213Sgibbs lenat++; 53847413Sgibbs this_copy = min((length - sizeof(int)), SCTP_PACKET_LOG_SIZE); 53939213Sgibbs memcpy((void *)lenat, (void *)SCTP_BASE_VAR(packet_log_buffer), this_copy); 54039213Sgibbs if (SCTP_PKTLOG_WRITERS_NEED_LOCK) { 54147413Sgibbs atomic_subtract_int(&SCTP_BASE_VAR(packet_log_writers), 54239213Sgibbs SCTP_PKTLOG_WRITERS_NEED_LOCK); 54339213Sgibbs } 54439213Sgibbs SCTP_IP_PKTLOG_UNLOCK(); 54539213Sgibbs return (this_copy + sizeof(int)); 546119708Sken} 547119708Sken 548119708Sken#endif 549119708Sken