Files

193 lines
6.2 KiB
C

/*
* PF-on-Linux mbuf shim: OpenBSD `struct mbuf` over Linux `sk_buff`.
*
* Design (see spec §4.1): PF-facing mbufs are ALWAYS single-segment
* (linearized on ingress). `m_data`/`m_len` mirror `skb->data`/`skb->len`.
* `m_pkthdr` carries PF's per-packet metadata (pf.* bits, ph.* aliases).
* Chains (m_next) are used only by our own concatenation (m_cat → copy);
* upstream PF never builds multi-segment chains it would hand back to Linux.
*
* (c) 2026 PF-on-Linux contributors — ISC.
*/
#ifndef _PFK_MBUF_H
#define _PFK_MBUF_H
#include <linux/skbuff.h>
struct pfk_ifnet; /* forward (pfk_if.h) */
struct mbuf_list; /* BSD mbuf list (pfk_if.h defines it) */
struct pf_state_key;
struct inpcb;
struct pf_tag;
struct m_tag {
struct m_tag *m_tag_next;
int m_tag_type;
u_int m_tag_len; /* opaque: byte count of data[] */
u_char m_tag_data[];
};
/* mbuf types (OpenBSD numbering) */
#define MT_FREE 0
#define MT_DATA 1
#define MT_HEADER 2
#define MT_SONAME 3
#define MT_SBUF 4
#define MT_ZOMBIE 5
#define MT_USER 6
#define MT_RTABLE 7
#define MT_IFADDR 8
#define MT_EXT 9
#define MT_RTMSG 10
#define MT_SOCKET 11
#define MT_PFDESC 12
#define MT_TAG 13
#define MT_OFDESC 14
#define MT_TAGV 10
#define MT_PFTOC TAG_PF
#define MT_PF TAG_PF
#define TAG_PF 0x50460000
#define TAG_PF_RR (TAG_PF + 1)
#define MT_PFTOC TAG_PF
struct pkthdr_pf {
u_int flags;
struct pf_state_key *statekey;
struct inpcb *inp;
u_int32_t qid;
int16_t prio;
u_int8_t delay;
u_int8_t routed;
u_int8_t dir;
u_int8_t reason;
u_int16_t ruleset;
u_int tag; /* OpenBSD: bitmask */
};
struct pkthdr {
int len;
struct pkthdr_pf pf;
u_int csum_flags;
void *ph_cookie;
u_int32_t ph_flowid;
u_int ph_ifidx;
u_int ph_rtableid;
int64_t ph_timestamp; /* OpenBSD 8.0: nanoseconds */
struct pfk_ifnet *ifp;
struct pfk_ifnet *rcvif;
u_short ph; /* tso segs: unused, kept as pad */
u_int8_t af;
u_int16_t proto;
u_int hdr_len;
struct m_tag *tags;
int pkthdr_len; /* == len mirror */
};
#define M_EXT 0x0001
#define M_PKTHDR 0x0002
#define M_EOR 0x0004
#define M_RO 0x0010
#define M_BCAST 0x0020
#define M_MCAST 0x0040
#define M_LOOP 0x0080
/* m_pkthdr.csum_flags bits (OpenBSD <sys/mbuf.h> names, port values).
* PFLINUX: the port does not trust driver offload yet; ingress packets get
* no IN_OK bit and pf.c re-checksums in software (pf_check_tcp_cksum). */
#define M_TCP_CSUM_IN_OK 0x0001
#define M_TCP_CSUM_IN_BAD 0x0002
#define M_TCP_CSUM_OUT 0x0004
#define M_UDP_CSUM_IN_OK 0x0010
#define M_UDP_CSUM_IN_BAD 0x0020
#define M_UDP_CSUM_OUT 0x0040
#define M_ICMP_CSUM_OUT 0x0100
#define M_IPV4_CSUM_OUT 0x0200
#define M_FLOWID 0x0400
/* m_copym/m_dup "copy everything" length (OpenBSD <sys/mbuf.h>) */
#ifndef M_COPYALL
#define M_COPYALL 1000000000
#endif
/* BSD M_PREPEND (OpenBSD <sys/mbuf.h>): m = m_prepend(m, h, f) */
#ifndef M_PREPEND
#define M_PREPEND(m, h, f) ((m) = m_prepend((m), (h), (f)))
#endif
#define M_SKIP_FIREWALL 0x0100
#define M_BPF_MCAST 0x0200
#define M_PROMISC 0x0400
#define M_READONLY 0x0800
#define M_CANTFIND (M_READONLY)
#define M_DONTFRAG 0x1000
struct mbuf {
struct mbuf *m_next;
struct mbuf *m_nextout;
u_short m_flags;
u_short m_len;
caddr_t m_data;
u_short m_type;
u_short m_maxsize;
int m_refcnt;
struct sk_buff *skb; /* canonical storage (linear) */
struct pkthdr m_pkthdr; /* valid iff M_PKTHDR */
};
#define MGET(m, f, t) do { (m) = m_get((f), (t)); } while (0)
#define MGETHDR(m, f, t) do { (m) = m_gethdr((f), (t)); } while (0)
#define mtod(m, t) ((t)((m)->m_data))
#define MTOU(m, t) ((t)((m)->m_data))
#define MFREE(m, n) ((n) = m_free((m)))
/* lifecycle */
struct mbuf *m_get(int how, short type);
struct mbuf *m_gethdr(int how, short type);
struct mbuf *m_alloc_skb(struct sk_buff *skb, int how); /* wrap borrowed skb */
struct mbuf *pfk_m_wrap_skb(struct sk_buff *skb, int af); /* ingress: extra ref */
struct mbuf *pfk_m_wrap_skb(struct sk_buff *skb, int af); /* ingress: takes extra ref */
struct mbuf *m_devget(char *buf, int totlen, int off,
struct pfk_ifnet *ifp, void (*copyin_fc)(caddr_t, int));
void pfk_m_setpkthdr(struct mbuf *m);
struct mbuf *m_copym(struct mbuf *m, int off, int len, int wait);
struct mbuf *m_dup(struct mbuf *m, int wait); /* full dup + headroom */
struct mbuf *m_prepend(struct mbuf *m, int len, int how);
struct mbuf *m_split(struct mbuf *m, int len, int flags);
struct mbuf *m_dup_pkt(struct mbuf *m, u_int hdr, int how);
#define m_copypacket(m, w) m_copym((m), 0, 0, (w))
void m_adj(struct mbuf *m, int dlen);
void m_trim(struct mbuf *m, int dlen);
int m_cat(struct mbuf *to, struct mbuf *from); /* copies+consumes from */
int m_copyback(struct mbuf *m, int off, int len, const void *copied, int type);
void m_copydata(const struct mbuf *m, int off, int len, caddr_t dest);
struct mbuf *m_getptr(struct mbuf *m, int loc, int *off);
int m_clump(struct mbuf **m0p, int len, int *mp_off, int *mp_len, caddr_t *doff);
void m_free_ext(struct mbuf *m);
struct mbuf *m_free(struct mbuf *m); /* returns next */
void m_freem(struct mbuf *m);
struct mbuf *m_dtom(struct sk_buff *skb); /* reverse map via skb->cb */
static inline struct sk_buff *m_to_skb(struct mbuf *m) { return m->skb; }
/* linearize: PF ingress guarantee */
int pfk_mbuf_linearize(struct mbuf *m); /* pskb_expand if fragged */
void pfk_mbuf_refresh(struct mbuf *m); /* resync m_len/pkthdr from skb */
/* m_tag */
struct m_tag *m_tag_alloc(int type, int len, int wait, caddr_t *align_data);
void m_tag_free(struct m_tag *m);
void m_tag_prepend(struct mbuf *m, struct m_tag *tag);
void m_tag_prepend_packet(struct mbuf *m, struct m_tag *tag);
void m_tag_delete(struct mbuf *m, struct m_tag *tag);
struct m_tag *m_tag_find(struct mbuf *m, int type, struct m_tag *start);
struct m_tag *m_tag_copy(struct m_tag *tag, int how);
int m_tag_copy_chain(struct mbuf *to, struct mbuf *from, int how);
void m_tag_delete_chain(struct mbuf *m, struct m_tag *end);
struct m_tag *m_tag_first(struct mbuf *m);
struct m_tag *m_tag_next(struct mbuf *m, struct m_tag *tag);
void m_tag_attach(struct mbuf *m, struct m_tag *t); /* append order */
/* PF flowid/toeplitz ingress hook + sysctl-ish knobs */
int pfk_mbuf_init(void);
void pfk_mbuf_exit(void);
#endif /* _PFK_MBUF_H */