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 103776df104SKristof Provost pf_nvbool(const nvlist_t *nvl, const char *name, bool *val) 104776df104SKristof Provost { 105776df104SKristof Provost if (! nvlist_exists_bool(nvl, name)) 106776df104SKristof Provost return (EINVAL); 107776df104SKristof Provost 108776df104SKristof Provost *val = nvlist_get_bool(nvl, name); 109776df104SKristof Provost 110776df104SKristof Provost return (0); 111776df104SKristof Provost } 112776df104SKristof Provost 113776df104SKristof Provost int 1145c62ededSKristof Provost pf_nvbinary(const nvlist_t *nvl, const char *name, void *data, 1155c62ededSKristof Provost size_t expected_size) 1165c62ededSKristof Provost { 1175c62ededSKristof Provost const uint8_t *nvdata; 1185c62ededSKristof Provost size_t len; 1195c62ededSKristof Provost 1205c62ededSKristof Provost bzero(data, expected_size); 1215c62ededSKristof Provost 1225c62ededSKristof Provost if (! nvlist_exists_binary(nvl, name)) 1235c62ededSKristof Provost return (EINVAL); 1245c62ededSKristof Provost 1255c62ededSKristof Provost nvdata = (const uint8_t *)nvlist_get_binary(nvl, name, &len); 1265c62ededSKristof Provost if (len > expected_size) 1275c62ededSKristof Provost return (EINVAL); 1285c62ededSKristof Provost 1295c62ededSKristof Provost memcpy(data, nvdata, len); 1305c62ededSKristof Provost 1315c62ededSKristof Provost return (0); 1325c62ededSKristof Provost } 1335c62ededSKristof Provost 134eaabed8aSKristof Provost PF_NV_IMPL_UINT(uint8, uint8_t, UINT8_MAX); 135eaabed8aSKristof Provost PF_NV_IMPL_UINT(uint16, uint16_t, UINT16_MAX); 136eaabed8aSKristof Provost PF_NV_IMPL_UINT(uint32, uint32_t, UINT32_MAX); 1377606a45dSKristof Provost PF_NV_IMPL_UINT(uint64, uint64_t, UINT64_MAX); 1385c62ededSKristof Provost 1395c62ededSKristof Provost int 1405c62ededSKristof Provost pf_nvint(const nvlist_t *nvl, const char *name, int *val) 1415c62ededSKristof Provost { 1425c62ededSKristof Provost int64_t raw; 1435c62ededSKristof Provost 1445c62ededSKristof Provost if (! nvlist_exists_number(nvl, name)) 1455c62ededSKristof Provost return (EINVAL); 1465c62ededSKristof Provost 1475c62ededSKristof Provost raw = nvlist_get_number(nvl, name); 1485c62ededSKristof Provost if (raw > INT_MAX || raw < INT_MIN) 1495c62ededSKristof Provost return (ERANGE); 1505c62ededSKristof Provost 1515c62ededSKristof Provost *val = (int)raw; 1525c62ededSKristof Provost 1535c62ededSKristof Provost return (0); 1545c62ededSKristof Provost } 1555c62ededSKristof Provost 1565c62ededSKristof Provost int 1575c62ededSKristof Provost pf_nvstring(const nvlist_t *nvl, const char *name, char *str, size_t maxlen) 1585c62ededSKristof Provost { 1595c62ededSKristof Provost int ret; 1605c62ededSKristof Provost 1615c62ededSKristof Provost if (! nvlist_exists_string(nvl, name)) 1625c62ededSKristof Provost return (EINVAL); 1635c62ededSKristof Provost 1645c62ededSKristof Provost ret = strlcpy(str, nvlist_get_string(nvl, name), maxlen); 1655c62ededSKristof Provost if (ret >= maxlen) 1665c62ededSKristof Provost return (EINVAL); 1675c62ededSKristof Provost 1685c62ededSKristof Provost return (0); 1695c62ededSKristof Provost } 1703032c353SKristof Provost 1713032c353SKristof Provost static int 1723032c353SKristof Provost pf_nvaddr_to_addr(const nvlist_t *nvl, struct pf_addr *paddr) 1733032c353SKristof Provost { 1743032c353SKristof Provost return (pf_nvbinary(nvl, "addr", paddr, sizeof(*paddr))); 1753032c353SKristof Provost } 1763032c353SKristof Provost 1773032c353SKristof Provost static nvlist_t * 1783032c353SKristof Provost pf_addr_to_nvaddr(const struct pf_addr *paddr) 1793032c353SKristof Provost { 1803032c353SKristof Provost nvlist_t *nvl; 1813032c353SKristof Provost 1823032c353SKristof Provost nvl = nvlist_create(0); 1833032c353SKristof Provost if (nvl == NULL) 1843032c353SKristof Provost return (NULL); 1853032c353SKristof Provost 1863032c353SKristof Provost nvlist_add_binary(nvl, "addr", paddr, sizeof(*paddr)); 1873032c353SKristof Provost 1883032c353SKristof Provost return (nvl); 1893032c353SKristof Provost } 1903032c353SKristof Provost 1913032c353SKristof Provost static int 1923032c353SKristof Provost pf_nvmape_to_mape(const nvlist_t *nvl, struct pf_mape_portset *mape) 1933032c353SKristof Provost { 1943032c353SKristof Provost int error = 0; 1953032c353SKristof Provost 1963032c353SKristof Provost bzero(mape, sizeof(*mape)); 1973032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "offset", &mape->offset)); 1983032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "psidlen", &mape->psidlen)); 1993032c353SKristof Provost PFNV_CHK(pf_nvuint16(nvl, "psid", &mape->psid)); 2003032c353SKristof Provost 2013032c353SKristof Provost errout: 2023032c353SKristof Provost return (error); 2033032c353SKristof Provost } 2043032c353SKristof Provost 2053032c353SKristof Provost static nvlist_t * 2063032c353SKristof Provost pf_mape_to_nvmape(const struct pf_mape_portset *mape) 2073032c353SKristof Provost { 2083032c353SKristof Provost nvlist_t *nvl; 2093032c353SKristof Provost 2103032c353SKristof Provost nvl = nvlist_create(0); 2113032c353SKristof Provost if (nvl == NULL) 2123032c353SKristof Provost return (NULL); 2133032c353SKristof Provost 2143032c353SKristof Provost nvlist_add_number(nvl, "offset", mape->offset); 2153032c353SKristof Provost nvlist_add_number(nvl, "psidlen", mape->psidlen); 2163032c353SKristof Provost nvlist_add_number(nvl, "psid", mape->psid); 2173032c353SKristof Provost 2183032c353SKristof Provost return (nvl); 2193032c353SKristof Provost } 2203032c353SKristof Provost 2213032c353SKristof Provost static int 2223032c353SKristof Provost pf_nvpool_to_pool(const nvlist_t *nvl, struct pf_kpool *kpool) 2233032c353SKristof Provost { 2243032c353SKristof Provost int error = 0; 2253032c353SKristof Provost 2263032c353SKristof Provost PFNV_CHK(pf_nvbinary(nvl, "key", &kpool->key, sizeof(kpool->key))); 2273032c353SKristof Provost 2283032c353SKristof Provost if (nvlist_exists_nvlist(nvl, "counter")) { 2293032c353SKristof Provost PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "counter"), 2303032c353SKristof Provost &kpool->counter)); 2313032c353SKristof Provost } 2323032c353SKristof Provost 2333032c353SKristof Provost PFNV_CHK(pf_nvint(nvl, "tblidx", &kpool->tblidx)); 2343032c353SKristof Provost PFNV_CHK(pf_nvuint16_array(nvl, "proxy_port", kpool->proxy_port, 2, 2353032c353SKristof Provost NULL)); 2363032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "opts", &kpool->opts)); 2373032c353SKristof Provost 2383032c353SKristof Provost if (nvlist_exists_nvlist(nvl, "mape")) { 2393032c353SKristof Provost PFNV_CHK(pf_nvmape_to_mape(nvlist_get_nvlist(nvl, "mape"), 2403032c353SKristof Provost &kpool->mape)); 2413032c353SKristof Provost } 2423032c353SKristof Provost 2433032c353SKristof Provost errout: 2443032c353SKristof Provost return (error); 2453032c353SKristof Provost } 2463032c353SKristof Provost 2473032c353SKristof Provost static nvlist_t * 2483032c353SKristof Provost pf_pool_to_nvpool(const struct pf_kpool *pool) 2493032c353SKristof Provost { 2503032c353SKristof Provost nvlist_t *nvl; 2513032c353SKristof Provost nvlist_t *tmp; 2523032c353SKristof Provost 2533032c353SKristof Provost nvl = nvlist_create(0); 2543032c353SKristof Provost if (nvl == NULL) 2553032c353SKristof Provost return (NULL); 2563032c353SKristof Provost 2573032c353SKristof Provost nvlist_add_binary(nvl, "key", &pool->key, sizeof(pool->key)); 2583032c353SKristof Provost tmp = pf_addr_to_nvaddr(&pool->counter); 2593032c353SKristof Provost if (tmp == NULL) 2603032c353SKristof Provost goto error; 2613032c353SKristof Provost nvlist_add_nvlist(nvl, "counter", tmp); 2623032c353SKristof Provost nvlist_destroy(tmp); 2633032c353SKristof Provost 2643032c353SKristof Provost nvlist_add_number(nvl, "tblidx", pool->tblidx); 2653032c353SKristof Provost pf_uint16_array_nv(nvl, "proxy_port", pool->proxy_port, 2); 2663032c353SKristof Provost nvlist_add_number(nvl, "opts", pool->opts); 2673032c353SKristof Provost 2683032c353SKristof Provost tmp = pf_mape_to_nvmape(&pool->mape); 2693032c353SKristof Provost if (tmp == NULL) 2703032c353SKristof Provost goto error; 2713032c353SKristof Provost nvlist_add_nvlist(nvl, "mape", tmp); 2723032c353SKristof Provost nvlist_destroy(tmp); 2733032c353SKristof Provost 2743032c353SKristof Provost return (nvl); 2753032c353SKristof Provost 2763032c353SKristof Provost error: 2773032c353SKristof Provost nvlist_destroy(nvl); 2783032c353SKristof Provost return (NULL); 2793032c353SKristof Provost } 2803032c353SKristof Provost 2813032c353SKristof Provost static int 2823032c353SKristof Provost pf_nvaddr_wrap_to_addr_wrap(const nvlist_t *nvl, struct pf_addr_wrap *addr) 2833032c353SKristof Provost { 2843032c353SKristof Provost int error = 0; 2853032c353SKristof Provost 2863032c353SKristof Provost bzero(addr, sizeof(*addr)); 2873032c353SKristof Provost 2883032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "type", &addr->type)); 2893032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "iflags", &addr->iflags)); 2903032c353SKristof Provost if (addr->type == PF_ADDR_DYNIFTL) 2913032c353SKristof Provost PFNV_CHK(pf_nvstring(nvl, "ifname", addr->v.ifname, 2923032c353SKristof Provost sizeof(addr->v.ifname))); 2933032c353SKristof Provost if (addr->type == PF_ADDR_TABLE) 2943032c353SKristof Provost PFNV_CHK(pf_nvstring(nvl, "tblname", addr->v.tblname, 2953032c353SKristof Provost sizeof(addr->v.tblname))); 2963032c353SKristof Provost 2973032c353SKristof Provost if (! nvlist_exists_nvlist(nvl, "addr")) 2983032c353SKristof Provost return (EINVAL); 2993032c353SKristof Provost PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "addr"), 3003032c353SKristof Provost &addr->v.a.addr)); 3013032c353SKristof Provost 3023032c353SKristof Provost if (! nvlist_exists_nvlist(nvl, "mask")) 3033032c353SKristof Provost return (EINVAL); 3043032c353SKristof Provost PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "mask"), 3053032c353SKristof Provost &addr->v.a.mask)); 3063032c353SKristof Provost 3073032c353SKristof Provost switch (addr->type) { 3083032c353SKristof Provost case PF_ADDR_DYNIFTL: 3093032c353SKristof Provost case PF_ADDR_TABLE: 3103032c353SKristof Provost case PF_ADDR_RANGE: 3113032c353SKristof Provost case PF_ADDR_ADDRMASK: 3123032c353SKristof Provost case PF_ADDR_NOROUTE: 3133032c353SKristof Provost case PF_ADDR_URPFFAILED: 3143032c353SKristof Provost break; 3153032c353SKristof Provost default: 3163032c353SKristof Provost return (EINVAL); 3173032c353SKristof Provost } 3183032c353SKristof Provost 3193032c353SKristof Provost errout: 3203032c353SKristof Provost return (error); 3213032c353SKristof Provost } 3223032c353SKristof Provost 3233032c353SKristof Provost static nvlist_t * 3243032c353SKristof Provost pf_addr_wrap_to_nvaddr_wrap(const struct pf_addr_wrap *addr) 3253032c353SKristof Provost { 3263032c353SKristof Provost nvlist_t *nvl; 3273032c353SKristof Provost nvlist_t *tmp; 328218a8a49SKristof Provost uint64_t num; 329218a8a49SKristof Provost struct pfr_ktable *kt; 3303032c353SKristof Provost 3313032c353SKristof Provost nvl = nvlist_create(0); 3323032c353SKristof Provost if (nvl == NULL) 3333032c353SKristof Provost return (NULL); 3343032c353SKristof Provost 3353032c353SKristof Provost nvlist_add_number(nvl, "type", addr->type); 3363032c353SKristof Provost nvlist_add_number(nvl, "iflags", addr->iflags); 337218a8a49SKristof Provost if (addr->type == PF_ADDR_DYNIFTL) { 3383032c353SKristof Provost nvlist_add_string(nvl, "ifname", addr->v.ifname); 339218a8a49SKristof Provost num = 0; 340218a8a49SKristof Provost if (addr->p.dyn != NULL) 341218a8a49SKristof Provost num = addr->p.dyn->pfid_acnt4 + 342218a8a49SKristof Provost addr->p.dyn->pfid_acnt6; 343218a8a49SKristof Provost nvlist_add_number(nvl, "dyncnt", num); 344218a8a49SKristof Provost } 345218a8a49SKristof Provost if (addr->type == PF_ADDR_TABLE) { 3463032c353SKristof Provost nvlist_add_string(nvl, "tblname", addr->v.tblname); 347218a8a49SKristof Provost num = -1; 348218a8a49SKristof Provost kt = addr->p.tbl; 349218a8a49SKristof Provost if ((kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && 350218a8a49SKristof Provost kt->pfrkt_root != NULL) 351218a8a49SKristof Provost kt = kt->pfrkt_root; 352218a8a49SKristof Provost if (kt->pfrkt_flags & PFR_TFLAG_ACTIVE) 353218a8a49SKristof Provost num = kt->pfrkt_cnt; 354218a8a49SKristof Provost nvlist_add_number(nvl, "tblcnt", num); 355218a8a49SKristof Provost } 3563032c353SKristof Provost 3573032c353SKristof Provost tmp = pf_addr_to_nvaddr(&addr->v.a.addr); 3583032c353SKristof Provost if (tmp == NULL) 3593032c353SKristof Provost goto error; 3603032c353SKristof Provost nvlist_add_nvlist(nvl, "addr", tmp); 3613032c353SKristof Provost nvlist_destroy(tmp); 3623032c353SKristof Provost tmp = pf_addr_to_nvaddr(&addr->v.a.mask); 3633032c353SKristof Provost if (tmp == NULL) 3643032c353SKristof Provost goto error; 3653032c353SKristof Provost nvlist_add_nvlist(nvl, "mask", tmp); 3663032c353SKristof Provost nvlist_destroy(tmp); 3673032c353SKristof Provost 3683032c353SKristof Provost return (nvl); 3693032c353SKristof Provost 3703032c353SKristof Provost error: 3713032c353SKristof Provost nvlist_destroy(nvl); 3723032c353SKristof Provost return (NULL); 3733032c353SKristof Provost } 3743032c353SKristof Provost 3753032c353SKristof Provost static int 3763032c353SKristof Provost pf_validate_op(uint8_t op) 3773032c353SKristof Provost { 3783032c353SKristof Provost switch (op) { 3793032c353SKristof Provost case PF_OP_NONE: 3803032c353SKristof Provost case PF_OP_IRG: 3813032c353SKristof Provost case PF_OP_EQ: 3823032c353SKristof Provost case PF_OP_NE: 3833032c353SKristof Provost case PF_OP_LT: 3843032c353SKristof Provost case PF_OP_LE: 3853032c353SKristof Provost case PF_OP_GT: 3863032c353SKristof Provost case PF_OP_GE: 3873032c353SKristof Provost case PF_OP_XRG: 3883032c353SKristof Provost case PF_OP_RRG: 3893032c353SKristof Provost break; 3903032c353SKristof Provost default: 3913032c353SKristof Provost return (EINVAL); 3923032c353SKristof Provost } 3933032c353SKristof Provost 3943032c353SKristof Provost return (0); 3953032c353SKristof Provost } 3963032c353SKristof Provost 3973032c353SKristof Provost static int 3983032c353SKristof Provost pf_nvrule_addr_to_rule_addr(const nvlist_t *nvl, struct pf_rule_addr *addr) 3993032c353SKristof Provost { 4003032c353SKristof Provost int error = 0; 4013032c353SKristof Provost 4023032c353SKristof Provost if (! nvlist_exists_nvlist(nvl, "addr")) 4033032c353SKristof Provost return (EINVAL); 4043032c353SKristof Provost 4053032c353SKristof Provost PFNV_CHK(pf_nvaddr_wrap_to_addr_wrap(nvlist_get_nvlist(nvl, "addr"), 4063032c353SKristof Provost &addr->addr)); 4073032c353SKristof Provost PFNV_CHK(pf_nvuint16_array(nvl, "port", addr->port, 2, NULL)); 4083032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "neg", &addr->neg)); 4093032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "port_op", &addr->port_op)); 4103032c353SKristof Provost 4113032c353SKristof Provost PFNV_CHK(pf_validate_op(addr->port_op)); 4123032c353SKristof Provost 4133032c353SKristof Provost errout: 4143032c353SKristof Provost return (error); 4153032c353SKristof Provost } 4163032c353SKristof Provost 4173032c353SKristof Provost static nvlist_t * 4183032c353SKristof Provost pf_rule_addr_to_nvrule_addr(const struct pf_rule_addr *addr) 4193032c353SKristof Provost { 4203032c353SKristof Provost nvlist_t *nvl; 4213032c353SKristof Provost nvlist_t *tmp; 4223032c353SKristof Provost 4233032c353SKristof Provost nvl = nvlist_create(0); 4243032c353SKristof Provost if (nvl == NULL) 4253032c353SKristof Provost return (NULL); 4263032c353SKristof Provost 4273032c353SKristof Provost tmp = pf_addr_wrap_to_nvaddr_wrap(&addr->addr); 4283032c353SKristof Provost if (tmp == NULL) 4293032c353SKristof Provost goto error; 4303032c353SKristof Provost nvlist_add_nvlist(nvl, "addr", tmp); 4313032c353SKristof Provost nvlist_destroy(tmp); 4323032c353SKristof Provost pf_uint16_array_nv(nvl, "port", addr->port, 2); 4333032c353SKristof Provost nvlist_add_number(nvl, "neg", addr->neg); 4343032c353SKristof Provost nvlist_add_number(nvl, "port_op", addr->port_op); 4353032c353SKristof Provost 4363032c353SKristof Provost return (nvl); 4373032c353SKristof Provost 4383032c353SKristof Provost error: 4393032c353SKristof Provost nvlist_destroy(nvl); 4403032c353SKristof Provost return (NULL); 4413032c353SKristof Provost } 4423032c353SKristof Provost 4433032c353SKristof Provost static int 4443032c353SKristof Provost pf_nvrule_uid_to_rule_uid(const nvlist_t *nvl, struct pf_rule_uid *uid) 4453032c353SKristof Provost { 4463032c353SKristof Provost int error = 0; 4473032c353SKristof Provost 4483032c353SKristof Provost bzero(uid, sizeof(*uid)); 4493032c353SKristof Provost 4503032c353SKristof Provost PFNV_CHK(pf_nvuint32_array(nvl, "uid", uid->uid, 2, NULL)); 4513032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "op", &uid->op)); 4523032c353SKristof Provost 4533032c353SKristof Provost PFNV_CHK(pf_validate_op(uid->op)); 4543032c353SKristof Provost 4553032c353SKristof Provost errout: 4563032c353SKristof Provost return (error); 4573032c353SKristof Provost } 4583032c353SKristof Provost 4593032c353SKristof Provost static nvlist_t * 4603032c353SKristof Provost pf_rule_uid_to_nvrule_uid(const struct pf_rule_uid *uid) 4613032c353SKristof Provost { 4623032c353SKristof Provost nvlist_t *nvl; 4633032c353SKristof Provost 4643032c353SKristof Provost nvl = nvlist_create(0); 4653032c353SKristof Provost if (nvl == NULL) 4663032c353SKristof Provost return (NULL); 4673032c353SKristof Provost 4683032c353SKristof Provost pf_uint32_array_nv(nvl, "uid", uid->uid, 2); 4693032c353SKristof Provost nvlist_add_number(nvl, "op", uid->op); 4703032c353SKristof Provost 4713032c353SKristof Provost return (nvl); 4723032c353SKristof Provost } 4733032c353SKristof Provost 4743032c353SKristof Provost static int 4753032c353SKristof Provost pf_nvrule_gid_to_rule_gid(const nvlist_t *nvl, struct pf_rule_gid *gid) 4763032c353SKristof Provost { 4773032c353SKristof Provost /* Cheat a little. These stucts are the same, other than the name of 4783032c353SKristof Provost * the first field. */ 4793032c353SKristof Provost return (pf_nvrule_uid_to_rule_uid(nvl, (struct pf_rule_uid *)gid)); 4803032c353SKristof Provost } 4813032c353SKristof Provost 4823032c353SKristof Provost int 4833032c353SKristof Provost pf_check_rule_addr(const struct pf_rule_addr *addr) 4843032c353SKristof Provost { 4853032c353SKristof Provost 4863032c353SKristof Provost switch (addr->addr.type) { 4873032c353SKristof Provost case PF_ADDR_ADDRMASK: 4883032c353SKristof Provost case PF_ADDR_NOROUTE: 4893032c353SKristof Provost case PF_ADDR_DYNIFTL: 4903032c353SKristof Provost case PF_ADDR_TABLE: 4913032c353SKristof Provost case PF_ADDR_URPFFAILED: 4923032c353SKristof Provost case PF_ADDR_RANGE: 4933032c353SKristof Provost break; 4943032c353SKristof Provost default: 4953032c353SKristof Provost return (EINVAL); 4963032c353SKristof Provost } 4973032c353SKristof Provost 4983032c353SKristof Provost if (addr->addr.p.dyn != NULL) { 4993032c353SKristof Provost return (EINVAL); 5003032c353SKristof Provost } 5013032c353SKristof Provost 5023032c353SKristof Provost return (0); 5033032c353SKristof Provost } 5043032c353SKristof Provost 5053032c353SKristof Provost 5063032c353SKristof Provost int 5073032c353SKristof Provost pf_nvrule_to_krule(const nvlist_t *nvl, struct pf_krule *rule) 5083032c353SKristof Provost { 5093032c353SKristof Provost int error = 0; 5103032c353SKristof Provost 5113032c353SKristof Provost #define ERROUT(x) ERROUT_FUNCTION(errout, x) 5123032c353SKristof Provost 5133032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "nr", &rule->nr)); 5143032c353SKristof Provost 5153032c353SKristof Provost if (! nvlist_exists_nvlist(nvl, "src")) 5163032c353SKristof Provost ERROUT(EINVAL); 5173032c353SKristof Provost 5183032c353SKristof Provost error = pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "src"), 5193032c353SKristof Provost &rule->src); 5203032c353SKristof Provost if (error != 0) 5213032c353SKristof Provost ERROUT(error); 5223032c353SKristof Provost 5233032c353SKristof Provost if (! nvlist_exists_nvlist(nvl, "dst")) 5243032c353SKristof Provost ERROUT(EINVAL); 5253032c353SKristof Provost 5263032c353SKristof Provost PFNV_CHK(pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "dst"), 5273032c353SKristof Provost &rule->dst)); 5283032c353SKristof Provost 5293032c353SKristof Provost if (nvlist_exists_string(nvl, "label")) { 5303032c353SKristof Provost PFNV_CHK(pf_nvstring(nvl, "label", rule->label[0], 5313032c353SKristof Provost sizeof(rule->label[0]))); 5323032c353SKristof Provost } else if (nvlist_exists_string_array(nvl, "labels")) { 5333032c353SKristof Provost const char *const *strs; 5343032c353SKristof Provost size_t items; 5353032c353SKristof Provost int ret; 5363032c353SKristof Provost 5373032c353SKristof Provost strs = nvlist_get_string_array(nvl, "labels", &items); 5383032c353SKristof Provost if (items > PF_RULE_MAX_LABEL_COUNT) 5393032c353SKristof Provost ERROUT(E2BIG); 5403032c353SKristof Provost 5413032c353SKristof Provost for (size_t i = 0; i < items; i++) { 5423032c353SKristof Provost ret = strlcpy(rule->label[i], strs[i], 5433032c353SKristof Provost sizeof(rule->label[0])); 5443032c353SKristof Provost if (ret >= sizeof(rule->label[0])) 5453032c353SKristof Provost ERROUT(E2BIG); 5463032c353SKristof Provost } 5473032c353SKristof Provost } 5483032c353SKristof Provost 54976c5eeccSKristof Provost PFNV_CHK(pf_nvuint32_opt(nvl, "ridentifier", &rule->ridentifier, 0)); 5503032c353SKristof Provost PFNV_CHK(pf_nvstring(nvl, "ifname", rule->ifname, 5513032c353SKristof Provost sizeof(rule->ifname))); 5523032c353SKristof Provost PFNV_CHK(pf_nvstring(nvl, "qname", rule->qname, sizeof(rule->qname))); 5533032c353SKristof Provost PFNV_CHK(pf_nvstring(nvl, "pqname", rule->pqname, 5543032c353SKristof Provost sizeof(rule->pqname))); 5553032c353SKristof Provost PFNV_CHK(pf_nvstring(nvl, "tagname", rule->tagname, 5563032c353SKristof Provost sizeof(rule->tagname))); 55763b3c1c7SKristof Provost PFNV_CHK(pf_nvuint16_opt(nvl, "dnpipe", &rule->dnpipe, 0)); 55863b3c1c7SKristof Provost PFNV_CHK(pf_nvuint16_opt(nvl, "dnrpipe", &rule->dnrpipe, 0)); 55963b3c1c7SKristof Provost PFNV_CHK(pf_nvuint32_opt(nvl, "dnflags", &rule->free_flags, 0)); 5603032c353SKristof Provost PFNV_CHK(pf_nvstring(nvl, "match_tagname", rule->match_tagname, 5613032c353SKristof Provost sizeof(rule->match_tagname))); 5623032c353SKristof Provost PFNV_CHK(pf_nvstring(nvl, "overload_tblname", rule->overload_tblname, 5633032c353SKristof Provost sizeof(rule->overload_tblname))); 5643032c353SKristof Provost 5653032c353SKristof Provost if (! nvlist_exists_nvlist(nvl, "rpool")) 5663032c353SKristof Provost ERROUT(EINVAL); 5673032c353SKristof Provost PFNV_CHK(pf_nvpool_to_pool(nvlist_get_nvlist(nvl, "rpool"), 5683032c353SKristof Provost &rule->rpool)); 5693032c353SKristof Provost 5703032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "os_fingerprint", &rule->os_fingerprint)); 5713032c353SKristof Provost 5723032c353SKristof Provost PFNV_CHK(pf_nvint(nvl, "rtableid", &rule->rtableid)); 5733032c353SKristof Provost PFNV_CHK(pf_nvuint32_array(nvl, "timeout", rule->timeout, PFTM_MAX, NULL)); 5743032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "max_states", &rule->max_states)); 5753032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "max_src_nodes", &rule->max_src_nodes)); 5763032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "max_src_states", &rule->max_src_states)); 5773032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "max_src_conn", &rule->max_src_conn)); 5783032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "max_src_conn_rate.limit", 5793032c353SKristof Provost &rule->max_src_conn_rate.limit)); 5803032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "max_src_conn_rate.seconds", 5813032c353SKristof Provost &rule->max_src_conn_rate.seconds)); 5823032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "prob", &rule->prob)); 5833032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "cuid", &rule->cuid)); 5843032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "cpid", &rule->cpid)); 5853032c353SKristof Provost 5863032c353SKristof Provost PFNV_CHK(pf_nvuint16(nvl, "return_icmp", &rule->return_icmp)); 5873032c353SKristof Provost PFNV_CHK(pf_nvuint16(nvl, "return_icmp6", &rule->return_icmp6)); 5883032c353SKristof Provost 5893032c353SKristof Provost PFNV_CHK(pf_nvuint16(nvl, "max_mss", &rule->max_mss)); 5903032c353SKristof Provost PFNV_CHK(pf_nvuint16(nvl, "scrub_flags", &rule->scrub_flags)); 5913032c353SKristof Provost 5923032c353SKristof Provost if (! nvlist_exists_nvlist(nvl, "uid")) 5933032c353SKristof Provost ERROUT(EINVAL); 5943032c353SKristof Provost PFNV_CHK(pf_nvrule_uid_to_rule_uid(nvlist_get_nvlist(nvl, "uid"), 5953032c353SKristof Provost &rule->uid)); 5963032c353SKristof Provost 5973032c353SKristof Provost if (! nvlist_exists_nvlist(nvl, "gid")) 5983032c353SKristof Provost ERROUT(EINVAL); 5993032c353SKristof Provost PFNV_CHK(pf_nvrule_gid_to_rule_gid(nvlist_get_nvlist(nvl, "gid"), 6003032c353SKristof Provost &rule->gid)); 6013032c353SKristof Provost 6023032c353SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "rule_flag", &rule->rule_flag)); 6033032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "action", &rule->action)); 6043032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "direction", &rule->direction)); 6053032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "log", &rule->log)); 6063032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "logif", &rule->logif)); 6073032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "quick", &rule->quick)); 6083032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "ifnot", &rule->ifnot)); 6093032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "match_tag_not", &rule->match_tag_not)); 6103032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "natpass", &rule->natpass)); 6113032c353SKristof Provost 6123032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "keep_state", &rule->keep_state)); 6133032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "af", &rule->af)); 6143032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "proto", &rule->proto)); 6153032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "type", &rule->type)); 6163032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "code", &rule->code)); 6173032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "flags", &rule->flags)); 6183032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "flagset", &rule->flagset)); 6193032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "min_ttl", &rule->min_ttl)); 6203032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "allow_opts", &rule->allow_opts)); 6213032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "rt", &rule->rt)); 6223032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "return_ttl", &rule->return_ttl)); 6233032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "tos", &rule->tos)); 6243032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "set_tos", &rule->set_tos)); 6253032c353SKristof Provost 6263032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "flush", &rule->flush)); 6273032c353SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "prio", &rule->prio)); 6283032c353SKristof Provost 6290143a6bbSFranco Fichtner PFNV_CHK(pf_nvuint8_array(nvl, "set_prio", rule->set_prio, 2, NULL)); 6303032c353SKristof Provost 6313032c353SKristof Provost if (nvlist_exists_nvlist(nvl, "divert")) { 6323032c353SKristof Provost const nvlist_t *nvldivert = nvlist_get_nvlist(nvl, "divert"); 6333032c353SKristof Provost 6343032c353SKristof Provost if (! nvlist_exists_nvlist(nvldivert, "addr")) 6353032c353SKristof Provost ERROUT(EINVAL); 6363032c353SKristof Provost PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvldivert, "addr"), 6373032c353SKristof Provost &rule->divert.addr)); 6383032c353SKristof Provost PFNV_CHK(pf_nvuint16(nvldivert, "port", &rule->divert.port)); 6393032c353SKristof Provost } 6403032c353SKristof Provost 6413032c353SKristof Provost /* Validation */ 6423032c353SKristof Provost #ifndef INET 6433032c353SKristof Provost if (rule->af == AF_INET) 6443032c353SKristof Provost ERROUT(EAFNOSUPPORT); 6453032c353SKristof Provost #endif /* INET */ 6463032c353SKristof Provost #ifndef INET6 6473032c353SKristof Provost if (rule->af == AF_INET6) 6483032c353SKristof Provost ERROUT(EAFNOSUPPORT); 6493032c353SKristof Provost #endif /* INET6 */ 6503032c353SKristof Provost 6513032c353SKristof Provost PFNV_CHK(pf_check_rule_addr(&rule->src)); 6523032c353SKristof Provost PFNV_CHK(pf_check_rule_addr(&rule->dst)); 6533032c353SKristof Provost 6543032c353SKristof Provost return (0); 6553032c353SKristof Provost 6563032c353SKristof Provost #undef ERROUT 6573032c353SKristof Provost errout: 6583032c353SKristof Provost return (error); 6593032c353SKristof Provost } 6603032c353SKristof Provost 6613032c353SKristof Provost static nvlist_t * 6623032c353SKristof Provost pf_divert_to_nvdivert(const struct pf_krule *rule) 6633032c353SKristof Provost { 6643032c353SKristof Provost nvlist_t *nvl; 6653032c353SKristof Provost nvlist_t *tmp; 6663032c353SKristof Provost 6673032c353SKristof Provost nvl = nvlist_create(0); 6683032c353SKristof Provost if (nvl == NULL) 6693032c353SKristof Provost return (NULL); 6703032c353SKristof Provost 6713032c353SKristof Provost tmp = pf_addr_to_nvaddr(&rule->divert.addr); 6723032c353SKristof Provost if (tmp == NULL) 6733032c353SKristof Provost goto error; 6743032c353SKristof Provost nvlist_add_nvlist(nvl, "addr", tmp); 6753032c353SKristof Provost nvlist_destroy(tmp); 6763032c353SKristof Provost nvlist_add_number(nvl, "port", rule->divert.port); 6773032c353SKristof Provost 6783032c353SKristof Provost return (nvl); 6793032c353SKristof Provost 6803032c353SKristof Provost error: 6813032c353SKristof Provost nvlist_destroy(nvl); 6823032c353SKristof Provost return (NULL); 6833032c353SKristof Provost } 6843032c353SKristof Provost 6853032c353SKristof Provost nvlist_t * 68602cf67ccSMateusz Guzik pf_krule_to_nvrule(struct pf_krule *rule) 6873032c353SKristof Provost { 6883032c353SKristof Provost nvlist_t *nvl, *tmp; 6893032c353SKristof Provost 6903032c353SKristof Provost nvl = nvlist_create(0); 6913032c353SKristof Provost if (nvl == NULL) 6923032c353SKristof Provost return (nvl); 6933032c353SKristof Provost 6943032c353SKristof Provost nvlist_add_number(nvl, "nr", rule->nr); 6953032c353SKristof Provost tmp = pf_rule_addr_to_nvrule_addr(&rule->src); 6963032c353SKristof Provost if (tmp == NULL) 6973032c353SKristof Provost goto error; 6983032c353SKristof Provost nvlist_add_nvlist(nvl, "src", tmp); 6993032c353SKristof Provost nvlist_destroy(tmp); 7003032c353SKristof Provost tmp = pf_rule_addr_to_nvrule_addr(&rule->dst); 7013032c353SKristof Provost if (tmp == NULL) 7023032c353SKristof Provost goto error; 7033032c353SKristof Provost nvlist_add_nvlist(nvl, "dst", tmp); 7043032c353SKristof Provost nvlist_destroy(tmp); 7053032c353SKristof Provost 7063032c353SKristof Provost for (int i = 0; i < PF_SKIP_COUNT; i++) { 7073032c353SKristof Provost nvlist_append_number_array(nvl, "skip", 7083032c353SKristof Provost rule->skip[i].ptr ? rule->skip[i].ptr->nr : -1); 7093032c353SKristof Provost } 7103032c353SKristof Provost 7113032c353SKristof Provost for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++) { 7123032c353SKristof Provost nvlist_append_string_array(nvl, "labels", rule->label[i]); 7133032c353SKristof Provost } 7143032c353SKristof Provost nvlist_add_string(nvl, "label", rule->label[0]); 71576c5eeccSKristof Provost nvlist_add_number(nvl, "ridentifier", rule->ridentifier); 7163032c353SKristof Provost nvlist_add_string(nvl, "ifname", rule->ifname); 7173032c353SKristof Provost nvlist_add_string(nvl, "qname", rule->qname); 7183032c353SKristof Provost nvlist_add_string(nvl, "pqname", rule->pqname); 71963b3c1c7SKristof Provost nvlist_add_number(nvl, "dnpipe", rule->dnpipe); 72063b3c1c7SKristof Provost nvlist_add_number(nvl, "dnrpipe", rule->dnrpipe); 72163b3c1c7SKristof Provost nvlist_add_number(nvl, "dnflags", rule->free_flags); 7223032c353SKristof Provost nvlist_add_string(nvl, "tagname", rule->tagname); 7233032c353SKristof Provost nvlist_add_string(nvl, "match_tagname", rule->match_tagname); 7243032c353SKristof Provost nvlist_add_string(nvl, "overload_tblname", rule->overload_tblname); 7253032c353SKristof Provost 7263032c353SKristof Provost tmp = pf_pool_to_nvpool(&rule->rpool); 7273032c353SKristof Provost if (tmp == NULL) 7283032c353SKristof Provost goto error; 7293032c353SKristof Provost nvlist_add_nvlist(nvl, "rpool", tmp); 7303032c353SKristof Provost nvlist_destroy(tmp); 7313032c353SKristof Provost 7323032c353SKristof Provost nvlist_add_number(nvl, "evaluations", 73302cf67ccSMateusz Guzik pf_counter_u64_fetch(&rule->evaluations)); 7343032c353SKristof Provost for (int i = 0; i < 2; i++) { 7353032c353SKristof Provost nvlist_append_number_array(nvl, "packets", 73602cf67ccSMateusz Guzik pf_counter_u64_fetch(&rule->packets[i])); 7373032c353SKristof Provost nvlist_append_number_array(nvl, "bytes", 73802cf67ccSMateusz Guzik pf_counter_u64_fetch(&rule->bytes[i])); 7393032c353SKristof Provost } 7400abcc1d2SReid Linnemann nvlist_add_number(nvl, "timestamp", pf_get_timestamp(rule)); 7413032c353SKristof Provost 7423032c353SKristof Provost nvlist_add_number(nvl, "os_fingerprint", rule->os_fingerprint); 7433032c353SKristof Provost 7443032c353SKristof Provost nvlist_add_number(nvl, "rtableid", rule->rtableid); 7453032c353SKristof Provost pf_uint32_array_nv(nvl, "timeout", rule->timeout, PFTM_MAX); 7463032c353SKristof Provost nvlist_add_number(nvl, "max_states", rule->max_states); 7473032c353SKristof Provost nvlist_add_number(nvl, "max_src_nodes", rule->max_src_nodes); 7483032c353SKristof Provost nvlist_add_number(nvl, "max_src_states", rule->max_src_states); 7493032c353SKristof Provost nvlist_add_number(nvl, "max_src_conn", rule->max_src_conn); 7503032c353SKristof Provost nvlist_add_number(nvl, "max_src_conn_rate.limit", 7513032c353SKristof Provost rule->max_src_conn_rate.limit); 7523032c353SKristof Provost nvlist_add_number(nvl, "max_src_conn_rate.seconds", 7533032c353SKristof Provost rule->max_src_conn_rate.seconds); 7543032c353SKristof Provost nvlist_add_number(nvl, "qid", rule->qid); 7553032c353SKristof Provost nvlist_add_number(nvl, "pqid", rule->pqid); 7563032c353SKristof Provost nvlist_add_number(nvl, "prob", rule->prob); 7573032c353SKristof Provost nvlist_add_number(nvl, "cuid", rule->cuid); 7583032c353SKristof Provost nvlist_add_number(nvl, "cpid", rule->cpid); 7593032c353SKristof Provost 7603032c353SKristof Provost nvlist_add_number(nvl, "states_cur", 7613032c353SKristof Provost counter_u64_fetch(rule->states_cur)); 7623032c353SKristof Provost nvlist_add_number(nvl, "states_tot", 7633032c353SKristof Provost counter_u64_fetch(rule->states_tot)); 7643032c353SKristof Provost nvlist_add_number(nvl, "src_nodes", 7653032c353SKristof Provost counter_u64_fetch(rule->src_nodes)); 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 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 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 8783032c353SKristof Provost errout: 8793032c353SKristof Provost return (error); 8803032c353SKristof Provost } 8813032c353SKristof Provost 8823032c353SKristof Provost static nvlist_t * 8833032c353SKristof Provost pf_state_key_to_nvstate_key(const struct pf_state_key *key) 8843032c353SKristof Provost { 8853032c353SKristof Provost nvlist_t *nvl, *tmp; 8863032c353SKristof Provost 8873032c353SKristof Provost nvl = nvlist_create(0); 8883032c353SKristof Provost if (nvl == NULL) 8893032c353SKristof Provost return (NULL); 8903032c353SKristof Provost 8913032c353SKristof Provost for (int i = 0; i < 2; i++) { 8923032c353SKristof Provost tmp = pf_addr_to_nvaddr(&key->addr[i]); 8933032c353SKristof Provost if (tmp == NULL) 8943032c353SKristof Provost goto errout; 8953032c353SKristof Provost nvlist_append_nvlist_array(nvl, "addr", tmp); 8960f86492bSKristof Provost nvlist_destroy(tmp); 8973032c353SKristof Provost nvlist_append_number_array(nvl, "port", key->port[i]); 8983032c353SKristof Provost } 8993032c353SKristof Provost nvlist_add_number(nvl, "af", key->af); 9003032c353SKristof Provost nvlist_add_number(nvl, "proto", key->proto); 9013032c353SKristof Provost 9023032c353SKristof Provost return (nvl); 9033032c353SKristof Provost 9043032c353SKristof Provost errout: 9053032c353SKristof Provost nvlist_destroy(nvl); 9063032c353SKristof Provost return (NULL); 9073032c353SKristof Provost } 9083032c353SKristof Provost 9093032c353SKristof Provost static nvlist_t * 91034285eefSKristof Provost pf_state_peer_to_nvstate_peer(const struct pf_state_peer *peer) 9113032c353SKristof Provost { 9123032c353SKristof Provost nvlist_t *nvl; 9133032c353SKristof Provost 9143032c353SKristof Provost nvl = nvlist_create(0); 9153032c353SKristof Provost if (nvl == NULL) 9163032c353SKristof Provost return (NULL); 9173032c353SKristof Provost 9183032c353SKristof Provost nvlist_add_number(nvl, "seqlo", peer->seqlo); 9193032c353SKristof Provost nvlist_add_number(nvl, "seqhi", peer->seqhi); 9203032c353SKristof Provost nvlist_add_number(nvl, "seqdiff", peer->seqdiff); 9213032c353SKristof Provost nvlist_add_number(nvl, "state", peer->state); 9223032c353SKristof Provost nvlist_add_number(nvl, "wscale", peer->wscale); 9233032c353SKristof Provost 9243032c353SKristof Provost return (nvl); 9253032c353SKristof Provost } 9263032c353SKristof Provost 9273032c353SKristof Provost nvlist_t * 928211cddf9SKristof Provost pf_state_to_nvstate(const struct pf_kstate *s) 9293032c353SKristof Provost { 9303032c353SKristof Provost nvlist_t *nvl, *tmp; 9313032c353SKristof Provost uint32_t expire, flags = 0; 9323032c353SKristof Provost 9333032c353SKristof Provost nvl = nvlist_create(0); 9343032c353SKristof Provost if (nvl == NULL) 9353032c353SKristof Provost return (NULL); 9363032c353SKristof Provost 9373032c353SKristof Provost nvlist_add_number(nvl, "id", s->id); 9383032c353SKristof Provost nvlist_add_string(nvl, "ifname", s->kif->pfik_name); 9393032c353SKristof Provost nvlist_add_string(nvl, "orig_ifname", s->orig_kif->pfik_name); 9403032c353SKristof Provost 9413032c353SKristof Provost tmp = pf_state_key_to_nvstate_key(s->key[PF_SK_STACK]); 9423032c353SKristof Provost if (tmp == NULL) 9433032c353SKristof Provost goto errout; 9443032c353SKristof Provost nvlist_add_nvlist(nvl, "stack_key", tmp); 9453032c353SKristof Provost nvlist_destroy(tmp); 9463032c353SKristof Provost 9473032c353SKristof Provost tmp = pf_state_key_to_nvstate_key(s->key[PF_SK_WIRE]); 9483032c353SKristof Provost if (tmp == NULL) 9493032c353SKristof Provost goto errout; 9503032c353SKristof Provost nvlist_add_nvlist(nvl, "wire_key", tmp); 9513032c353SKristof Provost nvlist_destroy(tmp); 9523032c353SKristof Provost 9533032c353SKristof Provost tmp = pf_state_peer_to_nvstate_peer(&s->src); 9543032c353SKristof Provost if (tmp == NULL) 9553032c353SKristof Provost goto errout; 9563032c353SKristof Provost nvlist_add_nvlist(nvl, "src", tmp); 9573032c353SKristof Provost nvlist_destroy(tmp); 9583032c353SKristof Provost 9593032c353SKristof Provost tmp = pf_state_peer_to_nvstate_peer(&s->dst); 9603032c353SKristof Provost if (tmp == NULL) 9613032c353SKristof Provost goto errout; 9623032c353SKristof Provost nvlist_add_nvlist(nvl, "dst", tmp); 9633032c353SKristof Provost nvlist_destroy(tmp); 9643032c353SKristof Provost 9653032c353SKristof Provost tmp = pf_addr_to_nvaddr(&s->rt_addr); 9663032c353SKristof Provost if (tmp == NULL) 9673032c353SKristof Provost goto errout; 9683032c353SKristof Provost nvlist_add_nvlist(nvl, "rt_addr", tmp); 9693032c353SKristof Provost nvlist_destroy(tmp); 9703032c353SKristof Provost 9713032c353SKristof Provost nvlist_add_number(nvl, "rule", s->rule.ptr ? s->rule.ptr->nr : -1); 9723032c353SKristof Provost nvlist_add_number(nvl, "anchor", 9733032c353SKristof Provost s->anchor.ptr ? s->anchor.ptr->nr : -1); 9743032c353SKristof Provost nvlist_add_number(nvl, "nat_rule", 9753032c353SKristof Provost s->nat_rule.ptr ? s->nat_rule.ptr->nr : -1); 9763032c353SKristof Provost nvlist_add_number(nvl, "creation", s->creation); 9773032c353SKristof Provost 9783032c353SKristof Provost expire = pf_state_expires(s); 9793032c353SKristof Provost if (expire <= time_uptime) 9803032c353SKristof Provost expire = 0; 9813032c353SKristof Provost else 9823032c353SKristof Provost expire = expire - time_uptime; 9833032c353SKristof Provost nvlist_add_number(nvl, "expire", expire); 9843032c353SKristof Provost 9853032c353SKristof Provost for (int i = 0; i < 2; i++) { 9863032c353SKristof Provost nvlist_append_number_array(nvl, "packets", 98755cc305dSMateusz Guzik s->packets[i]); 9883032c353SKristof Provost nvlist_append_number_array(nvl, "bytes", 98955cc305dSMateusz Guzik s->bytes[i]); 9903032c353SKristof Provost } 9913032c353SKristof Provost 9923032c353SKristof Provost nvlist_add_number(nvl, "creatorid", s->creatorid); 9933032c353SKristof Provost nvlist_add_number(nvl, "direction", s->direction); 9943032c353SKristof Provost nvlist_add_number(nvl, "state_flags", s->state_flags); 9953032c353SKristof Provost if (s->src_node) 9963032c353SKristof Provost flags |= PFSYNC_FLAG_SRCNODE; 9973032c353SKristof Provost if (s->nat_src_node) 9983032c353SKristof Provost flags |= PFSYNC_FLAG_NATSRCNODE; 9993032c353SKristof Provost nvlist_add_number(nvl, "sync_flags", flags); 10003032c353SKristof Provost 10013032c353SKristof Provost return (nvl); 10023032c353SKristof Provost 10033032c353SKristof Provost errout: 10043032c353SKristof Provost nvlist_destroy(nvl); 10053032c353SKristof Provost return (NULL); 10063032c353SKristof Provost } 1007e732e742SKristof Provost 1008e732e742SKristof Provost static int 1009e732e742SKristof Provost pf_nveth_rule_addr_to_keth_rule_addr(const nvlist_t *nvl, 1010e732e742SKristof Provost struct pf_keth_rule_addr *krule) 1011e732e742SKristof Provost { 1012e732e742SKristof Provost static const u_int8_t EMPTY_MAC[ETHER_ADDR_LEN] = { 0 }; 1013e732e742SKristof Provost int error = 0; 1014e732e742SKristof Provost 1015e732e742SKristof Provost PFNV_CHK(pf_nvbinary(nvl, "addr", &krule->addr, sizeof(krule->addr))); 1016e732e742SKristof Provost PFNV_CHK(pf_nvbool(nvl, "neg", &krule->neg)); 1017b590f17aSKristof Provost if (nvlist_exists_binary(nvl, "mask")) 1018b590f17aSKristof Provost PFNV_CHK(pf_nvbinary(nvl, "mask", &krule->mask, 1019b590f17aSKristof Provost sizeof(krule->mask))); 1020e732e742SKristof Provost 1021e732e742SKristof Provost /* To make checks for 'is this address set?' easier. */ 1022e732e742SKristof Provost if (memcmp(krule->addr, EMPTY_MAC, ETHER_ADDR_LEN) != 0) 1023e732e742SKristof Provost krule->isset = 1; 1024e732e742SKristof Provost 1025e732e742SKristof Provost errout: 1026e732e742SKristof Provost return (error); 1027e732e742SKristof Provost } 1028e732e742SKristof Provost 1029e732e742SKristof Provost static nvlist_t* 1030e732e742SKristof Provost pf_keth_rule_addr_to_nveth_rule_addr(const struct pf_keth_rule_addr *krule) 1031e732e742SKristof Provost { 1032e732e742SKristof Provost nvlist_t *nvl; 1033e732e742SKristof Provost 1034e732e742SKristof Provost nvl = nvlist_create(0); 1035e732e742SKristof Provost if (nvl == NULL) 1036e732e742SKristof Provost return (NULL); 1037e732e742SKristof Provost 1038e732e742SKristof Provost nvlist_add_binary(nvl, "addr", &krule->addr, sizeof(krule->addr)); 1039b590f17aSKristof Provost nvlist_add_binary(nvl, "mask", &krule->mask, sizeof(krule->mask)); 1040e732e742SKristof Provost nvlist_add_bool(nvl, "neg", krule->neg); 1041e732e742SKristof Provost 1042e732e742SKristof Provost return (nvl); 1043e732e742SKristof Provost } 1044e732e742SKristof Provost 1045e732e742SKristof Provost nvlist_t* 1046e732e742SKristof Provost pf_keth_rule_to_nveth_rule(const struct pf_keth_rule *krule) 1047e732e742SKristof Provost { 1048e732e742SKristof Provost nvlist_t *nvl, *addr; 1049e732e742SKristof Provost 1050e732e742SKristof Provost nvl = nvlist_create(0); 1051e732e742SKristof Provost if (nvl == NULL) 1052e732e742SKristof Provost return (NULL); 1053e732e742SKristof Provost 1054*ef661d4aSChristian McDonald for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++) { 1055*ef661d4aSChristian McDonald nvlist_append_string_array(nvl, "labels", krule->label[i]); 1056*ef661d4aSChristian McDonald } 1057*ef661d4aSChristian McDonald nvlist_add_number(nvl, "ridentifier", krule->ridentifier); 1058*ef661d4aSChristian McDonald 1059e732e742SKristof Provost nvlist_add_number(nvl, "nr", krule->nr); 1060e732e742SKristof Provost nvlist_add_bool(nvl, "quick", krule->quick); 1061e732e742SKristof Provost nvlist_add_string(nvl, "ifname", krule->ifname); 1062e732e742SKristof Provost nvlist_add_bool(nvl, "ifnot", krule->ifnot); 1063e732e742SKristof Provost nvlist_add_number(nvl, "direction", krule->direction); 1064e732e742SKristof Provost nvlist_add_number(nvl, "proto", krule->proto); 10651f61367fSKristof Provost nvlist_add_string(nvl, "match_tagname", krule->match_tagname); 10661f61367fSKristof Provost nvlist_add_number(nvl, "match_tag", krule->match_tag); 10671f61367fSKristof Provost nvlist_add_bool(nvl, "match_tag_not", krule->match_tag_not); 1068e732e742SKristof Provost 1069e732e742SKristof Provost addr = pf_keth_rule_addr_to_nveth_rule_addr(&krule->src); 1070e732e742SKristof Provost if (addr == NULL) { 1071e732e742SKristof Provost nvlist_destroy(nvl); 1072e732e742SKristof Provost return (NULL); 1073e732e742SKristof Provost } 1074e732e742SKristof Provost nvlist_add_nvlist(nvl, "src", addr); 10750044bd90SKristof Provost nvlist_destroy(addr); 1076e732e742SKristof Provost 1077e732e742SKristof Provost addr = pf_keth_rule_addr_to_nveth_rule_addr(&krule->dst); 1078e732e742SKristof Provost if (addr == NULL) { 1079e732e742SKristof Provost nvlist_destroy(nvl); 1080e732e742SKristof Provost return (NULL); 1081e732e742SKristof Provost } 1082e732e742SKristof Provost nvlist_add_nvlist(nvl, "dst", addr); 10830044bd90SKristof Provost nvlist_destroy(addr); 1084e732e742SKristof Provost 10858a42005dSKristof Provost addr = pf_rule_addr_to_nvrule_addr(&krule->ipsrc); 10868a42005dSKristof Provost if (addr == NULL) { 10878a42005dSKristof Provost nvlist_destroy(nvl); 10888a42005dSKristof Provost return (NULL); 10898a42005dSKristof Provost } 10908a42005dSKristof Provost nvlist_add_nvlist(nvl, "ipsrc", addr); 10918a42005dSKristof Provost nvlist_destroy(addr); 10928a42005dSKristof Provost 10938a42005dSKristof Provost addr = pf_rule_addr_to_nvrule_addr(&krule->ipdst); 10948a42005dSKristof Provost if (addr == NULL) { 10958a42005dSKristof Provost nvlist_destroy(nvl); 10968a42005dSKristof Provost return (NULL); 10978a42005dSKristof Provost } 10988a42005dSKristof Provost nvlist_add_nvlist(nvl, "ipdst", addr); 10998a42005dSKristof Provost nvlist_destroy(addr); 11008a42005dSKristof Provost 1101e732e742SKristof Provost nvlist_add_number(nvl, "evaluations", 1102e732e742SKristof Provost counter_u64_fetch(krule->evaluations)); 1103e732e742SKristof Provost nvlist_add_number(nvl, "packets-in", 1104e732e742SKristof Provost counter_u64_fetch(krule->packets[0])); 1105e732e742SKristof Provost nvlist_add_number(nvl, "packets-out", 1106e732e742SKristof Provost counter_u64_fetch(krule->packets[1])); 1107e732e742SKristof Provost nvlist_add_number(nvl, "bytes-in", 1108e732e742SKristof Provost counter_u64_fetch(krule->bytes[0])); 1109e732e742SKristof Provost nvlist_add_number(nvl, "bytes-out", 1110e732e742SKristof Provost counter_u64_fetch(krule->bytes[1])); 1111e732e742SKristof Provost 11120abcc1d2SReid Linnemann nvlist_add_number(nvl, "timestamp", pf_get_timestamp(krule)); 1113e732e742SKristof Provost nvlist_add_string(nvl, "qname", krule->qname); 1114e732e742SKristof Provost nvlist_add_string(nvl, "tagname", krule->tagname); 1115e732e742SKristof Provost 1116fb330f39SKristof Provost nvlist_add_number(nvl, "dnpipe", krule->dnpipe); 1117fb330f39SKristof Provost nvlist_add_number(nvl, "dnflags", krule->dnflags); 1118fb330f39SKristof Provost 1119c5131afeSKristof Provost nvlist_add_number(nvl, "anchor_relative", krule->anchor_relative); 1120c5131afeSKristof Provost nvlist_add_number(nvl, "anchor_wildcard", krule->anchor_wildcard); 1121c5131afeSKristof Provost 11228a8af942SKristof Provost nvlist_add_string(nvl, "bridge_to", krule->bridge_to_name); 1123e732e742SKristof Provost nvlist_add_number(nvl, "action", krule->action); 1124e732e742SKristof Provost 1125e732e742SKristof Provost return (nvl); 1126e732e742SKristof Provost } 1127e732e742SKristof Provost 1128e732e742SKristof Provost int 1129e732e742SKristof Provost pf_nveth_rule_to_keth_rule(const nvlist_t *nvl, 1130e732e742SKristof Provost struct pf_keth_rule *krule) 1131e732e742SKristof Provost { 1132fb330f39SKristof Provost int error = 0; 1133e732e742SKristof Provost 1134*ef661d4aSChristian McDonald #define ERROUT(x) ERROUT_FUNCTION(errout, x) 1135*ef661d4aSChristian McDonald 1136e732e742SKristof Provost bzero(krule, sizeof(*krule)); 1137e732e742SKristof Provost 1138*ef661d4aSChristian McDonald if (nvlist_exists_string_array(nvl, "labels")) { 1139*ef661d4aSChristian McDonald const char *const *strs; 1140*ef661d4aSChristian McDonald size_t items; 1141*ef661d4aSChristian McDonald int ret; 1142*ef661d4aSChristian McDonald 1143*ef661d4aSChristian McDonald strs = nvlist_get_string_array(nvl, "labels", &items); 1144*ef661d4aSChristian McDonald if (items > PF_RULE_MAX_LABEL_COUNT) 1145*ef661d4aSChristian McDonald ERROUT(E2BIG); 1146*ef661d4aSChristian McDonald 1147*ef661d4aSChristian McDonald for (size_t i = 0; i < items; i++) { 1148*ef661d4aSChristian McDonald ret = strlcpy(krule->label[i], strs[i], 1149*ef661d4aSChristian McDonald sizeof(krule->label[0])); 1150*ef661d4aSChristian McDonald if (ret >= sizeof(krule->label[0])) 1151*ef661d4aSChristian McDonald ERROUT(E2BIG); 1152*ef661d4aSChristian McDonald } 1153*ef661d4aSChristian McDonald } 1154*ef661d4aSChristian McDonald 1155*ef661d4aSChristian McDonald PFNV_CHK(pf_nvuint32_opt(nvl, "ridentifier", &krule->ridentifier, 0)); 1156*ef661d4aSChristian McDonald 1157e732e742SKristof Provost PFNV_CHK(pf_nvuint32(nvl, "nr", &krule->nr)); 1158e732e742SKristof Provost PFNV_CHK(pf_nvbool(nvl, "quick", &krule->quick)); 1159e732e742SKristof Provost PFNV_CHK(pf_nvstring(nvl, "ifname", krule->ifname, 1160e732e742SKristof Provost sizeof(krule->ifname))); 1161e732e742SKristof Provost PFNV_CHK(pf_nvbool(nvl, "ifnot", &krule->ifnot)); 1162e732e742SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "direction", &krule->direction)); 1163e732e742SKristof Provost PFNV_CHK(pf_nvuint16(nvl, "proto", &krule->proto)); 1164e732e742SKristof Provost 1165e732e742SKristof Provost if (nvlist_exists_nvlist(nvl, "src")) { 1166e732e742SKristof Provost error = pf_nveth_rule_addr_to_keth_rule_addr( 1167e732e742SKristof Provost nvlist_get_nvlist(nvl, "src"), &krule->src); 1168e732e742SKristof Provost if (error) 1169e732e742SKristof Provost return (error); 1170e732e742SKristof Provost } 1171e732e742SKristof Provost if (nvlist_exists_nvlist(nvl, "dst")) { 1172e732e742SKristof Provost error = pf_nveth_rule_addr_to_keth_rule_addr( 1173e732e742SKristof Provost nvlist_get_nvlist(nvl, "dst"), &krule->dst); 1174e732e742SKristof Provost if (error) 1175e732e742SKristof Provost return (error); 1176e732e742SKristof Provost } 1177e732e742SKristof Provost 11788a42005dSKristof Provost if (nvlist_exists_nvlist(nvl, "ipsrc")) { 11798a42005dSKristof Provost error = pf_nvrule_addr_to_rule_addr( 11808a42005dSKristof Provost nvlist_get_nvlist(nvl, "ipsrc"), &krule->ipsrc); 11818a42005dSKristof Provost if (error != 0) 11828a42005dSKristof Provost return (error); 11833468cd95SKristof Provost 1184812839e5SKristof Provost if (krule->ipsrc.addr.type != PF_ADDR_ADDRMASK && 1185812839e5SKristof Provost krule->ipsrc.addr.type != PF_ADDR_TABLE) 11863468cd95SKristof Provost return (EINVAL); 11878a42005dSKristof Provost } 11888a42005dSKristof Provost 11898a42005dSKristof Provost if (nvlist_exists_nvlist(nvl, "ipdst")) { 11908a42005dSKristof Provost error = pf_nvrule_addr_to_rule_addr( 11918a42005dSKristof Provost nvlist_get_nvlist(nvl, "ipdst"), &krule->ipdst); 11928a42005dSKristof Provost if (error != 0) 11938a42005dSKristof Provost return (error); 11943468cd95SKristof Provost 1195812839e5SKristof Provost if (krule->ipdst.addr.type != PF_ADDR_ADDRMASK && 1196812839e5SKristof Provost krule->ipdst.addr.type != PF_ADDR_TABLE) 11973468cd95SKristof Provost return (EINVAL); 11988a42005dSKristof Provost } 11998a42005dSKristof Provost 12001f61367fSKristof Provost if (nvlist_exists_string(nvl, "match_tagname")) { 12011f61367fSKristof Provost PFNV_CHK(pf_nvstring(nvl, "match_tagname", krule->match_tagname, 12021f61367fSKristof Provost sizeof(krule->match_tagname))); 12031f61367fSKristof Provost PFNV_CHK(pf_nvbool(nvl, "match_tag_not", &krule->match_tag_not)); 12041f61367fSKristof Provost } 12051f61367fSKristof Provost 1206e732e742SKristof Provost PFNV_CHK(pf_nvstring(nvl, "qname", krule->qname, sizeof(krule->qname))); 1207e732e742SKristof Provost PFNV_CHK(pf_nvstring(nvl, "tagname", krule->tagname, 1208e732e742SKristof Provost sizeof(krule->tagname))); 1209e732e742SKristof Provost 1210fb330f39SKristof Provost PFNV_CHK(pf_nvuint16_opt(nvl, "dnpipe", &krule->dnpipe, 0)); 1211fb330f39SKristof Provost PFNV_CHK(pf_nvuint32_opt(nvl, "dnflags", &krule->dnflags, 0)); 12128a8af942SKristof Provost PFNV_CHK(pf_nvstring(nvl, "bridge_to", krule->bridge_to_name, 12138a8af942SKristof Provost sizeof(krule->bridge_to_name))); 1214fb330f39SKristof Provost 1215e732e742SKristof Provost PFNV_CHK(pf_nvuint8(nvl, "action", &krule->action)); 1216e732e742SKristof Provost 1217d27c9f5bSKristof Provost if (krule->action != PF_PASS && krule->action != PF_DROP && 1218d27c9f5bSKristof Provost krule->action != PF_MATCH) 1219e732e742SKristof Provost return (EBADMSG); 1220e732e742SKristof Provost 1221*ef661d4aSChristian McDonald #undef ERROUT 1222e732e742SKristof Provost errout: 1223e732e742SKristof Provost return (error); 1224e732e742SKristof Provost } 1225