pf: convert DIOCCLRSTATUS to netlink

Sponsored by:	Rubicon Communications, LLC ("Netgate")
This commit is contained in:
Kristof Provost 2024-05-30 19:31:26 +02:00
parent 005dd61dd6
commit 9dbbe68bc5
7 changed files with 77 additions and 43 deletions

View file

@ -108,6 +108,35 @@ pfctl_fd(struct pfctl_handle *h)
return (h->fd);
}
static int
pfctl_do_netlink_cmd(struct pfctl_handle *h, uint cmd)
{
struct snl_errmsg_data e = {};
struct snl_writer nw;
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, cmd);
hdr = snl_finalize_msg(&nw);
if (hdr == NULL)
return (ENOMEM);
seq_id = hdr->nlmsg_seq;
snl_send_message(&h->ss, hdr);
while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) {
}
return (e.error);
}
static int
pfctl_do_ioctl(int dev, uint cmd, size_t size, nvlist_t **nvl)
{
@ -229,31 +258,7 @@ pf_nvuint_64_array(const nvlist_t *nvl, const char *name, size_t maxelems,
int
pfctl_startstop(struct pfctl_handle *h, int start)
{
struct snl_errmsg_data e = {};
struct snl_writer nw;
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,
start ? PFNL_CMD_START : PFNL_CMD_STOP);
hdr = snl_finalize_msg(&nw);
if (hdr == NULL)
return (ENOMEM);
seq_id = hdr->nlmsg_seq;
snl_send_message(&h->ss, hdr);
while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) {
}
return (e.error);
return (pfctl_do_netlink_cmd(h, start ? PFNL_CMD_START : PFNL_CMD_STOP));
}
static void
@ -487,6 +492,11 @@ pfctl_get_status(int dev)
return (status);
}
int
pfctl_clear_status(struct pfctl_handle *h)
{
return (pfctl_do_netlink_cmd(h, PFNL_CMD_CLEAR_STATUS));
}
static uint64_t
_pfctl_status_counter(struct pfctl_status_counters *counters, uint64_t id)

View file

@ -395,6 +395,7 @@ int pfctl_fd(struct pfctl_handle *);
int pfctl_startstop(struct pfctl_handle *h, int start);
struct pfctl_status* pfctl_get_status_h(struct pfctl_handle *h);
struct pfctl_status* pfctl_get_status(int dev);
int pfctl_clear_status(struct pfctl_handle *h);
uint64_t pfctl_status_counter(struct pfctl_status *status, int id);
uint64_t pfctl_status_lcounter(struct pfctl_status *status, int id);
uint64_t pfctl_status_fcounter(struct pfctl_status *status, int id);

View file

@ -66,7 +66,7 @@
void usage(void);
int pfctl_enable(int, int);
int pfctl_disable(int, int);
int pfctl_clear_stats(int, int);
int pfctl_clear_stats(struct pfctl_handle *, int);
int pfctl_get_skip_ifaces(void);
int pfctl_check_skip_ifaces(char *);
int pfctl_adjust_skip_ifaces(struct pfctl *);
@ -353,9 +353,9 @@ pfctl_disable(int dev, int opts)
}
int
pfctl_clear_stats(int dev, int opts)
pfctl_clear_stats(struct pfctl_handle *h, int opts)
{
if (ioctl(dev, DIOCCLRSTATUS))
if (pfctl_clear_status(h))
err(1, "DIOCCLRSTATUS");
if ((opts & PF_OPT_QUIET) == 0)
fprintf(stderr, "pf: statistics cleared\n");
@ -3237,7 +3237,7 @@ main(int argc, char *argv[])
pfctl_clear_src_nodes(dev, opts);
break;
case 'i':
pfctl_clear_stats(dev, opts);
pfctl_clear_stats(pfh, opts);
break;
case 'a':
pfctl_flush_eth_rules(dev, opts, anchorname);
@ -3248,7 +3248,7 @@ main(int argc, char *argv[])
pfctl_clear_altq(dev, opts);
pfctl_clear_iface_states(dev, ifaceopt, opts);
pfctl_clear_src_nodes(dev, opts);
pfctl_clear_stats(dev, opts);
pfctl_clear_stats(pfh, opts);
pfctl_clear_fingerprints(dev, opts);
pfctl_clear_interface_flags(dev, opts);
}

View file

@ -2502,6 +2502,7 @@ int pf_ioctl_getrules(struct pfioc_rule *);
int pf_ioctl_addrule(struct pf_krule *, uint32_t,
uint32_t, const char *, const char *, uid_t uid,
pid_t);
void pf_ioctl_clear_status(void);
void pf_krule_free(struct pf_krule *);
void pf_krule_clear_counters(struct pf_krule *);

View file

@ -2424,6 +2424,24 @@ pf_stop(void)
return (error);
}
void
pf_ioctl_clear_status(void)
{
PF_RULES_WLOCK();
for (int i = 0; i < PFRES_MAX; i++)
counter_u64_zero(V_pf_status.counters[i]);
for (int i = 0; i < FCNT_MAX; i++)
pf_counter_u64_zero(&V_pf_status.fcounters[i]);
for (int i = 0; i < SCNT_MAX; i++)
counter_u64_zero(V_pf_status.scounters[i]);
for (int i = 0; i < KLCNT_MAX; i++)
counter_u64_zero(V_pf_status.lcounters[i]);
V_pf_status.since = time_second;
if (*V_pf_status.ifname)
pfi_update_status(V_pf_status.ifname, NULL);
PF_RULES_WUNLOCK();
}
static int
pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td)
{
@ -3765,19 +3783,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
}
case DIOCCLRSTATUS: {
PF_RULES_WLOCK();
for (int i = 0; i < PFRES_MAX; i++)
counter_u64_zero(V_pf_status.counters[i]);
for (int i = 0; i < FCNT_MAX; i++)
pf_counter_u64_zero(&V_pf_status.fcounters[i]);
for (int i = 0; i < SCNT_MAX; i++)
counter_u64_zero(V_pf_status.scounters[i]);
for (int i = 0; i < KLCNT_MAX; i++)
counter_u64_zero(V_pf_status.lcounters[i]);
V_pf_status.since = time_second;
if (*V_pf_status.ifname)
pfi_update_status(V_pf_status.ifname, NULL);
PF_RULES_WUNLOCK();
pf_ioctl_clear_status();
break;
}

View file

@ -1214,6 +1214,14 @@ pf_handle_get_status(struct nlmsghdr *hdr, struct nl_pstate *npt)
return (error);
}
static int
pf_handle_clear_status(struct nlmsghdr *hdr, struct nl_pstate *npt)
{
pf_ioctl_clear_status();
return (0);
}
static const struct nlhdr_parser *all_parsers[] = {
&state_parser,
&addrule_parser,
@ -1302,6 +1310,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_CLEAR_STATUS,
.cmd_name = "CLEARSTATUS",
.cmd_cb = pf_handle_clear_status,
.cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_HASPOL,
.cmd_priv = PRIV_NETINET_PF,
},
};
void

View file

@ -47,6 +47,7 @@ enum {
PFNL_CMD_KILLSTATES = 9,
PFNL_CMD_SET_STATUSIF = 10,
PFNL_CMD_GET_STATUS = 11,
PFNL_CMD_CLEAR_STATUS = 12,
__PFNL_CMD_MAX,
};
#define PFNL_CMD_MAX (__PFNL_CMD_MAX -1)