From e86bddea9fe62d5093a1942cf21950b3c5ca62e5 Mon Sep 17 00:00:00 2001 From: Kristof Provost Date: Sat, 5 Dec 2020 14:32:54 +0100 Subject: [PATCH] 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 --- sys/net/pfvar.h | 234 ++++++++++++++++------ sys/netpfil/pf/if_pflog.c | 4 +- sys/netpfil/pf/if_pfsync.c | 2 +- sys/netpfil/pf/pf.c | 124 ++++++------ sys/netpfil/pf/pf.h | 48 +++++ sys/netpfil/pf/pf_if.c | 6 +- sys/netpfil/pf/pf_ioctl.c | 337 ++++++++++++++++++++++++-------- sys/netpfil/pf/pf_lb.c | 24 +-- sys/netpfil/pf/pf_norm.c | 10 +- sys/netpfil/pf/pf_ruleset.c | 377 +++++++++++++++++++++++++++++------- sys/netpfil/pf/pf_table.c | 36 ++-- 11 files changed, 894 insertions(+), 308 deletions(-) diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index b726abf894fe..846c6b9015e7 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -293,11 +293,115 @@ extern struct sx pf_end_lock; #define PF_ALGNMNT(off) (((off) % 2) == 0) #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 { LIST_ENTRY(pf_ksrc_node) entry; struct pf_addr addr; struct pf_addr raddr; - union pf_rule_ptr rule; + union pf_krule_ptr rule; struct pfi_kif *kif; counter_u64_t bytes[2]; counter_u64_t packets[2]; @@ -374,6 +478,15 @@ struct pf_state_cmp { 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 { u_int64_t id; u_int32_t creatorid; @@ -386,9 +499,9 @@ struct pf_state { LIST_ENTRY(pf_state) entry; struct pf_state_peer src; struct pf_state_peer dst; - union pf_rule_ptr rule; - union pf_rule_ptr anchor; - union pf_rule_ptr nat_rule; + union pf_krule_ptr rule; + union pf_krule_ptr anchor; + union pf_krule_ptr nat_rule; struct pf_addr rt_addr; struct pf_state_key *key[2]; /* addresses stack and wire */ struct pfi_kif *kif; @@ -403,13 +516,6 @@ struct pf_state { u_int16_t tag; u_int8_t log; 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 sync_state; /* PFSYNC_S_x */ @@ -417,6 +523,7 @@ struct pf_state { u_int8_t sync_updates; u_int8_t _tail[3]; }; +#endif /* * Unified state structures for pulling states out of the kernel @@ -501,11 +608,11 @@ void pfsync_state_export(struct pfsync_state *, struct pf_state *); /* pflog */ -struct pf_ruleset; +struct pf_kruleset; struct pf_pdesc; 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 *, - struct pf_ruleset *, struct pf_pdesc *, int); + u_int8_t, u_int8_t, struct pf_krule *, struct pf_krule *, + struct pf_kruleset *, struct pf_pdesc *, int); extern pflog_packet_t *pflog_packet_ptr; #endif /* _KERNEL */ @@ -563,42 +670,42 @@ extern pflog_packet_t *pflog_packet_ptr; d += ntohl(s[1]); \ } 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 pf_rulequeue queues[2]; + struct pf_krulequeue queues[2]; struct { - struct pf_rulequeue *ptr; - struct pf_rule **ptr_array; + struct pf_krulequeue *ptr; + struct pf_krule **ptr_array; u_int32_t rcount; u_int32_t ticket; int open; } active, inactive; } rules[PF_RULESET_MAX]; - struct pf_anchor *anchor; + struct pf_kanchor *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; +RB_HEAD(pf_kanchor_global, pf_kanchor); +RB_HEAD(pf_kanchor_node, pf_kanchor); +struct pf_kanchor { + RB_ENTRY(pf_kanchor) entry_global; + RB_ENTRY(pf_kanchor) entry_node; + struct pf_kanchor *parent; + struct pf_kanchor_node children; char name[PF_ANCHOR_NAME_SIZE]; char path[MAXPATHLEN]; - struct pf_ruleset ruleset; + struct pf_kruleset 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); +RB_PROTOTYPE(pf_kanchor_global, pf_kanchor, entry_global, pf_anchor_compare); +RB_PROTOTYPE(pf_kanchor_node, pf_kanchor, entry_node, pf_kanchor_compare); #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_COUNTERS) -struct pf_anchor_stackframe; +struct pf_kanchor_stackframe; struct pfr_table { char pfrt_anchor[MAXPATHLEN]; @@ -707,6 +814,7 @@ struct pfr_kcounters { ((kc)->pfrkc_counters + \ (dir) * PFR_OP_ADDR_MAX * PFR_TYPE_MAX + (op) * PFR_TYPE_MAX + (t)) +#ifdef _KERNEL SLIST_HEAD(pfr_kentryworkq, pfr_kentry); struct pfr_kentry { struct radix_node pfrke_node[2]; @@ -729,7 +837,7 @@ struct pfr_ktable { struct radix_node_head *pfrkt_ip6; struct pfr_ktable *pfrkt_shadow; struct pfr_ktable *pfrkt_root; - struct pf_ruleset *pfrkt_rs; + struct pf_kruleset *pfrkt_rs; long pfrkt_larg; int pfrkt_nflags; }; @@ -745,6 +853,7 @@ struct pfr_ktable { #define pfrkt_match pfrkt_kts.pfrkts_match #define pfrkt_nomatch pfrkt_kts.pfrkts_nomatch #define pfrkt_tzero pfrkt_kts.pfrkts_tzero +#endif /* keep synced with pfi_kif, used in RB_FIND */ struct pfi_kif_cmp { @@ -789,7 +898,7 @@ struct pf_pdesc { void *any; } 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 *dst; /* dst address */ 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); #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) void pf_initialize(void); @@ -1304,7 +1413,7 @@ void pf_cleanup(void); 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 extern void pf_altq_ifnet_event(struct ifnet *, int); #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 *, u_int, int *); 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 u_int pf_free_src_nodes(struct pf_ksrc_node_list *); 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); #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) extern void pf_addrcpy(struct pf_addr *, struct pf_addr *, u_int8_t); -void pf_free_rule(struct pf_rule *); +void pf_free_rule(struct pf_krule *); #ifdef INET 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); void pfr_dynaddr_update(struct pfr_ktable *, struct pfi_dynaddr *); struct pfr_ktable * - pfr_attach_table(struct pf_ruleset *, char *); + pfr_attach_table(struct pf_kruleset *, char *); void pfr_detach_table(struct pfr_ktable *); int pfr_clr_tables(struct pfr_table *, 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_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_addr_cmp(struct pf_addr *, struct pf_addr *, sa_family_t); @@ -1502,25 +1611,24 @@ VNET_DECLARE(struct pf_limit, pf_limits[PF_LIMIT_MAX]); #endif /* _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) -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 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); -void pf_init_ruleset(struct pf_ruleset *); -int pf_anchor_setup(struct pf_rule *, - const struct pf_ruleset *, const char *); -int pf_anchor_copyout(const struct pf_ruleset *, - const struct pf_rule *, struct pfioc_rule *); -void pf_anchor_remove(struct pf_rule *); -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 *); +void pf_init_kruleset(struct pf_kruleset *); +int pf_kanchor_setup(struct pf_krule *, + const struct pf_kruleset *, const char *); +int pf_kanchor_copyout(const struct pf_kruleset *, + const struct pf_krule *, struct pfioc_rule *); +void pf_kanchor_remove(struct pf_krule *); +void pf_remove_if_empty_kruleset(struct pf_kruleset *); +struct pf_kruleset *pf_find_kruleset(const char *); +struct pf_kruleset *pf_find_or_create_kruleset(const char *); void pf_rs_initialize(void); +#endif /* The fingerprint functions can be linked into userland programs (tcpdump) */ 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 void pf_print_host(struct pf_addr *, u_int16_t, u_int8_t); -void pf_step_into_anchor(struct pf_anchor_stackframe *, int *, - struct pf_ruleset **, int, struct pf_rule **, - struct pf_rule **, int *); -int pf_step_out_of_anchor(struct pf_anchor_stackframe *, int *, - struct pf_ruleset **, int, struct pf_rule **, - struct pf_rule **, int *); +void pf_step_into_anchor(struct pf_kanchor_stackframe *, int *, + struct pf_kruleset **, int, struct pf_krule **, + struct pf_krule **, int *); +int pf_step_out_of_anchor(struct pf_kanchor_stackframe *, int *, + struct pf_kruleset **, int, struct pf_krule **, + 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_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 **, struct pf_state_key **, struct pf_state_key **, 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_addr *, u_int16_t, u_int16_t); diff --git a/sys/netpfil/pf/if_pflog.c b/sys/netpfil/pf/if_pflog.c index 87e674f46942..030f75c2507e 100644 --- a/sys/netpfil/pf/if_pflog.c +++ b/sys/netpfil/pf/if_pflog.c @@ -202,8 +202,8 @@ pflogioctl(struct ifnet *ifp, u_long cmd, caddr_t data) static int 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, - struct pf_ruleset *ruleset, struct pf_pdesc *pd, int lookupsafe) + u_int8_t reason, struct pf_krule *rm, struct pf_krule *am, + struct pf_kruleset *ruleset, struct pf_pdesc *pd, int lookupsafe) { struct ifnet *ifn; struct pfloghdr hdr; diff --git a/sys/netpfil/pf/if_pfsync.c b/sys/netpfil/pf/if_pfsync.c index 2f696698e3eb..83ca4b969636 100644 --- a/sys/netpfil/pf/if_pfsync.c +++ b/sys/netpfil/pf/if_pfsync.c @@ -463,7 +463,7 @@ pfsync_state_import(struct pfsync_state *sp, u_int8_t flags) struct pfsync_state_key *kw, *ks; struct pf_state *st = NULL; struct pf_state_key *skw = NULL, *sks = NULL; - struct pf_rule *r = NULL; + struct pf_krule *r = NULL; struct pfi_kif *kif; int error; diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c index 6f393bd62698..469e6b0bc32f 100644 --- a/sys/netpfil/pf/pf.c +++ b/sys/netpfil/pf/pf.c @@ -181,7 +181,7 @@ struct pf_overload_entry { struct pf_addr addr; sa_family_t af; uint8_t dir; - struct pf_rule *rule; + struct pf_krule *rule; }; 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_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; MTX_SYSINIT(pf_unlnkdrules_mtx, &pf_unlnkdrules_mtx, "pf unlinked rules", 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_int8_t, sa_family_t); 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 *, 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_int16_t, struct ifnet *); 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 int pf_state_key_attach(struct pf_state_key *, struct pf_state_key *, struct pf_state *); static void pf_state_key_detach(struct pf_state *, int); static int pf_state_key_ctor(void *, int, void *, int); 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, - struct pf_pdesc *, struct pf_rule **, - struct pf_ruleset **, struct inpcb *); -static int pf_create_state(struct pf_rule *, struct pf_rule *, - struct pf_rule *, struct pf_pdesc *, + struct pf_pdesc *, struct pf_krule **, + struct pf_kruleset **, struct inpcb *); +static int pf_create_state(struct pf_krule *, struct pf_krule *, + struct pf_krule *, struct pf_pdesc *, struct pf_ksrc_node *, struct pf_state_key *, struct pf_state_key *, struct mbuf *, int, u_int16_t, u_int16_t, int *, struct pfi_kif *, struct pf_state **, int, u_int16_t, u_int16_t, 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 pf_pdesc *, struct pf_rule **, - struct pf_ruleset **); + struct pf_pdesc *, struct pf_krule **, + struct pf_kruleset **); static int pf_tcp_track_full(struct pf_state_peer *, struct pf_state_peer *, struct pf_state **, 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 void pf_overload_task(void *v, int pending); 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 void pf_purge_unlinked_rules(void); static int pf_mtag_uminit(void *, int, int); static void pf_mtag_free(struct m_tag *); #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 pf_pdesc *, struct inpcb *); #endif /* INET */ #ifdef INET6 static void pf_change_a6(struct pf_addr *, u_int16_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 pf_pdesc *, struct inpcb *); #endif /* INET6 */ @@ -678,7 +678,7 @@ pf_overload_task(void *v, int pending) * allocate and insert a new one. */ 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) { struct pf_srchash *sh; @@ -716,7 +716,7 @@ pf_free_src_node(struct pf_ksrc_node *sn) } 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) { @@ -1806,8 +1806,8 @@ pf_purge_expired_states(u_int i, int maxcheck) static void pf_purge_unlinked_rules() { - struct pf_rulequeue tmpq; - struct pf_rule *r, *r1; + struct pf_krulequeue tmpq; + struct pf_krule *r, *r1; /* * If we have overloading task pending, then we'd @@ -2032,9 +2032,9 @@ pf_print_flags(u_int8_t f) } while (0) 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; cur = TAILQ_FIRST(rules); @@ -2440,7 +2440,7 @@ pf_modulate_sack(struct mbuf *m, int off, struct pf_pdesc *pd, } 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, 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, @@ -2600,7 +2600,7 @@ pf_send_tcp(struct mbuf *replyto, const struct pf_rule *r, sa_family_t af, } 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 pfi_kif *kif, u_int16_t bproto_sum, u_int16_t bip_sum, int hdrlen, u_short *reason) @@ -2714,7 +2714,7 @@ pf_match_ieee8021q_pcp(u_int8_t prio, struct mbuf *m) static void 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 mbuf *m0; @@ -2902,7 +2902,7 @@ pf_match_gid(u_int8_t op, gid_t a1, gid_t a2, gid_t g) } 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) *tag = mtag; @@ -2926,10 +2926,10 @@ pf_tag_packet(struct mbuf *m, struct pf_pdesc *pd, int tag) } #define PF_ANCHOR_STACKSIZE 32 -struct pf_anchor_stackframe { - struct pf_ruleset *rs; - struct pf_rule *r; /* XXX: + match bit */ - struct pf_anchor *child; +struct pf_kanchor_stackframe { + struct pf_kruleset *rs; + struct pf_krule *r; /* XXX: + match bit */ + struct pf_kanchor *child; }; /* @@ -2939,18 +2939,18 @@ struct pf_anchor_stackframe { #define PF_ANCHORSTACK_MASK (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) #define PF_ANCHOR_SET_MATCH(f) do { (f)->r = (void *) \ ((uintptr_t)(f)->r | PF_ANCHORSTACK_MATCH); \ } while (0) void -pf_step_into_anchor(struct pf_anchor_stackframe *stack, int *depth, - struct pf_ruleset **rs, int n, struct pf_rule **r, struct pf_rule **a, +pf_step_into_anchor(struct pf_kanchor_stackframe *stack, int *depth, + struct pf_kruleset **rs, int n, struct pf_krule **r, struct pf_krule **a, int *match) { - struct pf_anchor_stackframe *f; + struct pf_kanchor_stackframe *f; PF_RULES_RASSERT(); @@ -2967,9 +2967,9 @@ pf_step_into_anchor(struct pf_anchor_stackframe *stack, int *depth, f->rs = *rs; f->r = *r; 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; return; } @@ -2982,12 +2982,12 @@ pf_step_into_anchor(struct pf_anchor_stackframe *stack, int *depth, } int -pf_step_out_of_anchor(struct pf_anchor_stackframe *stack, int *depth, - struct pf_ruleset **rs, int n, struct pf_rule **r, struct pf_rule **a, +pf_step_out_of_anchor(struct pf_kanchor_stackframe *stack, int *depth, + struct pf_kruleset **rs, int n, struct pf_krule **r, struct pf_krule **a, int *match) { - struct pf_anchor_stackframe *f; - struct pf_rule *fr; + struct pf_kanchor_stackframe *f; + struct pf_krule *fr; int quick = 0; PF_RULES_RASSERT(); @@ -2998,7 +2998,7 @@ pf_step_out_of_anchor(struct pf_anchor_stackframe *stack, int *depth, f = stack + *depth - 1; fr = PF_ANCHOR_RULE(f); if (f->child != NULL) { - struct pf_anchor_node *parent; + struct pf_kanchor_node *parent; /* * 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); *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) { *rs = &f->child->ruleset; *r = TAILQ_FIRST((*rs)->rules[n].active.ptr); @@ -3324,16 +3324,16 @@ pf_tcp_iss(struct pf_pdesc *pd) } 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 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 daddr = pd->dst; sa_family_t af = pd->af; - struct pf_rule *r, *a = NULL; - struct pf_ruleset *ruleset = NULL; + struct pf_krule *r, *a = NULL; + struct pf_kruleset *ruleset = NULL; struct pf_ksrc_node *nsn = NULL; struct tcphdr *th = pd->hdr.tcp; 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 bproto_sum = 0, bip_sum = 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(); @@ -3698,7 +3698,7 @@ pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction, } 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_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, @@ -3960,18 +3960,18 @@ pf_create_state(struct pf_rule *r, struct pf_rule *nr, struct pf_rule *a, } static int -pf_test_fragment(struct pf_rule **rm, int direction, struct pfi_kif *kif, - struct mbuf *m, void *h, struct pf_pdesc *pd, struct pf_rule **am, - struct pf_ruleset **rsm) +pf_test_fragment(struct pf_krule **rm, int direction, struct pfi_kif *kif, + struct mbuf *m, void *h, struct pf_pdesc *pd, struct pf_krule **am, + struct pf_kruleset **rsm) { - struct pf_rule *r, *a = NULL; - struct pf_ruleset *ruleset = NULL; + struct pf_krule *r, *a = NULL; + struct pf_kruleset *ruleset = NULL; sa_family_t af = pd->af; u_short reason; int tag = -1; int asd = 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(); @@ -5463,7 +5463,7 @@ pf_routable(struct pf_addr *addr, sa_family_t af, struct pfi_kif *kif, #ifdef INET 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 mbuf *m0, *m1; @@ -5626,7 +5626,7 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp, #ifdef INET6 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 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 ip *h = NULL; 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_ruleset *ruleset = NULL; + struct pf_kruleset *ruleset = NULL; struct pf_pdesc pd; 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) { - struct pf_rule *lr; + struct pf_krule *lr; if (s != NULL && s->nat_rule.ptr != NULL && 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 m_tag *mtag; 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_ruleset *ruleset = NULL; + struct pf_kruleset *ruleset = NULL; struct pf_pdesc pd; 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"); if (log) { - struct pf_rule *lr; + struct pf_krule *lr; if (s != NULL && s->nat_rule.ptr != NULL && s->nat_rule.ptr->log & PF_LOG_ALL) diff --git a/sys/netpfil/pf/pf.h b/sys/netpfil/pf/pf.h index aa6409bcbaa9..4e73d815aece 100644 --- a/sys/netpfil/pf/pf.h +++ b/sys/netpfil/pf/pf.h @@ -35,6 +35,8 @@ #ifndef _NET_PF_H_ #define _NET_PF_H_ +#include + #define PF_TCPS_PROXY_SRC ((TCP_NSTATES)+0) #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 */ +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_ */ diff --git a/sys/netpfil/pf/pf_if.c b/sys/netpfil/pf/pf_if.c index 24179f9f3e63..f8862a9416b5 100644 --- a/sys/netpfil/pf/pf_if.c +++ b/sys/netpfil/pf/pf_if.c @@ -403,7 +403,7 @@ pfi_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af) struct epoch_tracker et; struct pfi_dynaddr *dyn; char tblname[PF_TABLE_NAME_SIZE]; - struct pf_ruleset *ruleset = NULL; + struct pf_kruleset *ruleset = NULL; struct pfi_kif *kif; int rv = 0; @@ -441,7 +441,7 @@ pfi_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af) if (dyn->pfid_net != 128) snprintf(tblname + strlen(tblname), 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; goto _bad; } @@ -467,7 +467,7 @@ pfi_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af) if (dyn->pfid_kt != NULL) pfr_detach_table(dyn->pfid_kt); if (ruleset != NULL) - pf_remove_if_empty_ruleset(ruleset); + pf_remove_if_empty_kruleset(ruleset); if (dyn->pfid_kif != NULL) pfi_kif_unref(dyn->pfid_kif); free(dyn, PFI_MTYPE); diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c index bb7034f27daf..4b5ad44ab01d 100644 --- a/sys/netpfil/pf/pf_ioctl.c +++ b/sys/netpfil/pf/pf_ioctl.c @@ -109,11 +109,11 @@ static void pf_qid_unref(u_int32_t); #endif /* ALTQ */ static int pf_begin_rules(u_int32_t *, int, const char *); static int pf_rollback_rules(u_int32_t, int, char *); -static int pf_setup_pfsync_matching(struct pf_ruleset *); -static void pf_hash_rule(MD5_CTX *, struct pf_rule *); +static int pf_setup_pfsync_matching(struct pf_kruleset *); +static void pf_hash_rule(MD5_CTX *, struct pf_krule *); 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_addr_setup(struct pf_ruleset *, +static int pf_addr_setup(struct pf_kruleset *, struct pf_addr_wrap *, sa_family_t); static void pf_addr_copyout(struct pf_addr_wrap *); 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); #endif /* ALTQ */ -VNET_DEFINE(struct pf_rule, pf_default_rule); +VNET_DEFINE(struct pf_krule, pf_default_rule); #ifdef ALTQ VNET_DEFINE_STATIC(int, pf_altq_running); @@ -271,7 +271,7 @@ pfattach_vnet(void) V_pf_limits[PF_LIMIT_SRC_NODES].limit = PFSNODE_HIWAT; RB_INIT(&V_pf_anchors); - pf_init_ruleset(&pf_main_ruleset); + pf_init_kruleset(&pf_main_ruleset); /* default rule should never be garbage collected */ 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_int8_t check_ticket) { - struct pf_ruleset *ruleset; - struct pf_rule *rule; + struct pf_kruleset *ruleset; + struct pf_krule *rule; int rs_num; - ruleset = pf_find_ruleset(anchor); + ruleset = pf_find_kruleset(anchor); if (ruleset == NULL) return (NULL); 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); if (r_last) rule = TAILQ_LAST(ruleset->rules[rs_num].active.ptr, - pf_rulequeue); + pf_krulequeue); else rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr); } else { @@ -362,7 +362,7 @@ pf_get_pool(char *anchor, u_int32_t ticket, u_int8_t rule_action, return (NULL); if (r_last) rule = TAILQ_LAST(ruleset->rules[rs_num].inactive.ptr, - pf_rulequeue); + pf_krulequeue); else rule = TAILQ_FIRST(ruleset->rules[rs_num].inactive.ptr); } @@ -411,7 +411,7 @@ pf_empty_pool(struct pf_palist *poola) } 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(); @@ -425,7 +425,7 @@ pf_unlink_rule(struct pf_rulequeue *rulequeue, struct pf_rule *rule) } void -pf_free_rule(struct pf_rule *rule) +pf_free_rule(struct pf_krule *rule) { PF_RULES_WASSERT(); @@ -459,7 +459,7 @@ pf_free_rule(struct pf_rule *rule) pfr_detach_table(rule->overload_tbl); if (rule->kif) pfi_kif_unref(rule->kif); - pf_anchor_remove(rule); + pf_kanchor_remove(rule); pf_empty_pool(&rule->rpool.list); counter_u64_free(rule->states_cur); counter_u64_free(rule->states_tot); @@ -896,14 +896,14 @@ pf_altq_ifnet_event(struct ifnet *ifp, int remove) static int pf_begin_rules(u_int32_t *ticket, int rs_num, const char *anchor) { - struct pf_ruleset *rs; - struct pf_rule *rule; + struct pf_kruleset *rs; + struct pf_krule *rule; PF_RULES_WASSERT(); if (rs_num < 0 || rs_num >= PF_RULESET_MAX) return (EINVAL); - rs = pf_find_or_create_ruleset(anchor); + rs = pf_find_or_create_kruleset(anchor); if (rs == NULL) return (EINVAL); 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 pf_rollback_rules(u_int32_t ticket, int rs_num, char *anchor) { - struct pf_ruleset *rs; - struct pf_rule *rule; + struct pf_kruleset *rs; + struct pf_krule *rule; PF_RULES_WASSERT(); if (rs_num < 0 || rs_num >= PF_RULESET_MAX) return (EINVAL); - rs = pf_find_ruleset(anchor); + rs = pf_find_kruleset(anchor); if (rs == NULL || !rs->rules[rs_num].inactive.open || rs->rules[rs_num].inactive.ticket != ticket) return (0); @@ -979,7 +979,7 @@ pf_hash_rule_addr(MD5_CTX *ctx, struct pf_rule_addr *pfr) } 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_int32_t y; @@ -1020,9 +1020,9 @@ pf_hash_rule(MD5_CTX *ctx, struct pf_rule *rule) static int pf_commit_rules(u_int32_t ticket, int rs_num, char *anchor) { - struct pf_ruleset *rs; - struct pf_rule *rule, **old_array; - struct pf_rulequeue *old_rules; + struct pf_kruleset *rs; + struct pf_krule *rule, **old_array; + struct pf_krulequeue *old_rules; int error; 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) return (EINVAL); - rs = pf_find_ruleset(anchor); + rs = pf_find_kruleset(anchor); if (rs == NULL || !rs->rules[rs_num].inactive.open || ticket != rs->rules[rs_num].inactive.ticket) 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.rcount = 0; rs->rules[rs_num].inactive.open = 0; - pf_remove_if_empty_ruleset(rs); + pf_remove_if_empty_kruleset(rs); return (0); } static int -pf_setup_pfsync_matching(struct pf_ruleset *rs) +pf_setup_pfsync_matching(struct pf_kruleset *rs) { MD5_CTX ctx; - struct pf_rule *rule; + struct pf_krule *rule; int rs_cnt; u_int8_t digest[PF_MD5_DIGEST_LENGTH]; @@ -1115,7 +1115,7 @@ pf_setup_pfsync_matching(struct pf_ruleset *rs) } 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) { int error = 0; @@ -1425,6 +1425,194 @@ pf_altq_get_nth_active(u_int32_t n) } #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 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: { struct pfioc_rule *pr = (struct pfioc_rule *)addr; - struct pf_ruleset *ruleset; - struct pf_rule *rule, *tail; + struct pf_kruleset *ruleset; + struct pf_krule *rule, *tail; struct pf_pooladdr *pa; struct pfi_kif *kif = NULL; int rs_num; @@ -1616,7 +1804,8 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td #endif /* INET6 */ 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]) kif = malloc(sizeof(*kif), PFI_MTYPE, 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(); pr->anchor[sizeof(pr->anchor) - 1] = 0; - ruleset = pf_find_ruleset(pr->anchor); + ruleset = pf_find_kruleset(pr->anchor); if (ruleset == NULL) ERROUT(EINVAL); 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, - pf_rulequeue); + pf_krulequeue); if (tail) rule->nr = tail->nr + 1; else @@ -1693,7 +1882,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td error = ENOMEM; if (pf_addr_setup(ruleset, &rule->dst.addr, rule->af)) error = ENOMEM; - if (pf_anchor_setup(rule, ruleset, pr->anchor_call)) + if (pf_kanchor_setup(rule, ruleset, pr->anchor_call)) error = EINVAL; if (rule->scrub_flags & PFSTATE_SETPRIO && (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: { struct pfioc_rule *pr = (struct pfioc_rule *)addr; - struct pf_ruleset *ruleset; - struct pf_rule *tail; + struct pf_kruleset *ruleset; + struct pf_krule *tail; int rs_num; PF_RULES_WLOCK(); pr->anchor[sizeof(pr->anchor) - 1] = 0; - ruleset = pf_find_ruleset(pr->anchor); + ruleset = pf_find_kruleset(pr->anchor); if (ruleset == NULL) { PF_RULES_WUNLOCK(); error = EINVAL; @@ -1772,7 +1961,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td break; } tail = TAILQ_LAST(ruleset->rules[rs_num].active.ptr, - pf_rulequeue); + pf_krulequeue); if (tail) pr->nr = tail->nr + 1; else @@ -1784,13 +1973,13 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td case DIOCGETRULE: { struct pfioc_rule *pr = (struct pfioc_rule *)addr; - struct pf_ruleset *ruleset; - struct pf_rule *rule; - int rs_num, i; + struct pf_kruleset *ruleset; + struct pf_krule *rule; + int rs_num; PF_RULES_WLOCK(); pr->anchor[sizeof(pr->anchor) - 1] = 0; - ruleset = pf_find_ruleset(pr->anchor); + ruleset = pf_find_kruleset(pr->anchor); if (ruleset == NULL) { PF_RULES_WUNLOCK(); error = EINVAL; @@ -1815,23 +2004,16 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td error = EBUSY; break; } - bcopy(rule, &pr->rule, sizeof(struct pf_rule)); - pr->rule.u_states_cur = counter_u64_fetch(rule->states_cur); - pr->rule.u_states_tot = counter_u64_fetch(rule->states_tot); - pr->rule.u_src_nodes = counter_u64_fetch(rule->src_nodes); - if (pf_anchor_copyout(ruleset, rule, pr)) { + + pf_krule_to_rule(rule, &pr->rule); + + if (pf_kanchor_copyout(ruleset, rule, pr)) { PF_RULES_WUNLOCK(); error = EBUSY; break; } pf_addr_copyout(&pr->rule.src.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) { rule->evaluations = 0; @@ -1845,8 +2027,8 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td case DIOCCHANGERULE: { struct pfioc_rule *pcr = (struct pfioc_rule *)addr; - struct pf_ruleset *ruleset; - struct pf_rule *oldrule = NULL, *newrule = NULL; + struct pf_kruleset *ruleset; + struct pf_krule *oldrule = NULL, *newrule = NULL; struct pfi_kif *kif = NULL; struct pf_pooladdr *pa; 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 */ 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]) kif = malloc(sizeof(*kif), PFI_MTYPE, 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) ERROUT(EBUSY); - ruleset = pf_find_ruleset(pcr->anchor); + ruleset = pf_find_kruleset(pcr->anchor); if (ruleset == NULL) ERROUT(EINVAL); @@ -1953,7 +2136,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td error = ENOMEM; if (pf_addr_setup(ruleset, &newrule->dst.addr, newrule->af)) error = ENOMEM; - if (pf_anchor_setup(newrule, ruleset, pcr->anchor_call)) + if (pf_kanchor_setup(newrule, ruleset, pcr->anchor_call)) error = EINVAL; TAILQ_FOREACH(pa, &V_pf_pabuf, entries) 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); else if (pcr->action == PF_CHANGE_ADD_TAIL) oldrule = TAILQ_LAST( - ruleset->rules[rs_num].active.ptr, pf_rulequeue); + ruleset->rules[rs_num].active.ptr, pf_krulequeue); else { oldrule = TAILQ_FIRST( 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++; 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(); break; @@ -2432,8 +2615,8 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td case DIOCCLRRULECTRS: { /* obsoleted by DIOCGETRULE with action=PF_GET_CLR_CNTR */ - struct pf_ruleset *ruleset = &pf_main_ruleset; - struct pf_rule *rule; + struct pf_kruleset *ruleset = &pf_main_ruleset; + struct pf_krule *rule; PF_RULES_WLOCK(); 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 pf_pool *pool; struct pf_pooladdr *oldpa = NULL, *newpa = NULL; - struct pf_ruleset *ruleset; + struct pf_kruleset *ruleset; struct pfi_kif *kif = NULL; 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; } PF_RULES_WLOCK(); - ruleset = pf_find_ruleset(pca->anchor); + ruleset = pf_find_kruleset(pca->anchor); if (ruleset == NULL) ERROUT(EBUSY); @@ -2907,12 +3090,12 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td case DIOCGETRULESETS: { struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr; - struct pf_ruleset *ruleset; - struct pf_anchor *anchor; + struct pf_kruleset *ruleset; + struct pf_kanchor *anchor; PF_RULES_RLOCK(); 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(); error = ENOENT; break; @@ -2920,11 +3103,11 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td pr->nr = 0; if (ruleset->anchor == NULL) { /* 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) pr->nr++; } else { - RB_FOREACH(anchor, pf_anchor_node, + RB_FOREACH(anchor, pf_kanchor_node, &ruleset->anchor->children) pr->nr++; } @@ -2934,13 +3117,13 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td case DIOCGETRULESET: { struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr; - struct pf_ruleset *ruleset; - struct pf_anchor *anchor; + struct pf_kruleset *ruleset; + struct pf_kanchor *anchor; u_int32_t nr = 0; PF_RULES_RLOCK(); 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(); error = ENOENT; break; @@ -2948,14 +3131,14 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td pr->name[0] = 0; if (ruleset->anchor == NULL) { /* 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) { strlcpy(pr->name, anchor->name, sizeof(pr->name)); break; } } else { - RB_FOREACH(anchor, pf_anchor_node, + RB_FOREACH(anchor, pf_kanchor_node, &ruleset->anchor->children) if (nr++ == pr->nr) { 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: { struct pfioc_trans *io = (struct pfioc_trans *)addr; struct pfioc_trans_e *ioe, *ioes; - struct pf_ruleset *rs; + struct pf_kruleset *rs; size_t totlen; int i; @@ -3731,7 +3914,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td break; #endif /* ALTQ */ case PF_RULESET_TABLE: - rs = pf_find_ruleset(ioe->anchor); + rs = pf_find_kruleset(ioe->anchor); if (rs == NULL || !rs->topen || ioe->ticket != rs->tticket) { PF_RULES_WUNLOCK(); @@ -3748,7 +3931,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td error = EINVAL; goto fail; } - rs = pf_find_ruleset(ioe->anchor); + rs = pf_find_kruleset(ioe->anchor); if (rs == NULL || !rs->rules[ioe->rs_num].inactive.open || rs->rules[ioe->rs_num].inactive.ticket != diff --git a/sys/netpfil/pf/pf_lb.c b/sys/netpfil/pf/pf_lb.c index e8188e9ff4fb..964f576114fc 100644 --- a/sys/netpfil/pf/pf_lb.c +++ b/sys/netpfil/pf/pf_lb.c @@ -58,11 +58,11 @@ __FBSDID("$FreeBSD$"); static void pf_hash(struct pf_addr *, struct pf_addr *, 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 *, struct pf_addr *, u_int16_t, struct pf_addr *, - uint16_t, int, struct pf_anchor_stackframe *); -static int pf_get_sport(sa_family_t, uint8_t, struct pf_rule *, + uint16_t, int, struct pf_kanchor_stackframe *); +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 *, 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, 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_anchor_stackframe *anchor_stack) + struct pf_kanchor_stackframe *anchor_stack) { - struct pf_rule *r, *rm = NULL; - struct pf_ruleset *ruleset = NULL; + struct pf_krule *r, *rm = NULL; + struct pf_kruleset *ruleset = NULL; int tag = -1; int rtableid = -1; int asd = 0; @@ -212,7 +212,7 @@ pf_match_translation(struct pf_pdesc *pd, struct mbuf *m, int off, } 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, uint16_t dport, struct pf_addr *naddr, uint16_t *nport, uint16_t low, 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 -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_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); } -struct pf_rule * +struct pf_krule * pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction, struct pfi_kif *kif, struct pf_ksrc_node **sn, struct pf_state_key **skp, struct pf_state_key **nkp, 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; uint16_t *nport; diff --git a/sys/netpfil/pf/pf_norm.c b/sys/netpfil/pf/pf_norm.c index 1f99dafe2b27..656ce7c5f997 100644 --- a/sys/netpfil/pf/pf_norm.c +++ b/sys/netpfil/pf/pf_norm.c @@ -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_free_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); static struct pf_frent *pf_create_fragment(u_short *); 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 mbuf *m = *m0; - struct pf_rule *r; + struct pf_krule *r; struct ip *h = mtod(m, struct ip *); int mff = (ntohs(h->ip_off) & IP_MF); 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) { struct mbuf *m = *m0; - struct pf_rule *r; + struct pf_krule *r; struct ip6_hdr *h = mtod(m, struct ip6_hdr *); int extoff; int off; @@ -1298,7 +1298,7 @@ int pf_normalize_tcp(int dir, struct pfi_kif *kif, struct mbuf *m, int ipoff, 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; int rewrite = 0; u_short reason; @@ -1901,7 +1901,7 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd, } 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) { u_int16_t *mss; diff --git a/sys/netpfil/pf/pf_ruleset.c b/sys/netpfil/pf/pf_ruleset.c index 6595464132a7..b2604795811a 100644 --- a/sys/netpfil/pf/pf_ruleset.c +++ b/sys/netpfil/pf/pf_ruleset.c @@ -87,8 +87,8 @@ __FBSDID("$FreeBSD$"); #endif /* _KERNEL */ #ifdef _KERNEL -VNET_DEFINE(struct pf_anchor_global, pf_anchors); -VNET_DEFINE(struct pf_anchor, pf_main_anchor); +VNET_DEFINE(struct pf_kanchor_global, pf_anchors); +VNET_DEFINE(struct pf_kanchor, pf_main_anchor); #else /* ! _KERNEL */ struct pf_anchor_global pf_anchors; struct pf_anchor pf_main_anchor; @@ -98,13 +98,25 @@ struct pf_anchor pf_main_anchor; #define pf_main_ruleset pf_main_anchor.ruleset #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 *); RB_GENERATE(pf_anchor_global, pf_anchor, entry_global, pf_anchor_compare); RB_GENERATE(pf_anchor_node, pf_anchor, entry_node, pf_anchor_compare); +#endif + +#ifndef _KERNEL static __inline int 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); } +#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 pf_get_ruleset_number(u_int8_t action) @@ -143,6 +164,7 @@ pf_get_ruleset_number(u_int8_t action) } } +#ifndef _KERNEL void pf_init_ruleset(struct pf_ruleset *ruleset) { @@ -170,6 +192,292 @@ pf_find_anchor(const char *path) rs_free(key); 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 * pf_find_ruleset(const char *path) @@ -306,7 +614,6 @@ pf_remove_if_empty_ruleset(struct pf_ruleset *ruleset) ruleset = &parent->ruleset; } } - int pf_anchor_setup(struct pf_rule *r, const struct pf_ruleset *s, const char *name) @@ -362,64 +669,4 @@ pf_anchor_setup(struct pf_rule *r, const struct pf_ruleset *s, r->anchor->refcnt++; return (0); } - -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; -} +#endif diff --git a/sys/netpfil/pf/pf_table.c b/sys/netpfil/pf/pf_table.c index 92d9df5f189e..af2f614c9e8c 100644 --- a/sys/netpfil/pf/pf_table.c +++ b/sys/netpfil/pf/pf_table.c @@ -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_ktable *p; - struct pf_ruleset *rs; + struct pf_kruleset *rs; int xdel = 0; 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) return (ENOMEM); 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; rs->topen = 1; } else - pf_remove_if_empty_ruleset(rs); + pf_remove_if_empty_kruleset(rs); if (ndel != NULL) *ndel = xdel; 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_kentry *p; struct pfr_addr *ad; - struct pf_ruleset *rs; + struct pf_kruleset *rs; int i, rv, xadd = 0, xaddr = 0; 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, flags & PFR_FLAG_USERIOCTL)) return (EINVAL); - rs = pf_find_ruleset(tbl->pfrt_anchor); + rs = pf_find_kruleset(tbl->pfrt_anchor); if (rs == NULL || !rs->topen || ticket != rs->tticket) return (EBUSY); 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_ktable *p; - struct pf_ruleset *rs; + struct pf_kruleset *rs; int xdel = 0; PF_RULES_WASSERT(); 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) return (0); 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)) { pfr_setflags_ktables(&workq); rs->topen = 0; - pf_remove_if_empty_ruleset(rs); + pf_remove_if_empty_kruleset(rs); } if (ndel != NULL) *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_ktableworkq workq; - struct pf_ruleset *rs; + struct pf_kruleset *rs; int xadd = 0, xchange = 0; long tzero = time_second; PF_RULES_WASSERT(); 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) return (EBUSY); @@ -1628,7 +1628,7 @@ pfr_ina_commit(struct pfr_table *trs, u_int32_t ticket, int *nadd, pfr_commit_ktable(p, tzero); } rs->topen = 0; - pf_remove_if_empty_ruleset(rs); + pf_remove_if_empty_kruleset(rs); } if (nadd != NULL) *nadd = xadd; @@ -1756,14 +1756,14 @@ pfr_fix_anchor(char *anchor) int pfr_table_count(struct pfr_table *filter, int flags) { - struct pf_ruleset *rs; + struct pf_kruleset *rs; PF_RULES_ASSERT(); if (flags & PFR_FLAG_ALLRSETS) return (V_pfr_ktable_cnt); 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 (pf_main_ruleset.tables); @@ -1882,7 +1882,7 @@ static struct pfr_ktable * pfr_create_ktable(struct pfr_table *tbl, long tzero, int attachruleset) { struct pfr_ktable *kt; - struct pf_ruleset *rs; + struct pf_kruleset *rs; int pfr_dir, pfr_op; PF_RULES_WASSERT(); @@ -1893,7 +1893,7 @@ pfr_create_ktable(struct pfr_table *tbl, long tzero, int attachruleset) kt->pfrkt_t = *tbl; if (attachruleset) { - rs = pf_find_or_create_ruleset(tbl->pfrt_anchor); + rs = pf_find_or_create_kruleset(tbl->pfrt_anchor); if (!rs) { pfr_destroy_ktable(kt, 0); return (NULL); @@ -1972,7 +1972,7 @@ pfr_destroy_ktable(struct pfr_ktable *kt, int flushaddr) pfr_destroy_ktable(kt->pfrkt_shadow, flushaddr); if (kt->pfrkt_rs != NULL) { 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_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 * -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_table tbl; - struct pf_anchor *ac = rs->anchor; + struct pf_kanchor *ac = rs->anchor; PF_RULES_WASSERT();