15c62ededSKristof Provost /*- 25c62ededSKristof Provost * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 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> 295c62ededSKristof Provost __FBSDID("$FreeBSD$"); 305c62ededSKristof Provost 313032c353SKristof Provost #include "opt_inet.h" 323032c353SKristof Provost #include "opt_inet6.h" 333032c353SKristof Provost 345c62ededSKristof Provost #include <sys/param.h> 355c62ededSKristof Provost #include <sys/errno.h> 365c62ededSKristof Provost #include <sys/limits.h> 373032c353SKristof Provost #include <sys/queue.h> 385c62ededSKristof Provost #include <sys/systm.h> 395c62ededSKristof Provost 405c62ededSKristof Provost #include <netpfil/pf/pf_nv.h> 415c62ededSKristof Provost 42eaabed8aSKristof Provost #define PF_NV_IMPL_UINT(fnname, type, max) \ 435c62ededSKristof Provost int \ 447c434289SKristof Provost pf_nv ## fnname ## _opt(const nvlist_t *nvl, const char *name, \ 457c434289SKristof Provost type *val, type dflt) \ 467c434289SKristof Provost { \ 477c434289SKristof Provost uint64_t raw; \ 487c434289SKristof Provost if (! nvlist_exists_number(nvl, name)) { \ 497c434289SKristof Provost *val = dflt; \ 507c434289SKristof Provost return (0); \ 517c434289SKristof Provost } \ 527c434289SKristof Provost raw = nvlist_get_number(nvl, name); \ 537c434289SKristof Provost if (raw > max) \ 547c434289SKristof Provost return (ERANGE); \ 557c434289SKristof Provost *val = (type)raw; \ 567c434289SKristof Provost return (0); \ 577c434289SKristof Provost } \ 587c434289SKristof Provost int \ 59d710367dSKristof Provost pf_nv ## fnname(const nvlist_t *nvl, const char *name, type *val) \ 605c62ededSKristof Provost { \ 615c62ededSKristof Provost uint64_t raw; \ 625c62ededSKristof Provost if (! nvlist_exists_number(nvl, name)) \ 635c62ededSKristof Provost return (EINVAL); \ 645c62ededSKristof Provost raw = nvlist_get_number(nvl, name); \ 655c62ededSKristof Provost if (raw > max) \ 665c62ededSKristof Provost return (ERANGE); \ 675c62ededSKristof Provost *val = (type)raw; \ 685c62ededSKristof Provost return (0); \ 695c62ededSKristof Provost } \ 705c62ededSKristof Provost int \ 71d710367dSKristof Provost pf_nv ## fnname ## _array(const nvlist_t *nvl, const char *name, \ 72d710367dSKristof Provost type *array, size_t maxelems, size_t *nelems) \ 735c62ededSKristof Provost { \ 745c62ededSKristof Provost const uint64_t *n; \ 755c62ededSKristof Provost size_t nitems; \ 765c62ededSKristof Provost bzero(array, sizeof(type) * maxelems); \ 775c62ededSKristof Provost if (! nvlist_exists_number_array(nvl, name)) \ 785c62ededSKristof Provost return (EINVAL); \ 795c62ededSKristof Provost n = nvlist_get_number_array(nvl, name, &nitems); \ 805c62ededSKristof Provost if (nitems != maxelems) \ 815c62ededSKristof Provost return (E2BIG); \ 825c62ededSKristof Provost if (nelems != NULL) \ 835c62ededSKristof Provost *nelems = nitems; \ 845c62ededSKristof Provost for (size_t i = 0; i < nitems; i++) { \ 855c62ededSKristof Provost if (n[i] > max) \ 865c62ededSKristof Provost return (ERANGE); \ 875c62ededSKristof Provost array[i] = (type)n[i]; \ 885c62ededSKristof Provost } \ 895c62ededSKristof Provost return (0); \ 90d710367dSKristof Provost } \ 91d710367dSKristof Provost void \ 92d710367dSKristof Provost pf_ ## fnname ## _array_nv(nvlist_t *nvl, const char *name, \ 93d710367dSKristof Provost const type *numbers, size_t count) \ 94d710367dSKristof Provost { \ 95d710367dSKristof Provost uint64_t tmp; \ 96d710367dSKristof Provost for (size_t i = 0; i < count; i++) { \ 97d710367dSKristof Provost tmp = numbers[i]; \ 98d710367dSKristof Provost nvlist_append_number_array(nvl, name, tmp); \ 99d710367dSKristof Provost } \ 1005c62ededSKristof Provost } 101d710367dSKristof Provost 1025c62ededSKristof Provost int 1035c62ededSKristof Provost pf_nvbinary(const nvlist_t *nvl, const char *name, void *data, 1045c62ededSKristof Provost size_t expected_size) 1055c62ededSKristof Provost { 1065c62ededSKristof Provost const uint8_t *nvdata; 1075c62ededSKristof Provost size_t len; 1085c62ededSKristof Provost 1095c62ededSKristof Provost bzero(data, expected_size); 1105c62ededSKristof Provost 1115c62ededSKristof Provost if (! nvlist_exists_binary(nvl, name)) 1125c62ededSKristof Provost return (EINVAL); 1135c62ededSKristof Provost 1145c62ededSKristof Provost nvdata = (const uint8_t *)nvlist_get_binary(nvl, name, &len); 1155c62ededSKristof Provost if (len > expected_size) 1165c62ededSKristof Provost return (EINVAL); 1175c62ededSKristof Provost 1185c62ededSKristof Provost memcpy(data, nvdata, len); 1195c62ededSKristof Provost 1205c62ededSKristof Provost return (0); 1215c62ededSKristof Provost } 1225c62ededSKristof Provost 123eaabed8aSKristof Provost PF_NV_IMPL_UINT(uint8, uint8_t, UINT8_MAX); 124eaabed8aSKristof Provost PF_NV_IMPL_UINT(uint16, uint16_t, UINT16_MAX); 125eaabed8aSKristof Provost PF_NV_IMPL_UINT(uint32, uint32_t, UINT32_MAX); 1267606a45dSKristof Provost PF_NV_IMPL_UINT(uint64, uint64_t, UINT64_MAX); 1275c62ededSKristof Provost 1285c62ededSKristof Provost int 1295c62ededSKristof Provost pf_nvint(const nvlist_t *nvl, const char *name, int *val) 1305c62ededSKristof Provost { 1315c62ededSKristof Provost int64_t raw; 1325c62ededSKristof Provost 1335c62ededSKristof Provost if (! nvlist_exists_number(nvl, name)) 1345c62ededSKristof Provost return (EINVAL); 1355c62ededSKristof Provost 1365c62ededSKristof Provost raw = nvlist_get_number(nvl, name); 1375c62ededSKristof Provost if (raw > INT_MAX || raw < INT_MIN) 1385c62ededSKristof Provost return (ERANGE); 1395c62ededSKristof Provost 1405c62ededSKristof Provost *val = (int)raw; 1415c62ededSKristof Provost 1425c62ededSKristof Provost return (0); 1435c62ededSKristof Provost } 1445c62ededSKristof Provost 1455c62ededSKristof Provost int 1465c62ededSKristof Provost pf_nvstring(const nvlist_t *nvl, const char *name, char *str, size_t maxlen) 1475c62ededSKristof Provost { 1485c62ededSKristof Provost int ret; 1495c62ededSKristof Provost 1505c62ededSKristof Provost if (! nvlist_exists_string(nvl, name)) 1515c62ededSKristof Provost return (EINVAL); 1525c62ededSKristof Provost 1535c62ededSKristof Provost ret = strlcpy(str, nvlist_get_string(nvl, name), maxlen); 1545c62ededSKristof Provost if (ret >= maxlen) 1555c62ededSKristof Provost return (EINVAL); 1565c62ededSKristof Provost 1575c62ededSKristof Provost return (0); 1585c62ededSKristof Provost } 1593032c353SKristof Provost 1603032c353SKristof Provost static int 1613032c353SKristof Provost pf_nvaddr_to_addr(const nvlist_t *nvl, struct pf_addr *paddr) 1623032c353SKristof Provost { 1633032c353SKristof Provost return (pf_nvbinary(nvl, "addr", paddr, sizeof(*paddr))); 1643032c353SKristof Provost } 1653032c353SKristof Provost 1663032c353SKristof Provost static nvlist_t * 1673032c353SKristof Provost pf_addr_to_nvaddr(const struct pf_addr *paddr) 1683032c353SKristof Provost { 1693032c353SKristof Provost nvlist_t *nvl; 1703032c353SKristof Provost 1713032c353SKristof Provost nvl = nvlist_create(0); 1723032c353SKristof Provost if (nvl == NULL) 1733032c353SKristof Provost return (NULL); 1743032c353SKristof Provost 1753032c353SKristof Provost nvlist_add_binary(nvl, "addr", paddr, sizeof(*paddr)); 1763032c353SKristof Provost 1773032c353SKristof Provost return (nvl); 1783032c353SKristof Provost } 1793032c353SKristof Provost 1803032c353SKristof Provost static int 1813032c353SKristof Provost pf_nvmape_to_mape(const nvlist_t *nvl, struct pf_mape_portset *mape) 1823032c353SKristof Provost { 1833032c353SKristof Provost int error = 0; 1843032c353SKristof Provost 1853032c353SKristof Provost bzero(mape, sizeof(*mape)); 1863032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "offset", &mape->offset)); 1873032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "psidlen", &mape->psidlen)); 1883032c353SKristof Provost PFNV_CHK(pf_nvuint16(nvl, "psid", &mape->psid)); 1893032c353SKristof Provost 1903032c353SKristof Provost errout: 1913032c353SKristof Provost return (error); 1923032c353SKristof Provost } 1933032c353SKristof Provost 1943032c353SKristof Provost static nvlist_t * 1953032c353SKristof Provost pf_mape_to_nvmape(const struct pf_mape_portset *mape) 1963032c353SKristof Provost { 1973032c353SKristof Provost nvlist_t *nvl; 1983032c353SKristof Provost 1993032c353SKristof Provost nvl = nvlist_create(0); 2003032c353SKristof Provost if (nvl == NULL) 2013032c353SKristof Provost return (NULL); 2023032c353SKristof Provost 2033032c353SKristof Provost nvlist_add_number(nvl, "offset", mape->offset); 2043032c353SKristof Provost nvlist_add_number(nvl, "psidlen", mape->psidlen); 2053032c353SKristof Provost nvlist_add_number(nvl, "psid", mape->psid); 2063032c353SKristof Provost 2073032c353SKristof Provost return (nvl); 2083032c353SKristof Provost } 2093032c353SKristof Provost 2103032c353SKristof Provost static int 2113032c353SKristof Provost pf_nvpool_to_pool(const nvlist_t *nvl, struct pf_kpool *kpool) 2123032c353SKristof Provost { 2133032c353SKristof Provost int error = 0; 2143032c353SKristof Provost 2153032c353SKristof Provost bzero(kpool, sizeof(*kpool)); 2163032c353SKristof Provost 2173032c353SKristof Provost PFNV_CHK(pf_nvbinary(nvl, "key", &kpool->key, sizeof(kpool->key))); 2183032c353SKristof Provost 2193032c353SKristof Provost if (nvlist_exists_nvlist(nvl, "counter")) { 2203032c353SKristof Provost PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "counter"), 2213032c353SKristof Provost &kpool->counter)); 2223032c353SKristof Provost } 2233032c353SKristof Provost 2243032c353SKristof Provost PFNV_CHK(pf_nvint(nvl, "tblidx", &kpool->tblidx)); 2253032c353SKristof Provost PFNV_CHK(pf_nvuint16_array(nvl, "proxy_port", kpool->proxy_port, 2, 2263032c353SKristof Provost NULL)); 2273032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "opts", &kpool->opts)); 2283032c353SKristof Provost 2293032c353SKristof Provost if (nvlist_exists_nvlist(nvl, "mape")) { 2303032c353SKristof Provost PFNV_CHK(pf_nvmape_to_mape(nvlist_get_nvlist(nvl, "mape"), 2313032c353SKristof Provost &kpool->mape)); 2323032c353SKristof Provost } 2333032c353SKristof Provost 2343032c353SKristof Provost errout: 2353032c353SKristof Provost return (error); 2363032c353SKristof Provost } 2373032c353SKristof Provost 2383032c353SKristof Provost static nvlist_t * 2393032c353SKristof Provost pf_pool_to_nvpool(const struct pf_kpool *pool) 2403032c353SKristof Provost { 2413032c353SKristof Provost nvlist_t *nvl; 2423032c353SKristof Provost nvlist_t *tmp; 2433032c353SKristof Provost 2443032c353SKristof Provost nvl = nvlist_create(0); 2453032c353SKristof Provost if (nvl == NULL) 2463032c353SKristof Provost return (NULL); 2473032c353SKristof Provost 2483032c353SKristof Provost nvlist_add_binary(nvl, "key", &pool->key, sizeof(pool->key)); 2493032c353SKristof Provost tmp = pf_addr_to_nvaddr(&pool->counter); 2503032c353SKristof Provost if (tmp == NULL) 2513032c353SKristof Provost goto error; 2523032c353SKristof Provost nvlist_add_nvlist(nvl, "counter", tmp); 2533032c353SKristof Provost nvlist_destroy(tmp); 2543032c353SKristof Provost 2553032c353SKristof Provost nvlist_add_number(nvl, "tblidx", pool->tblidx); 2563032c353SKristof Provost pf_uint16_array_nv(nvl, "proxy_port", pool->proxy_port, 2); 2573032c353SKristof Provost nvlist_add_number(nvl, "opts", pool->opts); 2583032c353SKristof Provost 2593032c353SKristof Provost tmp = pf_mape_to_nvmape(&pool->mape); 2603032c353SKristof Provost if (tmp == NULL) 2613032c353SKristof Provost goto error; 2623032c353SKristof Provost nvlist_add_nvlist(nvl, "mape", tmp); 2633032c353SKristof Provost nvlist_destroy(tmp); 2643032c353SKristof Provost 2653032c353SKristof Provost return (nvl); 2663032c353SKristof Provost 2673032c353SKristof Provost error: 2683032c353SKristof Provost nvlist_destroy(nvl); 2693032c353SKristof Provost return (NULL); 2703032c353SKristof Provost } 2713032c353SKristof Provost 2723032c353SKristof Provost static int 2733032c353SKristof Provost pf_nvaddr_wrap_to_addr_wrap(const nvlist_t *nvl, struct pf_addr_wrap *addr) 2743032c353SKristof Provost { 2753032c353SKristof Provost int error = 0; 2763032c353SKristof Provost 2773032c353SKristof Provost bzero(addr, sizeof(*addr)); 2783032c353SKristof Provost 2793032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "type", &addr->type)); 2803032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "iflags", &addr->iflags)); 2813032c353SKristof Provost if (addr->type == PF_ADDR_DYNIFTL) 2823032c353SKristof Provost PFNV_CHK(pf_nvstring(nvl, "ifname", addr->v.ifname, 2833032c353SKristof Provost sizeof(addr->v.ifname))); 2843032c353SKristof Provost if (addr->type == PF_ADDR_TABLE) 2853032c353SKristof Provost PFNV_CHK(pf_nvstring(nvl, "tblname", addr->v.tblname, 2863032c353SKristof Provost sizeof(addr->v.tblname))); 2873032c353SKristof Provost 2883032c353SKristof Provost if (! nvlist_exists_nvlist(nvl, "addr")) 2893032c353SKristof Provost return (EINVAL); 2903032c353SKristof Provost PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "addr"), 2913032c353SKristof Provost &addr->v.a.addr)); 2923032c353SKristof Provost 2933032c353SKristof Provost if (! nvlist_exists_nvlist(nvl, "mask")) 2943032c353SKristof Provost return (EINVAL); 2953032c353SKristof Provost PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "mask"), 2963032c353SKristof Provost &addr->v.a.mask)); 2973032c353SKristof Provost 2983032c353SKristof Provost switch (addr->type) { 2993032c353SKristof Provost case PF_ADDR_DYNIFTL: 3003032c353SKristof Provost case PF_ADDR_TABLE: 3013032c353SKristof Provost case PF_ADDR_RANGE: 3023032c353SKristof Provost case PF_ADDR_ADDRMASK: 3033032c353SKristof Provost case PF_ADDR_NOROUTE: 3043032c353SKristof Provost case PF_ADDR_URPFFAILED: 3053032c353SKristof Provost break; 3063032c353SKristof Provost default: 3073032c353SKristof Provost return (EINVAL); 3083032c353SKristof Provost } 3093032c353SKristof Provost 3103032c353SKristof Provost errout: 3113032c353SKristof Provost return (error); 3123032c353SKristof Provost } 3133032c353SKristof Provost 3143032c353SKristof Provost static nvlist_t * 3153032c353SKristof Provost pf_addr_wrap_to_nvaddr_wrap(const struct pf_addr_wrap *addr) 3163032c353SKristof Provost { 3173032c353SKristof Provost nvlist_t *nvl; 3183032c353SKristof Provost nvlist_t *tmp; 3193032c353SKristof Provost 3203032c353SKristof Provost nvl = nvlist_create(0); 3213032c353SKristof Provost if (nvl == NULL) 3223032c353SKristof Provost return (NULL); 3233032c353SKristof Provost 3243032c353SKristof Provost nvlist_add_number(nvl, "type", addr->type); 3253032c353SKristof Provost nvlist_add_number(nvl, "iflags", addr->iflags); 3263032c353SKristof Provost if (addr->type == PF_ADDR_DYNIFTL) 3273032c353SKristof Provost nvlist_add_string(nvl, "ifname", addr->v.ifname); 3283032c353SKristof Provost if (addr->type == PF_ADDR_TABLE) 3293032c353SKristof Provost nvlist_add_string(nvl, "tblname", addr->v.tblname); 3303032c353SKristof Provost 3313032c353SKristof Provost tmp = pf_addr_to_nvaddr(&addr->v.a.addr); 3323032c353SKristof Provost if (tmp == NULL) 3333032c353SKristof Provost goto error; 3343032c353SKristof Provost nvlist_add_nvlist(nvl, "addr", tmp); 3353032c353SKristof Provost nvlist_destroy(tmp); 3363032c353SKristof Provost tmp = pf_addr_to_nvaddr(&addr->v.a.mask); 3373032c353SKristof Provost if (tmp == NULL) 3383032c353SKristof Provost goto error; 3393032c353SKristof Provost nvlist_add_nvlist(nvl, "mask", tmp); 3403032c353SKristof Provost nvlist_destroy(tmp); 3413032c353SKristof Provost 3423032c353SKristof Provost return (nvl); 3433032c353SKristof Provost 3443032c353SKristof Provost error: 3453032c353SKristof Provost nvlist_destroy(nvl); 3463032c353SKristof Provost return (NULL); 3473032c353SKristof Provost } 3483032c353SKristof Provost 3493032c353SKristof Provost static int 3503032c353SKristof Provost pf_validate_op(uint8_t op) 3513032c353SKristof Provost { 3523032c353SKristof Provost switch (op) { 3533032c353SKristof Provost case PF_OP_NONE: 3543032c353SKristof Provost case PF_OP_IRG: 3553032c353SKristof Provost case PF_OP_EQ: 3563032c353SKristof Provost case PF_OP_NE: 3573032c353SKristof Provost case PF_OP_LT: 3583032c353SKristof Provost case PF_OP_LE: 3593032c353SKristof Provost case PF_OP_GT: 3603032c353SKristof Provost case PF_OP_GE: 3613032c353SKristof Provost case PF_OP_XRG: 3623032c353SKristof Provost case PF_OP_RRG: 3633032c353SKristof Provost break; 3643032c353SKristof Provost default: 3653032c353SKristof Provost return (EINVAL); 3663032c353SKristof Provost } 3673032c353SKristof Provost 3683032c353SKristof Provost return (0); 3693032c353SKristof Provost } 3703032c353SKristof Provost 3713032c353SKristof Provost static int 3723032c353SKristof Provost pf_nvrule_addr_to_rule_addr(const nvlist_t *nvl, struct pf_rule_addr *addr) 3733032c353SKristof Provost { 3743032c353SKristof Provost int error = 0; 3753032c353SKristof Provost 3763032c353SKristof Provost if (! nvlist_exists_nvlist(nvl, "addr")) 3773032c353SKristof Provost return (EINVAL); 3783032c353SKristof Provost 3793032c353SKristof Provost PFNV_CHK(pf_nvaddr_wrap_to_addr_wrap(nvlist_get_nvlist(nvl, "addr"), 3803032c353SKristof Provost &addr->addr)); 3813032c353SKristof Provost PFNV_CHK(pf_nvuint16_array(nvl, "port", addr->port, 2, NULL)); 3823032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "neg", &addr->neg)); 3833032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "port_op", &addr->port_op)); 3843032c353SKristof Provost 3853032c353SKristof Provost PFNV_CHK(pf_validate_op(addr->port_op)); 3863032c353SKristof Provost 3873032c353SKristof Provost errout: 3883032c353SKristof Provost return (error); 3893032c353SKristof Provost } 3903032c353SKristof Provost 3913032c353SKristof Provost static nvlist_t * 3923032c353SKristof Provost pf_rule_addr_to_nvrule_addr(const struct pf_rule_addr *addr) 3933032c353SKristof Provost { 3943032c353SKristof Provost nvlist_t *nvl; 3953032c353SKristof Provost nvlist_t *tmp; 3963032c353SKristof Provost 3973032c353SKristof Provost nvl = nvlist_create(0); 3983032c353SKristof Provost if (nvl == NULL) 3993032c353SKristof Provost return (NULL); 4003032c353SKristof Provost 4013032c353SKristof Provost tmp = pf_addr_wrap_to_nvaddr_wrap(&addr->addr); 4023032c353SKristof Provost if (tmp == NULL) 4033032c353SKristof Provost goto error; 4043032c353SKristof Provost nvlist_add_nvlist(nvl, "addr", tmp); 4053032c353SKristof Provost nvlist_destroy(tmp); 4063032c353SKristof Provost pf_uint16_array_nv(nvl, "port", addr->port, 2); 4073032c353SKristof Provost nvlist_add_number(nvl, "neg", addr->neg); 4083032c353SKristof Provost nvlist_add_number(nvl, "port_op", addr->port_op); 4093032c353SKristof Provost 4103032c353SKristof Provost return (nvl); 4113032c353SKristof Provost 4123032c353SKristof Provost error: 4133032c353SKristof Provost nvlist_destroy(nvl); 4143032c353SKristof Provost return (NULL); 4153032c353SKristof Provost } 4163032c353SKristof Provost 4173032c353SKristof Provost static int 4183032c353SKristof Provost pf_nvrule_uid_to_rule_uid(const nvlist_t *nvl, struct pf_rule_uid *uid) 4193032c353SKristof Provost { 4203032c353SKristof Provost int error = 0; 4213032c353SKristof Provost 4223032c353SKristof Provost bzero(uid, sizeof(*uid)); 4233032c353SKristof Provost 4243032c353SKristof Provost PFNV_CHK(pf_nvuint32_array(nvl, "uid", uid->uid, 2, NULL)); 4253032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "op", &uid->op)); 4263032c353SKristof Provost 4273032c353SKristof Provost PFNV_CHK(pf_validate_op(uid->op)); 4283032c353SKristof Provost 4293032c353SKristof Provost errout: 4303032c353SKristof Provost return (error); 4313032c353SKristof Provost } 4323032c353SKristof Provost 4333032c353SKristof Provost static nvlist_t * 4343032c353SKristof Provost pf_rule_uid_to_nvrule_uid(const struct pf_rule_uid *uid) 4353032c353SKristof Provost { 4363032c353SKristof Provost nvlist_t *nvl; 4373032c353SKristof Provost 4383032c353SKristof Provost nvl = nvlist_create(0); 4393032c353SKristof Provost if (nvl == NULL) 4403032c353SKristof Provost return (NULL); 4413032c353SKristof Provost 4423032c353SKristof Provost pf_uint32_array_nv(nvl, "uid", uid->uid, 2); 4433032c353SKristof Provost nvlist_add_number(nvl, "op", uid->op); 4443032c353SKristof Provost 4453032c353SKristof Provost return (nvl); 4463032c353SKristof Provost } 4473032c353SKristof Provost 4483032c353SKristof Provost static int 4493032c353SKristof Provost pf_nvrule_gid_to_rule_gid(const nvlist_t *nvl, struct pf_rule_gid *gid) 4503032c353SKristof Provost { 4513032c353SKristof Provost /* Cheat a little. These stucts are the same, other than the name of 4523032c353SKristof Provost * the first field. */ 4533032c353SKristof Provost return (pf_nvrule_uid_to_rule_uid(nvl, (struct pf_rule_uid *)gid)); 4543032c353SKristof Provost } 4553032c353SKristof Provost 4563032c353SKristof Provost int 4573032c353SKristof Provost pf_check_rule_addr(const struct pf_rule_addr *addr) 4583032c353SKristof Provost { 4593032c353SKristof Provost 4603032c353SKristof Provost switch (addr->addr.type) { 4613032c353SKristof Provost case PF_ADDR_ADDRMASK: 4623032c353SKristof Provost case PF_ADDR_NOROUTE: 4633032c353SKristof Provost case PF_ADDR_DYNIFTL: 4643032c353SKristof Provost case PF_ADDR_TABLE: 4653032c353SKristof Provost case PF_ADDR_URPFFAILED: 4663032c353SKristof Provost case PF_ADDR_RANGE: 4673032c353SKristof Provost break; 4683032c353SKristof Provost default: 4693032c353SKristof Provost return (EINVAL); 4703032c353SKristof Provost } 4713032c353SKristof Provost 4723032c353SKristof Provost if (addr->addr.p.dyn != NULL) { 4733032c353SKristof Provost return (EINVAL); 4743032c353SKristof Provost } 4753032c353SKristof Provost 4763032c353SKristof Provost return (0); 4773032c353SKristof Provost } 4783032c353SKristof Provost 4793032c353SKristof Provost 4803032c353SKristof Provost int 4813032c353SKristof Provost pf_nvrule_to_krule(const nvlist_t *nvl, struct pf_krule *rule) 4823032c353SKristof Provost { 4833032c353SKristof Provost int error = 0; 4843032c353SKristof Provost 4853032c353SKristof Provost #define ERROUT(x) ERROUT_FUNCTION(errout, x) 4863032c353SKristof Provost 4873032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "nr", &rule->nr)); 4883032c353SKristof Provost 4893032c353SKristof Provost if (! nvlist_exists_nvlist(nvl, "src")) 4903032c353SKristof Provost ERROUT(EINVAL); 4913032c353SKristof Provost 4923032c353SKristof Provost error = pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "src"), 4933032c353SKristof Provost &rule->src); 4943032c353SKristof Provost if (error != 0) 4953032c353SKristof Provost ERROUT(error); 4963032c353SKristof Provost 4973032c353SKristof Provost if (! nvlist_exists_nvlist(nvl, "dst")) 4983032c353SKristof Provost ERROUT(EINVAL); 4993032c353SKristof Provost 5003032c353SKristof Provost PFNV_CHK(pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "dst"), 5013032c353SKristof Provost &rule->dst)); 5023032c353SKristof Provost 5033032c353SKristof Provost if (nvlist_exists_string(nvl, "label")) { 5043032c353SKristof Provost PFNV_CHK(pf_nvstring(nvl, "label", rule->label[0], 5053032c353SKristof Provost sizeof(rule->label[0]))); 5063032c353SKristof Provost } else if (nvlist_exists_string_array(nvl, "labels")) { 5073032c353SKristof Provost const char *const *strs; 5083032c353SKristof Provost size_t items; 5093032c353SKristof Provost int ret; 5103032c353SKristof Provost 5113032c353SKristof Provost strs = nvlist_get_string_array(nvl, "labels", &items); 5123032c353SKristof Provost if (items > PF_RULE_MAX_LABEL_COUNT) 5133032c353SKristof Provost ERROUT(E2BIG); 5143032c353SKristof Provost 5153032c353SKristof Provost for (size_t i = 0; i < items; i++) { 5163032c353SKristof Provost ret = strlcpy(rule->label[i], strs[i], 5173032c353SKristof Provost sizeof(rule->label[0])); 5183032c353SKristof Provost if (ret >= sizeof(rule->label[0])) 5193032c353SKristof Provost ERROUT(E2BIG); 5203032c353SKristof Provost } 5213032c353SKristof Provost } 5223032c353SKristof Provost 5233032c353SKristof Provost PFNV_CHK(pf_nvstring(nvl, "ifname", rule->ifname, 5243032c353SKristof Provost sizeof(rule->ifname))); 5253032c353SKristof Provost PFNV_CHK(pf_nvstring(nvl, "qname", rule->qname, sizeof(rule->qname))); 5263032c353SKristof Provost PFNV_CHK(pf_nvstring(nvl, "pqname", rule->pqname, 5273032c353SKristof Provost sizeof(rule->pqname))); 5283032c353SKristof Provost PFNV_CHK(pf_nvstring(nvl, "tagname", rule->tagname, 5293032c353SKristof Provost sizeof(rule->tagname))); 530*63b3c1c7SKristof Provost PFNV_CHK(pf_nvuint16_opt(nvl, "dnpipe", &rule->dnpipe, 0)); 531*63b3c1c7SKristof Provost PFNV_CHK(pf_nvuint16_opt(nvl, "dnrpipe", &rule->dnrpipe, 0)); 532*63b3c1c7SKristof Provost PFNV_CHK(pf_nvuint32_opt(nvl, "dnflags", &rule->free_flags, 0)); 5333032c353SKristof Provost PFNV_CHK(pf_nvstring(nvl, "match_tagname", rule->match_tagname, 5343032c353SKristof Provost sizeof(rule->match_tagname))); 5353032c353SKristof Provost PFNV_CHK(pf_nvstring(nvl, "overload_tblname", rule->overload_tblname, 5363032c353SKristof Provost sizeof(rule->overload_tblname))); 5373032c353SKristof Provost 5383032c353SKristof Provost if (! nvlist_exists_nvlist(nvl, "rpool")) 5393032c353SKristof Provost ERROUT(EINVAL); 5403032c353SKristof Provost PFNV_CHK(pf_nvpool_to_pool(nvlist_get_nvlist(nvl, "rpool"), 5413032c353SKristof Provost &rule->rpool)); 5423032c353SKristof Provost 5433032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "os_fingerprint", &rule->os_fingerprint)); 5443032c353SKristof Provost 5453032c353SKristof Provost PFNV_CHK(pf_nvint(nvl, "rtableid", &rule->rtableid)); 5463032c353SKristof Provost PFNV_CHK(pf_nvuint32_array(nvl, "timeout", rule->timeout, PFTM_MAX, NULL)); 5473032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "max_states", &rule->max_states)); 5483032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "max_src_nodes", &rule->max_src_nodes)); 5493032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "max_src_states", &rule->max_src_states)); 5503032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "max_src_conn", &rule->max_src_conn)); 5513032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "max_src_conn_rate.limit", 5523032c353SKristof Provost &rule->max_src_conn_rate.limit)); 5533032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "max_src_conn_rate.seconds", 5543032c353SKristof Provost &rule->max_src_conn_rate.seconds)); 5553032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "prob", &rule->prob)); 5563032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "cuid", &rule->cuid)); 5573032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "cpid", &rule->cpid)); 5583032c353SKristof Provost 5593032c353SKristof Provost PFNV_CHK(pf_nvuint16(nvl, "return_icmp", &rule->return_icmp)); 5603032c353SKristof Provost PFNV_CHK(pf_nvuint16(nvl, "return_icmp6", &rule->return_icmp6)); 5613032c353SKristof Provost 5623032c353SKristof Provost PFNV_CHK(pf_nvuint16(nvl, "max_mss", &rule->max_mss)); 5633032c353SKristof Provost PFNV_CHK(pf_nvuint16(nvl, "scrub_flags", &rule->scrub_flags)); 5643032c353SKristof Provost 5653032c353SKristof Provost if (! nvlist_exists_nvlist(nvl, "uid")) 5663032c353SKristof Provost ERROUT(EINVAL); 5673032c353SKristof Provost PFNV_CHK(pf_nvrule_uid_to_rule_uid(nvlist_get_nvlist(nvl, "uid"), 5683032c353SKristof Provost &rule->uid)); 5693032c353SKristof Provost 5703032c353SKristof Provost if (! nvlist_exists_nvlist(nvl, "gid")) 5713032c353SKristof Provost ERROUT(EINVAL); 5723032c353SKristof Provost PFNV_CHK(pf_nvrule_gid_to_rule_gid(nvlist_get_nvlist(nvl, "gid"), 5733032c353SKristof Provost &rule->gid)); 5743032c353SKristof Provost 5753032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "rule_flag", &rule->rule_flag)); 5763032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "action", &rule->action)); 5773032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "direction", &rule->direction)); 5783032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "log", &rule->log)); 5793032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "logif", &rule->logif)); 5803032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "quick", &rule->quick)); 5813032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "ifnot", &rule->ifnot)); 5823032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "match_tag_not", &rule->match_tag_not)); 5833032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "natpass", &rule->natpass)); 5843032c353SKristof Provost 5853032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "keep_state", &rule->keep_state)); 5863032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "af", &rule->af)); 5873032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "proto", &rule->proto)); 5883032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "type", &rule->type)); 5893032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "code", &rule->code)); 5903032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "flags", &rule->flags)); 5913032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "flagset", &rule->flagset)); 5923032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "min_ttl", &rule->min_ttl)); 5933032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "allow_opts", &rule->allow_opts)); 5943032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "rt", &rule->rt)); 5953032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "return_ttl", &rule->return_ttl)); 5963032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "tos", &rule->tos)); 5973032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "set_tos", &rule->set_tos)); 5983032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "anchor_relative", &rule->anchor_relative)); 5993032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "anchor_wildcard", &rule->anchor_wildcard)); 6003032c353SKristof Provost 6013032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "flush", &rule->flush)); 6023032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "prio", &rule->prio)); 6033032c353SKristof Provost 6043032c353SKristof Provost PFNV_CHK(pf_nvuint8_array(nvl, "set_prio", &rule->prio, 2, NULL)); 6053032c353SKristof Provost 6063032c353SKristof Provost if (nvlist_exists_nvlist(nvl, "divert")) { 6073032c353SKristof Provost const nvlist_t *nvldivert = nvlist_get_nvlist(nvl, "divert"); 6083032c353SKristof Provost 6093032c353SKristof Provost if (! nvlist_exists_nvlist(nvldivert, "addr")) 6103032c353SKristof Provost ERROUT(EINVAL); 6113032c353SKristof Provost PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvldivert, "addr"), 6123032c353SKristof Provost &rule->divert.addr)); 6133032c353SKristof Provost PFNV_CHK(pf_nvuint16(nvldivert, "port", &rule->divert.port)); 6143032c353SKristof Provost } 6153032c353SKristof Provost 6163032c353SKristof Provost /* Validation */ 6173032c353SKristof Provost #ifndef INET 6183032c353SKristof Provost if (rule->af == AF_INET) 6193032c353SKristof Provost ERROUT(EAFNOSUPPORT); 6203032c353SKristof Provost #endif /* INET */ 6213032c353SKristof Provost #ifndef INET6 6223032c353SKristof Provost if (rule->af == AF_INET6) 6233032c353SKristof Provost ERROUT(EAFNOSUPPORT); 6243032c353SKristof Provost #endif /* INET6 */ 6253032c353SKristof Provost 6263032c353SKristof Provost PFNV_CHK(pf_check_rule_addr(&rule->src)); 6273032c353SKristof Provost PFNV_CHK(pf_check_rule_addr(&rule->dst)); 6283032c353SKristof Provost 6293032c353SKristof Provost return (0); 6303032c353SKristof Provost 6313032c353SKristof Provost #undef ERROUT 6323032c353SKristof Provost errout: 6333032c353SKristof Provost return (error); 6343032c353SKristof Provost } 6353032c353SKristof Provost 6363032c353SKristof Provost static nvlist_t * 6373032c353SKristof Provost pf_divert_to_nvdivert(const struct pf_krule *rule) 6383032c353SKristof Provost { 6393032c353SKristof Provost nvlist_t *nvl; 6403032c353SKristof Provost nvlist_t *tmp; 6413032c353SKristof Provost 6423032c353SKristof Provost nvl = nvlist_create(0); 6433032c353SKristof Provost if (nvl == NULL) 6443032c353SKristof Provost return (NULL); 6453032c353SKristof Provost 6463032c353SKristof Provost tmp = pf_addr_to_nvaddr(&rule->divert.addr); 6473032c353SKristof Provost if (tmp == NULL) 6483032c353SKristof Provost goto error; 6493032c353SKristof Provost nvlist_add_nvlist(nvl, "addr", tmp); 6503032c353SKristof Provost nvlist_destroy(tmp); 6513032c353SKristof Provost nvlist_add_number(nvl, "port", rule->divert.port); 6523032c353SKristof Provost 6533032c353SKristof Provost return (nvl); 6543032c353SKristof Provost 6553032c353SKristof Provost error: 6563032c353SKristof Provost nvlist_destroy(nvl); 6573032c353SKristof Provost return (NULL); 6583032c353SKristof Provost } 6593032c353SKristof Provost 6603032c353SKristof Provost nvlist_t * 66102cf67ccSMateusz Guzik pf_krule_to_nvrule(struct pf_krule *rule) 6623032c353SKristof Provost { 6633032c353SKristof Provost nvlist_t *nvl, *tmp; 6643032c353SKristof Provost 6653032c353SKristof Provost nvl = nvlist_create(0); 6663032c353SKristof Provost if (nvl == NULL) 6673032c353SKristof Provost return (nvl); 6683032c353SKristof Provost 6693032c353SKristof Provost nvlist_add_number(nvl, "nr", rule->nr); 6703032c353SKristof Provost tmp = pf_rule_addr_to_nvrule_addr(&rule->src); 6713032c353SKristof Provost if (tmp == NULL) 6723032c353SKristof Provost goto error; 6733032c353SKristof Provost nvlist_add_nvlist(nvl, "src", tmp); 6743032c353SKristof Provost nvlist_destroy(tmp); 6753032c353SKristof Provost tmp = pf_rule_addr_to_nvrule_addr(&rule->dst); 6763032c353SKristof Provost if (tmp == NULL) 6773032c353SKristof Provost goto error; 6783032c353SKristof Provost nvlist_add_nvlist(nvl, "dst", tmp); 6793032c353SKristof Provost nvlist_destroy(tmp); 6803032c353SKristof Provost 6813032c353SKristof Provost for (int i = 0; i < PF_SKIP_COUNT; i++) { 6823032c353SKristof Provost nvlist_append_number_array(nvl, "skip", 6833032c353SKristof Provost rule->skip[i].ptr ? rule->skip[i].ptr->nr : -1); 6843032c353SKristof Provost } 6853032c353SKristof Provost 6863032c353SKristof Provost for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++) { 6873032c353SKristof Provost nvlist_append_string_array(nvl, "labels", rule->label[i]); 6883032c353SKristof Provost } 6893032c353SKristof Provost nvlist_add_string(nvl, "label", rule->label[0]); 6903032c353SKristof Provost nvlist_add_string(nvl, "ifname", rule->ifname); 6913032c353SKristof Provost nvlist_add_string(nvl, "qname", rule->qname); 6923032c353SKristof Provost nvlist_add_string(nvl, "pqname", rule->pqname); 693*63b3c1c7SKristof Provost nvlist_add_number(nvl, "dnpipe", rule->dnpipe); 694*63b3c1c7SKristof Provost nvlist_add_number(nvl, "dnrpipe", rule->dnrpipe); 695*63b3c1c7SKristof Provost nvlist_add_number(nvl, "dnflags", rule->free_flags); 6963032c353SKristof Provost nvlist_add_string(nvl, "tagname", rule->tagname); 6973032c353SKristof Provost nvlist_add_string(nvl, "match_tagname", rule->match_tagname); 6983032c353SKristof Provost nvlist_add_string(nvl, "overload_tblname", rule->overload_tblname); 6993032c353SKristof Provost 7003032c353SKristof Provost tmp = pf_pool_to_nvpool(&rule->rpool); 7013032c353SKristof Provost if (tmp == NULL) 7023032c353SKristof Provost goto error; 7033032c353SKristof Provost nvlist_add_nvlist(nvl, "rpool", tmp); 7043032c353SKristof Provost nvlist_destroy(tmp); 7053032c353SKristof Provost 7063032c353SKristof Provost nvlist_add_number(nvl, "evaluations", 70702cf67ccSMateusz Guzik pf_counter_u64_fetch(&rule->evaluations)); 7083032c353SKristof Provost for (int i = 0; i < 2; i++) { 7093032c353SKristof Provost nvlist_append_number_array(nvl, "packets", 71002cf67ccSMateusz Guzik pf_counter_u64_fetch(&rule->packets[i])); 7113032c353SKristof Provost nvlist_append_number_array(nvl, "bytes", 71202cf67ccSMateusz Guzik pf_counter_u64_fetch(&rule->bytes[i])); 7133032c353SKristof Provost } 7143032c353SKristof Provost 7153032c353SKristof Provost nvlist_add_number(nvl, "os_fingerprint", rule->os_fingerprint); 7163032c353SKristof Provost 7173032c353SKristof Provost nvlist_add_number(nvl, "rtableid", rule->rtableid); 7183032c353SKristof Provost pf_uint32_array_nv(nvl, "timeout", rule->timeout, PFTM_MAX); 7193032c353SKristof Provost nvlist_add_number(nvl, "max_states", rule->max_states); 7203032c353SKristof Provost nvlist_add_number(nvl, "max_src_nodes", rule->max_src_nodes); 7213032c353SKristof Provost nvlist_add_number(nvl, "max_src_states", rule->max_src_states); 7223032c353SKristof Provost nvlist_add_number(nvl, "max_src_conn", rule->max_src_conn); 7233032c353SKristof Provost nvlist_add_number(nvl, "max_src_conn_rate.limit", 7243032c353SKristof Provost rule->max_src_conn_rate.limit); 7253032c353SKristof Provost nvlist_add_number(nvl, "max_src_conn_rate.seconds", 7263032c353SKristof Provost rule->max_src_conn_rate.seconds); 7273032c353SKristof Provost nvlist_add_number(nvl, "qid", rule->qid); 7283032c353SKristof Provost nvlist_add_number(nvl, "pqid", rule->pqid); 7293032c353SKristof Provost nvlist_add_number(nvl, "prob", rule->prob); 7303032c353SKristof Provost nvlist_add_number(nvl, "cuid", rule->cuid); 7313032c353SKristof Provost nvlist_add_number(nvl, "cpid", rule->cpid); 7323032c353SKristof Provost 7333032c353SKristof Provost nvlist_add_number(nvl, "states_cur", 7343032c353SKristof Provost counter_u64_fetch(rule->states_cur)); 7353032c353SKristof Provost nvlist_add_number(nvl, "states_tot", 7363032c353SKristof Provost counter_u64_fetch(rule->states_tot)); 7373032c353SKristof Provost nvlist_add_number(nvl, "src_nodes", 7383032c353SKristof Provost counter_u64_fetch(rule->src_nodes)); 7393032c353SKristof Provost 7403032c353SKristof Provost nvlist_add_number(nvl, "return_icmp", rule->return_icmp); 7413032c353SKristof Provost nvlist_add_number(nvl, "return_icmp6", rule->return_icmp6); 7423032c353SKristof Provost 7433032c353SKristof Provost nvlist_add_number(nvl, "max_mss", rule->max_mss); 7443032c353SKristof Provost nvlist_add_number(nvl, "scrub_flags", rule->scrub_flags); 7453032c353SKristof Provost 7463032c353SKristof Provost tmp = pf_rule_uid_to_nvrule_uid(&rule->uid); 7473032c353SKristof Provost if (tmp == NULL) 7483032c353SKristof Provost goto error; 7493032c353SKristof Provost nvlist_add_nvlist(nvl, "uid", tmp); 7503032c353SKristof Provost nvlist_destroy(tmp); 7513032c353SKristof Provost tmp = pf_rule_uid_to_nvrule_uid((const struct pf_rule_uid *)&rule->gid); 7523032c353SKristof Provost if (tmp == NULL) 7533032c353SKristof Provost goto error; 7543032c353SKristof Provost nvlist_add_nvlist(nvl, "gid", tmp); 7553032c353SKristof Provost nvlist_destroy(tmp); 7563032c353SKristof Provost 7573032c353SKristof Provost nvlist_add_number(nvl, "rule_flag", rule->rule_flag); 7583032c353SKristof Provost nvlist_add_number(nvl, "action", rule->action); 7593032c353SKristof Provost nvlist_add_number(nvl, "direction", rule->direction); 7603032c353SKristof Provost nvlist_add_number(nvl, "log", rule->log); 7613032c353SKristof Provost nvlist_add_number(nvl, "logif", rule->logif); 7623032c353SKristof Provost nvlist_add_number(nvl, "quick", rule->quick); 7633032c353SKristof Provost nvlist_add_number(nvl, "ifnot", rule->ifnot); 7643032c353SKristof Provost nvlist_add_number(nvl, "match_tag_not", rule->match_tag_not); 7653032c353SKristof Provost nvlist_add_number(nvl, "natpass", rule->natpass); 7663032c353SKristof Provost 7673032c353SKristof Provost nvlist_add_number(nvl, "keep_state", rule->keep_state); 7683032c353SKristof Provost nvlist_add_number(nvl, "af", rule->af); 7693032c353SKristof Provost nvlist_add_number(nvl, "proto", rule->proto); 7703032c353SKristof Provost nvlist_add_number(nvl, "type", rule->type); 7713032c353SKristof Provost nvlist_add_number(nvl, "code", rule->code); 7723032c353SKristof Provost nvlist_add_number(nvl, "flags", rule->flags); 7733032c353SKristof Provost nvlist_add_number(nvl, "flagset", rule->flagset); 7743032c353SKristof Provost nvlist_add_number(nvl, "min_ttl", rule->min_ttl); 7753032c353SKristof Provost nvlist_add_number(nvl, "allow_opts", rule->allow_opts); 7763032c353SKristof Provost nvlist_add_number(nvl, "rt", rule->rt); 7773032c353SKristof Provost nvlist_add_number(nvl, "return_ttl", rule->return_ttl); 7783032c353SKristof Provost nvlist_add_number(nvl, "tos", rule->tos); 7793032c353SKristof Provost nvlist_add_number(nvl, "set_tos", rule->set_tos); 7803032c353SKristof Provost nvlist_add_number(nvl, "anchor_relative", rule->anchor_relative); 7813032c353SKristof Provost nvlist_add_number(nvl, "anchor_wildcard", rule->anchor_wildcard); 7823032c353SKristof Provost 7833032c353SKristof Provost nvlist_add_number(nvl, "flush", rule->flush); 7843032c353SKristof Provost nvlist_add_number(nvl, "prio", rule->prio); 7853032c353SKristof Provost 7863032c353SKristof Provost pf_uint8_array_nv(nvl, "set_prio", &rule->prio, 2); 7873032c353SKristof Provost 7883032c353SKristof Provost tmp = pf_divert_to_nvdivert(rule); 7893032c353SKristof Provost if (tmp == NULL) 7903032c353SKristof Provost goto error; 7913032c353SKristof Provost nvlist_add_nvlist(nvl, "divert", tmp); 7923032c353SKristof Provost nvlist_destroy(tmp); 7933032c353SKristof Provost 7943032c353SKristof Provost return (nvl); 7953032c353SKristof Provost 7963032c353SKristof Provost error: 7973032c353SKristof Provost nvlist_destroy(nvl); 7983032c353SKristof Provost return (NULL); 7993032c353SKristof Provost } 8003032c353SKristof Provost 8013032c353SKristof Provost static int 8023032c353SKristof Provost pf_nvstate_cmp_to_state_cmp(const nvlist_t *nvl, struct pf_state_cmp *cmp) 8033032c353SKristof Provost { 8043032c353SKristof Provost int error = 0; 8053032c353SKristof Provost 8063032c353SKristof Provost bzero(cmp, sizeof(*cmp)); 8073032c353SKristof Provost 8083032c353SKristof Provost PFNV_CHK(pf_nvuint64(nvl, "id", &cmp->id)); 8093032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "creatorid", &cmp->creatorid)); 8103032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "direction", &cmp->direction)); 8113032c353SKristof Provost 8123032c353SKristof Provost errout: 8133032c353SKristof Provost return (error); 8143032c353SKristof Provost } 8153032c353SKristof Provost 8163032c353SKristof Provost int 8173032c353SKristof Provost pf_nvstate_kill_to_kstate_kill(const nvlist_t *nvl, 8183032c353SKristof Provost struct pf_kstate_kill *kill) 8193032c353SKristof Provost { 8203032c353SKristof Provost int error = 0; 8213032c353SKristof Provost 8223032c353SKristof Provost bzero(kill, sizeof(*kill)); 8233032c353SKristof Provost 8243032c353SKristof Provost if (! nvlist_exists_nvlist(nvl, "cmp")) 8253032c353SKristof Provost return (EINVAL); 8263032c353SKristof Provost 8273032c353SKristof Provost PFNV_CHK(pf_nvstate_cmp_to_state_cmp(nvlist_get_nvlist(nvl, "cmp"), 8283032c353SKristof Provost &kill->psk_pfcmp)); 8293032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "af", &kill->psk_af)); 8303032c353SKristof Provost PFNV_CHK(pf_nvint(nvl, "proto", &kill->psk_proto)); 8313032c353SKristof Provost 8323032c353SKristof Provost if (! nvlist_exists_nvlist(nvl, "src")) 8333032c353SKristof Provost return (EINVAL); 8343032c353SKristof Provost PFNV_CHK(pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "src"), 8353032c353SKristof Provost &kill->psk_src)); 8363032c353SKristof Provost if (! nvlist_exists_nvlist(nvl, "dst")) 8373032c353SKristof Provost return (EINVAL); 8383032c353SKristof Provost PFNV_CHK(pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "dst"), 8393032c353SKristof Provost &kill->psk_dst)); 8403032c353SKristof Provost if (nvlist_exists_nvlist(nvl, "rt_addr")) { 8413032c353SKristof Provost PFNV_CHK(pf_nvrule_addr_to_rule_addr( 8423032c353SKristof Provost nvlist_get_nvlist(nvl, "rt_addr"), &kill->psk_rt_addr)); 8433032c353SKristof Provost } 8443032c353SKristof Provost 8453032c353SKristof Provost PFNV_CHK(pf_nvstring(nvl, "ifname", kill->psk_ifname, 8463032c353SKristof Provost sizeof(kill->psk_ifname))); 8473032c353SKristof Provost PFNV_CHK(pf_nvstring(nvl, "label", kill->psk_label, 8483032c353SKristof Provost sizeof(kill->psk_label))); 8493032c353SKristof Provost if (nvlist_exists_bool(nvl, "kill_match")) 8503032c353SKristof Provost kill->psk_kill_match = nvlist_get_bool(nvl, "kill_match"); 8513032c353SKristof Provost 8523032c353SKristof Provost errout: 8533032c353SKristof Provost return (error); 8543032c353SKristof Provost } 8553032c353SKristof Provost 8563032c353SKristof Provost static nvlist_t * 8573032c353SKristof Provost pf_state_key_to_nvstate_key(const struct pf_state_key *key) 8583032c353SKristof Provost { 8593032c353SKristof Provost nvlist_t *nvl, *tmp; 8603032c353SKristof Provost 8613032c353SKristof Provost nvl = nvlist_create(0); 8623032c353SKristof Provost if (nvl == NULL) 8633032c353SKristof Provost return (NULL); 8643032c353SKristof Provost 8653032c353SKristof Provost for (int i = 0; i < 2; i++) { 8663032c353SKristof Provost tmp = pf_addr_to_nvaddr(&key->addr[i]); 8673032c353SKristof Provost if (tmp == NULL) 8683032c353SKristof Provost goto errout; 8693032c353SKristof Provost nvlist_append_nvlist_array(nvl, "addr", tmp); 8700f86492bSKristof Provost nvlist_destroy(tmp); 8713032c353SKristof Provost nvlist_append_number_array(nvl, "port", key->port[i]); 8723032c353SKristof Provost } 8733032c353SKristof Provost nvlist_add_number(nvl, "af", key->af); 8743032c353SKristof Provost nvlist_add_number(nvl, "proto", key->proto); 8753032c353SKristof Provost 8763032c353SKristof Provost return (nvl); 8773032c353SKristof Provost 8783032c353SKristof Provost errout: 8793032c353SKristof Provost nvlist_destroy(nvl); 8803032c353SKristof Provost return (NULL); 8813032c353SKristof Provost } 8823032c353SKristof Provost 8833032c353SKristof Provost static nvlist_t * 88434285eefSKristof Provost pf_state_peer_to_nvstate_peer(const struct pf_state_peer *peer) 8853032c353SKristof Provost { 8863032c353SKristof Provost nvlist_t *nvl; 8873032c353SKristof Provost 8883032c353SKristof Provost nvl = nvlist_create(0); 8893032c353SKristof Provost if (nvl == NULL) 8903032c353SKristof Provost return (NULL); 8913032c353SKristof Provost 8923032c353SKristof Provost nvlist_add_number(nvl, "seqlo", peer->seqlo); 8933032c353SKristof Provost nvlist_add_number(nvl, "seqhi", peer->seqhi); 8943032c353SKristof Provost nvlist_add_number(nvl, "seqdiff", peer->seqdiff); 8953032c353SKristof Provost nvlist_add_number(nvl, "state", peer->state); 8963032c353SKristof Provost nvlist_add_number(nvl, "wscale", peer->wscale); 8973032c353SKristof Provost 8983032c353SKristof Provost return (nvl); 8993032c353SKristof Provost } 9003032c353SKristof Provost 9013032c353SKristof Provost nvlist_t * 902211cddf9SKristof Provost pf_state_to_nvstate(const struct pf_kstate *s) 9033032c353SKristof Provost { 9043032c353SKristof Provost nvlist_t *nvl, *tmp; 9053032c353SKristof Provost uint32_t expire, flags = 0; 9063032c353SKristof Provost 9073032c353SKristof Provost nvl = nvlist_create(0); 9083032c353SKristof Provost if (nvl == NULL) 9093032c353SKristof Provost return (NULL); 9103032c353SKristof Provost 9113032c353SKristof Provost nvlist_add_number(nvl, "id", s->id); 9123032c353SKristof Provost nvlist_add_string(nvl, "ifname", s->kif->pfik_name); 9133032c353SKristof Provost nvlist_add_string(nvl, "orig_ifname", s->orig_kif->pfik_name); 9143032c353SKristof Provost 9153032c353SKristof Provost tmp = pf_state_key_to_nvstate_key(s->key[PF_SK_STACK]); 9163032c353SKristof Provost if (tmp == NULL) 9173032c353SKristof Provost goto errout; 9183032c353SKristof Provost nvlist_add_nvlist(nvl, "stack_key", tmp); 9193032c353SKristof Provost nvlist_destroy(tmp); 9203032c353SKristof Provost 9213032c353SKristof Provost tmp = pf_state_key_to_nvstate_key(s->key[PF_SK_WIRE]); 9223032c353SKristof Provost if (tmp == NULL) 9233032c353SKristof Provost goto errout; 9243032c353SKristof Provost nvlist_add_nvlist(nvl, "wire_key", tmp); 9253032c353SKristof Provost nvlist_destroy(tmp); 9263032c353SKristof Provost 9273032c353SKristof Provost tmp = pf_state_peer_to_nvstate_peer(&s->src); 9283032c353SKristof Provost if (tmp == NULL) 9293032c353SKristof Provost goto errout; 9303032c353SKristof Provost nvlist_add_nvlist(nvl, "src", tmp); 9313032c353SKristof Provost nvlist_destroy(tmp); 9323032c353SKristof Provost 9333032c353SKristof Provost tmp = pf_state_peer_to_nvstate_peer(&s->dst); 9343032c353SKristof Provost if (tmp == NULL) 9353032c353SKristof Provost goto errout; 9363032c353SKristof Provost nvlist_add_nvlist(nvl, "dst", tmp); 9373032c353SKristof Provost nvlist_destroy(tmp); 9383032c353SKristof Provost 9393032c353SKristof Provost tmp = pf_addr_to_nvaddr(&s->rt_addr); 9403032c353SKristof Provost if (tmp == NULL) 9413032c353SKristof Provost goto errout; 9423032c353SKristof Provost nvlist_add_nvlist(nvl, "rt_addr", tmp); 9433032c353SKristof Provost nvlist_destroy(tmp); 9443032c353SKristof Provost 9453032c353SKristof Provost nvlist_add_number(nvl, "rule", s->rule.ptr ? s->rule.ptr->nr : -1); 9463032c353SKristof Provost nvlist_add_number(nvl, "anchor", 9473032c353SKristof Provost s->anchor.ptr ? s->anchor.ptr->nr : -1); 9483032c353SKristof Provost nvlist_add_number(nvl, "nat_rule", 9493032c353SKristof Provost s->nat_rule.ptr ? s->nat_rule.ptr->nr : -1); 9503032c353SKristof Provost nvlist_add_number(nvl, "creation", s->creation); 9513032c353SKristof Provost 9523032c353SKristof Provost expire = pf_state_expires(s); 9533032c353SKristof Provost if (expire <= time_uptime) 9543032c353SKristof Provost expire = 0; 9553032c353SKristof Provost else 9563032c353SKristof Provost expire = expire - time_uptime; 9573032c353SKristof Provost nvlist_add_number(nvl, "expire", expire); 9583032c353SKristof Provost 9593032c353SKristof Provost for (int i = 0; i < 2; i++) { 9603032c353SKristof Provost nvlist_append_number_array(nvl, "packets", 96155cc305dSMateusz Guzik s->packets[i]); 9623032c353SKristof Provost nvlist_append_number_array(nvl, "bytes", 96355cc305dSMateusz Guzik s->bytes[i]); 9643032c353SKristof Provost } 9653032c353SKristof Provost 9663032c353SKristof Provost nvlist_add_number(nvl, "creatorid", s->creatorid); 9673032c353SKristof Provost nvlist_add_number(nvl, "direction", s->direction); 9683032c353SKristof Provost nvlist_add_number(nvl, "state_flags", s->state_flags); 9693032c353SKristof Provost if (s->src_node) 9703032c353SKristof Provost flags |= PFSYNC_FLAG_SRCNODE; 9713032c353SKristof Provost if (s->nat_src_node) 9723032c353SKristof Provost flags |= PFSYNC_FLAG_NATSRCNODE; 9733032c353SKristof Provost nvlist_add_number(nvl, "sync_flags", flags); 9743032c353SKristof Provost 9753032c353SKristof Provost return (nvl); 9763032c353SKristof Provost 9773032c353SKristof Provost errout: 9783032c353SKristof Provost nvlist_destroy(nvl); 9793032c353SKristof Provost return (NULL); 9803032c353SKristof Provost } 981