#ifndef _NET_PFVAR_PRIV_H_
#define _NET_PFVAR_PRIV_H_
#ifdef _KERNEL
#include <sys/rwlock.h>
#include <sys/mutex.h>
#include <sys/pclock.h>
#include <sys/percpu.h>
struct pfsync_deferral;
struct kstat;
#define PF_STATE_LINK_TYPE_STATELIM 1
#define PF_STATE_LINK_TYPE_SOURCELIM 2
struct pf_state_link {
TAILQ_ENTRY(pf_state_link) pfl_link;
SLIST_ENTRY(pf_state_link) pfl_linkage;
struct pf_state *pfl_state;
unsigned int pfl_type;
};
TAILQ_HEAD(pf_state_link_list, pf_state_link);
SLIST_HEAD(pf_state_linkage, pf_state_link);
struct pf_state_item {
TAILQ_ENTRY(pf_state_item)
si_entry;
struct pf_state *si_st;
};
TAILQ_HEAD(pf_statelisthead, pf_state_item);
struct pf_state_key {
struct pf_addr addr[2];
u_int16_t port[2];
u_int16_t rdomain;
u_int16_t hash;
sa_family_t af;
u_int8_t proto;
RBT_ENTRY(pf_state_key) sk_entry;
struct pf_statelisthead sk_states;
struct pf_state_key *sk_reverse;
struct inpcb *sk_inp;
pf_refcnt_t sk_refcnt;
u_int8_t sk_removed;
};
RBT_HEAD(pf_state_tree, pf_state_key);
RBT_PROTOTYPE(pf_state_tree, pf_state_key, sk_entry, pf_state_compare_key);
#define PF_REVERSED_KEY(key, family) \
((key[PF_SK_WIRE]->af != key[PF_SK_STACK]->af) && \
(key[PF_SK_WIRE]->af != (family)))
struct pf_state {
u_int64_t id;
u_int32_t creatorid;
u_int8_t direction;
u_int8_t pad[3];
TAILQ_ENTRY(pf_state) sync_list;
struct pfsync_deferral *sync_defer;
TAILQ_ENTRY(pf_state) entry_list;
SLIST_ENTRY(pf_state) gc_list;
RBT_ENTRY(pf_state) entry_id;
struct pf_state_peer src;
struct pf_state_peer dst;
struct pf_rule_slist match_rules;
union pf_rule_ptr rule;
union pf_rule_ptr anchor;
union pf_rule_ptr natrule;
struct pf_addr rt_addr;
struct pf_sn_head src_nodes;
struct pf_state_key *key[2];
struct pfi_kif *kif;
struct mutex mtx;
pf_refcnt_t refcnt;
u_int64_t packets[2];
u_int64_t bytes[2];
int32_t creation;
int32_t expire;
int32_t pfsync_time;
int rtableid[2];
u_int16_t qid;
u_int16_t pqid;
u_int16_t tag;
u_int16_t state_flags;
u_int8_t log;
u_int8_t timeout;
u_int8_t sync_state;
u_int8_t sync_updates;
u_int8_t min_ttl;
u_int8_t set_tos;
u_int8_t set_prio[2];
u_int16_t max_mss;
u_int16_t if_index_in;
u_int16_t if_index_out;
u_int16_t delay;
u_int8_t rt;
uint8_t statelim;
uint8_t sourcelim;
struct pf_state_linkage linkage;
};
RBT_HEAD(pf_state_tree_id, pf_state);
RBT_PROTOTYPE(pf_state_tree_id, pf_state, entry_id, pf_state_compare_id);
extern struct pf_state_tree_id tree_id;
struct pf_state_list {
struct pf_state_queue pfs_list;
struct mutex pfs_mtx;
struct rwlock pfs_rwl;
};
#define PF_STATE_LIST_INITIALIZER(_pfs) { \
.pfs_list = TAILQ_HEAD_INITIALIZER(_pfs.pfs_list), \
.pfs_mtx = MUTEX_INITIALIZER(IPL_SOFTNET), \
.pfs_rwl = RWLOCK_INITIALIZER("pfstates"), \
}
struct pf_statelim {
RBT_ENTRY(pf_statelim) pfstlim_id_tree;
RBT_ENTRY(pf_statelim) pfstlim_nm_tree;
TAILQ_ENTRY(pf_statelim) pfstlim_list;
struct kstat *pfstlim_ks;
uint32_t pfstlim_id;
char pfstlim_nm[PF_STATELIM_NAME_LEN];
unsigned int pfstlim_limit;
struct {
unsigned int limit;
unsigned int seconds;
} pfstlim_rate;
struct pc_lock pfstlim_lock;
uint64_t pfstlim_rate_ts;
uint64_t pfstlim_rate_token;
uint64_t pfstlim_rate_bucket;
unsigned int pfstlim_inuse;
struct pf_state_link_list pfstlim_states;
struct {
uint64_t admitted;
uint64_t hardlimited;
uint64_t ratelimited;
} pfstlim_counters;
struct {
time_t created;
time_t updated;
time_t cleared;
} pfstlim_timestamps;
};
RBT_HEAD(pf_statelim_id_tree, pf_statelim);
RBT_PROTOTYPE(pf_statelim_id_tree, pf_statelim, pfstlim_id_tree, cmp);
RBT_HEAD(pf_statelim_nm_tree, pf_statelim);
RBT_PROTOTYPE(pf_statelim_nm_tree, pf_statelim, pfstlim_nm_tree, cmp);
TAILQ_HEAD(pf_statelim_list, pf_statelim);
extern struct pf_statelim_id_tree pf_statelim_id_tree_active;
extern struct pf_statelim_list pf_statelim_list_active;
extern struct pf_statelim_id_tree pf_statelim_id_tree_inactive;
extern struct pf_statelim_nm_tree pf_statelim_nm_tree_inactive;
extern struct pf_statelim_list pf_statelim_list_inactive;
static inline unsigned int
pf_statelim_enter(struct pf_statelim *pfstlim)
{
return (pc_sprod_enter(&pfstlim->pfstlim_lock));
}
static inline void
pf_statelim_leave(struct pf_statelim *pfstlim, unsigned int gen)
{
pc_sprod_leave(&pfstlim->pfstlim_lock, gen);
}
struct pf_sourcelim;
struct pf_source {
RBT_ENTRY(pf_source) pfsr_tree;
RBT_ENTRY(pf_source) pfsr_ioc_tree;
struct pf_sourcelim *pfsr_parent;
sa_family_t pfsr_af;
u_int16_t pfsr_rdomain;
struct pf_addr pfsr_addr;
unsigned int pfsr_inuse;
unsigned int pfsr_intable;
struct pf_state_link_list pfsr_states;
time_t pfsr_empty_ts;
TAILQ_ENTRY(pf_source) pfsr_empty_gc;
uint64_t pfsr_rate_ts;
struct {
uint64_t admitted;
uint64_t hardlimited;
uint64_t ratelimited;
} pfsr_counters;
};
RBT_HEAD(pf_source_tree, pf_source);
RBT_PROTOTYPE(pf_source_tree, pf_source, pfsr_tree, cmp);
RBT_HEAD(pf_source_ioc_tree, pf_source);
RBT_PROTOTYPE(pf_source_ioc_tree, pf_source, pfsr_ioc_tree, cmp);
TAILQ_HEAD(pf_source_list, pf_source);
struct pf_sourcelim {
RBT_ENTRY(pf_sourcelim) pfsrlim_id_tree;
RBT_ENTRY(pf_sourcelim) pfsrlim_nm_tree;
TAILQ_ENTRY(pf_sourcelim) pfsrlim_list;
struct kstat *pfsrlim_ks;
uint32_t pfsrlim_id;
char pfsrlim_nm[PF_SOURCELIM_NAME_LEN];
unsigned int pfsrlim_disabled;
unsigned int pfsrlim_entries;
unsigned int pfsrlim_limit;
unsigned int pfsrlim_ipv4_prefix;
unsigned int pfsrlim_ipv6_prefix;
struct {
unsigned int limit;
unsigned int seconds;
} pfsrlim_rate;
struct {
char name[PF_TABLE_NAME_SIZE];
unsigned int hwm;
unsigned int lwm;
struct pfr_ktable *table;
} pfsrlim_overload;
struct pc_lock pfsrlim_lock;
struct pf_addr pfsrlim_ipv4_mask;
struct pf_addr pfsrlim_ipv6_mask;
uint64_t pfsrlim_rate_token;
uint64_t pfsrlim_rate_bucket;
unsigned int pfsrlim_nsources;
struct pf_source_tree pfsrlim_sources;
struct pf_source_ioc_tree pfsrlim_ioc_sources;
struct {
uint64_t addrallocs;
uint64_t addrlimited;
uint64_t addrnomem;
uint64_t inuse;
uint64_t admitted;
uint64_t hardlimited;
uint64_t ratelimited;
} pfsrlim_counters;
};
RBT_HEAD(pf_sourcelim_id_tree, pf_sourcelim);
RBT_PROTOTYPE(pf_sourcelim_id_tree, pf_sourcelim, pfsrlim_id_tree, cmp);
RBT_HEAD(pf_sourcelim_nm_tree, pf_sourcelim);
RBT_PROTOTYPE(pf_sourcelim_nm_tree, pf_sourcelim, pfsrlim_nm_tree, cmp);
TAILQ_HEAD(pf_sourcelim_list, pf_sourcelim);
extern struct pf_sourcelim_id_tree pf_sourcelim_id_tree_active;
extern struct pf_sourcelim_list pf_sourcelim_list_active;
extern struct pf_sourcelim_id_tree pf_sourcelim_id_tree_inactive;
extern struct pf_sourcelim_nm_tree pf_sourcelim_nm_tree_inactive;
extern struct pf_sourcelim_list pf_sourcelim_list_inactive;
static inline unsigned int
pf_sourcelim_enter(struct pf_sourcelim *pfsrlim)
{
return (pc_sprod_enter(&pfsrlim->pfsrlim_lock));
}
static inline void
pf_sourcelim_leave(struct pf_sourcelim *pfsrlim, unsigned int gen)
{
pc_sprod_leave(&pfsrlim->pfsrlim_lock, gen);
}
extern struct rwlock pf_lock;
struct pf_pdesc {
struct {
int done;
uid_t uid;
gid_t gid;
pid_t pid;
} lookup;
u_int64_t tot_len;
struct pf_addr nsaddr;
struct pf_addr ndaddr;
struct pfi_kif *kif;
struct mbuf *m;
struct pf_addr *src;
struct pf_addr *dst;
u_int16_t *pcksum;
u_int16_t *sport;
u_int16_t *dport;
u_int16_t osport;
u_int16_t odport;
u_int16_t hash;
u_int16_t nsport;
u_int16_t ndport;
u_int32_t off;
u_int32_t hdrlen;
u_int32_t p_len;
u_int32_t extoff;
u_int32_t fragoff;
u_int32_t jumbolen;
u_int32_t badopts;
#define PF_OPT_OTHER 0x0001
#define PF_OPT_JUMBO 0x0002
#define PF_OPT_ROUTER_ALERT 0x0004
u_int16_t rdomain;
u_int16_t virtual_proto;
#define PF_VPROTO_FRAGMENT 256
sa_family_t af;
sa_family_t naf;
u_int8_t proto;
u_int8_t tos;
u_int8_t ttl;
u_int8_t dir;
u_int8_t sidx;
u_int8_t didx;
u_int8_t destchg;
u_int8_t pflog;
union {
struct tcphdr tcp;
struct udphdr udp;
struct icmp icmp;
#ifdef INET6
struct icmp6_hdr icmp6;
struct mld_hdr mld;
struct nd_neighbor_solicit nd_ns;
#endif
} hdr;
};
struct pf_anchor_stackframe {
struct pf_ruleset *sf_rs;
struct pf_rule *sf_anchor;
union {
struct pf_rule *u_r;
struct pf_anchor_stackframe *u_stack_top;
} u;
struct pf_anchor *sf_child;
int sf_jump_target;
};
#define sf_r u.u_r
#define sf_stack_top u.u_stack_top
enum {
PF_NEXT_RULE,
PF_NEXT_CHILD
};
extern struct cpumem *pf_anchor_stack;
enum pf_trans_type {
PF_TRANS_NONE,
PF_TRANS_GETRULE,
PF_TRANS_MAX
};
struct pf_trans {
LIST_ENTRY(pf_trans) pft_entry;
uint32_t pft_unit;
uint64_t pft_ticket;
enum pf_trans_type pft_type;
union {
struct {
u_int32_t gr_version;
struct pf_anchor *gr_anchor;
struct pf_rule *gr_rule;
} u_getrule;
} u;
};
#define pftgr_version u.u_getrule.gr_version
#define pftgr_anchor u.u_getrule.gr_anchor
#define pftgr_rule u.u_getrule.gr_rule
extern struct timeout pf_purge_states_to;
extern struct task pf_purge_task;
extern struct timeout pf_purge_to;
struct pf_state *pf_state_ref(struct pf_state *);
void pf_state_unref(struct pf_state *);
extern struct rwlock pf_lock;
extern struct rwlock pf_state_lock;
extern struct mutex pf_frag_mtx;
extern struct mutex pf_inp_mtx;
#define PF_LOCK() do { \
rw_enter_write(&pf_lock); \
} while (0)
#define PF_UNLOCK() do { \
PF_ASSERT_LOCKED(); \
rw_exit_write(&pf_lock); \
} while (0)
#define PF_ASSERT_LOCKED() do { \
if (rw_status(&pf_lock) != RW_WRITE) \
splassert_fail(RW_WRITE, \
rw_status(&pf_lock),__func__);\
} while (0)
#define PF_ASSERT_UNLOCKED() do { \
if (rw_status(&pf_lock) == RW_WRITE) \
splassert_fail(0, rw_status(&pf_lock), __func__);\
} while (0)
#define PF_STATE_ENTER_READ() do { \
rw_enter_read(&pf_state_lock); \
} while (0)
#define PF_STATE_EXIT_READ() do { \
rw_exit_read(&pf_state_lock); \
} while (0)
#define PF_STATE_ENTER_WRITE() do { \
rw_enter_write(&pf_state_lock); \
} while (0)
#define PF_STATE_EXIT_WRITE() do { \
PF_STATE_ASSERT_LOCKED(); \
rw_exit_write(&pf_state_lock); \
} while (0)
#define PF_STATE_ASSERT_LOCKED() do { \
if (rw_status(&pf_state_lock) != RW_WRITE)\
splassert_fail(RW_WRITE, \
rw_status(&pf_state_lock), __func__);\
} while (0)
#define PF_FRAG_LOCK() mtx_enter(&pf_frag_mtx)
#define PF_FRAG_UNLOCK() mtx_leave(&pf_frag_mtx)
void pf_state_peer_hton(const struct pf_state_peer *,
struct pfsync_state_peer *);
void pf_state_peer_ntoh(const struct pfsync_state_peer *,
struct pf_state_peer *);
u_int16_t pf_pkt_hash(sa_family_t, uint8_t,
const struct pf_addr *, const struct pf_addr *,
uint16_t, uint16_t);
void pf_status_init(void);
void pf_status_clear(void);
void pf_status_read(struct pf_status *);
#endif
#endif