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

# pfil(9)

packet filter interface

## NAME

**pfil**, **pfil\_head\_register**, **pfil\_head\_unregister**, **pfil\_link**, **pfil\_run\_hooks** – packet filter interface

## SYNOPSIS

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

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

**#include \<net/pfil.h\>**

*pfil\_head\_t*\

**pfil\_head\_register**(*struct pfil\_head\_args \*args*);

*void*\

**pfil\_head\_unregister**(*struct pfil\_head\_t \*head*);

*pfil\_hook\_t*\

**pfil\_add\_hook**(*struct pfil\_hook\_args \**);

*void*\

**pfil\_remove\_hook**(*pfil\_hook\_t*);

*int*\

**pfil\_link**(*struct pfil\_link\_args \*args*);

*int*\

**pfil\_run\_hooks**(*phil\_head\_t \**, *pfil\_packet\_t*, *struct ifnet \**, *int*, *struct inpcb \**);

## DESCRIPTION

The **pfil** framework allows for a specified function or a list of functions to be invoked for every incoming or outgoing packet for a particular network I/O stream. These hooks may be used to implement a firewall or perform packet transformations.

Packet filtering points, for historical reasons named *heads*, are registered with **pfil\_head\_register**(). The function is supplied with special versioned *struct* *pfil\_head\_args* structure that specifies type and features of the head as well as human readable name. If the filtering point to be ever destroyed, the subsystem that created it must unregister it with call to **pfil\_head\_unregister**().

Packet filtering systems may register arbitrary number of filters, for historical reasons named *hooks*. To register a new hook **pfil\_add\_hook**() with special versioned *struct* *pfil\_hook\_args* structure is called. The structure specifies type and features of the hook, pointer to the actual filtering function and user readable name of the filtering module and ruleset name. Later hooks can be removed with **pfil\_remove\_hook**() functions.

To connect existing *hook* to an existing *head* function **pfil\_link**() shall be used. The function is supplied with versioned *struct* *pfil\_link\_args* structure that specifies either literal names of hook and head or pointers to them. Typically **pfil\_link**() is called by filtering modules to autoregister their default ruleset and default filtering points. It also serves on the kernel side of [ioctl(2)](/ioctl/2.md) when user changes **pfil** configuration with help of [pfilctl(8)](/pfilctl/8.md) utility.

For every packet traveling through a *head* the latter shall invoke **pfil\_run\_hooks**(). The function can accept either *struct* *mbuf* *\** pointer or a *void* *\** pointer and length. In case if a hooked filtering module cannot understand *void* *\** pointer **pfil** will provide it with a fake one. All calls to **pfil\_run\_hooks**() are performed in network [epoch(9)](/epoch/9.md).

## HEADS (filtering points)

By default kernel creates the following heads:

- inet

  IPv4 packets.

- inet6

  IPv6 packets.

- ethernet

  Link-layer packets.

Default rulesets are automatically linked to these heads to preserve historical behaviour.

## SEE ALSO

[ipfilter(4)](/ipfilter/4.md), [ipfw(4)](/ipfw/4.md), [pf(4)](/pf/4.md), [pfilctl(8)](/pfilctl/8.md)

## HISTORY

The **pfil** interface first appeared in NetBSD 1.3. The **pfil** interface was imported into FreeBSD 5.2. In FreeBSD 13.0 the interface was significantly rewritten.
