---
name: "HHOOKS_RUN_IF"
section: "9"
platform: "freebsd"
package: "base"
version: "16.0-CURRENT-20261027-61c70dc16a79"
release: "FreeBSD 16.0-CURRENT (2026-10-27)"
platforms: ["freebsd"]
url: "https://new.carta.tech/HHOOKS_RUN_IF"
---

# HHOOKS\_RUN\_IF(9)

Helper Hook Framework

## NAME

**hhook**, **hhook\_head\_register**, **hhook\_head\_deregister**, **hhook\_head\_deregister\_lookup**, **hhook\_run\_hooks**, **HHOOKS\_RUN\_IF**, **HHOOKS\_RUN\_LOOKUP\_IF** – Helper Hook Framework

## SYNOPSIS

**#include \<sys/hhook.h\>**

*typedef* *int*\

**\*hhook\_func\_t**(*int32\_t hhook\_type*, *int32\_t hhook\_id*, *void \*udata*, *void \*ctx\_data*, *void \*hdata*, *struct osd \*hosd*);

**int hhook\_head\_register**(*int32\_t hhook\_type*, *int32\_t hhook\_id*, *struct hhook\_head \*\*hhh*, *uint32\_t flags*);

**int hhook\_head\_deregister**(*struct hhook\_head \*hhh*);

**int hhook\_head\_deregister\_lookup**(*int32\_t hhook\_type*, *int32\_t hhook\_id*);

**void hhook\_run\_hooks**(*struct hhook\_head \*hhh*, *void \*ctx\_data*, *struct osd \*hosd*);

**HHOOKS\_RUN\_IF**(*hhh*, *ctx\_data*, *hosd*);

**HHOOKS\_RUN\_LOOKUP\_IF**(*hhook\_type*, *hhook\_id*, *ctx\_data*, *hosd*);

## DESCRIPTION

**hhook** provides a framework for managing and running arbitrary hook functions at defined hook points within the kernel. The KPI was inspired by [pfil(9)](/pfil/9.md), and in many respects can be thought of as a more generic superset of pfil.

The [khelp(9)](/khelp/9.md) and **hhook** frameworks are tightly integrated. Khelp is responsible for registering and deregistering Khelp module hook functions with **hhook** points. The KPI functions used by [khelp(9)](/khelp/9.md) to do this are not documented here as they are not relevant to consumers wishing to instantiate hook points.

### Information for Khelp Module Implementors

Khelp modules indirectly interact with **hhook** by defining appropriate hook functions for insertion into hook points. Hook functions must conform to the *hhook\_func\_t* function pointer declaration outlined in the SYNOPSIS.

The *hhook\_type* and *hhook\_id* arguments identify the hook point which has called into the hook function. These are useful when a single hook function is registered for multiple hook points and wants to know which hook point has called into it. ⟨sys/hhook.h⟩ lists available *hhook\_type* defines and subsystems which export hook points are responsible for defining the *hhook\_id* value in appropriate header files.

The *udata* argument will be passed to the hook function if it was specified in the *struct* *hookinfo* at hook registration time.

The *ctx\_data* argument contains context specific data from the hook point call site. The data type passed is subsystem dependent.

The *hdata* argument is a pointer to the persistent per-object storage allocated for use by the module if required. The pointer will only ever be NULL if the module did not request per-object storage.

The *hosd* argument can be used with the [khelp(9)](/khelp/9.md) framework's **khelp\_get\_osd**() function to access data belonging to a different Khelp module.

Khelp modules instruct the Khelp framework to register their hook functions with **hhook** points by creating a *struct hookinfo* per hook point, which contains the following members:

```
struct hookinfo {
	hhook_func_t	hook_func;
	struct helper	*hook_helper;
	void		*hook_udata;
	int32_t		hook_id;
	int32_t		hook_type;
};
```

Khelp modules are responsible for setting all members of the struct except *hook\_helper* which is handled by the Khelp framework.

### Creating and Managing Hook Points

Kernel subsystems that wish to provide **hhook** points typically need to make four and possibly five key changes to their implementation:

- Define a list of *hhook\_id* mappings in an appropriate subsystem header.

- Register each hook point with the **hhook\_head\_register**() function during initialisation of the subsystem.

- Select or create a standardised data type to pass to hook functions as contextual data.

- Add a call to **HHOOKS\_RUN\_IF**() or **HHOOKS\_RUN\_IF\_LOOKUP**() at the point in the subsystem's code where the hook point should be executed.

- If the subsystem can be dynamically added/removed at runtime, each hook point registered with the **hhook\_head\_register**() function when the subsystem was initialised needs to be deregistered with the **hhook\_head\_deregister**() or **hhook\_head\_deregister\_lookup**() functions when the subsystem is being deinitialised prior to removal.

The **hhook\_head\_register**() function registers a hook point with the **hhook** framework. The *hook\_type* argument defines the high level type for the hook point. Valid types are defined in ⟨sys/hhook.h⟩ and new types should be added as required. The *hook\_id* argument specifies a unique, subsystem specific identifier for the hook point. The *hhh* argument will, if not NULL, be used to store a reference to the *struct* *hhook\_head* created as part of the registration process. Subsystems will generally want to store a local copy of the *struct* *hhook\_head* so that they can use the **HHOOKS\_RUN\_IF**() macro to instantiate hook points. The HHOOK\_WAITOK flag may be passed in via the *flags* argument if [malloc(9)](/malloc/9.md) is allowed to sleep waiting for memory to become available. If the hook point is within a virtualised subsystem (e.g. the network stack), the HHOOK\_HEADISINVNET flag should be passed in via the *flags* argument so that the *struct* *hhook\_head* created during the registration process will be added to a virtualised list.

The **hhook\_head\_deregister**() function deregisters a previously registered hook point from the **hhook** framework. The *hhh* argument is the pointer to the *struct* *hhook\_head* returned by **hhoook\_head\_register**() when the hook point was registered.

The **hhook\_head\_deregister\_lookup**() function can be used instead of **hhook\_head\_deregister**() in situations where the caller does not have a cached copy of the *struct* *hhook\_head* and wants to deregister a hook point using the appropriate *hook\_type* and *hook\_id* identifiers instead.

The **hhook\_run\_hooks**() function should normally not be called directly and should instead be called indirectly via the **HHOOKS\_RUN\_IF**() macro. However, there may be circumstances where it is preferable to call the function directly, and so it is documented here for completeness. The *hhh* argument references the **hhook** point to call all registered hook functions for. The *ctx\_data* argument specifies a pointer to the contextual hook point data to pass into the hook functions. The *hosd* argument should be the pointer to the appropriate object's *struct* *osd* if the subsystem provides the ability for Khelp modules to associate per-object data. Subsystems which do not should pass NULL.

The **HHOOKS\_RUN\_IF**() macro is the preferred way to implement hook points. It only calls the **hhook\_run\_hooks**() function if at least one hook function is registered for the hook point. By checking for registered hook functions, the macro minimises the cost associated with adding hook points to frequently used code paths by reducing to a simple if test in the common case where no hook functions are registered. The arguments are as described for the **hhook\_run\_hooks**() function.

The **HHOOKS\_RUN\_IF\_LOOKUP**() macro performs the same function as the **HHOOKS\_RUN\_IF**() macro, but performs an additional step to look up the *struct* *hhook\_head* for the specified *hook\_type* and *hook\_id* identifiers. It should not be used except in code paths which are infrequently executed because of the reference counting overhead associated with the look up.

## IMPLEMENTATION NOTES

Each *struct* *hhook\_head* protects its internal list of hook functions with a [rmlock(9)](/rmlock/9.md). Therefore, anytime **hhook\_run\_hooks**() is called directly or indirectly via the **HHOOKS\_RUN\_IF**() or **HHOOKS\_RUN\_IF\_LOOKUP**() macros, a non-sleepable read lock will be acquired and held across the calls to all registered hook functions.

## RETURN VALUES

**hhook\_head\_register**() returns 0 if no errors occurred. It returns EEXIST if a hook point with the same *hook\_type* and *hook\_id* is already registered. It returns EINVAL if the HHOOK\_HEADISINVNET flag is not set in *flags* because the implementation does not yet support hook points in non-virtualised subsystems (see the BUGS section for details). It returns ENOMEM if [malloc(9)](/malloc/9.md) failed to allocate memory for the new *struct* *hhook\_head*.

**hhook\_head\_deregister**() and **hhook\_head\_deregister\_lookup**() return 0 if no errors occurred. They return ENOENT if *hhh* is NULL. They return EBUSY if the reference count of *hhh* is greater than one.

## EXAMPLES

A well commented example Khelp module can be found at: */usr/share/examples/kld/khelp/h\_example.c*

The [tcp(4)](/tcp/4.md) implementation provides two **hhook** points which are called for packets sent/received when a connection is in the established phase. Search for HHOOK in the following files: *sys/netinet/tcp\_var.h*, *sys/netinet/tcp\_input.c*, *sys/netinet/tcp\_output.c* and *sys/netinet/tcp\_subr.c*.

## SEE ALSO

[khelp(9)](/khelp/9.md)

## ACKNOWLEDGEMENTS

Development and testing of this software were made possible in part by grants from the FreeBSD Foundation and Cisco University Research Program Fund at Community Foundation Silicon Valley.

## HISTORY

The **hhook** framework first appeared in FreeBSD 9.0.

The **hhook** framework was first released in 2010 by Lawrence Stewart whilst studying at Swinburne University of Technology's Centre for Advanced Internet Architectures, Melbourne, Australia. More details are available at:

http://caia.swin.edu.au/urp/newtcp/

## AUTHORS

The **hhook** framework was written by Lawrence Stewart ⟨*lstewart@FreeBSD.org*⟩.

This manual page was written by David Hayes ⟨*david.hayes@ieee.org*⟩ and Lawrence Stewart ⟨*lstewart@FreeBSD.org*⟩.
