diff options
Diffstat (limited to 'lib/libpfctl/libpfctl.c')
| -rw-r--r-- | lib/libpfctl/libpfctl.c | 507 |
1 files changed, 499 insertions, 8 deletions
diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c index 7e5a07ccd55a..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; @@ -3757,7 +3763,8 @@ struct nl_astats { struct pfr_astats *a; size_t max; size_t count; - uint64_t total_count; + uint32_t total_count; + uint32_t zeroed; }; #define _OUT(_field) offsetof(struct pfr_astats, _field) @@ -3792,6 +3799,7 @@ snl_attr_get_pfr_astats(struct snl_state *ss, struct nlattr *nla, static struct snl_attr_parser ap_table_get_astats[] = { { .type = PF_TAS_ASTATS, .off = 0, .cb = snl_attr_get_pfr_astats }, { .type = PF_TAS_ASTATS_COUNT, .off = _OUT(total_count), .cb = snl_attr_get_uint32 }, + { .type = PF_TAS_ASTATS_ZEROED, .off = _OUT(zeroed), .cb = snl_attr_get_uint32 }, }; #undef _OUT SNL_DECLARE_PARSER(table_astats_parser, struct genlmsghdr, snl_f_p_empty, ap_table_get_astats); @@ -3843,3 +3851,486 @@ pfctl_get_astats(struct pfctl_handle *h, const struct pfr_table *tbl, return (0); } + +static int +_pfctl_clr_astats(struct pfctl_handle *h, const struct pfr_table *tbl, + struct pfr_addr *addrs, int size, int *nzero, 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_CLEAR_ASTATS); + + 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 (nzero) + *nzero = attrs.zeroed; + + return (e.error); +} + +int +pfctl_clr_astats(struct pfctl_handle *h, const struct pfr_table *tbl, + struct pfr_addr *addrs, int size, int *nzero, int flags) +{ + int ret; + int off = 0; + int partial_zeroed; + int chunk_size; + + do { + chunk_size = MIN(size - off, 256); + ret = _pfctl_clr_astats(h, tbl, &addrs[off], chunk_size, + &partial_zeroed, flags); + if (ret != 0) + break; + if (nzero) + *nzero += partial_zeroed; + off += chunk_size; + } while (off < size); + + 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); +} |
