Date: Tue, 16 Jan 2024 08:51:54 GMT From: Kristof Provost <kp@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: baf9b6d04205 - main - pf: allow pflow to be activated per rule Message-ID: <202401160851.40G8psfL075765@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch main has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=baf9b6d04205e02e6248377b1e13b33059a35fc9 commit baf9b6d04205e02e6248377b1e13b33059a35fc9 Author: Kristof Provost <kp@FreeBSD.org> AuthorDate: 2023-12-01 13:55:50 +0000 Commit: Kristof Provost <kp@FreeBSD.org> CommitDate: 2024-01-16 08:45:54 +0000 pf: allow pflow to be activated per rule Only generate ipfix/netflow reports (through pflow) for the rules where this is enabled. Reports can also be enabled globally through 'set state-default pflow'. Obtained from: OpenBSD Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D43108 --- sbin/pfctl/parse.y | 22 ++++++++++++++++++++-- sbin/pfctl/pf_print_state.c | 2 ++ sbin/pfctl/pfctl_parser.c | 8 ++++++++ share/man/man5/pf.conf.5 | 9 +++++++-- sys/net/pflow.h | 1 - sys/net/pfvar.h | 3 +++ sys/netpfil/pf/pf.c | 5 +++++ sys/netpfil/pf/pf.h | 3 ++- sys/netpfil/pf/pf_ioctl.c | 1 + sys/netpfil/pf/pflow.c | 35 +++++++++++++++++++---------------- 10 files changed, 67 insertions(+), 22 deletions(-) diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y index 17227b674814..94b7e241cd25 100644 --- a/sbin/pfctl/parse.y +++ b/sbin/pfctl/parse.y @@ -172,7 +172,8 @@ enum { PF_STATE_OPT_MAX, PF_STATE_OPT_NOSYNC, PF_STATE_OPT_SRCTRACK, PF_STATE_OPT_MAX_SRC_STATES, PF_STATE_OPT_MAX_SRC_CONN, PF_STATE_OPT_MAX_SRC_CONN_RATE, PF_STATE_OPT_MAX_SRC_NODES, PF_STATE_OPT_OVERLOAD, PF_STATE_OPT_STATELOCK, - PF_STATE_OPT_TIMEOUT, PF_STATE_OPT_SLOPPY, }; + PF_STATE_OPT_TIMEOUT, PF_STATE_OPT_SLOPPY, + PF_STATE_OPT_PFLOW }; enum { PF_SRCTRACK_NONE, PF_SRCTRACK, PF_SRCTRACK_GLOBAL, PF_SRCTRACK_RULE }; @@ -512,7 +513,7 @@ int parseport(char *, struct range *r, int); %token DNPIPE DNQUEUE RIDENTIFIER %token LOAD RULESET_OPTIMIZATION PRIO %token STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE -%token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH SLOPPY +%token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH SLOPPY PFLOW %token TAGGED TAG IFBOUND FLOATING STATEPOLICY STATEDEFAULTS ROUTE SETTOS %token DIVERTTO DIVERTREPLY BRIDGE_TO %token <v.string> STRING @@ -2615,6 +2616,14 @@ pfrule : action dir logquick interface route af proto fromto } r.rule_flag |= PFRULE_STATESLOPPY; break; + case PF_STATE_OPT_PFLOW: + if (r.rule_flag & PFRULE_PFLOW) { + yyerror("state pflow option: " + "multiple definitions"); + YYERROR; + } + r.rule_flag |= PFRULE_PFLOW; + break; case PF_STATE_OPT_TIMEOUT: if (o->data.timeout.number == PFTM_ADAPTIVE_START || @@ -4368,6 +4377,14 @@ state_opt_item : MAXIMUM NUMBER { $$->next = NULL; $$->tail = $$; } + | PFLOW { + $$ = calloc(1, sizeof(struct node_state_opt)); + if ($$ == NULL) + err(1, "state_opt_item: calloc"); + $$->type = PF_STATE_OPT_PFLOW; + $$->next = NULL; + $$->tail = $$; + } | STRING NUMBER { int i; @@ -6318,6 +6335,7 @@ lookup(char *s) { "out", OUT}, { "overload", OVERLOAD}, { "pass", PASS}, + { "pflow", PFLOW}, { "port", PORT}, { "prio", PRIO}, { "priority", PRIORITY}, diff --git a/sbin/pfctl/pf_print_state.c b/sbin/pfctl/pf_print_state.c index 36c2103a2142..0b862273fab3 100644 --- a/sbin/pfctl/pf_print_state.c +++ b/sbin/pfctl/pf_print_state.c @@ -376,6 +376,8 @@ print_state(struct pfctl_state *s, int opts) printf(", sloppy"); if (s->state_flags & PFSTATE_NOSYNC) printf(", no-sync"); + if (s->state_flags & PFSTATE_PFLOW) + printf(", pflow"); if (s->state_flags & PFSTATE_ACK) printf(", psync-ack"); if (s->state_flags & PFSTATE_NODF) diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c index 7dc0c3ae0cf2..e71b7b160495 100644 --- a/sbin/pfctl/pfctl_parser.c +++ b/sbin/pfctl/pfctl_parser.c @@ -1051,6 +1051,8 @@ print_rule(struct pfctl_rule *r, const char *anchor_call, int verbose, int numer opts = 1; if (r->rule_flag & PFRULE_STATESLOPPY) opts = 1; + if (r->rule_flag & PFRULE_PFLOW) + opts = 1; for (i = 0; !opts && i < PFTM_MAX; ++i) if (r->timeout[i]) opts = 1; @@ -1123,6 +1125,12 @@ print_rule(struct pfctl_rule *r, const char *anchor_call, int verbose, int numer printf("sloppy"); opts = 0; } + if (r->rule_flag & PFRULE_PFLOW) { + if (!opts) + printf(", "); + printf("pflow"); + opts = 0; + } for (i = 0; i < PFTM_MAX; ++i) if (r->timeout[i]) { int j; diff --git a/share/man/man5/pf.conf.5 b/share/man/man5/pf.conf.5 index 3193c18760c8..9803d96bc5d9 100644 --- a/share/man/man5/pf.conf.5 +++ b/share/man/man5/pf.conf.5 @@ -27,7 +27,7 @@ .\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd November 17, 2023 +.Dd December 6, 2023 .Dt PF.CONF 5 .Os .Sh NAME @@ -2429,6 +2429,10 @@ easier. This is intended to be used in situations where one does not see all packets of a connection, e.g. in asymmetric routing situations. Cannot be used with modulate or synproxy state. +.It Ar pflow +States created by this rule are exported on the +.Xr pflow 4 +interface. .El .Pp Multiple options can be specified, separated by commas: @@ -3345,7 +3349,7 @@ state-opt = ( "max" number | "no-sync" | timeout | "sloppy" | "max-src-conn" number | "max-src-conn-rate" number "/" number | "overload" "\*(Lt" string "\*(Gt" [ "flush" ] | - "if-bound" | "floating" ) + "if-bound" | "floating" | "pflow" ) fragmentation = [ "fragment reassemble" ] @@ -3406,6 +3410,7 @@ Service name database. .Xr ip 4 , .Xr ip6 4 , .Xr pf 4 , +.Xr pflow 4 , .Xr pfsync 4 , .Xr tcp 4 , .Xr sctp 4 , diff --git a/sys/net/pflow.h b/sys/net/pflow.h index fcf24e091b57..2b7dfe24b5fc 100644 --- a/sys/net/pflow.h +++ b/sys/net/pflow.h @@ -326,7 +326,6 @@ enum pflow_set_type_t { }; #ifdef _KERNEL -int export_pflow(struct pf_kstate *); int pflow_sysctl(int *, u_int, void *, size_t *, void *, size_t); #endif /* _KERNEL */ diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index d6852244ce9b..037286a756be 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -1186,6 +1186,7 @@ typedef void pfsync_delete_state_t(struct pf_kstate *); typedef void pfsync_clear_states_t(u_int32_t, const char *); typedef int pfsync_defer_t(struct pf_kstate *, struct mbuf *); typedef void pfsync_detach_ifnet_t(struct ifnet *); +typedef void pflow_export_state_t(const struct pf_kstate *); VNET_DECLARE(pfsync_state_import_t *, pfsync_state_import_ptr); #define V_pfsync_state_import_ptr VNET(pfsync_state_import_ptr) @@ -1199,6 +1200,8 @@ VNET_DECLARE(pfsync_clear_states_t *, pfsync_clear_states_ptr); #define V_pfsync_clear_states_ptr VNET(pfsync_clear_states_ptr) VNET_DECLARE(pfsync_defer_t *, pfsync_defer_ptr); #define V_pfsync_defer_ptr VNET(pfsync_defer_ptr) +VNET_DECLARE(pflow_export_state_t *, pflow_export_state_ptr); +#define V_pflow_export_state_ptr VNET(pflow_export_state_ptr) extern pfsync_detach_ifnet_t *pfsync_detach_ifnet_ptr; void pfsync_state_export(union pfsync_state_union *, diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c index df93cc1bebc3..7eaac809e487 100644 --- a/sys/netpfil/pf/pf.c +++ b/sys/netpfil/pf/pf.c @@ -1397,6 +1397,9 @@ pf_detach_state(struct pf_kstate *s) pf_sctp_multihome_detach_addr(s); + if ((s->state_flags & PFSTATE_PFLOW) && V_pflow_export_state_ptr) + V_pflow_export_state_ptr(s); + if (sks != NULL) { kh = &V_pf_keyhash[pf_hashkey(sks)]; PF_HASHROW_LOCK(kh); @@ -4872,6 +4875,8 @@ pf_create_state(struct pf_krule *r, struct pf_krule *nr, struct pf_krule *a, s->state_flags |= PFSTATE_SLOPPY; if (pd->flags & PFDESC_TCP_NORM) /* Set by old-style scrub rules */ s->state_flags |= PFSTATE_SCRUB_TCP; + if (r->rule_flag & PFRULE_PFLOW) + s->state_flags |= PFSTATE_PFLOW; s->act.log = pd->act.log & PF_LOG_ALL; s->sync_state = PFSYNC_S_NONE; diff --git a/sys/netpfil/pf/pf.h b/sys/netpfil/pf/pf.h index dd9796b59ce9..d5ab4f03a96d 100644 --- a/sys/netpfil/pf/pf.h +++ b/sys/netpfil/pf/pf.h @@ -614,6 +614,7 @@ struct pf_rule { #define PFRULE_SET_TOS 0x00002000 #define PFRULE_IFBOUND 0x00010000 /* if-bound */ #define PFRULE_STATESLOPPY 0x00020000 /* sloppy state tracking */ +#define PFRULE_PFLOW 0x00040000 #ifdef _KERNEL #define PFRULE_REFS 0x0080 /* rule has references */ @@ -626,7 +627,7 @@ struct pf_rule { /* pf_state->state_flags, pf_rule_actions->flags, pf_krule->scrub_flags */ #define PFSTATE_ALLOWOPTS 0x0001 #define PFSTATE_SLOPPY 0x0002 -/* was PFSTATE_PFLOW 0x0004 */ +#define PFSTATE_PFLOW 0x0004 #define PFSTATE_NOSYNC 0x0008 #define PFSTATE_ACK 0x0010 #define PFSTATE_NODF 0x0020 diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c index e09b7b71920e..956d954d652c 100644 --- a/sys/netpfil/pf/pf_ioctl.c +++ b/sys/netpfil/pf/pf_ioctl.c @@ -304,6 +304,7 @@ VNET_DEFINE(pfsync_update_state_t *, pfsync_update_state_ptr); VNET_DEFINE(pfsync_delete_state_t *, pfsync_delete_state_ptr); VNET_DEFINE(pfsync_clear_states_t *, pfsync_clear_states_ptr); VNET_DEFINE(pfsync_defer_t *, pfsync_defer_ptr); +VNET_DEFINE(pflow_export_state_t *, pflow_export_state_ptr); pfsync_detach_ifnet_t *pfsync_detach_ifnet_ptr; /* pflog */ diff --git a/sys/netpfil/pf/pflow.c b/sys/netpfil/pf/pflow.c index 2dc612bd9e07..a2699240fbc8 100644 --- a/sys/netpfil/pf/pflow.c +++ b/sys/netpfil/pf/pflow.c @@ -87,18 +87,19 @@ static void pflow_timeout(void *); static void pflow_timeout6(void *); static void pflow_timeout_tmpl(void *); static void copy_flow_data(struct pflow_flow *, struct pflow_flow *, - struct pf_kstate *, struct pf_state_key *, int, int); + const struct pf_kstate *, struct pf_state_key *, int, int); static void copy_flow_ipfix_4_data(struct pflow_ipfix_flow4 *, - struct pflow_ipfix_flow4 *, struct pf_kstate *, struct pf_state_key *, + struct pflow_ipfix_flow4 *, const struct pf_kstate *, struct pf_state_key *, struct pflow_softc *, int, int); static void copy_flow_ipfix_6_data(struct pflow_ipfix_flow6 *, - struct pflow_ipfix_flow6 *, struct pf_kstate *, struct pf_state_key *, + struct pflow_ipfix_flow6 *, const struct pf_kstate *, struct pf_state_key *, struct pflow_softc *, int, int); -static int pflow_pack_flow(struct pf_kstate *, struct pf_state_key *, +static int pflow_pack_flow(const struct pf_kstate *, struct pf_state_key *, struct pflow_softc *); -static int pflow_pack_flow_ipfix(struct pf_kstate *, struct pf_state_key *, +static int pflow_pack_flow_ipfix(const struct pf_kstate *, struct pf_state_key *, struct pflow_softc *); -static int export_pflow_if(struct pf_kstate*, struct pf_state_key *, +static void export_pflow(const struct pf_kstate *); +static int export_pflow_if(const struct pf_kstate*, struct pf_state_key *, struct pflow_softc *); static int copy_flow_to_m(struct pflow_flow *flow, struct pflow_softc *sc); static int copy_flow_ipfix_4_to_m(struct pflow_ipfix_flow4 *flow, @@ -323,6 +324,8 @@ pflow_create(int unit) CK_LIST_INSERT_HEAD(&V_pflowif_list, pflowif, sc_next); mtx_unlock(&V_pflowif_list_mtx); + V_pflow_export_state_ptr = export_pflow; + return (0); } @@ -352,6 +355,8 @@ pflow_destroy(int unit, bool drain) return (ENOENT); } CK_LIST_REMOVE(sc, sc_next); + if (CK_LIST_EMPTY(&V_pflowif_list)) + V_pflow_export_state_ptr = NULL; mtx_unlock(&V_pflowif_list_mtx); sc->sc_dying = 1; @@ -511,7 +516,7 @@ pflow_get_mbuf(struct pflow_softc *sc, u_int16_t set_id) static void copy_flow_data(struct pflow_flow *flow1, struct pflow_flow *flow2, - struct pf_kstate *st, struct pf_state_key *sk, int src, int dst) + const struct pf_kstate *st, struct pf_state_key *sk, int src, int dst) { flow1->src_ip = flow2->dest_ip = sk->addr[src].v4.s_addr; flow1->src_port = flow2->dest_port = sk->port[src]; @@ -548,7 +553,7 @@ copy_flow_data(struct pflow_flow *flow1, struct pflow_flow *flow2, static void copy_flow_ipfix_4_data(struct pflow_ipfix_flow4 *flow1, - struct pflow_ipfix_flow4 *flow2, struct pf_kstate *st, + struct pflow_ipfix_flow4 *flow2, const struct pf_kstate *st, struct pf_state_key *sk, struct pflow_softc *sc, int src, int dst) { flow1->src_ip = flow2->dest_ip = sk->addr[src].v4.s_addr; @@ -585,7 +590,7 @@ copy_flow_ipfix_4_data(struct pflow_ipfix_flow4 *flow1, static void copy_flow_ipfix_6_data(struct pflow_ipfix_flow6 *flow1, - struct pflow_ipfix_flow6 *flow2, struct pf_kstate *st, + struct pflow_ipfix_flow6 *flow2, const struct pf_kstate *st, struct pf_state_key *sk, struct pflow_softc *sc, int src, int dst) { bcopy(&sk->addr[src].v6, &flow1->src_ip, sizeof(flow1->src_ip)); @@ -622,8 +627,8 @@ copy_flow_ipfix_6_data(struct pflow_ipfix_flow6 *flow1, flow1->tos = flow2->tos = st->rule.ptr->tos; } -int -export_pflow(struct pf_kstate *st) +static void +export_pflow(const struct pf_kstate *st) { struct pflow_softc *sc = NULL; struct pf_state_key *sk; @@ -648,12 +653,10 @@ export_pflow(struct pf_kstate *st) } PFLOW_UNLOCK(sc); } - - return (0); } static int -export_pflow_if(struct pf_kstate *st, struct pf_state_key *sk, +export_pflow_if(const struct pf_kstate *st, struct pf_state_key *sk, struct pflow_softc *sc) { struct pf_kstate pfs_copy; @@ -787,7 +790,7 @@ copy_flow_ipfix_6_to_m(struct pflow_ipfix_flow6 *flow, struct pflow_softc *sc) } static int -pflow_pack_flow(struct pf_kstate *st, struct pf_state_key *sk, +pflow_pack_flow(const struct pf_kstate *st, struct pf_state_key *sk, struct pflow_softc *sc) { struct pflow_flow flow1; @@ -812,7 +815,7 @@ pflow_pack_flow(struct pf_kstate *st, struct pf_state_key *sk, } static int -pflow_pack_flow_ipfix(struct pf_kstate *st, struct pf_state_key *sk, +pflow_pack_flow_ipfix(const struct pf_kstate *st, struct pf_state_key *sk, struct pflow_softc *sc) { struct pflow_ipfix_flow4 flow4_1, flow4_2;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202401160851.40G8psfL075765>