DUMMYMBUF(4)

πŸ“¦ version 15.1, in freebsd 15.1, nixpkgs unstable

πŸ’… DUMMYMBUF πŸ’…

okay bestie, buckle up β€” this is the manual page for dummymbuf, aka the mbuf alteration pfil hooks module, and honestly it's giving mad-scientist energy in the best way πŸ§ͺ✨


✨ SYNOPSIS ✨

So like, if you wanna compile this driver into the kernel, drop this line in your kernel configuration file:

device dummymbuf

Or, bestie, if you'd rather load it as a module at boot time, put this in loader.conf(5) instead:

dummymbuf_load="YES"

πŸ¦‹ DESCRIPTION πŸ¦‹

Okay so what does this thing even do? This module exists to test networking code when it's faced with unusual mbuf layouts β€” like, we're out here stress-testing the network stack with weird vibes and I'm obsessed. It hands you special pfil(9) hooks made for mbuf alteration, and you can list them all with pfilctl(8) like this:

  • dummymbuf:ethernet β€” Type: Ethernet
  • dummymbuf:inet6 β€” Type: IPv6
  • dummymbuf:inet β€” Type: IPv4

To actually activate a hook you gotta link it to the respective pfil(9) head β€” that's literally what pfilctl(8) is for, no cap.

Every single time a hook gets invoked it reads one shared set of β€œRULES” from the net.dummymbuf.rules sysctl. The rules get evaluated sequentially, and each matching rule performs the specified operation over the mbuf. Slay.

After every successfully applied operation, the net.dummymbuf.hits sysctl counter goes up by one πŸ’–

A hook returns an altered mbuf for further processing β€” but heads up, it drops the packet if rules parsing fails or if an operation fails 😭. Also important: the first mbuf of the original chain may be changed. Not a drill.

The module is VNET(9) based, so every jail(2) gets its own set of hooks and sysctl variables. Very main character energy, every jail gets its own little world 🫢


🌸 RULES 🌸

The set of rules is a semicolon separated list. An empty string is treated as a parsing failure (rude, but okay πŸ’€). A rule conceptually has two parts β€” filter and operation β€” with this exact syntax:

{inet | inet6 | ethernet} {in | out} <ifname> <opname>[ <opargs>];

Filter

The first word of a rule matches pfil(9) type. The second matches the packet's direction. And the third matches the network interface a packet is coming from. Three little words, doing all that ✨

Operation

An operation may have arguments, separated from its name by a space. Here's what's on the menu:

  • pull-head <number-of-bytes> β€” Unconditionally creates a brand new cluster-based mbuf and links it to be the first mbuf of the original mbuf chain, with the respective packet header moving. After that, the given number of bytes are pulled from the original mbuf chain.

If it's asked to pull 0 bytes then the first mbuf of the resulting chain will be left empty πŸ«₯. Asking to pull more than MCLBYTES is treated as an operation failure. And if an mbuf chain has less data than asked, then the entire packet is pulled with tail mbuf(s) left empty.

As a result, only the layout of an mbuf chain is altered β€” its content logically is left intact. It's giving "renovated the house but didn't move the furniture" πŸ›‹οΈ

  • enlarge <number-of-bytes> β€” Unconditionally replace the mbuf with an mbuf of the specified size.

πŸŽ€ SYSCTL VARIABLES πŸŽ€

The following variables are available:

  • net.dummymbuf.rules β€” A string representing a single set of β€œRULES” shared among all dummymbuf hooks. One ruleset to rule them all πŸ‘‘
  • net.dummymbuf.hits β€” Number of times a rule has been applied. It is reset to zero upon writing.

πŸ”₯ EXAMPLES πŸ”₯

As it was intended, dummymbuf can be found useful for firewall testing β€” and honestly that's where it eats. A mbuf chain could be altered before it hits a firewall, so you can test that the firewall can handle a case respectively. Which means... it is important to have the correct sequence of hooks. A test case should prepare and enable a firewall first to get its hooks linked. After that, the pfilctl(8) should be used to link dummymbuf hook(s) to put them in front of a firewall. Order matters, bestie, fr fr.

The following links dummymbuf:inet6 hook for inbound and puts it in front of other hooks:

pfilctl link -i dummymbuf:inet6 inet6

And this does the same for outbound:

pfilctl link -o -a dummymbuf:inet6 inet6

So for instance, we want to test a scenario in which the very first mbuf in a chain has zero m_len, to verify that a firewall can correctly read the packet data despite that. The following set of rules does it for inbound and outbound:

sysctl net.dummymbuf.rules="inet6 in em0 pull-head 0; inet6 out em0 pull-head 0;"
It is encouraged to verify the net.dummymbuf.hits sysctl counter along with other test assertions to make sure that dummymbuf really does its work and there is no false positive due to misconfiguration πŸ™ˆ It's a good idea to reset it before the action:
sysctl net.dummymbuf.hits=0

It is equally important to cleanup the things after the test case 🧹✨

pfilctl unlink -i dummymbuf:inet6 inet6
pfilctl unlink -o dummymbuf:inet6 inet6
sysctl net.dummymbuf.rules=""

And if a test case operates within a temporary vnet, then explicit cleanup can be omitted β€” the dummymbuf facilities will vanish along with its vnet instance. Poof, gone, iconic πŸ’¨


πŸ’€ DIAGNOSTICS πŸ’€

  • dummymbuf: <filter match>: rule parsing failed: <the rule in question> β€” If everything looks fine then extra spaces removal may help, because the parser is kept very simple. Like, very simple. It's not beating the "simple parser" allegations 😭
  • dummymbuf: <filter match>: mbuf operation failed: <the rule in question> β€” Incorrect operation argument has been found, mbuf allocation has failed, etc.

🌈 SEE ALSO 🌈

jail(2), pfilctl(8), mbuf(9), pfil(9), VNET(9)


πŸ‘‘ AUTHORS πŸ‘‘

The module and this manual page were written by Igor Ostapenko <pm@igoro.pro>. Thank you for your service, king πŸ«‘πŸ’œ


k that's the whole page bestie β€” mwah πŸ’‹ this one shipped from Debian, dated January 6, 2025, and yes that's the same date as DUMMYMBUF(4) because we keep it πŸ’― accurate around here. go forth and alter some mbufs πŸ¦‹βœ¨

πŸ“¦ where this page comes from