mirror of
https://github.com/freebsd/freebsd-src
synced 2024-07-21 18:27:22 +00:00
pf: support basic filters for state listing
Allow users(pace) to specify a protocol, interface, address family and/ or address and mask, allowing the state listing to be pre-filtered in the kernel. Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D42280
This commit is contained in:
parent
ffbf25951e
commit
044eef6ab9
|
@ -1342,7 +1342,7 @@ static const struct snl_hdr_parser *all_parsers[] = {
|
|||
};
|
||||
|
||||
static int
|
||||
pfctl_get_states_nl(struct snl_state *ss, pfctl_get_state_fn f, void *arg)
|
||||
pfctl_get_states_nl(struct pfctl_state_filter *filter, struct snl_state *ss, pfctl_get_state_fn f, void *arg)
|
||||
{
|
||||
SNL_VERIFY_PARSERS(all_parsers);
|
||||
int family_id = snl_get_genl_family(ss, PFNL_FAMILY_NAME);
|
||||
|
@ -1354,7 +1354,14 @@ pfctl_get_states_nl(struct snl_state *ss, pfctl_get_state_fn f, void *arg)
|
|||
snl_init_writer(ss, &nw);
|
||||
hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_GETSTATES);
|
||||
hdr->nlmsg_flags |= NLM_F_DUMP;
|
||||
snl_add_msg_attr_string(&nw, PF_ST_IFNAME, filter->ifname);
|
||||
snl_add_msg_attr_u16(&nw, PF_ST_PROTO, filter->proto);
|
||||
snl_add_msg_attr_u8(&nw, PF_ST_AF, filter->af);
|
||||
snl_add_msg_attr_ip6(&nw, PF_ST_FILTER_ADDR, &filter->addr.v6);
|
||||
snl_add_msg_attr_ip6(&nw, PF_ST_FILTER_MASK, &filter->mask.v6);
|
||||
|
||||
hdr = snl_finalize_msg(&nw);
|
||||
|
||||
uint32_t seq_id = hdr->nlmsg_seq;
|
||||
|
||||
snl_send_message(ss, hdr);
|
||||
|
@ -1379,12 +1386,19 @@ pfctl_get_states_nl(struct snl_state *ss, pfctl_get_state_fn f, void *arg)
|
|||
|
||||
int
|
||||
pfctl_get_states_iter(pfctl_get_state_fn f, void *arg)
|
||||
{
|
||||
struct pfctl_state_filter filter = {};
|
||||
return (pfctl_get_filtered_states_iter(&filter, f, arg));
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_get_filtered_states_iter(struct pfctl_state_filter *filter, pfctl_get_state_fn f, void *arg)
|
||||
{
|
||||
struct snl_state ss = {};
|
||||
int error;
|
||||
|
||||
snl_init(&ss, NETLINK_GENERIC);
|
||||
error = pfctl_get_states_nl(&ss, f, arg);
|
||||
error = pfctl_get_states_nl(filter, &ss, f, arg);
|
||||
snl_free(&ss);
|
||||
|
||||
return (error);
|
||||
|
|
|
@ -415,8 +415,17 @@ int pfctl_add_rule(int dev, const struct pfctl_rule *r,
|
|||
uint32_t pool_ticket);
|
||||
int pfctl_set_keepcounters(int dev, bool keep);
|
||||
int pfctl_get_creatorids(uint32_t *creators, size_t *len);
|
||||
|
||||
struct pfctl_state_filter {
|
||||
char ifname[IFNAMSIZ];
|
||||
uint16_t proto;
|
||||
sa_family_t af;
|
||||
struct pf_addr addr;
|
||||
struct pf_addr mask;
|
||||
};
|
||||
typedef int (*pfctl_get_state_fn)(struct pfctl_state *, void *);
|
||||
int pfctl_get_states_iter(pfctl_get_state_fn f, void *arg);
|
||||
int pfctl_get_filtered_states_iter(struct pfctl_state_filter *filter, pfctl_get_state_fn f, void *arg);
|
||||
int pfctl_get_states(int dev, struct pfctl_states *states);
|
||||
void pfctl_free_states(struct pfctl_states *states);
|
||||
int pfctl_clear_states(int dev, const struct pfctl_kill *kill,
|
||||
|
|
|
@ -1529,9 +1529,6 @@ pfctl_show_state(struct pfctl_state *s, void *arg)
|
|||
{
|
||||
struct pfctl_show_state_arg *a = (struct pfctl_show_state_arg *)arg;
|
||||
|
||||
if (a->iface != NULL && strcmp(s->ifname, a->iface))
|
||||
return (0);
|
||||
|
||||
if (a->dotitle) {
|
||||
pfctl_print_title("STATES:");
|
||||
a->dotitle = 0;
|
||||
|
@ -1545,12 +1542,16 @@ int
|
|||
pfctl_show_states(int dev, const char *iface, int opts)
|
||||
{
|
||||
struct pfctl_show_state_arg arg;
|
||||
struct pfctl_state_filter filter = {};
|
||||
|
||||
if (iface != NULL)
|
||||
strncpy(filter.ifname, iface, IFNAMSIZ);
|
||||
|
||||
arg.opts = opts;
|
||||
arg.dotitle = opts & PF_OPT_SHOWALL;
|
||||
arg.iface = iface;
|
||||
|
||||
if (pfctl_get_states_iter(pfctl_show_state, &arg))
|
||||
if (pfctl_get_filtered_states_iter(&filter, pfctl_show_state, &arg))
|
||||
return (-1);
|
||||
|
||||
return (0);
|
||||
|
|
|
@ -52,6 +52,11 @@ struct nl_parsed_state {
|
|||
uint8_t version;
|
||||
uint32_t id;
|
||||
uint32_t creatorid;
|
||||
char ifname[IFNAMSIZ];
|
||||
uint16_t proto;
|
||||
sa_family_t af;
|
||||
struct pf_addr addr;
|
||||
struct pf_addr mask;
|
||||
};
|
||||
|
||||
#define _IN(_field) offsetof(struct genlmsghdr, _field)
|
||||
|
@ -59,6 +64,11 @@ struct nl_parsed_state {
|
|||
static const struct nlattr_parser nla_p_state[] = {
|
||||
{ .type = PF_ST_ID, .off = _OUT(id), .cb = nlattr_get_uint32 },
|
||||
{ .type = PF_ST_CREATORID, .off = _OUT(creatorid), .cb = nlattr_get_uint32 },
|
||||
{ .type = PF_ST_IFNAME, .arg = (const void *)IFNAMSIZ, .off = _OUT(ifname), .cb = nlattr_get_chara },
|
||||
{ .type = PF_ST_AF, .off = _OUT(proto), .cb = nlattr_get_uint8 },
|
||||
{ .type = PF_ST_PROTO, .off = _OUT(proto), .cb = nlattr_get_uint16 },
|
||||
{ .type = PF_ST_FILTER_ADDR, .off = _OUT(addr), .cb = nlattr_get_in6_addr },
|
||||
{ .type = PF_ST_FILTER_MASK, .off = _OUT(mask), .cb = nlattr_get_in6_addr },
|
||||
};
|
||||
static const struct nlfield_parser nlf_p_generic[] = {
|
||||
{ .off_in = _IN(version), .off_out = _OUT(version), .cb = nlf_get_u8 },
|
||||
|
@ -217,11 +227,34 @@ handle_dumpstates(struct nlpcb *nlp, struct nl_parsed_state *attrs,
|
|||
|
||||
PF_HASHROW_LOCK(ih);
|
||||
LIST_FOREACH(s, &ih->states, entry) {
|
||||
if (s->timeout != PFTM_UNLINKED) {
|
||||
error = dump_state(nlp, hdr, s, npt);
|
||||
if (error != 0)
|
||||
break;
|
||||
}
|
||||
sa_family_t af = s->key[PF_SK_WIRE]->af;
|
||||
|
||||
if (s->timeout == PFTM_UNLINKED)
|
||||
continue;
|
||||
|
||||
/* Filter */
|
||||
if (attrs->creatorid != 0 && s->creatorid != attrs->creatorid)
|
||||
continue;
|
||||
if (attrs->ifname[0] != 0 &&
|
||||
strncmp(attrs->ifname, s->kif->pfik_name, IFNAMSIZ) != 0)
|
||||
continue;
|
||||
if (attrs->proto != 0 && s->key[PF_SK_WIRE]->proto != attrs->proto)
|
||||
continue;
|
||||
if (attrs->af != 0 && af != attrs->af)
|
||||
continue;
|
||||
if (pf_match_addr(1, &s->key[PF_SK_WIRE]->addr[0],
|
||||
&attrs->mask, &attrs->addr, af) &&
|
||||
pf_match_addr(1, &s->key[PF_SK_WIRE]->addr[1],
|
||||
&attrs->mask, &attrs->addr, af) &&
|
||||
pf_match_addr(1, &s->key[PF_SK_STACK]->addr[0],
|
||||
&attrs->mask, &attrs->addr, af) &&
|
||||
pf_match_addr(1, &s->key[PF_SK_STACK]->addr[1],
|
||||
&attrs->mask, &attrs->addr, af))
|
||||
continue;
|
||||
|
||||
error = dump_state(nlp, hdr, s, npt);
|
||||
if (error != 0)
|
||||
break;
|
||||
}
|
||||
PF_HASHROW_UNLOCK(ih);
|
||||
}
|
||||
|
|
|
@ -97,6 +97,8 @@ enum pfstate_type_t {
|
|||
PF_ST_SYNC_FLAGS = 26, /* u8 */
|
||||
PF_ST_UPDATES = 27, /* u8 */
|
||||
PF_ST_VERSION = 28, /* u64 */
|
||||
PF_ST_FILTER_ADDR = 29, /* in6_addr */
|
||||
PF_ST_FILTER_MASK = 30, /* in6_addr */
|
||||
};
|
||||
|
||||
enum pf_addr_type_t {
|
||||
|
|
Loading…
Reference in a new issue