pf: convert DIOCXBEGIN, DIOCXROLLBACK, DIOCXCOMMIT to netlink

Sponsored by:	Rubicon Communications, LLC ("Netgate")
This commit is contained in:
Kristof Provost committed 2026-10-30 13:21:10 +01:00
1 parent 0974ef03b4
commit a7aad5bbcd
11 files changed
+673 -76

No files matched your search

+200
View File
@@ -4594,6 +4594,206 @@ out:
return (e.error);
}
struct pfctl_trans_e {
int rs_num;
char anchor[MAXPATHLEN];
uint32_t ticket;
TAILQ_ENTRY(pfctl_trans_e) entry;
};
struct pfctl_trans {
struct pfctl_trans_e tmp;
TAILQ_HEAD(, pfctl_trans_e) elms;
};
struct pfctl_trans *
pfctl_trans_alloc(void)
{
struct pfctl_trans *t = malloc(sizeof(struct pfctl_trans));
bzero(t, sizeof(*t));
TAILQ_INIT(&t->elms);
return (t);
}
void
pfctl_trans_free(struct pfctl_trans *t)
{
struct pfctl_trans_e *e, *et;
TAILQ_FOREACH_SAFE(e, &t->elms, entry, et)
free(e);
free(t);
}
size_t
pfctl_trans_size(struct pfctl_trans *t)
{
struct pfctl_trans_e *e;
size_t s = 0;
TAILQ_FOREACH(e, &t->elms, entry)
s++;
return (s);
}
int
pfctl_trans_add(struct pfctl_trans *t, int rs_num, const char *anchor)
{
struct pfctl_trans_e *e;
e = malloc(sizeof(*e));
if (e == NULL)
return (ENOMEM);
e->rs_num = rs_num;
e->ticket = 0;
strlcpy(e->anchor, anchor, sizeof(e->anchor));
TAILQ_INSERT_TAIL(&t->elms, e, entry);
return (0);
}
uint32_t
pfctl_get_ticket(struct pfctl_trans *t, int rs_num, const char *anchor)
{
struct pfctl_trans_e *e;
TAILQ_FOREACH(e, &t->elms, entry) {
if (e->rs_num != rs_num)
continue;
if (strcmp(e->anchor, anchor) != 0)
continue;
return (e->ticket);
}
return (-1);
}
static void
snl_add_msg_attr_trans_e(struct snl_writer *nw, uint32_t type,
const struct pfctl_trans_e *e)
{
int off = snl_add_msg_attr_nested(nw, type);
snl_add_msg_attr_u32(nw, PF_TE_RULESET_NUM, e->rs_num);
snl_add_msg_attr_string(nw, PF_TE_ANCHOR, e->anchor);
snl_add_msg_attr_u32(nw, PF_TE_TICKET, e->ticket);
snl_end_attr_nested(nw, off);
}
#define _OUT(_field) offsetof(struct pfctl_trans_e, _field)
static const struct snl_attr_parser ap_trans_e[] = {
{ .type = PF_TE_RULESET_NUM, .off = _OUT(rs_num), .cb = snl_attr_get_uint32 },
{ .type = PF_TE_ANCHOR, .off = _OUT(anchor), .arg_u32 = MAXPATHLEN, .cb = snl_attr_copy_string },
{ .type = PF_TE_TICKET, .off = _OUT(ticket), .cb = snl_attr_get_uint32 },
};
#undef _OUT
static bool
_pfctl_trans_e_post(struct snl_state *ss, void *target)
{
struct pfctl_trans *t = (struct pfctl_trans *)target;
struct pfctl_trans_e *e;
(void)ss;
TAILQ_FOREACH(e, &t->elms, entry) {
if (e->rs_num != t->tmp.rs_num)
continue;
if (strcmp(e->anchor, t->tmp.anchor) != 0)
continue;
e->ticket = t->tmp.ticket;
return (true);
}
e = malloc(sizeof(*e));
if (! e)
return (false);
memcpy(e, &t->tmp, sizeof(*e));
TAILQ_INSERT_TAIL(&t->elms, e, entry);
return (true);
}
SNL_DECLARE_ATTR_PARSER_EXT(trans_e_parser, 0, ap_trans_e, _pfctl_trans_e_post);
static struct snl_attr_parser ap_trans[] = {
{ .type = PF_TR_TRANS, .arg = &trans_e_parser, .cb = snl_attr_get_nested },
};
SNL_DECLARE_PARSER(trans_parser, struct genlmsghdr, snl_f_p_empty, ap_trans);
static int
_pfctl_trans(struct pfctl_handle *h, struct pfctl_trans *t, size_t off, int cmd)
{
struct snl_writer nw;
struct snl_errmsg_data e = {};
struct nlmsghdr *hdr;
struct pfctl_trans_e *te;
uint32_t seq_id;
snl_init_writer(&h->ss, &nw);
hdr = snl_create_genl_msg_request(&nw, h->family_id,
cmd);
snl_add_msg_attr_u32(&nw, PF_TR_UNSPEC, 0);
TAILQ_FOREACH(te, &t->elms, entry) {
if (off) {
off--;
continue;
}
snl_add_msg_attr_trans_e(&nw, PF_TR_TRANS, te);
}
if ((hdr = snl_finalize_msg(&nw)) == NULL) {
e.error = ENXIO;
goto out;
}
seq_id = hdr->nlmsg_seq;
if (! snl_send_message(&h->ss, hdr)) {
e.error = ENXIO;
goto out;
}
while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) {
if (! snl_parse_nlmsg(&h->ss, hdr, &trans_parser, t))
continue;
}
out:
snl_clear_lb(&h->ss);
return (e.error);
}
int
pfctl_trans_begin(struct pfctl_handle *h, struct pfctl_trans *t, size_t off)
{
return (_pfctl_trans(h, t, off, PFNL_CMD_BEGIN));
}
int
pfctl_trans_commit(struct pfctl_handle *h, struct pfctl_trans *t, size_t off)
{
return (_pfctl_trans(h, t, off, PFNL_CMD_COMMIT));
}
int
pfctl_trans_rollback(struct pfctl_handle *h, struct pfctl_trans *t, size_t off)
{
return (_pfctl_trans(h, t, off, PFNL_CMD_ROLLBACK));
}
static const struct snl_hdr_parser *all_parsers[] = {
&begin_addrs_parser,
&clear_states_parser,
+12
View File
@@ -699,4 +699,16 @@ int pfctl_flush_fingerprints(struct pfctl_handle *h);
int pfctl_get_fingerprint(struct pfctl_handle *h, int idx, struct pf_osfp_ioctl *fp);
int pfctl_add_fingerprint(struct pfctl_handle *h, struct pf_osfp_ioctl *fp);
struct pfctl_trans;
struct pfctl_trans* pfctl_trans_alloc(void);
void pfctl_trans_free(struct pfctl_trans *t);
size_t pfctl_trans_size(struct pfctl_trans *t);
int pfctl_trans_add(struct pfctl_trans *t, int rs_num, const char *anchor);
uint32_t pfctl_get_ticket(struct pfctl_trans *t, int rs_num, const char *anchor);
int pfctl_trans_begin(struct pfctl_handle *h, struct pfctl_trans *t, size_t off);
int pfctl_trans_commit(struct pfctl_handle *h, struct pfctl_trans *t, size_t off);
int pfctl_trans_rollback(struct pfctl_handle *h, struct pfctl_trans *t, size_t off);
#endif
+16
View File
@@ -347,6 +347,18 @@ static const struct nlattr_decoder nla_d_ruleset[] = {
};
NL_DECLARE_ATTR_DECODER(ruleset_decoder, nla_d_ruleset);
static const struct nlattr_decoder nla_d_trans_e[] = {
{ .type = PF_TE_RULESET_NUM, .attr_name = "rs_num", .cb = nlattr_decode_uint32 },
{ .type = PF_TE_ANCHOR, .attr_name="anchor", .cb = nlattr_decode_string },
{ .type = PF_TE_TICKET, .attr_name = "ticket", .cb = nlattr_decode_uint32 },
};
NL_DECLARE_ATTR_DECODER(trans_e_decoder, nla_d_trans_e);
static const struct nlattr_decoder nla_d_trans[] = {
{ .type = PF_TR_TRANS, .attr_name = "trans", .cb = nlattr_decode_nested, .args = &trans_e_decoder },
};
NL_DECLARE_ATTR_DECODER(trans_decoder, nla_d_trans);
static inline void
nl_verify_decoders(const struct nlattr_decoder_set **decoder, size_t count)
{
@@ -368,6 +380,7 @@ static const struct nlattr_decoder_set *all_decoders[] = {
&rule_addr_decoder,
&killclear_states_decoder,
&ruleset_decoder,
&trans_decoder,
};
static const struct pfnl_cmd_decoder cmd_decoder[] = {
@@ -378,6 +391,9 @@ static const struct pfnl_cmd_decoder cmd_decoder[] = {
{ .cmd_num = PFNL_CMD_GET_ADDR, .ds = &addr_decoder },
{ .cmd_num = PFNL_CMD_GET_RULESETS, .ds = &ruleset_decoder },
{ .cmd_num = PFNL_CMD_GET_RULESET, .ds = &ruleset_decoder },
{ .cmd_num = PFNL_CMD_BEGIN, .ds = &trans_decoder },
{ .cmd_num = PFNL_CMD_COMMIT, .ds = &trans_decoder },
{ .cmd_num = PFNL_CMD_ROLLBACK, .ds = &trans_decoder },
};
static inline void