diff options
| author | Kristof Provost <kp@FreeBSD.org> | 2024-10-11 09:02:27 +0000 |
|---|---|---|
| committer | Kristof Provost <kp@FreeBSD.org> | 2024-10-15 14:29:11 +0000 |
| commit | 9c125336727b48c576bf3598d7d2c52daa5909d7 (patch) | |
| tree | e2c74acba40f37732e8f4e86f337f56238aa9888 /lib | |
| parent | 96f1dfc1be9cf5525152941d06f07c6889e60071 (diff) | |
pf: convert DIOCGETSRCNODES to netlink
Sponsored by: Rubicon Communications, LLC ("Netgate")
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/libpfctl/libpfctl.c | 68 | ||||
| -rw-r--r-- | lib/libpfctl/libpfctl.h | 24 |
2 files changed, 92 insertions, 0 deletions
diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c index e0d93041c551..4634fa99cb19 100644 --- a/lib/libpfctl/libpfctl.c +++ b/lib/libpfctl/libpfctl.c @@ -2998,3 +2998,71 @@ pfctl_get_ruleset(struct pfctl_handle *h, const char *path, uint32_t nr, struct return (e.error); } +#define _OUT(_field) offsetof(struct pfctl_threshold, _field) +static const struct snl_attr_parser ap_pfctl_threshold[] = { + { .type = PF_TH_LIMIT, .off = _OUT(limit), .cb = snl_attr_get_uint32 }, + { .type = PF_TH_SECONDS, .off = _OUT(seconds), .cb = snl_attr_get_uint32 }, + { .type = PF_TH_COUNT, .off = _OUT(count), .cb = snl_attr_get_uint32 }, + { .type = PF_TH_LAST, .off = _OUT(last), .cb = snl_attr_get_uint32 }, +}; +SNL_DECLARE_ATTR_PARSER(pfctl_threshold_parser, ap_pfctl_threshold); +#undef _OUT + +#define _OUT(_field) offsetof(struct pfctl_src_node, _field) +static struct snl_attr_parser ap_srcnode[] = { + { .type = PF_SN_ADDR, .off = _OUT(addr), .cb = snl_attr_get_in6_addr }, + { .type = PF_SN_RADDR, .off = _OUT(raddr), .cb = snl_attr_get_in6_addr }, + { .type = PF_SN_RULE_NR, .off = _OUT(rule), .cb = snl_attr_get_uint32 }, + { .type = PF_SN_BYTES_IN, .off = _OUT(bytes[0]), .cb = snl_attr_get_uint64 }, + { .type = PF_SN_BYTES_OUT, .off = _OUT(bytes[1]), .cb = snl_attr_get_uint64 }, + { .type = PF_SN_PACKETS_IN, .off = _OUT(packets[0]), .cb = snl_attr_get_uint64 }, + { .type = PF_SN_PACKETS_OUT, .off = _OUT(packets[1]), .cb = snl_attr_get_uint64 }, + { .type = PF_SN_STATES, .off = _OUT(states), .cb = snl_attr_get_uint32 }, + { .type = PF_SN_CONNECTIONS, .off = _OUT(conn), .cb = snl_attr_get_uint32 }, + { .type = PF_SN_AF, .off = _OUT(af), .cb = snl_attr_get_uint8 }, + { .type = PF_SN_RULE_TYPE, .off = _OUT(ruletype), .cb = snl_attr_get_uint8 }, + { .type = PF_SN_CREATION, .off = _OUT(creation), .cb = snl_attr_get_uint64 }, + { .type = PF_SN_EXPIRE, .off = _OUT(expire), .cb = snl_attr_get_uint64 }, + { .type = PF_SN_CONNECTION_RATE, .off = _OUT(conn_rate), .arg = &pfctl_threshold_parser, .cb = snl_attr_get_nested }, +}; +static struct snl_field_parser fp_srcnode[] = {}; +#undef _OUT +SNL_DECLARE_PARSER(srcnode_parser, struct genlmsghdr, fp_srcnode, ap_srcnode); + +int +pfctl_get_srcnodes(struct pfctl_handle *h, pfctl_get_srcnode_fn fn, void *arg) +{ + struct snl_writer nw; + struct pfctl_src_node sn; + struct snl_errmsg_data e = {}; + struct nlmsghdr *hdr; + uint32_t seq_id; + int family_id; + int ret; + + 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_GET_SRCNODES); + + 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, &srcnode_parser, &sn)) + continue; + + ret = fn(&sn, arg); + if (ret != 0) + return (ret); + } + + return (e.error); +} diff --git a/lib/libpfctl/libpfctl.h b/lib/libpfctl/libpfctl.h index 4da21774a958..5c3f1376960c 100644 --- a/lib/libpfctl/libpfctl.h +++ b/lib/libpfctl/libpfctl.h @@ -386,6 +386,28 @@ struct pfctl_syncookies { uint32_t halfopen_states; }; +struct pfctl_threshold { + uint32_t limit; + uint32_t seconds; + uint32_t count; + uint32_t last; +}; + +struct pfctl_src_node { + struct pf_addr addr; + struct pf_addr raddr; + int rule; + uint64_t bytes[2]; + uint64_t packets[2]; + uint32_t states; + uint32_t conn; + sa_family_t af; + uint8_t ruletype; + uint64_t creation; + uint64_t expire; + struct pfctl_threshold conn_rate; +}; + #define PF_DEVICE "/dev/pf" struct pfctl_handle; @@ -506,5 +528,7 @@ int pfctl_get_addr(struct pfctl_handle *h, uint32_t ticket, uint32_t r_num, uint8_t r_action, const char *anchor, uint32_t nr, struct pfioc_pooladdr *pa); int pfctl_get_rulesets(struct pfctl_handle *h, const char *path, uint32_t *nr); int pfctl_get_ruleset(struct pfctl_handle *h, const char *path, uint32_t nr, struct pfioc_ruleset *rs); +typedef int (*pfctl_get_srcnode_fn)(struct pfctl_src_node*, void *); +int pfctl_get_srcnodes(struct pfctl_handle *h, pfctl_get_srcnode_fn fn, void *arg); #endif |
