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