]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/kpi_socketfilter.c
xnu-3247.10.11.tar.gz
[apple/xnu.git] / bsd / kern / kpi_socketfilter.c
CommitLineData
91447636 1/*
39236c6e 2 * Copyright (c) 2003-2013 Apple Inc. All rights reserved.
5d5c5d0d 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
39236c6e 5 *
2d21ac55
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
39236c6e 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
39236c6e 17 *
2d21ac55
A
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
39236c6e 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
91447636
A
27 */
28
29#include <sys/kpi_socketfilter.h>
30
31#include <sys/socket.h>
32#include <sys/param.h>
33#include <sys/errno.h>
34#include <sys/malloc.h>
35#include <sys/protosw.h>
316670eb 36#include <sys/domain.h>
6d2010ae 37#include <sys/proc.h>
91447636 38#include <kern/locks.h>
6d2010ae
A
39#include <kern/thread.h>
40#include <kern/debug.h>
91447636 41#include <net/kext_net.h>
316670eb
A
42#include <net/if.h>
43#include <netinet/in_var.h>
44#include <netinet/ip.h>
45#include <netinet/ip_var.h>
46#include <netinet/tcp.h>
47#include <netinet/tcp_var.h>
48#include <netinet/udp.h>
49#include <netinet/udp_var.h>
91447636 50
c910b4d9 51#include <libkern/libkern.h>
6d2010ae 52#include <libkern/OSAtomic.h>
c910b4d9 53
2d21ac55
A
54#include <string.h>
55
6d2010ae
A
56#define SFEF_ATTACHED 0x1 /* SFE is on socket list */
57#define SFEF_NODETACH 0x2 /* Detach should not be called */
58#define SFEF_NOSOCKET 0x4 /* Socket is gone */
59
60struct socket_filter_entry {
61 struct socket_filter_entry *sfe_next_onsocket;
62 struct socket_filter_entry *sfe_next_onfilter;
63 struct socket_filter_entry *sfe_next_oncleanup;
39236c6e 64
6d2010ae 65 struct socket_filter *sfe_filter;
39236c6e
A
66 struct socket *sfe_socket;
67 void *sfe_cookie;
68
69 uint32_t sfe_flags;
70 int32_t sfe_refcount;
6d2010ae
A
71};
72
73struct socket_filter {
39236c6e 74 TAILQ_ENTRY(socket_filter) sf_protosw_next;
6d2010ae
A
75 TAILQ_ENTRY(socket_filter) sf_global_next;
76 struct socket_filter_entry *sf_entry_head;
39236c6e
A
77
78 struct protosw *sf_proto;
79 struct sflt_filter sf_filter;
80 u_int32_t sf_refcount;
6d2010ae
A
81};
82
83TAILQ_HEAD(socket_filter_list, socket_filter);
84
91447636 85static struct socket_filter_list sock_filter_head;
39236c6e
A
86static lck_rw_t *sock_filter_lock = NULL;
87static lck_mtx_t *sock_filter_cleanup_lock = NULL;
6d2010ae 88static struct socket_filter_entry *sock_filter_cleanup_entries = NULL;
39236c6e 89static thread_t sock_filter_cleanup_thread = NULL;
91447636 90
6d2010ae
A
91static void sflt_cleanup_thread(void *, wait_result_t);
92static void sflt_detach_locked(struct socket_filter_entry *entry);
93
94#pragma mark -- Internal State Management --
3a60a9f5 95
91447636
A
96__private_extern__ void
97sflt_init(void)
98{
39236c6e
A
99 lck_grp_attr_t *grp_attrib = NULL;
100 lck_attr_t *lck_attrib = NULL;
101 lck_grp_t *lck_group = NULL;
102
91447636 103 TAILQ_INIT(&sock_filter_head);
39236c6e 104
6d2010ae 105 /* Allocate a rw lock */
91447636 106 grp_attrib = lck_grp_attr_alloc_init();
91447636
A
107 lck_group = lck_grp_alloc_init("socket filter lock", grp_attrib);
108 lck_grp_attr_free(grp_attrib);
109 lck_attrib = lck_attr_alloc_init();
6d2010ae
A
110 sock_filter_lock = lck_rw_alloc_init(lck_group, lck_attrib);
111 sock_filter_cleanup_lock = lck_mtx_alloc_init(lck_group, lck_attrib);
91447636
A
112 lck_grp_free(lck_group);
113 lck_attr_free(lck_attrib);
114}
115
6d2010ae 116static void
39236c6e 117sflt_retain_locked(struct socket_filter *filter)
91447636 118{
6d2010ae
A
119 filter->sf_refcount++;
120}
121
122static void
39236c6e 123sflt_release_locked(struct socket_filter *filter)
6d2010ae
A
124{
125 filter->sf_refcount--;
39236c6e
A
126 if (filter->sf_refcount == 0) {
127 /* Call the unregistered function */
6d2010ae
A
128 if (filter->sf_filter.sf_unregistered) {
129 lck_rw_unlock_exclusive(sock_filter_lock);
39236c6e
A
130 filter->sf_filter.sf_unregistered(
131 filter->sf_filter.sf_handle);
6d2010ae
A
132 lck_rw_lock_exclusive(sock_filter_lock);
133 }
39236c6e
A
134
135 /* Free the entry */
6d2010ae
A
136 FREE(filter, M_IFADDR);
137 }
138}
139
140static void
39236c6e 141sflt_entry_retain(struct socket_filter_entry *entry)
6d2010ae 142{
39236c6e 143 if (OSIncrementAtomic(&entry->sfe_refcount) <= 0) {
6d2010ae 144 panic("sflt_entry_retain - sfe_refcount <= 0\n");
39236c6e
A
145 /* NOTREACHED */
146 }
6d2010ae
A
147}
148
149static void
39236c6e 150sflt_entry_release(struct socket_filter_entry *entry)
6d2010ae
A
151{
152 SInt32 old = OSDecrementAtomic(&entry->sfe_refcount);
153 if (old == 1) {
39236c6e
A
154 /* That was the last reference */
155
156 /* Take the cleanup lock */
6d2010ae 157 lck_mtx_lock(sock_filter_cleanup_lock);
39236c6e
A
158
159 /* Put this item on the cleanup list */
6d2010ae
A
160 entry->sfe_next_oncleanup = sock_filter_cleanup_entries;
161 sock_filter_cleanup_entries = entry;
39236c6e
A
162
163 /* If the item is the first item in the list */
6d2010ae
A
164 if (entry->sfe_next_oncleanup == NULL) {
165 if (sock_filter_cleanup_thread == NULL) {
39236c6e
A
166 /* Create a thread */
167 kernel_thread_start(sflt_cleanup_thread,
168 NULL, &sock_filter_cleanup_thread);
6d2010ae 169 } else {
39236c6e 170 /* Wakeup the thread */
6d2010ae
A
171 wakeup(&sock_filter_cleanup_entries);
172 }
173 }
39236c6e
A
174
175 /* Drop the cleanup lock */
6d2010ae 176 lck_mtx_unlock(sock_filter_cleanup_lock);
39236c6e
A
177 } else if (old <= 0) {
178 panic("sflt_entry_release - sfe_refcount (%d) <= 0\n",
179 (int)old);
180 /* NOTREACHED */
6d2010ae
A
181 }
182}
183
184static void
39236c6e 185sflt_cleanup_thread(void *blah, wait_result_t blah2)
6d2010ae 186{
39236c6e 187#pragma unused(blah, blah2)
6d2010ae
A
188 while (1) {
189 lck_mtx_lock(sock_filter_cleanup_lock);
190 while (sock_filter_cleanup_entries == NULL) {
39236c6e
A
191 /* Sleep until we've got something better to do */
192 msleep(&sock_filter_cleanup_entries,
193 sock_filter_cleanup_lock, PWAIT,
194 "sflt_cleanup", NULL);
6d2010ae 195 }
39236c6e
A
196
197 /* Pull the current list of dead items */
198 struct socket_filter_entry *dead = sock_filter_cleanup_entries;
6d2010ae 199 sock_filter_cleanup_entries = NULL;
39236c6e
A
200
201 /* Drop the lock */
6d2010ae 202 lck_mtx_unlock(sock_filter_cleanup_lock);
39236c6e
A
203
204 /* Take the socket filter lock */
6d2010ae 205 lck_rw_lock_exclusive(sock_filter_lock);
39236c6e
A
206
207 /* Cleanup every dead item */
6d2010ae
A
208 struct socket_filter_entry *entry;
209 for (entry = dead; entry; entry = dead) {
210 struct socket_filter_entry **nextpp;
39236c6e 211
6d2010ae 212 dead = entry->sfe_next_oncleanup;
39236c6e
A
213
214 /* Call detach function if necessary - drop the lock */
6d2010ae 215 if ((entry->sfe_flags & SFEF_NODETACH) == 0 &&
39236c6e 216 entry->sfe_filter->sf_filter.sf_detach) {
6d2010ae
A
217 entry->sfe_flags |= SFEF_NODETACH;
218 lck_rw_unlock_exclusive(sock_filter_lock);
39236c6e
A
219
220 /*
221 * Warning - passing a potentially
222 * dead socket may be bad
223 */
224 entry->sfe_filter->sf_filter. sf_detach(
225 entry->sfe_cookie, entry->sfe_socket);
226
6d2010ae
A
227 lck_rw_lock_exclusive(sock_filter_lock);
228 }
39236c6e
A
229
230 /*
231 * Pull entry off the socket list --
232 * if the socket still exists
233 */
6d2010ae 234 if ((entry->sfe_flags & SFEF_NOSOCKET) == 0) {
39236c6e
A
235 for (nextpp = &entry->sfe_socket->so_filt;
236 *nextpp;
237 nextpp = &(*nextpp)->sfe_next_onsocket) {
6d2010ae 238 if (*nextpp == entry) {
39236c6e
A
239 *nextpp =
240 entry->sfe_next_onsocket;
6d2010ae
A
241 break;
242 }
243 }
244 }
39236c6e
A
245
246 /* Pull entry off the filter list */
247 for (nextpp = &entry->sfe_filter->sf_entry_head;
248 *nextpp; nextpp = &(*nextpp)->sfe_next_onfilter) {
6d2010ae
A
249 if (*nextpp == entry) {
250 *nextpp = entry->sfe_next_onfilter;
251 break;
252 }
253 }
39236c6e
A
254
255 /*
256 * Release the filter -- may drop lock, but that's okay
257 */
6d2010ae
A
258 sflt_release_locked(entry->sfe_filter);
259 entry->sfe_socket = NULL;
260 entry->sfe_filter = NULL;
261 FREE(entry, M_IFADDR);
262 }
39236c6e
A
263
264 /* Drop the socket filter lock */
6d2010ae
A
265 lck_rw_unlock_exclusive(sock_filter_lock);
266 }
39236c6e 267 /* NOTREACHED */
6d2010ae
A
268}
269
270static int
39236c6e
A
271sflt_attach_locked(struct socket *so, struct socket_filter *filter,
272 int socklocked)
6d2010ae
A
273{
274 int error = 0;
275 struct socket_filter_entry *entry = NULL;
39236c6e 276
6d2010ae 277 if (filter == NULL)
39236c6e 278 return (ENOENT);
316670eb 279
39236c6e 280 for (entry = so->so_filt; entry; entry = entry->sfe_next_onfilter) {
316670eb
A
281 if (entry->sfe_filter->sf_filter.sf_handle ==
282 filter->sf_filter.sf_handle)
39236c6e
A
283 return (EEXIST);
284 }
316670eb 285 /* allocate the socket filter entry */
39236c6e 286 MALLOC(entry, struct socket_filter_entry *, sizeof (*entry), M_IFADDR,
316670eb
A
287 M_WAITOK);
288 if (entry == NULL)
39236c6e
A
289 return (ENOMEM);
290
316670eb
A
291 /* Initialize the socket filter entry */
292 entry->sfe_cookie = NULL;
293 entry->sfe_flags = SFEF_ATTACHED;
39236c6e
A
294 entry->sfe_refcount = 1; /* corresponds to SFEF_ATTACHED flag set */
295
316670eb
A
296 /* Put the entry in the filter list */
297 sflt_retain_locked(filter);
298 entry->sfe_filter = filter;
299 entry->sfe_next_onfilter = filter->sf_entry_head;
300 filter->sf_entry_head = entry;
39236c6e 301
316670eb
A
302 /* Put the entry on the socket filter list */
303 entry->sfe_socket = so;
304 entry->sfe_next_onsocket = so->so_filt;
305 so->so_filt = entry;
306
307 if (entry->sfe_filter->sf_filter.sf_attach) {
39236c6e 308 /* Retain the entry while we call attach */
316670eb 309 sflt_entry_retain(entry);
39236c6e
A
310
311 /*
312 * Release the filter lock --
313 * callers must be aware we will do this
314 */
316670eb 315 lck_rw_unlock_exclusive(sock_filter_lock);
39236c6e
A
316
317 /* Unlock the socket */
316670eb
A
318 if (socklocked)
319 socket_unlock(so, 0);
39236c6e
A
320
321 /* It's finally safe to call the filter function */
322 error = entry->sfe_filter->sf_filter.sf_attach(
323 &entry->sfe_cookie, so);
324
325 /* Lock the socket again */
316670eb
A
326 if (socklocked)
327 socket_lock(so, 0);
39236c6e
A
328
329 /* Lock the filters again */
316670eb 330 lck_rw_lock_exclusive(sock_filter_lock);
39236c6e
A
331
332 /*
333 * If the attach function returns an error,
334 * this filter must be detached
335 */
316670eb 336 if (error) {
39236c6e
A
337 /* don't call sf_detach */
338 entry->sfe_flags |= SFEF_NODETACH;
316670eb 339 sflt_detach_locked(entry);
91447636 340 }
39236c6e
A
341
342 /* Release the retain we held through the attach call */
316670eb 343 sflt_entry_release(entry);
91447636 344 }
39236c6e
A
345
346 return (error);
91447636
A
347}
348
6d2010ae 349errno_t
39236c6e 350sflt_attach_internal(socket_t socket, sflt_handle handle)
91447636 351{
6d2010ae 352 if (socket == NULL || handle == 0)
39236c6e
A
353 return (EINVAL);
354
6d2010ae 355 int result = EINVAL;
39236c6e 356
6d2010ae 357 lck_rw_lock_exclusive(sock_filter_lock);
39236c6e 358
6d2010ae
A
359 struct socket_filter *filter = NULL;
360 TAILQ_FOREACH(filter, &sock_filter_head, sf_global_next) {
361 if (filter->sf_filter.sf_handle == handle) break;
362 }
39236c6e 363
6d2010ae
A
364 if (filter) {
365 result = sflt_attach_locked(socket, filter, 1);
91447636 366 }
39236c6e 367
6d2010ae 368 lck_rw_unlock_exclusive(sock_filter_lock);
39236c6e
A
369
370 return (result);
91447636
A
371}
372
6d2010ae 373static void
39236c6e 374sflt_detach_locked(struct socket_filter_entry *entry)
6d2010ae
A
375{
376 if ((entry->sfe_flags & SFEF_ATTACHED) != 0) {
377 entry->sfe_flags &= ~SFEF_ATTACHED;
378 sflt_entry_release(entry);
379 }
380}
381
382#pragma mark -- Socket Layer Hooks --
383
91447636 384__private_extern__ void
39236c6e 385sflt_initsock(struct socket *so)
91447636 386{
39236c6e
A
387 /*
388 * Point to the real protosw, as so_proto might have been
389 * pointed to a modified version.
390 */
391 struct protosw *proto = so->so_proto->pr_protosw;
392
6d2010ae
A
393 lck_rw_lock_shared(sock_filter_lock);
394 if (TAILQ_FIRST(&proto->pr_filter_head) != NULL) {
39236c6e 395 /* Promote lock to exclusive */
6d2010ae
A
396 if (!lck_rw_lock_shared_to_exclusive(sock_filter_lock))
397 lck_rw_lock_exclusive(sock_filter_lock);
39236c6e
A
398
399 /*
400 * Warning: A filter unregistering will be pulled out of
401 * the list. This could happen while we drop the lock in
402 * sftl_attach_locked or sflt_release_locked. For this
403 * reason we retain a reference on the filter (or next_filter)
404 * while calling this function. This protects us from a panic,
405 * but it could result in a socket being created without all
406 * of the global filters if we're attaching a filter as it
407 * is removed, if that's possible.
408 */
409 struct socket_filter *filter =
410 TAILQ_FIRST(&proto->pr_filter_head);
411
6d2010ae 412 sflt_retain_locked(filter);
39236c6e
A
413
414 while (filter) {
6d2010ae 415 struct socket_filter *filter_next;
39236c6e
A
416 /*
417 * Warning: sflt_attach_private_locked
418 * will drop the lock
419 */
6d2010ae 420 sflt_attach_locked(so, filter, 0);
39236c6e 421
6d2010ae
A
422 filter_next = TAILQ_NEXT(filter, sf_protosw_next);
423 if (filter_next)
424 sflt_retain_locked(filter_next);
39236c6e
A
425
426 /*
427 * Warning: filt_release_locked may remove
428 * the filter from the queue
429 */
6d2010ae
A
430 sflt_release_locked(filter);
431 filter = filter_next;
432 }
433 }
434 lck_rw_done(sock_filter_lock);
91447636
A
435}
436
6d2010ae
A
437/*
438 * sflt_termsock
439 *
440 * Detaches all filters from the socket.
441 */
91447636 442__private_extern__ void
39236c6e 443sflt_termsock(struct socket *so)
91447636 444{
6d2010ae 445 lck_rw_lock_exclusive(sock_filter_lock);
39236c6e 446
6d2010ae 447 struct socket_filter_entry *entry;
39236c6e 448
6d2010ae 449 while ((entry = so->so_filt) != NULL) {
39236c6e 450 /* Pull filter off the socket */
6d2010ae
A
451 so->so_filt = entry->sfe_next_onsocket;
452 entry->sfe_flags |= SFEF_NOSOCKET;
39236c6e
A
453
454 /* Call detach */
6d2010ae 455 sflt_detach_locked(entry);
39236c6e
A
456
457 /*
458 * On sflt_termsock, we can't return until the detach function
459 * has been called. Call the detach function - this is gross
460 * because the socket filter entry could be freed when we drop
461 * the lock, so we make copies on the stack and retain
462 * everything we need before dropping the lock.
463 */
6d2010ae 464 if ((entry->sfe_flags & SFEF_NODETACH) == 0 &&
39236c6e
A
465 entry->sfe_filter->sf_filter.sf_detach) {
466 void *sfe_cookie = entry->sfe_cookie;
467 struct socket_filter *sfe_filter = entry->sfe_filter;
468
469 /* Retain the socket filter */
6d2010ae 470 sflt_retain_locked(sfe_filter);
39236c6e
A
471
472 /* Mark that we've called the detach function */
6d2010ae 473 entry->sfe_flags |= SFEF_NODETACH;
39236c6e
A
474
475 /* Drop the lock before calling the detach function */
6d2010ae
A
476 lck_rw_unlock_exclusive(sock_filter_lock);
477 sfe_filter->sf_filter.sf_detach(sfe_cookie, so);
478 lck_rw_lock_exclusive(sock_filter_lock);
39236c6e
A
479
480 /* Release the filter */
6d2010ae 481 sflt_release_locked(sfe_filter);
91447636
A
482 }
483 }
39236c6e 484
6d2010ae 485 lck_rw_unlock_exclusive(sock_filter_lock);
91447636
A
486}
487
316670eb
A
488
489static void
39236c6e
A
490sflt_notify_internal(struct socket *so, sflt_event_t event, void *param,
491 sflt_handle handle)
91447636 492{
39236c6e
A
493 if (so->so_filt == NULL)
494 return;
495
496 struct socket_filter_entry *entry;
497 int unlocked = 0;
498
6d2010ae
A
499 lck_rw_lock_shared(sock_filter_lock);
500 for (entry = so->so_filt; entry; entry = entry->sfe_next_onsocket) {
39236c6e
A
501 if ((entry->sfe_flags & SFEF_ATTACHED) &&
502 entry->sfe_filter->sf_filter.sf_notify &&
503 ((handle && entry->sfe_filter->sf_filter.sf_handle !=
504 handle) || !handle)) {
505 /*
506 * Retain the filter entry and release
507 * the socket filter lock
508 */
6d2010ae
A
509 sflt_entry_retain(entry);
510 lck_rw_unlock_shared(sock_filter_lock);
39236c6e
A
511
512 /* If the socket isn't already unlocked, unlock it */
6d2010ae
A
513 if (unlocked == 0) {
514 unlocked = 1;
91447636
A
515 socket_unlock(so, 0);
516 }
39236c6e
A
517
518 /* Finally call the filter */
519 entry->sfe_filter->sf_filter.sf_notify(
520 entry->sfe_cookie, so, event, param);
521
522 /*
523 * Take the socket filter lock again
524 * and release the entry
525 */
6d2010ae
A
526 lck_rw_lock_shared(sock_filter_lock);
527 sflt_entry_release(entry);
91447636
A
528 }
529 }
6d2010ae 530 lck_rw_unlock_shared(sock_filter_lock);
39236c6e 531
6d2010ae 532 if (unlocked != 0) {
91447636 533 socket_lock(so, 0);
91447636
A
534 }
535}
536
316670eb 537__private_extern__ void
39236c6e 538sflt_notify(struct socket *so, sflt_event_t event, void *param)
316670eb
A
539{
540 sflt_notify_internal(so, event, param, 0);
541}
542
543static void
39236c6e
A
544sflt_notify_after_register(struct socket *so, sflt_event_t event,
545 sflt_handle handle)
316670eb
A
546{
547 sflt_notify_internal(so, event, NULL, handle);
548}
549
91447636 550__private_extern__ int
39236c6e 551sflt_ioctl(struct socket *so, u_long cmd, caddr_t data)
91447636 552{
39236c6e
A
553 if (so->so_filt == NULL)
554 return (0);
555
556 struct socket_filter_entry *entry;
557 int unlocked = 0;
558 int error = 0;
559
6d2010ae
A
560 lck_rw_lock_shared(sock_filter_lock);
561 for (entry = so->so_filt; entry && error == 0;
39236c6e
A
562 entry = entry->sfe_next_onsocket) {
563 if ((entry->sfe_flags & SFEF_ATTACHED) &&
564 entry->sfe_filter->sf_filter.sf_ioctl) {
565 /*
566 * Retain the filter entry and release
567 * the socket filter lock
568 */
6d2010ae
A
569 sflt_entry_retain(entry);
570 lck_rw_unlock_shared(sock_filter_lock);
39236c6e
A
571
572 /* If the socket isn't already unlocked, unlock it */
6d2010ae 573 if (unlocked == 0) {
91447636 574 socket_unlock(so, 0);
6d2010ae 575 unlocked = 1;
91447636 576 }
39236c6e
A
577
578 /* Call the filter */
579 error = entry->sfe_filter->sf_filter.sf_ioctl(
580 entry->sfe_cookie, so, cmd, data);
581
582 /*
583 * Take the socket filter lock again
584 * and release the entry
585 */
6d2010ae
A
586 lck_rw_lock_shared(sock_filter_lock);
587 sflt_entry_release(entry);
91447636
A
588 }
589 }
6d2010ae
A
590 lck_rw_unlock_shared(sock_filter_lock);
591
592 if (unlocked) {
91447636 593 socket_lock(so, 0);
91447636 594 }
39236c6e
A
595
596 return (error);
91447636
A
597}
598
91447636 599__private_extern__ int
39236c6e 600sflt_bind(struct socket *so, const struct sockaddr *nam)
91447636 601{
39236c6e
A
602 if (so->so_filt == NULL)
603 return (0);
604
605 struct socket_filter_entry *entry;
606 int unlocked = 0;
607 int error = 0;
608
6d2010ae
A
609 lck_rw_lock_shared(sock_filter_lock);
610 for (entry = so->so_filt; entry && error == 0;
39236c6e
A
611 entry = entry->sfe_next_onsocket) {
612 if ((entry->sfe_flags & SFEF_ATTACHED) &&
613 entry->sfe_filter->sf_filter.sf_bind) {
614 /*
615 * Retain the filter entry and
616 * release the socket filter lock
617 */
6d2010ae
A
618 sflt_entry_retain(entry);
619 lck_rw_unlock_shared(sock_filter_lock);
39236c6e
A
620
621 /* If the socket isn't already unlocked, unlock it */
6d2010ae
A
622 if (unlocked == 0) {
623 socket_unlock(so, 0);
624 unlocked = 1;
625 }
39236c6e
A
626
627 /* Call the filter */
628 error = entry->sfe_filter->sf_filter.sf_bind(
629 entry->sfe_cookie, so, nam);
630
631 /*
632 * Take the socket filter lock again and
633 * release the entry
634 */
6d2010ae
A
635 lck_rw_lock_shared(sock_filter_lock);
636 sflt_entry_release(entry);
91447636
A
637 }
638 }
6d2010ae
A
639 lck_rw_unlock_shared(sock_filter_lock);
640
641 if (unlocked) {
642 socket_lock(so, 0);
643 }
39236c6e
A
644
645 return (error);
6d2010ae
A
646}
647
648__private_extern__ int
39236c6e 649sflt_listen(struct socket *so)
6d2010ae 650{
39236c6e
A
651 if (so->so_filt == NULL)
652 return (0);
653
654 struct socket_filter_entry *entry;
655 int unlocked = 0;
656 int error = 0;
657
6d2010ae
A
658 lck_rw_lock_shared(sock_filter_lock);
659 for (entry = so->so_filt; entry && error == 0;
39236c6e
A
660 entry = entry->sfe_next_onsocket) {
661 if ((entry->sfe_flags & SFEF_ATTACHED) &&
662 entry->sfe_filter->sf_filter.sf_listen) {
663 /*
664 * Retain the filter entry and release
665 * the socket filter lock
666 */
6d2010ae
A
667 sflt_entry_retain(entry);
668 lck_rw_unlock_shared(sock_filter_lock);
39236c6e
A
669
670 /* If the socket isn't already unlocked, unlock it */
6d2010ae
A
671 if (unlocked == 0) {
672 socket_unlock(so, 0);
673 unlocked = 1;
674 }
39236c6e
A
675
676 /* Call the filter */
677 error = entry->sfe_filter->sf_filter.sf_listen(
678 entry->sfe_cookie, so);
679
680 /*
681 * Take the socket filter lock again
682 * and release the entry
683 */
6d2010ae
A
684 lck_rw_lock_shared(sock_filter_lock);
685 sflt_entry_release(entry);
91447636
A
686 }
687 }
6d2010ae
A
688 lck_rw_unlock_shared(sock_filter_lock);
689
690 if (unlocked) {
691 socket_lock(so, 0);
692 }
39236c6e
A
693
694 return (error);
6d2010ae
A
695}
696
697__private_extern__ int
39236c6e
A
698sflt_accept(struct socket *head, struct socket *so,
699 const struct sockaddr *local, const struct sockaddr *remote)
6d2010ae 700{
39236c6e
A
701 if (so->so_filt == NULL)
702 return (0);
703
704 struct socket_filter_entry *entry;
705 int unlocked = 0;
706 int error = 0;
707
6d2010ae
A
708 lck_rw_lock_shared(sock_filter_lock);
709 for (entry = so->so_filt; entry && error == 0;
39236c6e
A
710 entry = entry->sfe_next_onsocket) {
711 if ((entry->sfe_flags & SFEF_ATTACHED) &&
712 entry->sfe_filter->sf_filter.sf_accept) {
713 /*
714 * Retain the filter entry and
715 * release the socket filter lock
716 */
6d2010ae
A
717 sflt_entry_retain(entry);
718 lck_rw_unlock_shared(sock_filter_lock);
39236c6e
A
719
720 /* If the socket isn't already unlocked, unlock it */
6d2010ae
A
721 if (unlocked == 0) {
722 socket_unlock(so, 0);
723 unlocked = 1;
91447636 724 }
39236c6e
A
725
726 /* Call the filter */
727 error = entry->sfe_filter->sf_filter.sf_accept(
728 entry->sfe_cookie, head, so, local, remote);
729
730 /*
731 * Take the socket filter lock again
732 * and release the entry
733 */
6d2010ae
A
734 lck_rw_lock_shared(sock_filter_lock);
735 sflt_entry_release(entry);
91447636
A
736 }
737 }
6d2010ae
A
738 lck_rw_unlock_shared(sock_filter_lock);
739
740 if (unlocked) {
741 socket_lock(so, 0);
91447636 742 }
39236c6e
A
743
744 return (error);
6d2010ae
A
745}
746
747__private_extern__ int
39236c6e 748sflt_getsockname(struct socket *so, struct sockaddr **local)
6d2010ae 749{
39236c6e
A
750 if (so->so_filt == NULL)
751 return (0);
752
753 struct socket_filter_entry *entry;
754 int unlocked = 0;
755 int error = 0;
756
6d2010ae
A
757 lck_rw_lock_shared(sock_filter_lock);
758 for (entry = so->so_filt; entry && error == 0;
39236c6e
A
759 entry = entry->sfe_next_onsocket) {
760 if ((entry->sfe_flags & SFEF_ATTACHED) &&
761 entry->sfe_filter->sf_filter.sf_getsockname) {
762 /*
763 * Retain the filter entry and
764 * release the socket filter lock
765 */
6d2010ae
A
766 sflt_entry_retain(entry);
767 lck_rw_unlock_shared(sock_filter_lock);
39236c6e
A
768
769 /* If the socket isn't already unlocked, unlock it */
6d2010ae
A
770 if (unlocked == 0) {
771 socket_unlock(so, 0);
772 unlocked = 1;
773 }
39236c6e
A
774
775 /* Call the filter */
776 error = entry->sfe_filter->sf_filter.sf_getsockname(
777 entry->sfe_cookie, so, local);
778
779 /*
780 * Take the socket filter lock again
781 * and release the entry
782 */
6d2010ae
A
783 lck_rw_lock_shared(sock_filter_lock);
784 sflt_entry_release(entry);
785 }
786 }
787 lck_rw_unlock_shared(sock_filter_lock);
788
789 if (unlocked) {
790 socket_lock(so, 0);
91447636 791 }
39236c6e
A
792
793 return (error);
91447636
A
794}
795
6d2010ae 796__private_extern__ int
39236c6e 797sflt_getpeername(struct socket *so, struct sockaddr **remote)
6d2010ae 798{
39236c6e
A
799 if (so->so_filt == NULL)
800 return (0);
801
802 struct socket_filter_entry *entry;
803 int unlocked = 0;
804 int error = 0;
805
6d2010ae
A
806 lck_rw_lock_shared(sock_filter_lock);
807 for (entry = so->so_filt; entry && error == 0;
39236c6e
A
808 entry = entry->sfe_next_onsocket) {
809 if ((entry->sfe_flags & SFEF_ATTACHED) &&
810 entry->sfe_filter->sf_filter.sf_getpeername) {
811 /*
812 * Retain the filter entry and release
813 * the socket filter lock
814 */
6d2010ae
A
815 sflt_entry_retain(entry);
816 lck_rw_unlock_shared(sock_filter_lock);
39236c6e
A
817
818 /* If the socket isn't already unlocked, unlock it */
6d2010ae
A
819 if (unlocked == 0) {
820 socket_unlock(so, 0);
821 unlocked = 1;
822 }
39236c6e
A
823
824 /* Call the filter */
825 error = entry->sfe_filter->sf_filter.sf_getpeername(
826 entry->sfe_cookie, so, remote);
827
828 /*
829 * Take the socket filter lock again
830 * and release the entry
831 */
6d2010ae
A
832 lck_rw_lock_shared(sock_filter_lock);
833 sflt_entry_release(entry);
834 }
835 }
836 lck_rw_unlock_shared(sock_filter_lock);
91447636 837
6d2010ae
A
838 if (unlocked) {
839 socket_lock(so, 0);
840 }
39236c6e
A
841
842 return (error);
6d2010ae 843}
91447636 844
6d2010ae 845__private_extern__ int
39236c6e 846sflt_connectin(struct socket *so, const struct sockaddr *remote)
91447636 847{
39236c6e
A
848 if (so->so_filt == NULL)
849 return (0);
850
851 struct socket_filter_entry *entry;
852 int unlocked = 0;
853 int error = 0;
854
6d2010ae
A
855 lck_rw_lock_shared(sock_filter_lock);
856 for (entry = so->so_filt; entry && error == 0;
39236c6e
A
857 entry = entry->sfe_next_onsocket) {
858 if ((entry->sfe_flags & SFEF_ATTACHED) &&
859 entry->sfe_filter->sf_filter.sf_connect_in) {
860 /*
861 * Retain the filter entry and release
862 * the socket filter lock
863 */
6d2010ae
A
864 sflt_entry_retain(entry);
865 lck_rw_unlock_shared(sock_filter_lock);
39236c6e
A
866
867 /* If the socket isn't already unlocked, unlock it */
6d2010ae
A
868 if (unlocked == 0) {
869 socket_unlock(so, 0);
870 unlocked = 1;
4a3eedf9 871 }
39236c6e
A
872
873 /* Call the filter */
874 error = entry->sfe_filter->sf_filter.sf_connect_in(
875 entry->sfe_cookie, so, remote);
876
877 /*
878 * Take the socket filter lock again
879 * and release the entry
880 */
6d2010ae
A
881 lck_rw_lock_shared(sock_filter_lock);
882 sflt_entry_release(entry);
3a60a9f5 883 }
6d2010ae
A
884 }
885 lck_rw_unlock_shared(sock_filter_lock);
886
887 if (unlocked) {
888 socket_lock(so, 0);
889 }
39236c6e
A
890
891 return (error);
6d2010ae
A
892}
893
894__private_extern__ int
39236c6e 895sflt_connectout(struct socket *so, const struct sockaddr *nam)
6d2010ae 896{
39236c6e
A
897 if (so->so_filt == NULL)
898 return (0);
899
900 struct socket_filter_entry *entry;
901 int unlocked = 0;
902 int error = 0;
903
6d2010ae
A
904 lck_rw_lock_shared(sock_filter_lock);
905 for (entry = so->so_filt; entry && error == 0;
39236c6e
A
906 entry = entry->sfe_next_onsocket) {
907 if ((entry->sfe_flags & SFEF_ATTACHED) &&
908 entry->sfe_filter->sf_filter.sf_connect_out) {
909 /*
910 * Retain the filter entry and release
911 * the socket filter lock
912 */
6d2010ae
A
913 sflt_entry_retain(entry);
914 lck_rw_unlock_shared(sock_filter_lock);
39236c6e
A
915
916 /* If the socket isn't already unlocked, unlock it */
6d2010ae
A
917 if (unlocked == 0) {
918 socket_unlock(so, 0);
919 unlocked = 1;
91447636 920 }
39236c6e
A
921
922 /* Call the filter */
923 error = entry->sfe_filter->sf_filter.sf_connect_out(
924 entry->sfe_cookie, so, nam);
925
926 /*
927 * Take the socket filter lock again
928 * and release the entry
929 */
6d2010ae
A
930 lck_rw_lock_shared(sock_filter_lock);
931 sflt_entry_release(entry);
91447636 932 }
91447636 933 }
6d2010ae
A
934 lck_rw_unlock_shared(sock_filter_lock);
935
936 if (unlocked) {
937 socket_lock(so, 0);
938 }
39236c6e
A
939
940 return (error);
941}
942
943__private_extern__ int
944sflt_connectxout(struct socket *so, struct sockaddr_list **dst_sl0)
945{
946 char buf[SOCK_MAXADDRLEN];
947 struct sockaddr_list *dst_sl;
948 struct sockaddr_entry *se, *tse;
949 int modified = 0;
950 int error = 0;
951
952 if (so->so_filt == NULL)
953 return (0);
954
955 /* make a copy as sflt_connectout() releases socket lock */
956 dst_sl = sockaddrlist_dup(*dst_sl0, M_WAITOK);
957 if (dst_sl == NULL)
958 return (ENOBUFS);
959
960 /*
961 * Hmm; we don't yet have a connectx socket filter callback,
962 * so the closest thing to do is to probably call sflt_connectout()
963 * as many times as there are addresses in the list, and bail
964 * as soon as we get an error.
965 */
966 TAILQ_FOREACH_SAFE(se, &dst_sl->sl_head, se_link, tse) {
967 int sa_len = se->se_addr->sa_len;
968
969 /* remember the original address */
970 bzero(buf, sizeof (buf));
971 bcopy(se->se_addr, buf, sa_len);
972
973 VERIFY(se->se_addr != NULL);
974 error = sflt_connectout(so, se->se_addr);
975 if (error != 0)
976 break;
977
978 /* see if the address was modified */
979 if (bcmp(se->se_addr, buf, sa_len) != 0)
980 modified = 1;
981 }
982
983 if (error != 0 || !modified) {
984 /* leave the original as is */
985 sockaddrlist_free(dst_sl);
986 } else {
987 /*
988 * At least one address was modified and there were no errors;
989 * ditch the original and return the modified list.
990 */
991 sockaddrlist_free(*dst_sl0);
992 *dst_sl0 = dst_sl;
993 }
994
995 return (error);
6d2010ae 996}
91447636 997
6d2010ae 998__private_extern__ int
39236c6e 999sflt_setsockopt(struct socket *so, struct sockopt *sopt)
6d2010ae 1000{
39236c6e
A
1001 if (so->so_filt == NULL)
1002 return (0);
1003
1004 struct socket_filter_entry *entry;
1005 int unlocked = 0;
1006 int error = 0;
1007
6d2010ae
A
1008 lck_rw_lock_shared(sock_filter_lock);
1009 for (entry = so->so_filt; entry && error == 0;
39236c6e
A
1010 entry = entry->sfe_next_onsocket) {
1011 if ((entry->sfe_flags & SFEF_ATTACHED) &&
1012 entry->sfe_filter->sf_filter.sf_setoption) {
1013 /*
1014 * Retain the filter entry and release
1015 * the socket filter lock
1016 */
6d2010ae
A
1017 sflt_entry_retain(entry);
1018 lck_rw_unlock_shared(sock_filter_lock);
39236c6e
A
1019
1020 /* If the socket isn't already unlocked, unlock it */
6d2010ae
A
1021 if (unlocked == 0) {
1022 socket_unlock(so, 0);
1023 unlocked = 1;
1024 }
39236c6e
A
1025
1026 /* Call the filter */
1027 error = entry->sfe_filter->sf_filter.sf_setoption(
1028 entry->sfe_cookie, so, sopt);
1029
1030 /*
1031 * Take the socket filter lock again
1032 * and release the entry
1033 */
6d2010ae
A
1034 lck_rw_lock_shared(sock_filter_lock);
1035 sflt_entry_release(entry);
c910b4d9 1036 }
6d2010ae
A
1037 }
1038 lck_rw_unlock_shared(sock_filter_lock);
1039
1040 if (unlocked) {
1041 socket_lock(so, 0);
1042 }
39236c6e
A
1043
1044 return (error);
6d2010ae
A
1045}
1046
1047__private_extern__ int
39236c6e 1048sflt_getsockopt(struct socket *so, struct sockopt *sopt)
6d2010ae 1049{
39236c6e
A
1050 if (so->so_filt == NULL)
1051 return (0);
1052
1053 struct socket_filter_entry *entry;
1054 int unlocked = 0;
1055 int error = 0;
1056
6d2010ae
A
1057 lck_rw_lock_shared(sock_filter_lock);
1058 for (entry = so->so_filt; entry && error == 0;
39236c6e
A
1059 entry = entry->sfe_next_onsocket) {
1060 if ((entry->sfe_flags & SFEF_ATTACHED) &&
1061 entry->sfe_filter->sf_filter.sf_getoption) {
1062 /*
1063 * Retain the filter entry and release
1064 * the socket filter lock
1065 */
6d2010ae
A
1066 sflt_entry_retain(entry);
1067 lck_rw_unlock_shared(sock_filter_lock);
39236c6e
A
1068
1069 /* If the socket isn't already unlocked, unlock it */
6d2010ae
A
1070 if (unlocked == 0) {
1071 socket_unlock(so, 0);
1072 unlocked = 1;
1073 }
39236c6e
A
1074
1075 /* Call the filter */
1076 error = entry->sfe_filter->sf_filter.sf_getoption(
1077 entry->sfe_cookie, so, sopt);
1078
1079 /*
1080 * Take the socket filter lock again
1081 * and release the entry
1082 */
6d2010ae
A
1083 lck_rw_lock_shared(sock_filter_lock);
1084 sflt_entry_release(entry);
91447636
A
1085 }
1086 }
6d2010ae
A
1087 lck_rw_unlock_shared(sock_filter_lock);
1088
1089 if (unlocked) {
1090 socket_lock(so, 0);
1091 }
39236c6e
A
1092
1093 return (error);
6d2010ae
A
1094}
1095
1096__private_extern__ int
39236c6e
A
1097sflt_data_out(struct socket *so, const struct sockaddr *to, mbuf_t *data,
1098 mbuf_t *control, sflt_data_flag_t flags)
6d2010ae 1099{
39236c6e
A
1100 if (so->so_filt == NULL)
1101 return (0);
1102
1103 struct socket_filter_entry *entry;
1104 int unlocked = 0;
1105 int setsendthread = 0;
1106 int error = 0;
1107
6d2010ae
A
1108 lck_rw_lock_shared(sock_filter_lock);
1109 for (entry = so->so_filt; entry && error == 0;
39236c6e
A
1110 entry = entry->sfe_next_onsocket) {
1111 /* skip if this is a subflow socket */
1112 if (so->so_flags & SOF_MP_SUBFLOW)
1113 continue;
1114 if ((entry->sfe_flags & SFEF_ATTACHED) &&
1115 entry->sfe_filter->sf_filter.sf_data_out) {
1116 /*
1117 * Retain the filter entry and
1118 * release the socket filter lock
1119 */
6d2010ae
A
1120 sflt_entry_retain(entry);
1121 lck_rw_unlock_shared(sock_filter_lock);
39236c6e
A
1122
1123 /* If the socket isn't already unlocked, unlock it */
6d2010ae
A
1124 if (unlocked == 0) {
1125 if (so->so_send_filt_thread == NULL) {
1126 setsendthread = 1;
39236c6e
A
1127 so->so_send_filt_thread =
1128 current_thread();
6d2010ae
A
1129 }
1130 socket_unlock(so, 0);
1131 unlocked = 1;
1132 }
39236c6e
A
1133
1134 /* Call the filter */
1135 error = entry->sfe_filter->sf_filter.sf_data_out(
1136 entry->sfe_cookie, so, to, data, control, flags);
1137
1138 /*
1139 * Take the socket filter lock again
1140 * and release the entry
1141 */
6d2010ae
A
1142 lck_rw_lock_shared(sock_filter_lock);
1143 sflt_entry_release(entry);
1144 }
91447636 1145 }
6d2010ae 1146 lck_rw_unlock_shared(sock_filter_lock);
3a60a9f5 1147
6d2010ae
A
1148 if (unlocked) {
1149 socket_lock(so, 0);
39236c6e
A
1150 if (setsendthread)
1151 so->so_send_filt_thread = NULL;
6d2010ae 1152 }
39236c6e
A
1153
1154 return (error);
6d2010ae 1155}
3a60a9f5 1156
6d2010ae 1157__private_extern__ int
39236c6e
A
1158sflt_data_in(struct socket *so, const struct sockaddr *from, mbuf_t *data,
1159 mbuf_t *control, sflt_data_flag_t flags)
6d2010ae 1160{
39236c6e
A
1161 if (so->so_filt == NULL)
1162 return (0);
1163
1164 struct socket_filter_entry *entry;
1165 int error = 0;
1166 int unlocked = 0;
1167
6d2010ae 1168 lck_rw_lock_shared(sock_filter_lock);
39236c6e 1169
6d2010ae 1170 for (entry = so->so_filt; entry && (error == 0);
39236c6e
A
1171 entry = entry->sfe_next_onsocket) {
1172 /* skip if this is a subflow socket */
1173 if (so->so_flags & SOF_MP_SUBFLOW)
1174 continue;
6d2010ae 1175 if ((entry->sfe_flags & SFEF_ATTACHED) &&
39236c6e
A
1176 entry->sfe_filter->sf_filter.sf_data_in) {
1177 /*
1178 * Retain the filter entry and
1179 * release the socket filter lock
1180 */
6d2010ae
A
1181 sflt_entry_retain(entry);
1182 lck_rw_unlock_shared(sock_filter_lock);
39236c6e
A
1183
1184 /* If the socket isn't already unlocked, unlock it */
6d2010ae
A
1185 if (unlocked == 0) {
1186 unlocked = 1;
1187 socket_unlock(so, 0);
1188 }
39236c6e
A
1189
1190 /* Call the filter */
6d2010ae 1191 error = entry->sfe_filter->sf_filter.sf_data_in(
39236c6e
A
1192 entry->sfe_cookie, so, from, data, control, flags);
1193
1194 /*
1195 * Take the socket filter lock again
1196 * and release the entry
1197 */
6d2010ae
A
1198 lck_rw_lock_shared(sock_filter_lock);
1199 sflt_entry_release(entry);
1200 }
1201 }
1202 lck_rw_unlock_shared(sock_filter_lock);
39236c6e 1203
6d2010ae
A
1204 if (unlocked) {
1205 socket_lock(so, 0);
1206 }
39236c6e
A
1207
1208 return (error);
91447636
A
1209}
1210
6d2010ae
A
1211#pragma mark -- KPI --
1212
91447636 1213errno_t
39236c6e 1214sflt_attach(socket_t socket, sflt_handle handle)
91447636 1215{
6d2010ae
A
1216 socket_lock(socket, 1);
1217 errno_t result = sflt_attach_internal(socket, handle);
1218 socket_unlock(socket, 1);
39236c6e 1219 return (result);
91447636
A
1220}
1221
1222errno_t
39236c6e 1223sflt_detach(socket_t socket, sflt_handle handle)
91447636 1224{
39236c6e 1225 struct socket_filter_entry *entry;
91447636 1226 errno_t result = 0;
39236c6e 1227
91447636 1228 if (socket == NULL || handle == 0)
39236c6e
A
1229 return (EINVAL);
1230
6d2010ae 1231 lck_rw_lock_exclusive(sock_filter_lock);
39236c6e 1232 for (entry = socket->so_filt; entry; entry = entry->sfe_next_onsocket) {
6d2010ae 1233 if (entry->sfe_filter->sf_filter.sf_handle == handle &&
39236c6e 1234 (entry->sfe_flags & SFEF_ATTACHED) != 0) {
91447636 1235 break;
6d2010ae 1236 }
91447636 1237 }
39236c6e 1238
6d2010ae
A
1239 if (entry != NULL) {
1240 sflt_detach_locked(entry);
91447636 1241 }
6d2010ae 1242 lck_rw_unlock_exclusive(sock_filter_lock);
39236c6e
A
1243
1244 return (result);
91447636
A
1245}
1246
316670eb
A
1247struct solist {
1248 struct solist *next;
1249 struct socket *so;
1250};
1251
91447636 1252errno_t
39236c6e
A
1253sflt_register(const struct sflt_filter *filter, int domain, int type,
1254 int protocol)
91447636
A
1255{
1256 struct socket_filter *sock_filt = NULL;
1257 struct socket_filter *match = NULL;
1258 int error = 0;
3e170ce0 1259 struct protosw *pr;
2d21ac55 1260 unsigned int len;
316670eb
A
1261 struct socket *so;
1262 struct inpcb *inp;
1263 struct solist *solisthead = NULL, *solist = NULL;
2d21ac55 1264
3e170ce0
A
1265 if ((domain != PF_INET) && (domain != PF_INET6))
1266 return (ENOTSUP);
1267
1268 pr = pffindproto(domain, protocol, type);
2d21ac55 1269 if (pr == NULL)
39236c6e 1270 return (ENOENT);
2d21ac55
A
1271
1272 if (filter->sf_attach == NULL || filter->sf_detach == NULL ||
1273 filter->sf_handle == 0 || filter->sf_name == NULL)
39236c6e 1274 return (EINVAL);
91447636
A
1275
1276 /* Allocate the socket filter */
2d21ac55
A
1277 MALLOC(sock_filt, struct socket_filter *, sizeof (*sock_filt),
1278 M_IFADDR, M_WAITOK);
91447636 1279 if (sock_filt == NULL) {
39236c6e 1280 return (ENOBUFS);
91447636 1281 }
2d21ac55
A
1282
1283 bzero(sock_filt, sizeof (*sock_filt));
1284
1285 /* Legacy sflt_filter length; current structure minus extended */
1286 len = sizeof (*filter) - sizeof (struct sflt_filter_ext);
1287 /*
1288 * Include extended fields if filter defines SFLT_EXTENDED.
1289 * We've zeroed out our internal sflt_filter placeholder,
1290 * so any unused portion would have been taken care of.
1291 */
1292 if (filter->sf_flags & SFLT_EXTENDED) {
1293 unsigned int ext_len = filter->sf_len;
1294
1295 if (ext_len > sizeof (struct sflt_filter_ext))
1296 ext_len = sizeof (struct sflt_filter_ext);
1297
1298 len += ext_len;
1299 }
1300 bcopy(filter, &sock_filt->sf_filter, len);
1301
6d2010ae 1302 lck_rw_lock_exclusive(sock_filter_lock);
91447636
A
1303 /* Look for an existing entry */
1304 TAILQ_FOREACH(match, &sock_filter_head, sf_global_next) {
2d21ac55
A
1305 if (match->sf_filter.sf_handle ==
1306 sock_filt->sf_filter.sf_handle) {
91447636
A
1307 break;
1308 }
1309 }
39236c6e 1310
91447636
A
1311 /* Add the entry only if there was no existing entry */
1312 if (match == NULL) {
1313 TAILQ_INSERT_TAIL(&sock_filter_head, sock_filt, sf_global_next);
1314 if ((sock_filt->sf_filter.sf_flags & SFLT_GLOBAL) != 0) {
2d21ac55
A
1315 TAILQ_INSERT_TAIL(&pr->pr_filter_head, sock_filt,
1316 sf_protosw_next);
91447636
A
1317 sock_filt->sf_proto = pr;
1318 }
6d2010ae 1319 sflt_retain_locked(sock_filt);
91447636 1320 }
6d2010ae 1321 lck_rw_unlock_exclusive(sock_filter_lock);
316670eb 1322
91447636
A
1323 if (match != NULL) {
1324 FREE(sock_filt, M_IFADDR);
39236c6e 1325 return (EEXIST);
91447636 1326 }
2d21ac55 1327
316670eb 1328 if (!(filter->sf_flags & SFLT_EXTENDED_REGISTRY))
39236c6e 1329 return (error);
316670eb
A
1330
1331 /*
1332 * Setup the filter on the TCP and UDP sockets already created.
1333 */
39236c6e 1334#define SOLIST_ADD(_so) do { \
316670eb
A
1335 solist->next = solisthead; \
1336 sock_retain((_so)); \
1337 solist->so = (_so); \
1338 solisthead = solist; \
1339} while (0)
1340 if (protocol == IPPROTO_TCP) {
39236c6e
A
1341 lck_rw_lock_shared(tcbinfo.ipi_lock);
1342 LIST_FOREACH(inp, tcbinfo.ipi_listhead, inp_list) {
316670eb 1343 so = inp->inp_socket;
39236c6e
A
1344 if (so == NULL || (so->so_state & SS_DEFUNCT) ||
1345 (!(so->so_flags & SOF_MP_SUBFLOW) &&
1346 (so->so_state & SS_NOFDREF)) ||
1347 !SOCK_CHECK_DOM(so, domain) ||
1348 !SOCK_CHECK_TYPE(so, type))
316670eb 1349 continue;
39236c6e 1350 MALLOC(solist, struct solist *, sizeof (*solist),
316670eb
A
1351 M_IFADDR, M_NOWAIT);
1352 if (!solist)
1353 continue;
1354 SOLIST_ADD(so);
1355 }
39236c6e 1356 lck_rw_done(tcbinfo.ipi_lock);
316670eb 1357 } else if (protocol == IPPROTO_UDP) {
39236c6e
A
1358 lck_rw_lock_shared(udbinfo.ipi_lock);
1359 LIST_FOREACH(inp, udbinfo.ipi_listhead, inp_list) {
316670eb 1360 so = inp->inp_socket;
39236c6e
A
1361 if (so == NULL || (so->so_state & SS_DEFUNCT) ||
1362 (!(so->so_flags & SOF_MP_SUBFLOW) &&
1363 (so->so_state & SS_NOFDREF)) ||
1364 !SOCK_CHECK_DOM(so, domain) ||
1365 !SOCK_CHECK_TYPE(so, type))
316670eb 1366 continue;
39236c6e 1367 MALLOC(solist, struct solist *, sizeof (*solist),
316670eb
A
1368 M_IFADDR, M_NOWAIT);
1369 if (!solist)
1370 continue;
1371 SOLIST_ADD(so);
1372 }
39236c6e 1373 lck_rw_done(udbinfo.ipi_lock);
316670eb
A
1374 }
1375 /* XXX it's possible to walk the raw socket list as well */
1376#undef SOLIST_ADD
1377
1378 while (solisthead) {
1379 sflt_handle handle = filter->sf_handle;
1380
1381 so = solisthead->so;
fe8ab488 1382 socket_lock(so, 0);
316670eb 1383 sflt_initsock(so);
316670eb
A
1384 if (so->so_state & SS_ISCONNECTING)
1385 sflt_notify_after_register(so, sock_evt_connecting,
1386 handle);
1387 else if (so->so_state & SS_ISCONNECTED)
1388 sflt_notify_after_register(so, sock_evt_connected,
1389 handle);
1390 else if ((so->so_state &
1391 (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE)) ==
1392 (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE))
1393 sflt_notify_after_register(so, sock_evt_disconnecting,
1394 handle);
1395 else if ((so->so_state &
1396 (SS_CANTRCVMORE|SS_CANTSENDMORE|SS_ISDISCONNECTED)) ==
1397 (SS_CANTRCVMORE|SS_CANTSENDMORE|SS_ISDISCONNECTED))
1398 sflt_notify_after_register(so, sock_evt_disconnected,
1399 handle);
1400 else if (so->so_state & SS_CANTSENDMORE)
1401 sflt_notify_after_register(so, sock_evt_cantsendmore,
1402 handle);
1403 else if (so->so_state & SS_CANTRCVMORE)
1404 sflt_notify_after_register(so, sock_evt_cantrecvmore,
1405 handle);
fe8ab488 1406 socket_unlock(so, 0);
316670eb
A
1407 /* XXX no easy way to post the sock_evt_closing event */
1408 sock_release(so);
1409 solist = solisthead;
1410 solisthead = solisthead->next;
1411 FREE(solist, M_IFADDR);
1412 }
1413
39236c6e 1414 return (error);
91447636
A
1415}
1416
1417errno_t
39236c6e 1418sflt_unregister(sflt_handle handle)
91447636
A
1419{
1420 struct socket_filter *filter;
6d2010ae 1421 lck_rw_lock_exclusive(sock_filter_lock);
39236c6e 1422
6d2010ae 1423 /* Find the entry by the handle */
91447636
A
1424 TAILQ_FOREACH(filter, &sock_filter_head, sf_global_next) {
1425 if (filter->sf_filter.sf_handle == handle)
1426 break;
1427 }
39236c6e 1428
91447636 1429 if (filter) {
39236c6e 1430 /* Remove it from the global list */
91447636 1431 TAILQ_REMOVE(&sock_filter_head, filter, sf_global_next);
39236c6e
A
1432
1433 /* Remove it from the protosw list */
91447636 1434 if ((filter->sf_filter.sf_flags & SFLT_GLOBAL) != 0) {
39236c6e
A
1435 TAILQ_REMOVE(&filter->sf_proto->pr_filter_head,
1436 filter, sf_protosw_next);
91447636 1437 }
39236c6e
A
1438
1439 /* Detach from any sockets */
6d2010ae 1440 struct socket_filter_entry *entry = NULL;
39236c6e
A
1441
1442 for (entry = filter->sf_entry_head; entry;
1443 entry = entry->sfe_next_onfilter) {
6d2010ae 1444 sflt_detach_locked(entry);
3a60a9f5 1445 }
39236c6e
A
1446
1447 /* Release the filter */
6d2010ae 1448 sflt_release_locked(filter);
91447636 1449 }
39236c6e 1450
6d2010ae 1451 lck_rw_unlock_exclusive(sock_filter_lock);
39236c6e 1452
91447636 1453 if (filter == NULL)
39236c6e
A
1454 return (ENOENT);
1455
1456 return (0);
91447636
A
1457}
1458
1459errno_t
39236c6e
A
1460sock_inject_data_in(socket_t so, const struct sockaddr *from, mbuf_t data,
1461 mbuf_t control, sflt_data_flag_t flags)
91447636
A
1462{
1463 int error = 0;
39236c6e
A
1464
1465 if (so == NULL || data == NULL)
1466 return (EINVAL);
1467
91447636 1468 if (flags & sock_data_filt_flag_oob) {
39236c6e 1469 return (ENOTSUP);
91447636 1470 }
39236c6e 1471
91447636 1472 socket_lock(so, 1);
39236c6e
A
1473
1474 /* reject if this is a subflow socket */
1475 if (so->so_flags & SOF_MP_SUBFLOW) {
1476 error = ENOTSUP;
1477 goto done;
1478 }
1479
91447636 1480 if (from) {
39236c6e
A
1481 if (sbappendaddr(&so->so_rcv,
1482 (struct sockaddr *)(uintptr_t)from, data, control, NULL))
91447636
A
1483 sorwakeup(so);
1484 goto done;
1485 }
39236c6e 1486
91447636
A
1487 if (control) {
1488 if (sbappendcontrol(&so->so_rcv, data, control, NULL))
1489 sorwakeup(so);
1490 goto done;
1491 }
39236c6e 1492
91447636
A
1493 if (flags & sock_data_filt_flag_record) {
1494 if (control || from) {
1495 error = EINVAL;
1496 goto done;
1497 }
39236c6e 1498 if (sbappendrecord(&so->so_rcv, (struct mbuf *)data))
91447636
A
1499 sorwakeup(so);
1500 goto done;
1501 }
39236c6e 1502
91447636
A
1503 if (sbappend(&so->so_rcv, data))
1504 sorwakeup(so);
1505done:
1506 socket_unlock(so, 1);
39236c6e 1507 return (error);
91447636
A
1508}
1509
1510errno_t
39236c6e
A
1511sock_inject_data_out(socket_t so, const struct sockaddr *to, mbuf_t data,
1512 mbuf_t control, sflt_data_flag_t flags)
91447636 1513{
39236c6e
A
1514 int sosendflags = 0;
1515
1516 /* reject if this is a subflow socket */
1517 if (so->so_flags & SOF_MP_SUBFLOW)
1518 return (ENOTSUP);
1519
1520 if (flags & sock_data_filt_flag_oob)
1521 sosendflags = MSG_OOB;
1522 return (sosend(so, (struct sockaddr *)(uintptr_t)to, NULL,
1523 data, control, sosendflags));
91447636
A
1524}
1525
1526sockopt_dir
39236c6e 1527sockopt_direction(sockopt_t sopt)
91447636 1528{
39236c6e 1529 return ((sopt->sopt_dir == SOPT_GET) ? sockopt_get : sockopt_set);
91447636
A
1530}
1531
1532int
39236c6e 1533sockopt_level(sockopt_t sopt)
91447636 1534{
39236c6e 1535 return (sopt->sopt_level);
91447636
A
1536}
1537
1538int
39236c6e 1539sockopt_name(sockopt_t sopt)
91447636 1540{
39236c6e 1541 return (sopt->sopt_name);
91447636
A
1542}
1543
1544size_t
39236c6e 1545sockopt_valsize(sockopt_t sopt)
91447636 1546{
39236c6e 1547 return (sopt->sopt_valsize);
91447636
A
1548}
1549
1550errno_t
39236c6e 1551sockopt_copyin(sockopt_t sopt, void *data, size_t len)
91447636 1552{
39236c6e 1553 return (sooptcopyin(sopt, data, len, len));
91447636
A
1554}
1555
1556errno_t
39236c6e 1557sockopt_copyout(sockopt_t sopt, void *data, size_t len)
91447636 1558{
39236c6e 1559 return (sooptcopyout(sopt, data, len));
91447636 1560}