2 * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
31 @header kpi_socketfilter.h
32 This header defines an API for intercepting communications at the
35 For the most part, socket filters want to do three things: Filter
36 data in and out, watch for state changes, and intercept a few calls
37 for security. The number of function pointers supplied by a socket
38 filter has been significantly reduced. The filter no longer has any
39 knowledge of socket buffers. The filter no longer intercepts nearly
40 every internal socket call. There are two data filters, an in
41 filter, and an out filter. The in filter occurs before data is
42 placed in the receive socket buffer. This is done to avoid waking
43 the process unnecessarily. The out filter occurs before the data is
44 appended to the send socket buffer. This should cover inbound and
45 outbound data. For monitoring state changes, we've added a notify
46 function that will be called when various events that the filter can
47 not intercept occur. In addition, we've added a few functions that a
48 filter may use to intercept common operations. These functions are:
49 connect (inbound), connect (outbound), bind, set socket option,
50 get socket option, and listen. Bind, listen, connect in, and connect
51 out could be used together to build a fairly comprehensive firewall
52 without having to do much with individual packets.
54 #ifndef __KPI_SOCKETFILTER__
55 #define __KPI_SOCKETFILTER__
57 #include <sys/kernel_types.h>
58 #include <sys/kpi_socket.h>
64 @abstract Constants defining mbuf flags. Only the flags listed below
65 can be set or retreieved.
66 @constant SFLT_GLOBAL Indicates this socket filter should be
67 attached to all new sockets when they're created.
68 @constant SFLT_PROG Indicates this socket filter should be attached
69 only when request by the application using the SO_NKE socket
76 typedef u_int32_t sflt_flags
;
80 @abstract A 4 byte identifier used with the SO_NKE socket option to
81 identify the socket filter to be attached.
83 typedef u_int32_t sflt_handle
;
87 @abstract Events notify a filter of state changes and other various
88 events related to the socket. These events can not be prevented
89 or intercepted, only observed.
90 @constant sock_evt_connected Indicates this socket has moved to the
92 @constant sock_evt_disconnected Indicates this socket has moved to
93 the disconnected state.
94 @constant sock_evt_flush_read The read socket buffer has been
96 @constant sock_evt_shutdown The read and or write side(s) of the
97 connection have been shutdown. The param will point to an
98 integer that indicates the direction that has been shutdown. See
99 'man 2 shutdown' for more information.
100 @constant sock_evt_cantrecvmore Indicates the socket can not receive
102 @constant sock_evt_cantsendmore Indicates the socket can not send
104 @constant sock_evt_closing Indicates the socket is closing.
107 sock_evt_connecting
= 1,
108 sock_evt_connected
= 2,
109 sock_evt_disconnecting
= 3,
110 sock_evt_disconnected
= 4,
111 sock_evt_flush_read
= 5,
112 sock_evt_shutdown
= 6, /* param points to an integer specifying how (read, write, or both) see man 2 shutdown */
113 sock_evt_cantrecvmore
= 7,
114 sock_evt_cantsendmore
= 8,
117 typedef u_int32_t sflt_event_t
;
120 @enum sflt_data_flag_t
121 @abstract Inbound and outbound data filters may handle many
122 different types of incoming and outgoing data. These flags help
123 distinguish between normal data, out-of-band data, and records.
124 @constant sock_data_filt_flag_oob Indicates this data is out-of-band
126 @constant sock_data_filt_flag_record Indicates this data is a
127 record. This flag is only ever seen on inbound data.
130 sock_data_filt_flag_oob
= 1,
131 sock_data_filt_flag_record
= 2
133 typedef u_int32_t sflt_data_flag_t
;
136 @typedef sf_unregistered_func
138 @discussion sf_unregistered_func is called to notify the filter it
139 has been unregistered. This is the last function the stack will
140 call and this function will only be called once all other
141 function calls in to your filter have completed. Once this
142 function has been called, your kext may safely unload.
143 @param handle The socket filter handle used to identify this filter.
145 typedef void (*sf_unregistered_func
)(sflt_handle handle
);
148 @typedef sf_attach_func
150 @discussion sf_attach_func is called to notify the filter it has
151 been attached to a socket. The filter may allocate memory for
152 this attachment and use the cookie to track it. This filter is
153 called in one of two cases:
154 1) You've installed a global filter and a new socket was created.
155 2) Your non-global socket filter is being attached using the SO_NKE
157 @param cookie Used to allow the socket filter to set the cookie for
159 @param so The socket the filter is being attached to.
160 @result If you return a non-zero value, your filter will not be
161 attached to this socket.
163 typedef errno_t (*sf_attach_func
)(void **cookie
, socket_t so
);
166 @typedef sf_detach_func
168 @discussion sf_detach_func is called to notify the filter it has
169 been detached from a socket. If the filter allocated any memory
170 for this attachment, it should be freed. This function will
171 be called when the socket is disposed of.
172 @param cookie Cookie value specified when the filter attach was
174 @param so The socket the filter is attached to.
175 @result If you return a non-zero value, your filter will not be
176 attached to this socket.
178 typedef void (*sf_detach_func
)(void *cookie
, socket_t so
);
181 @typedef sf_notify_func
183 @discussion sf_notify_func is called to notify the filter of various
184 state changes and other events occuring on the socket.
185 @param cookie Cookie value specified when the filter attach was
187 @param so The socket the filter is attached to.
188 @param event The type of event that has occurred.
189 @param param Additional information about the event.
191 typedef void (*sf_notify_func
)(void *cookie
, socket_t so
,
192 sflt_event_t event
, void *param
);
195 @typedef sf_getpeername_func
197 @discussion sf_getpeername_func is called to allow a filter to
198 to intercept the getpeername function. When called, sa will
199 point to a pointer to a socket address that was malloced
200 in zone M_SONAME. If you want to replace this address, either
201 modify the currenty copy or allocate a new one and free the
203 @param cookie Cookie value specified when the filter attach was
205 @param so The socket the filter is attached to.
206 @param sa A pointer to a socket address pointer.
207 @result If you return a non-zero value, processing will stop. If
208 you return EJUSTRETURN, no further filters will be called
209 but a result of zero will be returned to the caller of
212 typedef int (*sf_getpeername_func
)(void *cookie
, socket_t so
,
213 struct sockaddr
**sa
);
216 @typedef sf_getsockname_func
218 @discussion sf_getsockname_func is called to allow a filter to
219 to intercept the getsockname function. When called, sa will
220 point to a pointer to a socket address that was malloced
221 in zone M_SONAME. If you want to replace this address, either
222 modify the currenty copy or allocate a new one and free the
224 @param cookie Cookie value specified when the filter attach was
226 @param so The socket the filter is attached to.
227 @param sa A pointer to a socket address pointer.
228 @result If you return a non-zero value, processing will stop. If
229 you return EJUSTRETURN, no further filters will be called
230 but a result of zero will be returned to the caller of
233 typedef int (*sf_getsockname_func
)(void *cookie
, socket_t so
,
234 struct sockaddr
**sa
);
237 @typedef sf_data_in_func
239 @discussion sf_data_in_func is called to filter incoming data. If your
240 filter intercepts data for later reinjection, it must queue all incoming
241 data to preserve the order of the data. Use sock_inject_data_in to later
242 reinject this data if you return EJUSTRETURN. Warning: This filter is on
243 the data path. Do not spend excesive time. Do not wait for data on
245 @param cookie Cookie value specified when the filter attach was
247 @param so The socket the filter is attached to.
248 @param from The addres the data is from, may be NULL if the socket
250 @param data The data being received. Control data may appear in the
251 mbuf chain, be sure to check the mbuf types to find control
253 @param control Control data being passed separately from the data.
254 @param flags Flags to indicate if this is out of band data or a
257 0 - The caller will continue with normal processing of the data.
258 EJUSTRETURN - The caller will stop processing the data, the data will not be freed.
259 Anything Else - The caller will free the data and stop processing.
261 typedef errno_t (*sf_data_in_func
)(void *cookie
, socket_t so
,
262 const struct sockaddr
*from
, mbuf_t
*data
,
263 mbuf_t
*control
, sflt_data_flag_t flags
);
266 @typedef sf_data_out_func
268 @discussion sf_data_out_func is called to filter outbound data. If
269 your filter intercepts data for later reinjection, it must queue
270 all outbound data to preserve the order of the data when
271 reinjecting. Use sock_inject_data_out to later reinject this
273 @param cookie Cookie value specified when the filter attach was
275 @param so The socket the filter is attached to.
276 @param from The address the data is from, may be NULL if the socket
278 @param data The data being received. Control data may appear in the
279 mbuf chain, be sure to check the mbuf types to find control
281 @param control Control data being passed separately from the data.
282 @param flags Flags to indicate if this is out of band data or a
285 0 - The caller will continue with normal processing of the data.
286 EJUSTRETURN - The caller will stop processing the data, the data will not be freed.
287 Anything Else - The caller will free the data and stop processing.
289 typedef errno_t (*sf_data_out_func
)(void *cookie
, socket_t so
,
290 const struct sockaddr
*to
, mbuf_t
*data
,
291 mbuf_t
*control
, sflt_data_flag_t flags
);
294 @typedef sf_connect_in_func
296 @discussion sf_connect_in_func is called to filter inbound connections. A
297 protocol will call this before accepting an incoming connection and
298 placing it on the queue of completed connections. Warning: This filter
299 is on the data path. Do not spend excesive time. Do not wait for data on
301 @param cookie Cookie value specified when the filter attach was
303 @param so The socket the filter is attached to.
304 @param from The address the incoming connection is from.
306 0 - The caller will continue with normal processing of the connection.
307 Anything Else - The caller will rejecting the incoming connection.
309 typedef errno_t (*sf_connect_in_func
)(void *cookie
, socket_t so
,
310 const struct sockaddr
*from
);
313 @typedef sf_connect_out_func
315 @discussion sf_connect_out_func is called to filter outbound
316 connections. A protocol will call this before initiating an
318 @param cookie Cookie value specified when the filter attach was
320 @param so The socket the filter is attached to.
321 @param to The remote address of the outbound connection.
323 0 - The caller will continue with normal processing of the connection.
324 Anything Else - The caller will rejecting the outbound connection.
326 typedef errno_t (*sf_connect_out_func
)(void *cookie
, socket_t so
,
327 const struct sockaddr
*to
);
330 @typedef sf_bind_func
332 @discussion sf_bind_func is called before performing a bind
333 operation on a socket.
334 @param cookie Cookie value specified when the filter attach was
336 @param so The socket the filter is attached to.
337 @param to The local address of the socket will be bound to.
339 0 - The caller will continue with normal processing of the bind.
340 Anything Else - The caller will rejecting the bind.
342 typedef errno_t (*sf_bind_func
)(void *cookie
, socket_t so
,
343 const struct sockaddr
*to
);
346 @typedef sf_setoption_func
348 @discussion sf_setoption_func is called before performing setsockopt
350 @param cookie Cookie value specified when the filter attach was
352 @param so The socket the filter is attached to.
353 @param opt The socket option to set.
355 0 - The caller will continue with normal processing of the setsockopt.
356 Anything Else - The caller will stop processing and return this error.
358 typedef errno_t (*sf_setoption_func
)(void *cookie
, socket_t so
,
362 @typedef sf_getoption_func
364 @discussion sf_getoption_func is called before performing getsockopt
366 @param cookie Cookie value specified when the filter attach was
368 @param so The socket the filter is attached to.
369 @param opt The socket option to get.
371 0 - The caller will continue with normal processing of the getsockopt.
372 Anything Else - The caller will stop processing and return this error.
374 typedef errno_t (*sf_getoption_func
)(void *cookie
, socket_t so
,
378 @typedef sf_listen_func
380 @discussion sf_listen_func is called before performing listen
382 @param cookie Cookie value specified when the filter attach was
384 @param so The socket the filter is attached to.
386 0 - The caller will continue with normal processing of listen.
387 Anything Else - The caller will stop processing and return this error.
389 typedef errno_t (*sf_listen_func
)(void *cookie
, socket_t so
);
392 @typedef sf_ioctl_func
394 @discussion sf_ioctl_func is called before performing an ioctl
396 @param cookie Cookie value specified when the filter attach was
398 @param so The socket the filter is attached to.
399 @param request The ioctl name.
400 @param argp A pointer to the ioctl parameter.
402 0 - The caller will continue with normal processing of this ioctl.
403 Anything Else - The caller will stop processing and return this error.
405 typedef errno_t (*sf_ioctl_func
)(void *cookie
, socket_t so
,
406 u_int32_t request
, const char* argp
);
410 @discussion This structure is used to define a socket filter.
411 @field sf_handle A value used to find socket filters by
412 applications. An application can use this value to specify that
413 this filter should be attached when using the SO_NKE socket
415 @field sf_flags Indicate whether this filter should be attached to
416 all new sockets or just those that request the filter be
417 attached using the SO_NKE socket option.
418 @field sf_name A name used for debug purposes.
419 @field sf_unregistered Your function for being notified when your
420 filter has been unregistered.
421 @field sf_attach Your function for handling attaches to sockets.
422 @field sf_detach Your function for handling detaches from sockets.
423 @field sf_notify Your function for handling events. May be null.
424 @field sf_data_in Your function for handling incoming data. May be
426 @field sf_data_out Your function for handling outgoing data. May be
428 @field sf_connect_in Your function for handling inbound
429 connections. May be null.
430 @field sf_connect_in Your function for handling outbound
431 connections. May be null.
432 @field sf_bind Your function for handling binds. May be null.
433 @field sf_setoption Your function for handling setsockopt. May be null.
434 @field sf_getoption Your function for handling getsockopt. May be null.
435 @field sf_listen Your function for handling listen. May be null.
436 @field sf_ioctl Your function for handling ioctls. May be null.
439 sflt_handle sf_handle
;
443 sf_unregistered_func sf_unregistered
;
444 sf_attach_func sf_attach
;
445 sf_detach_func sf_detach
;
447 sf_notify_func sf_notify
;
448 sf_getpeername_func sf_getpeername
;
449 sf_getsockname_func sf_getsockname
;
450 sf_data_in_func sf_data_in
;
451 sf_data_out_func sf_data_out
;
452 sf_connect_in_func sf_connect_in
;
453 sf_connect_out_func sf_connect_out
;
454 sf_bind_func sf_bind
;
455 sf_setoption_func sf_setoption
;
456 sf_getoption_func sf_getoption
;
457 sf_listen_func sf_listen
;
458 sf_ioctl_func sf_ioctl
;
462 @function sflt_register
463 @discussion Registers a socket filter. See 'man 2 socket' for a
464 desciption of domain, type, and protocol.
465 @param filter A structure describing the filter.
466 @param domain The protocol domain these filters will be attached to.
467 @param type The socket type these filters will be attached to.
468 @param protocol The protocol these filters will be attached to.
469 @result 0 on success otherwise the errno error.
471 errno_t
sflt_register(const struct sflt_filter
*filter
, int domain
,
472 int type
, int protocol
);
475 @function sflt_unregister
476 @discussion Unregisters a socket filter. This will not detach the
477 socket filter from all sockets it may be attached to at the
478 time, it will just prevent the socket filter from being attached
480 @param handle The sf_handle of the socket filter to unregister.
481 @result 0 on success otherwise the errno error.
483 errno_t
sflt_unregister(sflt_handle handle
);
486 @function sflt_attach
487 @discussion Attaches a socket filter to the specified socket. A
488 filter must be registered before it can be attached.
489 @param socket The socket the filter should be attached to.
490 @param handle The handle of the registered filter to be attached.
491 @result 0 on success otherwise the errno error.
493 errno_t
sflt_attach(socket_t socket
, sflt_handle
);
496 @function sflt_detach
497 @discussion Detaches a socket filter from a specified socket.
498 @param socket The socket the filter should be detached from.
499 @param handle The handle of the registered filter to be detached.
500 @result 0 on success otherwise the errno error.
502 errno_t
sflt_detach(socket_t socket
, sflt_handle
);
504 /* Functions for manipulating sockets */
506 * Inject data in to the receive buffer of the socket as if it
507 * had come from the network.
509 * flags should match sflt_data_flag_t
513 @function sock_inject_data_in
514 @discussion Inject data in to the receive buffer of the socket as if
515 it had come from the network.
516 @param so The socket to inject the data on.
517 @param from The address the data is from, only necessary on
518 un-connected sockets. A copy of the address will be made, caller
519 is responsible for freeing the address after calling this
521 @param data The data and possibly control mbufs.
522 @param control The separate control mbufs.
523 @param flags Flags indicating the type of data.
524 @result 0 on success otherwise the errno error. If the function
525 returns an error, the caller is responsible for freeing the
528 errno_t
sock_inject_data_in(socket_t so
, const struct sockaddr
* from
,
529 mbuf_t data
, mbuf_t control
, sflt_data_flag_t flags
);
532 @function sock_inject_data_out
533 @discussion Inject data in to the send buffer of the socket as if it
534 had come from the client.
535 @param so The socket to inject the data on.
536 @param to The address the data should be sent to, only necessary on
537 un-connected sockets. The caller is responsible for freeing the
538 to address after sock_inject_data_out returns.
539 @param data The data and possibly control mbufs.
540 @param control The separate control mbufs.
541 @param flags Flags indicating the type of data.
542 @result 0 on success otherwise the errno error. The data and control
543 values are always freed regardless of return value.
545 errno_t
sock_inject_data_out(socket_t so
, const struct sockaddr
* to
,
546 mbuf_t data
, mbuf_t control
, sflt_data_flag_t flags
);
550 * sockopt_t accessors
557 typedef u_int8_t sockopt_dir
;
560 @function sockopt_direction
561 @discussion Retreives the direction of the socket option (Get or
563 @param sopt The socket option.
564 @result sock_opt_get or sock_opt_set.
566 sockopt_dir
sockopt_direction(sockopt_t sopt
);
569 @function sockopt_level
570 @discussion Retreives the socket option level. (SOL_SOCKET, etc).
571 @param sopt The socket option.
572 @result The socket option level. See man 2 setsockopt
574 int sockopt_level(sockopt_t sopt
);
577 @function sockopt_name
578 @discussion Retreives the socket option name. (SO_SNDBUF, etc).
579 @param sopt The socket option.
580 @result The socket option name. See man 2 setsockopt
582 int sockopt_name(sockopt_t sopt
);
585 @function sockopt_valsize
586 @discussion Retreives the size of the socket option data.
587 @param sopt The socket option.
588 @result The length, in bytes, of the data.
590 size_t sockopt_valsize(sockopt_t sopt
);
593 @function sockopt_copyin
594 @discussion Copies the data from the socket option to a buffer.
595 @param sopt The socket option.
596 @param data A pointer to the buffer to copy the data in to.
597 @param length The number of bytes to copy.
598 @result An errno error or zero upon success.
600 errno_t
sockopt_copyin(sockopt_t sopt
, void *data
, size_t length
);
603 @function sockopt_copyout
604 @discussion Copies the data from a buffer to a socket option.
605 @param sopt The socket option.
606 @param data A pointer to the buffer to copy the data out of.
607 @param length The number of bytes to copy.
608 @result An errno error or zero upon success.
610 errno_t
sockopt_copyout(sockopt_t sopt
, void *data
, size_t length
);