pf: convert DIOCBEGINADDRS to netlink

This commit is contained in:
Kristof Provost 2024-06-07 22:44:40 +02:00
parent 63a327b954
commit ba2a920786
9 changed files with 109 additions and 7 deletions

View File

@ -263,7 +263,7 @@ prepare_rule(u_int32_t id, int rs_num, struct sockaddr *src,
errno = EINVAL;
return (-1);
}
if (ioctl(pfctl_fd(pfh), DIOCBEGINADDRS, &pfp) == -1)
if (pfctl_begin_addrs(pfh, &pfp.ticket))
return (-1);
pfpool_ticket = pfp.ticket;

View File

@ -272,7 +272,7 @@ prepare_rule(u_int32_t id, int rs_num, struct sockaddr *src,
errno = EINVAL;
return (-1);
}
if (ioctl(pfctl_fd(pfh), DIOCBEGINADDRS, &pfp) == -1)
if (pfctl_begin_addrs(pfh, &pfp.ticket))
return (-1);
pfpool_ticket = pfp.ticket;

View File

@ -2688,3 +2688,52 @@ pfctl_get_limit(struct pfctl_handle *h, const int index, uint *limit)
return (e.error);
}
struct pfctl_nl_begin_addrs {
uint32_t ticket;
};
#define _OUT(_field) offsetof(struct pfctl_nl_begin_addrs, _field)
static struct snl_attr_parser ap_begin_addrs[] = {
{ .type = PF_BA_TICKET, .off = _OUT(ticket), .cb = snl_attr_get_uint32 },
};
static struct snl_field_parser fp_begin_addrs[] = {};
#undef _OUT
SNL_DECLARE_PARSER(begin_addrs_parser, struct genlmsghdr, fp_begin_addrs, ap_begin_addrs);
int
pfctl_begin_addrs(struct pfctl_handle *h, uint32_t *ticket)
{
struct snl_writer nw;
struct pfctl_nl_begin_addrs attrs = {};
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_BEGIN_ADDRS);
hdr->nlmsg_flags |= NLM_F_DUMP;
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, &begin_addrs_parser, &attrs))
continue;
}
if (ticket != NULL)
*ticket = attrs.ticket;
return (e.error);
}

View File

@ -497,5 +497,6 @@ int pfctl_set_timeout(struct pfctl_handle *h, uint32_t timeout, uint32_t seconds
int pfctl_get_timeout(struct pfctl_handle *h, uint32_t timeout, uint32_t *seconds);
int pfctl_set_limit(struct pfctl_handle *h, const int index, const uint limit);
int pfctl_get_limit(struct pfctl_handle *h, const int index, uint *limit);
int pfctl_begin_addrs(struct pfctl_handle *h, uint32_t *ticket);
#endif

View File

@ -1719,7 +1719,7 @@ pfctl_add_pool(struct pfctl *pf, struct pfctl_pool *p, sa_family_t af)
struct pf_pooladdr *pa;
if ((pf->opts & PF_OPT_NOACTION) == 0) {
if (ioctl(pf->dev, DIOCBEGINADDRS, &pf->paddr))
if (pfctl_begin_addrs(pf->h, &pf->paddr.ticket))
err(1, "DIOCBEGINADDRS");
}

View File

@ -2507,6 +2507,7 @@ int pf_ioctl_get_timeout(int, int *);
int pf_ioctl_set_timeout(int, int, int *);
int pf_ioctl_get_limit(int, unsigned int *);
int pf_ioctl_set_limit(int, unsigned int, unsigned int *);
int pf_ioctl_begin_addrs(uint32_t *);
void pf_krule_free(struct pf_krule *);
void pf_krule_clear_counters(struct pf_krule *);

View File

@ -2517,6 +2517,17 @@ pf_ioctl_get_limit(int index, unsigned int *limit)
return (0);
}
int
pf_ioctl_begin_addrs(uint32_t *ticket)
{
PF_RULES_WLOCK();
pf_empty_kpool(&V_pf_pabuf);
*ticket = ++V_ticket_pabuf;
PF_RULES_WUNLOCK();
return (0);
}
static int
pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td)
{
@ -4182,10 +4193,7 @@ DIOCGETSTATESV2_full:
case DIOCBEGINADDRS: {
struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr;
PF_RULES_WLOCK();
pf_empty_kpool(&V_pf_pabuf);
pp->ticket = ++V_ticket_pabuf;
PF_RULES_WUNLOCK();
error = pf_ioctl_begin_addrs(&pp->ticket);
break;
}

View File

@ -1471,6 +1471,36 @@ pf_handle_get_limit(struct nlmsghdr *hdr, struct nl_pstate *npt)
return (0);
}
static int
pf_handle_begin_addrs(struct nlmsghdr *hdr, struct nl_pstate *npt)
{
struct nl_writer *nw = npt->nw;
struct genlmsghdr *ghdr_new;
uint32_t ticket;
int error;
error = pf_ioctl_begin_addrs(&ticket);
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_BEGIN_ADDRS;
ghdr_new->version = 0;
ghdr_new->reserved = 0;
nlattr_add_u32(nw, PF_BA_TICKET, ticket);
if (!nlmsg_end(nw)) {
nlmsg_abort(nw);
return (ENOMEM);
}
return (0);
}
static const struct nlhdr_parser *all_parsers[] = {
&state_parser,
&addrule_parser,
@ -1612,6 +1642,13 @@ static const struct genl_cmd pf_cmds[] = {
.cmd_flags = GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL,
.cmd_priv = PRIV_NETINET_PF,
},
{
.cmd_num = PFNL_CMD_BEGIN_ADDRS,
.cmd_name = "BEGIN_ADDRS",
.cmd_cb = pf_handle_begin_addrs,
.cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL,
.cmd_priv = PRIV_NETINET_PF,
},
};
void

View File

@ -54,6 +54,7 @@ enum {
PFNL_CMD_GET_TIMEOUT = 16,
PFNL_CMD_SET_LIMIT = 17,
PFNL_CMD_GET_LIMIT = 18,
PFNL_CMD_BEGIN_ADDRS = 19,
__PFNL_CMD_MAX,
};
#define PFNL_CMD_MAX (__PFNL_CMD_MAX -1)
@ -350,6 +351,11 @@ enum pf_limit_types_t {
PF_LI_LIMIT = 2, /* u32 */
};
enum pf_begin_addrs_types_t {
PF_BA_UNSPEC,
PF_BA_TICKET = 1, /* u32 */
};
#ifdef _KERNEL
void pf_nl_register(void);