/*
 * Copyright (c) 2008-2017 Apple Computer, Inc. All rights reserved.
 *
 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
 *
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Apple Public Source License
 * Version 2.0 (the 'License'). You may not use this file except in
 * compliance with the License. The rights granted to you under the License
 * may not be used to create, or enable the creation or redistribution of,
 * unlawful or unlicensed copies of an Apple operating system, or to
 * circumvent, violate, or enable the circumvention or violation of, any
 * terms of an Apple operating system software license agreement.
 *
 * Please obtain a copy of the License at
 * http://www.opensource.apple.com/apsl/ and read it before using this file.
 *
 * The Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 * Please see the License for the specific language governing rights and
 * limitations under the License.
 *
 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
 */
/*!
 *       @header kpi_socketfilter.h
 *       This header defines an API for intercepting communications at the
 *       socket layer.
 *
 *       For the most part, socket filters want to do three things: Filter
 *       data in and out, watch for state changes, and intercept a few calls
 *       for security. The number of function pointers supplied by a socket
 *       filter has been significantly reduced. The filter no longer has any
 *       knowledge of socket buffers. The filter no longer intercepts nearly
 *       every internal socket call. There are two data filters, an in
 *       filter, and an out filter. The in filter occurs before data is
 *       placed in the receive socket buffer. This is done to avoid waking
 *       the process unnecessarily. The out filter occurs before the data is
 *       appended to the send socket buffer. This should cover inbound and
 *       outbound data. For monitoring state changes, we've added a notify
 *       function that will be called when various events that the filter can
 *       not intercept occur. In addition, we've added a few functions that a
 *       filter may use to intercept common operations. These functions are:
 *       connect (inbound), connect (outbound), bind, set socket option,
 *       get socket option, and listen. Bind, listen, connect in, and connect
 *       out could be used together to build a fairly comprehensive firewall
 *       without having to do much with individual packets.
 */
#ifndef __KPI_SOCKETFILTER__
#define __KPI_SOCKETFILTER__

#include <sys/kernel_types.h>
#include <sys/kpi_socket.h>

#ifndef PRIVATE
#include <Availability.h>
#define __NKE_API_DEPRECATED __API_DEPRECATED("Network Kernel Extension KPI is deprecated", macos(10.4, 10.15))
#else
#define __NKE_API_DEPRECATED
#endif /* PRIVATE */

struct sockaddr;

/*!
 *       @enum sflt_flags
 *       @abstract Constants defining mbuf flags. Only the flags listed below
 *               can be set or retrieved.
 *       @constant SFLT_GLOBAL Indicates this socket filter should be
 *               attached to all new sockets when they're created.
 *       @constant SFLT_PROG Indicates this socket filter should be attached
 *               only when request by the application using the SO_NKE socket
 *               option.
 *       @constant SFLT_EXTENDED	Indicates that this socket filter utilizes
 *               the extended fields within the sflt_filter structure.
 *       @constant SFLT_EXTENDED_REGISTRY Indicates that this socket filter
 *               wants to attach to all the sockets already present on the
 *               system. It will also receive notifications for these sockets.
 */
enum {
	SFLT_GLOBAL             = 0x01,
	SFLT_PROG               = 0x02,
	SFLT_EXTENDED           = 0x04,
	SFLT_EXTENDED_REGISTRY  = 0x08
};
typedef u_int32_t       sflt_flags;

/*!
 *       @typedef sflt_handle
 *       @abstract A 4 byte identifier used with the SO_NKE socket option to
 *               identify the socket filter to be attached.
 */
typedef u_int32_t       sflt_handle;

/*!
 *       @enum sflt_event_t
 *       @abstract Events notify a filter of state changes and other various
 *               events related to the socket. These events cannot be prevented
 *               or intercepted, only observed.
 *       @constant sock_evt_connected Indicates this socket has moved to the
 *               connected state.
 *       @constant sock_evt_disconnected Indicates this socket has moved to
 *               the disconnected state.
 *       @constant sock_evt_flush_read The read socket buffer has been
 *               flushed.
 *       @constant sock_evt_shutdown The read and or write side(s) of the
 *               connection have been shutdown. The param will point to an
 *               integer that indicates the direction that has been shutdown. See
 *               'man 2 shutdown' for more information.
 *       @constant sock_evt_cantrecvmore Indicates the socket cannot receive
 *               more data.
 *       @constant sock_evt_cantsendmore Indicates the socket cannot send
 *               more data.
 *       @constant sock_evt_closing Indicates the socket is closing.
 *       @constant sock_evt_bound Indicates this socket has moved to the
 *               bound state (only for PF_INET/PF_INET6 domain).
 */
enum {
	sock_evt_connecting             = 1,
	sock_evt_connected              = 2,
	sock_evt_disconnecting          = 3,
	sock_evt_disconnected           = 4,
	sock_evt_flush_read             = 5,
	sock_evt_shutdown               = 6, /* param points to an integer specifying how (read, write, or both) see man 2 shutdown */
	sock_evt_cantrecvmore           = 7,
	sock_evt_cantsendmore           = 8,
	sock_evt_closing                = 9,
	sock_evt_bound                  = 10
};
typedef u_int32_t       sflt_event_t;

/*!
 *       @enum sflt_data_flag_t
 *       @abstract Inbound and outbound data filters may handle many
 *               different types of incoming and outgoing data. These flags help
 *               distinguish between normal data, out-of-band data, and records.
 *       @constant sock_data_filt_flag_oob Indicates this data is out-of-band
 *               data.
 *       @constant sock_data_filt_flag_record Indicates this data is a
 *               record. This flag is only ever seen on inbound data.
 */
enum {
	sock_data_filt_flag_oob         = 1,
	sock_data_filt_flag_record      = 2
};
typedef u_int32_t       sflt_data_flag_t;

__BEGIN_DECLS

/*!
 *       @typedef sf_unregistered_func
 *
 *       @discussion sf_unregistered_func is called to notify the filter it
 *               has been unregistered. This is the last function the stack will
 *               call and this function will only be called once all other
 *               function calls in to your filter have completed. Once this
 *               function has been called, your kext may safely unload.
 *       @param handle The socket filter handle used to identify this filter.
 */
typedef void (*sf_unregistered_func)(sflt_handle handle);

/*!
 *       @typedef sf_attach_func
 *
 *       @discussion sf_attach_func is called to notify the filter it has
 *               been attached to a socket. The filter may allocate memory for
 *               this attachment and use the cookie to track it. This filter is
 *               called in one of two cases:
 *               1) You've installed a global filter and a new socket was created.
 *               2) Your non-global socket filter is being attached using the SO_NKE
 *               socket option.
 *       @param cookie Used to allow the socket filter to set the cookie for
 *               this attachment.
 *       @param so The socket the filter is being attached to.
 *       @result If you return a non-zero value, your filter will not be
 *               attached to this socket.
 */
typedef errno_t (*sf_attach_func)(void  **cookie, socket_t so);

/*!
 *       @typedef sf_detach_func
 *
 *       @discussion sf_detach_func is called to notify the filter it has
 *               been detached from a socket. If the filter allocated any memory
 *               for this attachment, it should be freed. This function will
 *               be called when the socket is disposed of.
 *       @param cookie Cookie value specified when the filter attach was
 *               called.
 *       @param so The socket the filter is attached to.
 *       @discussion If you return a non-zero value, your filter will not be
 *               attached to this socket.
 */
typedef void (*sf_detach_func)(void *cookie, socket_t so);

/*!
 *       @typedef sf_notify_func
 *
 *       @discussion sf_notify_func is called to notify the filter of various
 *               state changes and other events occuring on the socket.
 *       @param cookie Cookie value specified when the filter attach was
 *               called.
 *       @param so The socket the filter is attached to.
 *       @param event The type of event that has occurred.
 *       @param param Additional information about the event.
 */
typedef void (*sf_notify_func)(void *cookie, socket_t so, sflt_event_t event,
    void *param);

/*!
 *       @typedef sf_getpeername_func
 *
 *       @discussion sf_getpeername_func is called to allow a filter to
 *               to intercept the getpeername function. When called, sa will
 *               point to a pointer to a socket address that was malloced
 *               in zone M_SONAME. If you want to replace this address, either
 *               modify the currenty copy or allocate a new one and free the
 *               old one.
 *       @param cookie Cookie value specified when the filter attach was
 *               called.
 *       @param so The socket the filter is attached to.
 *       @param sa A pointer to a socket address pointer.
 *       @result If you return a non-zero value, processing will stop. If
 *               you return EJUSTRETURN, no further filters will be called
 *               but a result of zero will be returned to the caller of
 *               getpeername.
 */
typedef int (*sf_getpeername_func)(void *cookie, socket_t so,
    struct sockaddr **sa);

/*!
 *       @typedef sf_getsockname_func
 *
 *       @discussion sf_getsockname_func is called to allow a filter to
 *               to intercept the getsockname function. When called, sa will
 *               point to a pointer to a socket address that was malloced
 *               in zone M_SONAME. If you want to replace this address, either
 *               modify the currenty copy or allocate a new one and free the
 *               old one.
 *       @param cookie Cookie value specified when the filter attach was
 *               called.
 *       @param so The socket the filter is attached to.
 *       @param sa A pointer to a socket address pointer.
 *       @result If you return a non-zero value, processing will stop. If
 *               you return EJUSTRETURN, no further filters will be called
 *               but a result of zero will be returned to the caller of
 *               getsockname.
 */
typedef int (*sf_getsockname_func)(void *cookie, socket_t so,
    struct sockaddr **sa);

/*!
 *       @typedef sf_data_in_func
 *
 *       @discussion sf_data_in_func is called to filter incoming data. If your
 *               filter intercepts data for later reinjection, it must queue
 *               all incoming data to preserve the order of the data. Use
 *               sock_inject_data_in to later reinject this data if you return
 *               EJUSTRETURN. Warning: This filter is on the data path. Do not
 *               spend excesive time. Do not wait for data on another socket.
 *       @param cookie Cookie value specified when the filter attach was
 *               called.
 *       @param so The socket the filter is attached to.
 *       @param from The addres the data is from, may be NULL if the socket
 *               is connected.
 *       @param data The data being received. Control data may appear in the
 *               mbuf chain, be sure to check the mbuf types to find control
 *               data.
 *       @param control Control data being passed separately from the data.
 *       @param flags Flags to indicate if this is out of band data or a
 *               record.
 *       @result Return:
 *               0 - The caller will continue with normal processing of the data.
 *               EJUSTRETURN - The caller will stop processing the data, the
 *                       data will not be freed.
 *               Anything Else - The caller will free the data and stop
 *                       processing.
 */
typedef errno_t (*sf_data_in_func)(void *cookie, socket_t so,
    const struct sockaddr *from, mbuf_t *data, mbuf_t *control,
    sflt_data_flag_t flags);

/*!
 *       @typedef sf_data_out_func
 *
 *       @discussion sf_data_out_func is called to filter outbound data. If
 *               your filter intercepts data for later reinjection, it must queue
 *               all outbound data to preserve the order of the data when
 *               reinjecting. Use sock_inject_data_out to later reinject this
 *               data.
 *       @param cookie Cookie value specified when the filter attach was
 *               called.
 *       @param so The socket the filter is attached to.
 *       @param to The address the data is to, may be NULL if the socket
 *               is connected.
 *       @param data The data being received. Control data may appear in the
 *               mbuf chain, be sure to check the mbuf types to find control
 *               data.
 *       @param control Control data being passed separately from the data.
 *       @param flags Flags to indicate if this is out of band data or a
 *               record.
 *       @result Return:
 *               0 - The caller will continue with normal processing of the data.
 *               EJUSTRETURN - The caller will stop processing the data,
 *                       the data will not be freed.
 *               Anything Else - The caller will free the data and stop
 *                       processing.
 */
typedef errno_t (*sf_data_out_func)(void *cookie, socket_t so,
    const struct sockaddr *to, mbuf_t *data, mbuf_t *control,
    sflt_data_flag_t flags);

/*!
 *       @typedef sf_connect_in_func
 *
 *       @discussion sf_connect_in_func is called to filter inbound connections.
 *               A protocol will call this before accepting an incoming
 *               connection and placing it on the queue of completed connections.
 *               Warning: This filter is on the data path. Do not spend excesive
 *               time. Do not wait for data on another socket.
 *       @param cookie Cookie value specified when the filter attach was
 *               called.
 *       @param so The socket the filter is attached to.
 *       @param from The address the incoming connection is from.
 *       @result Return:
 *               0 - The caller will continue with normal processing of the
 *                       connection.
 *               Anything Else - The caller will rejecting the incoming
 *                       connection.
 */
typedef errno_t (*sf_connect_in_func)(void *cookie, socket_t so,
    const struct sockaddr *from);

/*!
 *       @typedef sf_connect_out_func
 *
 *       @discussion sf_connect_out_func is called to filter outbound
 *               connections. A protocol will call this before initiating an
 *               outbound connection.
 *       @param cookie Cookie value specified when the filter attach was
 *               called.
 *       @param so The socket the filter is attached to.
 *       @param to The remote address of the outbound connection.
 *       @result Return:
 *               0 - The caller will continue with normal processing of the
 *                       connection.
 *               EJUSTRETURN - The caller will return with a value of 0 (no error)
 *                       from that point without further processing the connect command. The
 *                       protocol layer will not see the call.
 *               Anything Else - The caller will rejecting the outbound
 *                       connection.
 */
typedef errno_t (*sf_connect_out_func)(void *cookie, socket_t so,
    const struct sockaddr *to);

/*!
 *       @typedef sf_bind_func
 *
 *       @discussion sf_bind_func is called before performing a bind
 *               operation on a socket.
 *       @param cookie Cookie value specified when the filter attach was
 *               called.
 *       @param so The socket the filter is attached to.
 *       @param to The local address of the socket will be bound to.
 *       @result Return:
 *               0 - The caller will continue with normal processing of the bind.
 *               EJUSTRETURN - The caller will return with a value of 0 (no error)
 *                       from that point without further processing the bind command. The
 *                       protocol layer will not see the call.
 *               Anything Else - The caller will rejecting the bind.
 */
typedef errno_t (*sf_bind_func)(void *cookie, socket_t so,
    const struct sockaddr *to);

/*!
 *       @typedef sf_setoption_func
 *
 *       @discussion sf_setoption_func is called before performing setsockopt
 *               on a socket.
 *       @param cookie Cookie value specified when the filter attach was
 *               called.
 *       @param so The socket the filter is attached to.
 *       @param opt The socket option to set.
 *       @result Return:
 *               0 - The caller will continue with normal processing of the
 *                       setsockopt.
 *               EJUSTRETURN - The caller will return with a value of 0 (no error)
 *                       from that point without further propagating the set option
 *                       command. The socket and protocol layers will not see the call.
 *               Anything Else - The caller will stop processing and return
 *                       this error.
 */
typedef errno_t (*sf_setoption_func)(void *cookie, socket_t so, sockopt_t opt);

/*!
 *       @typedef sf_getoption_func
 *
 *       @discussion sf_getoption_func is called before performing getsockopt
 *               on a socket.
 *       @param cookie Cookie value specified when the filter attach was
 *               called.
 *       @param so The socket the filter is attached to.
 *       @param opt The socket option to get.
 *       @result Return:
 *               0 - The caller will continue with normal processing of the
 *                       getsockopt.
 *               EJUSTRETURN - The caller will return with a value of 0 (no error)
 *                       from that point without further propagating the get option
 *                       command. The socket and protocol layers will not see the call.
 *               Anything Else - The caller will stop processing and return
 *                       this error.
 */
typedef errno_t (*sf_getoption_func)(void *cookie, socket_t so, sockopt_t opt);

/*!
 *       @typedef sf_listen_func
 *
 *       @discussion sf_listen_func is called before performing listen
 *               on a socket.
 *       @param cookie Cookie value specified when the filter attach was
 *               called.
 *       @param so The socket the filter is attached to.
 *       @result Return:
 *               0 - The caller will continue with normal processing of listen.
 *               EJUSTRETURN - The caller will return with a value of 0 (no error)
 *               from that point without further processing the listen command. The
 *               protocol will not see the call.
 *               Anything Else - The caller will stop processing and return
 *                       this error.
 */
typedef errno_t (*sf_listen_func)(void *cookie, socket_t so);

/*!
 *       @typedef sf_ioctl_func
 *
 *       @discussion sf_ioctl_func is called before performing an ioctl
 *               on a socket.
 *
 *               All undefined ioctls are reserved for future use by Apple. If
 *               you need to communicate with your kext using an ioctl, please
 *               use SIOCSIFKPI and SIOCGIFKPI.
 *       @param cookie Cookie value specified when the filter attach was
 *               called.
 *       @param so The socket the filter is attached to.
 *       @param request The ioctl name.
 *       @param argp A pointer to the ioctl parameter.
 *       @result Return:
 *               0 - The caller will continue with normal processing of
 *                       this ioctl.
 *               EJUSTRETURN - The caller will return with a value of 0 (no error)
 *                       from that point without further processing or propogating
 *                       the ioctl.
 *               Anything Else - The caller will stop processing and return
 *                       this error.
 */
typedef errno_t (*sf_ioctl_func)(void *cookie, socket_t so,
    unsigned long request, const char* argp);

/*!
 *       @typedef sf_accept_func
 *
 *       @discussion sf_accept_func is called after a socket is dequeued
 *               off the completed (incoming) connection list and before
 *               the file descriptor is associated with it.  A filter can
 *               utilize this callback to intercept the accepted socket
 *               in order to examine it, prior to returning the socket to
 *               the caller of accept.  Such a filter may also choose to
 *               discard the accepted socket if it wishes to do so.
 *       @param cookie Cookie value specified when the filter attach was called.
 *       @param so_listen The listening socket.
 *       @param so The socket that is about to be accepted.
 *       @param local The local address of the about to be accepted socket.
 *       @param remote The remote address of the about to be accepted socket.
 *       @result Return:
 *               0 - The caller will continue with normal processing of accept.
 *               EJUSTRETURN - The to be accepted socket will be disconnected
 *                   prior to being returned to the caller of accept.  No further
 *                   control or data operations on the socket will be allowed.
 *                   This is the recommended return value as it has the least
 *                   amount of impact, especially to applications which don't
 *                   check the error value returned by accept.
 *               Anything Else - The to be accepted socket will be closed and
 *                   the error will be returned to the caller of accept.
 *                   Note that socket filter developers are advised to exercise
 *                   caution when returning non-zero values to the caller,
 *                   since some applications don't check the error value
 *                   returned by accept and therefore risk breakage.
 */
typedef errno_t (*sf_accept_func)(void *cookie, socket_t so_listen, socket_t so,
    const struct sockaddr *local, const struct sockaddr *remote);

/*!
 *       @struct sflt_filter
 *       @discussion This structure is used to define a socket filter.
 *       @field sf_handle A value used to find socket filters by
 *               applications. An application can use this value to specify that
 *               this filter should be attached when using the SO_NKE socket
 *               option.
 *       @field sf_flags Indicate whether this filter should be attached to
 *               all new sockets or just those that request the filter be
 *               attached using the SO_NKE socket option. If this filter
 *               utilizes the socket filter extension fields, it must also
 *               set SFLT_EXTENDED.
 *       @field sf_name A name used for debug purposes.
 *       @field sf_unregistered Your function for being notified when your
 *               filter has been unregistered.
 *       @field sf_attach Your function for handling attaches to sockets.
 *       @field sf_detach Your function for handling detaches from sockets.
 *       @field sf_notify Your function for handling events. May be null.
 *       @field sf_data_in Your function for handling incoming data. May be
 *               null.
 *       @field sf_data_out Your function for handling outgoing data. May be
 *               null.
 *       @field sf_connect_in Your function for handling inbound
 *               connections. May be null.
 *       @field sf_connect_out Your function for handling outbound
 *               connections. May be null.
 *       @field sf_bind Your function for handling binds. May be null.
 *       @field sf_setoption Your function for handling setsockopt. May be null.
 *       @field sf_getoption Your function for handling getsockopt. May be null.
 *       @field sf_listen Your function for handling listen. May be null.
 *       @field sf_ioctl Your function for handling ioctls. May be null.
 *       @field sf_len Length of socket filter extension structure; developers
 *               must initialize this to sizeof sflt_filter_ext structure.
 *               This field and all fields following it will only be valid
 *               if SFLT_EXTENDED flag is set in sf_flags field.
 *       @field sf_ext_accept Your function for handling inbound connections
 *               at accept time.  May be null.
 *       @field sf_ext_rsvd Reserved for future use; you must initialize
 *               the reserved fields with zeroes.
 */
struct sflt_filter {
	sflt_handle                     sf_handle;
	int                             sf_flags;
	char                            *sf_name;

	sf_unregistered_func            sf_unregistered;
	sf_attach_func                  sf_attach;
	sf_detach_func                  sf_detach;

	sf_notify_func                  sf_notify;
	sf_getpeername_func             sf_getpeername;
	sf_getsockname_func             sf_getsockname;
	sf_data_in_func                 sf_data_in;
	sf_data_out_func                sf_data_out;
	sf_connect_in_func              sf_connect_in;
	sf_connect_out_func             sf_connect_out;
	sf_bind_func                    sf_bind;
	sf_setoption_func               sf_setoption;
	sf_getoption_func               sf_getoption;
	sf_listen_func                  sf_listen;
	sf_ioctl_func                   sf_ioctl;
	/*
	 * The following are valid only if SFLT_EXTENDED flag is set.
	 * Initialize sf_ext_len to sizeof sflt_filter_ext structure.
	 * Filters must also initialize reserved fields with zeroes.
	 */
	struct sflt_filter_ext {
		unsigned int            sf_ext_len;
		sf_accept_func          sf_ext_accept;
		void                    *sf_ext_rsvd[5];        /* Reserved */
	} sf_ext;
#define sf_len          sf_ext.sf_ext_len
#define sf_accept       sf_ext.sf_ext_accept
};

/*!
 *       @function sflt_register
 *       @discussion Registers a socket filter. See 'man 2 socket' for a
 *               desciption of domain, type, and protocol.
 *       @param filter A structure describing the filter.
 *       @param domain The protocol domain these filters will be attached to.
 *               Only PF_INET & PF_INET6 domains are supported.
 *       @param type The socket type these filters will be attached to.
 *       @param protocol The protocol these filters will be attached to.
 *       @result 0 on success otherwise the errno error.
 */
#ifdef KERNEL_PRIVATE
extern errno_t sflt_register_internal(const struct sflt_filter *filter,
    int domain, int type, int protocol);

#define sflt_register(filter, domain, type, protocol) \
    sflt_register_internal((filter), (domain), (type), (protocol))
#else
extern errno_t sflt_register(const struct sflt_filter *filter, int domain,
    int type, int protocol)
__NKE_API_DEPRECATED;
#endif /* KERNEL_PRIVATE */

/*!
 *       @function sflt_unregister
 *       @discussion Unregisters a socket filter. This will not detach the
 *               socket filter from all sockets it may be attached to at the
 *               time, it will just prevent the socket filter from being attached
 *               to any new sockets.
 *       @param handle The sf_handle of the socket filter to unregister.
 *       @result 0 on success otherwise the errno error.
 */
extern errno_t sflt_unregister(sflt_handle handle)
__NKE_API_DEPRECATED;

/*!
 *       @function sflt_attach
 *       @discussion Attaches a socket filter to the specified socket. A
 *               filter must be registered before it can be attached.
 *       @param socket The socket the filter should be attached to.
 *       @param handle The handle of the registered filter to be attached.
 *       @result 0 on success otherwise the errno error.
 */
extern errno_t sflt_attach(socket_t socket, sflt_handle handle)
__NKE_API_DEPRECATED;

/*!
 *       @function sflt_detach
 *       @discussion Detaches a socket filter from a specified socket.
 *       @param socket The socket the filter should be detached from.
 *       @param handle The handle of the registered filter to be detached.
 *       @result 0 on success otherwise the errno error.
 */
extern errno_t sflt_detach(socket_t socket, sflt_handle handle)
__NKE_API_DEPRECATED;

/* Functions for manipulating sockets */
/*
 * Inject data in to the receive buffer of the socket as if it
 * had come from the network.
 *
 * flags should match sflt_data_flag_t
 */

/*!
 *       @function sock_inject_data_in
 *       @discussion Inject data in to the receive buffer of the socket as if
 *               it had come from the network.
 *       @param so The socket to inject the data on.
 *       @param from The address the data is from, only necessary on
 *               un-connected sockets. A copy of the address will be made, caller
 *               is responsible for freeing the address after calling this
 *               function.
 *       @param data The data and possibly control mbufs.
 *       @param control The separate control mbufs.
 *       @param flags Flags indicating the type of data.
 *       @result 0 on success otherwise the errno error. If the function
 *               returns an error, the caller is responsible for freeing the
 *               mbuf.
 */
extern errno_t sock_inject_data_in(socket_t so, const struct sockaddr *from,
    mbuf_t data, mbuf_t control, sflt_data_flag_t flags)
__NKE_API_DEPRECATED;

/*!
 *       @function sock_inject_data_out
 *       @discussion Inject data in to the send buffer of the socket as if it
 *               had come from the client.
 *       @param so The socket to inject the data on.
 *       @param to The address the data should be sent to, only necessary on
 *               un-connected sockets. The caller is responsible for freeing the
 *               to address after sock_inject_data_out returns.
 *       @param data The data and possibly control mbufs.
 *       @param control The separate control mbufs.
 *       @param flags Flags indicating the type of data.
 *       @result 0 on success otherwise the errno error. The data and control
 *               values are always freed regardless of return value.
 */
extern errno_t sock_inject_data_out(socket_t so, const struct sockaddr *to,
    mbuf_t data, mbuf_t control, sflt_data_flag_t flags)
__NKE_API_DEPRECATED;


/*
 * sockopt_t accessors
 */

enum {
	sockopt_get     = 1,
	sockopt_set     = 2
};
typedef u_int8_t sockopt_dir;

/*!
 *       @function sockopt_direction
 *       @discussion Retrieves the direction of the socket option (Get or
 *               Set).
 *       @param sopt The socket option.
 *       @result sock_opt_get or sock_opt_set.
 */
extern sockopt_dir sockopt_direction(sockopt_t sopt)
__NKE_API_DEPRECATED;

/*!
 *       @function sockopt_level
 *       @discussion Retrieves the socket option level. (SOL_SOCKET, etc).
 *       @param sopt The socket option.
 *       @result The socket option level. See man 2 setsockopt
 */
extern int sockopt_level(sockopt_t sopt)
__NKE_API_DEPRECATED;

/*!
 *       @function sockopt_name
 *       @discussion Retrieves the socket option name. (SO_SNDBUF, etc).
 *       @param sopt The socket option.
 *       @result The socket option name. See man 2 setsockopt
 */
extern int sockopt_name(sockopt_t sopt)
__NKE_API_DEPRECATED;

/*!
 *       @function sockopt_valsize
 *       @discussion Retrieves the size of the socket option data.
 *       @param sopt The socket option.
 *       @result The length, in bytes, of the data.
 */
extern size_t sockopt_valsize(sockopt_t sopt)
__NKE_API_DEPRECATED;

/*!
 *       @function sockopt_copyin
 *       @discussion Copies the data from the socket option to a buffer.
 *       @param sopt The socket option.
 *       @param data A pointer to the buffer to copy the data in to.
 *       @param length The number of bytes to copy.
 *       @result An errno error or zero upon success.
 */
extern errno_t sockopt_copyin(sockopt_t sopt, void *data, size_t length)
__NKE_API_DEPRECATED;

/*!
 *       @function sockopt_copyout
 *       @discussion Copies the data from a buffer to a socket option.
 *       @param sopt The socket option.
 *       @param data A pointer to the buffer to copy the data out of.
 *       @param length The number of bytes to copy.
 *       @result An errno error or zero upon success.
 */
extern errno_t sockopt_copyout(sockopt_t sopt, void *data, size_t length)
__NKE_API_DEPRECATED;

__END_DECLS
#undef __NKE_API_DEPRECATED
#endif /* __KPI_SOCKETFILTER__ */
