Thu, 15 Jan 2015 21:03:48 +0100
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;
1010 }
1011 if (!(atomic_cmpset_int(&SCTP_BASE_VAR(packet_log_end), value, thisend))) {
1012 goto again_locked;
1013 }
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;
1024 }
1025 if (!(atomic_cmpset_int(&SCTP_BASE_VAR(packet_log_end), value, thisend))) {
1026 goto try_again;
1027 }
1028 }
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;
1040 }
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;
1056 }
1057 m_copydata(m, 0, length, (caddr_t)copyto);
1058 no_log:
1059 if (grabbed_lock) {
1060 SCTP_IP_PKTLOG_UNLOCK();
1061 }
1062 atomic_subtract_int(&SCTP_BASE_VAR(packet_log_writers), 1);
1063 }
1066 int
1067 sctp_copy_out_packet_log(uint8_t *target, int length)
1068 {
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);
1081 }
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;
1095 }
1096 }
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);
1106 }
1107 SCTP_IP_PKTLOG_UNLOCK();
1108 return (this_copy + sizeof(int));
1109 }
1111 #endif