Network Kernel Extensions Reference

The document KPI Reference describes the functions that NKEs can call and describes a few NKE-specific data types. They are organized by header file. This chapter includes a few additional APIs that may be useful when writing an NKE.

Kernel Utilities

NKEs can call a number of kernel utility functions including the following:

This list does not attempt to be exhaustive, but highlights many of the more frequently-used utility functions.

_MALLOC

Defined in: <sys/malloc.h>

Allocates kernel memory.

    void *_MALLOC(size_t size, int type, int flags);

_MALLOC is much like the user-space malloc function, but it has additional parameters that require some explanation.

The types argument is a number representing the type of data that will be stored in the argument. This is used primarily for accounting purposes. The known types are described in <sys/malloc.h>.

The flags argument consists of some combination of M_WAITOK, M_NOWAIT, and M_ZERO.

The flag M_NOWAIT causes _MALLOC to immediately return a null pointer if no space is available rather than waiting for space to become available. While this is appropriate for time-sensitive tasks that can be retried, it is not always what you want.

The more traditional (and default) behavior is M_WAITOK, which indicates that it is safe to wait for space to become available. If your code is in a critical path for performance, you should probably use M_NOWAIT if possible, and depend on the networking stack to retry after resources become available.

Finally, the flag M_ZERO requests that the allocator should zero the resulting allocation before returning it.

_FREE

Defined in: <sys/malloc.h>

Frees memory allocated with _MALLOC

    void _FREE(void *addr, int type);

The type flag passed to _FREE must be the same as the flag passed to the corresponding call to _MALLOC.

printf

Defined in: <libkern/libkern.h>

Print text to the console.

    void printf(const char *format, ... );

Identical to printf in user space. It is not safe to call printf from within an interrupt context. This should generally not be an issue, as you should avoid calling NKE functions from within an I/O Kit driver’s filter routine as a matter of course, but it is worth noting.

proc_exiting

Defined in: <sys/proc.h>

Returns 1 if a process is exiting, else 0.

    int proc_exiting(proc_t);

proc_is64bit

Defined in: <sys/proc.h>

Returns 1 if a process is a 64-bit executable, else 0.

    int proc_is64bit(proc_t);

proc_rele

Defined in: <sys/proc.h>

Releases a reference to a process entry.

    int proc_rele(proc_t);

proc_self

Defined in: <sys/proc.h>

Returns a reference to the running process. This must be released with “proc_rele”.

    proc_t proc_self(void);

proc_suser

Defined in: <sys/proc.h>

Checks to see if a process is running as the super-user (root).

    int proc_suser(struct proc *p);

msleep

Defined in: <sys/proc.h>

Sleep until an event is posted with “wakeup” or until a timeout occurs. This is commonly combined with a timeout value to bound the wait.

    int msleep(void *chan, lck_mtx_t *mtx, int pri, const char *wmesg, struct timespec *ts);

The timeout value is a standard timespec (defined in <sys/time.h>, and is measured in seconds and nanoseconds. To sleep until woken, you should pass a NULL value for ts.

The parameter mtx is a mutex (defined in a processor-specific include, but included with <sys/lock.h>) that will be released prior to sleeping. (The mutex must be locked prior to calling msleep.) The mutex will also be reacquired upon wake unless the PDROP flag is set in the priority value.

The parameter chan should be a unique identifier specific to a given wait event. Usually such an event is associated with the change in a variable, in which case the address of that variable makes a good value for chan.

The parameter pri is the desired priority on wake (defined in <sys/param.h>). After another thread has called “wakeup” on the desired event (specified by the value of chan), your code will begin executing at the specified priority. If the PCATCH flag is set on pri, signal handlers will be tried before and after the sleep.

Returns 0 if awakened with wakeup, EWOULDBLOCK on timeout expiry, and ERESTART or EINTR if PCATCH is set and a signal occurred, depending on whether the SA_RESTART flag is set on the signal.

wakeup

Defined in: <sys/proc.h>

Wakes all threads sleeping on a given channel through a call to “msleep”.

    void wakeup(void *chan);
 

wakeup_one

Defined in: <sys/proc.h>

Wakes the first thread sleeping on a given channel through a call to “msleep”.

    void wakeup_one(void *chan);