diff options
author | Kristof Provost <kp@FreeBSD.org> | 2025-02-07 16:35:46 +0000 |
---|---|---|
committer | Kristof Provost <kp@FreeBSD.org> | 2025-02-10 11:09:47 +0000 |
commit | 84a80eae6987bace1552882a7bb94e62fa1dc3ad (patch) | |
tree | c501afae61b01c876d0e35df06e7c4b00c54c8b6 | |
parent | b452e72bda5eaa09d6fad94d3b538f21754c5313 (diff) |
pf: convert DIOCRADDTABLES to netlink
Sponsored by: Rubicon Communications, LLC ("Netgate")
-rw-r--r-- | lib/libpfctl/libpfctl.c | 43 | ||||
-rw-r--r-- | lib/libpfctl/libpfctl.h | 2 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_radix.c | 15 | ||||
-rw-r--r-- | sys/netpfil/pf/pf_nl.c | 44 | ||||
-rw-r--r-- | sys/netpfil/pf/pf_nl.h | 2 |
5 files changed, 92 insertions, 14 deletions
diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c index 2297b24d37a0..50dfcfea703d 100644 --- a/lib/libpfctl/libpfctl.c +++ b/lib/libpfctl/libpfctl.c @@ -3100,3 +3100,46 @@ pfctl_clear_tables(struct pfctl_handle *h, struct pfr_table *filter, return (e.error); } + +static struct snl_attr_parser ap_nadd[] = { + { .type = PF_T_NBR_ADDED, .off = 0, .cb = snl_attr_get_uint32 }, +}; +SNL_DECLARE_PARSER(nadd_parser, struct genlmsghdr, snl_f_p_empty, ap_nadd); +int +pfctl_add_table(struct pfctl_handle *h, struct pfr_table *table, + int *nadd, int flags) +{ + struct snl_writer nw; + struct snl_errmsg_data e = {}; + struct nlmsghdr *hdr; + uint32_t seq_id; + int family_id; + + family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); + if (family_id == 0) + return (ENOTSUP); + + snl_init_writer(&h->ss, &nw); + hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_ADD_TABLE); + + snl_add_msg_attr_string(&nw, PF_T_ANCHOR, table->pfrt_anchor); + snl_add_msg_attr_string(&nw, PF_T_NAME, table->pfrt_name); + snl_add_msg_attr_u32(&nw, PF_T_TABLE_FLAGS, table->pfrt_flags); + snl_add_msg_attr_u32(&nw, PF_T_FLAGS, flags); + + if ((hdr = snl_finalize_msg(&nw)) == NULL) + return (ENXIO); + + seq_id = hdr->nlmsg_seq; + + if (!snl_send_message(&h->ss, hdr)) + return (ENXIO); + + while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { + if (!snl_parse_nlmsg(&h->ss, hdr, &nadd_parser, nadd)) + continue; + } + + return (e.error); +} + diff --git a/lib/libpfctl/libpfctl.h b/lib/libpfctl/libpfctl.h index 2532894ffa21..300511452d8f 100644 --- a/lib/libpfctl/libpfctl.h +++ b/lib/libpfctl/libpfctl.h @@ -542,5 +542,7 @@ int pfctl_get_srcnodes(struct pfctl_handle *h, pfctl_get_srcnode_fn fn, void *ar int pfctl_clear_tables(struct pfctl_handle *h, struct pfr_table *filter, int *ndel, int flags); +int pfctl_add_table(struct pfctl_handle *h, struct pfr_table *table, + int *nadd, int flags); #endif diff --git a/sbin/pfctl/pfctl_radix.c b/sbin/pfctl/pfctl_radix.c index 49a20d6c98f4..7cb9b6faa0d9 100644 --- a/sbin/pfctl/pfctl_radix.c +++ b/sbin/pfctl/pfctl_radix.c @@ -76,20 +76,7 @@ pfr_report_error(struct pfr_table *tbl, struct pfioc_table *io, int pfr_add_table(struct pfr_table *tbl, int *nadd, int flags) { - struct pfioc_table io; - - bzero(&io, sizeof io); - io.pfrio_flags = flags; - io.pfrio_buffer = tbl; - io.pfrio_esize = sizeof(*tbl); - io.pfrio_size = 1; - if (ioctl(dev, DIOCRADDTABLES, &io)) { - pfr_report_error(tbl, &io, "add table"); - return (-1); - } - if (nadd != NULL) - *nadd = io.pfrio_nadd; - return (0); + return (pfctl_add_table(pfh, tbl, nadd, flags)); } int diff --git a/sys/netpfil/pf/pf_nl.c b/sys/netpfil/pf/pf_nl.c index 737e9cf8cab8..74c5bdca4f77 100644 --- a/sys/netpfil/pf/pf_nl.c +++ b/sys/netpfil/pf/pf_nl.c @@ -1842,6 +1842,43 @@ pf_handle_clear_tables(struct nlmsghdr *hdr, struct nl_pstate *npt) return (0); } +static int +pf_handle_add_table(struct nlmsghdr *hdr, struct nl_pstate *npt) +{ + struct pfioc_table attrs = { 0 }; + struct nl_writer *nw = npt->nw; + struct genlmsghdr *ghdr_new; + int error; + + error = nl_parse_nlmsg(hdr, &table_parser, npt, &attrs); + if (error != 0) + return (error); + + PF_RULES_WLOCK(); + error = pfr_add_tables(&attrs.pfrio_table, 1, &attrs.pfrio_nadd, + attrs.pfrio_flags | PFR_FLAG_USERIOCTL); + PF_RULES_WUNLOCK(); + if (error != 0) + return (error); + + if (!nlmsg_reply(nw, hdr, sizeof(struct genlmsghdr))) + return (ENOMEM); + + ghdr_new = nlmsg_reserve_object(nw, struct genlmsghdr); + ghdr_new->cmd = PFNL_CMD_ADD_TABLE; + ghdr_new->version = 0; + ghdr_new->reserved = 0; + + nlattr_add_u32(nw, PF_T_NBR_ADDED, attrs.pfrio_nadd); + + if (!nlmsg_end(nw)) { + nlmsg_abort(nw); + return (ENOMEM); + } + + return (0); +} + static const struct nlhdr_parser *all_parsers[] = { &state_parser, &addrule_parser, @@ -2043,6 +2080,13 @@ static const struct genl_cmd pf_cmds[] = { .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, }, + { + .cmd_num = PFNL_CMD_ADD_TABLE, + .cmd_name = "ADD_TABLE", + .cmd_cb = pf_handle_add_table, + .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_HASPOL, + .cmd_priv = PRIV_NETINET_PF, + }, }; void diff --git a/sys/netpfil/pf/pf_nl.h b/sys/netpfil/pf/pf_nl.h index d749ef3ab99e..38a44c2c4395 100644 --- a/sys/netpfil/pf/pf_nl.h +++ b/sys/netpfil/pf/pf_nl.h @@ -62,6 +62,7 @@ enum { PFNL_CMD_GET_RULESET = 24, PFNL_CMD_GET_SRCNODES = 25, PFNL_CMD_CLEAR_TABLES = 26, + PFNL_CMD_ADD_TABLE = 27, __PFNL_CMD_MAX, }; #define PFNL_CMD_MAX (__PFNL_CMD_MAX -1) @@ -431,6 +432,7 @@ enum pf_tables_t { PF_T_TABLE_FLAGS = 3, /* u32 */ PF_T_FLAGS = 4, /* u32 */ PF_T_NBR_DELETED = 5, /* u32 */ + PF_T_NBR_ADDED = 6, /* u32 */ }; #ifdef _KERNEL |