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