diff options
Diffstat (limited to 'lib/libpfctl')
| -rw-r--r-- | lib/libpfctl/libpfctl.c | 438 | ||||
| -rw-r--r-- | lib/libpfctl/libpfctl.h | 109 |
2 files changed, 540 insertions, 7 deletions
diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c index f8c92a5cd319..59783592a370 100644 --- a/lib/libpfctl/libpfctl.c +++ b/lib/libpfctl/libpfctl.c @@ -69,12 +69,15 @@ const char* PFCTL_SYNCOOKIES_MODE_NAMES[] = { static int _pfctl_clear_states(int , const struct pfctl_kill *, unsigned int *, uint64_t); +static void _pfctl_verify_parsers(void); struct pfctl_handle * pfctl_open(const char *pf_device) { struct pfctl_handle *h; + _pfctl_verify_parsers(); + h = calloc(1, sizeof(struct pfctl_handle)); h->fd = open(pf_device, O_RDWR); @@ -389,8 +392,8 @@ static const struct snl_attr_parser ap_getstatus[] = { { .type = PF_GS_FCOUNTERS, .off = _OUT(fcounters), .cb = snl_attr_get_counters }, { .type = PF_GS_SCOUNTERS, .off = _OUT(scounters), .cb = snl_attr_get_counters }, { .type = PF_GS_CHKSUM, .off = _OUT(pf_chksum), .arg_u32 = PF_MD5_DIGEST_LENGTH, .cb = snl_attr_get_bytes }, - { .type = PF_GS_BCOUNTERS, .off = _OUT(bcounters), .arg_u32 = 2 * 2, .cb = snl_attr_get_uint64_array }, { .type = PF_GS_PCOUNTERS, .off = _OUT(pcounters), .arg_u32 = 2 * 2 * 2, .cb = snl_attr_get_uint64_array }, + { .type = PF_GS_BCOUNTERS, .off = _OUT(bcounters), .arg_u32 = 2 * 2, .cb = snl_attr_get_uint64_array }, { .type = PF_GS_NCOUNTERS, .off = _OUT(ncounters), .cb = snl_attr_get_counters }, { .type = PF_GS_FRAGMENTS, .off = _OUT(fragments), .cb = snl_attr_get_uint64 }, }; @@ -1313,6 +1316,11 @@ snl_add_msg_attr_pf_rule(struct snl_writer *nw, uint32_t type, const struct pfct snl_add_msg_attr_ip6(nw, PF_RT_DIVERT_ADDRESS, &r->divert.addr.v6); snl_add_msg_attr_u16(nw, PF_RT_DIVERT_PORT, r->divert.port); + snl_add_msg_attr_u8(nw, PF_RT_STATE_LIMIT, r->statelim.id); + snl_add_msg_attr_u32(nw, PF_RT_STATE_LIMIT_ACTION, r->statelim.limiter_action); + snl_add_msg_attr_u8(nw, PF_RT_SOURCE_LIMIT, r->sourcelim.id); + snl_add_msg_attr_u32(nw, PF_RT_SOURCE_LIMIT_ACTION, r->sourcelim.limiter_action); + snl_end_attr_nested(nw, off); } @@ -1704,6 +1712,10 @@ static struct snl_attr_parser ap_getrule[] = { { .type = PF_RT_TYPE_2, .off = _OUT(r.type), .cb = snl_attr_get_uint16 }, { .type = PF_RT_CODE_2, .off = _OUT(r.code), .cb = snl_attr_get_uint16 }, { .type = PF_RT_EXPTIME, .off = _OUT(r.exptime), .cb = snl_attr_get_time_t }, + { .type = PF_RT_STATE_LIMIT, .off = _OUT(r.statelim.id), .cb = snl_attr_get_uint8 }, + { .type = PF_RT_SOURCE_LIMIT, .off = _OUT(r.sourcelim.id), .cb = snl_attr_get_uint8 }, + { .type = PF_RT_STATE_LIMIT_ACTION, .off = _OUT(r.statelim.limiter_action), .cb = snl_attr_get_uint32 }, + { .type = PF_RT_SOURCE_LIMIT_ACTION, .off = _OUT(r.sourcelim.limiter_action), .cb = snl_attr_get_uint32 }, }; #undef _OUT SNL_DECLARE_PARSER(getrule_parser, struct genlmsghdr, snl_f_p_empty, ap_getrule); @@ -1956,15 +1968,9 @@ static struct snl_attr_parser ap_state[] = { #undef _OUT SNL_DECLARE_PARSER(state_parser, struct genlmsghdr, snl_f_p_empty, ap_state); -static const struct snl_hdr_parser *all_parsers[] = { - &state_parser, &skey_parser, &speer_parser, - &creator_parser, &getrules_parser -}; - int pfctl_get_states_h(struct pfctl_handle *h, struct pfctl_state_filter *filter, pfctl_get_state_fn f, void *arg) { - SNL_VERIFY_PARSERS(all_parsers); int family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); int ret; @@ -3910,3 +3916,421 @@ pfctl_clr_astats(struct pfctl_handle *h, const struct pfr_table *tbl, return (ret); } +static int +_pfctl_test_addrs(struct pfctl_handle *h, const struct pfr_table *tbl, + struct pfr_addr *addrs, int size, int *nmatch, int flags) +{ + struct snl_writer nw; + struct snl_errmsg_data e = {}; + struct nlmsghdr *hdr; + uint32_t seq_id; + struct nl_astats attrs; + 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_TABLE_TEST_ADDRS); + + snl_add_msg_attr_table(&nw, PF_TA_TABLE, tbl); + snl_add_msg_attr_u32(&nw, PF_TA_FLAGS, flags); + for (int i = 0; i < size; i++) + snl_add_msg_attr_pfr_addr(&nw, PF_TA_ADDR, &addrs[i]); + + 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, &table_astats_parser, &attrs)) + continue; + } + + if (nmatch) + *nmatch = attrs.total_count; + + return (e.error); +} + +int +pfctl_test_addrs(struct pfctl_handle *h, const struct pfr_table *tbl, + struct pfr_addr *addrs, int size, int *nmatch, int flags) +{ + int ret; + int off = 0; + int partial_match; + int chunk_size; + + if (nmatch) + *nmatch = 0; + + do { + chunk_size = MIN(size - off, 256); + ret = _pfctl_test_addrs(h, tbl, &addrs[off], chunk_size, + &partial_match, flags); + if (ret != 0) + break; + if (nmatch) + *nmatch += partial_match; + off += chunk_size; + } while (off < size); + + return (ret); +} + +static void +snl_add_msg_attr_limit_rate(struct snl_writer *nw, uint32_t type, + const struct pfctl_limit_rate *rate) +{ + int off; + + off = snl_add_msg_attr_nested(nw, type); + + snl_add_msg_attr_u32(nw, PF_LR_LIMIT, rate->limit); + snl_add_msg_attr_u32(nw, PF_LR_SECONDS, rate->seconds); + + snl_end_attr_nested(nw, off); +} + +#define _OUT(_field) offsetof(struct pfctl_limit_rate, _field) +static const struct snl_attr_parser ap_limit_rate[] = { + { .type = PF_LR_LIMIT, .off = _OUT(limit), .cb = snl_attr_get_uint32 }, + { .type = PF_LR_SECONDS, .off = _OUT(seconds), .cb = snl_attr_get_uint32 }, +}; +SNL_DECLARE_ATTR_PARSER(limit_rate_parser, ap_limit_rate); +#undef _OUT + +#define _OUT(_field) offsetof(struct pfctl_state_lim, _field) +static struct snl_attr_parser ap_statelim[] = { + { .type = PF_SL_NAME, .off = _OUT(name), .arg_u32 = PF_STATELIM_NAME_LEN, .cb = snl_attr_copy_string }, + { .type = PF_SL_ID, .off = _OUT(id), .cb = snl_attr_get_uint32 }, + { .type = PF_SL_LIMIT, .off = _OUT(limit), .cb = snl_attr_get_uint32 }, + { .type = PF_SL_RATE, .off = _OUT(rate), .arg = &limit_rate_parser, .cb = snl_attr_get_nested }, + { .type = PF_SL_DESCR, .off = _OUT(description), .arg_u32 = PF_STATELIM_DESCR_LEN, .cb = snl_attr_copy_string }, + { .type = PF_SL_INUSE, .off = _OUT(inuse), .cb = snl_attr_get_uint32 }, + { .type = PF_SL_ADMITTED, .off = _OUT(admitted), .cb = snl_attr_get_uint64 }, + { .type = PF_SL_HARDLIMITED, .off = _OUT(hardlimited), .cb = snl_attr_get_uint64 }, + { .type = PF_SL_RATELIMITED, .off = _OUT(ratelimited), .cb = snl_attr_get_uint64 }, +}; +#undef _OUT +SNL_DECLARE_PARSER(statelim_parser, struct genlmsghdr, snl_f_p_empty, ap_statelim); + +int +pfctl_state_limiter_nget(struct pfctl_handle *h, struct pfctl_state_lim *lim) +{ + struct snl_writer nw; + 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_STATE_LIMITER_NGET); + + snl_add_msg_attr_u32(&nw, PF_SL_ID, lim->id); + + 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, &statelim_parser, lim)) + continue; + } + + return (e.error); +} + +int +pfctl_state_limiter_add(struct pfctl_handle *h, struct pfctl_state_lim *lim) +{ + struct snl_writer nw; + 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_STATE_LIMITER_ADD); + + snl_add_msg_attr_u32(&nw, PF_SL_ID, lim->id); + snl_add_msg_attr_u32(&nw, PF_SL_TICKET, lim->ticket); + snl_add_msg_attr_string(&nw, PF_SL_NAME, lim->name); + snl_add_msg_attr_u32(&nw, PF_SL_LIMIT, lim->limit); + snl_add_msg_attr_limit_rate(&nw, PF_SL_RATE, &lim->rate); + snl_add_msg_attr_string(&nw, PF_SL_DESCR, lim->description); + + 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, &statelim_parser, lim)) + continue; + } + + return (e.error); +} + +#define _OUT(_field) offsetof(struct pfctl_source_lim, _field) +static struct snl_attr_parser ap_sourcelim[] = { + { .type = PF_SCL_NAME, .off = _OUT(name), .arg_u32 = PF_SOURCELIM_NAME_LEN, .cb = snl_attr_copy_string }, + { .type = PF_SCL_ID, .off = _OUT(id), .cb = snl_attr_get_uint32 }, + { .type = PF_SCL_ENTRIES, .off = _OUT(entries), .cb = snl_attr_get_uint32 }, + { .type = PF_SCL_LIMIT, .off = _OUT(limit), .cb = snl_attr_get_uint32 }, + { .type = PF_SCL_RATE, .off = _OUT(rate), .arg = &limit_rate_parser, .cb = snl_attr_get_nested }, + { .type = PF_SCL_OVERLOAD_TBL_NAME, .off = _OUT(overload_tblname), .arg_u32 = PF_TABLE_NAME_SIZE, .cb = snl_attr_copy_string }, + { .type = PF_SCL_OVERLOAD_HIGH_WM, .off = _OUT(overload_hwm), .cb = snl_attr_get_uint32 }, + { .type = PF_SCL_OVERLOAD_LOW_WM, .off = _OUT(overload_lwm), .cb = snl_attr_get_uint32 }, + { .type = PF_SCL_INET_PREFIX, .off = _OUT(inet_prefix), .cb = snl_attr_get_uint32 }, + { .type = PF_SCL_INET6_PREFIX, .off = _OUT(inet6_prefix), .cb = snl_attr_get_uint32 }, + { .type = PF_SCL_DESCR, .off = _OUT(description), .arg_u32 = PF_SOURCELIM_DESCR_LEN, .cb = snl_attr_copy_string }, + { .type = PF_SCL_NENTRIES, .off = _OUT(nentries), .cb = snl_attr_get_uint32 }, + { .type = PF_SCL_INUSE, .off = _OUT(inuse), .cb = snl_attr_get_uint32 }, + { .type = PF_SCL_ADDR_ALLOCS, .off = _OUT(addrallocs), .cb = snl_attr_get_uint64 }, + { .type = PF_SCL_ADDR_NOMEM, .off = _OUT(addrnomem), .cb = snl_attr_get_uint64 }, + { .type = PF_SCL_ADMITTED, .off = _OUT(admitted), .cb = snl_attr_get_uint64 }, + { .type = PF_SCL_ADDRLIMITED, .off = _OUT(addrlimited), .cb = snl_attr_get_uint64 }, + { .type = PF_SCL_HARDLIMITED, .off = _OUT(hardlimited), .cb = snl_attr_get_uint64 }, + { .type = PF_SCL_RATELIMITED, .off = _OUT(ratelimited), .cb = snl_attr_get_uint64 }, +}; +#undef _OUT +SNL_DECLARE_PARSER(sourcelim_parser, struct genlmsghdr, snl_f_p_empty, ap_sourcelim); + +int +pfctl_source_limiter_add(struct pfctl_handle *h, struct pfctl_source_lim *lim) +{ + struct snl_writer nw; + 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_SOURCE_LIMITER_ADD); + + snl_add_msg_attr_u32(&nw, PF_SCL_TICKET, lim->ticket); + snl_add_msg_attr_string(&nw, PF_SCL_NAME, lim->name); + snl_add_msg_attr_u32(&nw, PF_SCL_ID, lim->id); + snl_add_msg_attr_u32(&nw, PF_SCL_ENTRIES, lim->entries); + snl_add_msg_attr_u32(&nw, PF_SCL_LIMIT, lim->limit); + snl_add_msg_attr_limit_rate(&nw, PF_SCL_RATE, &lim->rate); + snl_add_msg_attr_string(&nw, PF_SCL_OVERLOAD_TBL_NAME, lim->overload_tblname); + snl_add_msg_attr_u32(&nw, PF_SCL_OVERLOAD_HIGH_WM, lim->overload_hwm); + snl_add_msg_attr_u32(&nw, PF_SCL_OVERLOAD_LOW_WM, lim->overload_lwm); + snl_add_msg_attr_u32(&nw, PF_SCL_INET_PREFIX, lim->inet_prefix); + snl_add_msg_attr_u32(&nw, PF_SCL_INET6_PREFIX, lim->inet6_prefix); + snl_add_msg_attr_string(&nw, PF_SCL_DESCR, lim->description); + + 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, &sourcelim_parser, lim)) + continue; + } + + return (e.error); +} + +static int +_pfctl_source_limiter_get(struct pfctl_handle *h, int cmd, struct pfctl_source_lim *lim) +{ + struct snl_writer nw; + 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, cmd); + + snl_add_msg_attr_u32(&nw, PF_SCL_ID, lim->id); + + 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, &sourcelim_parser, lim)) + continue; + } + + return (e.error); +} + +int +pfctl_source_limiter_get(struct pfctl_handle *h, struct pfctl_source_lim *lim) +{ + return (_pfctl_source_limiter_get(h, PFNL_CMD_SOURCE_LIMITER_GET, lim)); +} + +int +pfctl_source_limiter_nget(struct pfctl_handle *h, struct pfctl_source_lim *lim) +{ + return (_pfctl_source_limiter_get(h, PFNL_CMD_SOURCE_LIMITER_NGET, lim)); +} + +#define _OUT(_field) offsetof(struct pfctl_source, _field) +static struct snl_attr_parser ap_source[] = { + { .type = PF_SRC_AF, .off = _OUT(af), .cb = snl_attr_get_uint8 }, + { .type = PF_SRC_RDOMAIN, .off = _OUT(rdomain), .cb = snl_attr_get_uint32 }, + { .type = PF_SRC_ADDR, .off = _OUT(addr), .cb = snl_attr_get_in6_addr }, + { .type = PF_SRC_INUSE, .off = _OUT(inuse), .cb = snl_attr_get_uint32 }, + { .type = PF_SRC_ADMITTED, .off = _OUT(admitted), .cb = snl_attr_get_uint64 }, + { .type = PF_SRC_HARDLIMITED, .off = _OUT(hardlimited), .cb = snl_attr_get_uint64 }, + { .type = PF_SRC_RATELIMITED, .off = _OUT(ratelimited), .cb = snl_attr_get_uint64 }, + { .type = PF_SRC_LIMIT, .off = _OUT(limit), .cb = snl_attr_get_uint32 }, + { .type = PF_SRC_INET_PREFIX, .off = _OUT(inet_prefix), .cb = snl_attr_get_uint32 }, + {. type = PF_SRC_INET6_PREFIX, .off = _OUT(inet6_prefix), .cb = snl_attr_get_uint32 }, +}; +#undef _OUT +SNL_DECLARE_PARSER(source_parser, struct genlmsghdr, snl_f_p_empty, ap_source); + +int +pfctl_source_get(struct pfctl_handle *h, int id, pfctl_get_source_fn fn, void *arg) +{ + struct snl_writer nw; + struct snl_errmsg_data e = {}; + struct nlmsghdr *hdr; + uint32_t seq_id; + int family_id, error; + + 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_SOURCE_NGET); + + snl_add_msg_attr_u32(&nw, PF_SRC_ID, id); + + 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) { + struct pfctl_source src; + + if (! snl_parse_nlmsg(&h->ss, hdr, &source_parser, &src)) + continue; + + error = fn(&src, arg); + if (error != 0) { + e.error = error; + break; + } + } + + return (e.error); +} + +int +pfctl_source_clear(struct pfctl_handle *h, struct pfctl_source_clear *kill) +{ + struct snl_writer nw; + 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_SOURCE_CLEAR); + + snl_add_msg_attr_string(&nw, PF_SC_NAME, kill->name); + snl_add_msg_attr_u32(&nw, PF_SC_ID, kill->id); + snl_add_msg_attr_u32(&nw, PF_SC_RDOMAIN, kill->rdomain); + snl_add_msg_attr_u8(&nw, PF_SC_AF, kill->af); + snl_add_msg_attr_ip6(&nw, PF_SC_ADDR, &kill->addr.v6); + + 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) { + } + + return (e.error); +} + +static const struct snl_hdr_parser *all_parsers[] = { + &begin_addrs_parser, + &clear_states_parser, + &clr_addrs_parser, + &creator_parser, + &get_addr_parser, + &get_addrs_parser, + &get_limit_parser, + &get_timeout_parser, + &getrule_parser, + &getrules_parser, + &getstatus_parser, + &nadd_parser, + &natlook_parser, + &ndel_parser, + &ruleset_parser, + &skey_parser, + &source_parser, + &sourcelim_parser, + &speer_parser, + &srcnode_parser, + &state_parser, + &statelim_parser, + &table_add_addr_parser, + &table_astats_parser, + &table_del_addr_parser, + &table_get_addr_parser, + &table_set_addr_parser, + &tstats_clr_parser, + &tstats_parser, +}; + +static void +_pfctl_verify_parsers(void) +{ + SNL_VERIFY_PARSERS(all_parsers); +} diff --git a/lib/libpfctl/libpfctl.h b/lib/libpfctl/libpfctl.h index b885497ab0e8..1012be53db65 100644 --- a/lib/libpfctl/libpfctl.h +++ b/lib/libpfctl/libpfctl.h @@ -249,6 +249,14 @@ struct pfctl_rule { struct pf_rule_gid gid; char rcv_ifname[IFNAMSIZ]; bool rcvifnot; + struct { + uint8_t id; + int limiter_action; + } statelim; + struct { + uint8_t id; + int limiter_action; + } sourcelim; uint32_t rule_flag; uint8_t action; @@ -589,5 +597,106 @@ int pfctl_get_astats(struct pfctl_handle *h, const struct pfr_table *tbl, struct pfr_astats *addr, int *size, int flags); int pfctl_clr_astats(struct pfctl_handle *h, const struct pfr_table *tbl, struct pfr_addr *addr, int size, int *nzero, int flags); +int pfctl_test_addrs(struct pfctl_handle *h, const struct pfr_table *tbl, + struct pfr_addr *addr, int size, int *nmatch, int flags); + +struct pfctl_limit_rate { + unsigned int limit; + unsigned int seconds; +}; + +struct pfctl_state_lim { + uint32_t ticket; + char name[PF_STATELIM_NAME_LEN]; + uint32_t id; + unsigned int limit; + + struct pfctl_limit_rate rate; + + char description[PF_STATELIM_DESCR_LEN]; + + unsigned int inuse; + uint64_t admitted; + uint64_t hardlimited; + uint64_t ratelimited; +}; + +int pfctl_state_limiter_nget(struct pfctl_handle *h, struct pfctl_state_lim *lim); +int pfctl_state_limiter_add(struct pfctl_handle *h, struct pfctl_state_lim *lim); + +struct pfctl_source_lim { + uint32_t ticket; + + char name[PF_SOURCELIM_NAME_LEN]; + uint32_t id; + + /* limit on the total number of address entries */ + unsigned int entries; + + /* limit on the number of states per address entry */ + unsigned int limit; + + /* rate limit on the creation of states by an address entry */ + struct pfctl_limit_rate rate; + + /* + * when the number of states on an entry exceeds hwm, add + * the address to the specified table. when the number of + * states goes below lwm, remove it from the table. + */ + char overload_tblname[PF_TABLE_NAME_SIZE]; + unsigned int overload_hwm; + unsigned int overload_lwm; + + /* + * mask addresses before they're used for entries. /64s + * everywhere for inet6 makes it easy to use too much memory. + */ + unsigned int inet_prefix; + unsigned int inet6_prefix; + + char description[PF_SOURCELIM_DESCR_LEN]; + + unsigned int nentries; + unsigned int inuse; + + uint64_t addrallocs; + uint64_t addrnomem; + uint64_t admitted; + uint64_t addrlimited; + uint64_t hardlimited; + uint64_t ratelimited; +}; + +int pfctl_source_limiter_get(struct pfctl_handle *h, struct pfctl_source_lim *lim); +int pfctl_source_limiter_nget(struct pfctl_handle *h, struct pfctl_source_lim *lim); +int pfctl_source_limiter_add(struct pfctl_handle *h, struct pfctl_source_lim *lim); + +struct pfctl_source { + sa_family_t af; + unsigned int rdomain; + struct pf_addr addr; + + unsigned int inet_prefix; + unsigned int inet6_prefix; + + unsigned int limit; + unsigned int inuse; + uint64_t admitted; + uint64_t hardlimited; + uint64_t ratelimited; +}; +typedef int (*pfctl_get_source_fn)(struct pfctl_source *, void *); +int pfctl_source_get(struct pfctl_handle *h, int id, + pfctl_get_source_fn fn, void *arg); + +struct pfctl_source_clear { + char name[PF_SOURCELIM_NAME_LEN]; + uint32_t id; + sa_family_t af; + unsigned int rdomain; + struct pf_addr addr; +}; +int pfctl_source_clear(struct pfctl_handle *h, struct pfctl_source_clear *); #endif |
