Files
pf-linux-port/tools/Makefile
T
lgcosta 5323ee2c71 M2: live netfilter data path (pf_test per direction), pfattach bring-up, NET_LOCK reentrancy fix, static pfctl
- pfk_hooks: PRE→PF_IN, LOCAL_OUT/POST→PF_OUT v4+v6; replacement/buffer
  handling with NF_STOLEN + re-injection (documented divergence: re-entry)
- pfk_mod: pf_status_init/pfattach + pfi attach via pfk_if event callback
- pfk_kern: NET_LOCK holder reentrancy (fix deadlock when notifier fires
  under the write lock — observed as full-VM network hang)
- tools: static pfctl link for musl VMs
2026-11-11 15:20:01 -03:00

181 lines
6.5 KiB
Makefile

LDFLAGS ?= -static
# PFLINUX — build OpenBSD 8.0 pfctl userland for Linux.
#
# Layout:
# include/ compat headers (sys/ioctl.h with OpenBSD _IO encoding,
# net/{route,if,if_dl}.h, netinet/tcp_fsm.h, md5.h, ...)
# plus copies generated at build time:
# include/net/pfvar.h <- ../module/include/net/pfvar.h
# include/sys/{queue,tree}.h, include/net/{radix,hfsc,
# fq_codel}.h <- ../_vendor/upstream/sys/...
# pfctl/ pristine OpenBSD 8.0 sbin/pfctl sources + marked edits
# compat-user/ glibc missing pieces (sysctl, strtonum, md5, tcpstates)
# abitest/ ABI struct layout table (built twice: tools/include and
# module/include, compared, MD5-verified)
# out/ build products (make clean removes)
#
# Contract: `make -C tools` must work with plain make/gcc/bison.
TOP := $(abspath $(dir $(lastword $(MAKEFILE_LIST))))
ROOT := $(abspath $(TOP)/..)
MODULE := $(ROOT)/module
VENDOR := $(ROOT)/_vendor/upstream
SRC := $(TOP)/pfctl
COMPAT := $(TOP)/compat-user
INC := $(TOP)/include
OUT := $(TOP)/out
OBJ := $(OUT)/obj
GEN := $(OUT)/gen
CC ?= cc
BISON ?= bison
# PFLINUX: include order is ABI-critical. $(INC) first so sys/ioctl.h
# (OpenBSD PFKXIOC encoding, identical to module/include/pfk.h),
# net/pfvar.h, sys/{queue,tree}.h, net/{route,if,if_dl}.h,
# netinet/tcp_fsm.h and md5.h shadow the Linux system headers.
# pflinux_compat.h is force-included (attribute macros, strtonum,
# strings.h) before any source's own #includes.
CPPFLAGS += -I$(INC) -I$(GEN) -include $(INC)/pflinux_compat.h
CFLAGS ?= -O2 -g
CFLAGS += -std=gnu17 -Wall -D_GNU_SOURCE
LDLIBS += -lm
# Headers copied verbatim at build time (never edited; single source of
# truth stays in module/ and _vendor/).
GENHDRS := $(INC)/net/pfvar.h $(INC)/net/radix.h $(INC)/net/hfsc.h \
$(INC)/net/fq_codel.h $(INC)/sys/tree.h $(INC)/sys/queue.h
PF_SRCS := pfctl.c pfctl_parser.c pf_print_state.c pfctl_table.c \
pfctl_queue.c pfctl_radix.c pfctl_osfp.c pfctl_optimize.c
CB_SRCS := sysctl.c strtonum.c bsd.c md5.c rbtree.c inet_net_pton.c
PF_OBJS := $(addprefix $(OBJ)/,$(PF_SRCS:.c=.o)) $(OBJ)/parse.o
CB_OBJS := $(addprefix $(OBJ)/,$(CB_SRCS:.c=.o))
GOODTESTS := tests/01_basic.conf tests/02_translations.conf \
tests/03_queues_scrub.conf
.PHONY: all pfctl abitest test abi clean
all: pfctl abitest
pfctl: $(OUT)/pfctl
# ---------------------------------------------------------------------------
# generated (copied) headers
# ---------------------------------------------------------------------------
# Contract: userland MUST use the exact kernel-side ABI header.
$(INC)/net/pfvar.h: $(MODULE)/include/net/pfvar.h
@mkdir -p $(@D)
@cmp -s $< $@ || cp -f $< $@
$(INC)/net/radix.h: $(VENDOR)/sys/net/radix.h
@mkdir -p $(@D)
@cmp -s $< $@ || cp -f $< $@
$(INC)/net/hfsc.h: $(VENDOR)/sys/net/hfsc.h
@mkdir -p $(@D)
@cmp -s $< $@ || cp -f $< $@
$(INC)/net/fq_codel.h: $(VENDOR)/sys/net/fq_codel.h
@mkdir -p $(@D)
@cmp -s $< $@ || cp -f $< $@
$(INC)/sys/tree.h: $(VENDOR)/sys/sys/tree.h
@mkdir -p $(@D)
@cmp -s $< $@ || cp -f $< $@
$(INC)/sys/queue.h: $(VENDOR)/sys/sys/queue.h
@mkdir -p $(@D)
@cmp -s $< $@ || cp -f $< $@
# ---------------------------------------------------------------------------
# grammar: OpenBSD pfctl has a hand-written lexer inside parse.y; only
# bison is required (flex is NOT used).
# ---------------------------------------------------------------------------
$(GEN)/parse.c: $(SRC)/parse.y $(GENHDRS)
@mkdir -p $(GEN)
$(BISON) -d -o $@ $<
$(OBJ)/%.o: $(SRC)/%.c $(GENHDRS)
@mkdir -p $(OBJ)
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
$(OBJ)/parse.o: $(GEN)/parse.c $(SRC)/pfctl.h $(SRC)/pfctl_parser.h
@mkdir -p $(OBJ)
$(CC) $(CPPFLAGS) $(CFLAGS) -I$(SRC) -c $< -o $@
$(OBJ)/%.o: $(COMPAT)/%.c $(GENHDRS)
@mkdir -p $(OBJ)
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
# PFLINUX: OpenBSD 8.0 pfctl links the kernel's pf_ruleset.c userland
# branch ("Effort sponsored... Userland equivalents so we can lend code
# to pfctl") for anchor/ruleset management (pf_anchor_setup,
# pf_find_or_create_ruleset, pf_main_anchor, ...). Compiled straight
# from _vendor, unmodified.
$(OBJ)/pf_ruleset.o: $(VENDOR)/sys/net/pf_ruleset.c $(GENHDRS)
@mkdir -p $(OBJ)
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
$(OUT)/pfctl: $(PF_OBJS) $(CB_OBJS) $(OBJ)/pf_ruleset.o
@mkdir -p $(OUT)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(PF_OBJS) $(CB_OBJS) $(OBJ)/pf_ruleset.o $(LDLIBS)
# ---------------------------------------------------------------------------
# ABI table: same abitest.c compiled twice —
# out/abitest : headers from tools/include (copied pfvar.h)
# out/abitest-module : tools/include shims but net/pfvar.h taken directly
# from ../module/include (kernel ABI header)
# The two tables must be byte-identical (proof: MD5 over the table).
# The kernel-module-side check (structs compiled with the real kernel
# compat headers under -D_KERNEL) is done separately by the integrator.
# ---------------------------------------------------------------------------
abitest: $(OUT)/abitest $(OUT)/abitest-module
$(OBJ)/abitest-user.o: $(TOP)/abitest/abitest.c $(GENHDRS)
@mkdir -p $(OBJ)
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
$(OBJ)/abitest-module.o: $(TOP)/abitest/abitest.c $(GENHDRS)
@mkdir -p $(OBJ)
$(CC) -I$(MODULE)/include $(CPPFLAGS) $(CFLAGS) -c $< -o $@
$(OUT)/abitest: $(OBJ)/abitest-user.o $(OBJ)/md5.o
@mkdir -p $(OUT)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)
$(OUT)/abitest-module: $(OBJ)/abitest-module.o $(OBJ)/md5.o
@mkdir -p $(OUT)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)
abi: abitest
@$(OUT)/abitest > $(OUT)/abi-tools.tbl
@$(OUT)/abitest-module > $(OUT)/abi-module.tbl
@diff -u $(OUT)/abi-tools.tbl $(OUT)/abi-module.tbl && \
echo "ABI OK: identical tables"
@tail -n 1 $(OUT)/abi-tools.tbl
# ---------------------------------------------------------------------------
# offline (-n) parse validation, no /dev/pf required
# ---------------------------------------------------------------------------
test: $(OUT)/pfctl
@ok=1; for c in $(GOODTESTS); do \
if $(OUT)/pfctl -n -f $$c >/dev/null 2>&1; then \
echo "PASS $$c (exit 0)"; \
else \
echo "FAIL $$c (exit $$?)"; ok=0; \
fi; \
done; \
if $(OUT)/pfctl -n -f tests/broken.conf >/dev/null 2>&1; then \
echo "FAIL tests/broken.conf accepted"; ok=0; \
else \
echo "PASS tests/broken.conf rejected (non-zero exit)"; \
fi; \
test $$ok -eq 1
clean:
rm -rf $(OUT)
rm -f $(GENHDRS)