aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristof Provost <kp@FreeBSD.org>2021-05-18 07:24:50 +0000
committerKristof Provost <kp@FreeBSD.org>2021-06-01 14:29:50 +0000
commitae23d302479c5276e4e0a36e6ba1e882dc6e9899 (patch)
treef4f0b44b52c58dfab913a616df3b9340cc101460
parent3d5f931a771ce8937c0572a4fc11bf7a09323125 (diff)
downloadsrc-ae23d302479.tar.gz
src-ae23d302479.zip
pf: Move nvlist conversion functions to pf_nv
Separate the conversion functions (between kernel structs and nvlists) to pf_nv. This reduces the size of pf_ioctl.c, which is already quite large and complex, a good bit. It also keeps all the fairly straightforward conversion code together. MFC after: 1 week Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D30359 (cherry picked from commit 3032c353882aa70a461ef251b8aa6c59a0829ec5)
-rw-r--r--sys/netpfil/pf/pf_ioctl.c866
-rw-r--r--sys/netpfil/pf/pf_nv.c851
-rw-r--r--sys/netpfil/pf/pf_nv.h42
3 files changed, 888 insertions, 871 deletions
diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c
index ea4924e2dd41..af89ddf80daf 100644
--- a/sys/netpfil/pf/pf_ioctl.c
+++ b/sys/netpfil/pf/pf_ioctl.c
@@ -276,14 +276,6 @@ pflog_packet_t *pflog_packet_ptr = NULL;
extern u_long pf_ioctl_maxcount;
-#define ERROUT_FUNCTION(target, x) \
- do { \
- error = (x); \
- SDT_PROBE3(pf, ioctl, function, error, __func__, error, \
- __LINE__); \
- goto target; \
- } while (0)
-
static void
pfattach_vnet(void)
{
@@ -1667,648 +1659,6 @@ pf_krule_to_rule(const struct pf_krule *krule, struct pf_rule *rule)
}
static int
-pf_check_rule_addr(const struct pf_rule_addr *addr)
-{
-
- switch (addr->addr.type) {
- case PF_ADDR_ADDRMASK:
- case PF_ADDR_NOROUTE:
- case PF_ADDR_DYNIFTL:
- case PF_ADDR_TABLE:
- case PF_ADDR_URPFFAILED:
- case PF_ADDR_RANGE:
- break;
- default:
- return (EINVAL);
- }
-
- if (addr->addr.p.dyn != NULL) {
- return (EINVAL);
- }
-
- return (0);
-}
-
-static int
-pf_nvaddr_to_addr(const nvlist_t *nvl, struct pf_addr *paddr)
-{
- return (pf_nvbinary(nvl, "addr", paddr, sizeof(*paddr)));
-}
-
-static nvlist_t *
-pf_addr_to_nvaddr(const struct pf_addr *paddr)
-{
- nvlist_t *nvl;
-
- nvl = nvlist_create(0);
- if (nvl == NULL)
- return (NULL);
-
- nvlist_add_binary(nvl, "addr", paddr, sizeof(*paddr));
-
- return (nvl);
-}
-
-static int
-pf_nvmape_to_mape(const nvlist_t *nvl, struct pf_mape_portset *mape)
-{
- int error = 0;
-
- bzero(mape, sizeof(*mape));
- PFNV_CHK(pf_nvuint8(nvl, "offset", &mape->offset));
- PFNV_CHK(pf_nvuint8(nvl, "psidlen", &mape->psidlen));
- PFNV_CHK(pf_nvuint16(nvl, "psid", &mape->psid));
-
-errout:
- return (error);
-}
-
-static nvlist_t *
-pf_mape_to_nvmape(const struct pf_mape_portset *mape)
-{
- nvlist_t *nvl;
-
- nvl = nvlist_create(0);
- if (nvl == NULL)
- return (NULL);
-
- nvlist_add_number(nvl, "offset", mape->offset);
- nvlist_add_number(nvl, "psidlen", mape->psidlen);
- nvlist_add_number(nvl, "psid", mape->psid);
-
- return (nvl);
-}
-
-static int
-pf_nvpool_to_pool(const nvlist_t *nvl, struct pf_kpool *kpool)
-{
- int error = 0;
-
- bzero(kpool, sizeof(*kpool));
-
- PFNV_CHK(pf_nvbinary(nvl, "key", &kpool->key, sizeof(kpool->key)));
-
- if (nvlist_exists_nvlist(nvl, "counter")) {
- PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "counter"),
- &kpool->counter));
- }
-
- PFNV_CHK(pf_nvint(nvl, "tblidx", &kpool->tblidx));
- PFNV_CHK(pf_nvuint16_array(nvl, "proxy_port", kpool->proxy_port, 2,
- NULL));
- PFNV_CHK(pf_nvuint8(nvl, "opts", &kpool->opts));
-
- if (nvlist_exists_nvlist(nvl, "mape")) {
- PFNV_CHK(pf_nvmape_to_mape(nvlist_get_nvlist(nvl, "mape"),
- &kpool->mape));
- }
-
-errout:
- return (error);
-}
-
-static nvlist_t *
-pf_pool_to_nvpool(const struct pf_kpool *pool)
-{
- nvlist_t *nvl;
- nvlist_t *tmp;
-
- nvl = nvlist_create(0);
- if (nvl == NULL)
- return (NULL);
-
- nvlist_add_binary(nvl, "key", &pool->key, sizeof(pool->key));
- tmp = pf_addr_to_nvaddr(&pool->counter);
- if (tmp == NULL)
- goto error;
- nvlist_add_nvlist(nvl, "counter", tmp);
- nvlist_destroy(tmp);
-
- nvlist_add_number(nvl, "tblidx", pool->tblidx);
- pf_uint16_array_nv(nvl, "proxy_port", pool->proxy_port, 2);
- nvlist_add_number(nvl, "opts", pool->opts);
-
- tmp = pf_mape_to_nvmape(&pool->mape);
- if (tmp == NULL)
- goto error;
- nvlist_add_nvlist(nvl, "mape", tmp);
- nvlist_destroy(tmp);
-
- return (nvl);
-
-error:
- nvlist_destroy(nvl);
- return (NULL);
-}
-
-static int
-pf_nvaddr_wrap_to_addr_wrap(const nvlist_t *nvl, struct pf_addr_wrap *addr)
-{
- int error = 0;
-
- bzero(addr, sizeof(*addr));
-
- PFNV_CHK(pf_nvuint8(nvl, "type", &addr->type));
- PFNV_CHK(pf_nvuint8(nvl, "iflags", &addr->iflags));
- if (addr->type == PF_ADDR_DYNIFTL)
- PFNV_CHK(pf_nvstring(nvl, "ifname", addr->v.ifname,
- sizeof(addr->v.ifname)));
- if (addr->type == PF_ADDR_TABLE)
- PFNV_CHK(pf_nvstring(nvl, "tblname", addr->v.tblname,
- sizeof(addr->v.tblname)));
-
- if (! nvlist_exists_nvlist(nvl, "addr"))
- return (EINVAL);
- PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "addr"),
- &addr->v.a.addr));
-
- if (! nvlist_exists_nvlist(nvl, "mask"))
- return (EINVAL);
- PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "mask"),
- &addr->v.a.mask));
-
- switch (addr->type) {
- case PF_ADDR_DYNIFTL:
- case PF_ADDR_TABLE:
- case PF_ADDR_RANGE:
- case PF_ADDR_ADDRMASK:
- case PF_ADDR_NOROUTE:
- case PF_ADDR_URPFFAILED:
- break;
- default:
- return (EINVAL);
- }
-
-errout:
- return (error);
-}
-
-static nvlist_t *
-pf_addr_wrap_to_nvaddr_wrap(const struct pf_addr_wrap *addr)
-{
- nvlist_t *nvl;
- nvlist_t *tmp;
-
- nvl = nvlist_create(0);
- if (nvl == NULL)
- return (NULL);
-
- nvlist_add_number(nvl, "type", addr->type);
- nvlist_add_number(nvl, "iflags", addr->iflags);
- if (addr->type == PF_ADDR_DYNIFTL)
- nvlist_add_string(nvl, "ifname", addr->v.ifname);
- if (addr->type == PF_ADDR_TABLE)
- nvlist_add_string(nvl, "tblname", addr->v.tblname);
-
- tmp = pf_addr_to_nvaddr(&addr->v.a.addr);
- if (tmp == NULL)
- goto error;
- nvlist_add_nvlist(nvl, "addr", tmp);
- nvlist_destroy(tmp);
- tmp = pf_addr_to_nvaddr(&addr->v.a.mask);
- if (tmp == NULL)
- goto error;
- nvlist_add_nvlist(nvl, "mask", tmp);
- nvlist_destroy(tmp);
-
- return (nvl);
-
-error:
- nvlist_destroy(nvl);
- return (NULL);
-}
-
-static int
-pf_validate_op(uint8_t op)
-{
- switch (op) {
- case PF_OP_NONE:
- case PF_OP_IRG:
- case PF_OP_EQ:
- case PF_OP_NE:
- case PF_OP_LT:
- case PF_OP_LE:
- case PF_OP_GT:
- case PF_OP_GE:
- case PF_OP_XRG:
- case PF_OP_RRG:
- break;
- default:
- return (EINVAL);
- }
-
- return (0);
-}
-
-static int
-pf_nvrule_addr_to_rule_addr(const nvlist_t *nvl, struct pf_rule_addr *addr)
-{
- int error = 0;
-
- if (! nvlist_exists_nvlist(nvl, "addr"))
- return (EINVAL);
-
- PFNV_CHK(pf_nvaddr_wrap_to_addr_wrap(nvlist_get_nvlist(nvl, "addr"),
- &addr->addr));
- PFNV_CHK(pf_nvuint16_array(nvl, "port", addr->port, 2, NULL));
- PFNV_CHK(pf_nvuint8(nvl, "neg", &addr->neg));
- PFNV_CHK(pf_nvuint8(nvl, "port_op", &addr->port_op));
-
- PFNV_CHK(pf_validate_op(addr->port_op));
-
-errout:
- return (error);
-}
-
-static nvlist_t *
-pf_rule_addr_to_nvrule_addr(const struct pf_rule_addr *addr)
-{
- nvlist_t *nvl;
- nvlist_t *tmp;
-
- nvl = nvlist_create(0);
- if (nvl == NULL)
- return (NULL);
-
- tmp = pf_addr_wrap_to_nvaddr_wrap(&addr->addr);
- if (tmp == NULL)
- goto error;
- nvlist_add_nvlist(nvl, "addr", tmp);
- nvlist_destroy(tmp);
- pf_uint16_array_nv(nvl, "port", addr->port, 2);
- nvlist_add_number(nvl, "neg", addr->neg);
- nvlist_add_number(nvl, "port_op", addr->port_op);
-
- return (nvl);
-
-error:
- nvlist_destroy(nvl);
- return (NULL);
-}
-
-static int
-pf_nvrule_uid_to_rule_uid(const nvlist_t *nvl, struct pf_rule_uid *uid)
-{
- int error = 0;
-
- bzero(uid, sizeof(*uid));
-
- PFNV_CHK(pf_nvuint32_array(nvl, "uid", uid->uid, 2, NULL));
- PFNV_CHK(pf_nvuint8(nvl, "op", &uid->op));
-
- PFNV_CHK(pf_validate_op(uid->op));
-
-errout:
- return (error);
-}
-
-static nvlist_t *
-pf_rule_uid_to_nvrule_uid(const struct pf_rule_uid *uid)
-{
- nvlist_t *nvl;
-
- nvl = nvlist_create(0);
- if (nvl == NULL)
- return (NULL);
-
- pf_uint32_array_nv(nvl, "uid", uid->uid, 2);
- nvlist_add_number(nvl, "op", uid->op);
-
- return (nvl);
-}
-
-static int
-pf_nvrule_gid_to_rule_gid(const nvlist_t *nvl, struct pf_rule_gid *gid)
-{
- /* Cheat a little. These stucts are the same, other than the name of
- * the first field. */
- return (pf_nvrule_uid_to_rule_uid(nvl, (struct pf_rule_uid *)gid));
-}
-
-static int
-pf_nvrule_to_krule(const nvlist_t *nvl, struct pf_krule **prule)
-{
- struct pf_krule *rule;
- int error = 0;
-
-#define ERROUT(x) ERROUT_FUNCTION(errout, x)
-
- rule = malloc(sizeof(*rule), M_PFRULE, M_WAITOK | M_ZERO);
-
- PFNV_CHK(pf_nvuint32(nvl, "nr", &rule->nr));
-
- if (! nvlist_exists_nvlist(nvl, "src"))
- ERROUT(EINVAL);
-
- error = pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "src"),
- &rule->src);
- if (error != 0)
- ERROUT(error);
-
- if (! nvlist_exists_nvlist(nvl, "dst"))
- ERROUT(EINVAL);
-
- PFNV_CHK(pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "dst"),
- &rule->dst));
-
- if (nvlist_exists_string(nvl, "label")) {
- PFNV_CHK(pf_nvstring(nvl, "label", rule->label[0],
- sizeof(rule->label[0])));
- } else if (nvlist_exists_string_array(nvl, "labels")) {
- const char *const *strs;
- size_t items;
- int ret;
-
- strs = nvlist_get_string_array(nvl, "labels", &items);
- if (items > PF_RULE_MAX_LABEL_COUNT)
- ERROUT(E2BIG);
-
- for (size_t i = 0; i < items; i++) {
- ret = strlcpy(rule->label[i], strs[i],
- sizeof(rule->label[0]));
- if (ret >= sizeof(rule->label[0]))
- ERROUT(E2BIG);
- }
- }
-
- PFNV_CHK(pf_nvstring(nvl, "ifname", rule->ifname,
- sizeof(rule->ifname)));
- PFNV_CHK(pf_nvstring(nvl, "qname", rule->qname, sizeof(rule->qname)));
- PFNV_CHK(pf_nvstring(nvl, "pqname", rule->pqname,
- sizeof(rule->pqname)));
- PFNV_CHK(pf_nvstring(nvl, "tagname", rule->tagname,
- sizeof(rule->tagname)));
- PFNV_CHK(pf_nvstring(nvl, "match_tagname", rule->match_tagname,
- sizeof(rule->match_tagname)));
- PFNV_CHK(pf_nvstring(nvl, "overload_tblname", rule->overload_tblname,
- sizeof(rule->overload_tblname)));
-
- if (! nvlist_exists_nvlist(nvl, "rpool"))
- ERROUT(EINVAL);
- PFNV_CHK(pf_nvpool_to_pool(nvlist_get_nvlist(nvl, "rpool"),
- &rule->rpool));
-
- PFNV_CHK(pf_nvuint32(nvl, "os_fingerprint", &rule->os_fingerprint));
-
- PFNV_CHK(pf_nvint(nvl, "rtableid", &rule->rtableid));
- PFNV_CHK(pf_nvuint32_array(nvl, "timeout", rule->timeout, PFTM_MAX, NULL));
- PFNV_CHK(pf_nvuint32(nvl, "max_states", &rule->max_states));
- PFNV_CHK(pf_nvuint32(nvl, "max_src_nodes", &rule->max_src_nodes));
- PFNV_CHK(pf_nvuint32(nvl, "max_src_states", &rule->max_src_states));
- PFNV_CHK(pf_nvuint32(nvl, "max_src_conn", &rule->max_src_conn));
- PFNV_CHK(pf_nvuint32(nvl, "max_src_conn_rate.limit",
- &rule->max_src_conn_rate.limit));
- PFNV_CHK(pf_nvuint32(nvl, "max_src_conn_rate.seconds",
- &rule->max_src_conn_rate.seconds));
- PFNV_CHK(pf_nvuint32(nvl, "prob", &rule->prob));
- PFNV_CHK(pf_nvuint32(nvl, "cuid", &rule->cuid));
- PFNV_CHK(pf_nvuint32(nvl, "cpid", &rule->cpid));
-
- PFNV_CHK(pf_nvuint16(nvl, "return_icmp", &rule->return_icmp));
- PFNV_CHK(pf_nvuint16(nvl, "return_icmp6", &rule->return_icmp6));
-
- PFNV_CHK(pf_nvuint16(nvl, "max_mss", &rule->max_mss));
- PFNV_CHK(pf_nvuint16(nvl, "scrub_flags", &rule->scrub_flags));
-
- if (! nvlist_exists_nvlist(nvl, "uid"))
- ERROUT(EINVAL);
- PFNV_CHK(pf_nvrule_uid_to_rule_uid(nvlist_get_nvlist(nvl, "uid"),
- &rule->uid));
-
- if (! nvlist_exists_nvlist(nvl, "gid"))
- ERROUT(EINVAL);
- PFNV_CHK(pf_nvrule_gid_to_rule_gid(nvlist_get_nvlist(nvl, "gid"),
- &rule->gid));
-
- PFNV_CHK(pf_nvuint32(nvl, "rule_flag", &rule->rule_flag));
- PFNV_CHK(pf_nvuint8(nvl, "action", &rule->action));
- PFNV_CHK(pf_nvuint8(nvl, "direction", &rule->direction));
- PFNV_CHK(pf_nvuint8(nvl, "log", &rule->log));
- PFNV_CHK(pf_nvuint8(nvl, "logif", &rule->logif));
- PFNV_CHK(pf_nvuint8(nvl, "quick", &rule->quick));
- PFNV_CHK(pf_nvuint8(nvl, "ifnot", &rule->ifnot));
- PFNV_CHK(pf_nvuint8(nvl, "match_tag_not", &rule->match_tag_not));
- PFNV_CHK(pf_nvuint8(nvl, "natpass", &rule->natpass));
-
- PFNV_CHK(pf_nvuint8(nvl, "keep_state", &rule->keep_state));
- PFNV_CHK(pf_nvuint8(nvl, "af", &rule->af));
- PFNV_CHK(pf_nvuint8(nvl, "proto", &rule->proto));
- PFNV_CHK(pf_nvuint8(nvl, "type", &rule->type));
- PFNV_CHK(pf_nvuint8(nvl, "code", &rule->code));
- PFNV_CHK(pf_nvuint8(nvl, "flags", &rule->flags));
- PFNV_CHK(pf_nvuint8(nvl, "flagset", &rule->flagset));
- PFNV_CHK(pf_nvuint8(nvl, "min_ttl", &rule->min_ttl));
- PFNV_CHK(pf_nvuint8(nvl, "allow_opts", &rule->allow_opts));
- PFNV_CHK(pf_nvuint8(nvl, "rt", &rule->rt));
- PFNV_CHK(pf_nvuint8(nvl, "return_ttl", &rule->return_ttl));
- PFNV_CHK(pf_nvuint8(nvl, "tos", &rule->tos));
- PFNV_CHK(pf_nvuint8(nvl, "set_tos", &rule->set_tos));
- PFNV_CHK(pf_nvuint8(nvl, "anchor_relative", &rule->anchor_relative));
- PFNV_CHK(pf_nvuint8(nvl, "anchor_wildcard", &rule->anchor_wildcard));
-
- PFNV_CHK(pf_nvuint8(nvl, "flush", &rule->flush));
- PFNV_CHK(pf_nvuint8(nvl, "prio", &rule->prio));
-
- PFNV_CHK(pf_nvuint8_array(nvl, "set_prio", &rule->prio, 2, NULL));
-
- if (nvlist_exists_nvlist(nvl, "divert")) {
- const nvlist_t *nvldivert = nvlist_get_nvlist(nvl, "divert");
-
- if (! nvlist_exists_nvlist(nvldivert, "addr"))
- ERROUT(EINVAL);
- PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvldivert, "addr"),
- &rule->divert.addr));
- PFNV_CHK(pf_nvuint16(nvldivert, "port", &rule->divert.port));
- }
-
- /* Validation */
-#ifndef INET
- if (rule->af == AF_INET)
- ERROUT(EAFNOSUPPORT);
-#endif /* INET */
-#ifndef INET6
- if (rule->af == AF_INET6)
- ERROUT(EAFNOSUPPORT);
-#endif /* INET6 */
-
- PFNV_CHK(pf_check_rule_addr(&rule->src));
- PFNV_CHK(pf_check_rule_addr(&rule->dst));
-
- *prule = rule;
-
- return (0);
-
-#undef ERROUT
-errout:
- pf_krule_free(rule);
- *prule = NULL;
-
- return (error);
-}
-
-static nvlist_t *
-pf_divert_to_nvdivert(const struct pf_krule *rule)
-{
- nvlist_t *nvl;
- nvlist_t *tmp;
-
- nvl = nvlist_create(0);
- if (nvl == NULL)
- return (NULL);
-
- tmp = pf_addr_to_nvaddr(&rule->divert.addr);
- if (tmp == NULL)
- goto error;
- nvlist_add_nvlist(nvl, "addr", tmp);
- nvlist_destroy(tmp);
- nvlist_add_number(nvl, "port", rule->divert.port);
-
- return (nvl);
-
-error:
- nvlist_destroy(nvl);
- return (NULL);
-}
-
-static nvlist_t *
-pf_krule_to_nvrule(const struct pf_krule *rule)
-{
- nvlist_t *nvl, *tmp;
-
- nvl = nvlist_create(0);
- if (nvl == NULL)
- return (nvl);
-
- nvlist_add_number(nvl, "nr", rule->nr);
- tmp = pf_rule_addr_to_nvrule_addr(&rule->src);
- if (tmp == NULL)
- goto error;
- nvlist_add_nvlist(nvl, "src", tmp);
- nvlist_destroy(tmp);
- tmp = pf_rule_addr_to_nvrule_addr(&rule->dst);
- if (tmp == NULL)
- goto error;
- nvlist_add_nvlist(nvl, "dst", tmp);
- nvlist_destroy(tmp);
-
- for (int i = 0; i < PF_SKIP_COUNT; i++) {
- nvlist_append_number_array(nvl, "skip",
- rule->skip[i].ptr ? rule->skip[i].ptr->nr : -1);
- }
-
- for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++) {
- nvlist_append_string_array(nvl, "labels", rule->label[i]);
- }
- nvlist_add_string(nvl, "label", rule->label[0]);
- nvlist_add_string(nvl, "ifname", rule->ifname);
- nvlist_add_string(nvl, "qname", rule->qname);
- nvlist_add_string(nvl, "pqname", rule->pqname);
- nvlist_add_string(nvl, "tagname", rule->tagname);
- nvlist_add_string(nvl, "match_tagname", rule->match_tagname);
- nvlist_add_string(nvl, "overload_tblname", rule->overload_tblname);
-
- tmp = pf_pool_to_nvpool(&rule->rpool);
- if (tmp == NULL)
- goto error;
- nvlist_add_nvlist(nvl, "rpool", tmp);
- nvlist_destroy(tmp);
-
- nvlist_add_number(nvl, "evaluations",
- counter_u64_fetch(rule->evaluations));
- for (int i = 0; i < 2; i++) {
- nvlist_append_number_array(nvl, "packets",
- counter_u64_fetch(rule->packets[i]));
- nvlist_append_number_array(nvl, "bytes",
- counter_u64_fetch(rule->bytes[i]));
- }
-
- nvlist_add_number(nvl, "os_fingerprint", rule->os_fingerprint);
-
- nvlist_add_number(nvl, "rtableid", rule->rtableid);
- pf_uint32_array_nv(nvl, "timeout", rule->timeout, PFTM_MAX);
- nvlist_add_number(nvl, "max_states", rule->max_states);
- nvlist_add_number(nvl, "max_src_nodes", rule->max_src_nodes);
- nvlist_add_number(nvl, "max_src_states", rule->max_src_states);
- nvlist_add_number(nvl, "max_src_conn", rule->max_src_conn);
- nvlist_add_number(nvl, "max_src_conn_rate.limit",
- rule->max_src_conn_rate.limit);
- nvlist_add_number(nvl, "max_src_conn_rate.seconds",
- rule->max_src_conn_rate.seconds);
- nvlist_add_number(nvl, "qid", rule->qid);
- nvlist_add_number(nvl, "pqid", rule->pqid);
- nvlist_add_number(nvl, "prob", rule->prob);
- nvlist_add_number(nvl, "cuid", rule->cuid);
- nvlist_add_number(nvl, "cpid", rule->cpid);
-
- nvlist_add_number(nvl, "states_cur",
- counter_u64_fetch(rule->states_cur));
- nvlist_add_number(nvl, "states_tot",
- counter_u64_fetch(rule->states_tot));
- nvlist_add_number(nvl, "src_nodes",
- counter_u64_fetch(rule->src_nodes));
-
- nvlist_add_number(nvl, "return_icmp", rule->return_icmp);
- nvlist_add_number(nvl, "return_icmp6", rule->return_icmp6);
-
- nvlist_add_number(nvl, "max_mss", rule->max_mss);
- nvlist_add_number(nvl, "scrub_flags", rule->scrub_flags);
-
- tmp = pf_rule_uid_to_nvrule_uid(&rule->uid);
- if (tmp == NULL)
- goto error;
- nvlist_add_nvlist(nvl, "uid", tmp);
- nvlist_destroy(tmp);
- tmp = pf_rule_uid_to_nvrule_uid((const struct pf_rule_uid *)&rule->gid);
- if (tmp == NULL)
- goto error;
- nvlist_add_nvlist(nvl, "gid", tmp);
- nvlist_destroy(tmp);
-
- nvlist_add_number(nvl, "rule_flag", rule->rule_flag);
- nvlist_add_number(nvl, "action", rule->action);
- nvlist_add_number(nvl, "direction", rule->direction);
- nvlist_add_number(nvl, "log", rule->log);
- nvlist_add_number(nvl, "logif", rule->logif);
- nvlist_add_number(nvl, "quick", rule->quick);
- nvlist_add_number(nvl, "ifnot", rule->ifnot);
- nvlist_add_number(nvl, "match_tag_not", rule->match_tag_not);
- nvlist_add_number(nvl, "natpass", rule->natpass);
-
- nvlist_add_number(nvl, "keep_state", rule->keep_state);
- nvlist_add_number(nvl, "af", rule->af);
- nvlist_add_number(nvl, "proto", rule->proto);
- nvlist_add_number(nvl, "type", rule->type);
- nvlist_add_number(nvl, "code", rule->code);
- nvlist_add_number(nvl, "flags", rule->flags);
- nvlist_add_number(nvl, "flagset", rule->flagset);
- nvlist_add_number(nvl, "min_ttl", rule->min_ttl);
- nvlist_add_number(nvl, "allow_opts", rule->allow_opts);
- nvlist_add_number(nvl, "rt", rule->rt);
- nvlist_add_number(nvl, "return_ttl", rule->return_ttl);
- nvlist_add_number(nvl, "tos", rule->tos);
- nvlist_add_number(nvl, "set_tos", rule->set_tos);
- nvlist_add_number(nvl, "anchor_relative", rule->anchor_relative);
- nvlist_add_number(nvl, "anchor_wildcard", rule->anchor_wildcard);
-
- nvlist_add_number(nvl, "flush", rule->flush);
- nvlist_add_number(nvl, "prio", rule->prio);
-
- pf_uint8_array_nv(nvl, "set_prio", &rule->prio, 2);
-
- tmp = pf_divert_to_nvdivert(rule);
- if (tmp == NULL)
- goto error;
- nvlist_add_nvlist(nvl, "divert", tmp);
- nvlist_destroy(tmp);
-
- return (nvl);
-
-error:
- nvlist_destroy(nvl);
- return (NULL);
-}
-
-static int
pf_rule_to_krule(const struct pf_rule *rule, struct pf_krule *krule)
{
int ret;
@@ -2572,219 +1922,6 @@ pf_state_kill_to_kstate_kill(const struct pfioc_state_kill *psk,
}
static int
-pf_nvstate_cmp_to_state_cmp(const nvlist_t *nvl, struct pf_state_cmp *cmp)
-{
- int error = 0;
-
- bzero(cmp, sizeof(*cmp));
-
- PFNV_CHK(pf_nvuint64(nvl, "id", &cmp->id));
- PFNV_CHK(pf_nvuint32(nvl, "creatorid", &cmp->creatorid));
- PFNV_CHK(pf_nvuint8(nvl, "direction", &cmp->direction));
-
-errout:
- return (error);
-}
-
-static int
-pf_nvstate_kill_to_kstate_kill(const nvlist_t *nvl,
- struct pf_kstate_kill *kill)
-{
- int error = 0;
-
- bzero(kill, sizeof(*kill));
-
- if (! nvlist_exists_nvlist(nvl, "cmp"))
- return (EINVAL);
-
- PFNV_CHK(pf_nvstate_cmp_to_state_cmp(nvlist_get_nvlist(nvl, "cmp"),
- &kill->psk_pfcmp));
- PFNV_CHK(pf_nvuint8(nvl, "af", &kill->psk_af));
- PFNV_CHK(pf_nvint(nvl, "proto", &kill->psk_proto));
-
- if (! nvlist_exists_nvlist(nvl, "src"))
- return (EINVAL);
- PFNV_CHK(pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "src"),
- &kill->psk_src));
- if (! nvlist_exists_nvlist(nvl, "dst"))
- return (EINVAL);
- PFNV_CHK(pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "dst"),
- &kill->psk_dst));
- if (nvlist_exists_nvlist(nvl, "rt_addr")) {
- PFNV_CHK(pf_nvrule_addr_to_rule_addr(
- nvlist_get_nvlist(nvl, "rt_addr"), &kill->psk_rt_addr));
- }
-
- PFNV_CHK(pf_nvstring(nvl, "ifname", kill->psk_ifname,
- sizeof(kill->psk_ifname)));
- PFNV_CHK(pf_nvstring(nvl, "label", kill->psk_label,
- sizeof(kill->psk_label)));
- if (nvlist_exists_bool(nvl, "kill_match"))
- kill->psk_kill_match = nvlist_get_bool(nvl, "kill_match");
-
-errout:
- return (error);
-}
-
-static nvlist_t *
-pf_state_key_to_nvstate_key(const struct pf_state_key *key)
-{
- nvlist_t *nvl, *tmp;
-
- nvl = nvlist_create(0);
- if (nvl == NULL)
- return (NULL);
-
- for (int i = 0; i < 2; i++) {
- tmp = pf_addr_to_nvaddr(&key->addr[i]);
- if (tmp == NULL)
- goto errout;
- nvlist_append_nvlist_array(nvl, "addr", tmp);
- nvlist_append_number_array(nvl, "port", key->port[i]);
- }
- nvlist_add_number(nvl, "af", key->af);
- nvlist_add_number(nvl, "proto", key->proto);
-
- return (nvl);
-
-errout:
- nvlist_destroy(nvl);
- return (NULL);
-}
-
-static nvlist_t *
-pf_state_scrub_to_nvstate_scrub(const struct pf_state_scrub *scrub)
-{
- nvlist_t *nvl;
-
- nvl = nvlist_create(0);
- if (nvl == NULL)
- return (NULL);
-
- nvlist_add_bool(nvl, "timestamp", scrub->pfss_flags & PFSS_TIMESTAMP);
- nvlist_add_number(nvl, "ttl", scrub->pfss_ttl);
- nvlist_add_number(nvl, "ts_mod", scrub->pfss_ts_mod);
-
- return (nvl);
-}
-
-static nvlist_t *
-pf_state_peer_to_nvstate_peer(const struct pf_state_peer *peer)
-{
- nvlist_t *nvl, *tmp;
-
- nvl = nvlist_create(0);
- if (nvl == NULL)
- return (NULL);
-
- if (peer->scrub) {
- tmp = pf_state_scrub_to_nvstate_scrub(peer->scrub);
- if (tmp == NULL)
- goto errout;
- nvlist_add_nvlist(nvl, "scrub", tmp);
- nvlist_destroy(tmp);
- }
-
- nvlist_add_number(nvl, "seqlo", peer->seqlo);
- nvlist_add_number(nvl, "seqhi", peer->seqhi);
- nvlist_add_number(nvl, "seqdiff", peer->seqdiff);
- nvlist_add_number(nvl, "max_win", peer->max_win);
- nvlist_add_number(nvl, "mss", peer->mss);
- nvlist_add_number(nvl, "state", peer->state);
- nvlist_add_number(nvl, "wscale", peer->wscale);
-
- return (nvl);
-
-errout:
- nvlist_destroy(nvl);
- return (NULL);
-}
-
-
-static nvlist_t *
-pf_state_to_nvstate(const struct pf_state *s)
-{
- nvlist_t *nvl, *tmp;
- uint32_t expire, flags = 0;
-
- nvl = nvlist_create(0);
- if (nvl == NULL)
- return (NULL);
-
- nvlist_add_number(nvl, "id", s->id);
- nvlist_add_string(nvl, "ifname", s->kif->pfik_name);
- nvlist_add_string(nvl, "orig_ifname", s->orig_kif->pfik_name);
-
- tmp = pf_state_key_to_nvstate_key(s->key[PF_SK_STACK]);
- if (tmp == NULL)
- goto errout;
- nvlist_add_nvlist(nvl, "stack_key", tmp);
- nvlist_destroy(tmp);
-
- tmp = pf_state_key_to_nvstate_key(s->key[PF_SK_WIRE]);
- if (tmp == NULL)
- goto errout;
- nvlist_add_nvlist(nvl, "wire_key", tmp);
- nvlist_destroy(tmp);
-
- tmp = pf_state_peer_to_nvstate_peer(&s->src);
- if (tmp == NULL)
- goto errout;
- nvlist_add_nvlist(nvl, "src", tmp);
- nvlist_destroy(tmp);
-
- tmp = pf_state_peer_to_nvstate_peer(&s->dst);
- if (tmp == NULL)
- goto errout;
- nvlist_add_nvlist(nvl, "dst", tmp);
- nvlist_destroy(tmp);
-
- tmp = pf_addr_to_nvaddr(&s->rt_addr);
- if (tmp == NULL)
- goto errout;
- nvlist_add_nvlist(nvl, "rt_addr", tmp);
- nvlist_destroy(tmp);
-
- nvlist_add_number(nvl, "rule", s->rule.ptr ? s->rule.ptr->nr : -1);
- nvlist_add_number(nvl, "anchor",
- s->anchor.ptr ? s->anchor.ptr->nr : -1);
- nvlist_add_number(nvl, "nat_rule",
- s->nat_rule.ptr ? s->nat_rule.ptr->nr : -1);
- nvlist_add_number(nvl, "creation", s->creation);
-
- expire = pf_state_expires(s);
- if (expire <= time_uptime)
- expire = 0;
- else
- expire = expire - time_uptime;
- nvlist_add_number(nvl, "expire", expire);
-
- for (int i = 0; i < 2; i++) {
- nvlist_append_number_array(nvl, "packets",
- counter_u64_fetch(s->packets[i]));
- nvlist_append_number_array(nvl, "bytes",
- counter_u64_fetch(s->bytes[i]));
- }
-
- nvlist_add_number(nvl, "creatorid", s->creatorid);
- nvlist_add_number(nvl, "direction", s->direction);
- nvlist_add_number(nvl, "log", s->log);
- nvlist_add_number(nvl, "state_flags", s->state_flags);
- nvlist_add_number(nvl, "timeout", s->timeout);
- if (s->src_node)
- flags |= PFSYNC_FLAG_SRCNODE;
- if (s->nat_src_node)
- flags |= PFSYNC_FLAG_NATSRCNODE;
- nvlist_add_number(nvl, "sync_flags", flags);
-
- return (nvl);
-
-errout:
- nvlist_destroy(nvl);
- return (NULL);
-}
-
-static int
pf_ioctl_addrule(struct pf_krule *rule, uint32_t ticket,
uint32_t pool_ticket, const char *anchor, const char *anchor_call,
struct thread *td)
@@ -3139,8 +2276,9 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
if (! nvlist_exists_nvlist(nvl, "rule"))
ERROUT(EINVAL);
+ rule = malloc(sizeof(*rule), M_PFRULE, M_WAITOK | M_ZERO);
error = pf_nvrule_to_krule(nvlist_get_nvlist(nvl, "rule"),
- &rule);
+ rule);
if (error)
ERROUT(error);
diff --git a/sys/netpfil/pf/pf_nv.c b/sys/netpfil/pf/pf_nv.c
index 1fdb52e5fad0..863259dbf9aa 100644
--- a/sys/netpfil/pf/pf_nv.c
+++ b/sys/netpfil/pf/pf_nv.c
@@ -28,9 +28,13 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_inet.h"
+#include "opt_inet6.h"
+
#include <sys/param.h>
#include <sys/errno.h>
#include <sys/limits.h>
+#include <sys/queue.h>
#include <sys/systm.h>
#include <netpfil/pf/pf_nv.h>
@@ -137,3 +141,850 @@ pf_nvstring(const nvlist_t *nvl, const char *name, char *str, size_t maxlen)
return (0);
}
+
+static int
+pf_nvaddr_to_addr(const nvlist_t *nvl, struct pf_addr *paddr)
+{
+ return (pf_nvbinary(nvl, "addr", paddr, sizeof(*paddr)));
+}
+
+static nvlist_t *
+pf_addr_to_nvaddr(const struct pf_addr *paddr)
+{
+ nvlist_t *nvl;
+
+ nvl = nvlist_create(0);
+ if (nvl == NULL)
+ return (NULL);
+
+ nvlist_add_binary(nvl, "addr", paddr, sizeof(*paddr));
+
+ return (nvl);
+}
+
+static int
+pf_nvmape_to_mape(const nvlist_t *nvl, struct pf_mape_portset *mape)
+{
+ int error = 0;
+
+ bzero(mape, sizeof(*mape));
+ PFNV_CHK(pf_nvuint8(nvl, "offset", &mape->offset));
+ PFNV_CHK(pf_nvuint8(nvl, "psidlen", &mape->psidlen));
+ PFNV_CHK(pf_nvuint16(nvl, "psid", &mape->psid));
+
+errout:
+ return (error);
+}
+
+static nvlist_t *
+pf_mape_to_nvmape(const struct pf_mape_portset *mape)
+{
+ nvlist_t *nvl;
+
+ nvl = nvlist_create(0);
+ if (nvl == NULL)
+ return (NULL);
+
+ nvlist_add_number(nvl, "offset", mape->offset);
+ nvlist_add_number(nvl, "psidlen", mape->psidlen);
+ nvlist_add_number(nvl, "psid", mape->psid);
+
+ return (nvl);
+}
+
+static int
+pf_nvpool_to_pool(const nvlist_t *nvl, struct pf_kpool *kpool)
+{
+ int error = 0;
+
+ bzero(kpool, sizeof(*kpool));
+
+ PFNV_CHK(pf_nvbinary(nvl, "key", &kpool->key, sizeof(kpool->key)));
+
+ if (nvlist_exists_nvlist(nvl, "counter")) {
+ PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "counter"),
+ &kpool->counter));
+ }
+
+ PFNV_CHK(pf_nvint(nvl, "tblidx", &kpool->tblidx));
+ PFNV_CHK(pf_nvuint16_array(nvl, "proxy_port", kpool->proxy_port, 2,
+ NULL));
+ PFNV_CHK(pf_nvuint8(nvl, "opts", &kpool->opts));
+
+ if (nvlist_exists_nvlist(nvl, "mape")) {
+ PFNV_CHK(pf_nvmape_to_mape(nvlist_get_nvlist(nvl, "mape"),
+ &kpool->mape));
+ }
+
+errout:
+ return (error);
+}
+
+static nvlist_t *
+pf_pool_to_nvpool(const struct pf_kpool *pool)
+{
+ nvlist_t *nvl;
+ nvlist_t *tmp;
+
+ nvl = nvlist_create(0);
+ if (nvl == NULL)
+ return (NULL);
+
+ nvlist_add_binary(nvl, "key", &pool->key, sizeof(pool->key));
+ tmp = pf_addr_to_nvaddr(&pool->counter);
+ if (tmp == NULL)
+ goto error;
+ nvlist_add_nvlist(nvl, "counter", tmp);
+ nvlist_destroy(tmp);
+
+ nvlist_add_number(nvl, "tblidx", pool->tblidx);
+ pf_uint16_array_nv(nvl, "proxy_port", pool->proxy_port, 2);
+ nvlist_add_number(nvl, "opts", pool->opts);
+
+ tmp = pf_mape_to_nvmape(&pool->mape);
+ if (tmp == NULL)
+ goto error;
+ nvlist_add_nvlist(nvl, "mape", tmp);
+ nvlist_destroy(tmp);
+
+ return (nvl);
+
+error:
+ nvlist_destroy(nvl);
+ return (NULL);
+}
+
+static int
+pf_nvaddr_wrap_to_addr_wrap(const nvlist_t *nvl, struct pf_addr_wrap *addr)
+{
+ int error = 0;
+
+ bzero(addr, sizeof(*addr));
+
+ PFNV_CHK(pf_nvuint8(nvl, "type", &addr->type));
+ PFNV_CHK(pf_nvuint8(nvl, "iflags", &addr->iflags));
+ if (addr->type == PF_ADDR_DYNIFTL)
+ PFNV_CHK(pf_nvstring(nvl, "ifname", addr->v.ifname,
+ sizeof(addr->v.ifname)));
+ if (addr->type == PF_ADDR_TABLE)
+ PFNV_CHK(pf_nvstring(nvl, "tblname", addr->v.tblname,
+ sizeof(addr->v.tblname)));
+
+ if (! nvlist_exists_nvlist(nvl, "addr"))
+ return (EINVAL);
+ PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "addr"),
+ &addr->v.a.addr));
+
+ if (! nvlist_exists_nvlist(nvl, "mask"))
+ return (EINVAL);
+ PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "mask"),
+ &addr->v.a.mask));
+
+ switch (addr->type) {
+ case PF_ADDR_DYNIFTL:
+ case PF_ADDR_TABLE:
+ case PF_ADDR_RANGE:
+ case PF_ADDR_ADDRMASK:
+ case PF_ADDR_NOROUTE:
+ case PF_ADDR_URPFFAILED:
+ break;
+ default:
+ return (EINVAL);
+ }
+
+errout:
+ return (error);
+}
+
+static nvlist_t *
+pf_addr_wrap_to_nvaddr_wrap(const struct pf_addr_wrap *addr)
+{
+ nvlist_t *nvl;
+ nvlist_t *tmp;
+
+ nvl = nvlist_create(0);
+ if (nvl == NULL)
+ return (NULL);
+
+ nvlist_add_number(nvl, "type", addr->type);
+ nvlist_add_number(nvl, "iflags", addr->iflags);
+ if (addr->type == PF_ADDR_DYNIFTL)
+ nvlist_add_string(nvl, "ifname", addr->v.ifname);
+ if (addr->type == PF_ADDR_TABLE)
+ nvlist_add_string(nvl, "tblname", addr->v.tblname);
+
+ tmp = pf_addr_to_nvaddr(&addr->v.a.addr);
+ if (tmp == NULL)
+ goto error;
+ nvlist_add_nvlist(nvl, "addr", tmp);
+ nvlist_destroy(tmp);
+ tmp = pf_addr_to_nvaddr(&addr->v.a.mask);
+ if (tmp == NULL)
+ goto error;
+ nvlist_add_nvlist(nvl, "mask", tmp);
+ nvlist_destroy(tmp);
+
+ return (nvl);
+
+error:
+ nvlist_destroy(nvl);
+ return (NULL);
+}
+
+static int
+pf_validate_op(uint8_t op)
+{
+ switch (op) {
+ case PF_OP_NONE:
+ case PF_OP_IRG:
+ case PF_OP_EQ:
+ case PF_OP_NE:
+ case PF_OP_LT:
+ case PF_OP_LE:
+ case PF_OP_GT:
+ case PF_OP_GE:
+ case PF_OP_XRG:
+ case PF_OP_RRG:
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ return (0);
+}
+
+static int
+pf_nvrule_addr_to_rule_addr(const nvlist_t *nvl, struct pf_rule_addr *addr)
+{
+ int error = 0;
+
+ if (! nvlist_exists_nvlist(nvl, "addr"))
+ return (EINVAL);
+
+ PFNV_CHK(pf_nvaddr_wrap_to_addr_wrap(nvlist_get_nvlist(nvl, "addr"),
+ &addr->addr));
+ PFNV_CHK(pf_nvuint16_array(nvl, "port", addr->port, 2, NULL));
+ PFNV_CHK(pf_nvuint8(nvl, "neg", &addr->neg));
+ PFNV_CHK(pf_nvuint8(nvl, "port_op", &addr->port_op));
+
+ PFNV_CHK(pf_validate_op(addr->port_op));
+
+errout:
+ return (error);
+}
+
+static nvlist_t *
+pf_rule_addr_to_nvrule_addr(const struct pf_rule_addr *addr)
+{
+ nvlist_t *nvl;
+ nvlist_t *tmp;
+
+ nvl = nvlist_create(0);
+ if (nvl == NULL)
+ return (NULL);
+
+ tmp = pf_addr_wrap_to_nvaddr_wrap(&addr->addr);
+ if (tmp == NULL)
+ goto error;
+ nvlist_add_nvlist(nvl, "addr", tmp);
+ nvlist_destroy(tmp);
+ pf_uint16_array_nv(nvl, "port", addr->port, 2);
+ nvlist_add_number(nvl, "neg", addr->neg);
+ nvlist_add_number(nvl, "port_op", addr->port_op);
+
+ return (nvl);
+
+error:
+ nvlist_destroy(nvl);
+ return (NULL);
+}
+
+static int
+pf_nvrule_uid_to_rule_uid(const nvlist_t *nvl, struct pf_rule_uid *uid)
+{
+ int error = 0;
+
+ bzero(uid, sizeof(*uid));
+
+ PFNV_CHK(pf_nvuint32_array(nvl, "uid", uid->uid, 2, NULL));
+ PFNV_CHK(pf_nvuint8(nvl, "op", &uid->op));
+
+ PFNV_CHK(pf_validate_op(uid->op));
+
+errout:
+ return (error);
+}
+
+static nvlist_t *
+pf_rule_uid_to_nvrule_uid(const struct pf_rule_uid *uid)
+{
+ nvlist_t *nvl;
+
+ nvl = nvlist_create(0);
+ if (nvl == NULL)
+ return (NULL);
+
+ pf_uint32_array_nv(nvl, "uid", uid->uid, 2);
+ nvlist_add_number(nvl, "op", uid->op);
+
+ return (nvl);
+}
+
+static int
+pf_nvrule_gid_to_rule_gid(const nvlist_t *nvl, struct pf_rule_gid *gid)
+{
+ /* Cheat a little. These stucts are the same, other than the name of
+ * the first field. */
+ return (pf_nvrule_uid_to_rule_uid(nvl, (struct pf_rule_uid *)gid));
+}
+
+int
+pf_check_rule_addr(const struct pf_rule_addr *addr)
+{
+
+ switch (addr->addr.type) {
+ case PF_ADDR_ADDRMASK:
+ case PF_ADDR_NOROUTE:
+ case PF_ADDR_DYNIFTL:
+ case PF_ADDR_TABLE:
+ case PF_ADDR_URPFFAILED:
+ case PF_ADDR_RANGE:
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ if (addr->addr.p.dyn != NULL) {
+ return (EINVAL);
+ }
+
+ return (0);
+}
+
+
+int
+pf_nvrule_to_krule(const nvlist_t *nvl, struct pf_krule *rule)
+{
+ int error = 0;
+
+#define ERROUT(x) ERROUT_FUNCTION(errout, x)
+
+ PFNV_CHK(pf_nvuint32(nvl, "nr", &rule->nr));
+
+ if (! nvlist_exists_nvlist(nvl, "src"))
+ ERROUT(EINVAL);
+
+ error = pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "src"),
+ &rule->src);
+ if (error != 0)
+ ERROUT(error);
+
+ if (! nvlist_exists_nvlist(nvl, "dst"))
+ ERROUT(EINVAL);
+
+ PFNV_CHK(pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "dst"),
+ &rule->dst));
+
+ if (nvlist_exists_string(nvl, "label")) {
+ PFNV_CHK(pf_nvstring(nvl, "label", rule->label[0],
+ sizeof(rule->label[0])));
+ } else if (nvlist_exists_string_array(nvl, "labels")) {
+ const char *const *strs;
+ size_t items;
+ int ret;
+
+ strs = nvlist_get_string_array(nvl, "labels", &items);
+ if (items > PF_RULE_MAX_LABEL_COUNT)
+ ERROUT(E2BIG);
+
+ for (size_t i = 0; i < items; i++) {
+ ret = strlcpy(rule->label[i], strs[i],
+ sizeof(rule->label[0]));
+ if (ret >= sizeof(rule->label[0]))
+ ERROUT(E2BIG);
+ }
+ }
+
+ PFNV_CHK(pf_nvstring(nvl, "ifname", rule->ifname,
+ sizeof(rule->ifname)));
+ PFNV_CHK(pf_nvstring(nvl, "qname", rule->qname, sizeof(rule->qname)));
+ PFNV_CHK(pf_nvstring(nvl, "pqname", rule->pqname,
+ sizeof(rule->pqname)));
+ PFNV_CHK(pf_nvstring(nvl, "tagname", rule->tagname,
+ sizeof(rule->tagname)));
+ PFNV_CHK(pf_nvstring(nvl, "match_tagname", rule->match_tagname,
+ sizeof(rule->match_tagname)));
+ PFNV_CHK(pf_nvstring(nvl, "overload_tblname", rule->overload_tblname,
+ sizeof(rule->overload_tblname)));
+
+ if (! nvlist_exists_nvlist(nvl, "rpool"))
+ ERROUT(EINVAL);
+ PFNV_CHK(pf_nvpool_to_pool(nvlist_get_nvlist(nvl, "rpool"),
+ &rule->rpool));
+
+ PFNV_CHK(pf_nvuint32(nvl, "os_fingerprint", &rule->os_fingerprint));
+
+ PFNV_CHK(pf_nvint(nvl, "rtableid", &rule->rtableid));
+ PFNV_CHK(pf_nvuint32_array(nvl, "timeout", rule->timeout, PFTM_MAX, NULL));
+ PFNV_CHK(pf_nvuint32(nvl, "max_states", &rule->max_states));
+ PFNV_CHK(pf_nvuint32(nvl, "max_src_nodes", &rule->max_src_nodes));
+ PFNV_CHK(pf_nvuint32(nvl, "max_src_states", &rule->max_src_states));
+ PFNV_CHK(pf_nvuint32(nvl, "max_src_conn", &rule->max_src_conn));
+ PFNV_CHK(pf_nvuint32(nvl, "max_src_conn_rate.limit",
+ &rule->max_src_conn_rate.limit));
+ PFNV_CHK(pf_nvuint32(nvl, "max_src_conn_rate.seconds",
+ &rule->max_src_conn_rate.seconds));
+ PFNV_CHK(pf_nvuint32(nvl, "prob", &rule->prob));
+ PFNV_CHK(pf_nvuint32(nvl, "cuid", &rule->cuid));
+ PFNV_CHK(pf_nvuint32(nvl, "cpid", &rule->cpid));
+
+ PFNV_CHK(pf_nvuint16(nvl, "return_icmp", &rule->return_icmp));
+ PFNV_CHK(pf_nvuint16(nvl, "return_icmp6", &rule->return_icmp6));
+
+ PFNV_CHK(pf_nvuint16(nvl, "max_mss", &rule->max_mss));
+ PFNV_CHK(pf_nvuint16(nvl, "scrub_flags", &rule->scrub_flags));
+
+ if (! nvlist_exists_nvlist(nvl, "uid"))
+ ERROUT(EINVAL);
+ PFNV_CHK(pf_nvrule_uid_to_rule_uid(nvlist_get_nvlist(nvl, "uid"),
+ &rule->uid));
+
+ if (! nvlist_exists_nvlist(nvl, "gid"))
+ ERROUT(EINVAL);
+ PFNV_CHK(pf_nvrule_gid_to_rule_gid(nvlist_get_nvlist(nvl, "gid"),
+ &rule->gid));
+
+ PFNV_CHK(pf_nvuint32(nvl, "rule_flag", &rule->rule_flag));
+ PFNV_CHK(pf_nvuint8(nvl, "action", &rule->action));
+ PFNV_CHK(pf_nvuint8(nvl, "direction", &rule->direction));
+ PFNV_CHK(pf_nvuint8(nvl, "log", &rule->log));
+ PFNV_CHK(pf_nvuint8(nvl, "logif", &rule->logif));
+ PFNV_CHK(pf_nvuint8(nvl, "quick", &rule->quick));
+ PFNV_CHK(pf_nvuint8(nvl, "ifnot", &rule->ifnot));
+ PFNV_CHK(pf_nvuint8(nvl, "match_tag_not", &rule->match_tag_not));
+ PFNV_CHK(pf_nvuint8(nvl, "natpass", &rule->natpass));
+
+ PFNV_CHK(pf_nvuint8(nvl, "keep_state", &rule->keep_state));
+ PFNV_CHK(pf_nvuint8(nvl, "af", &rule->af));
+ PFNV_CHK(pf_nvuint8(nvl, "proto", &rule->proto));
+ PFNV_CHK(pf_nvuint8(nvl, "type", &rule->type));
+ PFNV_CHK(pf_nvuint8(nvl, "code", &rule->code));
+ PFNV_CHK(pf_nvuint8(nvl, "flags", &rule->flags));
+ PFNV_CHK(pf_nvuint8(nvl, "flagset", &rule->flagset));
+ PFNV_CHK(pf_nvuint8(nvl, "min_ttl", &rule->min_ttl));
+ PFNV_CHK(pf_nvuint8(nvl, "allow_opts", &rule->allow_opts));
+ PFNV_CHK(pf_nvuint8(nvl, "rt", &rule->rt));
+ PFNV_CHK(pf_nvuint8(nvl, "return_ttl", &rule->return_ttl));
+ PFNV_CHK(pf_nvuint8(nvl, "tos", &rule->tos));
+ PFNV_CHK(pf_nvuint8(nvl, "set_tos", &rule->set_tos));
+ PFNV_CHK(pf_nvuint8(nvl, "anchor_relative", &rule->anchor_relative));
+ PFNV_CHK(pf_nvuint8(nvl, "anchor_wildcard", &rule->anchor_wildcard));
+
+ PFNV_CHK(pf_nvuint8(nvl, "flush", &rule->flush));
+ PFNV_CHK(pf_nvuint8(nvl, "prio", &rule->prio));
+
+ PFNV_CHK(pf_nvuint8_array(nvl, "set_prio", &rule->prio, 2, NULL));
+
+ if (nvlist_exists_nvlist(nvl, "divert")) {
+ const nvlist_t *nvldivert = nvlist_get_nvlist(nvl, "divert");
+
+ if (! nvlist_exists_nvlist(nvldivert, "addr"))
+ ERROUT(EINVAL);
+ PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvldivert, "addr"),
+ &rule->divert.addr));
+ PFNV_CHK(pf_nvuint16(nvldivert, "port", &rule->divert.port));
+ }
+
+ /* Validation */
+#ifndef INET
+ if (rule->af == AF_INET)
+ ERROUT(EAFNOSUPPORT);
+#endif /* INET */
+#ifndef INET6
+ if (rule->af == AF_INET6)
+ ERROUT(EAFNOSUPPORT);
+#endif /* INET6 */
+
+ PFNV_CHK(pf_check_rule_addr(&rule->src));
+ PFNV_CHK(pf_check_rule_addr(&rule->dst));
+
+ return (0);
+
+#undef ERROUT
+errout:
+ return (error);
+}
+
+static nvlist_t *
+pf_divert_to_nvdivert(const struct pf_krule *rule)
+{
+ nvlist_t *nvl;
+ nvlist_t *tmp;
+
+ nvl = nvlist_create(0);
+ if (nvl == NULL)
+ return (NULL);
+
+ tmp = pf_addr_to_nvaddr(&rule->divert.addr);
+ if (tmp == NULL)
+ goto error;
+ nvlist_add_nvlist(nvl, "addr", tmp);
+ nvlist_destroy(tmp);
+ nvlist_add_number(nvl, "port", rule->divert.port);
+
+ return (nvl);
+
+error:
+ nvlist_destroy(nvl);
+ return (NULL);
+}
+
+nvlist_t *
+pf_krule_to_nvrule(const struct pf_krule *rule)
+{
+ nvlist_t *nvl, *tmp;
+
+ nvl = nvlist_create(0);
+ if (nvl == NULL)
+ return (nvl);
+
+ nvlist_add_number(nvl, "nr", rule->nr);
+ tmp = pf_rule_addr_to_nvrule_addr(&rule->src);
+ if (tmp == NULL)
+ goto error;
+ nvlist_add_nvlist(nvl, "src", tmp);
+ nvlist_destroy(tmp);
+ tmp = pf_rule_addr_to_nvrule_addr(&rule->dst);
+ if (tmp == NULL)
+ goto error;
+ nvlist_add_nvlist(nvl, "dst", tmp);
+ nvlist_destroy(tmp);
+
+ for (int i = 0; i < PF_SKIP_COUNT; i++) {
+ nvlist_append_number_array(nvl, "skip",
+ rule->skip[i].ptr ? rule->skip[i].ptr->nr : -1);
+ }
+
+ for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++) {
+ nvlist_append_string_array(nvl, "labels", rule->label[i]);
+ }
+ nvlist_add_string(nvl, "label", rule->label[0]);
+ nvlist_add_string(nvl, "ifname", rule->ifname);
+ nvlist_add_string(nvl, "qname", rule->qname);
+ nvlist_add_string(nvl, "pqname", rule->pqname);
+ nvlist_add_string(nvl, "tagname", rule->tagname);
+ nvlist_add_string(nvl, "match_tagname", rule->match_tagname);
+ nvlist_add_string(nvl, "overload_tblname", rule->overload_tblname);
+
+ tmp = pf_pool_to_nvpool(&rule->rpool);
+ if (tmp == NULL)
+ goto error;
+ nvlist_add_nvlist(nvl, "rpool", tmp);
+ nvlist_destroy(tmp);
+
+ nvlist_add_number(nvl, "evaluations",
+ counter_u64_fetch(rule->evaluations));
+ for (int i = 0; i < 2; i++) {
+ nvlist_append_number_array(nvl, "packets",
+ counter_u64_fetch(rule->packets[i]));
+ nvlist_append_number_array(nvl, "bytes",
+ counter_u64_fetch(rule->bytes[i]));
+ }
+
+ nvlist_add_number(nvl, "os_fingerprint", rule->os_fingerprint);
+
+ nvlist_add_number(nvl, "rtableid", rule->rtableid);
+ pf_uint32_array_nv(nvl, "timeout", rule->timeout, PFTM_MAX);
+ nvlist_add_number(nvl, "max_states", rule->max_states);
+ nvlist_add_number(nvl, "max_src_nodes", rule->max_src_nodes);
+ nvlist_add_number(nvl, "max_src_states", rule->max_src_states);
+ nvlist_add_number(nvl, "max_src_conn", rule->max_src_conn);
+ nvlist_add_number(nvl, "max_src_conn_rate.limit",
+ rule->max_src_conn_rate.limit);
+ nvlist_add_number(nvl, "max_src_conn_rate.seconds",
+ rule->max_src_conn_rate.seconds);
+ nvlist_add_number(nvl, "qid", rule->qid);
+ nvlist_add_number(nvl, "pqid", rule->pqid);
+ nvlist_add_number(nvl, "prob", rule->prob);
+ nvlist_add_number(nvl, "cuid", rule->cuid);
+ nvlist_add_number(nvl, "cpid", rule->cpid);
+
+ nvlist_add_number(nvl, "states_cur",
+ counter_u64_fetch(rule->states_cur));
+ nvlist_add_number(nvl, "states_tot",
+ counter_u64_fetch(rule->states_tot));
+ nvlist_add_number(nvl, "src_nodes",
+ counter_u64_fetch(rule->src_nodes));
+
+ nvlist_add_number(nvl, "return_icmp", rule->return_icmp);
+ nvlist_add_number(nvl, "return_icmp6", rule->return_icmp6);
+
+ nvlist_add_number(nvl, "max_mss", rule->max_mss);
+ nvlist_add_number(nvl, "scrub_flags", rule->scrub_flags);
+
+ tmp = pf_rule_uid_to_nvrule_uid(&rule->uid);
+ if (tmp == NULL)
+ goto error;
+ nvlist_add_nvlist(nvl, "uid", tmp);
+ nvlist_destroy(tmp);
+ tmp = pf_rule_uid_to_nvrule_uid((const struct pf_rule_uid *)&rule->gid);
+ if (tmp == NULL)
+ goto error;
+ nvlist_add_nvlist(nvl, "gid", tmp);
+ nvlist_destroy(tmp);
+
+ nvlist_add_number(nvl, "rule_flag", rule->rule_flag);
+ nvlist_add_number(nvl, "action", rule->action);
+ nvlist_add_number(nvl, "direction", rule->direction);
+ nvlist_add_number(nvl, "log", rule->log);
+ nvlist_add_number(nvl, "logif", rule->logif);
+ nvlist_add_number(nvl, "quick", rule->quick);
+ nvlist_add_number(nvl, "ifnot", rule->ifnot);
+ nvlist_add_number(nvl, "match_tag_not", rule->match_tag_not);
+ nvlist_add_number(nvl, "natpass", rule->natpass);
+
+ nvlist_add_number(nvl, "keep_state", rule->keep_state);
+ nvlist_add_number(nvl, "af", rule->af);
+ nvlist_add_number(nvl, "proto", rule->proto);
+ nvlist_add_number(nvl, "type", rule->type);
+ nvlist_add_number(nvl, "code", rule->code);
+ nvlist_add_number(nvl, "flags", rule->flags);
+ nvlist_add_number(nvl, "flagset", rule->flagset);
+ nvlist_add_number(nvl, "min_ttl", rule->min_ttl);
+ nvlist_add_number(nvl, "allow_opts", rule->allow_opts);
+ nvlist_add_number(nvl, "rt", rule->rt);
+ nvlist_add_number(nvl, "return_ttl", rule->return_ttl);
+ nvlist_add_number(nvl, "tos", rule->tos);
+ nvlist_add_number(nvl, "set_tos", rule->set_tos);
+ nvlist_add_number(nvl, "anchor_relative", rule->anchor_relative);
+ nvlist_add_number(nvl, "anchor_wildcard", rule->anchor_wildcard);
+
+ nvlist_add_number(nvl, "flush", rule->flush);
+ nvlist_add_number(nvl, "prio", rule->prio);
+
+ pf_uint8_array_nv(nvl, "set_prio", &rule->prio, 2);
+
+ tmp = pf_divert_to_nvdivert(rule);
+ if (tmp == NULL)
+ goto error;
+ nvlist_add_nvlist(nvl, "divert", tmp);
+ nvlist_destroy(tmp);
+
+ return (nvl);
+
+error:
+ nvlist_destroy(nvl);
+ return (NULL);
+}
+
+static int
+pf_nvstate_cmp_to_state_cmp(const nvlist_t *nvl, struct pf_state_cmp *cmp)
+{
+ int error = 0;
+
+ bzero(cmp, sizeof(*cmp));
+
+ PFNV_CHK(pf_nvuint64(nvl, "id", &cmp->id));
+ PFNV_CHK(pf_nvuint32(nvl, "creatorid", &cmp->creatorid));
+ PFNV_CHK(pf_nvuint8(nvl, "direction", &cmp->direction));
+
+errout:
+ return (error);
+}
+
+int
+pf_nvstate_kill_to_kstate_kill(const nvlist_t *nvl,
+ struct pf_kstate_kill *kill)
+{
+ int error = 0;
+
+ bzero(kill, sizeof(*kill));
+
+ if (! nvlist_exists_nvlist(nvl, "cmp"))
+ return (EINVAL);
+
+ PFNV_CHK(pf_nvstate_cmp_to_state_cmp(nvlist_get_nvlist(nvl, "cmp"),
+ &kill->psk_pfcmp));
+ PFNV_CHK(pf_nvuint8(nvl, "af", &kill->psk_af));
+ PFNV_CHK(pf_nvint(nvl, "proto", &kill->psk_proto));
+
+ if (! nvlist_exists_nvlist(nvl, "src"))
+ return (EINVAL);
+ PFNV_CHK(pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "src"),
+ &kill->psk_src));
+ if (! nvlist_exists_nvlist(nvl, "dst"))
+ return (EINVAL);
+ PFNV_CHK(pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "dst"),
+ &kill->psk_dst));
+ if (nvlist_exists_nvlist(nvl, "rt_addr")) {
+ PFNV_CHK(pf_nvrule_addr_to_rule_addr(
+ nvlist_get_nvlist(nvl, "rt_addr"), &kill->psk_rt_addr));
+ }
+
+ PFNV_CHK(pf_nvstring(nvl, "ifname", kill->psk_ifname,
+ sizeof(kill->psk_ifname)));
+ PFNV_CHK(pf_nvstring(nvl, "label", kill->psk_label,
+ sizeof(kill->psk_label)));
+ if (nvlist_exists_bool(nvl, "kill_match"))
+ kill->psk_kill_match = nvlist_get_bool(nvl, "kill_match");
+
+errout:
+ return (error);
+}
+
+static nvlist_t *
+pf_state_key_to_nvstate_key(const struct pf_state_key *key)
+{
+ nvlist_t *nvl, *tmp;
+
+ nvl = nvlist_create(0);
+ if (nvl == NULL)
+ return (NULL);
+
+ for (int i = 0; i < 2; i++) {
+ tmp = pf_addr_to_nvaddr(&key->addr[i]);
+ if (tmp == NULL)
+ goto errout;
+ nvlist_append_nvlist_array(nvl, "addr", tmp);
+ nvlist_append_number_array(nvl, "port", key->port[i]);
+ }
+ nvlist_add_number(nvl, "af", key->af);
+ nvlist_add_number(nvl, "proto", key->proto);
+
+ return (nvl);
+
+errout:
+ nvlist_destroy(nvl);
+ return (NULL);
+}
+
+static nvlist_t *
+pf_state_scrub_to_nvstate_scrub(const struct pf_state_scrub *scrub)
+{
+ nvlist_t *nvl;
+
+ nvl = nvlist_create(0);
+ if (nvl == NULL)
+ return (NULL);
+
+ nvlist_add_bool(nvl, "timestamp", scrub->pfss_flags & PFSS_TIMESTAMP);
+ nvlist_add_number(nvl, "ttl", scrub->pfss_ttl);
+ nvlist_add_number(nvl, "ts_mod", scrub->pfss_ts_mod);
+
+ return (nvl);
+}
+
+static nvlist_t *
+pf_state_peer_to_nvstate_peer(const struct pf_state_peer *peer)
+{
+ nvlist_t *nvl, *tmp;
+
+ nvl = nvlist_create(0);
+ if (nvl == NULL)
+ return (NULL);
+
+ if (peer->scrub) {
+ tmp = pf_state_scrub_to_nvstate_scrub(peer->scrub);
+ if (tmp == NULL)
+ goto errout;
+ nvlist_add_nvlist(nvl, "scrub", tmp);
+ nvlist_destroy(tmp);
+ }
+
+ nvlist_add_number(nvl, "seqlo", peer->seqlo);
+ nvlist_add_number(nvl, "seqhi", peer->seqhi);
+ nvlist_add_number(nvl, "seqdiff", peer->seqdiff);
+ nvlist_add_number(nvl, "max_win", peer->max_win);
+ nvlist_add_number(nvl, "mss", peer->mss);
+ nvlist_add_number(nvl, "state", peer->state);
+ nvlist_add_number(nvl, "wscale", peer->wscale);
+
+ return (nvl);
+
+errout:
+ nvlist_destroy(nvl);
+ return (NULL);
+}
+
+nvlist_t *
+pf_state_to_nvstate(const struct pf_state *s)
+{
+ nvlist_t *nvl, *tmp;
+ uint32_t expire, flags = 0;
+
+ nvl = nvlist_create(0);
+ if (nvl == NULL)
+ return (NULL);
+
+ nvlist_add_number(nvl, "id", s->id);
+ nvlist_add_string(nvl, "ifname", s->kif->pfik_name);
+ nvlist_add_string(nvl, "orig_ifname", s->orig_kif->pfik_name);
+
+ tmp = pf_state_key_to_nvstate_key(s->key[PF_SK_STACK]);
+ if (tmp == NULL)
+ goto errout;
+ nvlist_add_nvlist(nvl, "stack_key", tmp);
+ nvlist_destroy(tmp);
+
+ tmp = pf_state_key_to_nvstate_key(s->key[PF_SK_WIRE]);
+ if (tmp == NULL)
+ goto errout;
+ nvlist_add_nvlist(nvl, "wire_key", tmp);
+ nvlist_destroy(tmp);
+
+ tmp = pf_state_peer_to_nvstate_peer(&s->src);
+ if (tmp == NULL)
+ goto errout;
+ nvlist_add_nvlist(nvl, "src", tmp);
+ nvlist_destroy(tmp);
+
+ tmp = pf_state_peer_to_nvstate_peer(&s->dst);
+ if (tmp == NULL)
+ goto errout;
+ nvlist_add_nvlist(nvl, "dst", tmp);
+ nvlist_destroy(tmp);
+
+ tmp = pf_addr_to_nvaddr(&s->rt_addr);
+ if (tmp == NULL)
+ goto errout;
+ nvlist_add_nvlist(nvl, "rt_addr", tmp);
+ nvlist_destroy(tmp);
+
+ nvlist_add_number(nvl, "rule", s->rule.ptr ? s->rule.ptr->nr : -1);
+ nvlist_add_number(nvl, "anchor",
+ s->anchor.ptr ? s->anchor.ptr->nr : -1);
+ nvlist_add_number(nvl, "nat_rule",
+ s->nat_rule.ptr ? s->nat_rule.ptr->nr : -1);
+ nvlist_add_number(nvl, "creation", s->creation);
+
+ expire = pf_state_expires(s);
+ if (expire <= time_uptime)
+ expire = 0;
+ else
+ expire = expire - time_uptime;
+ nvlist_add_number(nvl, "expire", expire);
+
+ for (int i = 0; i < 2; i++) {
+ nvlist_append_number_array(nvl, "packets",
+ counter_u64_fetch(s->packets[i]));
+ nvlist_append_number_array(nvl, "bytes",
+ counter_u64_fetch(s->bytes[i]));
+ }
+
+ nvlist_add_number(nvl, "creatorid", s->creatorid);
+ nvlist_add_number(nvl, "direction", s->direction);
+ nvlist_add_number(nvl, "log", s->log);
+ nvlist_add_number(nvl, "state_flags", s->state_flags);
+ nvlist_add_number(nvl, "timeout", s->timeout);
+ if (s->src_node)
+ flags |= PFSYNC_FLAG_SRCNODE;
+ if (s->nat_src_node)
+ flags |= PFSYNC_FLAG_NATSRCNODE;
+ nvlist_add_number(nvl, "sync_flags", flags);
+
+ return (nvl);
+
+errout:
+ nvlist_destroy(nvl);
+ return (NULL);
+}
diff --git a/sys/netpfil/pf/pf_nv.h b/sys/netpfil/pf/pf_nv.h
index 589a1972fa43..321c0425fe7f 100644
--- a/sys/netpfil/pf/pf_nv.h
+++ b/sys/netpfil/pf/pf_nv.h
@@ -28,8 +28,33 @@
#ifndef _PF_NV_H_
#define _PF_NV_H_
-#include <sys/types.h>
#include <sys/nv.h>
+#include <sys/sdt.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
+#include <net/if.h>
+#include <net/if_var.h>
+#include <net/pfvar.h>
+
+SDT_PROVIDER_DECLARE(pf);
+SDT_PROBE_DECLARE(pf, ioctl, function, error);
+SDT_PROBE_DECLARE(pf, ioctl, nvchk, error);
+
+#define ERROUT_FUNCTION(target, x) \
+ do { \
+ error = (x); \
+ SDT_PROBE3(pf, ioctl, function, error, __func__, error, \
+ __LINE__); \
+ goto target; \
+ } while (0)
+
+#define PFNV_CHK(x) do { \
+ error = (x); \
+ SDT_PROBE2(pf, ioctl, nvchk, error, error, __LINE__); \
+ if (error != 0) \
+ goto errout; \
+ } while (0)
int pf_nvbinary(const nvlist_t *, const char *, void *, size_t);
int pf_nvint(const nvlist_t *, const char *, int *);
@@ -56,11 +81,14 @@ void pf_uint64_array_nv(nvlist_t *, const char *, const uint64_t *,
int pf_nvstring(const nvlist_t *, const char *, char *, size_t);
-#define PFNV_CHK(x) do { \
- error = (x); \
- SDT_PROBE2(pf, ioctl, nvchk, error, error, __LINE__); \
- if (error != 0) \
- goto errout; \
- } while (0)
+/* Translation functions */
+
+int pf_check_rule_addr(const struct pf_rule_addr *);
+
+nvlist_t *pf_krule_to_nvrule(const struct pf_krule *);
+int pf_nvrule_to_krule(const nvlist_t *, struct pf_krule *);
+int pf_nvstate_kill_to_kstate_kill(const nvlist_t *,
+ struct pf_kstate_kill *);
+nvlist_t *pf_state_to_nvstate(const struct pf_state *);
#endif