pf: Implement nvlist variant of DIOCGETRULE
MFC after: 4 weeks Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D29559
This commit is contained in:
parent
5c11c5a365
commit
d710367d11
@ -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>
|
||||
@ -1233,6 +1234,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)
|
||||
@ -1636,6 +1638,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 *);
|
||||
|
@ -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)
|
||||
{
|
||||
@ -2188,6 +2452,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:
|
||||
@ -2269,6 +2534,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:
|
||||
@ -2494,6 +2760,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;
|
||||
|
@ -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)
|
||||
|
@ -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 { \
|
||||
|
@ -336,6 +336,53 @@ pf_kanchor_setup(struct pf_krule *r, const struct pf_kruleset *s,
|
||||
return (0);
|
||||
}
|
||||
|
||||
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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user