LCOV - code coverage report
Current view: top level - netwerk/sctp/src/netinet - sctp_bsd_addr.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 59 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 8 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-
       2             :  * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
       3             :  * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
       4             :  * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
       5             :  *
       6             :  * Redistribution and use in source and binary forms, with or without
       7             :  * modification, are permitted provided that the following conditions are met:
       8             :  *
       9             :  * a) Redistributions of source code must retain the above copyright notice,
      10             :  *    this list of conditions and the following disclaimer.
      11             :  *
      12             :  * b) Redistributions in binary form must reproduce the above copyright
      13             :  *    notice, this list of conditions and the following disclaimer in
      14             :  *    the documentation and/or other materials provided with the distribution.
      15             :  *
      16             :  * c) Neither the name of Cisco Systems, Inc. nor the names of its
      17             :  *    contributors may be used to endorse or promote products derived
      18             :  *    from this software without specific prior written permission.
      19             :  *
      20             :  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      21             :  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
      22             :  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      23             :  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
      24             :  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      25             :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      26             :  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      27             :  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      28             :  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      29             :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
      30             :  * THE POSSIBILITY OF SUCH DAMAGE.
      31             :  */
      32             : 
      33             : #ifdef __FreeBSD__
      34             : #include <sys/cdefs.h>
      35             : __FBSDID("$FreeBSD: head/sys/netinet/sctp_bsd_addr.c 276914 2015-01-10 20:49:57Z tuexen $");
      36             : #endif
      37             : 
      38             : #include <netinet/sctp_os.h>
      39             : #include <netinet/sctp_var.h>
      40             : #include <netinet/sctp_pcb.h>
      41             : #include <netinet/sctp_header.h>
      42             : #include <netinet/sctputil.h>
      43             : #include <netinet/sctp_output.h>
      44             : #include <netinet/sctp_bsd_addr.h>
      45             : #include <netinet/sctp_uio.h>
      46             : #include <netinet/sctputil.h>
      47             : #include <netinet/sctp_timer.h>
      48             : #include <netinet/sctp_asconf.h>
      49             : #include <netinet/sctp_sysctl.h>
      50             : #include <netinet/sctp_indata.h>
      51             : #if defined(ANDROID)
      52             : #include <unistd.h>
      53             : #include <ifaddrs-android-ext.h>
      54             : #else
      55             : #if defined(__FreeBSD__)
      56             : #include <sys/unistd.h>
      57             : #endif
      58             : #endif
      59             : 
      60             : /* Declare all of our malloc named types */
      61             : #ifndef __Panda__
      62             : MALLOC_DEFINE(SCTP_M_MAP, "sctp_map", "sctp asoc map descriptor");
      63             : MALLOC_DEFINE(SCTP_M_STRMI, "sctp_stri", "sctp stream in array");
      64             : MALLOC_DEFINE(SCTP_M_STRMO, "sctp_stro", "sctp stream out array");
      65             : MALLOC_DEFINE(SCTP_M_ASC_ADDR, "sctp_aadr", "sctp asconf address");
      66             : MALLOC_DEFINE(SCTP_M_ASC_IT, "sctp_a_it", "sctp asconf iterator");
      67             : MALLOC_DEFINE(SCTP_M_AUTH_CL, "sctp_atcl", "sctp auth chunklist");
      68             : MALLOC_DEFINE(SCTP_M_AUTH_KY, "sctp_atky", "sctp auth key");
      69             : MALLOC_DEFINE(SCTP_M_AUTH_HL, "sctp_athm", "sctp auth hmac list");
      70             : MALLOC_DEFINE(SCTP_M_AUTH_IF, "sctp_athi", "sctp auth info");
      71             : MALLOC_DEFINE(SCTP_M_STRESET, "sctp_stre", "sctp stream reset");
      72             : MALLOC_DEFINE(SCTP_M_CMSG, "sctp_cmsg", "sctp CMSG buffer");
      73             : MALLOC_DEFINE(SCTP_M_COPYAL, "sctp_cpal", "sctp copy all");
      74             : MALLOC_DEFINE(SCTP_M_VRF, "sctp_vrf", "sctp vrf struct");
      75             : MALLOC_DEFINE(SCTP_M_IFA, "sctp_ifa", "sctp ifa struct");
      76             : MALLOC_DEFINE(SCTP_M_IFN, "sctp_ifn", "sctp ifn struct");
      77             : MALLOC_DEFINE(SCTP_M_TIMW, "sctp_timw", "sctp time block");
      78             : MALLOC_DEFINE(SCTP_M_MVRF, "sctp_mvrf", "sctp mvrf pcb list");
      79             : MALLOC_DEFINE(SCTP_M_ITER, "sctp_iter", "sctp iterator control");
      80             : MALLOC_DEFINE(SCTP_M_SOCKOPT, "sctp_socko", "sctp socket option");
      81             : MALLOC_DEFINE(SCTP_M_MCORE, "sctp_mcore", "sctp mcore queue");
      82             : #endif
      83             : 
      84             : /* Global NON-VNET structure that controls the iterator */
      85             : struct iterator_control sctp_it_ctl;
      86             : 
      87             : #if !defined(__FreeBSD__)
      88             : static void
      89           0 : sctp_cleanup_itqueue(void)
      90             : {
      91             :         struct sctp_iterator *it, *nit;
      92             : 
      93           0 :         TAILQ_FOREACH_SAFE(it, &sctp_it_ctl.iteratorhead, sctp_nxt_itr, nit) {
      94           0 :                 if (it->function_atend != NULL) {
      95           0 :                         (*it->function_atend) (it->pointer, it->val);
      96             :                 }
      97           0 :                 TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, it, sctp_nxt_itr);
      98           0 :                 SCTP_FREE(it, SCTP_M_ITER);
      99             :         }
     100           0 : }
     101             : #endif
     102             : #if defined(__Userspace__)
     103             : /*__Userspace__ TODO if we use thread based iterator
     104             :  * then the implementation of wakeup will need to change.
     105             :  * Currently we are using timeo_cond for ident so_timeo
     106             :  * but that is not sufficient if we need to use another ident
     107             :  * like wakeup(&sctppcbinfo.iterator_running);
     108             :  */
     109             : #endif
     110             : 
     111             : void
     112           0 : sctp_wakeup_iterator(void)
     113             : {
     114             : #if defined(SCTP_PROCESS_LEVEL_LOCKS)
     115             : #if defined(__Userspace_os_Windows)
     116             :         WakeAllConditionVariable(&sctp_it_ctl.iterator_wakeup);
     117             : #else
     118           0 :         pthread_cond_broadcast(&sctp_it_ctl.iterator_wakeup);
     119             : #endif
     120             : #else
     121             :         wakeup(&sctp_it_ctl.iterator_running);
     122             : #endif
     123           0 : }
     124             : 
     125             : #if defined(__Userspace__)
     126             : static void *
     127             : #else
     128             : static void
     129             : #endif
     130           0 : sctp_iterator_thread(void *v SCTP_UNUSED)
     131             : {
     132           0 :         SCTP_IPI_ITERATOR_WQ_LOCK();
     133             :         /* In FreeBSD this thread never terminates. */
     134             : #if defined(__FreeBSD__)
     135             :         for (;;) {
     136             : #else
     137           0 :         while ((sctp_it_ctl.iterator_flags & SCTP_ITERATOR_MUST_EXIT) == 0) {
     138             : #endif
     139             : #if !defined(__Userspace__)
     140             :                 msleep(&sctp_it_ctl.iterator_running,
     141             : #if defined(__FreeBSD__)
     142             :                        &sctp_it_ctl.ipi_iterator_wq_mtx,
     143             : #elif defined(__APPLE__) || defined(__Userspace_os_Darwin)
     144             :                        sctp_it_ctl.ipi_iterator_wq_mtx,
     145             : #endif
     146             :                        0, "waiting_for_work", 0);
     147             : #else
     148             : #if defined(__Userspace_os_Windows)
     149             :                 SleepConditionVariableCS(&sctp_it_ctl.iterator_wakeup, &sctp_it_ctl.ipi_iterator_wq_mtx, INFINITE);
     150             : #else
     151           0 :                 pthread_cond_wait(&sctp_it_ctl.iterator_wakeup, &sctp_it_ctl.ipi_iterator_wq_mtx);
     152             : #endif
     153             : #endif
     154             : #if !defined(__FreeBSD__)
     155           0 :                 if (sctp_it_ctl.iterator_flags & SCTP_ITERATOR_MUST_EXIT) {
     156           0 :                         break;
     157             :                 }
     158             : #endif
     159           0 :                 sctp_iterator_worker();
     160             :         }
     161             : #if !defined(__FreeBSD__)
     162             :         /* Now this thread needs to be terminated */
     163           0 :         sctp_cleanup_itqueue();
     164           0 :         sctp_it_ctl.iterator_flags |= SCTP_ITERATOR_EXITED;
     165           0 :         SCTP_IPI_ITERATOR_WQ_UNLOCK();
     166             : #if defined(__Userspace__)
     167           0 :         sctp_wakeup_iterator();
     168           0 :         return (NULL);
     169             : #else
     170             :         wakeup(&sctp_it_ctl.iterator_flags);
     171             :         thread_terminate(current_thread());
     172             : #ifdef INVARIANTS
     173             :         panic("Hmm. thread_terminate() continues...");
     174             : #endif
     175             : #endif
     176             : #endif
     177             : }
     178             : 
     179             : void
     180           0 : sctp_startup_iterator(void)
     181             : {
     182           0 :         if (sctp_it_ctl.thread_proc) {
     183             :                 /* You only get one */
     184           0 :                 return;
     185             :         }
     186             :         /* Initialize global locks here, thus only once. */
     187           0 :         SCTP_ITERATOR_LOCK_INIT();
     188           0 :         SCTP_IPI_ITERATOR_WQ_INIT();
     189           0 :         TAILQ_INIT(&sctp_it_ctl.iteratorhead);
     190             : #if defined(__FreeBSD__)
     191             : #if __FreeBSD_version <= 701000
     192             :         kthread_create(sctp_iterator_thread,
     193             : #else
     194             :         kproc_create(sctp_iterator_thread,
     195             : #endif
     196             :                      (void *)NULL,
     197             :                      &sctp_it_ctl.thread_proc,
     198             :                      RFPROC,
     199             :                      SCTP_KTHREAD_PAGES,
     200             :                      SCTP_KTRHEAD_NAME);
     201             : #elif defined(__APPLE__)
     202             :         kernel_thread_start((thread_continue_t)sctp_iterator_thread, NULL, &sctp_it_ctl.thread_proc);
     203             : #elif defined(__Userspace__)
     204             : #if defined(__Userspace_os_Windows)
     205             :         if ((sctp_it_ctl.thread_proc = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&sctp_iterator_thread, NULL, 0, NULL)) == NULL) {
     206             : #else
     207           0 :         if (pthread_create(&sctp_it_ctl.thread_proc, NULL, &sctp_iterator_thread, NULL)) {
     208             : #endif
     209           0 :                 SCTP_PRINTF("ERROR: Creating sctp_iterator_thread failed.\n");
     210             :         }
     211             : #endif
     212             : }
     213             : 
     214             : #ifdef INET6
     215             : 
     216             : #if defined(__Userspace__)
     217             : /* __Userspace__ TODO. struct in6_ifaddr is defined in sys/netinet6/in6_var.h
     218             :    ip6_use_deprecated is defined as  int ip6_use_deprecated = 1; in /src/sys/netinet6/in6_proto.c
     219             :  */
     220             : void
     221             : sctp_gather_internal_ifa_flags(struct sctp_ifa *ifa)
     222             : {
     223             :     return; /* stub */
     224             : }
     225             : #else
     226             : void
     227             : sctp_gather_internal_ifa_flags(struct sctp_ifa *ifa)
     228             : {
     229             :         struct in6_ifaddr *ifa6;
     230             : 
     231             :         ifa6 = (struct in6_ifaddr *)ifa->ifa;
     232             :         ifa->flags = ifa6->ia6_flags;
     233             :         if (!MODULE_GLOBAL(ip6_use_deprecated)) {
     234             :                 if (ifa->flags &
     235             :                     IN6_IFF_DEPRECATED) {
     236             :                         ifa->localifa_flags |= SCTP_ADDR_IFA_UNUSEABLE;
     237             :                 } else {
     238             :                         ifa->localifa_flags &= ~SCTP_ADDR_IFA_UNUSEABLE;
     239             :                 }
     240             :         } else {
     241             :                 ifa->localifa_flags &= ~SCTP_ADDR_IFA_UNUSEABLE;
     242             :         }
     243             :         if (ifa->flags &
     244             :             (IN6_IFF_DETACHED |
     245             :              IN6_IFF_ANYCAST |
     246             :              IN6_IFF_NOTREADY)) {
     247             :                 ifa->localifa_flags |= SCTP_ADDR_IFA_UNUSEABLE;
     248             :         } else {
     249             :                 ifa->localifa_flags &= ~SCTP_ADDR_IFA_UNUSEABLE;
     250             :         }
     251             : }
     252             : #endif /* __Userspace__ */
     253             : #endif /* INET6 */
     254             : 
     255             : 
     256             : #if !defined(__Userspace__)
     257             : static uint32_t
     258             : sctp_is_desired_interface_type(struct ifnet *ifn)
     259             : {
     260             :         int result;
     261             : 
     262             :         /* check the interface type to see if it's one we care about */
     263             : #if defined(__APPLE__)
     264             :         switch(ifnet_type(ifn)) {
     265             : #else
     266             :         switch (ifn->if_type) {
     267             : #endif
     268             :         case IFT_ETHER:
     269             :         case IFT_ISO88023:
     270             :         case IFT_ISO88024:
     271             :         case IFT_ISO88025:
     272             :         case IFT_ISO88026:
     273             :         case IFT_STARLAN:
     274             :         case IFT_P10:
     275             :         case IFT_P80:
     276             :         case IFT_HY:
     277             :         case IFT_FDDI:
     278             :         case IFT_XETHER:
     279             :         case IFT_ISDNBASIC:
     280             :         case IFT_ISDNPRIMARY:
     281             :         case IFT_PTPSERIAL:
     282             :         case IFT_OTHER:
     283             :         case IFT_PPP:
     284             :         case IFT_LOOP:
     285             :         case IFT_SLIP:
     286             :         case IFT_GIF:
     287             :         case IFT_L2VLAN:
     288             :         case IFT_STF:
     289             : #if !defined(__APPLE__)
     290             :         case IFT_IP:
     291             :         case IFT_IPOVERCDLC:
     292             :         case IFT_IPOVERCLAW:
     293             :         case IFT_PROPVIRTUAL: /* NetGraph Virtual too */
     294             :         case IFT_VIRTUALIPADDRESS:
     295             : #endif
     296             :                 result = 1;
     297             :                 break;
     298             :         default:
     299             :                 result = 0;
     300             :         }
     301             : 
     302             :         return (result);
     303             : }
     304             : #endif
     305             : 
     306             : #if defined(__APPLE__)
     307             : int
     308             : sctp_is_vmware_interface(struct ifnet *ifn)
     309             : {
     310             :         return (strncmp(ifnet_name(ifn), "vmnet", 5) == 0);
     311             : }
     312             : #endif
     313             : 
     314             : #if defined(__Userspace_os_Windows)
     315             : static void
     316             : sctp_init_ifns_for_vrf(int vrfid)
     317             : {
     318             : #if defined(INET) || defined(INET6)
     319             :         struct ifaddrs *ifa;
     320             :         struct sctp_ifa *sctp_ifa;
     321             :         DWORD Err, AdapterAddrsSize;
     322             :         PIP_ADAPTER_ADDRESSES pAdapterAddrs, pAdapt;
     323             :         PIP_ADAPTER_UNICAST_ADDRESS pUnicast;
     324             : #endif
     325             : 
     326             : #ifdef INET
     327             :         AdapterAddrsSize = 0;
     328             : 
     329             :         if ((Err = GetAdaptersAddresses(AF_INET, 0, NULL, NULL, &AdapterAddrsSize)) != 0) {
     330             :                 if ((Err != ERROR_BUFFER_OVERFLOW) && (Err != ERROR_INSUFFICIENT_BUFFER)) {
     331             :                         SCTP_PRINTF("GetAdaptersV4Addresses() sizing failed with error code %d\n", Err);
     332             :                         SCTP_PRINTF("err = %d; AdapterAddrsSize = %d\n", Err, AdapterAddrsSize);
     333             :                         return;
     334             :                 }
     335             :         }
     336             : 
     337             :         /* Allocate memory from sizing information */
     338             :         if ((pAdapterAddrs = (PIP_ADAPTER_ADDRESSES) GlobalAlloc(GPTR, AdapterAddrsSize)) == NULL) {
     339             :                 SCTP_PRINTF("Memory allocation error!\n");
     340             :                 return;
     341             :         }
     342             :         /* Get actual adapter information */
     343             :         if ((Err = GetAdaptersAddresses(AF_INET, 0, NULL, pAdapterAddrs, &AdapterAddrsSize)) != ERROR_SUCCESS) {
     344             :                 SCTP_PRINTF("GetAdaptersV4Addresses() failed with error code %d\n", Err);
     345             :                 return;
     346             :         }
     347             :         /* Enumerate through each returned adapter and save its information */
     348             :         for (pAdapt = pAdapterAddrs; pAdapt; pAdapt = pAdapt->Next) {
     349             :                 if (pAdapt->IfType == IF_TYPE_IEEE80211 || pAdapt->IfType == IF_TYPE_ETHERNET_CSMACD) {
     350             :                         for (pUnicast = pAdapt->FirstUnicastAddress; pUnicast; pUnicast = pUnicast->Next) {
     351             :                                 if (IN4_ISLINKLOCAL_ADDRESS(&(((struct sockaddr_in *)(pUnicast->Address.lpSockaddr))->sin_addr))) {
     352             :                                         continue;
     353             :                                 }
     354             :                                 ifa = (struct ifaddrs*)malloc(sizeof(struct ifaddrs));
     355             :                                 ifa->ifa_name = _strdup(pAdapt->AdapterName);
     356             :                                 ifa->ifa_flags = pAdapt->Flags;
     357             :                                 ifa->ifa_addr = (struct sockaddr *)malloc(sizeof(struct sockaddr_in));
     358             :                                 memcpy(ifa->ifa_addr, pUnicast->Address.lpSockaddr, sizeof(struct sockaddr_in));
     359             : 
     360             :                                 sctp_ifa = sctp_add_addr_to_vrf(0,
     361             :                                                                 ifa,
     362             :                                                                 pAdapt->IfIndex,
     363             :                                                                 (pAdapt->IfType == IF_TYPE_IEEE80211)?MIB_IF_TYPE_ETHERNET:pAdapt->IfType,
     364             :                                                                 ifa->ifa_name,
     365             :                                                                 (void *)ifa,
     366             :                                                                 ifa->ifa_addr,
     367             :                                                                 ifa->ifa_flags,
     368             :                                                                 0);
     369             :                                 if (sctp_ifa) {
     370             :                                         sctp_ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE;
     371             :                                 }
     372             :                         }
     373             :                 }
     374             :         }
     375             :         if (pAdapterAddrs)
     376             :                 GlobalFree(pAdapterAddrs);
     377             : #endif
     378             : #ifdef INET6
     379             :         AdapterAddrsSize = 0;
     380             : 
     381             :         if ((Err = GetAdaptersAddresses(AF_INET6, 0, NULL, NULL, &AdapterAddrsSize)) != 0) {
     382             :                 if ((Err != ERROR_BUFFER_OVERFLOW) && (Err != ERROR_INSUFFICIENT_BUFFER)) {
     383             :                         SCTP_PRINTF("GetAdaptersV6Addresses() sizing failed with error code %d\n", Err);
     384             :                         SCTP_PRINTF("err = %d; AdapterAddrsSize = %d\n", Err, AdapterAddrsSize);
     385             :                         return;
     386             :                 }
     387             :         }
     388             :         /* Allocate memory from sizing information */
     389             :         if ((pAdapterAddrs = (PIP_ADAPTER_ADDRESSES) GlobalAlloc(GPTR, AdapterAddrsSize)) == NULL) {
     390             :                 SCTP_PRINTF("Memory allocation error!\n");
     391             :                 return;
     392             :         }
     393             :         /* Get actual adapter information */
     394             :         if ((Err = GetAdaptersAddresses(AF_INET6, 0, NULL, pAdapterAddrs, &AdapterAddrsSize)) != ERROR_SUCCESS) {
     395             :                 SCTP_PRINTF("GetAdaptersV6Addresses() failed with error code %d\n", Err);
     396             :                 return;
     397             :         }
     398             :         /* Enumerate through each returned adapter and save its information */
     399             :         for (pAdapt = pAdapterAddrs; pAdapt; pAdapt = pAdapt->Next) {
     400             :                 if (pAdapt->IfType == IF_TYPE_IEEE80211 || pAdapt->IfType == IF_TYPE_ETHERNET_CSMACD) {
     401             :                         for (pUnicast = pAdapt->FirstUnicastAddress; pUnicast; pUnicast = pUnicast->Next) {
     402             :                                 ifa = (struct ifaddrs*)malloc(sizeof(struct ifaddrs));
     403             :                                 ifa->ifa_name = _strdup(pAdapt->AdapterName);
     404             :                                 ifa->ifa_flags = pAdapt->Flags;
     405             :                                 ifa->ifa_addr = (struct sockaddr *)malloc(sizeof(struct sockaddr_in6));
     406             :                                 memcpy(ifa->ifa_addr, pUnicast->Address.lpSockaddr, sizeof(struct sockaddr_in6));
     407             :                                 sctp_ifa = sctp_add_addr_to_vrf(0,
     408             :                                                                 ifa,
     409             :                                                                 pAdapt->Ipv6IfIndex,
     410             :                                                                 (pAdapt->IfType == IF_TYPE_IEEE80211)?MIB_IF_TYPE_ETHERNET:pAdapt->IfType,
     411             :                                                                 ifa->ifa_name,
     412             :                                                                 (void *)ifa,
     413             :                                                                 ifa->ifa_addr,
     414             :                                                                 ifa->ifa_flags,
     415             :                                                                 0);
     416             :                                 if (sctp_ifa) {
     417             :                                         sctp_ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE;
     418             :                                 }
     419             :                         }
     420             :                 }
     421             :         }
     422             :         if (pAdapterAddrs)
     423             :                 GlobalFree(pAdapterAddrs);
     424             : #endif
     425             : }
     426             : #elif defined(__Userspace__)
     427             : static void
     428           0 : sctp_init_ifns_for_vrf(int vrfid)
     429             : {
     430             : #if defined(INET) || defined(INET6)
     431             :         int rc;
     432             :         struct ifaddrs *ifa = NULL;
     433             :         struct sctp_ifa *sctp_ifa;
     434             :         uint32_t ifa_flags;
     435             : 
     436             :         rc = getifaddrs(&g_interfaces);
     437             :         if (rc != 0) {
     438             :                 return;
     439             :         }
     440             :         for (ifa = g_interfaces; ifa; ifa = ifa->ifa_next) {
     441             :                 if (ifa->ifa_addr == NULL) {
     442             :                         continue;
     443             :                 }
     444             : #if !defined(INET)
     445             :                 if (ifa->ifa_addr->sa_family != AF_INET6) {
     446             :                         /* non inet6 skip */
     447             :                         continue;
     448             :                 }
     449             : #elif !defined(INET6)
     450             :                 if (ifa->ifa_addr->sa_family != AF_INET) {
     451             :                         /* non inet skip */
     452             :                         continue;
     453             :                 }
     454             : #else
     455             :                 if ((ifa->ifa_addr->sa_family != AF_INET) && (ifa->ifa_addr->sa_family != AF_INET6)) {
     456             :                         /* non inet/inet6 skip */
     457             :                         continue;
     458             :                 }
     459             : #endif
     460             : #if defined(INET6)
     461             :                 if ((ifa->ifa_addr->sa_family == AF_INET6) &&
     462             :                     IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) {
     463             :                         /* skip unspecifed addresses */
     464             :                         continue;
     465             :                 }
     466             : #endif
     467             : #if defined(INET)
     468             :                 if (ifa->ifa_addr->sa_family == AF_INET &&
     469             :                     ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) {
     470             :                         continue;
     471             :                 }
     472             : #endif
     473             :                 ifa_flags = 0;
     474             :                 sctp_ifa = sctp_add_addr_to_vrf(vrfid,
     475             :                                                 ifa,
     476             :                                                 if_nametoindex(ifa->ifa_name),
     477             :                                                 0,
     478             :                                                 ifa->ifa_name,
     479             :                                                 (void *)ifa,
     480             :                                                 ifa->ifa_addr,
     481             :                                                 ifa_flags,
     482             :                                                 0);
     483             :                 if (sctp_ifa) {
     484             :                         sctp_ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE;
     485             :                 }
     486             :         }
     487             : #endif
     488           0 : }
     489             : #endif
     490             : 
     491             : #if defined(__APPLE__)
     492             : static void
     493             : sctp_init_ifns_for_vrf(int vrfid)
     494             : {
     495             :         /* Here we must apply ANY locks needed by the
     496             :          * IFN we access and also make sure we lock
     497             :          * any IFA that exists as we float through the
     498             :          * list of IFA's
     499             :          */
     500             :         struct ifnet **ifnetlist;
     501             :         uint32_t i, j, count;
     502             :         char name[SCTP_IFNAMSIZ];
     503             :         struct ifnet *ifn;
     504             :         struct ifaddr **ifaddrlist;
     505             :         struct ifaddr *ifa;
     506             :         struct in6_ifaddr *ifa6;
     507             :         struct sctp_ifa *sctp_ifa;
     508             :         uint32_t ifa_flags;
     509             : 
     510             :         if (ifnet_list_get(IFNET_FAMILY_ANY, &ifnetlist, &count) != 0) {
     511             :                 return;
     512             :         }
     513             :         for (i = 0; i < count; i++) {
     514             :                 ifn = ifnetlist[i];
     515             :                 if (SCTP_BASE_SYSCTL(sctp_ignore_vmware_interfaces) && sctp_is_vmware_interface(ifn)) {
     516             :                         continue;
     517             :                 }
     518             :                 if (sctp_is_desired_interface_type(ifn) == 0) {
     519             :                         /* non desired type */
     520             :                         continue;
     521             :                 }
     522             :                 if (ifnet_get_address_list(ifn, &ifaddrlist) != 0) {
     523             :                         continue;
     524             :                 }
     525             :                 for (j = 0; ifaddrlist[j] != NULL; j++) {
     526             :                         ifa = ifaddrlist[j];
     527             :                         if (ifa->ifa_addr == NULL) {
     528             :                                 continue;
     529             :                         }
     530             :                         if ((ifa->ifa_addr->sa_family != AF_INET) && (ifa->ifa_addr->sa_family != AF_INET6)) {
     531             :                                 /* non inet/inet6 skip */
     532             :                                 continue;
     533             :                         }
     534             :                         if (ifa->ifa_addr->sa_family == AF_INET6) {
     535             :                                 if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) {
     536             :                                         /* skip unspecifed addresses */
     537             :                                         continue;
     538             :                                 }
     539             :                         } else {
     540             :                                 if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == INADDR_ANY) {
     541             :                                         continue;
     542             :                                 }
     543             :                         }
     544             :                         if (ifa->ifa_addr->sa_family == AF_INET6) {
     545             :                                 ifa6 = (struct in6_ifaddr *)ifa;
     546             :                                 ifa_flags = ifa6->ia6_flags;
     547             :                         } else {
     548             :                                 ifa_flags = 0;
     549             :                         }
     550             :                         snprintf(name, SCTP_IFNAMSIZ, "%s%d", ifnet_name(ifn), ifnet_unit(ifn));
     551             :                         sctp_ifa = sctp_add_addr_to_vrf(vrfid,
     552             :                                                         (void *)ifn,
     553             :                                                         ifnet_index(ifn),
     554             :                                                         ifnet_type(ifn),
     555             :                                                         name,
     556             :                                                         (void *)ifa,
     557             :                                                         ifa->ifa_addr,
     558             :                                                         ifa_flags,
     559             :                                                         0);
     560             :                         if (sctp_ifa) {
     561             :                                 sctp_ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE;
     562             :                         }
     563             :                 }
     564             :                 ifnet_free_address_list(ifaddrlist);
     565             :         }
     566             :         ifnet_list_free(ifnetlist);
     567             : }
     568             : #endif
     569             : 
     570             : #if defined(__FreeBSD__)
     571             : static void
     572             : sctp_init_ifns_for_vrf(int vrfid)
     573             : {
     574             :         /* Here we must apply ANY locks needed by the
     575             :          * IFN we access and also make sure we lock
     576             :          * any IFA that exists as we float through the
     577             :          * list of IFA's
     578             :          */
     579             :         struct ifnet *ifn;
     580             :         struct ifaddr *ifa;
     581             :         struct sctp_ifa *sctp_ifa;
     582             :         uint32_t ifa_flags;
     583             : #ifdef INET6
     584             :         struct in6_ifaddr *ifa6;
     585             : #endif
     586             : 
     587             :         IFNET_RLOCK();
     588             :         TAILQ_FOREACH(ifn, &MODULE_GLOBAL(ifnet), if_list) {
     589             :                 if (sctp_is_desired_interface_type(ifn) == 0) {
     590             :                         /* non desired type */
     591             :                         continue;
     592             :                 }
     593             : #if (__FreeBSD_version >= 803000 && __FreeBSD_version < 900000) || __FreeBSD_version > 900000
     594             :                 IF_ADDR_RLOCK(ifn);
     595             : #else
     596             :                 IF_ADDR_LOCK(ifn);
     597             : #endif
     598             :                 TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list) {
     599             :                         if (ifa->ifa_addr == NULL) {
     600             :                                 continue;
     601             :                         }
     602             :                         switch (ifa->ifa_addr->sa_family) {
     603             : #ifdef INET
     604             :                         case AF_INET:
     605             :                                 if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) {
     606             :                                         continue;
     607             :                                 }
     608             :                                 break;
     609             : #endif
     610             : #ifdef INET6
     611             :                         case AF_INET6:
     612             :                                 if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) {
     613             :                                         /* skip unspecifed addresses */
     614             :                                         continue;
     615             :                                 }
     616             :                                 break;
     617             : #endif
     618             :                         default:
     619             :                                 continue;
     620             :                         }
     621             :                         switch (ifa->ifa_addr->sa_family) {
     622             : #ifdef INET
     623             :                         case AF_INET:
     624             :                                 ifa_flags = 0;
     625             :                                 break;
     626             : #endif
     627             : #ifdef INET6
     628             :                         case AF_INET6:
     629             :                                 ifa6 = (struct in6_ifaddr *)ifa;
     630             :                                 ifa_flags = ifa6->ia6_flags;
     631             :                                 break;
     632             : #endif
     633             :                         default:
     634             :                                 ifa_flags = 0;
     635             :                                 break;
     636             :                         }
     637             :                         sctp_ifa = sctp_add_addr_to_vrf(vrfid,
     638             :                                                         (void *)ifn,
     639             :                                                         ifn->if_index,
     640             :                                                         ifn->if_type,
     641             :                                                         ifn->if_xname,
     642             :                                                         (void *)ifa,
     643             :                                                         ifa->ifa_addr,
     644             :                                                         ifa_flags,
     645             :                                                         0);
     646             :                         if (sctp_ifa) {
     647             :                                 sctp_ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE;
     648             :                         }
     649             :                 }
     650             : #if (__FreeBSD_version >= 803000 && __FreeBSD_version < 900000) || __FreeBSD_version > 900000
     651             :                 IF_ADDR_RUNLOCK(ifn);
     652             : #else
     653             :                 IF_ADDR_UNLOCK(ifn);
     654             : #endif
     655             :         }
     656             :         IFNET_RUNLOCK();
     657             : }
     658             : #endif
     659             : 
     660             : void
     661           0 : sctp_init_vrf_list(int vrfid)
     662             : {
     663           0 :         if (vrfid > SCTP_MAX_VRF_ID)
     664             :                 /* can't do that */
     665           0 :                 return;
     666             : 
     667             :         /* Don't care about return here */
     668           0 :         (void)sctp_allocate_vrf(vrfid);
     669             : 
     670             :         /* Now we need to build all the ifn's
     671             :          * for this vrf and there addresses
     672             :          */
     673           0 :         sctp_init_ifns_for_vrf(vrfid);
     674             : }
     675             : 
     676             : void
     677           0 : sctp_addr_change(struct ifaddr *ifa, int cmd)
     678             : {
     679             : #if defined(__Userspace__)
     680           0 :         return;
     681             : #else
     682             :         uint32_t ifa_flags = 0;
     683             :         /* BSD only has one VRF, if this changes
     684             :          * we will need to hook in the right
     685             :          * things here to get the id to pass to
     686             :          * the address managment routine.
     687             :          */
     688             :         if (SCTP_BASE_VAR(first_time) == 0) {
     689             :                 /* Special test to see if my ::1 will showup with this */
     690             :                 SCTP_BASE_VAR(first_time) = 1;
     691             :                 sctp_init_ifns_for_vrf(SCTP_DEFAULT_VRFID);
     692             :         }
     693             : 
     694             :         if ((cmd != RTM_ADD) && (cmd != RTM_DELETE)) {
     695             :                 /* don't know what to do with this */
     696             :                 return;
     697             :         }
     698             : 
     699             :         if (ifa->ifa_addr == NULL) {
     700             :                 return;
     701             :         }
     702             :         if (sctp_is_desired_interface_type(ifa->ifa_ifp) == 0) {
     703             :                 /* non desired type */
     704             :                 return;
     705             :         }
     706             :         switch (ifa->ifa_addr->sa_family) {
     707             : #ifdef INET
     708             :         case AF_INET:
     709             :                 if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) {
     710             :                         return;
     711             :                 }
     712             :                 break;
     713             : #endif
     714             : #ifdef INET6
     715             :         case AF_INET6:
     716             :                 ifa_flags = ((struct in6_ifaddr *)ifa)->ia6_flags;
     717             :                 if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) {
     718             :                         /* skip unspecifed addresses */
     719             :                         return;
     720             :                 }
     721             :                 break;
     722             : #endif
     723             :         default:
     724             :                 /* non inet/inet6 skip */
     725             :                 return;
     726             :         }
     727             :         if (cmd == RTM_ADD) {
     728             :                 (void)sctp_add_addr_to_vrf(SCTP_DEFAULT_VRFID, (void *)ifa->ifa_ifp,
     729             : #if defined(__APPLE__)
     730             :                                            ifnet_index(ifa->ifa_ifp), ifnet_type(ifa->ifa_ifp), ifnet_name(ifa->ifa_ifp),
     731             : #else
     732             :                                            ifa->ifa_ifp->if_index, ifa->ifa_ifp->if_type, ifa->ifa_ifp->if_xname,
     733             : #endif
     734             :                                            (void *)ifa, ifa->ifa_addr, ifa_flags, 1);
     735             :         } else {
     736             : 
     737             :                 sctp_del_addr_from_vrf(SCTP_DEFAULT_VRFID, ifa->ifa_addr,
     738             : #if defined(__APPLE__)
     739             :                                        ifnet_index(ifa->ifa_ifp),
     740             :                                        ifnet_name(ifa->ifa_ifp));
     741             : #else
     742             :                                        ifa->ifa_ifp->if_index,
     743             :                                        ifa->ifa_ifp->if_xname);
     744             : #endif
     745             : 
     746             :                 /* We don't bump refcount here so when it completes
     747             :                  * the final delete will happen.
     748             :                  */
     749             :         }
     750             : #endif
     751             : }
     752             : 
     753             : #if defined(__FreeBSD__)
     754             : void
     755             : sctp_add_or_del_interfaces(int (*pred)(struct ifnet *), int add)
     756             : {
     757             :         struct ifnet *ifn;
     758             :         struct ifaddr *ifa;
     759             : 
     760             :         IFNET_RLOCK();
     761             :         TAILQ_FOREACH(ifn, &MODULE_GLOBAL(ifnet), if_list) {
     762             :                 if (!(*pred)(ifn)) {
     763             :                         continue;
     764             :                 }
     765             :                 TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list) {
     766             :                         sctp_addr_change(ifa, add ? RTM_ADD : RTM_DELETE);
     767             :                 }
     768             :         }
     769             :         IFNET_RUNLOCK();
     770             : }
     771             : #endif
     772             : #if defined(__APPLE__)
     773             : void
     774             : sctp_add_or_del_interfaces(int (*pred)(struct ifnet *), int add)
     775             : {
     776             :         struct ifnet **ifnetlist;
     777             :         struct ifaddr **ifaddrlist;
     778             :         uint32_t i, j, count;
     779             : 
     780             :         if (ifnet_list_get(IFNET_FAMILY_ANY, &ifnetlist, &count) != 0) {
     781             :                 return;
     782             :         }
     783             :         for (i = 0; i < count; i++) {
     784             :                 if (!(*pred)(ifnetlist[i])) {
     785             :                         continue;
     786             :                 }
     787             :                 if (ifnet_get_address_list(ifnetlist[i], &ifaddrlist) != 0) {
     788             :                         continue;
     789             :                 }
     790             :                 for (j = 0; ifaddrlist[j] != NULL; j++) {
     791             :                         sctp_addr_change(ifaddrlist[j], add ? RTM_ADD : RTM_DELETE);
     792             :                 }
     793             :                 ifnet_free_address_list(ifaddrlist);
     794             :         }
     795             :         ifnet_list_free(ifnetlist);
     796             :         return;
     797             : }
     798             : #endif
     799             : 
     800             : struct mbuf *
     801           0 : sctp_get_mbuf_for_msg(unsigned int space_needed, int want_header,
     802             :                       int how, int allonebuf, int type)
     803             : {
     804           0 :     struct mbuf *m = NULL;
     805             : #if defined(__Userspace__)
     806             : 
     807             :   /*
     808             :    * __Userspace__
     809             :    * Using m_clget, which creates and mbuf and a cluster and
     810             :    * hooks those together.
     811             :    * TODO: This does not yet have functionality for jumbo packets.
     812             :    *
     813             :    */
     814             : 
     815             :         int mbuf_threshold;
     816           0 :         if (want_header) {
     817           0 :                 MGETHDR(m, how, type);
     818             :         } else {
     819           0 :                 MGET(m, how, type);
     820             :         }
     821           0 :         if (m == NULL) {
     822           0 :                 return (NULL);
     823             :         }
     824           0 :         if (allonebuf == 0)
     825           0 :                 mbuf_threshold = SCTP_BASE_SYSCTL(sctp_mbuf_threshold_count);
     826             :         else
     827           0 :                 mbuf_threshold = 1;
     828             : 
     829             : 
     830           0 :         if ((int)space_needed > (((mbuf_threshold - 1) * MLEN) + MHLEN)) {
     831           0 :                 MCLGET(m, how);
     832           0 :                 if (m == NULL) {
     833           0 :                         return (NULL);
     834             :                 }
     835             : 
     836           0 :                 if (SCTP_BUF_IS_EXTENDED(m) == 0) {
     837           0 :                         sctp_m_freem(m);
     838           0 :                         return (NULL);
     839             :                 }
     840             :         }
     841           0 :         SCTP_BUF_LEN(m) = 0;
     842           0 :         SCTP_BUF_NEXT(m) = SCTP_BUF_NEXT_PKT(m) = NULL;
     843             : 
     844             :         /* __Userspace__
     845             :          * Check if anything need to be done to ensure logging works
     846             :          */
     847             : #ifdef SCTP_MBUF_LOGGING
     848             :         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
     849             :                 sctp_log_mb(m, SCTP_MBUF_IALLOC);
     850             :         }
     851             : #endif
     852             : #elif defined(__FreeBSD__) && __FreeBSD_version > 1100052
     853             :         m =  m_getm2(NULL, space_needed, how, type, want_header ? M_PKTHDR : 0);
     854             :         if (m == NULL) {
     855             :                 /* bad, no memory */
     856             :                 return (m);
     857             :         }
     858             :         if (allonebuf) {
     859             :                 if (SCTP_BUF_SIZE(m) < space_needed) {
     860             :                         m_freem(m);
     861             :                         return (NULL);
     862             :                 }
     863             :         }
     864             :         if (SCTP_BUF_NEXT(m)) {
     865             :                 sctp_m_freem(SCTP_BUF_NEXT(m));
     866             :                 SCTP_BUF_NEXT(m) = NULL;
     867             :         }
     868             : #ifdef SCTP_MBUF_LOGGING
     869             :         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
     870             :                 sctp_log_mb(m, SCTP_MBUF_IALLOC);
     871             :         }
     872             : #endif
     873             : #elif defined(__FreeBSD__) && __FreeBSD_version > 602000
     874             :         m =  m_getm2(NULL, space_needed, how, type, want_header ? M_PKTHDR : 0);
     875             :         if (m == NULL) {
     876             :                 /* bad, no memory */
     877             :                 return (m);
     878             :         }
     879             :         if (allonebuf) {
     880             :                 int siz;
     881             :                 if (SCTP_BUF_IS_EXTENDED(m)) {
     882             :                         siz = SCTP_BUF_EXTEND_SIZE(m);
     883             :                 } else {
     884             :                         if (want_header)
     885             :                                 siz = MHLEN;
     886             :                         else
     887             :                                 siz = MLEN;
     888             :                 }
     889             :                 if (siz < space_needed) {
     890             :                         m_freem(m);
     891             :                         return (NULL);
     892             :                 }
     893             :         }
     894             :         if (SCTP_BUF_NEXT(m)) {
     895             :                 sctp_m_freem(SCTP_BUF_NEXT(m));
     896             :                 SCTP_BUF_NEXT(m) = NULL;
     897             :         }
     898             : #ifdef SCTP_MBUF_LOGGING
     899             :         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
     900             :                 sctp_log_mb(m, SCTP_MBUF_IALLOC);
     901             :         }
     902             : #endif
     903             : #else
     904             : #if defined(__FreeBSD__) && __FreeBSD_version >= 601000
     905             :         int aloc_size;
     906             :         int index = 0;
     907             : #endif
     908             :         int mbuf_threshold;
     909             :         if (want_header) {
     910             :                 MGETHDR(m, how, type);
     911             :         } else {
     912             :                 MGET(m, how, type);
     913             :         }
     914             :         if (m == NULL) {
     915             :                 return (NULL);
     916             :         }
     917             :         if (allonebuf == 0)
     918             :                 mbuf_threshold = SCTP_BASE_SYSCTL(sctp_mbuf_threshold_count);
     919             :         else
     920             :                 mbuf_threshold = 1;
     921             : 
     922             : 
     923             :         if (space_needed > (((mbuf_threshold - 1) * MLEN) + MHLEN)) {
     924             : #if defined(__FreeBSD__) && __FreeBSD_version >= 601000
     925             :         try_again:
     926             :                 index = 4;
     927             :                 if (space_needed <= MCLBYTES) {
     928             :                         aloc_size = MCLBYTES;
     929             :                 } else {
     930             :                         aloc_size = MJUMPAGESIZE;
     931             :                         index = 5;
     932             :                 }
     933             :                 m_cljget(m, how, aloc_size);
     934             :                 if (m == NULL) {
     935             :                         return (NULL);
     936             :                 }
     937             :                 if (SCTP_BUF_IS_EXTENDED(m) == 0) {
     938             :                         if ((aloc_size != MCLBYTES) &&
     939             :                            (allonebuf == 0)) {
     940             :                                 aloc_size -= 10;
     941             :                                 goto try_again;
     942             :                         }
     943             :                         sctp_m_freem(m);
     944             :                         return (NULL);
     945             :                 }
     946             : #else
     947             :                 MCLGET(m, how);
     948             :                 if (m == NULL) {
     949             :                         return (NULL);
     950             :                 }
     951             :                 if (SCTP_BUF_IS_EXTENDED(m) == 0) {
     952             :                         sctp_m_freem(m);
     953             :                         return (NULL);
     954             :                 }
     955             : #endif
     956             :         }
     957             :         SCTP_BUF_LEN(m) = 0;
     958             :         SCTP_BUF_NEXT(m) = SCTP_BUF_NEXT_PKT(m) = NULL;
     959             : #ifdef SCTP_MBUF_LOGGING
     960             :         if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
     961             :                 sctp_log_mb(m, SCTP_MBUF_IALLOC);
     962             :         }
     963             : #endif
     964             : #endif
     965           0 :         return (m);
     966             : }
     967             : 
     968             : 
     969             : #ifdef SCTP_PACKET_LOGGING
     970             : void
     971             : sctp_packet_log(struct mbuf *m)
     972             : {
     973             :         int *lenat, thisone;
     974             :         void *copyto;
     975             :         uint32_t *tick_tock;
     976             :         int length;
     977             :         int total_len;
     978             :         int grabbed_lock = 0;
     979             :         int value, newval, thisend, thisbegin;
     980             :         /*
     981             :          * Buffer layout.
     982             :          * -sizeof this entry (total_len)
     983             :          * -previous end      (value)
     984             :          * -ticks of log      (ticks)
     985             :          * o -ip packet
     986             :          * o -as logged
     987             :          * - where this started (thisbegin)
     988             :          * x <--end points here
     989             :          */
     990             :         length = SCTP_HEADER_LEN(m);
     991             :         total_len = SCTP_SIZE32((length + (4 * sizeof(int))));
     992             :         /* Log a packet to the buffer. */
     993             :         if (total_len> SCTP_PACKET_LOG_SIZE) {
     994             :                 /* Can't log this packet I have not a buffer big enough */
     995             :                 return;
     996             :         }
     997             :         if (length < (int)(SCTP_MIN_V4_OVERHEAD + sizeof(struct sctp_cookie_ack_chunk))) {
     998             :                 return;
     999             :         }
    1000             :         atomic_add_int(&SCTP_BASE_VAR(packet_log_writers), 1);
    1001             :  try_again:
    1002             :         if (SCTP_BASE_VAR(packet_log_writers) > SCTP_PKTLOG_WRITERS_NEED_LOCK) {
    1003             :                 SCTP_IP_PKTLOG_LOCK();
    1004             :                 grabbed_lock = 1;
    1005             :         again_locked:
    1006             :                 value = SCTP_BASE_VAR(packet_log_end);
    1007             :                 newval = SCTP_BASE_VAR(packet_log_end) + total_len;
    1008             :                 if (newval >= SCTP_PACKET_LOG_SIZE) {
    1009             :                         /* we wrapped */
    1010             :                         thisbegin = 0;
    1011             :                         thisend = total_len;
    1012             :                 } else {
    1013             :                         thisbegin = SCTP_BASE_VAR(packet_log_end);
    1014             :                         thisend = newval;
    1015             :                 }
    1016             :                 if (!(atomic_cmpset_int(&SCTP_BASE_VAR(packet_log_end), value, thisend))) {
    1017             :                         goto again_locked;
    1018             :                 }
    1019             :         } else {
    1020             :                 value = SCTP_BASE_VAR(packet_log_end);
    1021             :                 newval = SCTP_BASE_VAR(packet_log_end) + total_len;
    1022             :                 if (newval >= SCTP_PACKET_LOG_SIZE) {
    1023             :                         /* we wrapped */
    1024             :                         thisbegin = 0;
    1025             :                         thisend = total_len;
    1026             :                 } else {
    1027             :                         thisbegin = SCTP_BASE_VAR(packet_log_end);
    1028             :                         thisend = newval;
    1029             :                 }
    1030             :                 if (!(atomic_cmpset_int(&SCTP_BASE_VAR(packet_log_end), value, thisend))) {
    1031             :                         goto try_again;
    1032             :                 }
    1033             :         }
    1034             :         /* Sanity check */
    1035             :         if (thisend >= SCTP_PACKET_LOG_SIZE) {
    1036             :                 SCTP_PRINTF("Insanity stops a log thisbegin:%d thisend:%d writers:%d lock:%d end:%d\n",
    1037             :                             thisbegin,
    1038             :                             thisend,
    1039             :                             SCTP_BASE_VAR(packet_log_writers),
    1040             :                             grabbed_lock,
    1041             :                             SCTP_BASE_VAR(packet_log_end));
    1042             :                 SCTP_BASE_VAR(packet_log_end) = 0;
    1043             :                 goto no_log;
    1044             : 
    1045             :         }
    1046             :         lenat = (int *)&SCTP_BASE_VAR(packet_log_buffer)[thisbegin];
    1047             :         *lenat = total_len;
    1048             :         lenat++;
    1049             :         *lenat = value;
    1050             :         lenat++;
    1051             :         tick_tock = (uint32_t *)lenat;
    1052             :         lenat++;
    1053             :         *tick_tock = sctp_get_tick_count();
    1054             :         copyto = (void *)lenat;
    1055             :         thisone = thisend - sizeof(int);
    1056             :         lenat = (int *)&SCTP_BASE_VAR(packet_log_buffer)[thisone];
    1057             :         *lenat = thisbegin;
    1058             :         if (grabbed_lock) {
    1059             :                 SCTP_IP_PKTLOG_UNLOCK();
    1060             :                 grabbed_lock = 0;
    1061             :         }
    1062             :         m_copydata(m, 0, length, (caddr_t)copyto);
    1063             :  no_log:
    1064             :         if (grabbed_lock) {
    1065             :                 SCTP_IP_PKTLOG_UNLOCK();
    1066             :         }
    1067             :         atomic_subtract_int(&SCTP_BASE_VAR(packet_log_writers), 1);
    1068             : }
    1069             : 
    1070             : 
    1071             : int
    1072             : sctp_copy_out_packet_log(uint8_t *target, int length)
    1073             : {
    1074             :         /* We wind through the packet log starting at
    1075             :          * start copying up to length bytes out.
    1076             :          * We return the number of bytes copied.
    1077             :          */
    1078             :         int tocopy, this_copy;
    1079             :         int *lenat;
    1080             :         int did_delay = 0;
    1081             : 
    1082             :         tocopy = length;
    1083             :         if (length < (int)(2 * sizeof(int))) {
    1084             :                 /* not enough room */
    1085             :                 return (0);
    1086             :         }
    1087             :         if (SCTP_PKTLOG_WRITERS_NEED_LOCK) {
    1088             :                 atomic_add_int(&SCTP_BASE_VAR(packet_log_writers), SCTP_PKTLOG_WRITERS_NEED_LOCK);
    1089             :         again:
    1090             :                 if ((did_delay == 0) && (SCTP_BASE_VAR(packet_log_writers) != SCTP_PKTLOG_WRITERS_NEED_LOCK)) {
    1091             :                         /* we delay here for just a moment hoping the writer(s) that were
    1092             :                          * present when we entered will have left and we only have
    1093             :                          * locking ones that will contend with us for the lock. This
    1094             :                          * does not assure 100% access, but its good enough for
    1095             :                          * a logging facility like this.
    1096             :                          */
    1097             :                         did_delay = 1;
    1098             :                         DELAY(10);
    1099             :                         goto again;
    1100             :                 }
    1101             :         }
    1102             :         SCTP_IP_PKTLOG_LOCK();
    1103             :         lenat = (int *)target;
    1104             :         *lenat = SCTP_BASE_VAR(packet_log_end);
    1105             :         lenat++;
    1106             :         this_copy = min((length - sizeof(int)), SCTP_PACKET_LOG_SIZE);
    1107             :         memcpy((void *)lenat, (void *)SCTP_BASE_VAR(packet_log_buffer), this_copy);
    1108             :         if (SCTP_PKTLOG_WRITERS_NEED_LOCK) {
    1109             :                 atomic_subtract_int(&SCTP_BASE_VAR(packet_log_writers),
    1110             :                                     SCTP_PKTLOG_WRITERS_NEED_LOCK);
    1111             :         }
    1112             :         SCTP_IP_PKTLOG_UNLOCK();
    1113             :         return (this_copy + sizeof(int));
    1114             : }
    1115             : 
    1116             : #endif

Generated by: LCOV version 1.13