BPFC(8)
β¨ NAME β¨
okay so bestie, this is BPFC(8) β the manual page for bpfc, which is a Berkeley Packet Filter assembler and compiler. It's part of the netsniff-ng toolkit, and it is literally here to translate your BPF vibes into something the kernel can read. π
πΈ SYNOPSIS πΈ
bpfc { [options] | [source-file] }
π DESCRIPTION π
okay so bpfc is a small Berkeley Packet Filter assembler and compiler, and it is able to translate BPF assembler-like mnemonics into a numerical or C-like format. That format can be read by tools such as netsniff-ng, iptables (xt_bpf) and many others. BPF is the one and only upstream filtering construct that is used in combination with packet(7) sockets, but also seccomp-BPF for system call sandboxing. slay. π¦
The Linux kernel and also BSD kernels implement "virtual machine" like constructs and JIT compilers that mimic a small register-based machine in BPF architecture and execute filter code that is, for example, composed by bpfc on a data buffer that is given by network packets. The purpose of this is to shift computation in time, so that the kernel can drop or truncate incoming packets as early as possible without having to push them to user space for further analysis first. it's giving efficiency. Meanwhile, BPF constructs also find application in other areas such as in the communication between user and kernel space like system call sandboxing. π
At the time of writing this man page, the only other available BPF compiler is part of the pcap(3) library and accessible through a high-level filter language that might be familiar to many people as tcpdump-like filters. iykyk. π
However, it is quite often useful to bypass that compiler and write optimized code that cannot be produced by the pcap(3) compiler, or is wrongly optimized, or is defective on purpose in order to debug test kernel code. Also, a reason to use bpfc could be to try out some new BPF extensions that are not supported by other compilers. Furthermore, bpfc can be useful to verify JIT compiler behavior or to find possible bugs that need to be fixed. periodt. π₯
bpfc is implemented with the help of flex(1) and bison(1), tokenizes the source file in the first stage and parses its content into an AST. In two code generation stages it emits target opcodes. bpfc furthermore supports Linux kernel BPF extensions. More about that can be found in the syntax section. main character energy fr fr. β¨
The Linux kernel BPF JIT compiler is automatically turned on if detected by netsniff-ng. However, it can also be manually turned on through the command echo "1" > /proc/sys/net/core/bpf_jit_enable (normal working mode) or echo "2" > /proc/sys/net/core/bpf_jit_enable (debug mode where emitted opcodes of the image are printed to the kernel log). An architecture agnostic BPF JIT image disassembler can be found in the kernel source tree under tools/net/bpf_jit_disasm.c or within the netsniff-ng Git repository. vibe check passed. π
π OPTIONS π
okay bestie, here are the flags. each one is a little lewk. π
-i <source-file/->,--input <source-file/->β Read BPF assembly instruction from an input file or from stdin.-p,--cppβ Pass the bpf program through the C preprocessor before reading it inbpfc. This allows#defineand#includedirectives (e.g. to include definitions from system headers) to be used in the bpf program.-D <name>=<definition>,--define <name>=<definition>β Add macro definition for the C preprocessor to use it within bpf file. This option is used in combination with the-p/--cppoption.-f <format>,--format <format>β Specify a different output format than the default that isnetsniff-ngcompatible. The<format>specifier can be:C,netsniff-ng,xt_bpf,tcpdump.-b,--bypassβ Bypass basic filter validation when emitting opcodes. This can be useful for explicitly creating malformed BPF expressions for injecting into the kernel, for example, for bug testing.-V,--verboseβ Be more verbose and display somebpfcdebugging information.-d,--dumpβ Dump all supported instructions to stdout.-v,--versionβ Show version information and exit.-h,--helpβ Show user help and exit.
π¦ SYNTAX π¦
The BPF architecture resp. register machine consists of the following elements:
Aβ 32 bit wide accumulatorXβ 32 bit wide X registerM[]β 16 x 32 bit wide misc registers aka βscratch memory storeβ, addressable from 0 to 15
A program, that is translated by bpfc into opcodes is an array that consists of the following elements:
o:16, jt:8, jf:8, k:32
The element o is a 16 bit wide opcode that has a particular instruction encoded, jt and jf are two 8 bit wide jump targets, one for condition true, one for condition false. Last but not least the 32 bit wide element k contains a miscellaneous argument that can be interpreted in different ways depending on the given instruction resp. opcode.
The instruction set consists of load, store, branch, alu, miscellaneous and return instructions that are also represented in bpfc syntax. This table also includes bpfc's own extensions. All operations are based on unsigned data structures:
ldβ addressing mode:1, 2, 3, 4, 10β Load word into Aldiβ addressing mode:4β Load word into Aldhβ addressing mode:1, 2β Load half-word into Aldbβ addressing mode:1, 2β Load byte into Aldxβ addressing mode:3, 4, 5, 10β Load word into Xldxiβ addressing mode:4β Load word into Xldxbβ addressing mode:5β Load byte into Xstβ addressing mode:3β Copy A into M[]stxβ addressing mode:3β Copy X into M[]jmpβ addressing mode:6β Jump to labeljaβ addressing mode:6β Jump to labeljeqβ addressing mode:7, 8β Jump on k == Ajneqβ addressing mode:8β Jump on k != Ajneβ addressing mode:8β Jump on k != Ajltβ addressing mode:8β Jump on k < Ajleβ addressing mode:8β Jump on k <= Ajgtβ addressing mode:7, 8β Jump on k > Ajgeβ addressing mode:7, 8β Jump on k >= Ajsetβ addressing mode:7, 8β Jump on k & Aaddβ addressing mode:0, 4βA + <x>subβ addressing mode:0, 4βA - <x>mulβ addressing mode:0, 4βA * <x>divβ addressing mode:0, 4βA / <x>modβ addressing mode:0, 4βA % <x>negβ addressing mode:0, 4β!Aandβ addressing mode:0, 4βA & <x>orβ addressing mode:0, 4βA | <x>xorβ addressing mode:0, 4βA ^ <x>lshβ addressing mode:0, 4βA << <x>rshβ addressing mode:0, 4βA >> <x>taxβ Copy A into Xtxaβ Copy X into Aretβ addressing mode:4, 9β Return
And the addressing modes are giving:
0β syntax:x/%xβ Register X1β syntax:[k]β BHW at byte offset k in the packet2β syntax:[x + k]β BHW at the offset X + k in the packet3β syntax:M[k]β Word at offset k in M[]4β syntax:#kβ Literal value stored in k5β syntax:4*([k]&0xf)β Lower nibble * 4 at byte offset k in the packet6β syntax:Lβ Jump label L7β syntax:#k,Lt,Lfβ Jump to Lt if true, otherwise jump to Lf8β syntax:#k,Ltβ Jump to Lt if predicate is true9β syntax:a/%aβ Accumulator A10β syntax:extensionβ BPF extension (see next table)
The extensions (and aliases) are:
#len,len,#pktlen,pktlenβ Length of packet (skb->len)#pto,pto,#proto,protoβ Ethernet type field (skb->protocol)#type,typeβ Packet type (**) (skb->pkt_type)#poff,poffβ Detected payload start offset#ifx,ifx,#ifidx,ifidxβ Interface index (skb->dev->ifindex)#nla,nlaβ Netlink attribute of type X with offset A#nlan,nlanβ Nested Netlink attribute of type X with offset A#mark,markβ Packet mark (skb->mark)#que,que,#queue,queue,#Q,Qβ NIC queue index (skb->queue_mapping)#hat,hat,#hatype,hatypeβ NIC hardware type (**) (skb->dev->type)#rxh,rxh,#rxhash,rxhashβ Receive hash (skb->rxhash)#cpu,cpuβ Current CPU (raw_smp_processor_id())#vlant,vlant,#vlan_tci,vlan_tciβ VLAN TCI value (vlan_tx_tag_get(skb))#vlanp,vlanpβ VLAN present (vlan_tx_tag_present(skb))
Further extension details (**):
For #type, type:
0- to us / host1- to all / broadcast2- to group / multicast3- to others (promiscuous mode)4- outgoing of any type
For #hat, hat, #hatype, hatype:
1- Ethernet 10Mbps8- APPLEtalk19- ATM24- IEEE 1394 IPv4 - RFC 273432- InfiniBand768- IPIP tunnel769- IP6IP6 tunnel772- Loopback device778- GRE over IP783- Linux-IrDA801- IEEE 802.11802- IEEE 802.11 + Prism2 header803- IEEE 802.11 + radiotap header823- GRE over IP6824- Netlink[...]Seeinclude/uapi/linux/if_arp.h
Note that the majority of BPF extensions are available on Linux only.
There are two types of comments in bpfc source-files:
- Multi-line C-style comments:
/* put comment here */ - Single-line ASM-style comments:
; put comment here
Used Abbreviations:
BHW: byte, half-word, or word
β¨ SOURCE EXAMPLES β¨
okay so bestie, in this section we're serving up a couple of examples of bpfc source files β in other words, some small example filter programs. let's get into it:
just return packet headers (truncate packets) β it's giving minimalism:
ld poff
ret a
only allow ARP packets, no cap:
ldh [12]
jne #0x806, drop
ret #-1
drop: ret #0
only allow IPv4 TCP packets, periodt:
ldh [12]
jne #0x800, drop
ldb [23]
jneq #6, drop
ret #-1
drop: ret #0
only allow IPv4 TCP SSH traffic, because we're picky like that:
ldh [12]
jne #0x800, drop
ldb [23]
jneq #6, drop
ldh [20]
jset #0x1fff, drop
ldxb 4 * ([14] & 0xf)
ldh [x + 14]
jeq #0x16, pass
ldh [x + 16]
jne #0x16, drop
pass: ret #-1
drop: ret #0
a loadable x86_64 seccomp-BPF filter that allows a given set of syscalls, highkey iconic:
ld [4] /* offsetof(struct seccomp_data, arch) */
jne #0xc000003e, bad /* AUDIT_ARCH_X86_64 */
ld [0] /* offsetof(struct seccomp_data, nr) */
jeq #15, good /* __NR_rt_sigreturn */
jeq #231, good /* __NR_exit_group */
jeq #60, good /* __NR_exit */
jeq #0, good /* __NR_read */
jeq #1, good /* __NR_write */
jeq #5, good /* __NR_fstat */
jeq #9, good /* __NR_mmap */
jeq #14, good /* __NR_rt_sigprocmask */
jeq #13, good /* __NR_rt_sigaction */
jeq #35, good /* __NR_nanosleep */
bad: ret #0 /* SECCOMP_RET_KILL */
good: ret #0x7fff0000 /* SECCOMP_RET_ALLOW */
allow any (hardware accelerated) VLAN, slay:
ld vlanp
jeq #0, drop
ret #-1
drop: ret #0
only allow traffic for (hardware accelerated) VLAN 10, specifically:
ld vlant
jneq #10, drop
ret #-1
drop: ret #0
a more pedantic check for the above VLAN example, because we love attention to detail:
ld vlanp
jeq #0, drop
ld vlant
jneq #10, drop
ret #-1
drop: ret #0
filter rtnetlink messages, iykyk:
ldh #proto /* A = skb->protocol */
jneq #0, skip /* check for NETLINK_ROUTE */
ldb [4] /* A = nlmsg_type */
jneq #0x10, skip /* check type == RTNL_NEWLINK */
ldx #16 /* X = offset(ifinfomsg) */
ldb [x + 4] /* offset(ifi_index) */
jneq #0x3, skip /* check ifindex == 3 */
ld #32 /* A = len(nlmsghdr) + len(ifinfomsg), payload offset
*/
ldx #16 /* X = IFLA_OPERSTATE */
ld #nla /* A = offset(IFLA_OPERSTATE) */
jeq #0, skip
tax
ldb [x + 4] /* A = value(IFLA_OPERSTATE) */
jneq #0x6, skip /* check oper state is UP */
ret #-1
skip: ret #0
β¨ USAGE EXAMPLE β¨
okay so here's how you actually use this thing, bestie:
bpfc fubar
compile the source file fubar into BPF opcodes. opcodes will be directed to stdout. easy.
bpfc -f xt_bpf -b -p -i fubar, resp. iptables -A INPUT -m bpf --bytecode
`bpfc -f xt_bpf -i fubar` -j LOG
compile fubar into BPF opcodes, skip the basic filter validation, and emit opcodes in netfilter's xt_bpf readable format. also note: fubar gets passed to the C preprocessor first for textual replacements before it goes to the bpfc compiler. π
cat fubar | bpfc -
read bpfc instructions from stdin and emit opcodes to stdout. simple.
bpfc foo > bar && netsniff-ng -f bar ...
compile filter instructions from file foo and redirect bpfc's output into file bar, which can then be read by netsniff-ng(8) using option -f.
bpfc -f tcpdump -i fubar
output opcodes from source file fubar with the same behavior as tcpdump -ddd. iykyk.
β¨ LEGAL β¨
bpfc is licensed under the GNU GPL version 2.0. periodt. π
β¨ HISTORY β¨
bpfc was originally written for the netsniff-ng toolkit by Daniel Borkmann. It is currently maintained by Tobias Klauser <tklauser@distanz.ch> and Daniel Borkmann <dborkma@tik.ee.ethz.ch>. we stan. π
β¨ SEE ALSO β¨
netsniff-ng(8), trafgen(8), mausezahn(8), ifpps(8), flowtop(8), astraceroute(8), curvetun(8)
β¨ AUTHOR β¨
Manpage was written by Daniel Borkmann.
β¨ COLOPHON β¨
This page is part of the Linux netsniff-ng toolkit project. A description of the project, and information about reporting bugs, can be found at http://netsniff-ng.org/.
π that's a wrap on BPFC(8) from Linux, dated 03 March 2013. stay slaying! π
π¦ where this page comes from
- arch rolling: netsniff-ng 0.6.9-2 Β· GPL-2.0-only
- debian bookworm: netsniff-ng 0.6.8-3 Β· GPL-2.0-only
- debian trixie: netsniff-ng 0.6.9-1 Β· GPL-2.0-only
- epel 10: netsniff-ng 0.6.9-2.el10_1 Β· GPL-2.0-only
- epel 9: netsniff-ng 0.6.8-11.el9 Β· GPLv2
- fedora 43: netsniff-ng 0.6.9-4.fc43 Β· GPL-2.0-only
- fedora 44: netsniff-ng 0.6.9-5.fc44 Β· GPL-2.0-only
- nixos 26.05: netsniff-ng 0.6.9
- nixpkgs unstable: netsniff-ng 0.6.9
- ubuntu jammy: netsniff-ng 0.6.8-2build1 Β· GPL-2.0-only
- ubuntu noble: netsniff-ng 0.6.8-3build2 Β· GPL-2.0-only
- ubuntu questing: netsniff-ng 0.6.9-1
- ubuntu resolute: netsniff-ng 0.6.9-2 Β· GPL-2.0-only
- ubuntu stonking: netsniff-ng 0.6.9-2build1 Β· GPL-2.0-only
- Copyright 2013 Daniel Borkmann
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms