/*
 * Copyright (c) 2000-2004, 2012-2016 Apple 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 kern_control.h
 *       This header defines an API to communicate between a kernel
 *       extension and a process outside of the kernel.
 */

#ifndef KPI_KERN_CONTROL_H
#define KPI_KERN_CONTROL_H


#include <sys/appleapiopts.h>
#include <sys/_types/_u_char.h>
#include <sys/_types/_u_int16_t.h>
#include <sys/_types/_u_int32_t.h>

/*
 * Define Controller event subclass, and associated events.
 * Subclass of KEV_SYSTEM_CLASS
 */

/*!
 *       @defined KEV_CTL_SUBCLASS
 *   @discussion The kernel event subclass for kernel control events.
 */
#define KEV_CTL_SUBCLASS        2

/*!
 *       @defined KEV_CTL_REGISTERED
 *   @discussion The event code indicating a new controller was
 *       registered. The data portion will contain a ctl_event_data.
 */
#define KEV_CTL_REGISTERED      1       /* a new controller appears */

/*!
 *       @defined KEV_CTL_DEREGISTERED
 *   @discussion The event code indicating a controller was unregistered.
 *       The data portion will contain a ctl_event_data.
 */
#define KEV_CTL_DEREGISTERED    2       /* a controller disappears */

/*!
 *       @struct ctl_event_data
 *       @discussion This structure is used for KEV_CTL_SUBCLASS kernel
 *               events.
 *       @field ctl_id The kernel control id.
 *       @field ctl_unit The kernel control unit.
 */
struct ctl_event_data {
	u_int32_t   ctl_id;             /* Kernel Controller ID */
	u_int32_t   ctl_unit;
};

/*
 * Controls destined to the Controller Manager.
 */

/*!
 *       @defined CTLIOCGCOUNT
 *   @discussion The CTLIOCGCOUNT ioctl can be used to determine the
 *       number of kernel controllers registered.
 */
#define CTLIOCGCOUNT    _IOR('N', 2, int)               /* get number of control structures registered */

/*!
 *       @defined CTLIOCGINFO
 *   @discussion The CTLIOCGINFO ioctl can be used to convert a kernel
 *       control name to a kernel control id.
 */
#define CTLIOCGINFO     _IOWR('N', 3, struct ctl_info)  /* get id from name */


/*!
 *       @defined MAX_KCTL_NAME
 *   @discussion Kernel control names must be no longer than
 *       MAX_KCTL_NAME.
 */
#define MAX_KCTL_NAME   96

/*
 * Controls destined to the Controller Manager.
 */

/*!
 *       @struct ctl_info
 *       @discussion This structure is used with the CTLIOCGINFO ioctl to
 *               translate from a kernel control name to a control id.
 *       @field ctl_id The kernel control id, filled out upon return.
 *       @field ctl_name The kernel control name to find.
 */
struct ctl_info {
	u_int32_t   ctl_id;                             /* Kernel Controller ID  */
	char        ctl_name[MAX_KCTL_NAME];            /* Kernel Controller Name (a C string) */
};


/*!
 *       @struct sockaddr_ctl
 *       @discussion The controller address structure is used to establish
 *               contact between a user client and a kernel controller. The
 *               sc_id/sc_unit uniquely identify each controller. sc_id is a
 *               unique identifier assigned to the controller. The identifier can
 *               be assigned by the system at registration time or be a 32-bit
 *               creator code obtained from Apple Computer. sc_unit is a unit
 *               number for this sc_id, and is privately used by the kernel
 *               controller to identify several instances of the controller.
 *       @field sc_len The length of the structure.
 *       @field sc_family AF_SYSTEM.
 *       @field ss_sysaddr AF_SYS_KERNCONTROL.
 *       @field sc_id Controller unique identifier.
 *       @field sc_unit Kernel controller private unit number.
 *       @field sc_reserved Reserved, must be set to zero.
 */
struct sockaddr_ctl {
	u_char      sc_len;     /* depends on size of bundle ID string */
	u_char      sc_family;  /* AF_SYSTEM */
	u_int16_t   ss_sysaddr; /* AF_SYS_KERNCONTROL */
	u_int32_t   sc_id;      /* Controller unique identifier  */
	u_int32_t   sc_unit;    /* Developer private unit number */
	u_int32_t   sc_reserved[5];
};

#ifdef PRIVATE

struct xkctl_reg {
	u_int32_t       xkr_len;
	u_int32_t       xkr_kind;
	u_int32_t       xkr_id;
	u_int32_t       xkr_reg_unit;
	u_int32_t       xkr_flags;
	u_int64_t       xkr_kctlref;
	u_int32_t       xkr_recvbufsize;
	u_int32_t       xkr_sendbufsize;
	u_int32_t       xkr_lastunit;
	u_int32_t       xkr_pcbcount;
	u_int64_t       xkr_connect;
	u_int64_t       xkr_disconnect;
	u_int64_t       xkr_send;
	u_int64_t       xkr_send_list;
	u_int64_t       xkr_setopt;
	u_int64_t       xkr_getopt;
	u_int64_t       xkr_rcvd;
	char            xkr_name[MAX_KCTL_NAME];
};

struct xkctlpcb {
	u_int32_t       xkp_len;
	u_int32_t       xkp_kind;
	u_int64_t       xkp_kctpcb;
	u_int32_t       xkp_unit;
	u_int32_t       xkp_kctlid;
	u_int64_t       xkp_kctlref;
	char            xkp_kctlname[MAX_KCTL_NAME];
};

struct kctlstat {
	u_int64_t       kcs_reg_total __attribute__((aligned(8)));
	u_int64_t       kcs_reg_count __attribute__((aligned(8)));
	u_int64_t       kcs_pcbcount __attribute__((aligned(8)));
	u_int64_t       kcs_gencnt __attribute__((aligned(8)));
	u_int64_t       kcs_connections __attribute__((aligned(8)));
	u_int64_t       kcs_conn_fail __attribute__((aligned(8)));
	u_int64_t       kcs_send_fail __attribute__((aligned(8)));
	u_int64_t       kcs_send_list_fail __attribute__((aligned(8)));
	u_int64_t       kcs_enqueue_fail __attribute__((aligned(8)));
	u_int64_t       kcs_enqueue_fullsock __attribute__((aligned(8)));
	u_int64_t       kcs_bad_kctlref __attribute__((aligned(8)));
	u_int64_t       kcs_tbl_size_too_big __attribute__((aligned(8)));
	u_int64_t       kcs_enqdata_mb_alloc_fail __attribute__((aligned(8)));
	u_int64_t       kcs_enqdata_sbappend_fail __attribute__((aligned(8)));
};

#endif /* PRIVATE */

#ifdef KERNEL

#include <sys/kpi_mbuf.h>

/*!
 *       @typedef kern_ctl_ref
 *       @discussion A control reference is used to track an attached kernel
 *               control. Registering a kernel control will create a kernel
 *               control reference. This reference is required for sending data
 *               or removing the kernel control. This reference will be passed to
 *               callbacks for that kernel control.
 */
typedef void * kern_ctl_ref;

/*!
 *       @defined CTL_FLAG_PRIVILEGED
 *   @discussion The CTL_FLAG_PRIVILEGED flag is passed in ctl_flags. If
 *       this flag is set, only privileged processes may attach to this
 *       kernel control.
 */
#define CTL_FLAG_PRIVILEGED     0x1
/*!
 *       @defined CTL_FLAG_REG_ID_UNIT
 *   @discussion The CTL_FLAG_REG_ID_UNIT flag is passed to indicate that
 *       the ctl_id specified should be used. If this flag is not
 *       present, a unique ctl_id will be dynamically assigned to your
 *       kernel control. The CTLIOCGINFO ioctl can be used by the client
 *       to find the dynamically assigned id based on the control name
 *       specified in ctl_name.
 */
#define CTL_FLAG_REG_ID_UNIT    0x2
/*!
 *       @defined CTL_FLAG_REG_SOCK_STREAM
 *   @discussion Use the CTL_FLAG_REG_SOCK_STREAM flag when client need to open
 *       socket of type SOCK_STREAM to communicate with the kernel control.
 *       By default kernel control sockets are of type SOCK_DGRAM.
 */
#define CTL_FLAG_REG_SOCK_STREAM        0x4

#ifdef KERNEL_PRIVATE
/*!
 *       @defined CTL_FLAG_REG_EXTENDED
 *   @discussion This flag indicates that this kernel control utilizes the
 *       the extended fields within the kern_ctl_reg structure.
 */
#define CTL_FLAG_REG_EXTENDED   0x8

/*!
 *       @defined CTL_FLAG_REG_CRIT
 *   @discussion This flag indicates that this kernel control utilizes the
 *       the extended fields within the kern_ctl_reg structure.
 */
#define CTL_FLAG_REG_CRIT       0x10

/*!
 *       @defined CTL_FLAG_REG_SETUP
 *   @discussion This flag indicates that this kernel control utilizes the
 *       the setup callback field within the kern_ctl_reg structure.
 */
#define CTL_FLAG_REG_SETUP      0x20
#endif /* KERNEL_PRIVATE */

/* Data flags for controllers */
/*!
 *       @defined CTL_DATA_NOWAKEUP
 *   @discussion The CTL_DATA_NOWAKEUP flag can be used for the enqueue
 *       data and enqueue mbuf functions to indicate that the process
 *       should not be woken up yet. This is useful when you want to
 *       enqueue data using more than one call but only want to wake up
 *       the client after all of the data has been enqueued.
 */
#define CTL_DATA_NOWAKEUP       0x1

/*!
 *       @defined CTL_DATA_EOR
 *   @discussion The CTL_DATA_EOR flag can be used for the enqueue
 *       data and enqueue mbuf functions to mark the end of a record.
 */
#define CTL_DATA_EOR            0x2

#ifdef KERNEL_PRIVATE
/*!
 *       @defined CTL_DATA_CRIT
 *       @discussion This flag indicates the data is critical to the client
 *               and that it needs to be forced into the socket buffer
 *               by resizing it if needed.
 */
#define CTL_DATA_CRIT   0x4
#endif /* KERNEL_PRIVATE */

__BEGIN_DECLS

/*!
 *       @typedef ctl_connect_func
 *       @discussion The ctl_connect_func is used to receive
 *               notification of a client connecting to the kernel control.
 *       @param kctlref The control ref for the kernel control the client is
 *               connecting to.
 *       @param sac The address used to connect to this control. The field sc_unit
 *               contains the unit number of the kernel control instance the client is
 *               connecting to. If CTL_FLAG_REG_ID_UNIT was set when the kernel control
 *               was registered, sc_unit is the ctl_unit of the kern_ctl_reg structure.
 *               If CTL_FLAG_REG_ID_UNIT was not set when the kernel control was
 *               registered, sc_unit is the dynamically allocated unit number of
 *               the new kernel control instance that is used for this connection.
 *       @param unitinfo A placeholder for a pointer to the optional user-defined
 *               private data associated with this kernel control instance.  This
 *               opaque info will be provided to the user when the rest of the
 *               callback routines are executed.  For example, it can be used
 *               to pass a pointer to an instance-specific data structure in
 *               order for the user to keep track of the states related to this
 *               kernel control instance.
 */
typedef errno_t (*ctl_connect_func)(kern_ctl_ref kctlref,
    struct sockaddr_ctl *sac,
    void **unitinfo);

/*!
 *       @typedef ctl_disconnect_func
 *       @discussion The ctl_disconnect_func is used to receive notification
 *               that a client has disconnected from the kernel control. This
 *               usually happens when the socket is closed. If this is the last
 *               socket attached to your kernel control, you may unregister your
 *               kernel control from this callback.
 *       @param kctlref The control ref for the kernel control instance the client has
 *               disconnected from.
 *       @param unit The unit number of the kernel control instance the client has
 *               disconnected from.
 *       @param unitinfo The user-defined private data initialized by the
 *               ctl_connect_func callback.
 */
typedef errno_t (*ctl_disconnect_func)(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo);

/*!
 *       @typedef ctl_send_func
 *       @discussion The ctl_send_func is used to receive data sent from
 *               the client to the kernel control.
 *       @param kctlref The control ref of the kernel control.
 *       @param unit The unit number of the kernel control instance the client has
 *               connected to.
 *       @param unitinfo The user-defined private data initialized by the
 *               ctl_connect_func callback.
 *       @param m The data sent by the client to the kernel control in an
 *               mbuf chain. Your function is responsible for releasing the
 *               mbuf chain.
 *       @param flags The flags specified by the client when calling
 *               send/sendto/sendmsg (MSG_OOB/MSG_DONTROUTE).
 */
typedef errno_t (*ctl_send_func)(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo,
    mbuf_t m, int flags);

/*!
 *       @typedef ctl_setopt_func
 *       @discussion The ctl_setopt_func is used to handle set socket option
 *               calls for the SYSPROTO_CONTROL option level.
 *       @param kctlref The control ref of the kernel control.
 *       @param unit The unit number of the kernel control instance.
 *       @param unitinfo The user-defined private data initialized by the
 *               ctl_connect_func callback.
 *       @param opt The socket option.
 *       @param data A pointer to the socket option data. The data has
 *               already been copied in to the kernel for you.
 *       @param len The length of the socket option data.
 */
typedef errno_t (*ctl_setopt_func)(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo,
    int opt, void *data, size_t len);

/*!
 *       @typedef ctl_getopt_func
 *       @discussion The ctl_getopt_func is used to handle client get socket
 *               option requests for the SYSPROTO_CONTROL option level. A buffer
 *               is allocated for storage and passed to your function. The length
 *               of that buffer is also passed. Upon return, you should set *len
 *               to length of the buffer used. In some cases, data may be NULL.
 *               When this happens, *len should be set to the length you would
 *               have returned had data not been NULL. If the buffer is too small,
 *               return an error.
 *       @param kctlref The control ref of the kernel control.
 *       @param unit The unit number of the kernel control instance.
 *       @param unitinfo The user-defined private data initialized by the
 *               ctl_connect_func callback.
 *       @param opt The socket option.
 *       @param data A buffer to copy the results in to. May be NULL, see
 *               discussion.
 *       @param len A pointer to the length of the buffer. This should be set
 *               to the length of the buffer used before returning.
 */
typedef errno_t (*ctl_getopt_func)(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo,
    int opt, void *data, size_t *len);

#ifdef KERNEL_PRIVATE
/*!
 *       @typedef ctl_rcvd_func
 *       @discussion The ctl_rcvd_func is called when the client reads data from
 *               the kernel control socket. The kernel control can use this callback
 *               in combination with ctl_getenqueuespace() to avoid overflowing
 *               the socket's receive buffer. When ctl_getenqueuespace() returns
 *               0 or ctl_enqueuedata()/ctl_enqueuembuf() return ENOBUFS, the
 *               kernel control can wait until this callback is called before
 *               trying to enqueue the data again.
 *       @param kctlref The control ref of the kernel control.
 *       @param unit The unit number of the kernel control instance.
 *       @param unitinfo The user-defined private data initialized by the
 *               ctl_connect_func callback.
 *       @param flags The recv flags. See the recv(2) man page.
 */
typedef void (*ctl_rcvd_func)(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo,
    int flags);

/*!
 *       @typedef ctl_send_list_func
 *       @discussion The ctl_send_list_func is used to receive data sent from
 *               the client to the kernel control.
 *       @param kctlref The control ref of the kernel control.
 *       @param unit The unit number of the kernel control instance the client has
 *               connected to.
 *       @param unitinfo The user-defined private data initialized by the
 *               ctl_connect_func callback.
 *       @param m The data sent by the client to the kernel control in an
 *               mbuf packet chain. Your function is responsible for releasing
 *               mbuf packet chain.
 *       @param flags The flags specified by the client when calling
 *               send/sendto/sendmsg (MSG_OOB/MSG_DONTROUTE).
 */
typedef errno_t (*ctl_send_list_func)(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo,
    mbuf_t m, int flags);

/*!
 *       @typedef ctl_bind_func
 *       @discussion The ctl_bind_func is an optional function that allows the client
 *               to set up their unitinfo prior to connecting.
 *       @param kctlref The control ref for the kernel control the client is
 *               binding to.
 *       @param sac The address used to connect to this control. The field sc_unit
 *               contains the unit number of the kernel control instance the client is
 *               binding to. If CTL_FLAG_REG_ID_UNIT was set when the kernel control
 *               was registered, sc_unit is the ctl_unit of the kern_ctl_reg structure.
 *               If CTL_FLAG_REG_ID_UNIT was not set when the kernel control was
 *               registered, sc_unit is the dynamically allocated unit number of
 *               the new kernel control instance that is used for this connection.
 *       @param unitinfo A placeholder for a pointer to the optional user-defined
 *               private data associated with this kernel control instance.  This
 *               opaque info will be provided to the user when the rest of the
 *               callback routines are executed.  For example, it can be used
 *               to pass a pointer to an instance-specific data structure in
 *               order for the user to keep track of the states related to this
 *               kernel control instance.
 */
typedef errno_t (*ctl_bind_func)(kern_ctl_ref kctlref,
    struct sockaddr_ctl *sac,
    void **unitinfo);

/*!
 *       @typedef ctl_setup_func
 *       @discussion The ctl_setup_func is an optional function that allows the client
 *               to pick a unit number in the case that the caller hasn't specified one
 *       @param unit A placeholder for a pointer to the unit number that is selected with
 *               this kernel control instance
 *       @param unitinfo A placeholder for a pointer to the optional user-defined
 *               private data associated with this kernel control instance.  This
 *               opaque info will be provided to the user when the rest of the
 *               callback routines are executed.  For example, it can be used
 *               to pass a pointer to an instance-specific data structure in
 *               order for the user to keep track of the states related to this
 *               kernel control instance.
 */
typedef errno_t (*ctl_setup_func)(u_int32_t *unit, void **unitinfo);
#endif /* KERNEL_PRIVATE */

/*!
 *       @struct kern_ctl_reg
 *       @discussion This structure defines the properties of a kernel
 *               control being registered.
 *       @field ctl_name A Bundle ID string of up to MAX_KCTL_NAME bytes (including the ending zero).
 *               This string should not be empty.
 *       @field ctl_id The control ID may be dynamically assigned or it can be a
 *               32-bit creator code assigned by DTS.
 *               For a DTS assigned creator code the CTL_FLAG_REG_ID_UNIT flag must be set.
 *               For a dynamically assigned control ID, do not set the CTL_FLAG_REG_ID_UNIT flag.
 *               The  value of the dynamically assigned control ID is set to this field
 *               when the registration succeeds.
 *       @field ctl_unit A separate unit number to register multiple units that
 *               share the same control ID with DTS assigned creator code when
 *               the CTL_FLAG_REG_ID_UNIT flag is set.
 *               This field is ignored for a dynamically assigned control ID.
 *       @field ctl_flags CTL_FLAG_PRIVILEGED and/or CTL_FLAG_REG_ID_UNIT.
 *       @field ctl_sendsize Override the default send size. If set to zero,
 *               the default send size will be used, and this default value
 *               is set to this field to be retrieved by the caller.
 *       @field ctl_recvsize Override the default receive size. If set to
 *               zero, the default receive size will be used, and this default value
 *               is set to this field to be retrieved by the caller.
 *       @field ctl_connect Specify the  function to be called whenever a client
 *               connects to the kernel control. This field must be specified.
 *       @field ctl_disconnect Specify a function to be called whenever a
 *               client disconnects from the kernel control.
 *       @field ctl_send Specify a function to handle data send from the
 *               client to the kernel control.
 *       @field ctl_setopt Specify a function to handle set socket option
 *               operations for the kernel control.
 *       @field ctl_getopt Specify a function to handle get socket option
 *               operations for the kernel control.
 */
struct kern_ctl_reg {
	/* control information */
	char            ctl_name[MAX_KCTL_NAME];
	u_int32_t       ctl_id;
	u_int32_t       ctl_unit;

	/* control settings */
	u_int32_t   ctl_flags;
	u_int32_t   ctl_sendsize;
	u_int32_t   ctl_recvsize;

	/* Dispatch functions */
	ctl_connect_func    ctl_connect;
	ctl_disconnect_func ctl_disconnect;
	ctl_send_func               ctl_send;
	ctl_setopt_func             ctl_setopt;
	ctl_getopt_func             ctl_getopt;
#ifdef KERNEL_PRIVATE
	ctl_rcvd_func               ctl_rcvd;   /* Only valid if CTL_FLAG_REG_EXTENDED is set */
	ctl_send_list_func          ctl_send_list;/* Only valid if CTL_FLAG_REG_EXTENDED is set */
	ctl_bind_func           ctl_bind;
	ctl_setup_func                  ctl_setup;
#endif /* KERNEL_PRIVATE */
};

/*!
 *       @function ctl_register
 *       @discussion Register a kernel control. This will enable clients to
 *               connect to the kernel control using a PF_SYSTEM socket.
 *       @param userkctl A structure defining the kernel control to be
 *               attached. The ctl_connect callback must be specified, the other callbacks
 *               are optional. If ctl_connect is set to zero, ctl_register fails with
 *               the error code EINVAL.
 *       @param kctlref Upon successful return, the kctlref will contain a
 *               reference to the attached kernel control. This reference is used
 *               to unregister the kernel control. This reference will also be
 *               passed in to the callbacks each time they are called.
 *       @result 0 - Kernel control was registered.
 *               EINVAL - The registration structure was not valid.
 *               ENOMEM - There was insufficient memory.
 *               EEXIST - A controller with that id/unit is already registered.
 */
errno_t
ctl_register(struct kern_ctl_reg *userkctl, kern_ctl_ref *kctlref);

/*!
 *       @function ctl_deregister
 *       @discussion Unregister a kernel control. A kernel extension must
 *               unregister it's kernel control(s) before unloading. If a kernel
 *               control has clients attached, this call will fail.
 *       @param kctlref The control reference of the control to unregister.
 *       @result 0 - Kernel control was unregistered.
 *               EINVAL - The kernel control reference was invalid.
 *               EBUSY - The kernel control has clients still attached.
 */
errno_t
ctl_deregister(kern_ctl_ref kctlref);

/*!
 *       @function ctl_enqueuedata
 *       @discussion Send data from the kernel control to the client.
 *       @param kctlref The control reference of the kernel control.
 *       @param unit The unit number of the kernel control instance.
 *       @param data A pointer to the data to send.
 *       @param len The length of data to send.
 *       @param flags Send flags. CTL_DATA_NOWAKEUP and CTL_DATA_EOR are currently
 *               the only supported flags.
 *       @result 0 - Data was enqueued to be read by the client.
 *               EINVAL - Invalid parameters.
 *               EMSGSIZE - The buffer is too large.
 *               ENOBUFS - The queue is full or there are no free mbufs.
 */
errno_t
ctl_enqueuedata(kern_ctl_ref kctlref, u_int32_t unit, void *data, size_t len, u_int32_t flags);

/*!
 *       @function ctl_enqueuembuf
 *       @discussion Send data stored in an mbuf chain from the kernel
 *               control to the client. The caller is responsible for freeing
 *               the mbuf chain if ctl_enqueuembuf returns an error.
 *       @param kctlref The control reference of the kernel control.
 *       @param unit The unit number of the kernel control instance.
 *       @param m An mbuf chain containing the data to send to the client.
 *       @param flags Send flags. CTL_DATA_NOWAKEUP and CTL_DATA_EOR are currently
 *               the only supported flags.
 *       @result 0 - Data was enqueued to be read by the client.
 *               EINVAL - Invalid parameters.
 *               ENOBUFS - The queue is full.
 */
errno_t
ctl_enqueuembuf(kern_ctl_ref kctlref, u_int32_t unit, mbuf_t m, u_int32_t flags);

#ifdef PRIVATE
/*!
 *       @function ctl_enqueuembuf_list
 *       @discussion Send data stored in an mbuf packet chain from the kernel
 *               control to the client. The caller is responsible for freeing
 *               the mbuf chain if ctl_enqueuembuf returns an error.
 *               Not valid if ctl_flags contains CTL_FLAG_REG_SOCK_STREAM.
 *       @param kctlref The control reference of the kernel control.
 *       @param unit The unit number of the kernel control instance.
 *       @param m_list An mbuf chain containing the data to send to the client.
 *       @param flags Send flags. CTL_DATA_NOWAKEUP is
 *               the only supported flags.
 *       @param m_remain A pointer to the list of mbuf packets in the chain that
 *               could not be enqueued.
 *       @result 0 - Data was enqueued to be read by the client.
 *               EINVAL - Invalid parameters.
 *               ENOBUFS - The queue is full.
 */
errno_t
ctl_enqueuembuf_list(kern_ctl_ref kctlref, u_int32_t unit, mbuf_t m_list,
    u_int32_t flags, mbuf_t *m_remain);

/*!
 *       @function ctl_getenqueuepacketcount
 *       @discussion Retrieve the number of packets in the socket
 *               receive buffer.
 *       @param kctlref The control reference of the kernel control.
 *       @param unit The unit number of the kernel control instance.
 *       @param pcnt The address where to return the current count.
 *       @result 0 - Success; the packet count is returned to caller.
 *               EINVAL - Invalid parameters.
 */
errno_t
ctl_getenqueuepacketcount(kern_ctl_ref kctlref, u_int32_t unit, u_int32_t *pcnt);

#endif /* PRIVATE */

/*!
 *       @function ctl_getenqueuespace
 *       @discussion Retrieve the amount of space currently available for data to be sent
 *               from the kernel control to the client.
 *       @param kctlref The control reference of the kernel control.
 *       @param unit The unit number of the kernel control instance.
 *       @param space The address where to return the current space available
 *       @result 0 - Success; the amount of space is returned to caller.
 *               EINVAL - Invalid parameters.
 */
errno_t
ctl_getenqueuespace(kern_ctl_ref kctlref, u_int32_t unit, size_t *space);

/*!
 *  @function ctl_getenqueuereadable
 *  @discussion Retrieve the difference between enqueued bytes and
 *       low-water mark for the socket receive buffer.
 *  @param kctlref The control reference of the kernel control.
 *  @param unit The unit number of the kernel control instance.
 *  @param difference The address at which to return the current difference
 *       between the low-water mark for the socket and the number of bytes
 *       enqueued. 0 indicates that the socket is readable by the client
 *       (the number of bytes in the buffer is above the low-water mark).
 *  @result 0 - Success; the difference is returned to caller.
 *  EINVAL - Invalid parameters.
 */
errno_t
ctl_getenqueuereadable(kern_ctl_ref kctlref, u_int32_t unit, u_int32_t *difference);

#ifdef KERNEL_PRIVATE

#include <sys/queue.h>
#include <libkern/locks.h>

/*
 * internal structure maintained for each register controller
 */
struct ctl_cb;
struct kctl;
struct socket;
struct socket_info;

void kctl_fill_socketinfo(struct socket *, struct socket_info *);

u_int32_t ctl_id_by_name(const char *name);
errno_t ctl_name_by_id(u_int32_t id, char *out_name, size_t maxsize);

extern const u_int32_t ctl_maxunit;
#endif /* KERNEL_PRIVATE */

__END_DECLS
#endif /* KERNEL */

#endif /* KPI_KERN_CONTROL_H */
