1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/sctp/src/netinet/sctp_bsd_addr.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1111 @@ 1.4 +/*- 1.5 + * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. 1.6 + * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. 1.7 + * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. 1.8 + * 1.9 + * Redistribution and use in source and binary forms, with or without 1.10 + * modification, are permitted provided that the following conditions are met: 1.11 + * 1.12 + * a) Redistributions of source code must retain the above copyright notice, 1.13 + * this list of conditions and the following disclaimer. 1.14 + * 1.15 + * b) Redistributions in binary form must reproduce the above copyright 1.16 + * notice, this list of conditions and the following disclaimer in 1.17 + * the documentation and/or other materials provided with the distribution. 1.18 + * 1.19 + * c) Neither the name of Cisco Systems, Inc. nor the names of its 1.20 + * contributors may be used to endorse or promote products derived 1.21 + * from this software without specific prior written permission. 1.22 + * 1.23 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.24 + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 1.25 + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1.26 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 1.27 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 1.28 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 1.29 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 1.30 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 1.31 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 1.32 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 1.33 + * THE POSSIBILITY OF SUCH DAMAGE. 1.34 + */ 1.35 + 1.36 +#ifdef __FreeBSD__ 1.37 +#include <sys/cdefs.h> 1.38 +__FBSDID("$FreeBSD: head/sys/netinet/sctp_bsd_addr.c 258765 2013-11-30 12:51:19Z tuexen $"); 1.39 +#endif 1.40 + 1.41 +#include <netinet/sctp_os.h> 1.42 +#include <netinet/sctp_var.h> 1.43 +#include <netinet/sctp_pcb.h> 1.44 +#include <netinet/sctp_header.h> 1.45 +#include <netinet/sctputil.h> 1.46 +#include <netinet/sctp_output.h> 1.47 +#include <netinet/sctp_bsd_addr.h> 1.48 +#include <netinet/sctp_uio.h> 1.49 +#include <netinet/sctputil.h> 1.50 +#include <netinet/sctp_timer.h> 1.51 +#include <netinet/sctp_asconf.h> 1.52 +#include <netinet/sctp_sysctl.h> 1.53 +#include <netinet/sctp_indata.h> 1.54 +#if defined(ANDROID) 1.55 +#include <unistd.h> 1.56 +#include <ifaddrs-android-ext.h> 1.57 +#else 1.58 +#if defined(__FreeBSD__) 1.59 +#include <sys/unistd.h> 1.60 +#endif 1.61 +#endif 1.62 + 1.63 +/* Declare all of our malloc named types */ 1.64 +#ifndef __Panda__ 1.65 +MALLOC_DEFINE(SCTP_M_MAP, "sctp_map", "sctp asoc map descriptor"); 1.66 +MALLOC_DEFINE(SCTP_M_STRMI, "sctp_stri", "sctp stream in array"); 1.67 +MALLOC_DEFINE(SCTP_M_STRMO, "sctp_stro", "sctp stream out array"); 1.68 +MALLOC_DEFINE(SCTP_M_ASC_ADDR, "sctp_aadr", "sctp asconf address"); 1.69 +MALLOC_DEFINE(SCTP_M_ASC_IT, "sctp_a_it", "sctp asconf iterator"); 1.70 +MALLOC_DEFINE(SCTP_M_AUTH_CL, "sctp_atcl", "sctp auth chunklist"); 1.71 +MALLOC_DEFINE(SCTP_M_AUTH_KY, "sctp_atky", "sctp auth key"); 1.72 +MALLOC_DEFINE(SCTP_M_AUTH_HL, "sctp_athm", "sctp auth hmac list"); 1.73 +MALLOC_DEFINE(SCTP_M_AUTH_IF, "sctp_athi", "sctp auth info"); 1.74 +MALLOC_DEFINE(SCTP_M_STRESET, "sctp_stre", "sctp stream reset"); 1.75 +MALLOC_DEFINE(SCTP_M_CMSG, "sctp_cmsg", "sctp CMSG buffer"); 1.76 +MALLOC_DEFINE(SCTP_M_COPYAL, "sctp_cpal", "sctp copy all"); 1.77 +MALLOC_DEFINE(SCTP_M_VRF, "sctp_vrf", "sctp vrf struct"); 1.78 +MALLOC_DEFINE(SCTP_M_IFA, "sctp_ifa", "sctp ifa struct"); 1.79 +MALLOC_DEFINE(SCTP_M_IFN, "sctp_ifn", "sctp ifn struct"); 1.80 +MALLOC_DEFINE(SCTP_M_TIMW, "sctp_timw", "sctp time block"); 1.81 +MALLOC_DEFINE(SCTP_M_MVRF, "sctp_mvrf", "sctp mvrf pcb list"); 1.82 +MALLOC_DEFINE(SCTP_M_ITER, "sctp_iter", "sctp iterator control"); 1.83 +MALLOC_DEFINE(SCTP_M_SOCKOPT, "sctp_socko", "sctp socket option"); 1.84 +MALLOC_DEFINE(SCTP_M_MCORE, "sctp_mcore", "sctp mcore queue"); 1.85 +#endif 1.86 + 1.87 +/* Global NON-VNET structure that controls the iterator */ 1.88 +struct iterator_control sctp_it_ctl; 1.89 + 1.90 +#if !defined(__FreeBSD__) 1.91 +static void 1.92 +sctp_cleanup_itqueue(void) 1.93 +{ 1.94 + struct sctp_iterator *it, *nit; 1.95 + 1.96 + TAILQ_FOREACH_SAFE(it, &sctp_it_ctl.iteratorhead, sctp_nxt_itr, nit) { 1.97 + if (it->function_atend != NULL) { 1.98 + (*it->function_atend) (it->pointer, it->val); 1.99 + } 1.100 + TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, it, sctp_nxt_itr); 1.101 + SCTP_FREE(it, SCTP_M_ITER); 1.102 + } 1.103 +} 1.104 +#endif 1.105 +#if defined(__Userspace__) 1.106 +/*__Userspace__ TODO if we use thread based iterator 1.107 + * then the implementation of wakeup will need to change. 1.108 + * Currently we are using timeo_cond for ident so_timeo 1.109 + * but that is not sufficient if we need to use another ident 1.110 + * like wakeup(&sctppcbinfo.iterator_running); 1.111 + */ 1.112 +#endif 1.113 + 1.114 +void 1.115 +sctp_wakeup_iterator(void) 1.116 +{ 1.117 +#if defined(SCTP_PROCESS_LEVEL_LOCKS) 1.118 +#if defined(__Userspace_os_Windows) 1.119 + WakeAllConditionVariable(&sctp_it_ctl.iterator_wakeup); 1.120 +#else 1.121 + pthread_cond_broadcast(&sctp_it_ctl.iterator_wakeup); 1.122 +#endif 1.123 +#else 1.124 + wakeup(&sctp_it_ctl.iterator_running); 1.125 +#endif 1.126 +} 1.127 + 1.128 +#if defined(__Userspace__) 1.129 +static void * 1.130 +#else 1.131 +static void 1.132 +#endif 1.133 +sctp_iterator_thread(void *v SCTP_UNUSED) 1.134 +{ 1.135 + SCTP_IPI_ITERATOR_WQ_LOCK(); 1.136 + /* In FreeBSD this thread never terminates. */ 1.137 +#if defined(__FreeBSD__) 1.138 + for (;;) { 1.139 +#else 1.140 + while ((sctp_it_ctl.iterator_flags & SCTP_ITERATOR_MUST_EXIT) == 0) { 1.141 +#endif 1.142 +#if !defined(__Userspace__) 1.143 + msleep(&sctp_it_ctl.iterator_running, 1.144 +#if defined(__FreeBSD__) 1.145 + &sctp_it_ctl.ipi_iterator_wq_mtx, 1.146 +#elif defined(__APPLE__) || defined(__Userspace_os_Darwin) 1.147 + sctp_it_ctl.ipi_iterator_wq_mtx, 1.148 +#endif 1.149 + 0, "waiting_for_work", 0); 1.150 +#else 1.151 +#if defined(__Userspace_os_Windows) 1.152 + SleepConditionVariableCS(&sctp_it_ctl.iterator_wakeup, &sctp_it_ctl.ipi_iterator_wq_mtx, INFINITE); 1.153 +#else 1.154 + pthread_cond_wait(&sctp_it_ctl.iterator_wakeup, &sctp_it_ctl.ipi_iterator_wq_mtx); 1.155 +#endif 1.156 +#endif 1.157 +#if !defined(__FreeBSD__) 1.158 + if (sctp_it_ctl.iterator_flags & SCTP_ITERATOR_MUST_EXIT) { 1.159 + break; 1.160 + } 1.161 +#endif 1.162 + sctp_iterator_worker(); 1.163 + } 1.164 +#if !defined(__FreeBSD__) 1.165 + /* Now this thread needs to be terminated */ 1.166 + sctp_cleanup_itqueue(); 1.167 + sctp_it_ctl.iterator_flags |= SCTP_ITERATOR_EXITED; 1.168 + SCTP_IPI_ITERATOR_WQ_UNLOCK(); 1.169 +#if defined(__Userspace__) 1.170 + sctp_wakeup_iterator(); 1.171 + return (NULL); 1.172 +#else 1.173 + wakeup(&sctp_it_ctl.iterator_flags); 1.174 + thread_terminate(current_thread()); 1.175 +#ifdef INVARIANTS 1.176 + panic("Hmm. thread_terminate() continues..."); 1.177 +#endif 1.178 +#endif 1.179 +#endif 1.180 +} 1.181 + 1.182 +void 1.183 +sctp_startup_iterator(void) 1.184 +{ 1.185 + if (sctp_it_ctl.thread_proc) { 1.186 + /* You only get one */ 1.187 + return; 1.188 + } 1.189 + /* Initialize global locks here, thus only once. */ 1.190 + SCTP_ITERATOR_LOCK_INIT(); 1.191 + SCTP_IPI_ITERATOR_WQ_INIT(); 1.192 + TAILQ_INIT(&sctp_it_ctl.iteratorhead); 1.193 +#if defined(__FreeBSD__) 1.194 +#if __FreeBSD_version <= 701000 1.195 + kthread_create(sctp_iterator_thread, 1.196 +#else 1.197 + kproc_create(sctp_iterator_thread, 1.198 +#endif 1.199 + (void *)NULL, 1.200 + &sctp_it_ctl.thread_proc, 1.201 + RFPROC, 1.202 + SCTP_KTHREAD_PAGES, 1.203 + SCTP_KTRHEAD_NAME); 1.204 +#elif defined(__APPLE__) 1.205 + kernel_thread_start((thread_continue_t)sctp_iterator_thread, NULL, &sctp_it_ctl.thread_proc); 1.206 +#elif defined(__Userspace__) 1.207 +#if defined(__Userspace_os_Windows) 1.208 + if ((sctp_it_ctl.thread_proc = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&sctp_iterator_thread, NULL, 0, NULL)) == NULL) { 1.209 +#else 1.210 + if (pthread_create(&sctp_it_ctl.thread_proc, NULL, &sctp_iterator_thread, NULL)) { 1.211 +#endif 1.212 + SCTP_PRINTF("ERROR: Creating sctp_iterator_thread failed.\n"); 1.213 + } 1.214 +#endif 1.215 +} 1.216 + 1.217 +#ifdef INET6 1.218 + 1.219 +#if defined(__Userspace__) 1.220 +/* __Userspace__ TODO. struct in6_ifaddr is defined in sys/netinet6/in6_var.h 1.221 + ip6_use_deprecated is defined as int ip6_use_deprecated = 1; in /src/sys/netinet6/in6_proto.c 1.222 + */ 1.223 +void 1.224 +sctp_gather_internal_ifa_flags(struct sctp_ifa *ifa) 1.225 +{ 1.226 + return; /* stub */ 1.227 +} 1.228 +#else 1.229 +void 1.230 +sctp_gather_internal_ifa_flags(struct sctp_ifa *ifa) 1.231 +{ 1.232 + struct in6_ifaddr *ifa6; 1.233 + 1.234 + ifa6 = (struct in6_ifaddr *)ifa->ifa; 1.235 + ifa->flags = ifa6->ia6_flags; 1.236 + if (!MODULE_GLOBAL(ip6_use_deprecated)) { 1.237 + if (ifa->flags & 1.238 + IN6_IFF_DEPRECATED) { 1.239 + ifa->localifa_flags |= SCTP_ADDR_IFA_UNUSEABLE; 1.240 + } else { 1.241 + ifa->localifa_flags &= ~SCTP_ADDR_IFA_UNUSEABLE; 1.242 + } 1.243 + } else { 1.244 + ifa->localifa_flags &= ~SCTP_ADDR_IFA_UNUSEABLE; 1.245 + } 1.246 + if (ifa->flags & 1.247 + (IN6_IFF_DETACHED | 1.248 + IN6_IFF_ANYCAST | 1.249 + IN6_IFF_NOTREADY)) { 1.250 + ifa->localifa_flags |= SCTP_ADDR_IFA_UNUSEABLE; 1.251 + } else { 1.252 + ifa->localifa_flags &= ~SCTP_ADDR_IFA_UNUSEABLE; 1.253 + } 1.254 +} 1.255 +#endif /* __Userspace__ */ 1.256 +#endif /* INET6 */ 1.257 + 1.258 + 1.259 +#if !defined(__Userspace__) 1.260 +static uint32_t 1.261 +sctp_is_desired_interface_type(struct ifnet *ifn) 1.262 +{ 1.263 + int result; 1.264 + 1.265 + /* check the interface type to see if it's one we care about */ 1.266 +#if defined(__APPLE__) 1.267 + switch(ifnet_type(ifn)) { 1.268 +#else 1.269 + switch (ifn->if_type) { 1.270 +#endif 1.271 + case IFT_ETHER: 1.272 + case IFT_ISO88023: 1.273 + case IFT_ISO88024: 1.274 + case IFT_ISO88025: 1.275 + case IFT_ISO88026: 1.276 + case IFT_STARLAN: 1.277 + case IFT_P10: 1.278 + case IFT_P80: 1.279 + case IFT_HY: 1.280 + case IFT_FDDI: 1.281 + case IFT_XETHER: 1.282 + case IFT_ISDNBASIC: 1.283 + case IFT_ISDNPRIMARY: 1.284 + case IFT_PTPSERIAL: 1.285 + case IFT_OTHER: 1.286 + case IFT_PPP: 1.287 + case IFT_LOOP: 1.288 + case IFT_SLIP: 1.289 + case IFT_GIF: 1.290 + case IFT_L2VLAN: 1.291 + case IFT_STF: 1.292 +#if !defined(__APPLE__) 1.293 + case IFT_IP: 1.294 + case IFT_IPOVERCDLC: 1.295 + case IFT_IPOVERCLAW: 1.296 + case IFT_PROPVIRTUAL: /* NetGraph Virtual too */ 1.297 + case IFT_VIRTUALIPADDRESS: 1.298 +#endif 1.299 + result = 1; 1.300 + break; 1.301 + default: 1.302 + result = 0; 1.303 + } 1.304 + 1.305 + return (result); 1.306 +} 1.307 +#endif 1.308 + 1.309 +#if defined(__APPLE__) 1.310 +int 1.311 +sctp_is_vmware_interface(struct ifnet *ifn) 1.312 +{ 1.313 + return (strncmp(ifnet_name(ifn), "vmnet", 5) == 0); 1.314 +} 1.315 +#endif 1.316 + 1.317 +#if defined(__Userspace_os_Windows) 1.318 +#ifdef MALLOC 1.319 +#undef MALLOC 1.320 +#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) 1.321 +#endif 1.322 +#ifdef FREE 1.323 +#undef FREE 1.324 +#define FREE(x) HeapFree(GetProcessHeap(), 0, (x)) 1.325 +#endif 1.326 +static void 1.327 +sctp_init_ifns_for_vrf(int vrfid) 1.328 +{ 1.329 +#if defined(INET) || defined(INET6) 1.330 + struct ifaddrs *ifa; 1.331 + struct sctp_ifa *sctp_ifa; 1.332 + DWORD Err, AdapterAddrsSize; 1.333 + PIP_ADAPTER_ADDRESSES pAdapterAddrs, pAdapt; 1.334 + PIP_ADAPTER_UNICAST_ADDRESS pUnicast; 1.335 +#endif 1.336 + 1.337 +#ifdef INET 1.338 + AdapterAddrsSize = 0; 1.339 + 1.340 + if ((Err = GetAdaptersAddresses(AF_INET, 0, NULL, NULL, &AdapterAddrsSize)) != 0) { 1.341 + if ((Err != ERROR_BUFFER_OVERFLOW) && (Err != ERROR_INSUFFICIENT_BUFFER)) { 1.342 + SCTP_PRINTF("GetAdaptersV4Addresses() sizing failed with error code %d\n", Err); 1.343 + SCTP_PRINTF("err = %d; AdapterAddrsSize = %d\n", Err, AdapterAddrsSize); 1.344 + return; 1.345 + } 1.346 + } 1.347 + 1.348 + /* Allocate memory from sizing information */ 1.349 + if ((pAdapterAddrs = (PIP_ADAPTER_ADDRESSES) GlobalAlloc(GPTR, AdapterAddrsSize)) == NULL) { 1.350 + SCTP_PRINTF("Memory allocation error!\n"); 1.351 + return; 1.352 + } 1.353 + /* Get actual adapter information */ 1.354 + if ((Err = GetAdaptersAddresses(AF_INET, 0, NULL, pAdapterAddrs, &AdapterAddrsSize)) != ERROR_SUCCESS) { 1.355 + SCTP_PRINTF("GetAdaptersV4Addresses() failed with error code %d\n", Err); 1.356 + return; 1.357 + } 1.358 + /* Enumerate through each returned adapter and save its information */ 1.359 + for (pAdapt = pAdapterAddrs; pAdapt; pAdapt = pAdapt->Next) { 1.360 + if (pAdapt->IfType == IF_TYPE_IEEE80211 || pAdapt->IfType == IF_TYPE_ETHERNET_CSMACD) { 1.361 + for (pUnicast = pAdapt->FirstUnicastAddress; pUnicast; pUnicast = pUnicast->Next) { 1.362 + if (IN4_ISLINKLOCAL_ADDRESS(&(((struct sockaddr_in *)(pUnicast->Address.lpSockaddr))->sin_addr))) { 1.363 + continue; 1.364 + } 1.365 + ifa = (struct ifaddrs*)malloc(sizeof(struct ifaddrs)); 1.366 + ifa->ifa_name = strdup(pAdapt->AdapterName); 1.367 + ifa->ifa_flags = pAdapt->Flags; 1.368 + ifa->ifa_addr = (struct sockaddr *)malloc(sizeof(struct sockaddr_in)); 1.369 + memcpy(ifa->ifa_addr, pUnicast->Address.lpSockaddr, sizeof(struct sockaddr_in)); 1.370 + 1.371 + sctp_ifa = sctp_add_addr_to_vrf(0, 1.372 + ifa, 1.373 + pAdapt->IfIndex, 1.374 + (pAdapt->IfType == IF_TYPE_IEEE80211)?MIB_IF_TYPE_ETHERNET:pAdapt->IfType, 1.375 + ifa->ifa_name, 1.376 + (void *)ifa, 1.377 + ifa->ifa_addr, 1.378 + ifa->ifa_flags, 1.379 + 0); 1.380 + if (sctp_ifa) { 1.381 + sctp_ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE; 1.382 + } 1.383 + } 1.384 + } 1.385 + } 1.386 + if (pAdapterAddrs) 1.387 + FREE(pAdapterAddrs); 1.388 +#endif 1.389 +#ifdef INET6 1.390 + AdapterAddrsSize = 0; 1.391 + 1.392 + if ((Err = GetAdaptersAddresses(AF_INET6, 0, NULL, NULL, &AdapterAddrsSize)) != 0) { 1.393 + if ((Err != ERROR_BUFFER_OVERFLOW) && (Err != ERROR_INSUFFICIENT_BUFFER)) { 1.394 + SCTP_PRINTF("GetAdaptersV6Addresses() sizing failed with error code %d\n", Err); 1.395 + SCTP_PRINTF("err = %d; AdapterAddrsSize = %d\n", Err, AdapterAddrsSize); 1.396 + return; 1.397 + } 1.398 + } 1.399 + /* Allocate memory from sizing information */ 1.400 + if ((pAdapterAddrs = (PIP_ADAPTER_ADDRESSES) GlobalAlloc(GPTR, AdapterAddrsSize)) == NULL) { 1.401 + SCTP_PRINTF("Memory allocation error!\n"); 1.402 + return; 1.403 + } 1.404 + /* Get actual adapter information */ 1.405 + if ((Err = GetAdaptersAddresses(AF_INET6, 0, NULL, pAdapterAddrs, &AdapterAddrsSize)) != ERROR_SUCCESS) { 1.406 + SCTP_PRINTF("GetAdaptersV6Addresses() failed with error code %d\n", Err); 1.407 + return; 1.408 + } 1.409 + /* Enumerate through each returned adapter and save its information */ 1.410 + for (pAdapt = pAdapterAddrs; pAdapt; pAdapt = pAdapt->Next) { 1.411 + if (pAdapt->IfType == IF_TYPE_IEEE80211 || pAdapt->IfType == IF_TYPE_ETHERNET_CSMACD) { 1.412 + for (pUnicast = pAdapt->FirstUnicastAddress; pUnicast; pUnicast = pUnicast->Next) { 1.413 + ifa = (struct ifaddrs*)malloc(sizeof(struct ifaddrs)); 1.414 + ifa->ifa_name = strdup(pAdapt->AdapterName); 1.415 + ifa->ifa_flags = pAdapt->Flags; 1.416 + ifa->ifa_addr = (struct sockaddr *)malloc(sizeof(struct sockaddr_in6)); 1.417 + memcpy(ifa->ifa_addr, pUnicast->Address.lpSockaddr, sizeof(struct sockaddr_in6)); 1.418 + sctp_ifa = sctp_add_addr_to_vrf(0, 1.419 + ifa, 1.420 + pAdapt->Ipv6IfIndex, 1.421 + (pAdapt->IfType == IF_TYPE_IEEE80211)?MIB_IF_TYPE_ETHERNET:pAdapt->IfType, 1.422 + ifa->ifa_name, 1.423 + (void *)ifa, 1.424 + ifa->ifa_addr, 1.425 + ifa->ifa_flags, 1.426 + 0); 1.427 + if (sctp_ifa) { 1.428 + sctp_ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE; 1.429 + } 1.430 + } 1.431 + } 1.432 + } 1.433 + if (pAdapterAddrs) 1.434 + FREE(pAdapterAddrs); 1.435 +#endif 1.436 +} 1.437 +#elif defined(__Userspace__) 1.438 +static void 1.439 +sctp_init_ifns_for_vrf(int vrfid) 1.440 +{ 1.441 +#if defined(INET) || defined(INET6) 1.442 + int rc; 1.443 + struct ifaddrs *ifa = NULL; 1.444 + struct sctp_ifa *sctp_ifa; 1.445 + uint32_t ifa_flags; 1.446 + 1.447 + rc = getifaddrs(&g_interfaces); 1.448 + if (rc != 0) { 1.449 + return; 1.450 + } 1.451 + for (ifa = g_interfaces; ifa; ifa = ifa->ifa_next) { 1.452 + if (ifa->ifa_addr == NULL) { 1.453 + continue; 1.454 + } 1.455 +#if !defined(INET) 1.456 + if (ifa->ifa_addr->sa_family != AF_INET6) { 1.457 + /* non inet6 skip */ 1.458 + continue; 1.459 + } 1.460 +#elif !defined(INET6) 1.461 + if (ifa->ifa_addr->sa_family != AF_INET) { 1.462 + /* non inet skip */ 1.463 + continue; 1.464 + } 1.465 +#else 1.466 + if ((ifa->ifa_addr->sa_family != AF_INET) && (ifa->ifa_addr->sa_family != AF_INET6)) { 1.467 + /* non inet/inet6 skip */ 1.468 + continue; 1.469 + } 1.470 +#endif 1.471 +#if defined(INET6) 1.472 + if ((ifa->ifa_addr->sa_family == AF_INET6) && 1.473 + IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) { 1.474 + /* skip unspecifed addresses */ 1.475 + continue; 1.476 + } 1.477 +#endif 1.478 +#if defined(INET) 1.479 + if (ifa->ifa_addr->sa_family == AF_INET && 1.480 + ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) { 1.481 + continue; 1.482 + } 1.483 +#endif 1.484 + ifa_flags = 0; 1.485 + sctp_ifa = sctp_add_addr_to_vrf(vrfid, 1.486 + ifa, 1.487 + if_nametoindex(ifa->ifa_name), 1.488 + 0, 1.489 + ifa->ifa_name, 1.490 + (void *)ifa, 1.491 + ifa->ifa_addr, 1.492 + ifa_flags, 1.493 + 0); 1.494 + if (sctp_ifa) { 1.495 + sctp_ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE; 1.496 + } 1.497 + } 1.498 +#endif 1.499 +} 1.500 +#endif 1.501 + 1.502 +#if defined(__APPLE__) 1.503 +static void 1.504 +sctp_init_ifns_for_vrf(int vrfid) 1.505 +{ 1.506 + /* Here we must apply ANY locks needed by the 1.507 + * IFN we access and also make sure we lock 1.508 + * any IFA that exists as we float through the 1.509 + * list of IFA's 1.510 + */ 1.511 + struct ifnet **ifnetlist; 1.512 + uint32_t i, j, count; 1.513 + char name[SCTP_IFNAMSIZ]; 1.514 + struct ifnet *ifn; 1.515 + struct ifaddr **ifaddrlist; 1.516 + struct ifaddr *ifa; 1.517 + struct in6_ifaddr *ifa6; 1.518 + struct sctp_ifa *sctp_ifa; 1.519 + uint32_t ifa_flags; 1.520 + 1.521 + if (ifnet_list_get(IFNET_FAMILY_ANY, &ifnetlist, &count) != 0) { 1.522 + return; 1.523 + } 1.524 + for (i = 0; i < count; i++) { 1.525 + ifn = ifnetlist[i]; 1.526 + if (SCTP_BASE_SYSCTL(sctp_ignore_vmware_interfaces) && sctp_is_vmware_interface(ifn)) { 1.527 + continue; 1.528 + } 1.529 + if (sctp_is_desired_interface_type(ifn) == 0) { 1.530 + /* non desired type */ 1.531 + continue; 1.532 + } 1.533 + if (ifnet_get_address_list(ifn, &ifaddrlist) != 0) { 1.534 + continue; 1.535 + } 1.536 + for (j = 0; ifaddrlist[j] != NULL; j++) { 1.537 + ifa = ifaddrlist[j]; 1.538 + if (ifa->ifa_addr == NULL) { 1.539 + continue; 1.540 + } 1.541 + if ((ifa->ifa_addr->sa_family != AF_INET) && (ifa->ifa_addr->sa_family != AF_INET6)) { 1.542 + /* non inet/inet6 skip */ 1.543 + continue; 1.544 + } 1.545 + if (ifa->ifa_addr->sa_family == AF_INET6) { 1.546 + if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) { 1.547 + /* skip unspecifed addresses */ 1.548 + continue; 1.549 + } 1.550 + } else { 1.551 + if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == INADDR_ANY) { 1.552 + continue; 1.553 + } 1.554 + } 1.555 + if (ifa->ifa_addr->sa_family == AF_INET6) { 1.556 + ifa6 = (struct in6_ifaddr *)ifa; 1.557 + ifa_flags = ifa6->ia6_flags; 1.558 + } else { 1.559 + ifa_flags = 0; 1.560 + } 1.561 + snprintf(name, SCTP_IFNAMSIZ, "%s%d", ifnet_name(ifn), ifnet_unit(ifn)); 1.562 + sctp_ifa = sctp_add_addr_to_vrf(vrfid, 1.563 + (void *)ifn, 1.564 + ifnet_index(ifn), 1.565 + ifnet_type(ifn), 1.566 + name, 1.567 + (void *)ifa, 1.568 + ifa->ifa_addr, 1.569 + ifa_flags, 1.570 + 0); 1.571 + if (sctp_ifa) { 1.572 + sctp_ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE; 1.573 + } 1.574 + } 1.575 + ifnet_free_address_list(ifaddrlist); 1.576 + } 1.577 + ifnet_list_free(ifnetlist); 1.578 +} 1.579 +#endif 1.580 + 1.581 +#if defined(__FreeBSD__) 1.582 +static void 1.583 +sctp_init_ifns_for_vrf(int vrfid) 1.584 +{ 1.585 + /* Here we must apply ANY locks needed by the 1.586 + * IFN we access and also make sure we lock 1.587 + * any IFA that exists as we float through the 1.588 + * list of IFA's 1.589 + */ 1.590 + struct ifnet *ifn; 1.591 + struct ifaddr *ifa; 1.592 + struct sctp_ifa *sctp_ifa; 1.593 + uint32_t ifa_flags; 1.594 +#ifdef INET6 1.595 + struct in6_ifaddr *ifa6; 1.596 +#endif 1.597 + 1.598 + IFNET_RLOCK(); 1.599 + TAILQ_FOREACH(ifn, &MODULE_GLOBAL(ifnet), if_list) { 1.600 + if (sctp_is_desired_interface_type(ifn) == 0) { 1.601 + /* non desired type */ 1.602 + continue; 1.603 + } 1.604 +#if (__FreeBSD_version >= 803000 && __FreeBSD_version < 900000) || __FreeBSD_version > 900000 1.605 + IF_ADDR_RLOCK(ifn); 1.606 +#else 1.607 + IF_ADDR_LOCK(ifn); 1.608 +#endif 1.609 + TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list) { 1.610 + if (ifa->ifa_addr == NULL) { 1.611 + continue; 1.612 + } 1.613 + switch (ifa->ifa_addr->sa_family) { 1.614 +#ifdef INET 1.615 + case AF_INET: 1.616 + if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) { 1.617 + continue; 1.618 + } 1.619 + break; 1.620 +#endif 1.621 +#ifdef INET6 1.622 + case AF_INET6: 1.623 + if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) { 1.624 + /* skip unspecifed addresses */ 1.625 + continue; 1.626 + } 1.627 + break; 1.628 +#endif 1.629 + default: 1.630 + continue; 1.631 + } 1.632 + switch (ifa->ifa_addr->sa_family) { 1.633 +#ifdef INET 1.634 + case AF_INET: 1.635 + ifa_flags = 0; 1.636 + break; 1.637 +#endif 1.638 +#ifdef INET6 1.639 + case AF_INET6: 1.640 + ifa6 = (struct in6_ifaddr *)ifa; 1.641 + ifa_flags = ifa6->ia6_flags; 1.642 + break; 1.643 +#endif 1.644 + default: 1.645 + ifa_flags = 0; 1.646 + break; 1.647 + } 1.648 + sctp_ifa = sctp_add_addr_to_vrf(vrfid, 1.649 + (void *)ifn, 1.650 + ifn->if_index, 1.651 + ifn->if_type, 1.652 + ifn->if_xname, 1.653 + (void *)ifa, 1.654 + ifa->ifa_addr, 1.655 + ifa_flags, 1.656 + 0); 1.657 + if (sctp_ifa) { 1.658 + sctp_ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE; 1.659 + } 1.660 + } 1.661 +#if (__FreeBSD_version >= 803000 && __FreeBSD_version < 900000) || __FreeBSD_version > 900000 1.662 + IF_ADDR_RUNLOCK(ifn); 1.663 +#else 1.664 + IF_ADDR_UNLOCK(ifn); 1.665 +#endif 1.666 + } 1.667 + IFNET_RUNLOCK(); 1.668 +} 1.669 +#endif 1.670 + 1.671 +void 1.672 +sctp_init_vrf_list(int vrfid) 1.673 +{ 1.674 + if (vrfid > SCTP_MAX_VRF_ID) 1.675 + /* can't do that */ 1.676 + return; 1.677 + 1.678 + /* Don't care about return here */ 1.679 + (void)sctp_allocate_vrf(vrfid); 1.680 + 1.681 + /* Now we need to build all the ifn's 1.682 + * for this vrf and there addresses 1.683 + */ 1.684 + sctp_init_ifns_for_vrf(vrfid); 1.685 +} 1.686 + 1.687 +void 1.688 +sctp_addr_change(struct ifaddr *ifa, int cmd) 1.689 +{ 1.690 +#if defined(__Userspace__) 1.691 + return; 1.692 +#else 1.693 + uint32_t ifa_flags = 0; 1.694 + /* BSD only has one VRF, if this changes 1.695 + * we will need to hook in the right 1.696 + * things here to get the id to pass to 1.697 + * the address managment routine. 1.698 + */ 1.699 + if (SCTP_BASE_VAR(first_time) == 0) { 1.700 + /* Special test to see if my ::1 will showup with this */ 1.701 + SCTP_BASE_VAR(first_time) = 1; 1.702 + sctp_init_ifns_for_vrf(SCTP_DEFAULT_VRFID); 1.703 + } 1.704 + 1.705 + if ((cmd != RTM_ADD) && (cmd != RTM_DELETE)) { 1.706 + /* don't know what to do with this */ 1.707 + return; 1.708 + } 1.709 + 1.710 + if (ifa->ifa_addr == NULL) { 1.711 + return; 1.712 + } 1.713 + if (sctp_is_desired_interface_type(ifa->ifa_ifp) == 0) { 1.714 + /* non desired type */ 1.715 + return; 1.716 + } 1.717 + switch (ifa->ifa_addr->sa_family) { 1.718 +#ifdef INET 1.719 + case AF_INET: 1.720 + if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) { 1.721 + return; 1.722 + } 1.723 + break; 1.724 +#endif 1.725 +#ifdef INET6 1.726 + case AF_INET6: 1.727 + ifa_flags = ((struct in6_ifaddr *)ifa)->ia6_flags; 1.728 + if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) { 1.729 + /* skip unspecifed addresses */ 1.730 + return; 1.731 + } 1.732 + break; 1.733 +#endif 1.734 + default: 1.735 + /* non inet/inet6 skip */ 1.736 + return; 1.737 + } 1.738 + if (cmd == RTM_ADD) { 1.739 + (void)sctp_add_addr_to_vrf(SCTP_DEFAULT_VRFID, (void *)ifa->ifa_ifp, 1.740 +#if defined(__APPLE__) 1.741 + ifnet_index(ifa->ifa_ifp), ifnet_type(ifa->ifa_ifp), ifnet_name(ifa->ifa_ifp), 1.742 +#else 1.743 + ifa->ifa_ifp->if_index, ifa->ifa_ifp->if_type, ifa->ifa_ifp->if_xname, 1.744 +#endif 1.745 + (void *)ifa, ifa->ifa_addr, ifa_flags, 1); 1.746 + } else { 1.747 + 1.748 + sctp_del_addr_from_vrf(SCTP_DEFAULT_VRFID, ifa->ifa_addr, 1.749 +#if defined(__APPLE__) 1.750 + ifnet_index(ifa->ifa_ifp), 1.751 + ifnet_name(ifa->ifa_ifp)); 1.752 +#else 1.753 + ifa->ifa_ifp->if_index, 1.754 + ifa->ifa_ifp->if_xname); 1.755 +#endif 1.756 + 1.757 + /* We don't bump refcount here so when it completes 1.758 + * the final delete will happen. 1.759 + */ 1.760 + } 1.761 +#endif 1.762 +} 1.763 + 1.764 +#if defined(__FreeBSD__) 1.765 +void 1.766 +sctp_add_or_del_interfaces(int (*pred)(struct ifnet *), int add) 1.767 +{ 1.768 + struct ifnet *ifn; 1.769 + struct ifaddr *ifa; 1.770 + 1.771 + IFNET_RLOCK(); 1.772 + TAILQ_FOREACH(ifn, &MODULE_GLOBAL(ifnet), if_list) { 1.773 + if (!(*pred)(ifn)) { 1.774 + continue; 1.775 + } 1.776 + TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list) { 1.777 + sctp_addr_change(ifa, add ? RTM_ADD : RTM_DELETE); 1.778 + } 1.779 + } 1.780 + IFNET_RUNLOCK(); 1.781 +} 1.782 +#endif 1.783 +#if defined(__APPLE__) 1.784 +void 1.785 +sctp_add_or_del_interfaces(int (*pred)(struct ifnet *), int add) 1.786 +{ 1.787 + struct ifnet **ifnetlist; 1.788 + struct ifaddr **ifaddrlist; 1.789 + uint32_t i, j, count; 1.790 + 1.791 + if (ifnet_list_get(IFNET_FAMILY_ANY, &ifnetlist, &count) != 0) { 1.792 + return; 1.793 + } 1.794 + for (i = 0; i < count; i++) { 1.795 + if (!(*pred)(ifnetlist[i])) { 1.796 + continue; 1.797 + } 1.798 + if (ifnet_get_address_list(ifnetlist[i], &ifaddrlist) != 0) { 1.799 + continue; 1.800 + } 1.801 + for (j = 0; ifaddrlist[j] != NULL; j++) { 1.802 + sctp_addr_change(ifaddrlist[j], add ? RTM_ADD : RTM_DELETE); 1.803 + } 1.804 + ifnet_free_address_list(ifaddrlist); 1.805 + } 1.806 + ifnet_list_free(ifnetlist); 1.807 + return; 1.808 +} 1.809 +#endif 1.810 + 1.811 +struct mbuf * 1.812 +sctp_get_mbuf_for_msg(unsigned int space_needed, int want_header, 1.813 + int how, int allonebuf, int type) 1.814 +{ 1.815 + struct mbuf *m = NULL; 1.816 +#if defined(__Userspace__) 1.817 + 1.818 + /* 1.819 + * __Userspace__ 1.820 + * Using m_clget, which creates and mbuf and a cluster and 1.821 + * hooks those together. 1.822 + * TODO: This does not yet have functionality for jumbo packets. 1.823 + * 1.824 + */ 1.825 + 1.826 + int mbuf_threshold; 1.827 + if (want_header) { 1.828 + MGETHDR(m, how, type); 1.829 + } else { 1.830 + MGET(m, how, type); 1.831 + } 1.832 + if (m == NULL) { 1.833 + return (NULL); 1.834 + } 1.835 + if (allonebuf == 0) 1.836 + mbuf_threshold = SCTP_BASE_SYSCTL(sctp_mbuf_threshold_count); 1.837 + else 1.838 + mbuf_threshold = 1; 1.839 + 1.840 + 1.841 + if ((int)space_needed > (((mbuf_threshold - 1) * MLEN) + MHLEN)) { 1.842 + MCLGET(m, how); 1.843 + if (m == NULL) { 1.844 + return (NULL); 1.845 + } 1.846 + 1.847 + if (SCTP_BUF_IS_EXTENDED(m) == 0) { 1.848 + sctp_m_freem(m); 1.849 + return (NULL); 1.850 + } 1.851 + } 1.852 + SCTP_BUF_LEN(m) = 0; 1.853 + SCTP_BUF_NEXT(m) = SCTP_BUF_NEXT_PKT(m) = NULL; 1.854 + 1.855 +#if defined(__Userspace__) 1.856 + /* __Userspace__ 1.857 + * Check if anything need to be done to ensure logging works 1.858 + */ 1.859 +#endif 1.860 +#ifdef SCTP_MBUF_LOGGING 1.861 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { 1.862 + if (SCTP_BUF_IS_EXTENDED(m)) { 1.863 + sctp_log_mb(m, SCTP_MBUF_IALLOC); 1.864 + } 1.865 + } 1.866 +#endif 1.867 +#elif defined(__FreeBSD__) && __FreeBSD_version > 602000 1.868 + m = m_getm2(NULL, space_needed, how, type, want_header ? M_PKTHDR : 0); 1.869 + if (m == NULL) { 1.870 + /* bad, no memory */ 1.871 + return (m); 1.872 + } 1.873 + if (allonebuf) { 1.874 + int siz; 1.875 + if (SCTP_BUF_IS_EXTENDED(m)) { 1.876 + siz = SCTP_BUF_EXTEND_SIZE(m); 1.877 + } else { 1.878 + if (want_header) 1.879 + siz = MHLEN; 1.880 + else 1.881 + siz = MLEN; 1.882 + } 1.883 + if (siz < space_needed) { 1.884 + m_freem(m); 1.885 + return (NULL); 1.886 + } 1.887 + } 1.888 + if (SCTP_BUF_NEXT(m)) { 1.889 + sctp_m_freem( SCTP_BUF_NEXT(m)); 1.890 + SCTP_BUF_NEXT(m) = NULL; 1.891 + } 1.892 +#ifdef SCTP_MBUF_LOGGING 1.893 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { 1.894 + if (SCTP_BUF_IS_EXTENDED(m)) { 1.895 + sctp_log_mb(m, SCTP_MBUF_IALLOC); 1.896 + } 1.897 + } 1.898 +#endif 1.899 +#else 1.900 +#if defined(__FreeBSD__) && __FreeBSD_version >= 601000 1.901 + int aloc_size; 1.902 + int index = 0; 1.903 +#endif 1.904 + int mbuf_threshold; 1.905 + if (want_header) { 1.906 + MGETHDR(m, how, type); 1.907 + } else { 1.908 + MGET(m, how, type); 1.909 + } 1.910 + if (m == NULL) { 1.911 + return (NULL); 1.912 + } 1.913 + if (allonebuf == 0) 1.914 + mbuf_threshold = SCTP_BASE_SYSCTL(sctp_mbuf_threshold_count); 1.915 + else 1.916 + mbuf_threshold = 1; 1.917 + 1.918 + 1.919 + if (space_needed > (((mbuf_threshold - 1) * MLEN) + MHLEN)) { 1.920 +#if defined(__FreeBSD__) && __FreeBSD_version >= 601000 1.921 + try_again: 1.922 + index = 4; 1.923 + if (space_needed <= MCLBYTES) { 1.924 + aloc_size = MCLBYTES; 1.925 + } else { 1.926 + aloc_size = MJUMPAGESIZE; 1.927 + index = 5; 1.928 + } 1.929 + m_cljget(m, how, aloc_size); 1.930 + if (m == NULL) { 1.931 + return (NULL); 1.932 + } 1.933 + if (SCTP_BUF_IS_EXTENDED(m) == 0) { 1.934 + if ((aloc_size != MCLBYTES) && 1.935 + (allonebuf == 0)) { 1.936 + aloc_size -= 10; 1.937 + goto try_again; 1.938 + } 1.939 + sctp_m_freem(m); 1.940 + return (NULL); 1.941 + } 1.942 +#else 1.943 + MCLGET(m, how); 1.944 + if (m == NULL) { 1.945 + return (NULL); 1.946 + } 1.947 + if (SCTP_BUF_IS_EXTENDED(m) == 0) { 1.948 + sctp_m_freem(m); 1.949 + return (NULL); 1.950 + } 1.951 +#endif 1.952 + } 1.953 + SCTP_BUF_LEN(m) = 0; 1.954 + SCTP_BUF_NEXT(m) = SCTP_BUF_NEXT_PKT(m) = NULL; 1.955 +#ifdef SCTP_MBUF_LOGGING 1.956 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { 1.957 + if (SCTP_BUF_IS_EXTENDED(m)) { 1.958 + sctp_log_mb(m, SCTP_MBUF_IALLOC); 1.959 + } 1.960 + } 1.961 +#endif 1.962 +#endif 1.963 + return (m); 1.964 +} 1.965 + 1.966 + 1.967 +#ifdef SCTP_PACKET_LOGGING 1.968 +void 1.969 +sctp_packet_log(struct mbuf *m) 1.970 +{ 1.971 + int *lenat, thisone; 1.972 + void *copyto; 1.973 + uint32_t *tick_tock; 1.974 + int length; 1.975 + int total_len; 1.976 + int grabbed_lock = 0; 1.977 + int value, newval, thisend, thisbegin; 1.978 + /* 1.979 + * Buffer layout. 1.980 + * -sizeof this entry (total_len) 1.981 + * -previous end (value) 1.982 + * -ticks of log (ticks) 1.983 + * o -ip packet 1.984 + * o -as logged 1.985 + * - where this started (thisbegin) 1.986 + * x <--end points here 1.987 + */ 1.988 + length = SCTP_HEADER_LEN(m); 1.989 + total_len = SCTP_SIZE32((length + (4 * sizeof(int)))); 1.990 + /* Log a packet to the buffer. */ 1.991 + if (total_len> SCTP_PACKET_LOG_SIZE) { 1.992 + /* Can't log this packet I have not a buffer big enough */ 1.993 + return; 1.994 + } 1.995 + if (length < (int)(SCTP_MIN_V4_OVERHEAD + sizeof(struct sctp_cookie_ack_chunk))) { 1.996 + return; 1.997 + } 1.998 + atomic_add_int(&SCTP_BASE_VAR(packet_log_writers), 1); 1.999 + try_again: 1.1000 + if (SCTP_BASE_VAR(packet_log_writers) > SCTP_PKTLOG_WRITERS_NEED_LOCK) { 1.1001 + SCTP_IP_PKTLOG_LOCK(); 1.1002 + grabbed_lock = 1; 1.1003 + again_locked: 1.1004 + value = SCTP_BASE_VAR(packet_log_end); 1.1005 + newval = SCTP_BASE_VAR(packet_log_end) + total_len; 1.1006 + if (newval >= SCTP_PACKET_LOG_SIZE) { 1.1007 + /* we wrapped */ 1.1008 + thisbegin = 0; 1.1009 + thisend = total_len; 1.1010 + } else { 1.1011 + thisbegin = SCTP_BASE_VAR(packet_log_end); 1.1012 + thisend = newval; 1.1013 + } 1.1014 + if (!(atomic_cmpset_int(&SCTP_BASE_VAR(packet_log_end), value, thisend))) { 1.1015 + goto again_locked; 1.1016 + } 1.1017 + } else { 1.1018 + value = SCTP_BASE_VAR(packet_log_end); 1.1019 + newval = SCTP_BASE_VAR(packet_log_end) + total_len; 1.1020 + if (newval >= SCTP_PACKET_LOG_SIZE) { 1.1021 + /* we wrapped */ 1.1022 + thisbegin = 0; 1.1023 + thisend = total_len; 1.1024 + } else { 1.1025 + thisbegin = SCTP_BASE_VAR(packet_log_end); 1.1026 + thisend = newval; 1.1027 + } 1.1028 + if (!(atomic_cmpset_int(&SCTP_BASE_VAR(packet_log_end), value, thisend))) { 1.1029 + goto try_again; 1.1030 + } 1.1031 + } 1.1032 + /* Sanity check */ 1.1033 + if (thisend >= SCTP_PACKET_LOG_SIZE) { 1.1034 + SCTP_PRINTF("Insanity stops a log thisbegin:%d thisend:%d writers:%d lock:%d end:%d\n", 1.1035 + thisbegin, 1.1036 + thisend, 1.1037 + SCTP_BASE_VAR(packet_log_writers), 1.1038 + grabbed_lock, 1.1039 + SCTP_BASE_VAR(packet_log_end)); 1.1040 + SCTP_BASE_VAR(packet_log_end) = 0; 1.1041 + goto no_log; 1.1042 + 1.1043 + } 1.1044 + lenat = (int *)&SCTP_BASE_VAR(packet_log_buffer)[thisbegin]; 1.1045 + *lenat = total_len; 1.1046 + lenat++; 1.1047 + *lenat = value; 1.1048 + lenat++; 1.1049 + tick_tock = (uint32_t *)lenat; 1.1050 + lenat++; 1.1051 + *tick_tock = sctp_get_tick_count(); 1.1052 + copyto = (void *)lenat; 1.1053 + thisone = thisend - sizeof(int); 1.1054 + lenat = (int *)&SCTP_BASE_VAR(packet_log_buffer)[thisone]; 1.1055 + *lenat = thisbegin; 1.1056 + if (grabbed_lock) { 1.1057 + SCTP_IP_PKTLOG_UNLOCK(); 1.1058 + grabbed_lock = 0; 1.1059 + } 1.1060 + m_copydata(m, 0, length, (caddr_t)copyto); 1.1061 + no_log: 1.1062 + if (grabbed_lock) { 1.1063 + SCTP_IP_PKTLOG_UNLOCK(); 1.1064 + } 1.1065 + atomic_subtract_int(&SCTP_BASE_VAR(packet_log_writers), 1); 1.1066 +} 1.1067 + 1.1068 + 1.1069 +int 1.1070 +sctp_copy_out_packet_log(uint8_t *target, int length) 1.1071 +{ 1.1072 + /* We wind through the packet log starting at 1.1073 + * start copying up to length bytes out. 1.1074 + * We return the number of bytes copied. 1.1075 + */ 1.1076 + int tocopy, this_copy; 1.1077 + int *lenat; 1.1078 + int did_delay = 0; 1.1079 + 1.1080 + tocopy = length; 1.1081 + if (length < (int)(2 * sizeof(int))) { 1.1082 + /* not enough room */ 1.1083 + return (0); 1.1084 + } 1.1085 + if (SCTP_PKTLOG_WRITERS_NEED_LOCK) { 1.1086 + atomic_add_int(&SCTP_BASE_VAR(packet_log_writers), SCTP_PKTLOG_WRITERS_NEED_LOCK); 1.1087 + again: 1.1088 + if ((did_delay == 0) && (SCTP_BASE_VAR(packet_log_writers) != SCTP_PKTLOG_WRITERS_NEED_LOCK)) { 1.1089 + /* we delay here for just a moment hoping the writer(s) that were 1.1090 + * present when we entered will have left and we only have 1.1091 + * locking ones that will contend with us for the lock. This 1.1092 + * does not assure 100% access, but its good enough for 1.1093 + * a logging facility like this. 1.1094 + */ 1.1095 + did_delay = 1; 1.1096 + DELAY(10); 1.1097 + goto again; 1.1098 + } 1.1099 + } 1.1100 + SCTP_IP_PKTLOG_LOCK(); 1.1101 + lenat = (int *)target; 1.1102 + *lenat = SCTP_BASE_VAR(packet_log_end); 1.1103 + lenat++; 1.1104 + this_copy = min((length - sizeof(int)), SCTP_PACKET_LOG_SIZE); 1.1105 + memcpy((void *)lenat, (void *)SCTP_BASE_VAR(packet_log_buffer), this_copy); 1.1106 + if (SCTP_PKTLOG_WRITERS_NEED_LOCK) { 1.1107 + atomic_subtract_int(&SCTP_BASE_VAR(packet_log_writers), 1.1108 + SCTP_PKTLOG_WRITERS_NEED_LOCK); 1.1109 + } 1.1110 + SCTP_IP_PKTLOG_UNLOCK(); 1.1111 + return (this_copy + sizeof(int)); 1.1112 +} 1.1113 + 1.1114 +#endif