pf: Split pf_rule into kernel and user space versions

No functional change intended.

MFC after:	2 weeks
Sponsored by:	Orange Business Services
Differential Revision:	https://reviews.freebsd.org/D27758
This commit is contained in:
Kristof Provost 2020-12-05 14:32:54 +01:00
parent dc865dae89
commit e86bddea9f
11 changed files with 894 additions and 308 deletions

View File

@ -293,11 +293,115 @@ extern struct sx pf_end_lock;
#define PF_ALGNMNT(off) (((off) % 2) == 0) #define PF_ALGNMNT(off) (((off) % 2) == 0)
#ifdef _KERNEL #ifdef _KERNEL
union pf_krule_ptr {
struct pf_krule *ptr;
u_int32_t nr;
};
struct pf_krule {
struct pf_rule_addr src;
struct pf_rule_addr dst;
union pf_krule_ptr skip[PF_SKIP_COUNT];
char label[PF_RULE_LABEL_SIZE];
char ifname[IFNAMSIZ];
char qname[PF_QNAME_SIZE];
char pqname[PF_QNAME_SIZE];
char tagname[PF_TAG_NAME_SIZE];
char match_tagname[PF_TAG_NAME_SIZE];
char overload_tblname[PF_TABLE_NAME_SIZE];
TAILQ_ENTRY(pf_krule) entries;
struct pf_pool rpool;
u_int64_t evaluations;
u_int64_t packets[2];
u_int64_t bytes[2];
struct pfi_kif *kif;
struct pf_kanchor *anchor;
struct pfr_ktable *overload_tbl;
pf_osfp_t os_fingerprint;
int rtableid;
u_int32_t timeout[PFTM_MAX];
u_int32_t max_states;
u_int32_t max_src_nodes;
u_int32_t max_src_states;
u_int32_t max_src_conn;
struct {
u_int32_t limit;
u_int32_t seconds;
} max_src_conn_rate;
u_int32_t qid;
u_int32_t pqid;
u_int32_t rt_listid;
u_int32_t nr;
u_int32_t prob;
uid_t cuid;
pid_t cpid;
counter_u64_t states_cur;
counter_u64_t states_tot;
counter_u64_t src_nodes;
u_int16_t return_icmp;
u_int16_t return_icmp6;
u_int16_t max_mss;
u_int16_t tag;
u_int16_t match_tag;
u_int16_t scrub_flags;
struct pf_rule_uid uid;
struct pf_rule_gid gid;
u_int32_t rule_flag;
u_int8_t action;
u_int8_t direction;
u_int8_t log;
u_int8_t logif;
u_int8_t quick;
u_int8_t ifnot;
u_int8_t match_tag_not;
u_int8_t natpass;
u_int8_t keep_state;
sa_family_t af;
u_int8_t proto;
u_int8_t type;
u_int8_t code;
u_int8_t flags;
u_int8_t flagset;
u_int8_t min_ttl;
u_int8_t allow_opts;
u_int8_t rt;
u_int8_t return_ttl;
u_int8_t tos;
u_int8_t set_tos;
u_int8_t anchor_relative;
u_int8_t anchor_wildcard;
u_int8_t flush;
u_int8_t prio;
u_int8_t set_prio[2];
struct {
struct pf_addr addr;
u_int16_t port;
} divert;
uint64_t u_states_cur;
uint64_t u_states_tot;
uint64_t u_src_nodes;
};
struct pf_ksrc_node { struct pf_ksrc_node {
LIST_ENTRY(pf_ksrc_node) entry; LIST_ENTRY(pf_ksrc_node) entry;
struct pf_addr addr; struct pf_addr addr;
struct pf_addr raddr; struct pf_addr raddr;
union pf_rule_ptr rule; union pf_krule_ptr rule;
struct pfi_kif *kif; struct pfi_kif *kif;
counter_u64_t bytes[2]; counter_u64_t bytes[2];
counter_u64_t packets[2]; counter_u64_t packets[2];
@ -374,6 +478,15 @@ struct pf_state_cmp {
u_int8_t pad[3]; u_int8_t pad[3];
}; };
#define PFSTATE_ALLOWOPTS 0x01
#define PFSTATE_SLOPPY 0x02
/* was PFSTATE_PFLOW 0x04 */
#define PFSTATE_NOSYNC 0x08
#define PFSTATE_ACK 0x10
#define PFSTATE_SETPRIO 0x0200
#define PFSTATE_SETMASK (PFSTATE_SETPRIO)
#ifdef _KERNEL
struct pf_state { struct pf_state {
u_int64_t id; u_int64_t id;
u_int32_t creatorid; u_int32_t creatorid;
@ -386,9 +499,9 @@ struct pf_state {
LIST_ENTRY(pf_state) entry; LIST_ENTRY(pf_state) entry;
struct pf_state_peer src; struct pf_state_peer src;
struct pf_state_peer dst; struct pf_state_peer dst;
union pf_rule_ptr rule; union pf_krule_ptr rule;
union pf_rule_ptr anchor; union pf_krule_ptr anchor;
union pf_rule_ptr nat_rule; union pf_krule_ptr nat_rule;
struct pf_addr rt_addr; struct pf_addr rt_addr;
struct pf_state_key *key[2]; /* addresses stack and wire */ struct pf_state_key *key[2]; /* addresses stack and wire */
struct pfi_kif *kif; struct pfi_kif *kif;
@ -403,13 +516,6 @@ struct pf_state {
u_int16_t tag; u_int16_t tag;
u_int8_t log; u_int8_t log;
u_int8_t state_flags; u_int8_t state_flags;
#define PFSTATE_ALLOWOPTS 0x01
#define PFSTATE_SLOPPY 0x02
/* was PFSTATE_PFLOW 0x04 */
#define PFSTATE_NOSYNC 0x08
#define PFSTATE_ACK 0x10
#define PFSTATE_SETPRIO 0x0200
#define PFSTATE_SETMASK (PFSTATE_SETPRIO)
u_int8_t timeout; u_int8_t timeout;
u_int8_t sync_state; /* PFSYNC_S_x */ u_int8_t sync_state; /* PFSYNC_S_x */
@ -417,6 +523,7 @@ struct pf_state {
u_int8_t sync_updates; u_int8_t sync_updates;
u_int8_t _tail[3]; u_int8_t _tail[3];
}; };
#endif
/* /*
* Unified state structures for pulling states out of the kernel * Unified state structures for pulling states out of the kernel
@ -501,11 +608,11 @@ void pfsync_state_export(struct pfsync_state *,
struct pf_state *); struct pf_state *);
/* pflog */ /* pflog */
struct pf_ruleset; struct pf_kruleset;
struct pf_pdesc; struct pf_pdesc;
typedef int pflog_packet_t(struct pfi_kif *, struct mbuf *, sa_family_t, typedef int pflog_packet_t(struct pfi_kif *, struct mbuf *, sa_family_t,
u_int8_t, u_int8_t, struct pf_rule *, struct pf_rule *, u_int8_t, u_int8_t, struct pf_krule *, struct pf_krule *,
struct pf_ruleset *, struct pf_pdesc *, int); struct pf_kruleset *, struct pf_pdesc *, int);
extern pflog_packet_t *pflog_packet_ptr; extern pflog_packet_t *pflog_packet_ptr;
#endif /* _KERNEL */ #endif /* _KERNEL */
@ -563,42 +670,42 @@ extern pflog_packet_t *pflog_packet_ptr;
d += ntohl(s[1]); \ d += ntohl(s[1]); \
} while (0) } while (0)
TAILQ_HEAD(pf_rulequeue, pf_rule); TAILQ_HEAD(pf_krulequeue, pf_krule);
struct pf_anchor; struct pf_kanchor;
struct pf_ruleset { struct pf_kruleset {
struct { struct {
struct pf_rulequeue queues[2]; struct pf_krulequeue queues[2];
struct { struct {
struct pf_rulequeue *ptr; struct pf_krulequeue *ptr;
struct pf_rule **ptr_array; struct pf_krule **ptr_array;
u_int32_t rcount; u_int32_t rcount;
u_int32_t ticket; u_int32_t ticket;
int open; int open;
} active, inactive; } active, inactive;
} rules[PF_RULESET_MAX]; } rules[PF_RULESET_MAX];
struct pf_anchor *anchor; struct pf_kanchor *anchor;
u_int32_t tticket; u_int32_t tticket;
int tables; int tables;
int topen; int topen;
}; };
RB_HEAD(pf_anchor_global, pf_anchor); RB_HEAD(pf_kanchor_global, pf_kanchor);
RB_HEAD(pf_anchor_node, pf_anchor); RB_HEAD(pf_kanchor_node, pf_kanchor);
struct pf_anchor { struct pf_kanchor {
RB_ENTRY(pf_anchor) entry_global; RB_ENTRY(pf_kanchor) entry_global;
RB_ENTRY(pf_anchor) entry_node; RB_ENTRY(pf_kanchor) entry_node;
struct pf_anchor *parent; struct pf_kanchor *parent;
struct pf_anchor_node children; struct pf_kanchor_node children;
char name[PF_ANCHOR_NAME_SIZE]; char name[PF_ANCHOR_NAME_SIZE];
char path[MAXPATHLEN]; char path[MAXPATHLEN];
struct pf_ruleset ruleset; struct pf_kruleset ruleset;
int refcnt; /* anchor rules */ int refcnt; /* anchor rules */
int match; /* XXX: used for pfctl black magic */ int match; /* XXX: used for pfctl black magic */
}; };
RB_PROTOTYPE(pf_anchor_global, pf_anchor, entry_global, pf_anchor_compare); RB_PROTOTYPE(pf_kanchor_global, pf_kanchor, entry_global, pf_anchor_compare);
RB_PROTOTYPE(pf_anchor_node, pf_anchor, entry_node, pf_anchor_compare); RB_PROTOTYPE(pf_kanchor_node, pf_kanchor, entry_node, pf_kanchor_compare);
#define PF_RESERVED_ANCHOR "_pf" #define PF_RESERVED_ANCHOR "_pf"
@ -625,7 +732,7 @@ RB_PROTOTYPE(pf_anchor_node, pf_anchor, entry_node, pf_anchor_compare);
PFR_TFLAG_REFDANCHOR | \ PFR_TFLAG_REFDANCHOR | \
PFR_TFLAG_COUNTERS) PFR_TFLAG_COUNTERS)
struct pf_anchor_stackframe; struct pf_kanchor_stackframe;
struct pfr_table { struct pfr_table {
char pfrt_anchor[MAXPATHLEN]; char pfrt_anchor[MAXPATHLEN];
@ -707,6 +814,7 @@ struct pfr_kcounters {
((kc)->pfrkc_counters + \ ((kc)->pfrkc_counters + \
(dir) * PFR_OP_ADDR_MAX * PFR_TYPE_MAX + (op) * PFR_TYPE_MAX + (t)) (dir) * PFR_OP_ADDR_MAX * PFR_TYPE_MAX + (op) * PFR_TYPE_MAX + (t))
#ifdef _KERNEL
SLIST_HEAD(pfr_kentryworkq, pfr_kentry); SLIST_HEAD(pfr_kentryworkq, pfr_kentry);
struct pfr_kentry { struct pfr_kentry {
struct radix_node pfrke_node[2]; struct radix_node pfrke_node[2];
@ -729,7 +837,7 @@ struct pfr_ktable {
struct radix_node_head *pfrkt_ip6; struct radix_node_head *pfrkt_ip6;
struct pfr_ktable *pfrkt_shadow; struct pfr_ktable *pfrkt_shadow;
struct pfr_ktable *pfrkt_root; struct pfr_ktable *pfrkt_root;
struct pf_ruleset *pfrkt_rs; struct pf_kruleset *pfrkt_rs;
long pfrkt_larg; long pfrkt_larg;
int pfrkt_nflags; int pfrkt_nflags;
}; };
@ -745,6 +853,7 @@ struct pfr_ktable {
#define pfrkt_match pfrkt_kts.pfrkts_match #define pfrkt_match pfrkt_kts.pfrkts_match
#define pfrkt_nomatch pfrkt_kts.pfrkts_nomatch #define pfrkt_nomatch pfrkt_kts.pfrkts_nomatch
#define pfrkt_tzero pfrkt_kts.pfrkts_tzero #define pfrkt_tzero pfrkt_kts.pfrkts_tzero
#endif
/* keep synced with pfi_kif, used in RB_FIND */ /* keep synced with pfi_kif, used in RB_FIND */
struct pfi_kif_cmp { struct pfi_kif_cmp {
@ -789,7 +898,7 @@ struct pf_pdesc {
void *any; void *any;
} hdr; } hdr;
struct pf_rule *nat_rule; /* nat/rdr rule applied to packet */ struct pf_krule *nat_rule; /* nat/rdr rule applied to packet */
struct pf_addr *src; /* src address */ struct pf_addr *src; /* src address */
struct pf_addr *dst; /* dst address */ struct pf_addr *dst; /* dst address */
u_int16_t *sport; u_int16_t *sport;
@ -1294,7 +1403,7 @@ VNET_DECLARE(struct pf_altqqueue *, pf_altqs_inactive);
VNET_DECLARE(struct pf_altqqueue *, pf_altq_ifs_inactive); VNET_DECLARE(struct pf_altqqueue *, pf_altq_ifs_inactive);
#define V_pf_altq_ifs_inactive VNET(pf_altq_ifs_inactive) #define V_pf_altq_ifs_inactive VNET(pf_altq_ifs_inactive)
VNET_DECLARE(struct pf_rulequeue, pf_unlinked_rules); VNET_DECLARE(struct pf_krulequeue, pf_unlinked_rules);
#define V_pf_unlinked_rules VNET(pf_unlinked_rules) #define V_pf_unlinked_rules VNET(pf_unlinked_rules)
void pf_initialize(void); void pf_initialize(void);
@ -1304,7 +1413,7 @@ void pf_cleanup(void);
struct pf_mtag *pf_get_mtag(struct mbuf *); struct pf_mtag *pf_get_mtag(struct mbuf *);
extern void pf_calc_skip_steps(struct pf_rulequeue *); extern void pf_calc_skip_steps(struct pf_krulequeue *);
#ifdef ALTQ #ifdef ALTQ
extern void pf_altq_ifnet_event(struct ifnet *, int); extern void pf_altq_ifnet_event(struct ifnet *, int);
#endif #endif
@ -1351,7 +1460,7 @@ extern struct pf_state *pf_find_state_byid(uint64_t, uint32_t);
extern struct pf_state *pf_find_state_all(struct pf_state_key_cmp *, extern struct pf_state *pf_find_state_all(struct pf_state_key_cmp *,
u_int, int *); u_int, int *);
extern struct pf_ksrc_node *pf_find_src_node(struct pf_addr *, extern struct pf_ksrc_node *pf_find_src_node(struct pf_addr *,
struct pf_rule *, sa_family_t, int); struct pf_krule *, sa_family_t, int);
extern void pf_unlink_src_node(struct pf_ksrc_node *); extern void pf_unlink_src_node(struct pf_ksrc_node *);
extern u_int pf_free_src_nodes(struct pf_ksrc_node_list *); extern u_int pf_free_src_nodes(struct pf_ksrc_node_list *);
extern void pf_print_state(struct pf_state *); extern void pf_print_state(struct pf_state *);
@ -1363,11 +1472,11 @@ extern u_int16_t pf_proto_cksum_fixup(struct mbuf *, u_int16_t,
VNET_DECLARE(struct ifnet *, sync_ifp); VNET_DECLARE(struct ifnet *, sync_ifp);
#define V_sync_ifp VNET(sync_ifp); #define V_sync_ifp VNET(sync_ifp);
VNET_DECLARE(struct pf_rule, pf_default_rule); VNET_DECLARE(struct pf_krule, pf_default_rule);
#define V_pf_default_rule VNET(pf_default_rule) #define V_pf_default_rule VNET(pf_default_rule)
extern void pf_addrcpy(struct pf_addr *, struct pf_addr *, extern void pf_addrcpy(struct pf_addr *, struct pf_addr *,
u_int8_t); u_int8_t);
void pf_free_rule(struct pf_rule *); void pf_free_rule(struct pf_krule *);
#ifdef INET #ifdef INET
int pf_test(int, int, struct ifnet *, struct mbuf **, struct inpcb *); int pf_test(int, int, struct ifnet *, struct mbuf **, struct inpcb *);
@ -1429,7 +1538,7 @@ void pfr_update_stats(struct pfr_ktable *, struct pf_addr *, sa_family_t,
int pfr_pool_get(struct pfr_ktable *, int *, struct pf_addr *, sa_family_t); int pfr_pool_get(struct pfr_ktable *, int *, struct pf_addr *, sa_family_t);
void pfr_dynaddr_update(struct pfr_ktable *, struct pfi_dynaddr *); void pfr_dynaddr_update(struct pfr_ktable *, struct pfi_dynaddr *);
struct pfr_ktable * struct pfr_ktable *
pfr_attach_table(struct pf_ruleset *, char *); pfr_attach_table(struct pf_kruleset *, char *);
void pfr_detach_table(struct pfr_ktable *); void pfr_detach_table(struct pfr_ktable *);
int pfr_clr_tables(struct pfr_table *, int *, int); int pfr_clr_tables(struct pfr_table *, int *, int);
int pfr_add_tables(struct pfr_table *, int, int *, int); int pfr_add_tables(struct pfr_table *, int, int *, int);
@ -1483,7 +1592,7 @@ void pfi_get_ifaces(const char *, struct pfi_kif *, int *);
int pfi_set_flags(const char *, int); int pfi_set_flags(const char *, int);
int pfi_clear_flags(const char *, int); int pfi_clear_flags(const char *, int);
int pf_match_tag(struct mbuf *, struct pf_rule *, int *, int); int pf_match_tag(struct mbuf *, struct pf_krule *, int *, int);
int pf_tag_packet(struct mbuf *, struct pf_pdesc *, int); int pf_tag_packet(struct mbuf *, struct pf_pdesc *, int);
int pf_addr_cmp(struct pf_addr *, struct pf_addr *, int pf_addr_cmp(struct pf_addr *, struct pf_addr *,
sa_family_t); sa_family_t);
@ -1502,25 +1611,24 @@ VNET_DECLARE(struct pf_limit, pf_limits[PF_LIMIT_MAX]);
#endif /* _KERNEL */ #endif /* _KERNEL */
#ifdef _KERNEL #ifdef _KERNEL
VNET_DECLARE(struct pf_anchor_global, pf_anchors); VNET_DECLARE(struct pf_kanchor_global, pf_anchors);
#define V_pf_anchors VNET(pf_anchors) #define V_pf_anchors VNET(pf_anchors)
VNET_DECLARE(struct pf_anchor, pf_main_anchor); VNET_DECLARE(struct pf_kanchor, pf_main_anchor);
#define V_pf_main_anchor VNET(pf_main_anchor) #define V_pf_main_anchor VNET(pf_main_anchor)
#define pf_main_ruleset V_pf_main_anchor.ruleset #define pf_main_ruleset V_pf_main_anchor.ruleset
#endif
/* these ruleset functions can be linked into userland programs (pfctl) */
int pf_get_ruleset_number(u_int8_t); int pf_get_ruleset_number(u_int8_t);
void pf_init_ruleset(struct pf_ruleset *); void pf_init_kruleset(struct pf_kruleset *);
int pf_anchor_setup(struct pf_rule *, int pf_kanchor_setup(struct pf_krule *,
const struct pf_ruleset *, const char *); const struct pf_kruleset *, const char *);
int pf_anchor_copyout(const struct pf_ruleset *, int pf_kanchor_copyout(const struct pf_kruleset *,
const struct pf_rule *, struct pfioc_rule *); const struct pf_krule *, struct pfioc_rule *);
void pf_anchor_remove(struct pf_rule *); void pf_kanchor_remove(struct pf_krule *);
void pf_remove_if_empty_ruleset(struct pf_ruleset *); void pf_remove_if_empty_kruleset(struct pf_kruleset *);
struct pf_ruleset *pf_find_ruleset(const char *); struct pf_kruleset *pf_find_kruleset(const char *);
struct pf_ruleset *pf_find_or_create_ruleset(const char *); struct pf_kruleset *pf_find_or_create_kruleset(const char *);
void pf_rs_initialize(void); void pf_rs_initialize(void);
#endif
/* The fingerprint functions can be linked into userland programs (tcpdump) */ /* The fingerprint functions can be linked into userland programs (tcpdump) */
int pf_osfp_add(struct pf_osfp_ioctl *); int pf_osfp_add(struct pf_osfp_ioctl *);
@ -1536,21 +1644,21 @@ int pf_osfp_match(struct pf_osfp_enlist *, pf_osfp_t);
#ifdef _KERNEL #ifdef _KERNEL
void pf_print_host(struct pf_addr *, u_int16_t, u_int8_t); void pf_print_host(struct pf_addr *, u_int16_t, u_int8_t);
void pf_step_into_anchor(struct pf_anchor_stackframe *, int *, void pf_step_into_anchor(struct pf_kanchor_stackframe *, int *,
struct pf_ruleset **, int, struct pf_rule **, struct pf_kruleset **, int, struct pf_krule **,
struct pf_rule **, int *); struct pf_krule **, int *);
int pf_step_out_of_anchor(struct pf_anchor_stackframe *, int *, int pf_step_out_of_anchor(struct pf_kanchor_stackframe *, int *,
struct pf_ruleset **, int, struct pf_rule **, struct pf_kruleset **, int, struct pf_krule **,
struct pf_rule **, int *); struct pf_krule **, int *);
int pf_map_addr(u_int8_t, struct pf_rule *, int pf_map_addr(u_int8_t, struct pf_krule *,
struct pf_addr *, struct pf_addr *, struct pf_addr *, struct pf_addr *,
struct pf_addr *, struct pf_ksrc_node **); struct pf_addr *, struct pf_ksrc_node **);
struct pf_rule *pf_get_translation(struct pf_pdesc *, struct mbuf *, struct pf_krule *pf_get_translation(struct pf_pdesc *, struct mbuf *,
int, int, struct pfi_kif *, struct pf_ksrc_node **, int, int, struct pfi_kif *, struct pf_ksrc_node **,
struct pf_state_key **, struct pf_state_key **, struct pf_state_key **, struct pf_state_key **,
struct pf_addr *, struct pf_addr *, struct pf_addr *, struct pf_addr *,
uint16_t, uint16_t, struct pf_anchor_stackframe *); uint16_t, uint16_t, struct pf_kanchor_stackframe *);
struct pf_state_key *pf_state_key_setup(struct pf_pdesc *, struct pf_addr *, struct pf_state_key *pf_state_key_setup(struct pf_pdesc *, struct pf_addr *,
struct pf_addr *, u_int16_t, u_int16_t); struct pf_addr *, u_int16_t, u_int16_t);

View File

@ -202,8 +202,8 @@ pflogioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
static int static int
pflog_packet(struct pfi_kif *kif, struct mbuf *m, sa_family_t af, u_int8_t dir, pflog_packet(struct pfi_kif *kif, struct mbuf *m, sa_family_t af, u_int8_t dir,
u_int8_t reason, struct pf_rule *rm, struct pf_rule *am, u_int8_t reason, struct pf_krule *rm, struct pf_krule *am,
struct pf_ruleset *ruleset, struct pf_pdesc *pd, int lookupsafe) struct pf_kruleset *ruleset, struct pf_pdesc *pd, int lookupsafe)
{ {
struct ifnet *ifn; struct ifnet *ifn;
struct pfloghdr hdr; struct pfloghdr hdr;

View File

@ -463,7 +463,7 @@ pfsync_state_import(struct pfsync_state *sp, u_int8_t flags)
struct pfsync_state_key *kw, *ks; struct pfsync_state_key *kw, *ks;
struct pf_state *st = NULL; struct pf_state *st = NULL;
struct pf_state_key *skw = NULL, *sks = NULL; struct pf_state_key *skw = NULL, *sks = NULL;
struct pf_rule *r = NULL; struct pf_krule *r = NULL;
struct pfi_kif *kif; struct pfi_kif *kif;
int error; int error;

View File

@ -181,7 +181,7 @@ struct pf_overload_entry {
struct pf_addr addr; struct pf_addr addr;
sa_family_t af; sa_family_t af;
uint8_t dir; uint8_t dir;
struct pf_rule *rule; struct pf_krule *rule;
}; };
SLIST_HEAD(pf_overload_head, pf_overload_entry); SLIST_HEAD(pf_overload_head, pf_overload_entry);
@ -196,7 +196,7 @@ MTX_SYSINIT(pf_overloadqueue_mtx, &pf_overloadqueue_mtx,
#define PF_OVERLOADQ_LOCK() mtx_lock(&pf_overloadqueue_mtx) #define PF_OVERLOADQ_LOCK() mtx_lock(&pf_overloadqueue_mtx)
#define PF_OVERLOADQ_UNLOCK() mtx_unlock(&pf_overloadqueue_mtx) #define PF_OVERLOADQ_UNLOCK() mtx_unlock(&pf_overloadqueue_mtx)
VNET_DEFINE(struct pf_rulequeue, pf_unlinked_rules); VNET_DEFINE(struct pf_krulequeue, pf_unlinked_rules);
struct mtx pf_unlnkdrules_mtx; struct mtx pf_unlnkdrules_mtx;
MTX_SYSINIT(pf_unlnkdrules_mtx, &pf_unlnkdrules_mtx, "pf unlinked rules", MTX_SYSINIT(pf_unlnkdrules_mtx, &pf_unlnkdrules_mtx, "pf unlinked rules",
MTX_DEF); MTX_DEF);
@ -230,34 +230,34 @@ static void pf_change_icmp(struct pf_addr *, u_int16_t *,
u_int16_t *, u_int16_t *, u_int16_t *, u_int16_t *, u_int16_t *, u_int16_t *,
u_int16_t *, u_int8_t, sa_family_t); u_int16_t *, u_int8_t, sa_family_t);
static void pf_send_tcp(struct mbuf *, static void pf_send_tcp(struct mbuf *,
const struct pf_rule *, sa_family_t, const struct pf_krule *, sa_family_t,
const struct pf_addr *, const struct pf_addr *, const struct pf_addr *, const struct pf_addr *,
u_int16_t, u_int16_t, u_int32_t, u_int32_t, u_int16_t, u_int16_t, u_int32_t, u_int32_t,
u_int8_t, u_int16_t, u_int16_t, u_int8_t, int, u_int8_t, u_int16_t, u_int16_t, u_int8_t, int,
u_int16_t, struct ifnet *); u_int16_t, struct ifnet *);
static void pf_send_icmp(struct mbuf *, u_int8_t, u_int8_t, static void pf_send_icmp(struct mbuf *, u_int8_t, u_int8_t,
sa_family_t, struct pf_rule *); sa_family_t, struct pf_krule *);
static void pf_detach_state(struct pf_state *); static void pf_detach_state(struct pf_state *);
static int pf_state_key_attach(struct pf_state_key *, static int pf_state_key_attach(struct pf_state_key *,
struct pf_state_key *, struct pf_state *); struct pf_state_key *, struct pf_state *);
static void pf_state_key_detach(struct pf_state *, int); static void pf_state_key_detach(struct pf_state *, int);
static int pf_state_key_ctor(void *, int, void *, int); static int pf_state_key_ctor(void *, int, void *, int);
static u_int32_t pf_tcp_iss(struct pf_pdesc *); static u_int32_t pf_tcp_iss(struct pf_pdesc *);
static int pf_test_rule(struct pf_rule **, struct pf_state **, static int pf_test_rule(struct pf_krule **, struct pf_state **,
int, struct pfi_kif *, struct mbuf *, int, int, struct pfi_kif *, struct mbuf *, int,
struct pf_pdesc *, struct pf_rule **, struct pf_pdesc *, struct pf_krule **,
struct pf_ruleset **, struct inpcb *); struct pf_kruleset **, struct inpcb *);
static int pf_create_state(struct pf_rule *, struct pf_rule *, static int pf_create_state(struct pf_krule *, struct pf_krule *,
struct pf_rule *, struct pf_pdesc *, struct pf_krule *, struct pf_pdesc *,
struct pf_ksrc_node *, struct pf_state_key *, struct pf_ksrc_node *, struct pf_state_key *,
struct pf_state_key *, struct mbuf *, int, struct pf_state_key *, struct mbuf *, int,
u_int16_t, u_int16_t, int *, struct pfi_kif *, u_int16_t, u_int16_t, int *, struct pfi_kif *,
struct pf_state **, int, u_int16_t, u_int16_t, struct pf_state **, int, u_int16_t, u_int16_t,
int); int);
static int pf_test_fragment(struct pf_rule **, int, static int pf_test_fragment(struct pf_krule **, int,
struct pfi_kif *, struct mbuf *, void *, struct pfi_kif *, struct mbuf *, void *,
struct pf_pdesc *, struct pf_rule **, struct pf_pdesc *, struct pf_krule **,
struct pf_ruleset **); struct pf_kruleset **);
static int pf_tcp_track_full(struct pf_state_peer *, static int pf_tcp_track_full(struct pf_state_peer *,
struct pf_state_peer *, struct pf_state **, struct pf_state_peer *, struct pf_state **,
struct pfi_kif *, struct mbuf *, int, struct pfi_kif *, struct mbuf *, int,
@ -295,20 +295,20 @@ static struct pf_state *pf_find_state(struct pfi_kif *,
static int pf_src_connlimit(struct pf_state **); static int pf_src_connlimit(struct pf_state **);
static void pf_overload_task(void *v, int pending); static void pf_overload_task(void *v, int pending);
static int pf_insert_src_node(struct pf_ksrc_node **, static int pf_insert_src_node(struct pf_ksrc_node **,
struct pf_rule *, struct pf_addr *, sa_family_t); struct pf_krule *, struct pf_addr *, sa_family_t);
static u_int pf_purge_expired_states(u_int, int); static u_int pf_purge_expired_states(u_int, int);
static void pf_purge_unlinked_rules(void); static void pf_purge_unlinked_rules(void);
static int pf_mtag_uminit(void *, int, int); static int pf_mtag_uminit(void *, int, int);
static void pf_mtag_free(struct m_tag *); static void pf_mtag_free(struct m_tag *);
#ifdef INET #ifdef INET
static void pf_route(struct mbuf **, struct pf_rule *, int, static void pf_route(struct mbuf **, struct pf_krule *, int,
struct ifnet *, struct pf_state *, struct ifnet *, struct pf_state *,
struct pf_pdesc *, struct inpcb *); struct pf_pdesc *, struct inpcb *);
#endif /* INET */ #endif /* INET */
#ifdef INET6 #ifdef INET6
static void pf_change_a6(struct pf_addr *, u_int16_t *, static void pf_change_a6(struct pf_addr *, u_int16_t *,
struct pf_addr *, u_int8_t); struct pf_addr *, u_int8_t);
static void pf_route6(struct mbuf **, struct pf_rule *, int, static void pf_route6(struct mbuf **, struct pf_krule *, int,
struct ifnet *, struct pf_state *, struct ifnet *, struct pf_state *,
struct pf_pdesc *, struct inpcb *); struct pf_pdesc *, struct inpcb *);
#endif /* INET6 */ #endif /* INET6 */
@ -678,7 +678,7 @@ pf_overload_task(void *v, int pending)
* allocate and insert a new one. * allocate and insert a new one.
*/ */
struct pf_ksrc_node * struct pf_ksrc_node *
pf_find_src_node(struct pf_addr *src, struct pf_rule *rule, sa_family_t af, pf_find_src_node(struct pf_addr *src, struct pf_krule *rule, sa_family_t af,
int returnlocked) int returnlocked)
{ {
struct pf_srchash *sh; struct pf_srchash *sh;
@ -716,7 +716,7 @@ pf_free_src_node(struct pf_ksrc_node *sn)
} }
static int static int
pf_insert_src_node(struct pf_ksrc_node **sn, struct pf_rule *rule, pf_insert_src_node(struct pf_ksrc_node **sn, struct pf_krule *rule,
struct pf_addr *src, sa_family_t af) struct pf_addr *src, sa_family_t af)
{ {
@ -1806,8 +1806,8 @@ pf_purge_expired_states(u_int i, int maxcheck)
static void static void
pf_purge_unlinked_rules() pf_purge_unlinked_rules()
{ {
struct pf_rulequeue tmpq; struct pf_krulequeue tmpq;
struct pf_rule *r, *r1; struct pf_krule *r, *r1;
/* /*
* If we have overloading task pending, then we'd * If we have overloading task pending, then we'd
@ -2032,9 +2032,9 @@ pf_print_flags(u_int8_t f)
} while (0) } while (0)
void void
pf_calc_skip_steps(struct pf_rulequeue *rules) pf_calc_skip_steps(struct pf_krulequeue *rules)
{ {
struct pf_rule *cur, *prev, *head[PF_SKIP_COUNT]; struct pf_krule *cur, *prev, *head[PF_SKIP_COUNT];
int i; int i;
cur = TAILQ_FIRST(rules); cur = TAILQ_FIRST(rules);
@ -2440,7 +2440,7 @@ pf_modulate_sack(struct mbuf *m, int off, struct pf_pdesc *pd,
} }
static void static void
pf_send_tcp(struct mbuf *replyto, const struct pf_rule *r, sa_family_t af, pf_send_tcp(struct mbuf *replyto, const struct pf_krule *r, sa_family_t af,
const struct pf_addr *saddr, const struct pf_addr *daddr, const struct pf_addr *saddr, const struct pf_addr *daddr,
u_int16_t sport, u_int16_t dport, u_int32_t seq, u_int32_t ack, u_int16_t sport, u_int16_t dport, u_int32_t seq, u_int32_t ack,
u_int8_t flags, u_int16_t win, u_int16_t mss, u_int8_t ttl, int tag, u_int8_t flags, u_int16_t win, u_int16_t mss, u_int8_t ttl, int tag,
@ -2600,7 +2600,7 @@ pf_send_tcp(struct mbuf *replyto, const struct pf_rule *r, sa_family_t af,
} }
static void static void
pf_return(struct pf_rule *r, struct pf_rule *nr, struct pf_pdesc *pd, pf_return(struct pf_krule *r, struct pf_krule *nr, struct pf_pdesc *pd,
struct pf_state_key *sk, int off, struct mbuf *m, struct tcphdr *th, struct pf_state_key *sk, int off, struct mbuf *m, struct tcphdr *th,
struct pfi_kif *kif, u_int16_t bproto_sum, u_int16_t bip_sum, int hdrlen, struct pfi_kif *kif, u_int16_t bproto_sum, u_int16_t bip_sum, int hdrlen,
u_short *reason) u_short *reason)
@ -2714,7 +2714,7 @@ pf_match_ieee8021q_pcp(u_int8_t prio, struct mbuf *m)
static void static void
pf_send_icmp(struct mbuf *m, u_int8_t type, u_int8_t code, sa_family_t af, pf_send_icmp(struct mbuf *m, u_int8_t type, u_int8_t code, sa_family_t af,
struct pf_rule *r) struct pf_krule *r)
{ {
struct pf_send_entry *pfse; struct pf_send_entry *pfse;
struct mbuf *m0; struct mbuf *m0;
@ -2902,7 +2902,7 @@ pf_match_gid(u_int8_t op, gid_t a1, gid_t a2, gid_t g)
} }
int int
pf_match_tag(struct mbuf *m, struct pf_rule *r, int *tag, int mtag) pf_match_tag(struct mbuf *m, struct pf_krule *r, int *tag, int mtag)
{ {
if (*tag == -1) if (*tag == -1)
*tag = mtag; *tag = mtag;
@ -2926,10 +2926,10 @@ pf_tag_packet(struct mbuf *m, struct pf_pdesc *pd, int tag)
} }
#define PF_ANCHOR_STACKSIZE 32 #define PF_ANCHOR_STACKSIZE 32
struct pf_anchor_stackframe { struct pf_kanchor_stackframe {
struct pf_ruleset *rs; struct pf_kruleset *rs;
struct pf_rule *r; /* XXX: + match bit */ struct pf_krule *r; /* XXX: + match bit */
struct pf_anchor *child; struct pf_kanchor *child;
}; };
/* /*
@ -2939,18 +2939,18 @@ struct pf_anchor_stackframe {
#define PF_ANCHORSTACK_MASK (PF_ANCHORSTACK_MATCH) #define PF_ANCHORSTACK_MASK (PF_ANCHORSTACK_MATCH)
#define PF_ANCHOR_MATCH(f) ((uintptr_t)(f)->r & PF_ANCHORSTACK_MATCH) #define PF_ANCHOR_MATCH(f) ((uintptr_t)(f)->r & PF_ANCHORSTACK_MATCH)
#define PF_ANCHOR_RULE(f) (struct pf_rule *) \ #define PF_ANCHOR_RULE(f) (struct pf_krule *) \
((uintptr_t)(f)->r & ~PF_ANCHORSTACK_MASK) ((uintptr_t)(f)->r & ~PF_ANCHORSTACK_MASK)
#define PF_ANCHOR_SET_MATCH(f) do { (f)->r = (void *) \ #define PF_ANCHOR_SET_MATCH(f) do { (f)->r = (void *) \
((uintptr_t)(f)->r | PF_ANCHORSTACK_MATCH); \ ((uintptr_t)(f)->r | PF_ANCHORSTACK_MATCH); \
} while (0) } while (0)
void void
pf_step_into_anchor(struct pf_anchor_stackframe *stack, int *depth, pf_step_into_anchor(struct pf_kanchor_stackframe *stack, int *depth,
struct pf_ruleset **rs, int n, struct pf_rule **r, struct pf_rule **a, struct pf_kruleset **rs, int n, struct pf_krule **r, struct pf_krule **a,
int *match) int *match)
{ {
struct pf_anchor_stackframe *f; struct pf_kanchor_stackframe *f;
PF_RULES_RASSERT(); PF_RULES_RASSERT();
@ -2967,9 +2967,9 @@ pf_step_into_anchor(struct pf_anchor_stackframe *stack, int *depth,
f->rs = *rs; f->rs = *rs;
f->r = *r; f->r = *r;
if ((*r)->anchor_wildcard) { if ((*r)->anchor_wildcard) {
struct pf_anchor_node *parent = &(*r)->anchor->children; struct pf_kanchor_node *parent = &(*r)->anchor->children;
if ((f->child = RB_MIN(pf_anchor_node, parent)) == NULL) { if ((f->child = RB_MIN(pf_kanchor_node, parent)) == NULL) {
*r = NULL; *r = NULL;
return; return;
} }
@ -2982,12 +2982,12 @@ pf_step_into_anchor(struct pf_anchor_stackframe *stack, int *depth,
} }
int int
pf_step_out_of_anchor(struct pf_anchor_stackframe *stack, int *depth, pf_step_out_of_anchor(struct pf_kanchor_stackframe *stack, int *depth,
struct pf_ruleset **rs, int n, struct pf_rule **r, struct pf_rule **a, struct pf_kruleset **rs, int n, struct pf_krule **r, struct pf_krule **a,
int *match) int *match)
{ {
struct pf_anchor_stackframe *f; struct pf_kanchor_stackframe *f;
struct pf_rule *fr; struct pf_krule *fr;
int quick = 0; int quick = 0;
PF_RULES_RASSERT(); PF_RULES_RASSERT();
@ -2998,7 +2998,7 @@ pf_step_out_of_anchor(struct pf_anchor_stackframe *stack, int *depth,
f = stack + *depth - 1; f = stack + *depth - 1;
fr = PF_ANCHOR_RULE(f); fr = PF_ANCHOR_RULE(f);
if (f->child != NULL) { if (f->child != NULL) {
struct pf_anchor_node *parent; struct pf_kanchor_node *parent;
/* /*
* This block traverses through * This block traverses through
@ -3014,7 +3014,7 @@ pf_step_out_of_anchor(struct pf_anchor_stackframe *stack, int *depth,
PF_ANCHOR_SET_MATCH(f); PF_ANCHOR_SET_MATCH(f);
*match = 0; *match = 0;
} }
f->child = RB_NEXT(pf_anchor_node, parent, f->child); f->child = RB_NEXT(pf_kanchor_node, parent, f->child);
if (f->child != NULL) { if (f->child != NULL) {
*rs = &f->child->ruleset; *rs = &f->child->ruleset;
*r = TAILQ_FIRST((*rs)->rules[n].active.ptr); *r = TAILQ_FIRST((*rs)->rules[n].active.ptr);
@ -3324,16 +3324,16 @@ pf_tcp_iss(struct pf_pdesc *pd)
} }
static int static int
pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction, pf_test_rule(struct pf_krule **rm, struct pf_state **sm, int direction,
struct pfi_kif *kif, struct mbuf *m, int off, struct pf_pdesc *pd, struct pfi_kif *kif, struct mbuf *m, int off, struct pf_pdesc *pd,
struct pf_rule **am, struct pf_ruleset **rsm, struct inpcb *inp) struct pf_krule **am, struct pf_kruleset **rsm, struct inpcb *inp)
{ {
struct pf_rule *nr = NULL; struct pf_krule *nr = NULL;
struct pf_addr * const saddr = pd->src; struct pf_addr * const saddr = pd->src;
struct pf_addr * const daddr = pd->dst; struct pf_addr * const daddr = pd->dst;
sa_family_t af = pd->af; sa_family_t af = pd->af;
struct pf_rule *r, *a = NULL; struct pf_krule *r, *a = NULL;
struct pf_ruleset *ruleset = NULL; struct pf_kruleset *ruleset = NULL;
struct pf_ksrc_node *nsn = NULL; struct pf_ksrc_node *nsn = NULL;
struct tcphdr *th = pd->hdr.tcp; struct tcphdr *th = pd->hdr.tcp;
struct pf_state_key *sk = NULL, *nk = NULL; struct pf_state_key *sk = NULL, *nk = NULL;
@ -3346,7 +3346,7 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
u_int16_t sport = 0, dport = 0; u_int16_t sport = 0, dport = 0;
u_int16_t bproto_sum = 0, bip_sum = 0; u_int16_t bproto_sum = 0, bip_sum = 0;
u_int8_t icmptype = 0, icmpcode = 0; u_int8_t icmptype = 0, icmpcode = 0;
struct pf_anchor_stackframe anchor_stack[PF_ANCHOR_STACKSIZE]; struct pf_kanchor_stackframe anchor_stack[PF_ANCHOR_STACKSIZE];
PF_RULES_RASSERT(); PF_RULES_RASSERT();
@ -3698,7 +3698,7 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
} }
static int static int
pf_create_state(struct pf_rule *r, struct pf_rule *nr, struct pf_rule *a, pf_create_state(struct pf_krule *r, struct pf_krule *nr, struct pf_krule *a,
struct pf_pdesc *pd, struct pf_ksrc_node *nsn, struct pf_state_key *nk, struct pf_pdesc *pd, struct pf_ksrc_node *nsn, struct pf_state_key *nk,
struct pf_state_key *sk, struct mbuf *m, int off, u_int16_t sport, struct pf_state_key *sk, struct mbuf *m, int off, u_int16_t sport,
u_int16_t dport, int *rewrite, struct pfi_kif *kif, struct pf_state **sm, u_int16_t dport, int *rewrite, struct pfi_kif *kif, struct pf_state **sm,
@ -3960,18 +3960,18 @@ pf_create_state(struct pf_rule *r, struct pf_rule *nr, struct pf_rule *a,
} }
static int static int
pf_test_fragment(struct pf_rule **rm, int direction, struct pfi_kif *kif, pf_test_fragment(struct pf_krule **rm, int direction, struct pfi_kif *kif,
struct mbuf *m, void *h, struct pf_pdesc *pd, struct pf_rule **am, struct mbuf *m, void *h, struct pf_pdesc *pd, struct pf_krule **am,
struct pf_ruleset **rsm) struct pf_kruleset **rsm)
{ {
struct pf_rule *r, *a = NULL; struct pf_krule *r, *a = NULL;
struct pf_ruleset *ruleset = NULL; struct pf_kruleset *ruleset = NULL;
sa_family_t af = pd->af; sa_family_t af = pd->af;
u_short reason; u_short reason;
int tag = -1; int tag = -1;
int asd = 0; int asd = 0;
int match = 0; int match = 0;
struct pf_anchor_stackframe anchor_stack[PF_ANCHOR_STACKSIZE]; struct pf_kanchor_stackframe anchor_stack[PF_ANCHOR_STACKSIZE];
PF_RULES_RASSERT(); PF_RULES_RASSERT();
@ -5463,7 +5463,7 @@ pf_routable(struct pf_addr *addr, sa_family_t af, struct pfi_kif *kif,
#ifdef INET #ifdef INET
static void static void
pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp, pf_route(struct mbuf **m, struct pf_krule *r, int dir, struct ifnet *oifp,
struct pf_state *s, struct pf_pdesc *pd, struct inpcb *inp) struct pf_state *s, struct pf_pdesc *pd, struct inpcb *inp)
{ {
struct mbuf *m0, *m1; struct mbuf *m0, *m1;
@ -5626,7 +5626,7 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
#ifdef INET6 #ifdef INET6
static void static void
pf_route6(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp, pf_route6(struct mbuf **m, struct pf_krule *r, int dir, struct ifnet *oifp,
struct pf_state *s, struct pf_pdesc *pd, struct inpcb *inp) struct pf_state *s, struct pf_pdesc *pd, struct inpcb *inp)
{ {
struct mbuf *m0; struct mbuf *m0;
@ -5893,9 +5893,9 @@ pf_test(int dir, int pflags, struct ifnet *ifp, struct mbuf **m0, struct inpcb *
struct mbuf *m = *m0; struct mbuf *m = *m0;
struct ip *h = NULL; struct ip *h = NULL;
struct m_tag *ipfwtag; struct m_tag *ipfwtag;
struct pf_rule *a = NULL, *r = &V_pf_default_rule, *tr, *nr; struct pf_krule *a = NULL, *r = &V_pf_default_rule, *tr, *nr;
struct pf_state *s = NULL; struct pf_state *s = NULL;
struct pf_ruleset *ruleset = NULL; struct pf_kruleset *ruleset = NULL;
struct pf_pdesc pd; struct pf_pdesc pd;
int off, dirndx, pqid = 0; int off, dirndx, pqid = 0;
@ -6185,7 +6185,7 @@ pf_test(int dir, int pflags, struct ifnet *ifp, struct mbuf **m0, struct inpcb *
} }
if (log) { if (log) {
struct pf_rule *lr; struct pf_krule *lr;
if (s != NULL && s->nat_rule.ptr != NULL && if (s != NULL && s->nat_rule.ptr != NULL &&
s->nat_rule.ptr->log & PF_LOG_ALL) s->nat_rule.ptr->log & PF_LOG_ALL)
@ -6283,9 +6283,9 @@ pf_test6(int dir, int pflags, struct ifnet *ifp, struct mbuf **m0, struct inpcb
struct mbuf *m = *m0, *n = NULL; struct mbuf *m = *m0, *n = NULL;
struct m_tag *mtag; struct m_tag *mtag;
struct ip6_hdr *h = NULL; struct ip6_hdr *h = NULL;
struct pf_rule *a = NULL, *r = &V_pf_default_rule, *tr, *nr; struct pf_krule *a = NULL, *r = &V_pf_default_rule, *tr, *nr;
struct pf_state *s = NULL; struct pf_state *s = NULL;
struct pf_ruleset *ruleset = NULL; struct pf_kruleset *ruleset = NULL;
struct pf_pdesc pd; struct pf_pdesc pd;
int off, terminal = 0, dirndx, rh_cnt = 0, pqid = 0; int off, terminal = 0, dirndx, rh_cnt = 0, pqid = 0;
@ -6585,7 +6585,7 @@ pf_test6(int dir, int pflags, struct ifnet *ifp, struct mbuf **m0, struct inpcb
printf("pf: divert(9) is not supported for IPv6\n"); printf("pf: divert(9) is not supported for IPv6\n");
if (log) { if (log) {
struct pf_rule *lr; struct pf_krule *lr;
if (s != NULL && s->nat_rule.ptr != NULL && if (s != NULL && s->nat_rule.ptr != NULL &&
s->nat_rule.ptr->log & PF_LOG_ALL) s->nat_rule.ptr->log & PF_LOG_ALL)

View File

@ -35,6 +35,8 @@
#ifndef _NET_PF_H_ #ifndef _NET_PF_H_
#define _NET_PF_H_ #define _NET_PF_H_
#include <sys/tree.h>
#define PF_TCPS_PROXY_SRC ((TCP_NSTATES)+0) #define PF_TCPS_PROXY_SRC ((TCP_NSTATES)+0)
#define PF_TCPS_PROXY_DST ((TCP_NSTATES)+1) #define PF_TCPS_PROXY_DST ((TCP_NSTATES)+1)
@ -569,4 +571,50 @@ struct pf_src_node {
#define PFSNODE_HIWAT 10000 /* default source node table size */ #define PFSNODE_HIWAT 10000 /* default source node table size */
TAILQ_HEAD(pf_rulequeue, pf_rule);
struct pf_anchor;
struct pf_ruleset {
struct {
struct pf_rulequeue queues[2];
struct {
struct pf_rulequeue *ptr;
struct pf_rule **ptr_array;
u_int32_t rcount;
u_int32_t ticket;
int open;
} active, inactive;
} rules[PF_RULESET_MAX];
struct pf_anchor *anchor;
u_int32_t tticket;
int tables;
int topen;
};
RB_HEAD(pf_anchor_global, pf_anchor);
RB_HEAD(pf_anchor_node, pf_anchor);
struct pf_anchor {
RB_ENTRY(pf_anchor) entry_global;
RB_ENTRY(pf_anchor) entry_node;
struct pf_anchor *parent;
struct pf_anchor_node children;
char name[PF_ANCHOR_NAME_SIZE];
char path[MAXPATHLEN];
struct pf_ruleset ruleset;
int refcnt; /* anchor rules */
int match; /* XXX: used for pfctl black magic */
};
RB_PROTOTYPE(pf_anchor_global, pf_anchor, entry_global, pf_anchor_compare);
RB_PROTOTYPE(pf_anchor_node, pf_anchor, entry_node, pf_anchor_compare);
/* these ruleset functions can be linked into userland programs (pfctl) */
int pf_get_ruleset_number(u_int8_t);
void pf_init_ruleset(struct pf_ruleset *);
int pf_anchor_setup(struct pf_rule *,
const struct pf_ruleset *, const char *);
void pf_remove_if_empty_ruleset(struct pf_ruleset *);
struct pf_ruleset *pf_find_ruleset(const char *);
struct pf_ruleset *pf_find_or_create_ruleset(const char *);
#endif /* _NET_PF_H_ */ #endif /* _NET_PF_H_ */

View File

@ -403,7 +403,7 @@ pfi_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af)
struct epoch_tracker et; struct epoch_tracker et;
struct pfi_dynaddr *dyn; struct pfi_dynaddr *dyn;
char tblname[PF_TABLE_NAME_SIZE]; char tblname[PF_TABLE_NAME_SIZE];
struct pf_ruleset *ruleset = NULL; struct pf_kruleset *ruleset = NULL;
struct pfi_kif *kif; struct pfi_kif *kif;
int rv = 0; int rv = 0;
@ -441,7 +441,7 @@ pfi_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af)
if (dyn->pfid_net != 128) if (dyn->pfid_net != 128)
snprintf(tblname + strlen(tblname), snprintf(tblname + strlen(tblname),
sizeof(tblname) - strlen(tblname), "/%d", dyn->pfid_net); sizeof(tblname) - strlen(tblname), "/%d", dyn->pfid_net);
if ((ruleset = pf_find_or_create_ruleset(PF_RESERVED_ANCHOR)) == NULL) { if ((ruleset = pf_find_or_create_kruleset(PF_RESERVED_ANCHOR)) == NULL) {
rv = ENOMEM; rv = ENOMEM;
goto _bad; goto _bad;
} }
@ -467,7 +467,7 @@ pfi_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af)
if (dyn->pfid_kt != NULL) if (dyn->pfid_kt != NULL)
pfr_detach_table(dyn->pfid_kt); pfr_detach_table(dyn->pfid_kt);
if (ruleset != NULL) if (ruleset != NULL)
pf_remove_if_empty_ruleset(ruleset); pf_remove_if_empty_kruleset(ruleset);
if (dyn->pfid_kif != NULL) if (dyn->pfid_kif != NULL)
pfi_kif_unref(dyn->pfid_kif); pfi_kif_unref(dyn->pfid_kif);
free(dyn, PFI_MTYPE); free(dyn, PFI_MTYPE);

View File

@ -109,11 +109,11 @@ static void pf_qid_unref(u_int32_t);
#endif /* ALTQ */ #endif /* ALTQ */
static int pf_begin_rules(u_int32_t *, int, const char *); static int pf_begin_rules(u_int32_t *, int, const char *);
static int pf_rollback_rules(u_int32_t, int, char *); static int pf_rollback_rules(u_int32_t, int, char *);
static int pf_setup_pfsync_matching(struct pf_ruleset *); static int pf_setup_pfsync_matching(struct pf_kruleset *);
static void pf_hash_rule(MD5_CTX *, struct pf_rule *); static void pf_hash_rule(MD5_CTX *, struct pf_krule *);
static void pf_hash_rule_addr(MD5_CTX *, struct pf_rule_addr *); static void pf_hash_rule_addr(MD5_CTX *, struct pf_rule_addr *);
static int pf_commit_rules(u_int32_t, int, char *); static int pf_commit_rules(u_int32_t, int, char *);
static int pf_addr_setup(struct pf_ruleset *, static int pf_addr_setup(struct pf_kruleset *,
struct pf_addr_wrap *, sa_family_t); struct pf_addr_wrap *, sa_family_t);
static void pf_addr_copyout(struct pf_addr_wrap *); static void pf_addr_copyout(struct pf_addr_wrap *);
static void pf_src_node_copy(const struct pf_ksrc_node *, static void pf_src_node_copy(const struct pf_ksrc_node *,
@ -125,7 +125,7 @@ static int pf_import_kaltq(struct pfioc_altq_v1 *,
struct pf_altq *, size_t); struct pf_altq *, size_t);
#endif /* ALTQ */ #endif /* ALTQ */
VNET_DEFINE(struct pf_rule, pf_default_rule); VNET_DEFINE(struct pf_krule, pf_default_rule);
#ifdef ALTQ #ifdef ALTQ
VNET_DEFINE_STATIC(int, pf_altq_running); VNET_DEFINE_STATIC(int, pf_altq_running);
@ -271,7 +271,7 @@ pfattach_vnet(void)
V_pf_limits[PF_LIMIT_SRC_NODES].limit = PFSNODE_HIWAT; V_pf_limits[PF_LIMIT_SRC_NODES].limit = PFSNODE_HIWAT;
RB_INIT(&V_pf_anchors); RB_INIT(&V_pf_anchors);
pf_init_ruleset(&pf_main_ruleset); pf_init_kruleset(&pf_main_ruleset);
/* default rule should never be garbage collected */ /* default rule should never be garbage collected */
V_pf_default_rule.entries.tqe_prev = &V_pf_default_rule.entries.tqe_next; V_pf_default_rule.entries.tqe_prev = &V_pf_default_rule.entries.tqe_next;
@ -337,11 +337,11 @@ pf_get_pool(char *anchor, u_int32_t ticket, u_int8_t rule_action,
u_int32_t rule_number, u_int8_t r_last, u_int8_t active, u_int32_t rule_number, u_int8_t r_last, u_int8_t active,
u_int8_t check_ticket) u_int8_t check_ticket)
{ {
struct pf_ruleset *ruleset; struct pf_kruleset *ruleset;
struct pf_rule *rule; struct pf_krule *rule;
int rs_num; int rs_num;
ruleset = pf_find_ruleset(anchor); ruleset = pf_find_kruleset(anchor);
if (ruleset == NULL) if (ruleset == NULL)
return (NULL); return (NULL);
rs_num = pf_get_ruleset_number(rule_action); rs_num = pf_get_ruleset_number(rule_action);
@ -353,7 +353,7 @@ pf_get_pool(char *anchor, u_int32_t ticket, u_int8_t rule_action,
return (NULL); return (NULL);
if (r_last) if (r_last)
rule = TAILQ_LAST(ruleset->rules[rs_num].active.ptr, rule = TAILQ_LAST(ruleset->rules[rs_num].active.ptr,
pf_rulequeue); pf_krulequeue);
else else
rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr); rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr);
} else { } else {
@ -362,7 +362,7 @@ pf_get_pool(char *anchor, u_int32_t ticket, u_int8_t rule_action,
return (NULL); return (NULL);
if (r_last) if (r_last)
rule = TAILQ_LAST(ruleset->rules[rs_num].inactive.ptr, rule = TAILQ_LAST(ruleset->rules[rs_num].inactive.ptr,
pf_rulequeue); pf_krulequeue);
else else
rule = TAILQ_FIRST(ruleset->rules[rs_num].inactive.ptr); rule = TAILQ_FIRST(ruleset->rules[rs_num].inactive.ptr);
} }
@ -411,7 +411,7 @@ pf_empty_pool(struct pf_palist *poola)
} }
static void static void
pf_unlink_rule(struct pf_rulequeue *rulequeue, struct pf_rule *rule) pf_unlink_rule(struct pf_krulequeue *rulequeue, struct pf_krule *rule)
{ {
PF_RULES_WASSERT(); PF_RULES_WASSERT();
@ -425,7 +425,7 @@ pf_unlink_rule(struct pf_rulequeue *rulequeue, struct pf_rule *rule)
} }
void void
pf_free_rule(struct pf_rule *rule) pf_free_rule(struct pf_krule *rule)
{ {
PF_RULES_WASSERT(); PF_RULES_WASSERT();
@ -459,7 +459,7 @@ pf_free_rule(struct pf_rule *rule)
pfr_detach_table(rule->overload_tbl); pfr_detach_table(rule->overload_tbl);
if (rule->kif) if (rule->kif)
pfi_kif_unref(rule->kif); pfi_kif_unref(rule->kif);
pf_anchor_remove(rule); pf_kanchor_remove(rule);
pf_empty_pool(&rule->rpool.list); pf_empty_pool(&rule->rpool.list);
counter_u64_free(rule->states_cur); counter_u64_free(rule->states_cur);
counter_u64_free(rule->states_tot); counter_u64_free(rule->states_tot);
@ -896,14 +896,14 @@ pf_altq_ifnet_event(struct ifnet *ifp, int remove)
static int static int
pf_begin_rules(u_int32_t *ticket, int rs_num, const char *anchor) pf_begin_rules(u_int32_t *ticket, int rs_num, const char *anchor)
{ {
struct pf_ruleset *rs; struct pf_kruleset *rs;
struct pf_rule *rule; struct pf_krule *rule;
PF_RULES_WASSERT(); PF_RULES_WASSERT();
if (rs_num < 0 || rs_num >= PF_RULESET_MAX) if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
return (EINVAL); return (EINVAL);
rs = pf_find_or_create_ruleset(anchor); rs = pf_find_or_create_kruleset(anchor);
if (rs == NULL) if (rs == NULL)
return (EINVAL); return (EINVAL);
while ((rule = TAILQ_FIRST(rs->rules[rs_num].inactive.ptr)) != NULL) { while ((rule = TAILQ_FIRST(rs->rules[rs_num].inactive.ptr)) != NULL) {
@ -918,14 +918,14 @@ pf_begin_rules(u_int32_t *ticket, int rs_num, const char *anchor)
static int static int
pf_rollback_rules(u_int32_t ticket, int rs_num, char *anchor) pf_rollback_rules(u_int32_t ticket, int rs_num, char *anchor)
{ {
struct pf_ruleset *rs; struct pf_kruleset *rs;
struct pf_rule *rule; struct pf_krule *rule;
PF_RULES_WASSERT(); PF_RULES_WASSERT();
if (rs_num < 0 || rs_num >= PF_RULESET_MAX) if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
return (EINVAL); return (EINVAL);
rs = pf_find_ruleset(anchor); rs = pf_find_kruleset(anchor);
if (rs == NULL || !rs->rules[rs_num].inactive.open || if (rs == NULL || !rs->rules[rs_num].inactive.open ||
rs->rules[rs_num].inactive.ticket != ticket) rs->rules[rs_num].inactive.ticket != ticket)
return (0); return (0);
@ -979,7 +979,7 @@ pf_hash_rule_addr(MD5_CTX *ctx, struct pf_rule_addr *pfr)
} }
static void static void
pf_hash_rule(MD5_CTX *ctx, struct pf_rule *rule) pf_hash_rule(MD5_CTX *ctx, struct pf_krule *rule)
{ {
u_int16_t x; u_int16_t x;
u_int32_t y; u_int32_t y;
@ -1020,9 +1020,9 @@ pf_hash_rule(MD5_CTX *ctx, struct pf_rule *rule)
static int static int
pf_commit_rules(u_int32_t ticket, int rs_num, char *anchor) pf_commit_rules(u_int32_t ticket, int rs_num, char *anchor)
{ {
struct pf_ruleset *rs; struct pf_kruleset *rs;
struct pf_rule *rule, **old_array; struct pf_krule *rule, **old_array;
struct pf_rulequeue *old_rules; struct pf_krulequeue *old_rules;
int error; int error;
u_int32_t old_rcount; u_int32_t old_rcount;
@ -1030,7 +1030,7 @@ pf_commit_rules(u_int32_t ticket, int rs_num, char *anchor)
if (rs_num < 0 || rs_num >= PF_RULESET_MAX) if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
return (EINVAL); return (EINVAL);
rs = pf_find_ruleset(anchor); rs = pf_find_kruleset(anchor);
if (rs == NULL || !rs->rules[rs_num].inactive.open || if (rs == NULL || !rs->rules[rs_num].inactive.open ||
ticket != rs->rules[rs_num].inactive.ticket) ticket != rs->rules[rs_num].inactive.ticket)
return (EBUSY); return (EBUSY);
@ -1069,16 +1069,16 @@ pf_commit_rules(u_int32_t ticket, int rs_num, char *anchor)
rs->rules[rs_num].inactive.ptr_array = NULL; rs->rules[rs_num].inactive.ptr_array = NULL;
rs->rules[rs_num].inactive.rcount = 0; rs->rules[rs_num].inactive.rcount = 0;
rs->rules[rs_num].inactive.open = 0; rs->rules[rs_num].inactive.open = 0;
pf_remove_if_empty_ruleset(rs); pf_remove_if_empty_kruleset(rs);
return (0); return (0);
} }
static int static int
pf_setup_pfsync_matching(struct pf_ruleset *rs) pf_setup_pfsync_matching(struct pf_kruleset *rs)
{ {
MD5_CTX ctx; MD5_CTX ctx;
struct pf_rule *rule; struct pf_krule *rule;
int rs_cnt; int rs_cnt;
u_int8_t digest[PF_MD5_DIGEST_LENGTH]; u_int8_t digest[PF_MD5_DIGEST_LENGTH];
@ -1115,7 +1115,7 @@ pf_setup_pfsync_matching(struct pf_ruleset *rs)
} }
static int static int
pf_addr_setup(struct pf_ruleset *ruleset, struct pf_addr_wrap *addr, pf_addr_setup(struct pf_kruleset *ruleset, struct pf_addr_wrap *addr,
sa_family_t af) sa_family_t af)
{ {
int error = 0; int error = 0;
@ -1425,6 +1425,194 @@ pf_altq_get_nth_active(u_int32_t n)
} }
#endif /* ALTQ */ #endif /* ALTQ */
static void
pf_krule_to_rule(const struct pf_krule *krule, struct pf_rule *rule)
{
bzero(rule, sizeof(*rule));
bcopy(&krule->src, &rule->src, sizeof(rule->src));
bcopy(&krule->dst, &rule->dst, sizeof(rule->dst));
for (int i = 0; i < PF_SKIP_COUNT; ++i) {
if (rule->skip[i].ptr == NULL)
rule->skip[i].nr = -1;
else
rule->skip[i].nr = krule->skip[i].ptr->nr;
}
strlcpy(rule->label, krule->label, sizeof(rule->label));
strlcpy(rule->ifname, krule->ifname, sizeof(rule->ifname));
strlcpy(rule->qname, krule->qname, sizeof(rule->qname));
strlcpy(rule->pqname, krule->pqname, sizeof(rule->pqname));
strlcpy(rule->tagname, krule->tagname, sizeof(rule->tagname));
strlcpy(rule->match_tagname, krule->match_tagname,
sizeof(rule->match_tagname));
strlcpy(rule->overload_tblname, krule->overload_tblname,
sizeof(rule->overload_tblname));
bcopy(&krule->rpool, &rule->rpool, sizeof(krule->rpool));
rule->evaluations = krule->evaluations;
for (int i = 0; i < 2; i++) {
rule->packets[i] = krule->packets[i];
rule->bytes[i] = krule->bytes[i];
}
/* kif, anchor, overload_tbl are not copied over. */
rule->os_fingerprint = krule->os_fingerprint;
rule->rtableid = krule->rtableid;
bcopy(krule->timeout, rule->timeout, sizeof(krule->timeout));
rule->max_states = krule->max_states;
rule->max_src_nodes = krule->max_src_nodes;
rule->max_src_states = krule->max_src_states;
rule->max_src_conn = krule->max_src_conn;
rule->max_src_conn_rate.limit = krule->max_src_conn_rate.limit;
rule->max_src_conn_rate.seconds = krule->max_src_conn_rate.seconds;
rule->qid = krule->qid;
rule->pqid = krule->pqid;
rule->rt_listid = krule->rt_listid;
rule->nr = krule->nr;
rule->prob = krule->prob;
rule->cuid = krule->cuid;
rule->cpid = krule->cpid;
rule->return_icmp = krule->return_icmp;
rule->return_icmp6 = krule->return_icmp6;
rule->max_mss = krule->max_mss;
rule->tag = krule->tag;
rule->match_tag = krule->match_tag;
rule->scrub_flags = krule->scrub_flags;
bcopy(&krule->uid, &rule->uid, sizeof(krule->uid));
bcopy(&krule->gid, &rule->gid, sizeof(krule->gid));
rule->rule_flag = krule->rule_flag;
rule->action = krule->action;
rule->direction = krule->direction;
rule->log = krule->log;
rule->logif = krule->logif;
rule->quick = krule->quick;
rule->ifnot = krule->ifnot;
rule->match_tag_not = krule->match_tag_not;
rule->natpass = krule->natpass;
rule->keep_state = krule->keep_state;
rule->af = krule->af;
rule->proto = krule->proto;
rule->type = krule->type;
rule->code = krule->code;
rule->flags = krule->flags;
rule->flagset = krule->flagset;
rule->min_ttl = krule->min_ttl;
rule->allow_opts = krule->allow_opts;
rule->rt = krule->rt;
rule->return_ttl = krule->return_ttl;
rule->tos = krule->tos;
rule->set_tos = krule->set_tos;
rule->anchor_relative = krule->anchor_relative;
rule->anchor_wildcard = krule->anchor_wildcard;
rule->flush = krule->flush;
rule->prio = krule->prio;
rule->set_prio[0] = krule->set_prio[0];
rule->set_prio[1] = krule->set_prio[1];
bcopy(&krule->divert, &rule->divert, sizeof(krule->divert));
rule->u_states_cur = counter_u64_fetch(krule->states_cur);
rule->u_states_tot = counter_u64_fetch(krule->states_tot);
rule->u_src_nodes = counter_u64_fetch(krule->src_nodes);
}
static void
pf_rule_to_krule(const struct pf_rule *rule, struct pf_krule *krule)
{
bzero(krule, sizeof(*krule));
bcopy(&rule->src, &krule->src, sizeof(rule->src));
bcopy(&rule->dst, &krule->dst, sizeof(rule->dst));
strlcpy(krule->label, rule->label, sizeof(rule->label));
strlcpy(krule->ifname, rule->ifname, sizeof(rule->ifname));
strlcpy(krule->qname, rule->qname, sizeof(rule->qname));
strlcpy(krule->pqname, rule->pqname, sizeof(rule->pqname));
strlcpy(krule->tagname, rule->tagname, sizeof(rule->tagname));
strlcpy(krule->match_tagname, rule->match_tagname,
sizeof(rule->match_tagname));
strlcpy(krule->overload_tblname, rule->overload_tblname,
sizeof(rule->overload_tblname));
bcopy(&rule->rpool, &krule->rpool, sizeof(krule->rpool));
/* Don't allow userspace to set evaulations, packets or bytes. */
/* kif, anchor, overload_tbl are not copied over. */
krule->os_fingerprint = krule->os_fingerprint;
krule->rtableid = rule->rtableid;
bcopy(rule->timeout, krule->timeout, sizeof(krule->timeout));
krule->max_states = rule->max_states;
krule->max_src_nodes = rule->max_src_nodes;
krule->max_src_states = rule->max_src_states;
krule->max_src_conn = rule->max_src_conn;
krule->max_src_conn_rate.limit = rule->max_src_conn_rate.limit;
krule->max_src_conn_rate.seconds = rule->max_src_conn_rate.seconds;
krule->qid = rule->qid;
krule->pqid = rule->pqid;
krule->rt_listid = rule->rt_listid;
krule->nr = rule->nr;
krule->prob = rule->prob;
krule->cuid = rule->cuid;
krule->cpid = rule->cpid;
krule->return_icmp = rule->return_icmp;
krule->return_icmp6 = rule->return_icmp6;
krule->max_mss = rule->max_mss;
krule->tag = rule->tag;
krule->match_tag = rule->match_tag;
krule->scrub_flags = rule->scrub_flags;
bcopy(&rule->uid, &krule->uid, sizeof(krule->uid));
bcopy(&rule->gid, &krule->gid, sizeof(krule->gid));
krule->rule_flag = rule->rule_flag;
krule->action = rule->action;
krule->direction = rule->direction;
krule->log = rule->log;
krule->logif = rule->logif;
krule->quick = rule->quick;
krule->ifnot = rule->ifnot;
krule->match_tag_not = rule->match_tag_not;
krule->natpass = rule->natpass;
krule->keep_state = rule->keep_state;
krule->af = rule->af;
krule->proto = rule->proto;
krule->type = rule->type;
krule->code = rule->code;
krule->flags = rule->flags;
krule->flagset = rule->flagset;
krule->min_ttl = rule->min_ttl;
krule->allow_opts = rule->allow_opts;
krule->rt = rule->rt;
krule->return_ttl = rule->return_ttl;
krule->tos = rule->tos;
krule->set_tos = rule->set_tos;
krule->anchor_relative = rule->anchor_relative;
krule->anchor_wildcard = rule->anchor_wildcard;
krule->flush = rule->flush;
krule->prio = rule->prio;
krule->set_prio[0] = rule->set_prio[0];
krule->set_prio[1] = rule->set_prio[1];
bcopy(&rule->divert, &krule->divert, sizeof(krule->divert));
}
static int static int
pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td) pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td)
{ {
@ -1587,8 +1775,8 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
case DIOCADDRULE: { case DIOCADDRULE: {
struct pfioc_rule *pr = (struct pfioc_rule *)addr; struct pfioc_rule *pr = (struct pfioc_rule *)addr;
struct pf_ruleset *ruleset; struct pf_kruleset *ruleset;
struct pf_rule *rule, *tail; struct pf_krule *rule, *tail;
struct pf_pooladdr *pa; struct pf_pooladdr *pa;
struct pfi_kif *kif = NULL; struct pfi_kif *kif = NULL;
int rs_num; int rs_num;
@ -1616,7 +1804,8 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
#endif /* INET6 */ #endif /* INET6 */
rule = malloc(sizeof(*rule), M_PFRULE, M_WAITOK); rule = malloc(sizeof(*rule), M_PFRULE, M_WAITOK);
bcopy(&pr->rule, rule, sizeof(struct pf_rule)); pf_rule_to_krule(&pr->rule, rule);
if (rule->ifname[0]) if (rule->ifname[0])
kif = malloc(sizeof(*kif), PFI_MTYPE, M_WAITOK); kif = malloc(sizeof(*kif), PFI_MTYPE, M_WAITOK);
rule->states_cur = counter_u64_alloc(M_WAITOK); rule->states_cur = counter_u64_alloc(M_WAITOK);
@ -1629,7 +1818,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
PF_RULES_WLOCK(); PF_RULES_WLOCK();
pr->anchor[sizeof(pr->anchor) - 1] = 0; pr->anchor[sizeof(pr->anchor) - 1] = 0;
ruleset = pf_find_ruleset(pr->anchor); ruleset = pf_find_kruleset(pr->anchor);
if (ruleset == NULL) if (ruleset == NULL)
ERROUT(EINVAL); ERROUT(EINVAL);
rs_num = pf_get_ruleset_number(pr->rule.action); rs_num = pf_get_ruleset_number(pr->rule.action);
@ -1649,7 +1838,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
} }
tail = TAILQ_LAST(ruleset->rules[rs_num].inactive.ptr, tail = TAILQ_LAST(ruleset->rules[rs_num].inactive.ptr,
pf_rulequeue); pf_krulequeue);
if (tail) if (tail)
rule->nr = tail->nr + 1; rule->nr = tail->nr + 1;
else else
@ -1693,7 +1882,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
error = ENOMEM; error = ENOMEM;
if (pf_addr_setup(ruleset, &rule->dst.addr, rule->af)) if (pf_addr_setup(ruleset, &rule->dst.addr, rule->af))
error = ENOMEM; error = ENOMEM;
if (pf_anchor_setup(rule, ruleset, pr->anchor_call)) if (pf_kanchor_setup(rule, ruleset, pr->anchor_call))
error = EINVAL; error = EINVAL;
if (rule->scrub_flags & PFSTATE_SETPRIO && if (rule->scrub_flags & PFSTATE_SETPRIO &&
(rule->set_prio[0] > PF_PRIO_MAX || (rule->set_prio[0] > PF_PRIO_MAX ||
@ -1753,13 +1942,13 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
case DIOCGETRULES: { case DIOCGETRULES: {
struct pfioc_rule *pr = (struct pfioc_rule *)addr; struct pfioc_rule *pr = (struct pfioc_rule *)addr;
struct pf_ruleset *ruleset; struct pf_kruleset *ruleset;
struct pf_rule *tail; struct pf_krule *tail;
int rs_num; int rs_num;
PF_RULES_WLOCK(); PF_RULES_WLOCK();
pr->anchor[sizeof(pr->anchor) - 1] = 0; pr->anchor[sizeof(pr->anchor) - 1] = 0;
ruleset = pf_find_ruleset(pr->anchor); ruleset = pf_find_kruleset(pr->anchor);
if (ruleset == NULL) { if (ruleset == NULL) {
PF_RULES_WUNLOCK(); PF_RULES_WUNLOCK();
error = EINVAL; error = EINVAL;
@ -1772,7 +1961,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
break; break;
} }
tail = TAILQ_LAST(ruleset->rules[rs_num].active.ptr, tail = TAILQ_LAST(ruleset->rules[rs_num].active.ptr,
pf_rulequeue); pf_krulequeue);
if (tail) if (tail)
pr->nr = tail->nr + 1; pr->nr = tail->nr + 1;
else else
@ -1784,13 +1973,13 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
case DIOCGETRULE: { case DIOCGETRULE: {
struct pfioc_rule *pr = (struct pfioc_rule *)addr; struct pfioc_rule *pr = (struct pfioc_rule *)addr;
struct pf_ruleset *ruleset; struct pf_kruleset *ruleset;
struct pf_rule *rule; struct pf_krule *rule;
int rs_num, i; int rs_num;
PF_RULES_WLOCK(); PF_RULES_WLOCK();
pr->anchor[sizeof(pr->anchor) - 1] = 0; pr->anchor[sizeof(pr->anchor) - 1] = 0;
ruleset = pf_find_ruleset(pr->anchor); ruleset = pf_find_kruleset(pr->anchor);
if (ruleset == NULL) { if (ruleset == NULL) {
PF_RULES_WUNLOCK(); PF_RULES_WUNLOCK();
error = EINVAL; error = EINVAL;
@ -1815,23 +2004,16 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
error = EBUSY; error = EBUSY;
break; break;
} }
bcopy(rule, &pr->rule, sizeof(struct pf_rule));
pr->rule.u_states_cur = counter_u64_fetch(rule->states_cur); pf_krule_to_rule(rule, &pr->rule);
pr->rule.u_states_tot = counter_u64_fetch(rule->states_tot);
pr->rule.u_src_nodes = counter_u64_fetch(rule->src_nodes); if (pf_kanchor_copyout(ruleset, rule, pr)) {
if (pf_anchor_copyout(ruleset, rule, pr)) {
PF_RULES_WUNLOCK(); PF_RULES_WUNLOCK();
error = EBUSY; error = EBUSY;
break; break;
} }
pf_addr_copyout(&pr->rule.src.addr); pf_addr_copyout(&pr->rule.src.addr);
pf_addr_copyout(&pr->rule.dst.addr); pf_addr_copyout(&pr->rule.dst.addr);
for (i = 0; i < PF_SKIP_COUNT; ++i)
if (rule->skip[i].ptr == NULL)
pr->rule.skip[i].nr = -1;
else
pr->rule.skip[i].nr =
rule->skip[i].ptr->nr;
if (pr->action == PF_GET_CLR_CNTR) { if (pr->action == PF_GET_CLR_CNTR) {
rule->evaluations = 0; rule->evaluations = 0;
@ -1845,8 +2027,8 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
case DIOCCHANGERULE: { case DIOCCHANGERULE: {
struct pfioc_rule *pcr = (struct pfioc_rule *)addr; struct pfioc_rule *pcr = (struct pfioc_rule *)addr;
struct pf_ruleset *ruleset; struct pf_kruleset *ruleset;
struct pf_rule *oldrule = NULL, *newrule = NULL; struct pf_krule *oldrule = NULL, *newrule = NULL;
struct pfi_kif *kif = NULL; struct pfi_kif *kif = NULL;
struct pf_pooladdr *pa; struct pf_pooladdr *pa;
u_int32_t nr = 0; u_int32_t nr = 0;
@ -1876,7 +2058,8 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
} }
#endif /* INET6 */ #endif /* INET6 */
newrule = malloc(sizeof(*newrule), M_PFRULE, M_WAITOK); newrule = malloc(sizeof(*newrule), M_PFRULE, M_WAITOK);
bcopy(&pcr->rule, newrule, sizeof(struct pf_rule)); pf_rule_to_krule(&pcr->rule, newrule);
if (newrule->ifname[0]) if (newrule->ifname[0])
kif = malloc(sizeof(*kif), PFI_MTYPE, M_WAITOK); kif = malloc(sizeof(*kif), PFI_MTYPE, M_WAITOK);
newrule->states_cur = counter_u64_alloc(M_WAITOK); newrule->states_cur = counter_u64_alloc(M_WAITOK);
@ -1894,7 +2077,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
pcr->pool_ticket != V_ticket_pabuf) pcr->pool_ticket != V_ticket_pabuf)
ERROUT(EBUSY); ERROUT(EBUSY);
ruleset = pf_find_ruleset(pcr->anchor); ruleset = pf_find_kruleset(pcr->anchor);
if (ruleset == NULL) if (ruleset == NULL)
ERROUT(EINVAL); ERROUT(EINVAL);
@ -1953,7 +2136,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
error = ENOMEM; error = ENOMEM;
if (pf_addr_setup(ruleset, &newrule->dst.addr, newrule->af)) if (pf_addr_setup(ruleset, &newrule->dst.addr, newrule->af))
error = ENOMEM; error = ENOMEM;
if (pf_anchor_setup(newrule, ruleset, pcr->anchor_call)) if (pf_kanchor_setup(newrule, ruleset, pcr->anchor_call))
error = EINVAL; error = EINVAL;
TAILQ_FOREACH(pa, &V_pf_pabuf, entries) TAILQ_FOREACH(pa, &V_pf_pabuf, entries)
if (pa->addr.type == PF_ADDR_TABLE) { if (pa->addr.type == PF_ADDR_TABLE) {
@ -2002,7 +2185,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
ruleset->rules[rs_num].active.ptr); ruleset->rules[rs_num].active.ptr);
else if (pcr->action == PF_CHANGE_ADD_TAIL) else if (pcr->action == PF_CHANGE_ADD_TAIL)
oldrule = TAILQ_LAST( oldrule = TAILQ_LAST(
ruleset->rules[rs_num].active.ptr, pf_rulequeue); ruleset->rules[rs_num].active.ptr, pf_krulequeue);
else { else {
oldrule = TAILQ_FIRST( oldrule = TAILQ_FIRST(
ruleset->rules[rs_num].active.ptr); ruleset->rules[rs_num].active.ptr);
@ -2044,7 +2227,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
ruleset->rules[rs_num].active.ticket++; ruleset->rules[rs_num].active.ticket++;
pf_calc_skip_steps(ruleset->rules[rs_num].active.ptr); pf_calc_skip_steps(ruleset->rules[rs_num].active.ptr);
pf_remove_if_empty_ruleset(ruleset); pf_remove_if_empty_kruleset(ruleset);
PF_RULES_WUNLOCK(); PF_RULES_WUNLOCK();
break; break;
@ -2432,8 +2615,8 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
case DIOCCLRRULECTRS: { case DIOCCLRRULECTRS: {
/* obsoleted by DIOCGETRULE with action=PF_GET_CLR_CNTR */ /* obsoleted by DIOCGETRULE with action=PF_GET_CLR_CNTR */
struct pf_ruleset *ruleset = &pf_main_ruleset; struct pf_kruleset *ruleset = &pf_main_ruleset;
struct pf_rule *rule; struct pf_krule *rule;
PF_RULES_WLOCK(); PF_RULES_WLOCK();
TAILQ_FOREACH(rule, TAILQ_FOREACH(rule,
@ -2775,7 +2958,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
struct pfioc_pooladdr *pca = (struct pfioc_pooladdr *)addr; struct pfioc_pooladdr *pca = (struct pfioc_pooladdr *)addr;
struct pf_pool *pool; struct pf_pool *pool;
struct pf_pooladdr *oldpa = NULL, *newpa = NULL; struct pf_pooladdr *oldpa = NULL, *newpa = NULL;
struct pf_ruleset *ruleset; struct pf_kruleset *ruleset;
struct pfi_kif *kif = NULL; struct pfi_kif *kif = NULL;
if (pca->action < PF_CHANGE_ADD_HEAD || if (pca->action < PF_CHANGE_ADD_HEAD ||
@ -2815,7 +2998,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
} }
#define ERROUT(x) { error = (x); goto DIOCCHANGEADDR_error; } #define ERROUT(x) { error = (x); goto DIOCCHANGEADDR_error; }
PF_RULES_WLOCK(); PF_RULES_WLOCK();
ruleset = pf_find_ruleset(pca->anchor); ruleset = pf_find_kruleset(pca->anchor);
if (ruleset == NULL) if (ruleset == NULL)
ERROUT(EBUSY); ERROUT(EBUSY);
@ -2907,12 +3090,12 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
case DIOCGETRULESETS: { case DIOCGETRULESETS: {
struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr; struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr;
struct pf_ruleset *ruleset; struct pf_kruleset *ruleset;
struct pf_anchor *anchor; struct pf_kanchor *anchor;
PF_RULES_RLOCK(); PF_RULES_RLOCK();
pr->path[sizeof(pr->path) - 1] = 0; pr->path[sizeof(pr->path) - 1] = 0;
if ((ruleset = pf_find_ruleset(pr->path)) == NULL) { if ((ruleset = pf_find_kruleset(pr->path)) == NULL) {
PF_RULES_RUNLOCK(); PF_RULES_RUNLOCK();
error = ENOENT; error = ENOENT;
break; break;
@ -2920,11 +3103,11 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
pr->nr = 0; pr->nr = 0;
if (ruleset->anchor == NULL) { if (ruleset->anchor == NULL) {
/* XXX kludge for pf_main_ruleset */ /* XXX kludge for pf_main_ruleset */
RB_FOREACH(anchor, pf_anchor_global, &V_pf_anchors) RB_FOREACH(anchor, pf_kanchor_global, &V_pf_anchors)
if (anchor->parent == NULL) if (anchor->parent == NULL)
pr->nr++; pr->nr++;
} else { } else {
RB_FOREACH(anchor, pf_anchor_node, RB_FOREACH(anchor, pf_kanchor_node,
&ruleset->anchor->children) &ruleset->anchor->children)
pr->nr++; pr->nr++;
} }
@ -2934,13 +3117,13 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
case DIOCGETRULESET: { case DIOCGETRULESET: {
struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr; struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr;
struct pf_ruleset *ruleset; struct pf_kruleset *ruleset;
struct pf_anchor *anchor; struct pf_kanchor *anchor;
u_int32_t nr = 0; u_int32_t nr = 0;
PF_RULES_RLOCK(); PF_RULES_RLOCK();
pr->path[sizeof(pr->path) - 1] = 0; pr->path[sizeof(pr->path) - 1] = 0;
if ((ruleset = pf_find_ruleset(pr->path)) == NULL) { if ((ruleset = pf_find_kruleset(pr->path)) == NULL) {
PF_RULES_RUNLOCK(); PF_RULES_RUNLOCK();
error = ENOENT; error = ENOENT;
break; break;
@ -2948,14 +3131,14 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
pr->name[0] = 0; pr->name[0] = 0;
if (ruleset->anchor == NULL) { if (ruleset->anchor == NULL) {
/* XXX kludge for pf_main_ruleset */ /* XXX kludge for pf_main_ruleset */
RB_FOREACH(anchor, pf_anchor_global, &V_pf_anchors) RB_FOREACH(anchor, pf_kanchor_global, &V_pf_anchors)
if (anchor->parent == NULL && nr++ == pr->nr) { if (anchor->parent == NULL && nr++ == pr->nr) {
strlcpy(pr->name, anchor->name, strlcpy(pr->name, anchor->name,
sizeof(pr->name)); sizeof(pr->name));
break; break;
} }
} else { } else {
RB_FOREACH(anchor, pf_anchor_node, RB_FOREACH(anchor, pf_kanchor_node,
&ruleset->anchor->children) &ruleset->anchor->children)
if (nr++ == pr->nr) { if (nr++ == pr->nr) {
strlcpy(pr->name, anchor->name, strlcpy(pr->name, anchor->name,
@ -3681,7 +3864,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
case DIOCXCOMMIT: { case DIOCXCOMMIT: {
struct pfioc_trans *io = (struct pfioc_trans *)addr; struct pfioc_trans *io = (struct pfioc_trans *)addr;
struct pfioc_trans_e *ioe, *ioes; struct pfioc_trans_e *ioe, *ioes;
struct pf_ruleset *rs; struct pf_kruleset *rs;
size_t totlen; size_t totlen;
int i; int i;
@ -3731,7 +3914,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
break; break;
#endif /* ALTQ */ #endif /* ALTQ */
case PF_RULESET_TABLE: case PF_RULESET_TABLE:
rs = pf_find_ruleset(ioe->anchor); rs = pf_find_kruleset(ioe->anchor);
if (rs == NULL || !rs->topen || ioe->ticket != if (rs == NULL || !rs->topen || ioe->ticket !=
rs->tticket) { rs->tticket) {
PF_RULES_WUNLOCK(); PF_RULES_WUNLOCK();
@ -3748,7 +3931,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
error = EINVAL; error = EINVAL;
goto fail; goto fail;
} }
rs = pf_find_ruleset(ioe->anchor); rs = pf_find_kruleset(ioe->anchor);
if (rs == NULL || if (rs == NULL ||
!rs->rules[ioe->rs_num].inactive.open || !rs->rules[ioe->rs_num].inactive.open ||
rs->rules[ioe->rs_num].inactive.ticket != rs->rules[ioe->rs_num].inactive.ticket !=

View File

@ -58,11 +58,11 @@ __FBSDID("$FreeBSD$");
static void pf_hash(struct pf_addr *, struct pf_addr *, static void pf_hash(struct pf_addr *, struct pf_addr *,
struct pf_poolhashkey *, sa_family_t); struct pf_poolhashkey *, sa_family_t);
static struct pf_rule *pf_match_translation(struct pf_pdesc *, struct mbuf *, static struct pf_krule *pf_match_translation(struct pf_pdesc *, struct mbuf *,
int, int, struct pfi_kif *, int, int, struct pfi_kif *,
struct pf_addr *, u_int16_t, struct pf_addr *, struct pf_addr *, u_int16_t, struct pf_addr *,
uint16_t, int, struct pf_anchor_stackframe *); uint16_t, int, struct pf_kanchor_stackframe *);
static int pf_get_sport(sa_family_t, uint8_t, struct pf_rule *, static int pf_get_sport(sa_family_t, uint8_t, struct pf_krule *,
struct pf_addr *, uint16_t, struct pf_addr *, uint16_t, struct pf_addr *, struct pf_addr *, uint16_t, struct pf_addr *, uint16_t, struct pf_addr *,
uint16_t *, uint16_t, uint16_t, struct pf_ksrc_node **); uint16_t *, uint16_t, uint16_t, struct pf_ksrc_node **);
@ -123,14 +123,14 @@ pf_hash(struct pf_addr *inaddr, struct pf_addr *hash,
} }
} }
static struct pf_rule * static struct pf_krule *
pf_match_translation(struct pf_pdesc *pd, struct mbuf *m, int off, pf_match_translation(struct pf_pdesc *pd, struct mbuf *m, int off,
int direction, struct pfi_kif *kif, struct pf_addr *saddr, u_int16_t sport, int direction, struct pfi_kif *kif, struct pf_addr *saddr, u_int16_t sport,
struct pf_addr *daddr, uint16_t dport, int rs_num, struct pf_addr *daddr, uint16_t dport, int rs_num,
struct pf_anchor_stackframe *anchor_stack) struct pf_kanchor_stackframe *anchor_stack)
{ {
struct pf_rule *r, *rm = NULL; struct pf_krule *r, *rm = NULL;
struct pf_ruleset *ruleset = NULL; struct pf_kruleset *ruleset = NULL;
int tag = -1; int tag = -1;
int rtableid = -1; int rtableid = -1;
int asd = 0; int asd = 0;
@ -212,7 +212,7 @@ pf_match_translation(struct pf_pdesc *pd, struct mbuf *m, int off,
} }
static int static int
pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r, pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_krule *r,
struct pf_addr *saddr, uint16_t sport, struct pf_addr *daddr, struct pf_addr *saddr, uint16_t sport, struct pf_addr *daddr,
uint16_t dport, struct pf_addr *naddr, uint16_t *nport, uint16_t low, uint16_t dport, struct pf_addr *naddr, uint16_t *nport, uint16_t low,
uint16_t high, struct pf_ksrc_node **sn) uint16_t high, struct pf_ksrc_node **sn)
@ -311,7 +311,7 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
} }
int int
pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr, pf_map_addr(sa_family_t af, struct pf_krule *r, struct pf_addr *saddr,
struct pf_addr *naddr, struct pf_addr *init_addr, struct pf_ksrc_node **sn) struct pf_addr *naddr, struct pf_addr *init_addr, struct pf_ksrc_node **sn)
{ {
struct pf_pool *rpool = &r->rpool; struct pf_pool *rpool = &r->rpool;
@ -520,14 +520,14 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr,
return (0); return (0);
} }
struct pf_rule * struct pf_krule *
pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction, pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction,
struct pfi_kif *kif, struct pf_ksrc_node **sn, struct pfi_kif *kif, struct pf_ksrc_node **sn,
struct pf_state_key **skp, struct pf_state_key **nkp, struct pf_state_key **skp, struct pf_state_key **nkp,
struct pf_addr *saddr, struct pf_addr *daddr, struct pf_addr *saddr, struct pf_addr *daddr,
uint16_t sport, uint16_t dport, struct pf_anchor_stackframe *anchor_stack) uint16_t sport, uint16_t dport, struct pf_kanchor_stackframe *anchor_stack)
{ {
struct pf_rule *r = NULL; struct pf_krule *r = NULL;
struct pf_addr *naddr; struct pf_addr *naddr;
uint16_t *nport; uint16_t *nport;

View File

@ -134,7 +134,7 @@ static RB_GENERATE(pf_frag_tree, pf_fragment, fr_entry, pf_frag_compare);
static void pf_flush_fragments(void); static void pf_flush_fragments(void);
static void pf_free_fragment(struct pf_fragment *); static void pf_free_fragment(struct pf_fragment *);
static void pf_remove_fragment(struct pf_fragment *); static void pf_remove_fragment(struct pf_fragment *);
static int pf_normalize_tcpopt(struct pf_rule *, struct mbuf *, static int pf_normalize_tcpopt(struct pf_krule *, struct mbuf *,
struct tcphdr *, int, sa_family_t); struct tcphdr *, int, sa_family_t);
static struct pf_frent *pf_create_fragment(u_short *); static struct pf_frent *pf_create_fragment(u_short *);
static int pf_frent_holes(struct pf_frent *frent); static int pf_frent_holes(struct pf_frent *frent);
@ -997,7 +997,7 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
struct pf_pdesc *pd) struct pf_pdesc *pd)
{ {
struct mbuf *m = *m0; struct mbuf *m = *m0;
struct pf_rule *r; struct pf_krule *r;
struct ip *h = mtod(m, struct ip *); struct ip *h = mtod(m, struct ip *);
int mff = (ntohs(h->ip_off) & IP_MF); int mff = (ntohs(h->ip_off) & IP_MF);
int hlen = h->ip_hl << 2; int hlen = h->ip_hl << 2;
@ -1138,7 +1138,7 @@ pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kif *kif,
u_short *reason, struct pf_pdesc *pd) u_short *reason, struct pf_pdesc *pd)
{ {
struct mbuf *m = *m0; struct mbuf *m = *m0;
struct pf_rule *r; struct pf_krule *r;
struct ip6_hdr *h = mtod(m, struct ip6_hdr *); struct ip6_hdr *h = mtod(m, struct ip6_hdr *);
int extoff; int extoff;
int off; int off;
@ -1298,7 +1298,7 @@ int
pf_normalize_tcp(int dir, struct pfi_kif *kif, struct mbuf *m, int ipoff, pf_normalize_tcp(int dir, struct pfi_kif *kif, struct mbuf *m, int ipoff,
int off, void *h, struct pf_pdesc *pd) int off, void *h, struct pf_pdesc *pd)
{ {
struct pf_rule *r, *rm = NULL; struct pf_krule *r, *rm = NULL;
struct tcphdr *th = pd->hdr.tcp; struct tcphdr *th = pd->hdr.tcp;
int rewrite = 0; int rewrite = 0;
u_short reason; u_short reason;
@ -1901,7 +1901,7 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
} }
static int static int
pf_normalize_tcpopt(struct pf_rule *r, struct mbuf *m, struct tcphdr *th, pf_normalize_tcpopt(struct pf_krule *r, struct mbuf *m, struct tcphdr *th,
int off, sa_family_t af) int off, sa_family_t af)
{ {
u_int16_t *mss; u_int16_t *mss;

View File

@ -87,8 +87,8 @@ __FBSDID("$FreeBSD$");
#endif /* _KERNEL */ #endif /* _KERNEL */
#ifdef _KERNEL #ifdef _KERNEL
VNET_DEFINE(struct pf_anchor_global, pf_anchors); VNET_DEFINE(struct pf_kanchor_global, pf_anchors);
VNET_DEFINE(struct pf_anchor, pf_main_anchor); VNET_DEFINE(struct pf_kanchor, pf_main_anchor);
#else /* ! _KERNEL */ #else /* ! _KERNEL */
struct pf_anchor_global pf_anchors; struct pf_anchor_global pf_anchors;
struct pf_anchor pf_main_anchor; struct pf_anchor pf_main_anchor;
@ -98,13 +98,25 @@ struct pf_anchor pf_main_anchor;
#define pf_main_ruleset pf_main_anchor.ruleset #define pf_main_ruleset pf_main_anchor.ruleset
#endif /* _KERNEL */ #endif /* _KERNEL */
static __inline int pf_anchor_compare(struct pf_anchor *, struct pf_anchor *);
#ifdef _KERNEL
static __inline int pf_kanchor_compare(struct pf_kanchor *,
struct pf_kanchor *);
static struct pf_kanchor *pf_find_kanchor(const char *);
RB_GENERATE(pf_kanchor_global, pf_kanchor, entry_global, pf_kanchor_compare);
RB_GENERATE(pf_kanchor_node, pf_kanchor, entry_node, pf_kanchor_compare);
#else
static __inline int pf_anchor_compare(struct pf_anchor *,
struct pf_anchor *);
static struct pf_anchor *pf_find_anchor(const char *); static struct pf_anchor *pf_find_anchor(const char *);
RB_GENERATE(pf_anchor_global, pf_anchor, entry_global, pf_anchor_compare); RB_GENERATE(pf_anchor_global, pf_anchor, entry_global, pf_anchor_compare);
RB_GENERATE(pf_anchor_node, pf_anchor, entry_node, pf_anchor_compare); RB_GENERATE(pf_anchor_node, pf_anchor, entry_node, pf_anchor_compare);
#endif
#ifndef _KERNEL
static __inline int static __inline int
pf_anchor_compare(struct pf_anchor *a, struct pf_anchor *b) pf_anchor_compare(struct pf_anchor *a, struct pf_anchor *b)
{ {
@ -112,6 +124,15 @@ pf_anchor_compare(struct pf_anchor *a, struct pf_anchor *b)
return (c ? (c < 0 ? -1 : 1) : 0); return (c ? (c < 0 ? -1 : 1) : 0);
} }
#else
static __inline int
pf_kanchor_compare(struct pf_kanchor *a, struct pf_kanchor *b)
{
int c = strcmp(a->path, b->path);
return (c ? (c < 0 ? -1 : 1) : 0);
}
#endif
int int
pf_get_ruleset_number(u_int8_t action) pf_get_ruleset_number(u_int8_t action)
@ -143,6 +164,7 @@ pf_get_ruleset_number(u_int8_t action)
} }
} }
#ifndef _KERNEL
void void
pf_init_ruleset(struct pf_ruleset *ruleset) pf_init_ruleset(struct pf_ruleset *ruleset)
{ {
@ -170,6 +192,292 @@ pf_find_anchor(const char *path)
rs_free(key); rs_free(key);
return (found); return (found);
} }
#else
static struct pf_kanchor *
pf_find_kanchor(const char *path)
{
struct pf_kanchor *key, *found;
key = (struct pf_kanchor *)rs_malloc(sizeof(*key));
if (key == NULL)
return (NULL);
strlcpy(key->path, path, sizeof(key->path));
found = RB_FIND(pf_kanchor_global, &V_pf_anchors, key);
rs_free(key);
return (found);
}
void
pf_init_kruleset(struct pf_kruleset *ruleset)
{
int i;
memset(ruleset, 0, sizeof(struct pf_kruleset));
for (i = 0; i < PF_RULESET_MAX; i++) {
TAILQ_INIT(&ruleset->rules[i].queues[0]);
TAILQ_INIT(&ruleset->rules[i].queues[1]);
ruleset->rules[i].active.ptr = &ruleset->rules[i].queues[0];
ruleset->rules[i].inactive.ptr = &ruleset->rules[i].queues[1];
}
}
#endif
#ifdef _KERNEL
struct pf_kruleset *
pf_find_kruleset(const char *path)
{
struct pf_kanchor *anchor;
while (*path == '/')
path++;
if (!*path)
return (&pf_main_ruleset);
anchor = pf_find_kanchor(path);
if (anchor == NULL)
return (NULL);
else
return (&anchor->ruleset);
}
struct pf_kruleset *
pf_find_or_create_kruleset(const char *path)
{
char *p, *q, *r;
struct pf_kruleset *ruleset;
struct pf_kanchor *anchor = NULL, *dup, *parent = NULL;
if (path[0] == 0)
return (&pf_main_ruleset);
while (*path == '/')
path++;
ruleset = pf_find_kruleset(path);
if (ruleset != NULL)
return (ruleset);
p = (char *)rs_malloc(MAXPATHLEN);
if (p == NULL)
return (NULL);
strlcpy(p, path, MAXPATHLEN);
while (parent == NULL && (q = strrchr(p, '/')) != NULL) {
*q = 0;
if ((ruleset = pf_find_kruleset(p)) != NULL) {
parent = ruleset->anchor;
break;
}
}
if (q == NULL)
q = p;
else
q++;
strlcpy(p, path, MAXPATHLEN);
if (!*q) {
rs_free(p);
return (NULL);
}
while ((r = strchr(q, '/')) != NULL || *q) {
if (r != NULL)
*r = 0;
if (!*q || strlen(q) >= PF_ANCHOR_NAME_SIZE ||
(parent != NULL && strlen(parent->path) >=
MAXPATHLEN - PF_ANCHOR_NAME_SIZE - 1)) {
rs_free(p);
return (NULL);
}
anchor = (struct pf_kanchor *)rs_malloc(sizeof(*anchor));
if (anchor == NULL) {
rs_free(p);
return (NULL);
}
RB_INIT(&anchor->children);
strlcpy(anchor->name, q, sizeof(anchor->name));
if (parent != NULL) {
strlcpy(anchor->path, parent->path,
sizeof(anchor->path));
strlcat(anchor->path, "/", sizeof(anchor->path));
}
strlcat(anchor->path, anchor->name, sizeof(anchor->path));
if ((dup = RB_INSERT(pf_kanchor_global, &V_pf_anchors, anchor)) !=
NULL) {
printf("pf_find_or_create_ruleset: RB_INSERT1 "
"'%s' '%s' collides with '%s' '%s'\n",
anchor->path, anchor->name, dup->path, dup->name);
rs_free(anchor);
rs_free(p);
return (NULL);
}
if (parent != NULL) {
anchor->parent = parent;
if ((dup = RB_INSERT(pf_kanchor_node, &parent->children,
anchor)) != NULL) {
printf("pf_find_or_create_ruleset: "
"RB_INSERT2 '%s' '%s' collides with "
"'%s' '%s'\n", anchor->path, anchor->name,
dup->path, dup->name);
RB_REMOVE(pf_kanchor_global, &V_pf_anchors,
anchor);
rs_free(anchor);
rs_free(p);
return (NULL);
}
}
pf_init_kruleset(&anchor->ruleset);
anchor->ruleset.anchor = anchor;
parent = anchor;
if (r != NULL)
q = r + 1;
else
*q = 0;
}
rs_free(p);
return (&anchor->ruleset);
}
void
pf_remove_if_empty_kruleset(struct pf_kruleset *ruleset)
{
struct pf_kanchor *parent;
int i;
while (ruleset != NULL) {
if (ruleset == &pf_main_ruleset || ruleset->anchor == NULL ||
!RB_EMPTY(&ruleset->anchor->children) ||
ruleset->anchor->refcnt > 0 || ruleset->tables > 0 ||
ruleset->topen)
return;
for (i = 0; i < PF_RULESET_MAX; ++i)
if (!TAILQ_EMPTY(ruleset->rules[i].active.ptr) ||
!TAILQ_EMPTY(ruleset->rules[i].inactive.ptr) ||
ruleset->rules[i].inactive.open)
return;
RB_REMOVE(pf_kanchor_global, &V_pf_anchors, ruleset->anchor);
if ((parent = ruleset->anchor->parent) != NULL)
RB_REMOVE(pf_kanchor_node, &parent->children,
ruleset->anchor);
rs_free(ruleset->anchor);
if (parent == NULL)
return;
ruleset = &parent->ruleset;
}
}
int
pf_kanchor_setup(struct pf_krule *r, const struct pf_kruleset *s,
const char *name)
{
char *p, *path;
struct pf_kruleset *ruleset;
r->anchor = NULL;
r->anchor_relative = 0;
r->anchor_wildcard = 0;
if (!name[0])
return (0);
path = (char *)rs_malloc(MAXPATHLEN);
if (path == NULL)
return (1);
if (name[0] == '/')
strlcpy(path, name + 1, MAXPATHLEN);
else {
/* relative path */
r->anchor_relative = 1;
if (s->anchor == NULL || !s->anchor->path[0])
path[0] = 0;
else
strlcpy(path, s->anchor->path, MAXPATHLEN);
while (name[0] == '.' && name[1] == '.' && name[2] == '/') {
if (!path[0]) {
printf("pf_anchor_setup: .. beyond root\n");
rs_free(path);
return (1);
}
if ((p = strrchr(path, '/')) != NULL)
*p = 0;
else
path[0] = 0;
r->anchor_relative++;
name += 3;
}
if (path[0])
strlcat(path, "/", MAXPATHLEN);
strlcat(path, name, MAXPATHLEN);
}
if ((p = strrchr(path, '/')) != NULL && !strcmp(p, "/*")) {
r->anchor_wildcard = 1;
*p = 0;
}
ruleset = pf_find_or_create_kruleset(path);
rs_free(path);
if (ruleset == NULL || ruleset->anchor == NULL) {
printf("pf_anchor_setup: ruleset\n");
return (1);
}
r->anchor = ruleset->anchor;
r->anchor->refcnt++;
return (0);
}
int
pf_kanchor_copyout(const struct pf_kruleset *rs, const struct pf_krule *r,
struct pfioc_rule *pr)
{
pr->anchor_call[0] = 0;
if (r->anchor == NULL)
return (0);
if (!r->anchor_relative) {
strlcpy(pr->anchor_call, "/", sizeof(pr->anchor_call));
strlcat(pr->anchor_call, r->anchor->path,
sizeof(pr->anchor_call));
} else {
char *a, *p;
int i;
a = (char *)rs_malloc(MAXPATHLEN);
if (a == NULL)
return (1);
if (rs->anchor == NULL)
a[0] = 0;
else
strlcpy(a, rs->anchor->path, MAXPATHLEN);
for (i = 1; i < r->anchor_relative; ++i) {
if ((p = strrchr(a, '/')) == NULL)
p = a;
*p = 0;
strlcat(pr->anchor_call, "../",
sizeof(pr->anchor_call));
}
if (strncmp(a, r->anchor->path, strlen(a))) {
printf("pf_anchor_copyout: '%s' '%s'\n", a,
r->anchor->path);
rs_free(a);
return (1);
}
if (strlen(r->anchor->path) > strlen(a))
strlcat(pr->anchor_call, r->anchor->path + (a[0] ?
strlen(a) + 1 : 0), sizeof(pr->anchor_call));
rs_free(a);
}
if (r->anchor_wildcard)
strlcat(pr->anchor_call, pr->anchor_call[0] ? "/*" : "*",
sizeof(pr->anchor_call));
return (0);
}
void
pf_kanchor_remove(struct pf_krule *r)
{
if (r->anchor == NULL)
return;
if (r->anchor->refcnt <= 0) {
printf("pf_anchor_remove: broken refcount\n");
r->anchor = NULL;
return;
}
if (!--r->anchor->refcnt)
pf_remove_if_empty_kruleset(&r->anchor->ruleset);
r->anchor = NULL;
}
#else
struct pf_ruleset * struct pf_ruleset *
pf_find_ruleset(const char *path) pf_find_ruleset(const char *path)
@ -306,7 +614,6 @@ pf_remove_if_empty_ruleset(struct pf_ruleset *ruleset)
ruleset = &parent->ruleset; ruleset = &parent->ruleset;
} }
} }
int int
pf_anchor_setup(struct pf_rule *r, const struct pf_ruleset *s, pf_anchor_setup(struct pf_rule *r, const struct pf_ruleset *s,
const char *name) const char *name)
@ -362,64 +669,4 @@ pf_anchor_setup(struct pf_rule *r, const struct pf_ruleset *s,
r->anchor->refcnt++; r->anchor->refcnt++;
return (0); return (0);
} }
#endif
int
pf_anchor_copyout(const struct pf_ruleset *rs, const struct pf_rule *r,
struct pfioc_rule *pr)
{
pr->anchor_call[0] = 0;
if (r->anchor == NULL)
return (0);
if (!r->anchor_relative) {
strlcpy(pr->anchor_call, "/", sizeof(pr->anchor_call));
strlcat(pr->anchor_call, r->anchor->path,
sizeof(pr->anchor_call));
} else {
char *a, *p;
int i;
a = (char *)rs_malloc(MAXPATHLEN);
if (a == NULL)
return (1);
if (rs->anchor == NULL)
a[0] = 0;
else
strlcpy(a, rs->anchor->path, MAXPATHLEN);
for (i = 1; i < r->anchor_relative; ++i) {
if ((p = strrchr(a, '/')) == NULL)
p = a;
*p = 0;
strlcat(pr->anchor_call, "../",
sizeof(pr->anchor_call));
}
if (strncmp(a, r->anchor->path, strlen(a))) {
printf("pf_anchor_copyout: '%s' '%s'\n", a,
r->anchor->path);
rs_free(a);
return (1);
}
if (strlen(r->anchor->path) > strlen(a))
strlcat(pr->anchor_call, r->anchor->path + (a[0] ?
strlen(a) + 1 : 0), sizeof(pr->anchor_call));
rs_free(a);
}
if (r->anchor_wildcard)
strlcat(pr->anchor_call, pr->anchor_call[0] ? "/*" : "*",
sizeof(pr->anchor_call));
return (0);
}
void
pf_anchor_remove(struct pf_rule *r)
{
if (r->anchor == NULL)
return;
if (r->anchor->refcnt <= 0) {
printf("pf_anchor_remove: broken refcount\n");
r->anchor = NULL;
return;
}
if (!--r->anchor->refcnt)
pf_remove_if_empty_ruleset(&r->anchor->ruleset);
r->anchor = NULL;
}

View File

@ -1431,11 +1431,11 @@ pfr_ina_begin(struct pfr_table *trs, u_int32_t *ticket, int *ndel, int flags)
{ {
struct pfr_ktableworkq workq; struct pfr_ktableworkq workq;
struct pfr_ktable *p; struct pfr_ktable *p;
struct pf_ruleset *rs; struct pf_kruleset *rs;
int xdel = 0; int xdel = 0;
ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY); ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY);
rs = pf_find_or_create_ruleset(trs->pfrt_anchor); rs = pf_find_or_create_kruleset(trs->pfrt_anchor);
if (rs == NULL) if (rs == NULL)
return (ENOMEM); return (ENOMEM);
SLIST_INIT(&workq); SLIST_INIT(&workq);
@ -1453,7 +1453,7 @@ pfr_ina_begin(struct pfr_table *trs, u_int32_t *ticket, int *ndel, int flags)
*ticket = ++rs->tticket; *ticket = ++rs->tticket;
rs->topen = 1; rs->topen = 1;
} else } else
pf_remove_if_empty_ruleset(rs); pf_remove_if_empty_kruleset(rs);
if (ndel != NULL) if (ndel != NULL)
*ndel = xdel; *ndel = xdel;
return (0); return (0);
@ -1468,7 +1468,7 @@ pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
struct pfr_ktable *kt, *rt, *shadow, key; struct pfr_ktable *kt, *rt, *shadow, key;
struct pfr_kentry *p; struct pfr_kentry *p;
struct pfr_addr *ad; struct pfr_addr *ad;
struct pf_ruleset *rs; struct pf_kruleset *rs;
int i, rv, xadd = 0, xaddr = 0; int i, rv, xadd = 0, xaddr = 0;
PF_RULES_WASSERT(); PF_RULES_WASSERT();
@ -1479,7 +1479,7 @@ pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
if (pfr_validate_table(tbl, PFR_TFLAG_USRMASK, if (pfr_validate_table(tbl, PFR_TFLAG_USRMASK,
flags & PFR_FLAG_USERIOCTL)) flags & PFR_FLAG_USERIOCTL))
return (EINVAL); return (EINVAL);
rs = pf_find_ruleset(tbl->pfrt_anchor); rs = pf_find_kruleset(tbl->pfrt_anchor);
if (rs == NULL || !rs->topen || ticket != rs->tticket) if (rs == NULL || !rs->topen || ticket != rs->tticket)
return (EBUSY); return (EBUSY);
tbl->pfrt_flags |= PFR_TFLAG_INACTIVE; tbl->pfrt_flags |= PFR_TFLAG_INACTIVE;
@ -1565,13 +1565,13 @@ pfr_ina_rollback(struct pfr_table *trs, u_int32_t ticket, int *ndel, int flags)
{ {
struct pfr_ktableworkq workq; struct pfr_ktableworkq workq;
struct pfr_ktable *p; struct pfr_ktable *p;
struct pf_ruleset *rs; struct pf_kruleset *rs;
int xdel = 0; int xdel = 0;
PF_RULES_WASSERT(); PF_RULES_WASSERT();
ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY); ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY);
rs = pf_find_ruleset(trs->pfrt_anchor); rs = pf_find_kruleset(trs->pfrt_anchor);
if (rs == NULL || !rs->topen || ticket != rs->tticket) if (rs == NULL || !rs->topen || ticket != rs->tticket)
return (0); return (0);
SLIST_INIT(&workq); SLIST_INIT(&workq);
@ -1586,7 +1586,7 @@ pfr_ina_rollback(struct pfr_table *trs, u_int32_t ticket, int *ndel, int flags)
if (!(flags & PFR_FLAG_DUMMY)) { if (!(flags & PFR_FLAG_DUMMY)) {
pfr_setflags_ktables(&workq); pfr_setflags_ktables(&workq);
rs->topen = 0; rs->topen = 0;
pf_remove_if_empty_ruleset(rs); pf_remove_if_empty_kruleset(rs);
} }
if (ndel != NULL) if (ndel != NULL)
*ndel = xdel; *ndel = xdel;
@ -1599,14 +1599,14 @@ pfr_ina_commit(struct pfr_table *trs, u_int32_t ticket, int *nadd,
{ {
struct pfr_ktable *p, *q; struct pfr_ktable *p, *q;
struct pfr_ktableworkq workq; struct pfr_ktableworkq workq;
struct pf_ruleset *rs; struct pf_kruleset *rs;
int xadd = 0, xchange = 0; int xadd = 0, xchange = 0;
long tzero = time_second; long tzero = time_second;
PF_RULES_WASSERT(); PF_RULES_WASSERT();
ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY); ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY);
rs = pf_find_ruleset(trs->pfrt_anchor); rs = pf_find_kruleset(trs->pfrt_anchor);
if (rs == NULL || !rs->topen || ticket != rs->tticket) if (rs == NULL || !rs->topen || ticket != rs->tticket)
return (EBUSY); return (EBUSY);
@ -1628,7 +1628,7 @@ pfr_ina_commit(struct pfr_table *trs, u_int32_t ticket, int *nadd,
pfr_commit_ktable(p, tzero); pfr_commit_ktable(p, tzero);
} }
rs->topen = 0; rs->topen = 0;
pf_remove_if_empty_ruleset(rs); pf_remove_if_empty_kruleset(rs);
} }
if (nadd != NULL) if (nadd != NULL)
*nadd = xadd; *nadd = xadd;
@ -1756,14 +1756,14 @@ pfr_fix_anchor(char *anchor)
int int
pfr_table_count(struct pfr_table *filter, int flags) pfr_table_count(struct pfr_table *filter, int flags)
{ {
struct pf_ruleset *rs; struct pf_kruleset *rs;
PF_RULES_ASSERT(); PF_RULES_ASSERT();
if (flags & PFR_FLAG_ALLRSETS) if (flags & PFR_FLAG_ALLRSETS)
return (V_pfr_ktable_cnt); return (V_pfr_ktable_cnt);
if (filter->pfrt_anchor[0]) { if (filter->pfrt_anchor[0]) {
rs = pf_find_ruleset(filter->pfrt_anchor); rs = pf_find_kruleset(filter->pfrt_anchor);
return ((rs != NULL) ? rs->tables : -1); return ((rs != NULL) ? rs->tables : -1);
} }
return (pf_main_ruleset.tables); return (pf_main_ruleset.tables);
@ -1882,7 +1882,7 @@ static struct pfr_ktable *
pfr_create_ktable(struct pfr_table *tbl, long tzero, int attachruleset) pfr_create_ktable(struct pfr_table *tbl, long tzero, int attachruleset)
{ {
struct pfr_ktable *kt; struct pfr_ktable *kt;
struct pf_ruleset *rs; struct pf_kruleset *rs;
int pfr_dir, pfr_op; int pfr_dir, pfr_op;
PF_RULES_WASSERT(); PF_RULES_WASSERT();
@ -1893,7 +1893,7 @@ pfr_create_ktable(struct pfr_table *tbl, long tzero, int attachruleset)
kt->pfrkt_t = *tbl; kt->pfrkt_t = *tbl;
if (attachruleset) { if (attachruleset) {
rs = pf_find_or_create_ruleset(tbl->pfrt_anchor); rs = pf_find_or_create_kruleset(tbl->pfrt_anchor);
if (!rs) { if (!rs) {
pfr_destroy_ktable(kt, 0); pfr_destroy_ktable(kt, 0);
return (NULL); return (NULL);
@ -1972,7 +1972,7 @@ pfr_destroy_ktable(struct pfr_ktable *kt, int flushaddr)
pfr_destroy_ktable(kt->pfrkt_shadow, flushaddr); pfr_destroy_ktable(kt->pfrkt_shadow, flushaddr);
if (kt->pfrkt_rs != NULL) { if (kt->pfrkt_rs != NULL) {
kt->pfrkt_rs->tables--; kt->pfrkt_rs->tables--;
pf_remove_if_empty_ruleset(kt->pfrkt_rs); pf_remove_if_empty_kruleset(kt->pfrkt_rs);
} }
for (pfr_dir = 0; pfr_dir < PFR_DIR_MAX; pfr_dir ++) { for (pfr_dir = 0; pfr_dir < PFR_DIR_MAX; pfr_dir ++) {
for (pfr_op = 0; pfr_op < PFR_OP_TABLE_MAX; pfr_op ++) { for (pfr_op = 0; pfr_op < PFR_OP_TABLE_MAX; pfr_op ++) {
@ -2120,11 +2120,11 @@ pfr_update_stats(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af,
} }
struct pfr_ktable * struct pfr_ktable *
pfr_attach_table(struct pf_ruleset *rs, char *name) pfr_attach_table(struct pf_kruleset *rs, char *name)
{ {
struct pfr_ktable *kt, *rt; struct pfr_ktable *kt, *rt;
struct pfr_table tbl; struct pfr_table tbl;
struct pf_anchor *ac = rs->anchor; struct pf_kanchor *ac = rs->anchor;
PF_RULES_WASSERT(); PF_RULES_WASSERT();