netwerk/sctp/src/netinet/sctp_bsd_addr.c

Thu, 15 Jan 2015 21:03:48 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 21:03:48 +0100
branch
TOR_BUG_9701
changeset 11
deefc01c0e14
permissions
-rwxr-xr-x

Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)

     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  */
    33 #ifdef __FreeBSD__
    34 #include <sys/cdefs.h>
    35 __FBSDID("$FreeBSD: head/sys/netinet/sctp_bsd_addr.c 258765 2013-11-30 12:51:19Z tuexen $");
    36 #endif
    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
    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
    84 /* Global NON-VNET structure that controls the iterator */
    85 struct iterator_control sctp_it_ctl;
    87 #if !defined(__FreeBSD__)
    88 static void
    89 sctp_cleanup_itqueue(void)
    90 {
    91 	struct sctp_iterator *it, *nit;
    93 	TAILQ_FOREACH_SAFE(it, &sctp_it_ctl.iteratorhead, sctp_nxt_itr, nit) {
    94 		if (it->function_atend != NULL) {
    95 			(*it->function_atend) (it->pointer, it->val);
    96 		}
    97 		TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, it, sctp_nxt_itr);
    98 		SCTP_FREE(it, SCTP_M_ITER);
    99 	}
   100 }
   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
   111 void
   112 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 	pthread_cond_broadcast(&sctp_it_ctl.iterator_wakeup);
   119 #endif
   120 #else
   121 	wakeup(&sctp_it_ctl.iterator_running);
   122 #endif
   123 }
   125 #if defined(__Userspace__)
   126 static void *
   127 #else
   128 static void
   129 #endif
   130 sctp_iterator_thread(void *v SCTP_UNUSED)
   131 {
   132 	SCTP_IPI_ITERATOR_WQ_LOCK();
   133 	/* In FreeBSD this thread never terminates. */
   134 #if defined(__FreeBSD__)
   135 	for (;;) {
   136 #else
   137 	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 		pthread_cond_wait(&sctp_it_ctl.iterator_wakeup, &sctp_it_ctl.ipi_iterator_wq_mtx);
   152 #endif
   153 #endif
   154 #if !defined(__FreeBSD__)
   155 		if (sctp_it_ctl.iterator_flags & SCTP_ITERATOR_MUST_EXIT) {
   156 			break;
   157 		}
   158 #endif
   159 		sctp_iterator_worker();
   160 	}
   161 #if !defined(__FreeBSD__)
   162 	/* Now this thread needs to be terminated */
   163 	sctp_cleanup_itqueue();
   164 	sctp_it_ctl.iterator_flags |= SCTP_ITERATOR_EXITED;
   165 	SCTP_IPI_ITERATOR_WQ_UNLOCK();
   166 #if defined(__Userspace__)
   167 	sctp_wakeup_iterator();
   168 	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 }
   179 void
   180 sctp_startup_iterator(void)
   181 {
   182 	if (sctp_it_ctl.thread_proc) {
   183 		/* You only get one */
   184 		return;
   185 	}
   186 	/* Initialize global locks here, thus only once. */
   187 	SCTP_ITERATOR_LOCK_INIT();
   188 	SCTP_IPI_ITERATOR_WQ_INIT();
   189 	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 	if (pthread_create(&sctp_it_ctl.thread_proc, NULL, &sctp_iterator_thread, NULL)) {
   208 #endif
   209 		SCTP_PRINTF("ERROR: Creating sctp_iterator_thread failed.\n");
   210 	}
   211 #endif
   212 }
   214 #ifdef INET6
   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;
   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 */
   256 #if !defined(__Userspace__)
   257 static uint32_t
   258 sctp_is_desired_interface_type(struct ifnet *ifn)
   259 {
   260 	int result;
   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 	}
   302 	return (result);
   303 }
   304 #endif
   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
   314 #if defined(__Userspace_os_Windows)
   315 #ifdef MALLOC
   316 #undef MALLOC
   317 #define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
   318 #endif
   319 #ifdef FREE
   320 #undef FREE
   321 #define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
   322 #endif
   323 static void
   324 sctp_init_ifns_for_vrf(int vrfid)
   325 {
   326 #if defined(INET) || defined(INET6)
   327 	struct ifaddrs *ifa;
   328 	struct sctp_ifa *sctp_ifa;
   329 	DWORD Err, AdapterAddrsSize;
   330 	PIP_ADAPTER_ADDRESSES pAdapterAddrs, pAdapt;
   331 	PIP_ADAPTER_UNICAST_ADDRESS pUnicast;
   332 #endif
   334 #ifdef INET
   335 	AdapterAddrsSize = 0;
   337 	if ((Err = GetAdaptersAddresses(AF_INET, 0, NULL, NULL, &AdapterAddrsSize)) != 0) {
   338 		if ((Err != ERROR_BUFFER_OVERFLOW) && (Err != ERROR_INSUFFICIENT_BUFFER)) {
   339 			SCTP_PRINTF("GetAdaptersV4Addresses() sizing failed with error code %d\n", Err);
   340 			SCTP_PRINTF("err = %d; AdapterAddrsSize = %d\n", Err, AdapterAddrsSize);
   341 			return;
   342 		}
   343 	}
   345 	/* Allocate memory from sizing information */
   346 	if ((pAdapterAddrs = (PIP_ADAPTER_ADDRESSES) GlobalAlloc(GPTR, AdapterAddrsSize)) == NULL) {
   347 		SCTP_PRINTF("Memory allocation error!\n");
   348 		return;
   349 	}
   350 	/* Get actual adapter information */
   351 	if ((Err = GetAdaptersAddresses(AF_INET, 0, NULL, pAdapterAddrs, &AdapterAddrsSize)) != ERROR_SUCCESS) {
   352 		SCTP_PRINTF("GetAdaptersV4Addresses() failed with error code %d\n", Err);
   353 		return;
   354 	}
   355 	/* Enumerate through each returned adapter and save its information */
   356 	for (pAdapt = pAdapterAddrs; pAdapt; pAdapt = pAdapt->Next) {
   357 		if (pAdapt->IfType == IF_TYPE_IEEE80211 || pAdapt->IfType == IF_TYPE_ETHERNET_CSMACD) {
   358 			for (pUnicast = pAdapt->FirstUnicastAddress; pUnicast; pUnicast = pUnicast->Next) {
   359 				if (IN4_ISLINKLOCAL_ADDRESS(&(((struct sockaddr_in *)(pUnicast->Address.lpSockaddr))->sin_addr))) {
   360 					continue;
   361 				}
   362 				ifa = (struct ifaddrs*)malloc(sizeof(struct ifaddrs));
   363 				ifa->ifa_name = strdup(pAdapt->AdapterName);
   364 				ifa->ifa_flags = pAdapt->Flags;
   365 				ifa->ifa_addr = (struct sockaddr *)malloc(sizeof(struct sockaddr_in));
   366 				memcpy(ifa->ifa_addr, pUnicast->Address.lpSockaddr, sizeof(struct sockaddr_in));
   368 				sctp_ifa = sctp_add_addr_to_vrf(0,
   369 				                                ifa,
   370 				                                pAdapt->IfIndex,
   371 				                                (pAdapt->IfType == IF_TYPE_IEEE80211)?MIB_IF_TYPE_ETHERNET:pAdapt->IfType,
   372 				                                ifa->ifa_name,
   373 				                                (void *)ifa,
   374 				                                ifa->ifa_addr,
   375 				                                ifa->ifa_flags,
   376 				                                0);
   377 				if (sctp_ifa) {
   378 					sctp_ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE;
   379 				}
   380 			}
   381 		}
   382 	}
   383 	if (pAdapterAddrs)
   384 		FREE(pAdapterAddrs);
   385 #endif
   386 #ifdef INET6
   387 	AdapterAddrsSize = 0;
   389 	if ((Err = GetAdaptersAddresses(AF_INET6, 0, NULL, NULL, &AdapterAddrsSize)) != 0) {
   390 		if ((Err != ERROR_BUFFER_OVERFLOW) && (Err != ERROR_INSUFFICIENT_BUFFER)) {
   391 			SCTP_PRINTF("GetAdaptersV6Addresses() sizing failed with error code %d\n", Err);
   392 			SCTP_PRINTF("err = %d; AdapterAddrsSize = %d\n", Err, AdapterAddrsSize);
   393 			return;
   394 		}
   395 	}
   396 	/* Allocate memory from sizing information */
   397 	if ((pAdapterAddrs = (PIP_ADAPTER_ADDRESSES) GlobalAlloc(GPTR, AdapterAddrsSize)) == NULL) {
   398 		SCTP_PRINTF("Memory allocation error!\n");
   399 		return;
   400 	}
   401 	/* Get actual adapter information */
   402 	if ((Err = GetAdaptersAddresses(AF_INET6, 0, NULL, pAdapterAddrs, &AdapterAddrsSize)) != ERROR_SUCCESS) {
   403 		SCTP_PRINTF("GetAdaptersV6Addresses() failed with error code %d\n", Err);
   404 		return;
   405 	}
   406 	/* Enumerate through each returned adapter and save its information */
   407 	for (pAdapt = pAdapterAddrs; pAdapt; pAdapt = pAdapt->Next) {
   408 		if (pAdapt->IfType == IF_TYPE_IEEE80211 || pAdapt->IfType == IF_TYPE_ETHERNET_CSMACD) {
   409 			for (pUnicast = pAdapt->FirstUnicastAddress; pUnicast; pUnicast = pUnicast->Next) {
   410 				ifa = (struct ifaddrs*)malloc(sizeof(struct ifaddrs));
   411 				ifa->ifa_name = strdup(pAdapt->AdapterName);
   412 				ifa->ifa_flags = pAdapt->Flags;
   413 				ifa->ifa_addr = (struct sockaddr *)malloc(sizeof(struct sockaddr_in6));
   414 				memcpy(ifa->ifa_addr, pUnicast->Address.lpSockaddr, sizeof(struct sockaddr_in6));
   415 				sctp_ifa = sctp_add_addr_to_vrf(0,
   416 				                                ifa,
   417 				                                pAdapt->Ipv6IfIndex,
   418 				                                (pAdapt->IfType == IF_TYPE_IEEE80211)?MIB_IF_TYPE_ETHERNET:pAdapt->IfType,
   419 				                                ifa->ifa_name,
   420 				                                (void *)ifa,
   421 				                                ifa->ifa_addr,
   422 				                                ifa->ifa_flags,
   423 				                                0);
   424 				if (sctp_ifa) {
   425 					sctp_ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE;
   426 				}
   427 			}
   428 		}
   429 	}
   430 	if (pAdapterAddrs)
   431 		FREE(pAdapterAddrs);
   432 #endif
   433 }
   434 #elif defined(__Userspace__)
   435 static void
   436 sctp_init_ifns_for_vrf(int vrfid)
   437 {
   438 #if defined(INET) || defined(INET6)
   439 	int rc;
   440 	struct ifaddrs *ifa = NULL;
   441 	struct sctp_ifa *sctp_ifa;
   442 	uint32_t ifa_flags;
   444 	rc = getifaddrs(&g_interfaces);
   445 	if (rc != 0) {
   446 		return;
   447 	}
   448 	for (ifa = g_interfaces; ifa; ifa = ifa->ifa_next) {
   449 		if (ifa->ifa_addr == NULL) {
   450 			continue;
   451 		}
   452 #if !defined(INET)
   453 		if (ifa->ifa_addr->sa_family != AF_INET6) {
   454 			/* non inet6 skip */
   455 			continue;
   456 		}
   457 #elif !defined(INET6)
   458 		if (ifa->ifa_addr->sa_family != AF_INET) {
   459 			/* non inet skip */
   460 			continue;
   461 		}
   462 #else
   463 		if ((ifa->ifa_addr->sa_family != AF_INET) && (ifa->ifa_addr->sa_family != AF_INET6)) {
   464 			/* non inet/inet6 skip */
   465 			continue;
   466 		}
   467 #endif
   468 #if defined(INET6)
   469 		if ((ifa->ifa_addr->sa_family == AF_INET6) &&
   470 		    IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) {
   471 			/* skip unspecifed addresses */
   472 			continue;
   473 		}
   474 #endif
   475 #if defined(INET)
   476 		if (ifa->ifa_addr->sa_family == AF_INET &&
   477 		    ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) {
   478 			continue;
   479 		}
   480 #endif
   481 		ifa_flags = 0;
   482 		sctp_ifa = sctp_add_addr_to_vrf(vrfid,
   483 		                                ifa,
   484 		                                if_nametoindex(ifa->ifa_name),
   485 		                                0,
   486 		                                ifa->ifa_name,
   487 		                                (void *)ifa,
   488 		                                ifa->ifa_addr,
   489 		                                ifa_flags,
   490 		                                0);
   491 		if (sctp_ifa) {
   492 			sctp_ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE;
   493 		}
   494 	}
   495 #endif
   496 }
   497 #endif
   499 #if defined(__APPLE__)
   500 static void
   501 sctp_init_ifns_for_vrf(int vrfid)
   502 {
   503 	/* Here we must apply ANY locks needed by the
   504 	 * IFN we access and also make sure we lock
   505 	 * any IFA that exists as we float through the
   506 	 * list of IFA's
   507 	 */
   508 	struct ifnet **ifnetlist;
   509 	uint32_t i, j, count;
   510 	char name[SCTP_IFNAMSIZ];
   511 	struct ifnet *ifn;
   512 	struct ifaddr **ifaddrlist;
   513 	struct ifaddr *ifa;
   514 	struct in6_ifaddr *ifa6;
   515 	struct sctp_ifa *sctp_ifa;
   516 	uint32_t ifa_flags;
   518 	if (ifnet_list_get(IFNET_FAMILY_ANY, &ifnetlist, &count) != 0) {
   519 		return;
   520 	}
   521 	for (i = 0; i < count; i++) {
   522 		ifn = ifnetlist[i];
   523 		if (SCTP_BASE_SYSCTL(sctp_ignore_vmware_interfaces) && sctp_is_vmware_interface(ifn)) {
   524 			continue;
   525 		}
   526 		if (sctp_is_desired_interface_type(ifn) == 0) {
   527 			/* non desired type */
   528 			continue;
   529 		}
   530 		if (ifnet_get_address_list(ifn, &ifaddrlist) != 0) {
   531 			continue;
   532 		}
   533 		for (j = 0; ifaddrlist[j] != NULL; j++) {
   534 			ifa = ifaddrlist[j];
   535 			if (ifa->ifa_addr == NULL) {
   536 				continue;
   537 			}
   538 			if ((ifa->ifa_addr->sa_family != AF_INET) && (ifa->ifa_addr->sa_family != AF_INET6)) {
   539 				/* non inet/inet6 skip */
   540 				continue;
   541 			}
   542 			if (ifa->ifa_addr->sa_family == AF_INET6) {
   543 				if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) {
   544 					/* skip unspecifed addresses */
   545 					continue;
   546 				}
   547 			} else {
   548 				if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == INADDR_ANY) {
   549 					continue;
   550 				}
   551 			}
   552 			if (ifa->ifa_addr->sa_family == AF_INET6) {
   553 				ifa6 = (struct in6_ifaddr *)ifa;
   554 				ifa_flags = ifa6->ia6_flags;
   555 			} else {
   556 				ifa_flags = 0;
   557 			}
   558 			snprintf(name, SCTP_IFNAMSIZ, "%s%d", ifnet_name(ifn), ifnet_unit(ifn));
   559 			sctp_ifa = sctp_add_addr_to_vrf(vrfid,
   560 			                                (void *)ifn,
   561 			                                ifnet_index(ifn),
   562 			                                ifnet_type(ifn),
   563 			                                name,
   564 			                                (void *)ifa,
   565 			                                ifa->ifa_addr,
   566 			                                ifa_flags,
   567 			                                0);
   568 			if (sctp_ifa) {
   569 				sctp_ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE;
   570 			}
   571 		}
   572 		ifnet_free_address_list(ifaddrlist);
   573 	}
   574 	ifnet_list_free(ifnetlist);
   575 }
   576 #endif
   578 #if defined(__FreeBSD__)
   579 static void
   580 sctp_init_ifns_for_vrf(int vrfid)
   581 {
   582 	/* Here we must apply ANY locks needed by the
   583 	 * IFN we access and also make sure we lock
   584 	 * any IFA that exists as we float through the
   585 	 * list of IFA's
   586 	 */
   587 	struct ifnet *ifn;
   588 	struct ifaddr *ifa;
   589 	struct sctp_ifa *sctp_ifa;
   590 	uint32_t ifa_flags;
   591 #ifdef INET6
   592 	struct in6_ifaddr *ifa6;
   593 #endif
   595 	IFNET_RLOCK();
   596 	TAILQ_FOREACH(ifn, &MODULE_GLOBAL(ifnet), if_list) {
   597 		if (sctp_is_desired_interface_type(ifn) == 0) {
   598 			/* non desired type */
   599 			continue;
   600 		}
   601 #if (__FreeBSD_version >= 803000 && __FreeBSD_version < 900000) || __FreeBSD_version > 900000
   602 		IF_ADDR_RLOCK(ifn);
   603 #else
   604 		IF_ADDR_LOCK(ifn);
   605 #endif
   606 		TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list) {
   607 			if (ifa->ifa_addr == NULL) {
   608 				continue;
   609 			}
   610 			switch (ifa->ifa_addr->sa_family) {
   611 #ifdef INET
   612 			case AF_INET:
   613 				if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) {
   614 					continue;
   615 				}
   616 				break;
   617 #endif
   618 #ifdef INET6
   619 			case AF_INET6:
   620 				if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) {
   621 					/* skip unspecifed addresses */
   622 					continue;
   623 				}
   624 				break;
   625 #endif
   626 			default:
   627 				continue;
   628 			}
   629 			switch (ifa->ifa_addr->sa_family) {
   630 #ifdef INET
   631 			case AF_INET:
   632 				ifa_flags = 0;
   633 				break;
   634 #endif
   635 #ifdef INET6
   636 			case AF_INET6:
   637 				ifa6 = (struct in6_ifaddr *)ifa;
   638 				ifa_flags = ifa6->ia6_flags;
   639 				break;
   640 #endif
   641 			default:
   642 				ifa_flags = 0;
   643 				break;
   644 			}
   645 			sctp_ifa = sctp_add_addr_to_vrf(vrfid,
   646 			                                (void *)ifn,
   647 			                                ifn->if_index,
   648 			                                ifn->if_type,
   649 			                                ifn->if_xname,
   650 			                                (void *)ifa,
   651 			                                ifa->ifa_addr,
   652 			                                ifa_flags,
   653 			                                0);
   654 			if (sctp_ifa) {
   655 				sctp_ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE;
   656 			}
   657 		}
   658 #if (__FreeBSD_version >= 803000 && __FreeBSD_version < 900000) || __FreeBSD_version > 900000
   659 		IF_ADDR_RUNLOCK(ifn);
   660 #else
   661 		IF_ADDR_UNLOCK(ifn);
   662 #endif
   663 	}
   664 	IFNET_RUNLOCK();
   665 }
   666 #endif
   668 void
   669 sctp_init_vrf_list(int vrfid)
   670 {
   671 	if (vrfid > SCTP_MAX_VRF_ID)
   672 		/* can't do that */
   673 		return;
   675 	/* Don't care about return here */
   676 	(void)sctp_allocate_vrf(vrfid);
   678 	/* Now we need to build all the ifn's
   679 	 * for this vrf and there addresses
   680 	 */
   681 	sctp_init_ifns_for_vrf(vrfid);
   682 }
   684 void
   685 sctp_addr_change(struct ifaddr *ifa, int cmd)
   686 {
   687 #if defined(__Userspace__)
   688         return;
   689 #else
   690 	uint32_t ifa_flags = 0;
   691 	/* BSD only has one VRF, if this changes
   692 	 * we will need to hook in the right
   693 	 * things here to get the id to pass to
   694 	 * the address managment routine.
   695 	 */
   696 	if (SCTP_BASE_VAR(first_time) == 0) {
   697 		/* Special test to see if my ::1 will showup with this */
   698 		SCTP_BASE_VAR(first_time) = 1;
   699 		sctp_init_ifns_for_vrf(SCTP_DEFAULT_VRFID);
   700 	}
   702 	if ((cmd != RTM_ADD) && (cmd != RTM_DELETE)) {
   703 		/* don't know what to do with this */
   704 		return;
   705 	}
   707 	if (ifa->ifa_addr == NULL) {
   708 		return;
   709 	}
   710 	if (sctp_is_desired_interface_type(ifa->ifa_ifp) == 0) {
   711 		/* non desired type */
   712 		return;
   713 	}
   714 	switch (ifa->ifa_addr->sa_family) {
   715 #ifdef INET
   716 	case AF_INET:
   717 		if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) {
   718 			return;
   719 		}
   720 		break;
   721 #endif
   722 #ifdef INET6
   723 	case AF_INET6:
   724 		ifa_flags = ((struct in6_ifaddr *)ifa)->ia6_flags;
   725 		if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) {
   726 			/* skip unspecifed addresses */
   727 			return;
   728 		}
   729 		break;
   730 #endif
   731 	default:
   732 		/* non inet/inet6 skip */
   733 		return;
   734 	}
   735 	if (cmd == RTM_ADD) {
   736 		(void)sctp_add_addr_to_vrf(SCTP_DEFAULT_VRFID, (void *)ifa->ifa_ifp,
   737 #if defined(__APPLE__)
   738 		                           ifnet_index(ifa->ifa_ifp), ifnet_type(ifa->ifa_ifp), ifnet_name(ifa->ifa_ifp),
   739 #else
   740 		                           ifa->ifa_ifp->if_index, ifa->ifa_ifp->if_type, ifa->ifa_ifp->if_xname,
   741 #endif
   742 		                           (void *)ifa, ifa->ifa_addr, ifa_flags, 1);
   743 	} else {
   745 		sctp_del_addr_from_vrf(SCTP_DEFAULT_VRFID, ifa->ifa_addr,
   746 #if defined(__APPLE__)
   747 		                       ifnet_index(ifa->ifa_ifp),
   748 		                       ifnet_name(ifa->ifa_ifp));
   749 #else
   750 		                       ifa->ifa_ifp->if_index,
   751 		                       ifa->ifa_ifp->if_xname);
   752 #endif
   754 		/* We don't bump refcount here so when it completes
   755 		 * the final delete will happen.
   756 		 */
   757 	}
   758 #endif
   759 }
   761 #if defined(__FreeBSD__)
   762 void
   763 sctp_add_or_del_interfaces(int (*pred)(struct ifnet *), int add)
   764 {
   765 	struct ifnet *ifn;
   766 	struct ifaddr *ifa;
   768 	IFNET_RLOCK();
   769 	TAILQ_FOREACH(ifn, &MODULE_GLOBAL(ifnet), if_list) {
   770 		if (!(*pred)(ifn)) {
   771 			continue;
   772 		}
   773 		TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list) {
   774 			sctp_addr_change(ifa, add ? RTM_ADD : RTM_DELETE);
   775 		}
   776 	}
   777 	IFNET_RUNLOCK();
   778 }
   779 #endif
   780 #if defined(__APPLE__)
   781 void
   782 sctp_add_or_del_interfaces(int (*pred)(struct ifnet *), int add)
   783 {
   784 	struct ifnet **ifnetlist;
   785 	struct ifaddr **ifaddrlist;
   786 	uint32_t i, j, count;
   788 	if (ifnet_list_get(IFNET_FAMILY_ANY, &ifnetlist, &count) != 0) {
   789 		return;
   790 	}
   791 	for (i = 0; i < count; i++) {
   792 		if (!(*pred)(ifnetlist[i])) {
   793 			continue;
   794 		}
   795 		if (ifnet_get_address_list(ifnetlist[i], &ifaddrlist) != 0) {
   796 			continue;
   797 		}
   798 		for (j = 0; ifaddrlist[j] != NULL; j++) {
   799 			sctp_addr_change(ifaddrlist[j], add ? RTM_ADD : RTM_DELETE);
   800 		}
   801 		ifnet_free_address_list(ifaddrlist);
   802 	}
   803 	ifnet_list_free(ifnetlist);
   804 	return;
   805 }
   806 #endif
   808 struct mbuf *
   809 sctp_get_mbuf_for_msg(unsigned int space_needed, int want_header,
   810 		      int how, int allonebuf, int type)
   811 {
   812     struct mbuf *m = NULL;
   813 #if defined(__Userspace__)
   815   /*
   816    * __Userspace__
   817    * Using m_clget, which creates and mbuf and a cluster and
   818    * hooks those together.
   819    * TODO: This does not yet have functionality for jumbo packets.
   820    *
   821    */
   823 	int mbuf_threshold;
   824 	if (want_header) {
   825 		MGETHDR(m, how, type);
   826 	} else {
   827 		MGET(m, how, type);
   828 	}
   829 	if (m == NULL) {
   830 		return (NULL);
   831 	}
   832 	if (allonebuf == 0)
   833 		mbuf_threshold = SCTP_BASE_SYSCTL(sctp_mbuf_threshold_count);
   834 	else
   835 		mbuf_threshold = 1;
   838 	if ((int)space_needed > (((mbuf_threshold - 1) * MLEN) + MHLEN)) {
   839 		MCLGET(m, how);
   840 		if (m == NULL) {
   841 			return (NULL);
   842 		}
   844 		if (SCTP_BUF_IS_EXTENDED(m) == 0) {
   845 		  sctp_m_freem(m);
   846 		  return (NULL);
   847 		}
   848 	}
   849 	SCTP_BUF_LEN(m) = 0;
   850 	SCTP_BUF_NEXT(m) = SCTP_BUF_NEXT_PKT(m) = NULL;
   852 #if defined(__Userspace__)
   853 	/* __Userspace__
   854 	 * Check if anything need to be done to ensure logging works
   855 	 */
   856 #endif
   857 #ifdef SCTP_MBUF_LOGGING
   858 	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
   859 		if (SCTP_BUF_IS_EXTENDED(m)) {
   860 			sctp_log_mb(m, SCTP_MBUF_IALLOC);
   861 		}
   862 	}
   863 #endif
   864 #elif defined(__FreeBSD__) && __FreeBSD_version > 602000
   865 	m =  m_getm2(NULL, space_needed, how, type, want_header ? M_PKTHDR : 0);
   866 	if (m == NULL) {
   867 		/* bad, no memory */
   868 		return (m);
   869 	}
   870 	if (allonebuf) {
   871 		int siz;
   872 		if (SCTP_BUF_IS_EXTENDED(m)) {
   873 			siz = SCTP_BUF_EXTEND_SIZE(m);
   874 		} else {
   875 			if (want_header)
   876 				siz = MHLEN;
   877 			else
   878 				siz = MLEN;
   879 		}
   880 		if (siz < space_needed) {
   881 			m_freem(m);
   882 			return (NULL);
   883 		}
   884 	}
   885 	if (SCTP_BUF_NEXT(m)) {
   886 		sctp_m_freem( SCTP_BUF_NEXT(m));
   887 		SCTP_BUF_NEXT(m) = NULL;
   888 	}
   889 #ifdef SCTP_MBUF_LOGGING
   890 	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
   891 		if (SCTP_BUF_IS_EXTENDED(m)) {
   892 			sctp_log_mb(m, SCTP_MBUF_IALLOC);
   893 		}
   894 	}
   895 #endif
   896 #else
   897 #if defined(__FreeBSD__) && __FreeBSD_version >= 601000
   898 	int aloc_size;
   899 	int index = 0;
   900 #endif
   901 	int mbuf_threshold;
   902 	if (want_header) {
   903 		MGETHDR(m, how, type);
   904 	} else {
   905 		MGET(m, how, type);
   906 	}
   907 	if (m == NULL) {
   908 		return (NULL);
   909 	}
   910 	if (allonebuf == 0)
   911 		mbuf_threshold = SCTP_BASE_SYSCTL(sctp_mbuf_threshold_count);
   912 	else
   913 		mbuf_threshold = 1;
   916 	if (space_needed > (((mbuf_threshold - 1) * MLEN) + MHLEN)) {
   917 #if defined(__FreeBSD__) && __FreeBSD_version >= 601000
   918 	try_again:
   919 		index = 4;
   920 		if (space_needed <= MCLBYTES) {
   921 			aloc_size = MCLBYTES;
   922 		} else {
   923 			aloc_size = MJUMPAGESIZE;
   924 			index = 5;
   925 		}
   926 		m_cljget(m, how, aloc_size);
   927 		if (m == NULL) {
   928 			return (NULL);
   929 		}
   930 		if (SCTP_BUF_IS_EXTENDED(m) == 0) {
   931 			if ((aloc_size != MCLBYTES) &&
   932 			   (allonebuf == 0)) {
   933 				aloc_size -= 10;
   934 				goto try_again;
   935 			}
   936 			sctp_m_freem(m);
   937 			return (NULL);
   938 		}
   939 #else
   940 		MCLGET(m, how);
   941 		if (m == NULL) {
   942 			return (NULL);
   943 		}
   944 		if (SCTP_BUF_IS_EXTENDED(m) == 0) {
   945 			sctp_m_freem(m);
   946 			return (NULL);
   947 		}
   948 #endif
   949 	}
   950 	SCTP_BUF_LEN(m) = 0;
   951 	SCTP_BUF_NEXT(m) = SCTP_BUF_NEXT_PKT(m) = NULL;
   952 #ifdef SCTP_MBUF_LOGGING
   953 	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
   954 		if (SCTP_BUF_IS_EXTENDED(m)) {
   955 			sctp_log_mb(m, SCTP_MBUF_IALLOC);
   956 		}
   957 	}
   958 #endif
   959 #endif
   960 	return (m);
   961 }
   964 #ifdef SCTP_PACKET_LOGGING
   965 void
   966 sctp_packet_log(struct mbuf *m)
   967 {
   968 	int *lenat, thisone;
   969 	void *copyto;
   970 	uint32_t *tick_tock;
   971 	int length;
   972 	int total_len;
   973 	int grabbed_lock = 0;
   974 	int value, newval, thisend, thisbegin;
   975 	/*
   976 	 * Buffer layout.
   977 	 * -sizeof this entry (total_len)
   978 	 * -previous end      (value)
   979 	 * -ticks of log      (ticks)
   980 	 * o -ip packet
   981 	 * o -as logged
   982 	 * - where this started (thisbegin)
   983 	 * x <--end points here
   984 	 */
   985 	length = SCTP_HEADER_LEN(m);
   986 	total_len = SCTP_SIZE32((length + (4 * sizeof(int))));
   987 	/* Log a packet to the buffer. */
   988 	if (total_len> SCTP_PACKET_LOG_SIZE) {
   989 		/* Can't log this packet I have not a buffer big enough */
   990 		return;
   991 	}
   992 	if (length < (int)(SCTP_MIN_V4_OVERHEAD + sizeof(struct sctp_cookie_ack_chunk))) {
   993 		return;
   994 	}
   995 	atomic_add_int(&SCTP_BASE_VAR(packet_log_writers), 1);
   996  try_again:
   997 	if (SCTP_BASE_VAR(packet_log_writers) > SCTP_PKTLOG_WRITERS_NEED_LOCK) {
   998 		SCTP_IP_PKTLOG_LOCK();
   999 		grabbed_lock = 1;
  1000 	again_locked:
  1001 		value = SCTP_BASE_VAR(packet_log_end);
  1002 		newval = SCTP_BASE_VAR(packet_log_end) + total_len;
  1003 		if (newval >= SCTP_PACKET_LOG_SIZE) {
  1004 			/* we wrapped */
  1005 			thisbegin = 0;
  1006 			thisend = total_len;
  1007 		} else {
  1008 			thisbegin = SCTP_BASE_VAR(packet_log_end);
  1009 			thisend = newval;
  1011 		if (!(atomic_cmpset_int(&SCTP_BASE_VAR(packet_log_end), value, thisend))) {
  1012 			goto again_locked;
  1014 	} else {
  1015 		value = SCTP_BASE_VAR(packet_log_end);
  1016 		newval = SCTP_BASE_VAR(packet_log_end) + total_len;
  1017 		if (newval >= SCTP_PACKET_LOG_SIZE) {
  1018 			/* we wrapped */
  1019 			thisbegin = 0;
  1020 			thisend = total_len;
  1021 		} else {
  1022 			thisbegin = SCTP_BASE_VAR(packet_log_end);
  1023 			thisend = newval;
  1025 		if (!(atomic_cmpset_int(&SCTP_BASE_VAR(packet_log_end), value, thisend))) {
  1026 			goto try_again;
  1029 	/* Sanity check */
  1030 	if (thisend >= SCTP_PACKET_LOG_SIZE) {
  1031 		SCTP_PRINTF("Insanity stops a log thisbegin:%d thisend:%d writers:%d lock:%d end:%d\n",
  1032 		            thisbegin,
  1033 		            thisend,
  1034 		            SCTP_BASE_VAR(packet_log_writers),
  1035 		            grabbed_lock,
  1036 		            SCTP_BASE_VAR(packet_log_end));
  1037 		SCTP_BASE_VAR(packet_log_end) = 0;
  1038 		goto no_log;
  1041 	lenat = (int *)&SCTP_BASE_VAR(packet_log_buffer)[thisbegin];
  1042 	*lenat = total_len;
  1043 	lenat++;
  1044 	*lenat = value;
  1045 	lenat++;
  1046 	tick_tock = (uint32_t *)lenat;
  1047 	lenat++;
  1048 	*tick_tock = sctp_get_tick_count();
  1049 	copyto = (void *)lenat;
  1050 	thisone = thisend - sizeof(int);
  1051 	lenat = (int *)&SCTP_BASE_VAR(packet_log_buffer)[thisone];
  1052 	*lenat = thisbegin;
  1053 	if (grabbed_lock) {
  1054 		SCTP_IP_PKTLOG_UNLOCK();
  1055 		grabbed_lock = 0;
  1057 	m_copydata(m, 0, length, (caddr_t)copyto);
  1058  no_log:
  1059 	if (grabbed_lock) {
  1060 		SCTP_IP_PKTLOG_UNLOCK();
  1062 	atomic_subtract_int(&SCTP_BASE_VAR(packet_log_writers), 1);
  1066 int
  1067 sctp_copy_out_packet_log(uint8_t *target, int length)
  1069 	/* We wind through the packet log starting at
  1070 	 * start copying up to length bytes out.
  1071 	 * We return the number of bytes copied.
  1072 	 */
  1073 	int tocopy, this_copy;
  1074 	int *lenat;
  1075 	int did_delay = 0;
  1077 	tocopy = length;
  1078 	if (length < (int)(2 * sizeof(int))) {
  1079 		/* not enough room */
  1080 		return (0);
  1082 	if (SCTP_PKTLOG_WRITERS_NEED_LOCK) {
  1083 		atomic_add_int(&SCTP_BASE_VAR(packet_log_writers), SCTP_PKTLOG_WRITERS_NEED_LOCK);
  1084 	again:
  1085 		if ((did_delay == 0) && (SCTP_BASE_VAR(packet_log_writers) != SCTP_PKTLOG_WRITERS_NEED_LOCK)) {
  1086 			/* we delay here for just a moment hoping the writer(s) that were
  1087 			 * present when we entered will have left and we only have
  1088 			 * locking ones that will contend with us for the lock. This
  1089 			 * does not assure 100% access, but its good enough for
  1090 			 * a logging facility like this.
  1091 			 */
  1092 			did_delay = 1;
  1093 			DELAY(10);
  1094 			goto again;
  1097 	SCTP_IP_PKTLOG_LOCK();
  1098 	lenat = (int *)target;
  1099 	*lenat = SCTP_BASE_VAR(packet_log_end);
  1100 	lenat++;
  1101 	this_copy = min((length - sizeof(int)), SCTP_PACKET_LOG_SIZE);
  1102 	memcpy((void *)lenat, (void *)SCTP_BASE_VAR(packet_log_buffer), this_copy);
  1103 	if (SCTP_PKTLOG_WRITERS_NEED_LOCK) {
  1104 		atomic_subtract_int(&SCTP_BASE_VAR(packet_log_writers),
  1105 				    SCTP_PKTLOG_WRITERS_NEED_LOCK);
  1107 	SCTP_IP_PKTLOG_UNLOCK();
  1108 	return (this_copy + sizeof(int));
  1111 #endif

mercurial