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