15c62ededSKristof Provost /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
35c62ededSKristof Provost *
45c62ededSKristof Provost * Copyright (c) 2021 Rubicon Communications, LLC (Netgate)
55c62ededSKristof Provost *
65c62ededSKristof Provost * Redistribution and use in source and binary forms, with or without
75c62ededSKristof Provost * modification, are permitted provided that the following conditions
85c62ededSKristof Provost * are met:
95c62ededSKristof Provost * 1. Redistributions of source code must retain the above copyright
105c62ededSKristof Provost * notice, this list of conditions and the following disclaimer.
115c62ededSKristof Provost * 2. Redistributions in binary form must reproduce the above copyright
125c62ededSKristof Provost * notice, this list of conditions and the following disclaimer in the
135c62ededSKristof Provost * documentation and/or other materials provided with the distribution.
145c62ededSKristof Provost *
155c62ededSKristof Provost * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
165c62ededSKristof Provost * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
175c62ededSKristof Provost * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
185c62ededSKristof Provost * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
195c62ededSKristof Provost * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
205c62ededSKristof Provost * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
215c62ededSKristof Provost * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
225c62ededSKristof Provost * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
235c62ededSKristof Provost * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
245c62ededSKristof Provost * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
255c62ededSKristof Provost * SUCH DAMAGE.
265c62ededSKristof Provost *
275c62ededSKristof Provost */
285c62ededSKristof Provost #include <sys/cdefs.h>
293032c353SKristof Provost #include "opt_inet.h"
303032c353SKristof Provost #include "opt_inet6.h"
313032c353SKristof Provost
325c62ededSKristof Provost #include <sys/param.h>
335c62ededSKristof Provost #include <sys/errno.h>
345c62ededSKristof Provost #include <sys/limits.h>
353032c353SKristof Provost #include <sys/queue.h>
365c62ededSKristof Provost #include <sys/systm.h>
375c62ededSKristof Provost
385c62ededSKristof Provost #include <netpfil/pf/pf_nv.h>
395c62ededSKristof Provost
40eaabed8aSKristof Provost #define PF_NV_IMPL_UINT(fnname, type, max) \
415c62ededSKristof Provost int \
427c434289SKristof Provost pf_nv ## fnname ## _opt(const nvlist_t *nvl, const char *name, \
437c434289SKristof Provost type *val, type dflt) \
447c434289SKristof Provost { \
457c434289SKristof Provost uint64_t raw; \
467c434289SKristof Provost if (! nvlist_exists_number(nvl, name)) { \
477c434289SKristof Provost *val = dflt; \
487c434289SKristof Provost return (0); \
497c434289SKristof Provost } \
507c434289SKristof Provost raw = nvlist_get_number(nvl, name); \
517c434289SKristof Provost if (raw > max) \
527c434289SKristof Provost return (ERANGE); \
537c434289SKristof Provost *val = (type)raw; \
547c434289SKristof Provost return (0); \
557c434289SKristof Provost } \
567c434289SKristof Provost int \
57d710367dSKristof Provost pf_nv ## fnname(const nvlist_t *nvl, const char *name, type *val) \
585c62ededSKristof Provost { \
595c62ededSKristof Provost uint64_t raw; \
605c62ededSKristof Provost if (! nvlist_exists_number(nvl, name)) \
615c62ededSKristof Provost return (EINVAL); \
625c62ededSKristof Provost raw = nvlist_get_number(nvl, name); \
635c62ededSKristof Provost if (raw > max) \
645c62ededSKristof Provost return (ERANGE); \
655c62ededSKristof Provost *val = (type)raw; \
665c62ededSKristof Provost return (0); \
675c62ededSKristof Provost } \
685c62ededSKristof Provost int \
69d710367dSKristof Provost pf_nv ## fnname ## _array(const nvlist_t *nvl, const char *name, \
70d710367dSKristof Provost type *array, size_t maxelems, size_t *nelems) \
715c62ededSKristof Provost { \
725c62ededSKristof Provost const uint64_t *n; \
735c62ededSKristof Provost size_t nitems; \
745c62ededSKristof Provost bzero(array, sizeof(type) * maxelems); \
755c62ededSKristof Provost if (! nvlist_exists_number_array(nvl, name)) \
765c62ededSKristof Provost return (EINVAL); \
775c62ededSKristof Provost n = nvlist_get_number_array(nvl, name, &nitems); \
7876c8f202SKristof Provost if (nitems > maxelems) \
795c62ededSKristof Provost return (E2BIG); \
805c62ededSKristof Provost if (nelems != NULL) \
815c62ededSKristof Provost *nelems = nitems; \
825c62ededSKristof Provost for (size_t i = 0; i < nitems; i++) { \
835c62ededSKristof Provost if (n[i] > max) \
845c62ededSKristof Provost return (ERANGE); \
855c62ededSKristof Provost array[i] = (type)n[i]; \
865c62ededSKristof Provost } \
875c62ededSKristof Provost return (0); \
88d710367dSKristof Provost } \
89d710367dSKristof Provost void \
90d710367dSKristof Provost pf_ ## fnname ## _array_nv(nvlist_t *nvl, const char *name, \
91d710367dSKristof Provost const type *numbers, size_t count) \
92d710367dSKristof Provost { \
93d710367dSKristof Provost uint64_t tmp; \
94d710367dSKristof Provost for (size_t i = 0; i < count; i++) { \
95d710367dSKristof Provost tmp = numbers[i]; \
96d710367dSKristof Provost nvlist_append_number_array(nvl, name, tmp); \
97d710367dSKristof Provost } \
985c62ededSKristof Provost }
99d710367dSKristof Provost
1005c62ededSKristof Provost int
pf_nvbool(const nvlist_t * nvl,const char * name,bool * val)101776df104SKristof Provost pf_nvbool(const nvlist_t *nvl, const char *name, bool *val)
102776df104SKristof Provost {
103776df104SKristof Provost if (! nvlist_exists_bool(nvl, name))
104776df104SKristof Provost return (EINVAL);
105776df104SKristof Provost
106776df104SKristof Provost *val = nvlist_get_bool(nvl, name);
107776df104SKristof Provost
108776df104SKristof Provost return (0);
109776df104SKristof Provost }
110776df104SKristof Provost
111776df104SKristof Provost int
pf_nvbinary(const nvlist_t * nvl,const char * name,void * data,size_t expected_size)1125c62ededSKristof Provost pf_nvbinary(const nvlist_t *nvl, const char *name, void *data,
1135c62ededSKristof Provost size_t expected_size)
1145c62ededSKristof Provost {
1155c62ededSKristof Provost const uint8_t *nvdata;
1165c62ededSKristof Provost size_t len;
1175c62ededSKristof Provost
1185c62ededSKristof Provost bzero(data, expected_size);
1195c62ededSKristof Provost
1205c62ededSKristof Provost if (! nvlist_exists_binary(nvl, name))
1215c62ededSKristof Provost return (EINVAL);
1225c62ededSKristof Provost
1235c62ededSKristof Provost nvdata = (const uint8_t *)nvlist_get_binary(nvl, name, &len);
1245c62ededSKristof Provost if (len > expected_size)
1255c62ededSKristof Provost return (EINVAL);
1265c62ededSKristof Provost
1275c62ededSKristof Provost memcpy(data, nvdata, len);
1285c62ededSKristof Provost
1295c62ededSKristof Provost return (0);
1305c62ededSKristof Provost }
1315c62ededSKristof Provost
132eaabed8aSKristof Provost PF_NV_IMPL_UINT(uint8, uint8_t, UINT8_MAX);
133eaabed8aSKristof Provost PF_NV_IMPL_UINT(uint16, uint16_t, UINT16_MAX);
134eaabed8aSKristof Provost PF_NV_IMPL_UINT(uint32, uint32_t, UINT32_MAX);
1357606a45dSKristof Provost PF_NV_IMPL_UINT(uint64, uint64_t, UINT64_MAX);
1365c62ededSKristof Provost
1375c62ededSKristof Provost int
pf_nvint(const nvlist_t * nvl,const char * name,int * val)1385c62ededSKristof Provost pf_nvint(const nvlist_t *nvl, const char *name, int *val)
1395c62ededSKristof Provost {
1405c62ededSKristof Provost int64_t raw;
1415c62ededSKristof Provost
1425c62ededSKristof Provost if (! nvlist_exists_number(nvl, name))
1435c62ededSKristof Provost return (EINVAL);
1445c62ededSKristof Provost
1455c62ededSKristof Provost raw = nvlist_get_number(nvl, name);
1465c62ededSKristof Provost if (raw > INT_MAX || raw < INT_MIN)
1475c62ededSKristof Provost return (ERANGE);
1485c62ededSKristof Provost
1495c62ededSKristof Provost *val = (int)raw;
1505c62ededSKristof Provost
1515c62ededSKristof Provost return (0);
1525c62ededSKristof Provost }
1535c62ededSKristof Provost
1545c62ededSKristof Provost int
pf_nvstring(const nvlist_t * nvl,const char * name,char * str,size_t maxlen)1555c62ededSKristof Provost pf_nvstring(const nvlist_t *nvl, const char *name, char *str, size_t maxlen)
1565c62ededSKristof Provost {
1575c62ededSKristof Provost int ret;
1585c62ededSKristof Provost
1595c62ededSKristof Provost if (! nvlist_exists_string(nvl, name))
1605c62ededSKristof Provost return (EINVAL);
1615c62ededSKristof Provost
1625c62ededSKristof Provost ret = strlcpy(str, nvlist_get_string(nvl, name), maxlen);
1635c62ededSKristof Provost if (ret >= maxlen)
1645c62ededSKristof Provost return (EINVAL);
1655c62ededSKristof Provost
1665c62ededSKristof Provost return (0);
1675c62ededSKristof Provost }
1683032c353SKristof Provost
1693032c353SKristof Provost static int
pf_nvaddr_to_addr(const nvlist_t * nvl,struct pf_addr * paddr)1703032c353SKristof Provost pf_nvaddr_to_addr(const nvlist_t *nvl, struct pf_addr *paddr)
1713032c353SKristof Provost {
1723032c353SKristof Provost return (pf_nvbinary(nvl, "addr", paddr, sizeof(*paddr)));
1733032c353SKristof Provost }
1743032c353SKristof Provost
1753032c353SKristof Provost static nvlist_t *
pf_addr_to_nvaddr(const struct pf_addr * paddr)1763032c353SKristof Provost pf_addr_to_nvaddr(const struct pf_addr *paddr)
1773032c353SKristof Provost {
1783032c353SKristof Provost nvlist_t *nvl;
1793032c353SKristof Provost
1803032c353SKristof Provost nvl = nvlist_create(0);
1813032c353SKristof Provost if (nvl == NULL)
1823032c353SKristof Provost return (NULL);
1833032c353SKristof Provost
1843032c353SKristof Provost nvlist_add_binary(nvl, "addr", paddr, sizeof(*paddr));
1853032c353SKristof Provost
1863032c353SKristof Provost return (nvl);
1873032c353SKristof Provost }
1883032c353SKristof Provost
1893032c353SKristof Provost static int
pf_nvmape_to_mape(const nvlist_t * nvl,struct pf_mape_portset * mape)1903032c353SKristof Provost pf_nvmape_to_mape(const nvlist_t *nvl, struct pf_mape_portset *mape)
1913032c353SKristof Provost {
1923032c353SKristof Provost int error = 0;
1933032c353SKristof Provost
1943032c353SKristof Provost bzero(mape, sizeof(*mape));
1953032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "offset", &mape->offset));
1963032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "psidlen", &mape->psidlen));
1973032c353SKristof Provost PFNV_CHK(pf_nvuint16(nvl, "psid", &mape->psid));
1983032c353SKristof Provost
1993032c353SKristof Provost errout:
2003032c353SKristof Provost return (error);
2013032c353SKristof Provost }
2023032c353SKristof Provost
2033032c353SKristof Provost static nvlist_t *
pf_mape_to_nvmape(const struct pf_mape_portset * mape)2043032c353SKristof Provost pf_mape_to_nvmape(const struct pf_mape_portset *mape)
2053032c353SKristof Provost {
2063032c353SKristof Provost nvlist_t *nvl;
2073032c353SKristof Provost
2083032c353SKristof Provost nvl = nvlist_create(0);
2093032c353SKristof Provost if (nvl == NULL)
2103032c353SKristof Provost return (NULL);
2113032c353SKristof Provost
2123032c353SKristof Provost nvlist_add_number(nvl, "offset", mape->offset);
2133032c353SKristof Provost nvlist_add_number(nvl, "psidlen", mape->psidlen);
2143032c353SKristof Provost nvlist_add_number(nvl, "psid", mape->psid);
2153032c353SKristof Provost
2163032c353SKristof Provost return (nvl);
2173032c353SKristof Provost }
2183032c353SKristof Provost
2193032c353SKristof Provost static int
pf_nvpool_to_pool(const nvlist_t * nvl,struct pf_kpool * kpool)2203032c353SKristof Provost pf_nvpool_to_pool(const nvlist_t *nvl, struct pf_kpool *kpool)
2213032c353SKristof Provost {
2223032c353SKristof Provost int error = 0;
2233032c353SKristof Provost
2243032c353SKristof Provost PFNV_CHK(pf_nvbinary(nvl, "key", &kpool->key, sizeof(kpool->key)));
2253032c353SKristof Provost
2263032c353SKristof Provost if (nvlist_exists_nvlist(nvl, "counter")) {
2273032c353SKristof Provost PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "counter"),
2283032c353SKristof Provost &kpool->counter));
2293032c353SKristof Provost }
2303032c353SKristof Provost
2313032c353SKristof Provost PFNV_CHK(pf_nvint(nvl, "tblidx", &kpool->tblidx));
2323032c353SKristof Provost PFNV_CHK(pf_nvuint16_array(nvl, "proxy_port", kpool->proxy_port, 2,
2333032c353SKristof Provost NULL));
2343032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "opts", &kpool->opts));
2353032c353SKristof Provost
2363032c353SKristof Provost if (nvlist_exists_nvlist(nvl, "mape")) {
2373032c353SKristof Provost PFNV_CHK(pf_nvmape_to_mape(nvlist_get_nvlist(nvl, "mape"),
2383032c353SKristof Provost &kpool->mape));
2393032c353SKristof Provost }
2403032c353SKristof Provost
2413032c353SKristof Provost errout:
2423032c353SKristof Provost return (error);
2433032c353SKristof Provost }
2443032c353SKristof Provost
2453032c353SKristof Provost static nvlist_t *
pf_pool_to_nvpool(const struct pf_kpool * pool)2463032c353SKristof Provost pf_pool_to_nvpool(const struct pf_kpool *pool)
2473032c353SKristof Provost {
2483032c353SKristof Provost nvlist_t *nvl;
2493032c353SKristof Provost nvlist_t *tmp;
2503032c353SKristof Provost
2513032c353SKristof Provost nvl = nvlist_create(0);
2523032c353SKristof Provost if (nvl == NULL)
2533032c353SKristof Provost return (NULL);
2543032c353SKristof Provost
2553032c353SKristof Provost nvlist_add_binary(nvl, "key", &pool->key, sizeof(pool->key));
2563032c353SKristof Provost tmp = pf_addr_to_nvaddr(&pool->counter);
2573032c353SKristof Provost if (tmp == NULL)
2583032c353SKristof Provost goto error;
2593032c353SKristof Provost nvlist_add_nvlist(nvl, "counter", tmp);
2603032c353SKristof Provost nvlist_destroy(tmp);
2613032c353SKristof Provost
2623032c353SKristof Provost nvlist_add_number(nvl, "tblidx", pool->tblidx);
2633032c353SKristof Provost pf_uint16_array_nv(nvl, "proxy_port", pool->proxy_port, 2);
2643032c353SKristof Provost nvlist_add_number(nvl, "opts", pool->opts);
2653032c353SKristof Provost
2663032c353SKristof Provost tmp = pf_mape_to_nvmape(&pool->mape);
2673032c353SKristof Provost if (tmp == NULL)
2683032c353SKristof Provost goto error;
2693032c353SKristof Provost nvlist_add_nvlist(nvl, "mape", tmp);
2703032c353SKristof Provost nvlist_destroy(tmp);
2713032c353SKristof Provost
2723032c353SKristof Provost return (nvl);
2733032c353SKristof Provost
2743032c353SKristof Provost error:
2753032c353SKristof Provost nvlist_destroy(nvl);
2763032c353SKristof Provost return (NULL);
2773032c353SKristof Provost }
2783032c353SKristof Provost
2793032c353SKristof Provost static int
pf_nvaddr_wrap_to_addr_wrap(const nvlist_t * nvl,struct pf_addr_wrap * addr)2803032c353SKristof Provost pf_nvaddr_wrap_to_addr_wrap(const nvlist_t *nvl, struct pf_addr_wrap *addr)
2813032c353SKristof Provost {
2823032c353SKristof Provost int error = 0;
2833032c353SKristof Provost
2843032c353SKristof Provost bzero(addr, sizeof(*addr));
2853032c353SKristof Provost
2863032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "type", &addr->type));
2873032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "iflags", &addr->iflags));
2883032c353SKristof Provost if (addr->type == PF_ADDR_DYNIFTL)
2893032c353SKristof Provost PFNV_CHK(pf_nvstring(nvl, "ifname", addr->v.ifname,
2903032c353SKristof Provost sizeof(addr->v.ifname)));
2913032c353SKristof Provost if (addr->type == PF_ADDR_TABLE)
2923032c353SKristof Provost PFNV_CHK(pf_nvstring(nvl, "tblname", addr->v.tblname,
2933032c353SKristof Provost sizeof(addr->v.tblname)));
2943032c353SKristof Provost
2953032c353SKristof Provost if (! nvlist_exists_nvlist(nvl, "addr"))
2963032c353SKristof Provost return (EINVAL);
2973032c353SKristof Provost PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "addr"),
2983032c353SKristof Provost &addr->v.a.addr));
2993032c353SKristof Provost
3003032c353SKristof Provost if (! nvlist_exists_nvlist(nvl, "mask"))
3013032c353SKristof Provost return (EINVAL);
3023032c353SKristof Provost PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "mask"),
3033032c353SKristof Provost &addr->v.a.mask));
3043032c353SKristof Provost
3053032c353SKristof Provost switch (addr->type) {
3063032c353SKristof Provost case PF_ADDR_DYNIFTL:
3073032c353SKristof Provost case PF_ADDR_TABLE:
3083032c353SKristof Provost case PF_ADDR_RANGE:
3093032c353SKristof Provost case PF_ADDR_ADDRMASK:
3103032c353SKristof Provost case PF_ADDR_NOROUTE:
3113032c353SKristof Provost case PF_ADDR_URPFFAILED:
3123032c353SKristof Provost break;
3133032c353SKristof Provost default:
3143032c353SKristof Provost return (EINVAL);
3153032c353SKristof Provost }
3163032c353SKristof Provost
3173032c353SKristof Provost errout:
3183032c353SKristof Provost return (error);
3193032c353SKristof Provost }
3203032c353SKristof Provost
3213032c353SKristof Provost static nvlist_t *
pf_addr_wrap_to_nvaddr_wrap(const struct pf_addr_wrap * addr)3223032c353SKristof Provost pf_addr_wrap_to_nvaddr_wrap(const struct pf_addr_wrap *addr)
3233032c353SKristof Provost {
3243032c353SKristof Provost nvlist_t *nvl;
3253032c353SKristof Provost nvlist_t *tmp;
326218a8a49SKristof Provost uint64_t num;
327218a8a49SKristof Provost struct pfr_ktable *kt;
3283032c353SKristof Provost
3293032c353SKristof Provost nvl = nvlist_create(0);
3303032c353SKristof Provost if (nvl == NULL)
3313032c353SKristof Provost return (NULL);
3323032c353SKristof Provost
3333032c353SKristof Provost nvlist_add_number(nvl, "type", addr->type);
3343032c353SKristof Provost nvlist_add_number(nvl, "iflags", addr->iflags);
335218a8a49SKristof Provost if (addr->type == PF_ADDR_DYNIFTL) {
3363032c353SKristof Provost nvlist_add_string(nvl, "ifname", addr->v.ifname);
337218a8a49SKristof Provost num = 0;
338218a8a49SKristof Provost if (addr->p.dyn != NULL)
339218a8a49SKristof Provost num = addr->p.dyn->pfid_acnt4 +
340218a8a49SKristof Provost addr->p.dyn->pfid_acnt6;
341218a8a49SKristof Provost nvlist_add_number(nvl, "dyncnt", num);
342218a8a49SKristof Provost }
343218a8a49SKristof Provost if (addr->type == PF_ADDR_TABLE) {
3443032c353SKristof Provost nvlist_add_string(nvl, "tblname", addr->v.tblname);
345218a8a49SKristof Provost num = -1;
346218a8a49SKristof Provost kt = addr->p.tbl;
347218a8a49SKristof Provost if ((kt->pfrkt_flags & PFR_TFLAG_ACTIVE) &&
348218a8a49SKristof Provost kt->pfrkt_root != NULL)
349218a8a49SKristof Provost kt = kt->pfrkt_root;
350218a8a49SKristof Provost if (kt->pfrkt_flags & PFR_TFLAG_ACTIVE)
351218a8a49SKristof Provost num = kt->pfrkt_cnt;
352218a8a49SKristof Provost nvlist_add_number(nvl, "tblcnt", num);
353218a8a49SKristof Provost }
3543032c353SKristof Provost
3553032c353SKristof Provost tmp = pf_addr_to_nvaddr(&addr->v.a.addr);
3563032c353SKristof Provost if (tmp == NULL)
3573032c353SKristof Provost goto error;
3583032c353SKristof Provost nvlist_add_nvlist(nvl, "addr", tmp);
3593032c353SKristof Provost nvlist_destroy(tmp);
3603032c353SKristof Provost tmp = pf_addr_to_nvaddr(&addr->v.a.mask);
3613032c353SKristof Provost if (tmp == NULL)
3623032c353SKristof Provost goto error;
3633032c353SKristof Provost nvlist_add_nvlist(nvl, "mask", tmp);
3643032c353SKristof Provost nvlist_destroy(tmp);
3653032c353SKristof Provost
3663032c353SKristof Provost return (nvl);
3673032c353SKristof Provost
3683032c353SKristof Provost error:
3693032c353SKristof Provost nvlist_destroy(nvl);
3703032c353SKristof Provost return (NULL);
3713032c353SKristof Provost }
3723032c353SKristof Provost
3733032c353SKristof Provost static int
pf_validate_op(uint8_t op)3743032c353SKristof Provost pf_validate_op(uint8_t op)
3753032c353SKristof Provost {
3763032c353SKristof Provost switch (op) {
3773032c353SKristof Provost case PF_OP_NONE:
3783032c353SKristof Provost case PF_OP_IRG:
3793032c353SKristof Provost case PF_OP_EQ:
3803032c353SKristof Provost case PF_OP_NE:
3813032c353SKristof Provost case PF_OP_LT:
3823032c353SKristof Provost case PF_OP_LE:
3833032c353SKristof Provost case PF_OP_GT:
3843032c353SKristof Provost case PF_OP_GE:
3853032c353SKristof Provost case PF_OP_XRG:
3863032c353SKristof Provost case PF_OP_RRG:
3873032c353SKristof Provost break;
3883032c353SKristof Provost default:
3893032c353SKristof Provost return (EINVAL);
3903032c353SKristof Provost }
3913032c353SKristof Provost
3923032c353SKristof Provost return (0);
3933032c353SKristof Provost }
3943032c353SKristof Provost
3953032c353SKristof Provost static int
pf_nvrule_addr_to_rule_addr(const nvlist_t * nvl,struct pf_rule_addr * addr)3963032c353SKristof Provost pf_nvrule_addr_to_rule_addr(const nvlist_t *nvl, struct pf_rule_addr *addr)
3973032c353SKristof Provost {
3983032c353SKristof Provost int error = 0;
3993032c353SKristof Provost
4003032c353SKristof Provost if (! nvlist_exists_nvlist(nvl, "addr"))
4013032c353SKristof Provost return (EINVAL);
4023032c353SKristof Provost
4033032c353SKristof Provost PFNV_CHK(pf_nvaddr_wrap_to_addr_wrap(nvlist_get_nvlist(nvl, "addr"),
4043032c353SKristof Provost &addr->addr));
4053032c353SKristof Provost PFNV_CHK(pf_nvuint16_array(nvl, "port", addr->port, 2, NULL));
4063032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "neg", &addr->neg));
4073032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "port_op", &addr->port_op));
4083032c353SKristof Provost
4093032c353SKristof Provost PFNV_CHK(pf_validate_op(addr->port_op));
4103032c353SKristof Provost
4113032c353SKristof Provost errout:
4123032c353SKristof Provost return (error);
4133032c353SKristof Provost }
4143032c353SKristof Provost
4153032c353SKristof Provost static nvlist_t *
pf_rule_addr_to_nvrule_addr(const struct pf_rule_addr * addr)4163032c353SKristof Provost pf_rule_addr_to_nvrule_addr(const struct pf_rule_addr *addr)
4173032c353SKristof Provost {
4183032c353SKristof Provost nvlist_t *nvl;
4193032c353SKristof Provost nvlist_t *tmp;
4203032c353SKristof Provost
4213032c353SKristof Provost nvl = nvlist_create(0);
4223032c353SKristof Provost if (nvl == NULL)
4233032c353SKristof Provost return (NULL);
4243032c353SKristof Provost
4253032c353SKristof Provost tmp = pf_addr_wrap_to_nvaddr_wrap(&addr->addr);
4263032c353SKristof Provost if (tmp == NULL)
4273032c353SKristof Provost goto error;
4283032c353SKristof Provost nvlist_add_nvlist(nvl, "addr", tmp);
4293032c353SKristof Provost nvlist_destroy(tmp);
4303032c353SKristof Provost pf_uint16_array_nv(nvl, "port", addr->port, 2);
4313032c353SKristof Provost nvlist_add_number(nvl, "neg", addr->neg);
4323032c353SKristof Provost nvlist_add_number(nvl, "port_op", addr->port_op);
4333032c353SKristof Provost
4343032c353SKristof Provost return (nvl);
4353032c353SKristof Provost
4363032c353SKristof Provost error:
4373032c353SKristof Provost nvlist_destroy(nvl);
4383032c353SKristof Provost return (NULL);
4393032c353SKristof Provost }
4403032c353SKristof Provost
4413032c353SKristof Provost static int
pf_nvrule_uid_to_rule_uid(const nvlist_t * nvl,struct pf_rule_uid * uid)4423032c353SKristof Provost pf_nvrule_uid_to_rule_uid(const nvlist_t *nvl, struct pf_rule_uid *uid)
4433032c353SKristof Provost {
4443032c353SKristof Provost int error = 0;
4453032c353SKristof Provost
4463032c353SKristof Provost bzero(uid, sizeof(*uid));
4473032c353SKristof Provost
4483032c353SKristof Provost PFNV_CHK(pf_nvuint32_array(nvl, "uid", uid->uid, 2, NULL));
4493032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "op", &uid->op));
4503032c353SKristof Provost
4513032c353SKristof Provost PFNV_CHK(pf_validate_op(uid->op));
4523032c353SKristof Provost
4533032c353SKristof Provost errout:
4543032c353SKristof Provost return (error);
4553032c353SKristof Provost }
4563032c353SKristof Provost
4573032c353SKristof Provost static nvlist_t *
pf_rule_uid_to_nvrule_uid(const struct pf_rule_uid * uid)4583032c353SKristof Provost pf_rule_uid_to_nvrule_uid(const struct pf_rule_uid *uid)
4593032c353SKristof Provost {
4603032c353SKristof Provost nvlist_t *nvl;
4613032c353SKristof Provost
4623032c353SKristof Provost nvl = nvlist_create(0);
4633032c353SKristof Provost if (nvl == NULL)
4643032c353SKristof Provost return (NULL);
4653032c353SKristof Provost
4663032c353SKristof Provost pf_uint32_array_nv(nvl, "uid", uid->uid, 2);
4673032c353SKristof Provost nvlist_add_number(nvl, "op", uid->op);
4683032c353SKristof Provost
4693032c353SKristof Provost return (nvl);
4703032c353SKristof Provost }
4713032c353SKristof Provost
4723032c353SKristof Provost static int
pf_nvrule_gid_to_rule_gid(const nvlist_t * nvl,struct pf_rule_gid * gid)4733032c353SKristof Provost pf_nvrule_gid_to_rule_gid(const nvlist_t *nvl, struct pf_rule_gid *gid)
4743032c353SKristof Provost {
4753032c353SKristof Provost /* Cheat a little. These stucts are the same, other than the name of
4763032c353SKristof Provost * the first field. */
4773032c353SKristof Provost return (pf_nvrule_uid_to_rule_uid(nvl, (struct pf_rule_uid *)gid));
4783032c353SKristof Provost }
4793032c353SKristof Provost
4803032c353SKristof Provost int
pf_check_rule_addr(const struct pf_rule_addr * addr)4813032c353SKristof Provost pf_check_rule_addr(const struct pf_rule_addr *addr)
4823032c353SKristof Provost {
4833032c353SKristof Provost
4843032c353SKristof Provost switch (addr->addr.type) {
4853032c353SKristof Provost case PF_ADDR_ADDRMASK:
4863032c353SKristof Provost case PF_ADDR_NOROUTE:
4873032c353SKristof Provost case PF_ADDR_DYNIFTL:
4883032c353SKristof Provost case PF_ADDR_TABLE:
4893032c353SKristof Provost case PF_ADDR_URPFFAILED:
4903032c353SKristof Provost case PF_ADDR_RANGE:
4913032c353SKristof Provost break;
4923032c353SKristof Provost default:
4933032c353SKristof Provost return (EINVAL);
4943032c353SKristof Provost }
4953032c353SKristof Provost
4963032c353SKristof Provost if (addr->addr.p.dyn != NULL) {
4973032c353SKristof Provost return (EINVAL);
4983032c353SKristof Provost }
4993032c353SKristof Provost
5003032c353SKristof Provost return (0);
5013032c353SKristof Provost }
5023032c353SKristof Provost
5033032c353SKristof Provost
5043032c353SKristof Provost int
pf_nvrule_to_krule(const nvlist_t * nvl,struct pf_krule * rule)5053032c353SKristof Provost pf_nvrule_to_krule(const nvlist_t *nvl, struct pf_krule *rule)
5063032c353SKristof Provost {
5073032c353SKristof Provost int error = 0;
5083032c353SKristof Provost
5093032c353SKristof Provost #define ERROUT(x) ERROUT_FUNCTION(errout, x)
5103032c353SKristof Provost
5113032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "nr", &rule->nr));
5123032c353SKristof Provost
5133032c353SKristof Provost if (! nvlist_exists_nvlist(nvl, "src"))
5143032c353SKristof Provost ERROUT(EINVAL);
5153032c353SKristof Provost
5163032c353SKristof Provost error = pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "src"),
5173032c353SKristof Provost &rule->src);
5183032c353SKristof Provost if (error != 0)
5193032c353SKristof Provost ERROUT(error);
5203032c353SKristof Provost
5213032c353SKristof Provost if (! nvlist_exists_nvlist(nvl, "dst"))
5223032c353SKristof Provost ERROUT(EINVAL);
5233032c353SKristof Provost
5243032c353SKristof Provost PFNV_CHK(pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "dst"),
5253032c353SKristof Provost &rule->dst));
5263032c353SKristof Provost
5273032c353SKristof Provost if (nvlist_exists_string(nvl, "label")) {
5283032c353SKristof Provost PFNV_CHK(pf_nvstring(nvl, "label", rule->label[0],
5293032c353SKristof Provost sizeof(rule->label[0])));
5303032c353SKristof Provost } else if (nvlist_exists_string_array(nvl, "labels")) {
5313032c353SKristof Provost const char *const *strs;
5323032c353SKristof Provost size_t items;
5333032c353SKristof Provost int ret;
5343032c353SKristof Provost
5353032c353SKristof Provost strs = nvlist_get_string_array(nvl, "labels", &items);
5363032c353SKristof Provost if (items > PF_RULE_MAX_LABEL_COUNT)
5373032c353SKristof Provost ERROUT(E2BIG);
5383032c353SKristof Provost
5393032c353SKristof Provost for (size_t i = 0; i < items; i++) {
5403032c353SKristof Provost ret = strlcpy(rule->label[i], strs[i],
5413032c353SKristof Provost sizeof(rule->label[0]));
5423032c353SKristof Provost if (ret >= sizeof(rule->label[0]))
5433032c353SKristof Provost ERROUT(E2BIG);
5443032c353SKristof Provost }
5453032c353SKristof Provost }
5463032c353SKristof Provost
54776c5eeccSKristof Provost PFNV_CHK(pf_nvuint32_opt(nvl, "ridentifier", &rule->ridentifier, 0));
5483032c353SKristof Provost PFNV_CHK(pf_nvstring(nvl, "ifname", rule->ifname,
5493032c353SKristof Provost sizeof(rule->ifname)));
5503032c353SKristof Provost PFNV_CHK(pf_nvstring(nvl, "qname", rule->qname, sizeof(rule->qname)));
5513032c353SKristof Provost PFNV_CHK(pf_nvstring(nvl, "pqname", rule->pqname,
5523032c353SKristof Provost sizeof(rule->pqname)));
5533032c353SKristof Provost PFNV_CHK(pf_nvstring(nvl, "tagname", rule->tagname,
5543032c353SKristof Provost sizeof(rule->tagname)));
55563b3c1c7SKristof Provost PFNV_CHK(pf_nvuint16_opt(nvl, "dnpipe", &rule->dnpipe, 0));
55663b3c1c7SKristof Provost PFNV_CHK(pf_nvuint16_opt(nvl, "dnrpipe", &rule->dnrpipe, 0));
55763b3c1c7SKristof Provost PFNV_CHK(pf_nvuint32_opt(nvl, "dnflags", &rule->free_flags, 0));
5583032c353SKristof Provost PFNV_CHK(pf_nvstring(nvl, "match_tagname", rule->match_tagname,
5593032c353SKristof Provost sizeof(rule->match_tagname)));
5603032c353SKristof Provost PFNV_CHK(pf_nvstring(nvl, "overload_tblname", rule->overload_tblname,
5613032c353SKristof Provost sizeof(rule->overload_tblname)));
5623032c353SKristof Provost
5633032c353SKristof Provost if (! nvlist_exists_nvlist(nvl, "rpool"))
5643032c353SKristof Provost ERROUT(EINVAL);
5653032c353SKristof Provost PFNV_CHK(pf_nvpool_to_pool(nvlist_get_nvlist(nvl, "rpool"),
566e11dacbfSKristof Provost &rule->rdr));
5673032c353SKristof Provost
5683032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "os_fingerprint", &rule->os_fingerprint));
5693032c353SKristof Provost
5703032c353SKristof Provost PFNV_CHK(pf_nvint(nvl, "rtableid", &rule->rtableid));
5713032c353SKristof Provost PFNV_CHK(pf_nvuint32_array(nvl, "timeout", rule->timeout, PFTM_MAX, NULL));
5723032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "max_states", &rule->max_states));
5733032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "max_src_nodes", &rule->max_src_nodes));
5743032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "max_src_states", &rule->max_src_states));
5753032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "max_src_conn", &rule->max_src_conn));
5763032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "max_src_conn_rate.limit",
5773032c353SKristof Provost &rule->max_src_conn_rate.limit));
5783032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "max_src_conn_rate.seconds",
5793032c353SKristof Provost &rule->max_src_conn_rate.seconds));
5803032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "prob", &rule->prob));
5813032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "cuid", &rule->cuid));
5823032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "cpid", &rule->cpid));
5833032c353SKristof Provost
5843032c353SKristof Provost PFNV_CHK(pf_nvuint16(nvl, "return_icmp", &rule->return_icmp));
5853032c353SKristof Provost PFNV_CHK(pf_nvuint16(nvl, "return_icmp6", &rule->return_icmp6));
5863032c353SKristof Provost
5873032c353SKristof Provost PFNV_CHK(pf_nvuint16(nvl, "max_mss", &rule->max_mss));
5883032c353SKristof Provost PFNV_CHK(pf_nvuint16(nvl, "scrub_flags", &rule->scrub_flags));
5893032c353SKristof Provost
5903032c353SKristof Provost if (! nvlist_exists_nvlist(nvl, "uid"))
5913032c353SKristof Provost ERROUT(EINVAL);
5923032c353SKristof Provost PFNV_CHK(pf_nvrule_uid_to_rule_uid(nvlist_get_nvlist(nvl, "uid"),
5933032c353SKristof Provost &rule->uid));
5943032c353SKristof Provost
5953032c353SKristof Provost if (! nvlist_exists_nvlist(nvl, "gid"))
5963032c353SKristof Provost ERROUT(EINVAL);
5973032c353SKristof Provost PFNV_CHK(pf_nvrule_gid_to_rule_gid(nvlist_get_nvlist(nvl, "gid"),
5983032c353SKristof Provost &rule->gid));
5993032c353SKristof Provost
6003032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "rule_flag", &rule->rule_flag));
6013032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "action", &rule->action));
6023032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "direction", &rule->direction));
6033032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "log", &rule->log));
6043032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "logif", &rule->logif));
6053032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "quick", &rule->quick));
6063032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "ifnot", &rule->ifnot));
6073032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "match_tag_not", &rule->match_tag_not));
6083032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "natpass", &rule->natpass));
6093032c353SKristof Provost
6103032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "keep_state", &rule->keep_state));
6113032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "af", &rule->af));
6123032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "proto", &rule->proto));
6133032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "type", &rule->type));
6143032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "code", &rule->code));
6153032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "flags", &rule->flags));
6163032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "flagset", &rule->flagset));
6173032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "min_ttl", &rule->min_ttl));
6183032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "allow_opts", &rule->allow_opts));
6193032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "rt", &rule->rt));
6203032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "return_ttl", &rule->return_ttl));
6213032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "tos", &rule->tos));
6223032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "set_tos", &rule->set_tos));
6233032c353SKristof Provost
6243032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "flush", &rule->flush));
6253032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "prio", &rule->prio));
6263032c353SKristof Provost
6270143a6bbSFranco Fichtner PFNV_CHK(pf_nvuint8_array(nvl, "set_prio", rule->set_prio, 2, NULL));
6283032c353SKristof Provost
6293032c353SKristof Provost if (nvlist_exists_nvlist(nvl, "divert")) {
6303032c353SKristof Provost const nvlist_t *nvldivert = nvlist_get_nvlist(nvl, "divert");
6313032c353SKristof Provost
6323032c353SKristof Provost if (! nvlist_exists_nvlist(nvldivert, "addr"))
6333032c353SKristof Provost ERROUT(EINVAL);
6343032c353SKristof Provost PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvldivert, "addr"),
6353032c353SKristof Provost &rule->divert.addr));
6363032c353SKristof Provost PFNV_CHK(pf_nvuint16(nvldivert, "port", &rule->divert.port));
6373032c353SKristof Provost }
6383032c353SKristof Provost
6393032c353SKristof Provost /* Validation */
6403032c353SKristof Provost #ifndef INET
6413032c353SKristof Provost if (rule->af == AF_INET)
6423032c353SKristof Provost ERROUT(EAFNOSUPPORT);
6433032c353SKristof Provost #endif /* INET */
6443032c353SKristof Provost #ifndef INET6
6453032c353SKristof Provost if (rule->af == AF_INET6)
6463032c353SKristof Provost ERROUT(EAFNOSUPPORT);
6473032c353SKristof Provost #endif /* INET6 */
6483032c353SKristof Provost
6493032c353SKristof Provost PFNV_CHK(pf_check_rule_addr(&rule->src));
6503032c353SKristof Provost PFNV_CHK(pf_check_rule_addr(&rule->dst));
6513032c353SKristof Provost
6523032c353SKristof Provost return (0);
6533032c353SKristof Provost
6543032c353SKristof Provost #undef ERROUT
6553032c353SKristof Provost errout:
6563032c353SKristof Provost return (error);
6573032c353SKristof Provost }
6583032c353SKristof Provost
6593032c353SKristof Provost static nvlist_t *
pf_divert_to_nvdivert(const struct pf_krule * rule)6603032c353SKristof Provost pf_divert_to_nvdivert(const struct pf_krule *rule)
6613032c353SKristof Provost {
6623032c353SKristof Provost nvlist_t *nvl;
6633032c353SKristof Provost nvlist_t *tmp;
6643032c353SKristof Provost
6653032c353SKristof Provost nvl = nvlist_create(0);
6663032c353SKristof Provost if (nvl == NULL)
6673032c353SKristof Provost return (NULL);
6683032c353SKristof Provost
6693032c353SKristof Provost tmp = pf_addr_to_nvaddr(&rule->divert.addr);
6703032c353SKristof Provost if (tmp == NULL)
6713032c353SKristof Provost goto error;
6723032c353SKristof Provost nvlist_add_nvlist(nvl, "addr", tmp);
6733032c353SKristof Provost nvlist_destroy(tmp);
6743032c353SKristof Provost nvlist_add_number(nvl, "port", rule->divert.port);
6753032c353SKristof Provost
6763032c353SKristof Provost return (nvl);
6773032c353SKristof Provost
6783032c353SKristof Provost error:
6793032c353SKristof Provost nvlist_destroy(nvl);
6803032c353SKristof Provost return (NULL);
6813032c353SKristof Provost }
6823032c353SKristof Provost
6833032c353SKristof Provost nvlist_t *
pf_krule_to_nvrule(struct pf_krule * rule)68402cf67ccSMateusz Guzik pf_krule_to_nvrule(struct pf_krule *rule)
6853032c353SKristof Provost {
6863032c353SKristof Provost nvlist_t *nvl, *tmp;
687*07e070efSKajetan Staszkiewicz u_int64_t src_nodes_total = 0;
6883032c353SKristof Provost
6893032c353SKristof Provost nvl = nvlist_create(0);
6903032c353SKristof Provost if (nvl == NULL)
6913032c353SKristof Provost return (nvl);
6923032c353SKristof Provost
6933032c353SKristof Provost nvlist_add_number(nvl, "nr", rule->nr);
6943032c353SKristof Provost tmp = pf_rule_addr_to_nvrule_addr(&rule->src);
6953032c353SKristof Provost if (tmp == NULL)
6963032c353SKristof Provost goto error;
6973032c353SKristof Provost nvlist_add_nvlist(nvl, "src", tmp);
6983032c353SKristof Provost nvlist_destroy(tmp);
6993032c353SKristof Provost tmp = pf_rule_addr_to_nvrule_addr(&rule->dst);
7003032c353SKristof Provost if (tmp == NULL)
7013032c353SKristof Provost goto error;
7023032c353SKristof Provost nvlist_add_nvlist(nvl, "dst", tmp);
7033032c353SKristof Provost nvlist_destroy(tmp);
7043032c353SKristof Provost
7053032c353SKristof Provost for (int i = 0; i < PF_SKIP_COUNT; i++) {
7063032c353SKristof Provost nvlist_append_number_array(nvl, "skip",
707e5c64b26SKajetan Staszkiewicz rule->skip[i] ? rule->skip[i]->nr : -1);
7083032c353SKristof Provost }
7093032c353SKristof Provost
7103032c353SKristof Provost for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++) {
7113032c353SKristof Provost nvlist_append_string_array(nvl, "labels", rule->label[i]);
7123032c353SKristof Provost }
7133032c353SKristof Provost nvlist_add_string(nvl, "label", rule->label[0]);
71476c5eeccSKristof Provost nvlist_add_number(nvl, "ridentifier", rule->ridentifier);
7153032c353SKristof Provost nvlist_add_string(nvl, "ifname", rule->ifname);
7163032c353SKristof Provost nvlist_add_string(nvl, "qname", rule->qname);
7173032c353SKristof Provost nvlist_add_string(nvl, "pqname", rule->pqname);
71863b3c1c7SKristof Provost nvlist_add_number(nvl, "dnpipe", rule->dnpipe);
71963b3c1c7SKristof Provost nvlist_add_number(nvl, "dnrpipe", rule->dnrpipe);
72063b3c1c7SKristof Provost nvlist_add_number(nvl, "dnflags", rule->free_flags);
7213032c353SKristof Provost nvlist_add_string(nvl, "tagname", rule->tagname);
7223032c353SKristof Provost nvlist_add_string(nvl, "match_tagname", rule->match_tagname);
7233032c353SKristof Provost nvlist_add_string(nvl, "overload_tblname", rule->overload_tblname);
7243032c353SKristof Provost
725e11dacbfSKristof Provost tmp = pf_pool_to_nvpool(&rule->rdr);
7263032c353SKristof Provost if (tmp == NULL)
7273032c353SKristof Provost goto error;
7283032c353SKristof Provost nvlist_add_nvlist(nvl, "rpool", tmp);
7293032c353SKristof Provost nvlist_destroy(tmp);
7303032c353SKristof Provost
7313032c353SKristof Provost nvlist_add_number(nvl, "evaluations",
73202cf67ccSMateusz Guzik pf_counter_u64_fetch(&rule->evaluations));
7333032c353SKristof Provost for (int i = 0; i < 2; i++) {
7343032c353SKristof Provost nvlist_append_number_array(nvl, "packets",
73502cf67ccSMateusz Guzik pf_counter_u64_fetch(&rule->packets[i]));
7363032c353SKristof Provost nvlist_append_number_array(nvl, "bytes",
73702cf67ccSMateusz Guzik pf_counter_u64_fetch(&rule->bytes[i]));
7383032c353SKristof Provost }
7390abcc1d2SReid Linnemann nvlist_add_number(nvl, "timestamp", pf_get_timestamp(rule));
7403032c353SKristof Provost
7413032c353SKristof Provost nvlist_add_number(nvl, "os_fingerprint", rule->os_fingerprint);
7423032c353SKristof Provost
7433032c353SKristof Provost nvlist_add_number(nvl, "rtableid", rule->rtableid);
7443032c353SKristof Provost pf_uint32_array_nv(nvl, "timeout", rule->timeout, PFTM_MAX);
7453032c353SKristof Provost nvlist_add_number(nvl, "max_states", rule->max_states);
7463032c353SKristof Provost nvlist_add_number(nvl, "max_src_nodes", rule->max_src_nodes);
7473032c353SKristof Provost nvlist_add_number(nvl, "max_src_states", rule->max_src_states);
7483032c353SKristof Provost nvlist_add_number(nvl, "max_src_conn", rule->max_src_conn);
7493032c353SKristof Provost nvlist_add_number(nvl, "max_src_conn_rate.limit",
7503032c353SKristof Provost rule->max_src_conn_rate.limit);
7513032c353SKristof Provost nvlist_add_number(nvl, "max_src_conn_rate.seconds",
7523032c353SKristof Provost rule->max_src_conn_rate.seconds);
7533032c353SKristof Provost nvlist_add_number(nvl, "qid", rule->qid);
7543032c353SKristof Provost nvlist_add_number(nvl, "pqid", rule->pqid);
7553032c353SKristof Provost nvlist_add_number(nvl, "prob", rule->prob);
7563032c353SKristof Provost nvlist_add_number(nvl, "cuid", rule->cuid);
7573032c353SKristof Provost nvlist_add_number(nvl, "cpid", rule->cpid);
7583032c353SKristof Provost
7593032c353SKristof Provost nvlist_add_number(nvl, "states_cur",
7603032c353SKristof Provost counter_u64_fetch(rule->states_cur));
7613032c353SKristof Provost nvlist_add_number(nvl, "states_tot",
7623032c353SKristof Provost counter_u64_fetch(rule->states_tot));
763*07e070efSKajetan Staszkiewicz for (pf_sn_types_t sn_type=0; sn_type<PF_SN_MAX; sn_type++)
764*07e070efSKajetan Staszkiewicz src_nodes_total += counter_u64_fetch(rule->src_nodes[sn_type]);
765*07e070efSKajetan Staszkiewicz nvlist_add_number(nvl, "src_nodes", src_nodes_total);
7663032c353SKristof Provost
7673032c353SKristof Provost nvlist_add_number(nvl, "return_icmp", rule->return_icmp);
7683032c353SKristof Provost nvlist_add_number(nvl, "return_icmp6", rule->return_icmp6);
7693032c353SKristof Provost
7703032c353SKristof Provost nvlist_add_number(nvl, "max_mss", rule->max_mss);
7713032c353SKristof Provost nvlist_add_number(nvl, "scrub_flags", rule->scrub_flags);
7723032c353SKristof Provost
7733032c353SKristof Provost tmp = pf_rule_uid_to_nvrule_uid(&rule->uid);
7743032c353SKristof Provost if (tmp == NULL)
7753032c353SKristof Provost goto error;
7763032c353SKristof Provost nvlist_add_nvlist(nvl, "uid", tmp);
7773032c353SKristof Provost nvlist_destroy(tmp);
7783032c353SKristof Provost tmp = pf_rule_uid_to_nvrule_uid((const struct pf_rule_uid *)&rule->gid);
7793032c353SKristof Provost if (tmp == NULL)
7803032c353SKristof Provost goto error;
7813032c353SKristof Provost nvlist_add_nvlist(nvl, "gid", tmp);
7823032c353SKristof Provost nvlist_destroy(tmp);
7833032c353SKristof Provost
7843032c353SKristof Provost nvlist_add_number(nvl, "rule_flag", rule->rule_flag);
7853032c353SKristof Provost nvlist_add_number(nvl, "action", rule->action);
7863032c353SKristof Provost nvlist_add_number(nvl, "direction", rule->direction);
7873032c353SKristof Provost nvlist_add_number(nvl, "log", rule->log);
7883032c353SKristof Provost nvlist_add_number(nvl, "logif", rule->logif);
7893032c353SKristof Provost nvlist_add_number(nvl, "quick", rule->quick);
7903032c353SKristof Provost nvlist_add_number(nvl, "ifnot", rule->ifnot);
7913032c353SKristof Provost nvlist_add_number(nvl, "match_tag_not", rule->match_tag_not);
7923032c353SKristof Provost nvlist_add_number(nvl, "natpass", rule->natpass);
7933032c353SKristof Provost
7943032c353SKristof Provost nvlist_add_number(nvl, "keep_state", rule->keep_state);
7953032c353SKristof Provost nvlist_add_number(nvl, "af", rule->af);
7963032c353SKristof Provost nvlist_add_number(nvl, "proto", rule->proto);
7973032c353SKristof Provost nvlist_add_number(nvl, "type", rule->type);
7983032c353SKristof Provost nvlist_add_number(nvl, "code", rule->code);
7993032c353SKristof Provost nvlist_add_number(nvl, "flags", rule->flags);
8003032c353SKristof Provost nvlist_add_number(nvl, "flagset", rule->flagset);
8013032c353SKristof Provost nvlist_add_number(nvl, "min_ttl", rule->min_ttl);
8023032c353SKristof Provost nvlist_add_number(nvl, "allow_opts", rule->allow_opts);
8033032c353SKristof Provost nvlist_add_number(nvl, "rt", rule->rt);
8043032c353SKristof Provost nvlist_add_number(nvl, "return_ttl", rule->return_ttl);
8053032c353SKristof Provost nvlist_add_number(nvl, "tos", rule->tos);
8063032c353SKristof Provost nvlist_add_number(nvl, "set_tos", rule->set_tos);
8073032c353SKristof Provost nvlist_add_number(nvl, "anchor_relative", rule->anchor_relative);
8083032c353SKristof Provost nvlist_add_number(nvl, "anchor_wildcard", rule->anchor_wildcard);
8093032c353SKristof Provost
8103032c353SKristof Provost nvlist_add_number(nvl, "flush", rule->flush);
8113032c353SKristof Provost nvlist_add_number(nvl, "prio", rule->prio);
8123032c353SKristof Provost
8130143a6bbSFranco Fichtner pf_uint8_array_nv(nvl, "set_prio", rule->set_prio, 2);
8143032c353SKristof Provost
8153032c353SKristof Provost tmp = pf_divert_to_nvdivert(rule);
8163032c353SKristof Provost if (tmp == NULL)
8173032c353SKristof Provost goto error;
8183032c353SKristof Provost nvlist_add_nvlist(nvl, "divert", tmp);
8193032c353SKristof Provost nvlist_destroy(tmp);
8203032c353SKristof Provost
8213032c353SKristof Provost return (nvl);
8223032c353SKristof Provost
8233032c353SKristof Provost error:
8243032c353SKristof Provost nvlist_destroy(nvl);
8253032c353SKristof Provost return (NULL);
8263032c353SKristof Provost }
8273032c353SKristof Provost
8283032c353SKristof Provost static int
pf_nvstate_cmp_to_state_cmp(const nvlist_t * nvl,struct pf_state_cmp * cmp)8293032c353SKristof Provost pf_nvstate_cmp_to_state_cmp(const nvlist_t *nvl, struct pf_state_cmp *cmp)
8303032c353SKristof Provost {
8313032c353SKristof Provost int error = 0;
8323032c353SKristof Provost
8333032c353SKristof Provost bzero(cmp, sizeof(*cmp));
8343032c353SKristof Provost
8353032c353SKristof Provost PFNV_CHK(pf_nvuint64(nvl, "id", &cmp->id));
8363032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "creatorid", &cmp->creatorid));
8373032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "direction", &cmp->direction));
8383032c353SKristof Provost
8393032c353SKristof Provost errout:
8403032c353SKristof Provost return (error);
8413032c353SKristof Provost }
8423032c353SKristof Provost
8433032c353SKristof Provost int
pf_nvstate_kill_to_kstate_kill(const nvlist_t * nvl,struct pf_kstate_kill * kill)8443032c353SKristof Provost pf_nvstate_kill_to_kstate_kill(const nvlist_t *nvl,
8453032c353SKristof Provost struct pf_kstate_kill *kill)
8463032c353SKristof Provost {
8473032c353SKristof Provost int error = 0;
8483032c353SKristof Provost
8493032c353SKristof Provost bzero(kill, sizeof(*kill));
8503032c353SKristof Provost
8513032c353SKristof Provost if (! nvlist_exists_nvlist(nvl, "cmp"))
8523032c353SKristof Provost return (EINVAL);
8533032c353SKristof Provost
8543032c353SKristof Provost PFNV_CHK(pf_nvstate_cmp_to_state_cmp(nvlist_get_nvlist(nvl, "cmp"),
8553032c353SKristof Provost &kill->psk_pfcmp));
8563032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "af", &kill->psk_af));
8573032c353SKristof Provost PFNV_CHK(pf_nvint(nvl, "proto", &kill->psk_proto));
8583032c353SKristof Provost
8593032c353SKristof Provost if (! nvlist_exists_nvlist(nvl, "src"))
8603032c353SKristof Provost return (EINVAL);
8613032c353SKristof Provost PFNV_CHK(pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "src"),
8623032c353SKristof Provost &kill->psk_src));
8633032c353SKristof Provost if (! nvlist_exists_nvlist(nvl, "dst"))
8643032c353SKristof Provost return (EINVAL);
8653032c353SKristof Provost PFNV_CHK(pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "dst"),
8663032c353SKristof Provost &kill->psk_dst));
8673032c353SKristof Provost if (nvlist_exists_nvlist(nvl, "rt_addr")) {
8683032c353SKristof Provost PFNV_CHK(pf_nvrule_addr_to_rule_addr(
8693032c353SKristof Provost nvlist_get_nvlist(nvl, "rt_addr"), &kill->psk_rt_addr));
8703032c353SKristof Provost }
8713032c353SKristof Provost
8723032c353SKristof Provost PFNV_CHK(pf_nvstring(nvl, "ifname", kill->psk_ifname,
8733032c353SKristof Provost sizeof(kill->psk_ifname)));
8743032c353SKristof Provost PFNV_CHK(pf_nvstring(nvl, "label", kill->psk_label,
8753032c353SKristof Provost sizeof(kill->psk_label)));
876776df104SKristof Provost PFNV_CHK(pf_nvbool(nvl, "kill_match", &kill->psk_kill_match));
8773032c353SKristof Provost
8784f337550SKristof Provost if (nvlist_exists_bool(nvl, "nat"))
8794f337550SKristof Provost PFNV_CHK(pf_nvbool(nvl, "nat", &kill->psk_nat));
8804f337550SKristof Provost
8813032c353SKristof Provost errout:
8823032c353SKristof Provost return (error);
8833032c353SKristof Provost }
8843032c353SKristof Provost
8853032c353SKristof Provost static nvlist_t *
pf_state_key_to_nvstate_key(const struct pf_state_key * key)8863032c353SKristof Provost pf_state_key_to_nvstate_key(const struct pf_state_key *key)
8873032c353SKristof Provost {
8883032c353SKristof Provost nvlist_t *nvl, *tmp;
8893032c353SKristof Provost
8903032c353SKristof Provost nvl = nvlist_create(0);
8913032c353SKristof Provost if (nvl == NULL)
8923032c353SKristof Provost return (NULL);
8933032c353SKristof Provost
8943032c353SKristof Provost for (int i = 0; i < 2; i++) {
8953032c353SKristof Provost tmp = pf_addr_to_nvaddr(&key->addr[i]);
8963032c353SKristof Provost if (tmp == NULL)
8973032c353SKristof Provost goto errout;
8983032c353SKristof Provost nvlist_append_nvlist_array(nvl, "addr", tmp);
8990f86492bSKristof Provost nvlist_destroy(tmp);
9003032c353SKristof Provost nvlist_append_number_array(nvl, "port", key->port[i]);
9013032c353SKristof Provost }
9023032c353SKristof Provost nvlist_add_number(nvl, "af", key->af);
9033032c353SKristof Provost nvlist_add_number(nvl, "proto", key->proto);
9043032c353SKristof Provost
9053032c353SKristof Provost return (nvl);
9063032c353SKristof Provost
9073032c353SKristof Provost errout:
9083032c353SKristof Provost nvlist_destroy(nvl);
9093032c353SKristof Provost return (NULL);
9103032c353SKristof Provost }
9113032c353SKristof Provost
9123032c353SKristof Provost static nvlist_t *
pf_state_peer_to_nvstate_peer(const struct pf_state_peer * peer)91334285eefSKristof Provost pf_state_peer_to_nvstate_peer(const struct pf_state_peer *peer)
9143032c353SKristof Provost {
9153032c353SKristof Provost nvlist_t *nvl;
9163032c353SKristof Provost
9173032c353SKristof Provost nvl = nvlist_create(0);
9183032c353SKristof Provost if (nvl == NULL)
9193032c353SKristof Provost return (NULL);
9203032c353SKristof Provost
9213032c353SKristof Provost nvlist_add_number(nvl, "seqlo", peer->seqlo);
9223032c353SKristof Provost nvlist_add_number(nvl, "seqhi", peer->seqhi);
9233032c353SKristof Provost nvlist_add_number(nvl, "seqdiff", peer->seqdiff);
9243032c353SKristof Provost nvlist_add_number(nvl, "state", peer->state);
9253032c353SKristof Provost nvlist_add_number(nvl, "wscale", peer->wscale);
9263032c353SKristof Provost
9273032c353SKristof Provost return (nvl);
9283032c353SKristof Provost }
9293032c353SKristof Provost
9303032c353SKristof Provost nvlist_t *
pf_state_to_nvstate(const struct pf_kstate * s)931211cddf9SKristof Provost pf_state_to_nvstate(const struct pf_kstate *s)
9323032c353SKristof Provost {
9333032c353SKristof Provost nvlist_t *nvl, *tmp;
9343032c353SKristof Provost uint32_t expire, flags = 0;
9353032c353SKristof Provost
9363032c353SKristof Provost nvl = nvlist_create(0);
9373032c353SKristof Provost if (nvl == NULL)
9383032c353SKristof Provost return (NULL);
9393032c353SKristof Provost
9403032c353SKristof Provost nvlist_add_number(nvl, "id", s->id);
9413032c353SKristof Provost nvlist_add_string(nvl, "ifname", s->kif->pfik_name);
9423032c353SKristof Provost nvlist_add_string(nvl, "orig_ifname", s->orig_kif->pfik_name);
9433032c353SKristof Provost
9443032c353SKristof Provost tmp = pf_state_key_to_nvstate_key(s->key[PF_SK_STACK]);
9453032c353SKristof Provost if (tmp == NULL)
9463032c353SKristof Provost goto errout;
9473032c353SKristof Provost nvlist_add_nvlist(nvl, "stack_key", tmp);
9483032c353SKristof Provost nvlist_destroy(tmp);
9493032c353SKristof Provost
9503032c353SKristof Provost tmp = pf_state_key_to_nvstate_key(s->key[PF_SK_WIRE]);
9513032c353SKristof Provost if (tmp == NULL)
9523032c353SKristof Provost goto errout;
9533032c353SKristof Provost nvlist_add_nvlist(nvl, "wire_key", tmp);
9543032c353SKristof Provost nvlist_destroy(tmp);
9553032c353SKristof Provost
9563032c353SKristof Provost tmp = pf_state_peer_to_nvstate_peer(&s->src);
9573032c353SKristof Provost if (tmp == NULL)
9583032c353SKristof Provost goto errout;
9593032c353SKristof Provost nvlist_add_nvlist(nvl, "src", tmp);
9603032c353SKristof Provost nvlist_destroy(tmp);
9613032c353SKristof Provost
9623032c353SKristof Provost tmp = pf_state_peer_to_nvstate_peer(&s->dst);
9633032c353SKristof Provost if (tmp == NULL)
9643032c353SKristof Provost goto errout;
9653032c353SKristof Provost nvlist_add_nvlist(nvl, "dst", tmp);
9663032c353SKristof Provost nvlist_destroy(tmp);
9673032c353SKristof Provost
968c49c9da2SKajetan Staszkiewicz tmp = pf_addr_to_nvaddr(&s->act.rt_addr);
9693032c353SKristof Provost if (tmp == NULL)
9703032c353SKristof Provost goto errout;
9713032c353SKristof Provost nvlist_add_nvlist(nvl, "rt_addr", tmp);
9723032c353SKristof Provost nvlist_destroy(tmp);
9733032c353SKristof Provost
974e5c64b26SKajetan Staszkiewicz nvlist_add_number(nvl, "rule", s->rule ? s->rule->nr : -1);
9753032c353SKristof Provost nvlist_add_number(nvl, "anchor",
976e5c64b26SKajetan Staszkiewicz s->anchor ? s->anchor->nr : -1);
9773032c353SKristof Provost nvlist_add_number(nvl, "nat_rule",
978e5c64b26SKajetan Staszkiewicz s->nat_rule ? s->nat_rule->nr : -1);
97904932601SKristof Provost nvlist_add_number(nvl, "creation", s->creation / 1000);
9803032c353SKristof Provost
9813032c353SKristof Provost expire = pf_state_expires(s);
9823032c353SKristof Provost if (expire <= time_uptime)
9833032c353SKristof Provost expire = 0;
9843032c353SKristof Provost else
9853032c353SKristof Provost expire = expire - time_uptime;
9863032c353SKristof Provost nvlist_add_number(nvl, "expire", expire);
9873032c353SKristof Provost
9883032c353SKristof Provost for (int i = 0; i < 2; i++) {
9893032c353SKristof Provost nvlist_append_number_array(nvl, "packets",
99055cc305dSMateusz Guzik s->packets[i]);
9913032c353SKristof Provost nvlist_append_number_array(nvl, "bytes",
99255cc305dSMateusz Guzik s->bytes[i]);
9933032c353SKristof Provost }
9943032c353SKristof Provost
9953032c353SKristof Provost nvlist_add_number(nvl, "creatorid", s->creatorid);
9963032c353SKristof Provost nvlist_add_number(nvl, "direction", s->direction);
9973032c353SKristof Provost nvlist_add_number(nvl, "state_flags", s->state_flags);
998*07e070efSKajetan Staszkiewicz if (s->sns[PF_SN_LIMIT] != NULL)
9993032c353SKristof Provost flags |= PFSYNC_FLAG_SRCNODE;
1000*07e070efSKajetan Staszkiewicz if (s->sns[PF_SN_NAT] != NULL || s->sns[PF_SN_ROUTE])
10013032c353SKristof Provost flags |= PFSYNC_FLAG_NATSRCNODE;
10023032c353SKristof Provost nvlist_add_number(nvl, "sync_flags", flags);
10033032c353SKristof Provost
10043032c353SKristof Provost return (nvl);
10053032c353SKristof Provost
10063032c353SKristof Provost errout:
10073032c353SKristof Provost nvlist_destroy(nvl);
10083032c353SKristof Provost return (NULL);
10093032c353SKristof Provost }
1010e732e742SKristof Provost
1011e732e742SKristof Provost static int
pf_nveth_rule_addr_to_keth_rule_addr(const nvlist_t * nvl,struct pf_keth_rule_addr * krule)1012e732e742SKristof Provost pf_nveth_rule_addr_to_keth_rule_addr(const nvlist_t *nvl,
1013e732e742SKristof Provost struct pf_keth_rule_addr *krule)
1014e732e742SKristof Provost {
1015e732e742SKristof Provost static const u_int8_t EMPTY_MAC[ETHER_ADDR_LEN] = { 0 };
1016e732e742SKristof Provost int error = 0;
1017e732e742SKristof Provost
1018e732e742SKristof Provost PFNV_CHK(pf_nvbinary(nvl, "addr", &krule->addr, sizeof(krule->addr)));
1019e732e742SKristof Provost PFNV_CHK(pf_nvbool(nvl, "neg", &krule->neg));
1020b590f17aSKristof Provost if (nvlist_exists_binary(nvl, "mask"))
1021b590f17aSKristof Provost PFNV_CHK(pf_nvbinary(nvl, "mask", &krule->mask,
1022b590f17aSKristof Provost sizeof(krule->mask)));
1023e732e742SKristof Provost
1024e732e742SKristof Provost /* To make checks for 'is this address set?' easier. */
1025e732e742SKristof Provost if (memcmp(krule->addr, EMPTY_MAC, ETHER_ADDR_LEN) != 0)
1026e732e742SKristof Provost krule->isset = 1;
1027e732e742SKristof Provost
1028e732e742SKristof Provost errout:
1029e732e742SKristof Provost return (error);
1030e732e742SKristof Provost }
1031e732e742SKristof Provost
1032e732e742SKristof Provost static nvlist_t*
pf_keth_rule_addr_to_nveth_rule_addr(const struct pf_keth_rule_addr * krule)1033e732e742SKristof Provost pf_keth_rule_addr_to_nveth_rule_addr(const struct pf_keth_rule_addr *krule)
1034e732e742SKristof Provost {
1035e732e742SKristof Provost nvlist_t *nvl;
1036e732e742SKristof Provost
1037e732e742SKristof Provost nvl = nvlist_create(0);
1038e732e742SKristof Provost if (nvl == NULL)
1039e732e742SKristof Provost return (NULL);
1040e732e742SKristof Provost
1041e732e742SKristof Provost nvlist_add_binary(nvl, "addr", &krule->addr, sizeof(krule->addr));
1042b590f17aSKristof Provost nvlist_add_binary(nvl, "mask", &krule->mask, sizeof(krule->mask));
1043e732e742SKristof Provost nvlist_add_bool(nvl, "neg", krule->neg);
1044e732e742SKristof Provost
1045e732e742SKristof Provost return (nvl);
1046e732e742SKristof Provost }
1047e732e742SKristof Provost
1048e732e742SKristof Provost nvlist_t*
pf_keth_rule_to_nveth_rule(const struct pf_keth_rule * krule)1049e732e742SKristof Provost pf_keth_rule_to_nveth_rule(const struct pf_keth_rule *krule)
1050e732e742SKristof Provost {
1051e732e742SKristof Provost nvlist_t *nvl, *addr;
1052e732e742SKristof Provost
1053e732e742SKristof Provost nvl = nvlist_create(0);
1054e732e742SKristof Provost if (nvl == NULL)
1055e732e742SKristof Provost return (NULL);
1056e732e742SKristof Provost
1057ef661d4aSChristian McDonald for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++) {
1058ef661d4aSChristian McDonald nvlist_append_string_array(nvl, "labels", krule->label[i]);
1059ef661d4aSChristian McDonald }
1060ef661d4aSChristian McDonald nvlist_add_number(nvl, "ridentifier", krule->ridentifier);
1061ef661d4aSChristian McDonald
1062e732e742SKristof Provost nvlist_add_number(nvl, "nr", krule->nr);
1063e732e742SKristof Provost nvlist_add_bool(nvl, "quick", krule->quick);
1064e732e742SKristof Provost nvlist_add_string(nvl, "ifname", krule->ifname);
1065e732e742SKristof Provost nvlist_add_bool(nvl, "ifnot", krule->ifnot);
1066e732e742SKristof Provost nvlist_add_number(nvl, "direction", krule->direction);
1067e732e742SKristof Provost nvlist_add_number(nvl, "proto", krule->proto);
10681f61367fSKristof Provost nvlist_add_string(nvl, "match_tagname", krule->match_tagname);
10691f61367fSKristof Provost nvlist_add_number(nvl, "match_tag", krule->match_tag);
10701f61367fSKristof Provost nvlist_add_bool(nvl, "match_tag_not", krule->match_tag_not);
1071e732e742SKristof Provost
1072e732e742SKristof Provost addr = pf_keth_rule_addr_to_nveth_rule_addr(&krule->src);
1073e732e742SKristof Provost if (addr == NULL) {
1074e732e742SKristof Provost nvlist_destroy(nvl);
1075e732e742SKristof Provost return (NULL);
1076e732e742SKristof Provost }
1077e732e742SKristof Provost nvlist_add_nvlist(nvl, "src", addr);
10780044bd90SKristof Provost nvlist_destroy(addr);
1079e732e742SKristof Provost
1080e732e742SKristof Provost addr = pf_keth_rule_addr_to_nveth_rule_addr(&krule->dst);
1081e732e742SKristof Provost if (addr == NULL) {
1082e732e742SKristof Provost nvlist_destroy(nvl);
1083e732e742SKristof Provost return (NULL);
1084e732e742SKristof Provost }
1085e732e742SKristof Provost nvlist_add_nvlist(nvl, "dst", addr);
10860044bd90SKristof Provost nvlist_destroy(addr);
1087e732e742SKristof Provost
10888a42005dSKristof Provost addr = pf_rule_addr_to_nvrule_addr(&krule->ipsrc);
10898a42005dSKristof Provost if (addr == NULL) {
10908a42005dSKristof Provost nvlist_destroy(nvl);
10918a42005dSKristof Provost return (NULL);
10928a42005dSKristof Provost }
10938a42005dSKristof Provost nvlist_add_nvlist(nvl, "ipsrc", addr);
10948a42005dSKristof Provost nvlist_destroy(addr);
10958a42005dSKristof Provost
10968a42005dSKristof Provost addr = pf_rule_addr_to_nvrule_addr(&krule->ipdst);
10978a42005dSKristof Provost if (addr == NULL) {
10988a42005dSKristof Provost nvlist_destroy(nvl);
10998a42005dSKristof Provost return (NULL);
11008a42005dSKristof Provost }
11018a42005dSKristof Provost nvlist_add_nvlist(nvl, "ipdst", addr);
11028a42005dSKristof Provost nvlist_destroy(addr);
11038a42005dSKristof Provost
1104e732e742SKristof Provost nvlist_add_number(nvl, "evaluations",
1105e732e742SKristof Provost counter_u64_fetch(krule->evaluations));
1106e732e742SKristof Provost nvlist_add_number(nvl, "packets-in",
1107e732e742SKristof Provost counter_u64_fetch(krule->packets[0]));
1108e732e742SKristof Provost nvlist_add_number(nvl, "packets-out",
1109e732e742SKristof Provost counter_u64_fetch(krule->packets[1]));
1110e732e742SKristof Provost nvlist_add_number(nvl, "bytes-in",
1111e732e742SKristof Provost counter_u64_fetch(krule->bytes[0]));
1112e732e742SKristof Provost nvlist_add_number(nvl, "bytes-out",
1113e732e742SKristof Provost counter_u64_fetch(krule->bytes[1]));
1114e732e742SKristof Provost
11150abcc1d2SReid Linnemann nvlist_add_number(nvl, "timestamp", pf_get_timestamp(krule));
1116e732e742SKristof Provost nvlist_add_string(nvl, "qname", krule->qname);
1117e732e742SKristof Provost nvlist_add_string(nvl, "tagname", krule->tagname);
1118e732e742SKristof Provost
1119fb330f39SKristof Provost nvlist_add_number(nvl, "dnpipe", krule->dnpipe);
1120fb330f39SKristof Provost nvlist_add_number(nvl, "dnflags", krule->dnflags);
1121fb330f39SKristof Provost
1122c5131afeSKristof Provost nvlist_add_number(nvl, "anchor_relative", krule->anchor_relative);
1123c5131afeSKristof Provost nvlist_add_number(nvl, "anchor_wildcard", krule->anchor_wildcard);
1124c5131afeSKristof Provost
11258a8af942SKristof Provost nvlist_add_string(nvl, "bridge_to", krule->bridge_to_name);
1126e732e742SKristof Provost nvlist_add_number(nvl, "action", krule->action);
1127e732e742SKristof Provost
1128e732e742SKristof Provost return (nvl);
1129e732e742SKristof Provost }
1130e732e742SKristof Provost
1131e732e742SKristof Provost int
pf_nveth_rule_to_keth_rule(const nvlist_t * nvl,struct pf_keth_rule * krule)1132e732e742SKristof Provost pf_nveth_rule_to_keth_rule(const nvlist_t *nvl,
1133e732e742SKristof Provost struct pf_keth_rule *krule)
1134e732e742SKristof Provost {
1135fb330f39SKristof Provost int error = 0;
1136e732e742SKristof Provost
1137ef661d4aSChristian McDonald #define ERROUT(x) ERROUT_FUNCTION(errout, x)
1138ef661d4aSChristian McDonald
1139e732e742SKristof Provost bzero(krule, sizeof(*krule));
1140e732e742SKristof Provost
1141ef661d4aSChristian McDonald if (nvlist_exists_string_array(nvl, "labels")) {
1142ef661d4aSChristian McDonald const char *const *strs;
1143ef661d4aSChristian McDonald size_t items;
1144ef661d4aSChristian McDonald int ret;
1145ef661d4aSChristian McDonald
1146ef661d4aSChristian McDonald strs = nvlist_get_string_array(nvl, "labels", &items);
1147ef661d4aSChristian McDonald if (items > PF_RULE_MAX_LABEL_COUNT)
1148ef661d4aSChristian McDonald ERROUT(E2BIG);
1149ef661d4aSChristian McDonald
1150ef661d4aSChristian McDonald for (size_t i = 0; i < items; i++) {
1151ef661d4aSChristian McDonald ret = strlcpy(krule->label[i], strs[i],
1152ef661d4aSChristian McDonald sizeof(krule->label[0]));
1153ef661d4aSChristian McDonald if (ret >= sizeof(krule->label[0]))
1154ef661d4aSChristian McDonald ERROUT(E2BIG);
1155ef661d4aSChristian McDonald }
1156ef661d4aSChristian McDonald }
1157ef661d4aSChristian McDonald
1158ef661d4aSChristian McDonald PFNV_CHK(pf_nvuint32_opt(nvl, "ridentifier", &krule->ridentifier, 0));
1159ef661d4aSChristian McDonald
1160e732e742SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "nr", &krule->nr));
1161e732e742SKristof Provost PFNV_CHK(pf_nvbool(nvl, "quick", &krule->quick));
1162e732e742SKristof Provost PFNV_CHK(pf_nvstring(nvl, "ifname", krule->ifname,
1163e732e742SKristof Provost sizeof(krule->ifname)));
1164e732e742SKristof Provost PFNV_CHK(pf_nvbool(nvl, "ifnot", &krule->ifnot));
1165e732e742SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "direction", &krule->direction));
1166e732e742SKristof Provost PFNV_CHK(pf_nvuint16(nvl, "proto", &krule->proto));
1167e732e742SKristof Provost
1168e732e742SKristof Provost if (nvlist_exists_nvlist(nvl, "src")) {
1169e732e742SKristof Provost error = pf_nveth_rule_addr_to_keth_rule_addr(
1170e732e742SKristof Provost nvlist_get_nvlist(nvl, "src"), &krule->src);
1171e732e742SKristof Provost if (error)
1172e732e742SKristof Provost return (error);
1173e732e742SKristof Provost }
1174e732e742SKristof Provost if (nvlist_exists_nvlist(nvl, "dst")) {
1175e732e742SKristof Provost error = pf_nveth_rule_addr_to_keth_rule_addr(
1176e732e742SKristof Provost nvlist_get_nvlist(nvl, "dst"), &krule->dst);
1177e732e742SKristof Provost if (error)
1178e732e742SKristof Provost return (error);
1179e732e742SKristof Provost }
1180e732e742SKristof Provost
11818a42005dSKristof Provost if (nvlist_exists_nvlist(nvl, "ipsrc")) {
11828a42005dSKristof Provost error = pf_nvrule_addr_to_rule_addr(
11838a42005dSKristof Provost nvlist_get_nvlist(nvl, "ipsrc"), &krule->ipsrc);
11848a42005dSKristof Provost if (error != 0)
11858a42005dSKristof Provost return (error);
11863468cd95SKristof Provost
1187812839e5SKristof Provost if (krule->ipsrc.addr.type != PF_ADDR_ADDRMASK &&
1188812839e5SKristof Provost krule->ipsrc.addr.type != PF_ADDR_TABLE)
11893468cd95SKristof Provost return (EINVAL);
11908a42005dSKristof Provost }
11918a42005dSKristof Provost
11928a42005dSKristof Provost if (nvlist_exists_nvlist(nvl, "ipdst")) {
11938a42005dSKristof Provost error = pf_nvrule_addr_to_rule_addr(
11948a42005dSKristof Provost nvlist_get_nvlist(nvl, "ipdst"), &krule->ipdst);
11958a42005dSKristof Provost if (error != 0)
11968a42005dSKristof Provost return (error);
11973468cd95SKristof Provost
1198812839e5SKristof Provost if (krule->ipdst.addr.type != PF_ADDR_ADDRMASK &&
1199812839e5SKristof Provost krule->ipdst.addr.type != PF_ADDR_TABLE)
12003468cd95SKristof Provost return (EINVAL);
12018a42005dSKristof Provost }
12028a42005dSKristof Provost
12031f61367fSKristof Provost if (nvlist_exists_string(nvl, "match_tagname")) {
12041f61367fSKristof Provost PFNV_CHK(pf_nvstring(nvl, "match_tagname", krule->match_tagname,
12051f61367fSKristof Provost sizeof(krule->match_tagname)));
12061f61367fSKristof Provost PFNV_CHK(pf_nvbool(nvl, "match_tag_not", &krule->match_tag_not));
12071f61367fSKristof Provost }
12081f61367fSKristof Provost
1209e732e742SKristof Provost PFNV_CHK(pf_nvstring(nvl, "qname", krule->qname, sizeof(krule->qname)));
1210e732e742SKristof Provost PFNV_CHK(pf_nvstring(nvl, "tagname", krule->tagname,
1211e732e742SKristof Provost sizeof(krule->tagname)));
1212e732e742SKristof Provost
1213fb330f39SKristof Provost PFNV_CHK(pf_nvuint16_opt(nvl, "dnpipe", &krule->dnpipe, 0));
1214fb330f39SKristof Provost PFNV_CHK(pf_nvuint32_opt(nvl, "dnflags", &krule->dnflags, 0));
12158a8af942SKristof Provost PFNV_CHK(pf_nvstring(nvl, "bridge_to", krule->bridge_to_name,
12168a8af942SKristof Provost sizeof(krule->bridge_to_name)));
1217fb330f39SKristof Provost
1218e732e742SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "action", &krule->action));
1219e732e742SKristof Provost
1220d27c9f5bSKristof Provost if (krule->action != PF_PASS && krule->action != PF_DROP &&
1221d27c9f5bSKristof Provost krule->action != PF_MATCH)
1222e732e742SKristof Provost return (EBADMSG);
1223e732e742SKristof Provost
1224ef661d4aSChristian McDonald #undef ERROUT
1225e732e742SKristof Provost errout:
1226e732e742SKristof Provost return (error);
1227e732e742SKristof Provost }
1228