aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorKajetan Staszkiewicz <ks@FreeBSD.org>2025-02-07 11:40:09 +0000
committerKajetan Staszkiewicz <ks@FreeBSD.org>2025-02-13 14:59:12 +0000
commit07e070ef086997590cd6d9d47908885c12947bd2 (patch)
tree280e9348bb8714ef281b49a6bbf8ff8b9a8c3208 /lib
parentb61fbbed73ea3bf0c84589b56cca160c46a3739d (diff)
pf: Add support for multiple source node types
For every state pf creates up to two source nodes: a limiting one struct pf_kstate -> src_node and a NAT one struct pf_kstate -> nat_src_node. The limiting source node is tracking information needed for limits using max-src-states and max-src-nodes and the NAT source node is tracking NAT rules only. On closer inspection some issues emerge: - For route-to rules the redirection decision is stored in the limiting source node. Thus sticky-address and source limiting can't be used separately. - Global source tracking, as promised in the man page, is totally absent from the code. Pfctl is capable of setting flags PFRULE_SRCTRACK (enable source tracking) and PFRULE_RULESRCTRACK (make source tracking per rule). The kernel code checks PFRULE_SRCTRACK but ignores PFRULE_RULESRCTRACK. That makes source tracking work per-rule only. This patch is based on OpenBSD approach where source nodes have a type and each state has an array of source node pointers indexed by source node type instead of just two pointers. The conditions for limiting are applied only to source nodes of PF_SN_LIMIT type. For global limit tracking source nodes are attached to the default rule. Reviewed by: kp Approved by: kp (mentor) Sponsored by: InnoGames GmbH Differential Revision: https://reviews.freebsd.org/D39880
Diffstat (limited to 'lib')
-rw-r--r--lib/libpfctl/libpfctl.c5
-rw-r--r--lib/libpfctl/libpfctl.h3
2 files changed, 8 insertions, 0 deletions
diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c
index fe63c91c1174..e93c79758428 100644
--- a/lib/libpfctl/libpfctl.c
+++ b/lib/libpfctl/libpfctl.c
@@ -1665,6 +1665,9 @@ static struct snl_attr_parser ap_getrule[] = {
{ .type = PF_RT_NAF, .off = _OUT(r.naf), .cb = snl_attr_get_uint8 },
{ .type = PF_RT_RPOOL_RT, .off = _OUT(r.route), .arg = &pool_parser, .cb = snl_attr_get_nested },
{ .type = PF_RT_RCV_IFNOT, .off = _OUT(r.rcvifnot),.cb = snl_attr_get_bool },
+ { .type = PF_RT_SRC_NODES_LIMIT, .off = _OUT(r.src_nodes_type[PF_SN_LIMIT]), .cb = snl_attr_get_uint64 },
+ { .type = PF_RT_SRC_NODES_NAT, .off = _OUT(r.src_nodes_type[PF_SN_NAT]), .cb = snl_attr_get_uint64 },
+ { .type = PF_RT_SRC_NODES_ROUTE, .off = _OUT(r.src_nodes_type[PF_SN_ROUTE]), .cb = snl_attr_get_uint64 },
};
#undef _OUT
SNL_DECLARE_PARSER(getrule_parser, struct genlmsghdr, snl_f_p_empty, ap_getrule);
@@ -1910,6 +1913,7 @@ static struct snl_attr_parser ap_state[] = {
{ .type = PF_ST_DNRPIPE, .off = _OUT(dnrpipe), .cb = snl_attr_get_uint16 },
{ .type = PF_ST_RT, .off = _OUT(rt), .cb = snl_attr_get_uint8 },
{ .type = PF_ST_RT_IFNAME, .off = _OUT(rt_ifname), .cb = snl_attr_store_ifname },
+ { .type = PF_ST_SRC_NODE_FLAGS, .off = _OUT(src_node_flags), .cb = snl_attr_get_uint8 },
};
#undef _IN
#undef _OUT
@@ -3018,6 +3022,7 @@ static struct snl_attr_parser ap_srcnode[] = {
{ .type = PF_SN_EXPIRE, .off = _OUT(expire), .cb = snl_attr_get_uint64 },
{ .type = PF_SN_CONNECTION_RATE, .off = _OUT(conn_rate), .arg = &pfctl_threshold_parser, .cb = snl_attr_get_nested },
{ .type = PF_SN_NAF, .off = _OUT(naf), .cb = snl_attr_get_uint8 },
+ { .type = PF_SN_NODE_TYPE, .off = _OUT(type), .cb = snl_attr_get_uint8 },
};
#undef _OUT
SNL_DECLARE_PARSER(srcnode_parser, struct genlmsghdr, snl_f_p_empty, ap_srcnode);
diff --git a/lib/libpfctl/libpfctl.h b/lib/libpfctl/libpfctl.h
index e1af4b5e97ff..1108b0ffc693 100644
--- a/lib/libpfctl/libpfctl.h
+++ b/lib/libpfctl/libpfctl.h
@@ -216,6 +216,7 @@ struct pfctl_rule {
uint64_t states_cur;
uint64_t states_tot;
uint64_t src_nodes;
+ uint64_t src_nodes_type[PF_SN_MAX];
uint16_t return_icmp;
uint16_t return_icmp6;
@@ -373,6 +374,7 @@ struct pfctl_state {
uint8_t set_prio[2];
uint8_t rt;
char rt_ifname[IFNAMSIZ];
+ uint8_t src_node_flags;
};
TAILQ_HEAD(pfctl_statelist, pfctl_state);
@@ -415,6 +417,7 @@ struct pfctl_src_node {
uint64_t creation;
uint64_t expire;
struct pfctl_threshold conn_rate;
+ pf_sn_types_t type;
};
#define PF_DEVICE "/dev/pf"