netwerk/sctp/src/netinet/sctp_bsd_addr.c

changeset 0
6474c204b198
     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

mercurial