/* * PF-on-Linux: master compatibility header (pfk). * * Every ported OpenBSD file includes INSTEAD of the original * #include block. pfk.h pulls Linux headers first, then provides the * OpenBSD-flavored types/APIs the PF code expects, so the ported logic * stays line-proximate to upstream (ISC, (c) 2026 PF-on-Linux contributors; * ported code: OpenBSD project, see LICENSE). */ #ifndef _PFK_H #define _PFK_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* ------------------------------------------------------------ basic types */ #ifndef u_int8_t typedef __u8 u_int8_t; #endif #ifndef u_int16_t typedef __u16 u_int16_t; #endif #ifndef u_int32_t typedef __u32 u_int32_t; #endif #ifndef u_int64_t typedef __u64 u_int64_t; #endif #ifndef u64 typedef __u64 u64; #endif #ifndef u_int typedef unsigned int u_int; #endif #ifndef u_char typedef unsigned char u_char; #endif /* caddr_t/time_t/timeval: kernel provides caddr_t; BSD time types below */ #ifndef u_short typedef unsigned short u_short; #endif typedef __be16 pf_in_port_t; typedef __be32 pf_in_addr_t; /* uapi linux/in6.h already provides s6_addr/s6_addr16/s6_addr32 macros * matching OpenBSD usage on the same union layout. */ /* roundup/MIN/MAX/rounddown/NULL/PTR_ALIGN are already provided by the * Linux kernel headers — use those. BSD-only extras kept under unique names. */ #define roundup2(x, y) (((x)+((y)-1))&(~((y)-1))) #define howmany(x, y) (((x)+((y)-1))/(y)) #define MINIMUM(a, b) (((a) < (b)) ? (a) : (b)) #define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b)) #define PFK_PTR_ALIGN(p) ((caddr_t)(((unsigned long)(p) + 3) & ~3UL)) #define P2ALIGN(x, y) ((x) & -(y)) /* OpenBSD rwlock name; the kernel has its own debug `struct rwlock`, so the * BSD-visible struct is pfk_rwlock + alias macro (no further kernel headers * are included after pfk.h, so the alias cannot leak). */ struct pfk_rwlock { struct rw_semaphore sem; const char *name; int is_writer; atomic_t readers; }; #define rwlock pfk_rwlock #define rwlock_s pfk_rwlock /* OpenBSD ioctl encoding: OUR kernel-side and our Linux pfctl use EXACTLY * these macros so _IOR/_IOW direction bits stay bit-compatible with * OpenBSD (Linux asm/ioctl.h differs). Ported TUs must include NO further * kernel headers after pfk.h (see porting-notes). */ #undef _IO #undef _IOR #undef _IOW #undef _IOWR #define PFKXIOC_NRBITS 8 #define PFKXIOC_TYPEBITS 8 #define PFKXIOC_SIZEBITS 13 #define PFKXIOC_DIRBITS 2 #define PFKXIOC_NRSHIFT 0 #define PFKXIOC_TYPESHIFT (PFKXIOC_NRSHIFT + PFKXIOC_NRBITS) #define PFKXIOC_SIZESHIFT (PFKXIOC_TYPESHIFT + PFKXIOC_TYPEBITS) #define PFKXIOC_DIRSHIFT (PFKXIOC_SIZESHIFT + PFKXIOC_SIZEBITS + 1) #define PFKXIOC_NONE 0U #define PFKXIOC_WRITE 1U /* OpenBSD IOC_IN (copyin) */ #define PFKXIOC_READ 2U /* OpenBSD IOC_OUT (copyout) */ #define PFKXIOC(dir,type,nr,size) \ (((dir) << PFKXIOC_DIRSHIFT) | ((type) << PFKXIOC_TYPESHIFT) | \ ((nr) << PFKXIOC_NRSHIFT) | ((size) << PFKXIOC_SIZESHIFT)) #define _IO(t, n) PFKXIOC(PFKXIOC_NONE, (t), (n), 0) #define _IOWR(t, n, s) PFKXIOC(PFKXIOC_WRITE|PFKXIOC_READ, (t), (n), sizeof(s)) #define _IOW(t, n, s) PFKXIOC(PFKXIOC_WRITE, (t), (n), sizeof(s)) #define _IOR(t, n, s) PFKXIOC(PFKXIOC_READ, (t), (n), sizeof(s)) #define PFKIOC_TYPE(nr) (((nr) >> PFKXIOC_TYPESHIFT) & ((1U<> PFKXIOC_NRSHIFT) & ((1U<> PFKXIOC_DIRSHIFT) & ((1U< → resolves to the kernel's net/route.h; * BSD-only bits it expects must be provided here. */ #define RTLABEL_LEN 32 /* syslog levels (BSD numbering == Linux numbering for these) */ #define LOG_EMERG 0 #define LOG_ALERT 1 #define LOG_CRIT 2 #define LOG_ERR 3 #define LOG_WARNING 4 #define LOG_NOTICE 5 #define LOG_INFO 6 #define LOG_DEBUG 7 void pfk_log(int level, const char *fmt, ...); #define log pfk_log #define printf pfk_printk_compat int pfk_printk_compat(const char *fmt, ...); #define panic(x...) do { pr_emerg("pfk panic: " x); BUG(); } while (0) /* time */ typedef long time_t; struct timeval { long tv_sec; long tv_usec; }; /* BSD layout (uapi may clash) */ static inline __u64 pfk_time_sec(void) { return ktime_get_seconds(); } static inline __u64 pfk_time_ms(void) { return ktime_get_ns() / 1000000ULL; } struct pfk_timeval { __s64 tv_sec; __s64 tv_usec; }; static inline void pfk_getmicrotime(struct pfk_timeval *tv) { struct timespec64 ts; ktime_get_real_ts64(&ts); tv->tv_sec = ts.tv_sec; tv->tv_usec = ts.tv_nsec / 1000; } static inline __s64 pfk_ntptime_delta(void) { return 0; } /* PFLINUX: ntpd adj not modeled */ /* MALLOC / pool */ #define M_TEMP 0x10000 #define M_PF 0x10001 #define M_DEVBUF 0x10002 #define M_IFADDR 0x10003 #define M_PFX 0x10004 #define M_TAG 0x10005 #define M_PFADDR 0x10006 #define M_PFRWP 0x10007 #define M_PFTOC 0x10008 #define M_PFRTABLE 0x10009 #define M_IFMADDR 0x1000a #define M_PFXSRC 0x1000b #define M_ZOMBIE 0x1000c #define M_PCR 0x1000d #define M_PRoute 0x1000e #define M_NOWAIT 0x01 #define M_WAITOK 0x02 #define M_CANFAIL 0x04 #define M_ZERO 0x08 void *pfk_malloc(size_t sz, int flags); void pfk_free(void *p); #define malloc(sz, t, f) pfk_malloc((sz), (f)) #define free(p, t) pfk_free(p) /* * pools: struct pool backed by kmem_cache when size fixed (pool_init), * lazily created on first get for simplicity of many small pools. */ struct pool { struct kmem_cache *slab; size_t p_size; int p_flags; /* PR_WAITOK semantics via M_* on init */ unsigned long p_alloc; unsigned long p_used; unsigned long p_hardlimit; struct list_head p_objects; /* for zeroed reuse semantics if needed */ }; #define PR_WAITOK 0x01 #define PR_NOWAIT 0x02 #define PR_ZERO 0x08 struct srcptr_static { const char *file; int line; }; #define SRCPOINT() (&(struct srcptr_static){__FILE__, __LINE__}) int pool_init(struct pool *pl, size_t size, int align, int ipl, const char *use, void *p, int flags, void (*ih)(void *, void *), void *arg, struct srcptr_static *sp); void pool_destroy(struct pool *pl); void *pool_get(struct pool *pl, int flags); void pool_put(struct pool *pl, void *v); void pool_sethardlimit(struct pool *pl, unsigned long lim, const char *msg, int msglevel); /* timeout.h: OpenBSD embeds `struct timeout` in statics/globals → fixed layout */ #include "compat/sys/timeout.h" void timeout_set(struct timeout *to, timeout_fn *fn, void *arg); void timeout_set_micro(struct timeout *to, timeout_fn *fn, void *arg); int timeout_add(struct timeout *to, long ms); int timeout_add_sec(struct timeout *to, int secs); int timeout_add_usec(struct timeout *to, int us); int timeout_del(struct timeout *to); void timeout_barrier(struct timeout *to, int flags); void timeout_del_sync(struct timeout *to); int timeout_pending(struct timeout *to); int tsleep(void *p, int pr, const char *w, int timo); /* PFLINUX: control-path only */ #define wakeup pfk_wakeup void pfk_wakeup(void *p); /* refcnt.h */ #include "compat/sys/refcnt.h" /* rnd / random */ static inline u_int32_t arc4random(void) { return get_random_u32(); } static inline void arc4random_buf(void *b, size_t l) { get_random_bytes(b, l); } static inline u_int32_t arc4random_uniform(u_int32_t n) { return get_random_u32_below(n); } static inline u_int32_t rnd(void) { return get_random_u32(); } static inline u_int32_t random(void) { return get_random_u32(); } #define karc4random() get_random_u32() #define karc4random_uniform(n) get_random_u32_below(n) /* copyin/copyout */ #define copyin(u, k, l) (copy_from_user((k), (u), (l)) ? EFAULT : 0) #define copyout(k, u, l) (copy_to_user((u), (k), (l)) ? EFAULT : 0) /* assert-ish */ #define KASSERT(cond) WARN_ON(!(cond)) #define __arraycount(a) (sizeof(a) / sizeof((a)[0])) #define __predictfalse(x) unlikely(x) #define __predicttrue(x) likely(x) #define __predict(x, y) ((y) ? likely(x) : unlikely(x)) #define __UNCONST(a) ((void *)(unsigned long)(const void *)(a)) /* NET_LOCK: OpenBSD global network rwlock. PF data path runs under NET_READ; * ioctls take NET_LOCK (write). We map to a global rw_semaphore. */ void pfk_net_lock_init(void); void pfk_net_lock(void); /* write */ void pfk_net_unlock(void); void pfk_net_read_enter(void); /* read */ void pfk_net_read_release(void); #define NET_LOCK() pfk_net_lock() #define NET_UNLOCK() pfk_net_unlock() #define NET_READ_ENTER() pfk_net_read_enter() #define NET_READ_RELEASE() pfk_net_read_release() void rw_init(struct rwlock_s *l, const char *name); void rw_enter(struct rwlock_s *l, int mode); void rw_exit(struct rwlock_s *l); int rw_status(struct rwlock_s *l); #define RW_READER 1 #define RW_WRITER 2 #define RW_NAPUTS 0 #define rw_assert(l, m) do { } while (0) /* PFLINUX: advisory */ /* BSD queue.h/tree.h/staged helpers — the Linux kernel's list.h/rbtree.h * define a few identically-named macros; ported TUs never use Linux's * list APIs via those names, so we clear and override. */ #undef LIST_HEAD #undef LIST_HEAD_INIT #undef RB_ROOT #undef RB_CLEAR_NODE #include "compat/sys/queue.h" #include "compat/sys/tree.h" #include "compat/sys/socket.h" #include "compat/net/if_types.h" #include "compat/net/if_var.h" /* mbuf + BSD wire structs + pf ifnet registry */ #include "pfk_mbuf.h" #include "pfk_net.h" #include "pfk_if.h" /* OpenBSD digest + toeplitz helpers (vendored into compat/crypto, compat/net) */ #include "compat/net/toeplitz.h" #include "compat/crypto/siphash.h" /* pf headers resolve via -I module/include */ #define NPFSYNC 0 #define NPFLOG 1 #define NPFLOW 0 #define NCARP 0 #define NPF 1 void pfk_mod_init_done(void); #endif /* _PFK_H */