aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristof Provost <kp@FreeBSD.org>2021-03-25 09:39:14 +0000
committerKristof Provost <kp@FreeBSD.org>2021-05-07 08:15:41 +0000
commita3e4fd8b33932a8168cf8a99381b4bd6c87aaad7 (patch)
tree31890873c4c6598c779a15689659387ffb74fc75
parent9a8b5708124660ae16a920f71117c85b34b455c1 (diff)
downloadsrc-a3e4fd8b33932a8168cf8a99381b4bd6c87aaad7.tar.gz
src-a3e4fd8b33932a8168cf8a99381b4bd6c87aaad7.zip
pf: Implement nvlist variant of DIOCGETRULE
MFC after: 4 weeks Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D29559 (cherry picked from commit d710367d1159423ed4da6628b7ab042d3e44f900)
-rw-r--r--sys/net/pfvar.h4
-rw-r--r--sys/netpfil/pf/pf_ioctl.c398
-rw-r--r--sys/netpfil/pf/pf_nv.c23
-rw-r--r--sys/netpfil/pf/pf_nv.h7
-rw-r--r--sys/netpfil/pf/pf_ruleset.c47
5 files changed, 473 insertions, 6 deletions
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index 584724b88b13..0ca46bb8048a 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -40,6 +40,7 @@
#include <sys/counter.h>
#include <sys/cpuset.h>
#include <sys/malloc.h>
+#include <sys/nv.h>
#include <sys/refcount.h>
#include <sys/sysctl.h>
#include <sys/lock.h>
@@ -1231,6 +1232,7 @@ struct pfioc_iface {
#define DIOCADDRULENV _IOWR('D', 4, struct pfioc_nv)
#define DIOCGETRULES _IOWR('D', 6, struct pfioc_rule)
#define DIOCGETRULE _IOWR('D', 7, struct pfioc_rule)
+#define DIOCGETRULENV _IOWR('D', 7, struct pfioc_nv)
/* XXX cut 8 - 17 */
#define DIOCCLRSTATES _IOWR('D', 18, struct pfioc_state_kill)
#define DIOCGETSTATE _IOWR('D', 19, struct pfioc_state)
@@ -1634,6 +1636,8 @@ VNET_DECLARE(struct pf_kanchor, pf_main_anchor);
void pf_init_kruleset(struct pf_kruleset *);
int pf_kanchor_setup(struct pf_krule *,
const struct pf_kruleset *, const char *);
+int pf_kanchor_nvcopyout(const struct pf_kruleset *,
+ const struct pf_krule *, nvlist_t *);
int pf_kanchor_copyout(const struct pf_kruleset *,
const struct pf_krule *, struct pfioc_rule *);
void pf_kanchor_remove(struct pf_krule *);
diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c
index 87a52dd41542..cdff32916953 100644
--- a/sys/netpfil/pf/pf_ioctl.c
+++ b/sys/netpfil/pf/pf_ioctl.c
@@ -1630,6 +1630,20 @@ 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_nvpool_to_pool(const nvlist_t *nvl, struct pf_kpool *kpool)
{
@@ -1653,6 +1667,33 @@ 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_add_number(nvl, "tblidx", pool->tblidx);
+ pf_uint16_array_nv(nvl, "proxy_port", pool->proxy_port, 2);
+ nvlist_add_number(nvl, "opts", pool->opts);
+
+ 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)
{
@@ -1693,6 +1734,37 @@ 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);
+ nvlist_add_string(nvl, "ifname", addr->v.ifname);
+ 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);
+ tmp = pf_addr_to_nvaddr(&addr->v.a.mask);
+ if (tmp == NULL)
+ goto error;
+ nvlist_add_nvlist(nvl, "mask", tmp);
+
+ return (nvl);
+
+error:
+ nvlist_destroy(nvl);
+ return (NULL);
+}
+
static int
pf_validate_op(uint8_t op)
{
@@ -1735,6 +1807,31 @@ 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);
+ 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)
{
@@ -1751,6 +1848,21 @@ 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)
{
@@ -1912,6 +2024,158 @@ 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_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);
+ tmp = pf_rule_addr_to_nvrule_addr(&rule->dst);
+ if (tmp == NULL)
+ goto error;
+ nvlist_add_nvlist(nvl, "dst", 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);
+ }
+
+ nvlist_add_string(nvl, "label", rule->label);
+ 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_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);
+ 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_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);
+
+ return (nvl);
+
+error:
+ nvlist_destroy(nvl);
+ return (NULL);
+}
+
static int
pf_rule_to_krule(const struct pf_rule *rule, struct pf_krule *krule)
{
@@ -2254,6 +2518,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
switch (cmd) {
case DIOCGETRULES:
case DIOCGETRULE:
+ case DIOCGETRULENV:
case DIOCGETADDRS:
case DIOCGETADDR:
case DIOCGETSTATE:
@@ -2335,6 +2600,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
case DIOCIGETIFACES:
case DIOCGIFSPEEDV1:
case DIOCGIFSPEEDV0:
+ case DIOCGETRULENV:
break;
case DIOCRCLRTABLES:
case DIOCRADDTABLES:
@@ -2560,6 +2826,138 @@ DIOCADDRULENV_error:
break;
}
+ case DIOCGETRULENV: {
+ struct pfioc_nv *nv = (struct pfioc_nv *)addr;
+ nvlist_t *nvrule = NULL;
+ nvlist_t *nvl = NULL;
+ struct pf_kruleset *ruleset;
+ struct pf_krule *rule;
+ void *nvlpacked = NULL;
+ int rs_num, nr;
+ bool clear_counter = false;
+
+#define ERROUT(x) do { error = (x); goto DIOCGETRULENV_error; } while (0)
+
+ if (nv->len > pf_ioctl_maxcount)
+ ERROUT(ENOMEM);
+
+ /* Copy the request in */
+ nvlpacked = malloc(nv->len, M_TEMP, M_WAITOK);
+ if (nvlpacked == NULL)
+ ERROUT(ENOMEM);
+
+ error = copyin(nv->data, nvlpacked, nv->len);
+ if (error)
+ ERROUT(error);
+
+ nvl = nvlist_unpack(nvlpacked, nv->len, 0);
+ if (nvl == NULL)
+ ERROUT(EBADMSG);
+
+ if (! nvlist_exists_string(nvl, "anchor"))
+ ERROUT(EBADMSG);
+ if (! nvlist_exists_number(nvl, "ruleset"))
+ ERROUT(EBADMSG);
+ if (! nvlist_exists_number(nvl, "ticket"))
+ ERROUT(EBADMSG);
+ if (! nvlist_exists_number(nvl, "nr"))
+ ERROUT(EBADMSG);
+
+ if (nvlist_exists_bool(nvl, "clear_counter"))
+ clear_counter = nvlist_get_bool(nvl, "clear_counter");
+
+ if (clear_counter && !(flags & FWRITE))
+ ERROUT(EACCES);
+
+ nr = nvlist_get_number(nvl, "nr");
+
+ PF_RULES_WLOCK();
+ ruleset = pf_find_kruleset(nvlist_get_string(nvl, "anchor"));
+ if (ruleset == NULL) {
+ PF_RULES_WUNLOCK();
+ ERROUT(ENOENT);
+ }
+
+ rs_num = pf_get_ruleset_number(nvlist_get_number(nvl, "ruleset"));
+ if (rs_num >= PF_RULESET_MAX) {
+ PF_RULES_WUNLOCK();
+ ERROUT(EINVAL);
+ }
+
+ if (nvlist_get_number(nvl, "ticket") !=
+ ruleset->rules[rs_num].active.ticket) {
+ PF_RULES_WUNLOCK();
+ ERROUT(EBUSY);
+ break;
+ }
+
+ if ((error = nvlist_error(nvl))) {
+ PF_RULES_WUNLOCK();
+ ERROUT(error);
+ }
+
+ rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr);
+ while ((rule != NULL) && (rule->nr != nr))
+ rule = TAILQ_NEXT(rule, entries);
+ if (rule == NULL) {
+ PF_RULES_WUNLOCK();
+ ERROUT(EBUSY);
+ break;
+ }
+
+ nvrule = pf_krule_to_nvrule(rule);
+
+ nvlist_destroy(nvl);
+ nvl = nvlist_create(0);
+ if (nvl == NULL) {
+ PF_RULES_WUNLOCK();
+ ERROUT(ENOMEM);
+ }
+ nvlist_add_number(nvl, "nr", nr);
+ nvlist_add_nvlist(nvl, "rule", nvrule);
+ nvrule = NULL;
+ if (pf_kanchor_nvcopyout(ruleset, rule, nvl)) {
+ PF_RULES_WUNLOCK();
+ ERROUT(EBUSY);
+ }
+
+ free(nvlpacked, M_TEMP);
+ nvlpacked = nvlist_pack(nvl, &nv->len);
+ if (nvlpacked == NULL) {
+ PF_RULES_WUNLOCK();
+ ERROUT(ENOMEM);
+ }
+
+ if (nv->size == 0) {
+ PF_RULES_WUNLOCK();
+ ERROUT(0);
+ }
+ else if (nv->size < nv->len) {
+ PF_RULES_WUNLOCK();
+ ERROUT(ENOSPC);
+ }
+
+ error = copyout(nvlpacked, nv->data, nv->len);
+
+ if (clear_counter) {
+ counter_u64_zero(rule->evaluations);
+ for (int i = 0; i < 2; i++) {
+ counter_u64_zero(rule->packets[i]);
+ counter_u64_zero(rule->bytes[i]);
+ }
+ counter_u64_zero(rule->states_tot);
+ }
+ PF_RULES_WUNLOCK();
+
+#undef ERROUT
+DIOCGETRULENV_error:
+ free(nvlpacked, M_TEMP);
+ nvlist_destroy(nvrule);
+ nvlist_destroy(nvl);
+
+ break;
+ }
+
case DIOCCHANGERULE: {
struct pfioc_rule *pcr = (struct pfioc_rule *)addr;
struct pf_kruleset *ruleset;
diff --git a/sys/netpfil/pf/pf_nv.c b/sys/netpfil/pf/pf_nv.c
index d583844c4086..d88c0b14e435 100644
--- a/sys/netpfil/pf/pf_nv.c
+++ b/sys/netpfil/pf/pf_nv.c
@@ -37,7 +37,7 @@ __FBSDID("$FreeBSD$");
#define PV_NV_IMPL_UINT(fnname, type, max) \
int \
- fnname(const nvlist_t *nvl, const char *name, type *val) \
+ pf_nv ## fnname(const nvlist_t *nvl, const char *name, type *val) \
{ \
uint64_t raw; \
if (! nvlist_exists_number(nvl, name)) \
@@ -49,8 +49,8 @@ __FBSDID("$FreeBSD$");
return (0); \
} \
int \
- fnname ## _array(const nvlist_t *nvl, const char *name, type *array, \
- size_t maxelems, size_t *nelems) \
+ pf_nv ## fnname ## _array(const nvlist_t *nvl, const char *name, \
+ type *array, size_t maxelems, size_t *nelems) \
{ \
const uint64_t *n; \
size_t nitems; \
@@ -68,7 +68,18 @@ __FBSDID("$FreeBSD$");
array[i] = (type)n[i]; \
} \
return (0); \
+ } \
+ void \
+ pf_ ## fnname ## _array_nv(nvlist_t *nvl, const char *name, \
+ const type *numbers, size_t count) \
+ { \
+ uint64_t tmp; \
+ for (size_t i = 0; i < count; i++) { \
+ tmp = numbers[i]; \
+ nvlist_append_number_array(nvl, name, tmp); \
+ } \
}
+
int
pf_nvbinary(const nvlist_t *nvl, const char *name, void *data,
size_t expected_size)
@@ -90,9 +101,9 @@ pf_nvbinary(const nvlist_t *nvl, const char *name, void *data,
return (0);
}
-PV_NV_IMPL_UINT(pf_nvuint8, uint8_t, UINT8_MAX)
-PV_NV_IMPL_UINT(pf_nvuint16, uint16_t, UINT16_MAX);
-PV_NV_IMPL_UINT(pf_nvuint32, uint32_t, UINT32_MAX)
+PV_NV_IMPL_UINT(uint8, uint8_t, UINT8_MAX)
+PV_NV_IMPL_UINT(uint16, uint16_t, UINT16_MAX);
+PV_NV_IMPL_UINT(uint32, uint32_t, UINT32_MAX)
int
pf_nvint(const nvlist_t *nvl, const char *name, int *val)
diff --git a/sys/netpfil/pf/pf_nv.h b/sys/netpfil/pf/pf_nv.h
index f0db1e880e9e..0a0f9beeef40 100644
--- a/sys/netpfil/pf/pf_nv.h
+++ b/sys/netpfil/pf/pf_nv.h
@@ -36,12 +36,19 @@ int pf_nvint(const nvlist_t *, const char *, int *);
int pf_nvuint8(const nvlist_t *, const char *, uint8_t *);
int pf_nvuint8_array(const nvlist_t *, const char *, uint8_t *,
size_t, size_t *);
+void pf_uint8_array_nv(nvlist_t *, const char *, const uint8_t *,
+ size_t);
int pf_nvuint16(const nvlist_t *, const char *, uint16_t *);
int pf_nvuint16_array(const nvlist_t *, const char *, uint16_t *,
size_t, size_t *);
+void pf_uint16_array_nv(nvlist_t *, const char *, const uint16_t *,
+ size_t);
int pf_nvuint32(const nvlist_t *, const char *, uint32_t *);
int pf_nvuint32_array(const nvlist_t *, const char *, uint32_t *,
size_t, size_t *);
+void pf_uint32_array_nv(nvlist_t *, const char *, const uint32_t *,
+ size_t);
+
int pf_nvstring(const nvlist_t *, const char *, char *, size_t);
#define PFNV_CHK(x) do { \
diff --git a/sys/netpfil/pf/pf_ruleset.c b/sys/netpfil/pf/pf_ruleset.c
index 0cc0c357d59d..ad1b07f69fe6 100644
--- a/sys/netpfil/pf/pf_ruleset.c
+++ b/sys/netpfil/pf/pf_ruleset.c
@@ -337,6 +337,53 @@ pf_kanchor_setup(struct pf_krule *r, const struct pf_kruleset *s,
}
int
+pf_kanchor_nvcopyout(const struct pf_kruleset *rs, const struct pf_krule *r,
+ nvlist_t *nvl)
+{
+ char anchor_call[MAXPATHLEN] = { 0 };
+
+ if (r->anchor == NULL)
+ goto done;
+ if (!r->anchor_relative) {
+ strlcpy(anchor_call, "/", sizeof(anchor_call));
+ strlcat(anchor_call, r->anchor->path,
+ sizeof(anchor_call));
+ } else {
+ char a[MAXPATHLEN];
+ char *p;
+ int i;
+ if (rs->anchor == NULL)
+ a[0] = 0;
+ else
+ strlcpy(a, rs->anchor->path, MAXPATHLEN);
+ for (i = 1; i < r->anchor_relative; ++i) {
+ if ((p = strrchr(a, '/')) == NULL)
+ p = a;
+ *p = 0;
+ strlcat(anchor_call, "../",
+ sizeof(anchor_call));
+ }
+ if (strncmp(a, r->anchor->path, strlen(a))) {
+ printf("pf_anchor_copyout: '%s' '%s'\n", a,
+ r->anchor->path);
+ return (1);
+ }
+ if (strlen(r->anchor->path) > strlen(a))
+ strlcat(anchor_call, r->anchor->path + (a[0] ?
+ strlen(a) + 1 : 0), sizeof(anchor_call));
+
+ }
+ if (r->anchor_wildcard)
+ strlcat(anchor_call, anchor_call[0] ? "/*" : "*",
+ sizeof(anchor_call));
+
+done:
+ nvlist_add_string(nvl, "anchor_call", anchor_call);
+
+ return (0);
+}
+
+int
pf_kanchor_copyout(const struct pf_kruleset *rs, const struct pf_krule *r,
struct pfioc_rule *pr)
{