10d71f9f3SKristof Provost /*- 20d71f9f3SKristof Provost * SPDX-License-Identifier: BSD-2-Clause 30d71f9f3SKristof Provost * 40d71f9f3SKristof Provost * Copyright (c) 2021 Rubicon Communications, LLC (Netgate) 50d71f9f3SKristof Provost * All rights reserved. 60d71f9f3SKristof Provost * 70d71f9f3SKristof Provost * Redistribution and use in source and binary forms, with or without 80d71f9f3SKristof Provost * modification, are permitted provided that the following conditions 90d71f9f3SKristof Provost * are met: 100d71f9f3SKristof Provost * 110d71f9f3SKristof Provost * - Redistributions of source code must retain the above copyright 120d71f9f3SKristof Provost * notice, this list of conditions and the following disclaimer. 130d71f9f3SKristof Provost * - Redistributions in binary form must reproduce the above 140d71f9f3SKristof Provost * copyright notice, this list of conditions and the following 150d71f9f3SKristof Provost * disclaimer in the documentation and/or other materials provided 160d71f9f3SKristof Provost * with the distribution. 170d71f9f3SKristof Provost * 180d71f9f3SKristof Provost * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 190d71f9f3SKristof Provost * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 200d71f9f3SKristof Provost * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 210d71f9f3SKristof Provost * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 220d71f9f3SKristof Provost * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 230d71f9f3SKristof Provost * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 240d71f9f3SKristof Provost * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 250d71f9f3SKristof Provost * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 260d71f9f3SKristof Provost * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 270d71f9f3SKristof Provost * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 280d71f9f3SKristof Provost * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 290d71f9f3SKristof Provost * POSSIBILITY OF SUCH DAMAGE. 300d71f9f3SKristof Provost */ 310d71f9f3SKristof Provost 320d71f9f3SKristof Provost #include <sys/cdefs.h> 330d71f9f3SKristof Provost 340d71f9f3SKristof Provost #include <sys/ioctl.h> 350d71f9f3SKristof Provost #include <sys/nv.h> 360d71f9f3SKristof Provost #include <sys/queue.h> 370d71f9f3SKristof Provost #include <sys/types.h> 380d71f9f3SKristof Provost 390d71f9f3SKristof Provost #include <net/if.h> 400d71f9f3SKristof Provost #include <net/pfvar.h> 410d71f9f3SKristof Provost #include <netinet/in.h> 420d71f9f3SKristof Provost 432cef6288SAlexander V. Chernikov #include <netpfil/pf/pf_nl.h> 442cef6288SAlexander V. Chernikov #include <netlink/netlink.h> 452cef6288SAlexander V. Chernikov #include <netlink/netlink_generic.h> 462cef6288SAlexander V. Chernikov #include <netlink/netlink_snl.h> 472cef6288SAlexander V. Chernikov #include <netlink/netlink_snl_generic.h> 482cef6288SAlexander V. Chernikov #include <netlink/netlink_snl_route.h> 492cef6288SAlexander V. Chernikov 500d71f9f3SKristof Provost #include <assert.h> 510d71f9f3SKristof Provost #include <err.h> 520d71f9f3SKristof Provost #include <errno.h> 5366cacc14SKristof Provost #include <fcntl.h> 540d71f9f3SKristof Provost #include <stdlib.h> 550d71f9f3SKristof Provost #include <string.h> 560d71f9f3SKristof Provost 570d71f9f3SKristof Provost #include "libpfctl.h" 580d71f9f3SKristof Provost 5966cacc14SKristof Provost struct pfctl_handle { 6066cacc14SKristof Provost int fd; 6166cacc14SKristof Provost struct snl_state ss; 6266cacc14SKristof Provost }; 6366cacc14SKristof Provost 645062afffSKristof Provost const char* PFCTL_SYNCOOKIES_MODE_NAMES[] = { 655062afffSKristof Provost "never", 665062afffSKristof Provost "always", 675062afffSKristof Provost "adaptive" 685062afffSKristof Provost }; 695062afffSKristof Provost 702a00c4dbSKristof Provost static int _pfctl_clear_states(int , const struct pfctl_kill *, 712a00c4dbSKristof Provost unsigned int *, uint64_t); 722a00c4dbSKristof Provost 7366cacc14SKristof Provost struct pfctl_handle * 7466cacc14SKristof Provost pfctl_open(const char *pf_device) 7566cacc14SKristof Provost { 7666cacc14SKristof Provost struct pfctl_handle *h; 7766cacc14SKristof Provost 7866cacc14SKristof Provost h = calloc(1, sizeof(struct pfctl_handle)); 7966cacc14SKristof Provost h->fd = -1; 8066cacc14SKristof Provost 8166cacc14SKristof Provost h->fd = open(pf_device, O_RDWR); 8266cacc14SKristof Provost if (h->fd < 0) 8366cacc14SKristof Provost goto error; 8466cacc14SKristof Provost 8566cacc14SKristof Provost if (!snl_init(&h->ss, NETLINK_GENERIC)) 8666cacc14SKristof Provost goto error; 8766cacc14SKristof Provost 8866cacc14SKristof Provost return (h); 8966cacc14SKristof Provost error: 9066cacc14SKristof Provost close(h->fd); 9166cacc14SKristof Provost snl_free(&h->ss); 9266cacc14SKristof Provost free(h); 9366cacc14SKristof Provost 9466cacc14SKristof Provost return (NULL); 9566cacc14SKristof Provost } 9666cacc14SKristof Provost 9766cacc14SKristof Provost void 9866cacc14SKristof Provost pfctl_close(struct pfctl_handle *h) 9966cacc14SKristof Provost { 10066cacc14SKristof Provost close(h->fd); 10166cacc14SKristof Provost snl_free(&h->ss); 10266cacc14SKristof Provost free(h); 10366cacc14SKristof Provost } 10466cacc14SKristof Provost 105044243fcSKristof Provost int 106044243fcSKristof Provost pfctl_fd(struct pfctl_handle *h) 107044243fcSKristof Provost { 108044243fcSKristof Provost return (h->fd); 109044243fcSKristof Provost } 110044243fcSKristof Provost 1117ed19f5cSKristof Provost static int 1129dbbe68bSKristof Provost pfctl_do_netlink_cmd(struct pfctl_handle *h, uint cmd) 1139dbbe68bSKristof Provost { 1149dbbe68bSKristof Provost struct snl_errmsg_data e = {}; 1159dbbe68bSKristof Provost struct snl_writer nw; 1169dbbe68bSKristof Provost struct nlmsghdr *hdr; 1179dbbe68bSKristof Provost uint32_t seq_id; 1189dbbe68bSKristof Provost int family_id; 1199dbbe68bSKristof Provost 1209dbbe68bSKristof Provost family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 1219dbbe68bSKristof Provost if (family_id == 0) 1229dbbe68bSKristof Provost return (ENOTSUP); 1239dbbe68bSKristof Provost 1249dbbe68bSKristof Provost snl_init_writer(&h->ss, &nw); 1259dbbe68bSKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, cmd); 1269dbbe68bSKristof Provost 1279dbbe68bSKristof Provost hdr = snl_finalize_msg(&nw); 1289dbbe68bSKristof Provost if (hdr == NULL) 1299dbbe68bSKristof Provost return (ENOMEM); 1309dbbe68bSKristof Provost seq_id = hdr->nlmsg_seq; 1319dbbe68bSKristof Provost 1329dbbe68bSKristof Provost snl_send_message(&h->ss, hdr); 1339dbbe68bSKristof Provost 1349dbbe68bSKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 1359dbbe68bSKristof Provost } 1369dbbe68bSKristof Provost 1379dbbe68bSKristof Provost return (e.error); 1389dbbe68bSKristof Provost } 1399dbbe68bSKristof Provost 1409dbbe68bSKristof Provost static int 1417ed19f5cSKristof Provost pfctl_do_ioctl(int dev, uint cmd, size_t size, nvlist_t **nvl) 1427ed19f5cSKristof Provost { 1437ed19f5cSKristof Provost struct pfioc_nv nv; 1447ed19f5cSKristof Provost void *data; 1457ed19f5cSKristof Provost size_t nvlen; 1467ed19f5cSKristof Provost int ret; 1477ed19f5cSKristof Provost 1487ed19f5cSKristof Provost data = nvlist_pack(*nvl, &nvlen); 1496422599eSKristof Provost if (nvlen > size) 1506422599eSKristof Provost size = nvlen; 1517ed19f5cSKristof Provost 1527ed19f5cSKristof Provost retry: 1537ed19f5cSKristof Provost nv.data = malloc(size); 15433d55d0dSKristof Provost if (nv.data == NULL) { 15533d55d0dSKristof Provost ret = ENOMEM; 15633d55d0dSKristof Provost goto out; 15733d55d0dSKristof Provost } 15833d55d0dSKristof Provost 1597ed19f5cSKristof Provost memcpy(nv.data, data, nvlen); 1607ed19f5cSKristof Provost 1617ed19f5cSKristof Provost nv.len = nvlen; 1627ed19f5cSKristof Provost nv.size = size; 1637ed19f5cSKristof Provost 1647ed19f5cSKristof Provost ret = ioctl(dev, cmd, &nv); 1657ed19f5cSKristof Provost if (ret == -1 && errno == ENOSPC) { 1667ed19f5cSKristof Provost size *= 2; 1677ed19f5cSKristof Provost free(nv.data); 1687ed19f5cSKristof Provost goto retry; 1697ed19f5cSKristof Provost } 1707ed19f5cSKristof Provost 1717ed19f5cSKristof Provost nvlist_destroy(*nvl); 1727ed19f5cSKristof Provost *nvl = NULL; 1737ed19f5cSKristof Provost 1747ed19f5cSKristof Provost if (ret == 0) { 1757ed19f5cSKristof Provost *nvl = nvlist_unpack(nv.data, nv.len, 0); 1767ed19f5cSKristof Provost if (*nvl == NULL) { 1772cffb525SKristof Provost ret = EIO; 1782cffb525SKristof Provost goto out; 1797ed19f5cSKristof Provost } 1807ed19f5cSKristof Provost } else { 1817ed19f5cSKristof Provost ret = errno; 1827ed19f5cSKristof Provost } 1837ed19f5cSKristof Provost 1842cffb525SKristof Provost out: 1852cffb525SKristof Provost free(data); 1867ed19f5cSKristof Provost free(nv.data); 1877ed19f5cSKristof Provost 1887ed19f5cSKristof Provost return (ret); 1897ed19f5cSKristof Provost } 1907ed19f5cSKristof Provost 1910d71f9f3SKristof Provost static void 1920d71f9f3SKristof Provost pf_nvuint_8_array(const nvlist_t *nvl, const char *name, size_t maxelems, 1937bb3c927SKristof Provost uint8_t *numbers, size_t *nelems) 1940d71f9f3SKristof Provost { 1950d71f9f3SKristof Provost const uint64_t *tmp; 1960d71f9f3SKristof Provost size_t elems; 1970d71f9f3SKristof Provost 1980d71f9f3SKristof Provost tmp = nvlist_get_number_array(nvl, name, &elems); 1990d71f9f3SKristof Provost assert(elems <= maxelems); 2000d71f9f3SKristof Provost 2010d71f9f3SKristof Provost for (size_t i = 0; i < elems; i++) 2020d71f9f3SKristof Provost numbers[i] = tmp[i]; 2030d71f9f3SKristof Provost 2040d71f9f3SKristof Provost if (nelems) 2050d71f9f3SKristof Provost *nelems = elems; 2060d71f9f3SKristof Provost } 2070d71f9f3SKristof Provost 2080d71f9f3SKristof Provost static void 2090d71f9f3SKristof Provost pf_nvuint_16_array(const nvlist_t *nvl, const char *name, size_t maxelems, 2107bb3c927SKristof Provost uint16_t *numbers, size_t *nelems) 2110d71f9f3SKristof Provost { 2120d71f9f3SKristof Provost const uint64_t *tmp; 2130d71f9f3SKristof Provost size_t elems; 2140d71f9f3SKristof Provost 2150d71f9f3SKristof Provost tmp = nvlist_get_number_array(nvl, name, &elems); 2160d71f9f3SKristof Provost assert(elems <= maxelems); 2170d71f9f3SKristof Provost 2180d71f9f3SKristof Provost for (size_t i = 0; i < elems; i++) 2190d71f9f3SKristof Provost numbers[i] = tmp[i]; 2200d71f9f3SKristof Provost 2210d71f9f3SKristof Provost if (nelems) 2220d71f9f3SKristof Provost *nelems = elems; 2230d71f9f3SKristof Provost } 2240d71f9f3SKristof Provost 2250d71f9f3SKristof Provost static void 2260d71f9f3SKristof Provost pf_nvuint_32_array(const nvlist_t *nvl, const char *name, size_t maxelems, 2277bb3c927SKristof Provost uint32_t *numbers, size_t *nelems) 2280d71f9f3SKristof Provost { 2290d71f9f3SKristof Provost const uint64_t *tmp; 2300d71f9f3SKristof Provost size_t elems; 2310d71f9f3SKristof Provost 2320d71f9f3SKristof Provost tmp = nvlist_get_number_array(nvl, name, &elems); 2330d71f9f3SKristof Provost 2342b1eb63fSKristof Provost for (size_t i = 0; i < elems && i < maxelems; i++) 2350d71f9f3SKristof Provost numbers[i] = tmp[i]; 2360d71f9f3SKristof Provost 2370d71f9f3SKristof Provost if (nelems) 2380d71f9f3SKristof Provost *nelems = elems; 2390d71f9f3SKristof Provost } 2400d71f9f3SKristof Provost 2410d71f9f3SKristof Provost static void 2420d71f9f3SKristof Provost pf_nvuint_64_array(const nvlist_t *nvl, const char *name, size_t maxelems, 2437bb3c927SKristof Provost uint64_t *numbers, size_t *nelems) 2440d71f9f3SKristof Provost { 2450d71f9f3SKristof Provost const uint64_t *tmp; 2460d71f9f3SKristof Provost size_t elems; 2470d71f9f3SKristof Provost 2480d71f9f3SKristof Provost tmp = nvlist_get_number_array(nvl, name, &elems); 2490d71f9f3SKristof Provost assert(elems <= maxelems); 2500d71f9f3SKristof Provost 2510d71f9f3SKristof Provost for (size_t i = 0; i < elems; i++) 2520d71f9f3SKristof Provost numbers[i] = tmp[i]; 2530d71f9f3SKristof Provost 2540d71f9f3SKristof Provost if (nelems) 2550d71f9f3SKristof Provost *nelems = elems; 2560d71f9f3SKristof Provost } 2570d71f9f3SKristof Provost 25881647eb6SKristof Provost int 25966cacc14SKristof Provost pfctl_startstop(struct pfctl_handle *h, int start) 26081647eb6SKristof Provost { 2619dbbe68bSKristof Provost return (pfctl_do_netlink_cmd(h, start ? PFNL_CMD_START : PFNL_CMD_STOP)); 26281647eb6SKristof Provost } 26381647eb6SKristof Provost 2640d71f9f3SKristof Provost static void 26546fb68b1SKristof Provost _pfctl_get_status_counters(const nvlist_t *nvl, 26646fb68b1SKristof Provost struct pfctl_status_counters *counters) 26746fb68b1SKristof Provost { 26846fb68b1SKristof Provost const uint64_t *ids, *counts; 26946fb68b1SKristof Provost const char *const *names; 27046fb68b1SKristof Provost size_t id_len, counter_len, names_len; 27146fb68b1SKristof Provost 27246fb68b1SKristof Provost ids = nvlist_get_number_array(nvl, "ids", &id_len); 27346fb68b1SKristof Provost counts = nvlist_get_number_array(nvl, "counters", &counter_len); 27446fb68b1SKristof Provost names = nvlist_get_string_array(nvl, "names", &names_len); 27546fb68b1SKristof Provost assert(id_len == counter_len); 27646fb68b1SKristof Provost assert(counter_len == names_len); 27746fb68b1SKristof Provost 27846fb68b1SKristof Provost TAILQ_INIT(counters); 27946fb68b1SKristof Provost 28046fb68b1SKristof Provost for (size_t i = 0; i < id_len; i++) { 28146fb68b1SKristof Provost struct pfctl_status_counter *c; 28246fb68b1SKristof Provost 28346fb68b1SKristof Provost c = malloc(sizeof(*c)); 28433d55d0dSKristof Provost if (c == NULL) 28533d55d0dSKristof Provost continue; 28646fb68b1SKristof Provost 28746fb68b1SKristof Provost c->id = ids[i]; 28846fb68b1SKristof Provost c->counter = counts[i]; 28946fb68b1SKristof Provost c->name = strdup(names[i]); 29046fb68b1SKristof Provost 29146fb68b1SKristof Provost TAILQ_INSERT_TAIL(counters, c, entry); 29246fb68b1SKristof Provost } 29346fb68b1SKristof Provost } 29446fb68b1SKristof Provost 2955824df8dSKristof Provost #define _OUT(_field) offsetof(struct pfctl_status_counter, _field) 2965824df8dSKristof Provost static const struct snl_attr_parser ap_counter[] = { 2975824df8dSKristof Provost { .type = PF_C_COUNTER, .off = _OUT(counter), .cb = snl_attr_get_uint64 }, 2985824df8dSKristof Provost { .type = PF_C_NAME, .off = _OUT(name), .cb = snl_attr_get_string }, 2995824df8dSKristof Provost { .type = PF_C_ID, .off = _OUT(id), .cb = snl_attr_get_uint32 }, 3005824df8dSKristof Provost }; 3015824df8dSKristof Provost SNL_DECLARE_ATTR_PARSER(counter_parser, ap_counter); 3025824df8dSKristof Provost #undef _OUT 3035824df8dSKristof Provost 3045824df8dSKristof Provost static bool 3055824df8dSKristof Provost snl_attr_get_counters(struct snl_state *ss, struct nlattr *nla, 3065824df8dSKristof Provost const void *arg __unused, void *target) 3075824df8dSKristof Provost { 3085824df8dSKristof Provost struct pfctl_status_counter counter = {}; 3095824df8dSKristof Provost struct pfctl_status_counter *c; 3105824df8dSKristof Provost bool error; 3115824df8dSKristof Provost 3125824df8dSKristof Provost error = snl_parse_header(ss, NLA_DATA(nla), NLA_DATA_LEN(nla), &counter_parser, &counter); 3135824df8dSKristof Provost if (! error) 3145824df8dSKristof Provost return (error); 3155824df8dSKristof Provost 3165824df8dSKristof Provost c = malloc(sizeof(*c)); 3175824df8dSKristof Provost if (c == NULL) 3185824df8dSKristof Provost return (false); 3195824df8dSKristof Provost 3205824df8dSKristof Provost c->id = counter.id; 3215824df8dSKristof Provost c->counter = counter.counter; 3225824df8dSKristof Provost c->name = strdup(counter.name); 3235824df8dSKristof Provost 3245824df8dSKristof Provost TAILQ_INSERT_TAIL((struct pfctl_status_counters *)target, c, entry); 3255824df8dSKristof Provost 3265824df8dSKristof Provost return (error); 3275824df8dSKristof Provost } 3285824df8dSKristof Provost 3295824df8dSKristof Provost struct snl_uint64_array { 3305824df8dSKristof Provost uint64_t *array; 3315824df8dSKristof Provost size_t count; 3325824df8dSKristof Provost size_t max; 3335824df8dSKristof Provost }; 3345824df8dSKristof Provost static bool 3355824df8dSKristof Provost snl_attr_get_uint64_element(struct snl_state *ss, struct nlattr *nla, 3365824df8dSKristof Provost const void *arg, void *target) 3375824df8dSKristof Provost { 3385824df8dSKristof Provost bool error; 3395824df8dSKristof Provost uint64_t value; 3405824df8dSKristof Provost struct snl_uint64_array *t = (struct snl_uint64_array *)target; 3415824df8dSKristof Provost 3425824df8dSKristof Provost if (t->count >= t->max) 3435824df8dSKristof Provost return (false); 3445824df8dSKristof Provost 3455824df8dSKristof Provost error = snl_attr_get_uint64(ss, nla, arg, &value); 3465824df8dSKristof Provost if (! error) 3475824df8dSKristof Provost return (error); 3485824df8dSKristof Provost 3495824df8dSKristof Provost t->array[t->count++] = value; 3505824df8dSKristof Provost 3515824df8dSKristof Provost return (true); 3525824df8dSKristof Provost } 3535824df8dSKristof Provost 3545824df8dSKristof Provost static const struct snl_attr_parser ap_array[] = { 3555824df8dSKristof Provost { .cb = snl_attr_get_uint64_element }, 3565824df8dSKristof Provost }; 3575824df8dSKristof Provost SNL_DECLARE_ATTR_PARSER(array_parser, ap_array); 3585824df8dSKristof Provost static bool 3595824df8dSKristof Provost snl_attr_get_uint64_array(struct snl_state *ss, struct nlattr *nla, 3605824df8dSKristof Provost const void *arg, void *target) 3615824df8dSKristof Provost { 3625824df8dSKristof Provost struct snl_uint64_array a = { 3635824df8dSKristof Provost .array = target, 3645824df8dSKristof Provost .count = 0, 3655824df8dSKristof Provost .max = (size_t)arg, 3665824df8dSKristof Provost }; 3675824df8dSKristof Provost bool error; 3685824df8dSKristof Provost 3695824df8dSKristof Provost error = snl_parse_header(ss, NLA_DATA(nla), NLA_DATA_LEN(nla), &array_parser, &a); 3705824df8dSKristof Provost if (! error) 3715824df8dSKristof Provost return (error); 3725824df8dSKristof Provost 3735824df8dSKristof Provost return (true); 3745824df8dSKristof Provost } 3755824df8dSKristof Provost 3765824df8dSKristof Provost #define _OUT(_field) offsetof(struct pfctl_status, _field) 3775824df8dSKristof Provost static const struct snl_attr_parser ap_getstatus[] = { 3785824df8dSKristof Provost { .type = PF_GS_IFNAME, .off = _OUT(ifname), .arg_u32 = IFNAMSIZ, .cb = snl_attr_copy_string }, 3795824df8dSKristof Provost { .type = PF_GS_RUNNING, .off = _OUT(running), .cb = snl_attr_get_bool }, 3805824df8dSKristof Provost { .type = PF_GS_SINCE, .off = _OUT(since), .cb = snl_attr_get_uint32 }, 3815824df8dSKristof Provost { .type = PF_GS_DEBUG, .off = _OUT(debug), .cb = snl_attr_get_uint32 }, 3825824df8dSKristof Provost { .type = PF_GS_HOSTID, .off = _OUT(hostid), .cb = snl_attr_get_uint32 }, 3835824df8dSKristof Provost { .type = PF_GS_STATES, .off = _OUT(states), .cb = snl_attr_get_uint32 }, 3845824df8dSKristof Provost { .type = PF_GS_SRC_NODES, .off = _OUT(src_nodes), .cb = snl_attr_get_uint32 }, 3855824df8dSKristof Provost { .type = PF_GS_REASSEMBLE, .off = _OUT(reass), .cb = snl_attr_get_uint32 }, 3865824df8dSKristof Provost { .type = PF_GS_SYNCOOKIES_ACTIVE, .off = _OUT(syncookies_active), .cb = snl_attr_get_uint32 }, 3875824df8dSKristof Provost { .type = PF_GS_COUNTERS, .off = _OUT(counters), .cb = snl_attr_get_counters }, 3885824df8dSKristof Provost { .type = PF_GS_LCOUNTERS, .off = _OUT(lcounters), .cb = snl_attr_get_counters }, 3895824df8dSKristof Provost { .type = PF_GS_FCOUNTERS, .off = _OUT(fcounters), .cb = snl_attr_get_counters }, 3905824df8dSKristof Provost { .type = PF_GS_SCOUNTERS, .off = _OUT(scounters), .cb = snl_attr_get_counters }, 3915824df8dSKristof Provost { .type = PF_GS_CHKSUM, .off = _OUT(pf_chksum), .arg_u32 = PF_MD5_DIGEST_LENGTH, .cb = snl_attr_get_bytes }, 3925824df8dSKristof Provost { .type = PF_GS_BCOUNTERS, .off = _OUT(bcounters), .arg_u32 = 2 * 2, .cb = snl_attr_get_uint64_array }, 3935824df8dSKristof Provost { .type = PF_GS_PCOUNTERS, .off = _OUT(pcounters), .arg_u32 = 2 * 2 * 2, .cb = snl_attr_get_uint64_array }, 3945824df8dSKristof Provost }; 3957c882c69SKristof Provost SNL_DECLARE_PARSER(getstatus_parser, struct genlmsghdr, snl_f_p_empty, ap_getstatus); 3965824df8dSKristof Provost #undef _OUT 3975824df8dSKristof Provost 3985824df8dSKristof Provost struct pfctl_status * 3995824df8dSKristof Provost pfctl_get_status_h(struct pfctl_handle *h __unused) 4005824df8dSKristof Provost { 4015824df8dSKristof Provost struct pfctl_status *status; 4025824df8dSKristof Provost struct snl_errmsg_data e = {}; 4035824df8dSKristof Provost struct nlmsghdr *hdr; 4045824df8dSKristof Provost struct snl_writer nw; 4055824df8dSKristof Provost uint32_t seq_id; 4065824df8dSKristof Provost int family_id; 4075824df8dSKristof Provost 4085824df8dSKristof Provost family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 4095824df8dSKristof Provost if (family_id == 0) 4105824df8dSKristof Provost return (NULL); 4115824df8dSKristof Provost 4125824df8dSKristof Provost snl_init_writer(&h->ss, &nw); 4135824df8dSKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_GET_STATUS); 4145824df8dSKristof Provost hdr->nlmsg_flags |= NLM_F_DUMP; 4155824df8dSKristof Provost 4165824df8dSKristof Provost hdr = snl_finalize_msg(&nw); 4175824df8dSKristof Provost if (hdr == NULL) { 4185824df8dSKristof Provost return (NULL); 4195824df8dSKristof Provost } 4205824df8dSKristof Provost 4215824df8dSKristof Provost seq_id = hdr->nlmsg_seq; 4225824df8dSKristof Provost if (! snl_send_message(&h->ss, hdr)) 4235824df8dSKristof Provost return (NULL); 4245824df8dSKristof Provost 4255824df8dSKristof Provost status = calloc(1, sizeof(*status)); 4265824df8dSKristof Provost if (status == NULL) 4275824df8dSKristof Provost return (NULL); 4285824df8dSKristof Provost TAILQ_INIT(&status->counters); 4295824df8dSKristof Provost TAILQ_INIT(&status->lcounters); 4305824df8dSKristof Provost TAILQ_INIT(&status->fcounters); 4315824df8dSKristof Provost TAILQ_INIT(&status->scounters); 4325824df8dSKristof Provost 4335824df8dSKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 4345824df8dSKristof Provost if (! snl_parse_nlmsg(&h->ss, hdr, &getstatus_parser, status)) 4355824df8dSKristof Provost continue; 4365824df8dSKristof Provost } 4375824df8dSKristof Provost 4385824df8dSKristof Provost return (status); 4395824df8dSKristof Provost } 4405824df8dSKristof Provost 44146fb68b1SKristof Provost struct pfctl_status * 44246fb68b1SKristof Provost pfctl_get_status(int dev) 44346fb68b1SKristof Provost { 44446fb68b1SKristof Provost struct pfctl_status *status; 44546fb68b1SKristof Provost nvlist_t *nvl; 44646fb68b1SKristof Provost size_t len; 44746fb68b1SKristof Provost const void *chksum; 44846fb68b1SKristof Provost 44946fb68b1SKristof Provost status = calloc(1, sizeof(*status)); 45046fb68b1SKristof Provost if (status == NULL) 45146fb68b1SKristof Provost return (NULL); 45246fb68b1SKristof Provost 4537ed19f5cSKristof Provost nvl = nvlist_create(0); 45446fb68b1SKristof Provost 4557ed19f5cSKristof Provost if (pfctl_do_ioctl(dev, DIOCGETSTATUSNV, 4096, &nvl)) { 456498934c5SKristof Provost nvlist_destroy(nvl); 45746fb68b1SKristof Provost free(status); 45846fb68b1SKristof Provost return (NULL); 45946fb68b1SKristof Provost } 46046fb68b1SKristof Provost 46146fb68b1SKristof Provost status->running = nvlist_get_bool(nvl, "running"); 46246fb68b1SKristof Provost status->since = nvlist_get_number(nvl, "since"); 46346fb68b1SKristof Provost status->debug = nvlist_get_number(nvl, "debug"); 464735748f3SKristof Provost status->hostid = ntohl(nvlist_get_number(nvl, "hostid")); 46546fb68b1SKristof Provost status->states = nvlist_get_number(nvl, "states"); 46646fb68b1SKristof Provost status->src_nodes = nvlist_get_number(nvl, "src_nodes"); 467444a77caSKristof Provost status->syncookies_active = nvlist_get_bool(nvl, "syncookies_active"); 46839282ef3SKajetan Staszkiewicz status->reass = nvlist_get_number(nvl, "reass"); 46946fb68b1SKristof Provost 47046fb68b1SKristof Provost strlcpy(status->ifname, nvlist_get_string(nvl, "ifname"), 47146fb68b1SKristof Provost IFNAMSIZ); 47246fb68b1SKristof Provost chksum = nvlist_get_binary(nvl, "chksum", &len); 47346fb68b1SKristof Provost assert(len == PF_MD5_DIGEST_LENGTH); 47446fb68b1SKristof Provost memcpy(status->pf_chksum, chksum, len); 47546fb68b1SKristof Provost 47646fb68b1SKristof Provost _pfctl_get_status_counters(nvlist_get_nvlist(nvl, "counters"), 47746fb68b1SKristof Provost &status->counters); 47846fb68b1SKristof Provost _pfctl_get_status_counters(nvlist_get_nvlist(nvl, "lcounters"), 47946fb68b1SKristof Provost &status->lcounters); 48046fb68b1SKristof Provost _pfctl_get_status_counters(nvlist_get_nvlist(nvl, "fcounters"), 48146fb68b1SKristof Provost &status->fcounters); 48246fb68b1SKristof Provost _pfctl_get_status_counters(nvlist_get_nvlist(nvl, "scounters"), 48346fb68b1SKristof Provost &status->scounters); 48446fb68b1SKristof Provost 485a3f71765SKristof Provost pf_nvuint_64_array(nvl, "pcounters", 2 * 2 * 2, 48646fb68b1SKristof Provost (uint64_t *)status->pcounters, NULL); 48746fb68b1SKristof Provost pf_nvuint_64_array(nvl, "bcounters", 2 * 2, 48846fb68b1SKristof Provost (uint64_t *)status->bcounters, NULL); 48946fb68b1SKristof Provost 49046fb68b1SKristof Provost nvlist_destroy(nvl); 49146fb68b1SKristof Provost 49246fb68b1SKristof Provost return (status); 49346fb68b1SKristof Provost } 4949dbbe68bSKristof Provost int 4959dbbe68bSKristof Provost pfctl_clear_status(struct pfctl_handle *h) 4969dbbe68bSKristof Provost { 4979dbbe68bSKristof Provost return (pfctl_do_netlink_cmd(h, PFNL_CMD_CLEAR_STATUS)); 4989dbbe68bSKristof Provost } 49946fb68b1SKristof Provost 500e3d3d61aSKristof Provost static uint64_t 501e3d3d61aSKristof Provost _pfctl_status_counter(struct pfctl_status_counters *counters, uint64_t id) 502e3d3d61aSKristof Provost { 503e3d3d61aSKristof Provost struct pfctl_status_counter *c; 504e3d3d61aSKristof Provost 505e3d3d61aSKristof Provost TAILQ_FOREACH(c, counters, entry) { 506e3d3d61aSKristof Provost if (c->id == id) 507e3d3d61aSKristof Provost return (c->counter); 508e3d3d61aSKristof Provost } 509e3d3d61aSKristof Provost 510e3d3d61aSKristof Provost return (0); 511e3d3d61aSKristof Provost } 512e3d3d61aSKristof Provost 513e3d3d61aSKristof Provost uint64_t 514e3d3d61aSKristof Provost pfctl_status_counter(struct pfctl_status *status, int id) 515e3d3d61aSKristof Provost { 516e3d3d61aSKristof Provost return (_pfctl_status_counter(&status->counters, id)); 517e3d3d61aSKristof Provost } 518e3d3d61aSKristof Provost 519e3d3d61aSKristof Provost uint64_t 5201c824f43SKristof Provost pfctl_status_lcounter(struct pfctl_status *status, int id) 5211c824f43SKristof Provost { 5221c824f43SKristof Provost return (_pfctl_status_counter(&status->lcounters, id)); 5231c824f43SKristof Provost } 5241c824f43SKristof Provost 5251c824f43SKristof Provost uint64_t 526e3d3d61aSKristof Provost pfctl_status_fcounter(struct pfctl_status *status, int id) 527e3d3d61aSKristof Provost { 528e3d3d61aSKristof Provost return (_pfctl_status_counter(&status->fcounters, id)); 529e3d3d61aSKristof Provost } 530e3d3d61aSKristof Provost 531e3d3d61aSKristof Provost uint64_t 532e3d3d61aSKristof Provost pfctl_status_scounter(struct pfctl_status *status, int id) 533e3d3d61aSKristof Provost { 534e3d3d61aSKristof Provost return (_pfctl_status_counter(&status->scounters, id)); 535e3d3d61aSKristof Provost } 536e3d3d61aSKristof Provost 53746fb68b1SKristof Provost void 53846fb68b1SKristof Provost pfctl_free_status(struct pfctl_status *status) 53946fb68b1SKristof Provost { 54046fb68b1SKristof Provost struct pfctl_status_counter *c, *tmp; 54146fb68b1SKristof Provost 5420b01878fSKristof Provost if (status == NULL) 5430b01878fSKristof Provost return; 5440b01878fSKristof Provost 54546fb68b1SKristof Provost TAILQ_FOREACH_SAFE(c, &status->counters, entry, tmp) { 54646fb68b1SKristof Provost free(c->name); 54746fb68b1SKristof Provost free(c); 54846fb68b1SKristof Provost } 54946fb68b1SKristof Provost TAILQ_FOREACH_SAFE(c, &status->lcounters, entry, tmp) { 55046fb68b1SKristof Provost free(c->name); 55146fb68b1SKristof Provost free(c); 55246fb68b1SKristof Provost } 55346fb68b1SKristof Provost TAILQ_FOREACH_SAFE(c, &status->fcounters, entry, tmp) { 55446fb68b1SKristof Provost free(c->name); 55546fb68b1SKristof Provost free(c); 55646fb68b1SKristof Provost } 55746fb68b1SKristof Provost TAILQ_FOREACH_SAFE(c, &status->scounters, entry, tmp) { 55846fb68b1SKristof Provost free(c->name); 55946fb68b1SKristof Provost free(c); 56046fb68b1SKristof Provost } 56146fb68b1SKristof Provost 56246fb68b1SKristof Provost free(status); 56346fb68b1SKristof Provost } 56446fb68b1SKristof Provost 56546fb68b1SKristof Provost static void 5660d71f9f3SKristof Provost pfctl_nv_add_addr(nvlist_t *nvparent, const char *name, 5670d71f9f3SKristof Provost const struct pf_addr *addr) 5680d71f9f3SKristof Provost { 5690d71f9f3SKristof Provost nvlist_t *nvl = nvlist_create(0); 5700d71f9f3SKristof Provost 5710d71f9f3SKristof Provost nvlist_add_binary(nvl, "addr", addr, sizeof(*addr)); 5720d71f9f3SKristof Provost 5730d71f9f3SKristof Provost nvlist_add_nvlist(nvparent, name, nvl); 5746dbb729dSKristof Provost nvlist_destroy(nvl); 5750d71f9f3SKristof Provost } 5760d71f9f3SKristof Provost 5770d71f9f3SKristof Provost static void 5780d71f9f3SKristof Provost pf_nvaddr_to_addr(const nvlist_t *nvl, struct pf_addr *addr) 5790d71f9f3SKristof Provost { 5800d71f9f3SKristof Provost size_t len; 5810d71f9f3SKristof Provost const void *data; 5820d71f9f3SKristof Provost 5830d71f9f3SKristof Provost data = nvlist_get_binary(nvl, "addr", &len); 5840d71f9f3SKristof Provost assert(len == sizeof(struct pf_addr)); 5850d71f9f3SKristof Provost memcpy(addr, data, len); 5860d71f9f3SKristof Provost } 5870d71f9f3SKristof Provost 5880d71f9f3SKristof Provost static void 5890d71f9f3SKristof Provost pfctl_nv_add_addr_wrap(nvlist_t *nvparent, const char *name, 5900d71f9f3SKristof Provost const struct pf_addr_wrap *addr) 5910d71f9f3SKristof Provost { 5920d71f9f3SKristof Provost nvlist_t *nvl = nvlist_create(0); 5930d71f9f3SKristof Provost 5940d71f9f3SKristof Provost nvlist_add_number(nvl, "type", addr->type); 5950d71f9f3SKristof Provost nvlist_add_number(nvl, "iflags", addr->iflags); 596402dfb0aSKristof Provost if (addr->type == PF_ADDR_DYNIFTL) 5970d71f9f3SKristof Provost nvlist_add_string(nvl, "ifname", addr->v.ifname); 598402dfb0aSKristof Provost if (addr->type == PF_ADDR_TABLE) 5990d71f9f3SKristof Provost nvlist_add_string(nvl, "tblname", addr->v.tblname); 6000d71f9f3SKristof Provost pfctl_nv_add_addr(nvl, "addr", &addr->v.a.addr); 6010d71f9f3SKristof Provost pfctl_nv_add_addr(nvl, "mask", &addr->v.a.mask); 6020d71f9f3SKristof Provost 6030d71f9f3SKristof Provost nvlist_add_nvlist(nvparent, name, nvl); 6046dbb729dSKristof Provost nvlist_destroy(nvl); 6050d71f9f3SKristof Provost } 6060d71f9f3SKristof Provost 6070d71f9f3SKristof Provost static void 6080d71f9f3SKristof Provost pf_nvaddr_wrap_to_addr_wrap(const nvlist_t *nvl, struct pf_addr_wrap *addr) 6090d71f9f3SKristof Provost { 610218a8a49SKristof Provost bzero(addr, sizeof(*addr)); 611218a8a49SKristof Provost 6120d71f9f3SKristof Provost addr->type = nvlist_get_number(nvl, "type"); 6130d71f9f3SKristof Provost addr->iflags = nvlist_get_number(nvl, "iflags"); 614218a8a49SKristof Provost if (addr->type == PF_ADDR_DYNIFTL) { 615402dfb0aSKristof Provost strlcpy(addr->v.ifname, nvlist_get_string(nvl, "ifname"), 616402dfb0aSKristof Provost IFNAMSIZ); 6172de49deeSKristof Provost addr->p.dyncnt = nvlist_get_number(nvl, "dyncnt"); 618218a8a49SKristof Provost } 619218a8a49SKristof Provost if (addr->type == PF_ADDR_TABLE) { 6200d71f9f3SKristof Provost strlcpy(addr->v.tblname, nvlist_get_string(nvl, "tblname"), 6210d71f9f3SKristof Provost PF_TABLE_NAME_SIZE); 622218a8a49SKristof Provost addr->p.tblcnt = nvlist_get_number(nvl, "tblcnt"); 623218a8a49SKristof Provost } 6240d71f9f3SKristof Provost 6250d71f9f3SKristof Provost pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "addr"), &addr->v.a.addr); 6260d71f9f3SKristof Provost pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "mask"), &addr->v.a.mask); 6270d71f9f3SKristof Provost } 6280d71f9f3SKristof Provost 6290d71f9f3SKristof Provost static void 6300d71f9f3SKristof Provost pfctl_nv_add_rule_addr(nvlist_t *nvparent, const char *name, 6310d71f9f3SKristof Provost const struct pf_rule_addr *addr) 6320d71f9f3SKristof Provost { 6337bb3c927SKristof Provost uint64_t ports[2]; 6340d71f9f3SKristof Provost nvlist_t *nvl = nvlist_create(0); 6350d71f9f3SKristof Provost 6360d71f9f3SKristof Provost pfctl_nv_add_addr_wrap(nvl, "addr", &addr->addr); 6370d71f9f3SKristof Provost ports[0] = addr->port[0]; 6380d71f9f3SKristof Provost ports[1] = addr->port[1]; 6390d71f9f3SKristof Provost nvlist_add_number_array(nvl, "port", ports, 2); 6400d71f9f3SKristof Provost nvlist_add_number(nvl, "neg", addr->neg); 6410d71f9f3SKristof Provost nvlist_add_number(nvl, "port_op", addr->port_op); 6420d71f9f3SKristof Provost 6430d71f9f3SKristof Provost nvlist_add_nvlist(nvparent, name, nvl); 6446dbb729dSKristof Provost nvlist_destroy(nvl); 6450d71f9f3SKristof Provost } 6460d71f9f3SKristof Provost 6470d71f9f3SKristof Provost static void 6480d71f9f3SKristof Provost pf_nvrule_addr_to_rule_addr(const nvlist_t *nvl, struct pf_rule_addr *addr) 6490d71f9f3SKristof Provost { 6500d71f9f3SKristof Provost pf_nvaddr_wrap_to_addr_wrap(nvlist_get_nvlist(nvl, "addr"), &addr->addr); 6510d71f9f3SKristof Provost 6520d71f9f3SKristof Provost pf_nvuint_16_array(nvl, "port", 2, addr->port, NULL); 6530d71f9f3SKristof Provost addr->neg = nvlist_get_number(nvl, "neg"); 6540d71f9f3SKristof Provost addr->port_op = nvlist_get_number(nvl, "port_op"); 6550d71f9f3SKristof Provost } 6560d71f9f3SKristof Provost 6570d71f9f3SKristof Provost static void 6582aa21096SKurosawa Takahiro pf_nvmape_to_mape(const nvlist_t *nvl, struct pf_mape_portset *mape) 6592aa21096SKurosawa Takahiro { 6602aa21096SKurosawa Takahiro mape->offset = nvlist_get_number(nvl, "offset"); 6612aa21096SKurosawa Takahiro mape->psidlen = nvlist_get_number(nvl, "psidlen"); 6622aa21096SKurosawa Takahiro mape->psid = nvlist_get_number(nvl, "psid"); 6632aa21096SKurosawa Takahiro } 6642aa21096SKurosawa Takahiro 6652aa21096SKurosawa Takahiro static void 666600bd6ceSKurosawa Takahiro pf_nvpool_to_pool(const nvlist_t *nvl, struct pfctl_pool *pool) 6670d71f9f3SKristof Provost { 6680d71f9f3SKristof Provost size_t len; 6690d71f9f3SKristof Provost const void *data; 6700d71f9f3SKristof Provost 6710d71f9f3SKristof Provost data = nvlist_get_binary(nvl, "key", &len); 6720d71f9f3SKristof Provost assert(len == sizeof(pool->key)); 6730d71f9f3SKristof Provost memcpy(&pool->key, data, len); 6740d71f9f3SKristof Provost 6750d71f9f3SKristof Provost pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "counter"), &pool->counter); 6760d71f9f3SKristof Provost 6770d71f9f3SKristof Provost pool->tblidx = nvlist_get_number(nvl, "tblidx"); 6780d71f9f3SKristof Provost pf_nvuint_16_array(nvl, "proxy_port", 2, pool->proxy_port, NULL); 6790d71f9f3SKristof Provost pool->opts = nvlist_get_number(nvl, "opts"); 6802aa21096SKurosawa Takahiro 6812aa21096SKurosawa Takahiro if (nvlist_exists_nvlist(nvl, "mape")) 6822aa21096SKurosawa Takahiro pf_nvmape_to_mape(nvlist_get_nvlist(nvl, "mape"), &pool->mape); 6830d71f9f3SKristof Provost } 6840d71f9f3SKristof Provost 6850d71f9f3SKristof Provost static void 6860d71f9f3SKristof Provost pf_nvrule_uid_to_rule_uid(const nvlist_t *nvl, struct pf_rule_uid *uid) 6870d71f9f3SKristof Provost { 6880d71f9f3SKristof Provost pf_nvuint_32_array(nvl, "uid", 2, uid->uid, NULL); 6890d71f9f3SKristof Provost uid->op = nvlist_get_number(nvl, "op"); 6900d71f9f3SKristof Provost } 6910d71f9f3SKristof Provost 6920d71f9f3SKristof Provost static void 693e9eb0941SKristof Provost pf_nvdivert_to_divert(const nvlist_t *nvl, struct pfctl_rule *rule) 6940d71f9f3SKristof Provost { 6950d71f9f3SKristof Provost pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "addr"), &rule->divert.addr); 6960d71f9f3SKristof Provost rule->divert.port = nvlist_get_number(nvl, "port"); 6970d71f9f3SKristof Provost } 6980d71f9f3SKristof Provost 6990d71f9f3SKristof Provost static void 700e9eb0941SKristof Provost pf_nvrule_to_rule(const nvlist_t *nvl, struct pfctl_rule *rule) 7010d71f9f3SKristof Provost { 7020d71f9f3SKristof Provost const uint64_t *skip; 7036fcc8e04SKristof Provost const char *const *labels; 7046fcc8e04SKristof Provost size_t skipcount, labelcount; 7050d71f9f3SKristof Provost 7060d71f9f3SKristof Provost rule->nr = nvlist_get_number(nvl, "nr"); 7070d71f9f3SKristof Provost 7080d71f9f3SKristof Provost pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "src"), &rule->src); 7090d71f9f3SKristof Provost pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "dst"), &rule->dst); 7100d71f9f3SKristof Provost 7110d71f9f3SKristof Provost skip = nvlist_get_number_array(nvl, "skip", &skipcount); 7120d71f9f3SKristof Provost assert(skip); 7130d71f9f3SKristof Provost assert(skipcount == PF_SKIP_COUNT); 7140d71f9f3SKristof Provost for (int i = 0; i < PF_SKIP_COUNT; i++) 7150d71f9f3SKristof Provost rule->skip[i].nr = skip[i]; 7160d71f9f3SKristof Provost 7176fcc8e04SKristof Provost labels = nvlist_get_string_array(nvl, "labels", &labelcount); 7186fcc8e04SKristof Provost assert(labelcount <= PF_RULE_MAX_LABEL_COUNT); 7196fcc8e04SKristof Provost for (size_t i = 0; i < labelcount; i++) 7206fcc8e04SKristof Provost strlcpy(rule->label[i], labels[i], PF_RULE_LABEL_SIZE); 72176c5eeccSKristof Provost rule->ridentifier = nvlist_get_number(nvl, "ridentifier"); 7220d71f9f3SKristof Provost strlcpy(rule->ifname, nvlist_get_string(nvl, "ifname"), IFNAMSIZ); 7230d71f9f3SKristof Provost strlcpy(rule->qname, nvlist_get_string(nvl, "qname"), PF_QNAME_SIZE); 7240d71f9f3SKristof Provost strlcpy(rule->pqname, nvlist_get_string(nvl, "pqname"), PF_QNAME_SIZE); 7250d71f9f3SKristof Provost strlcpy(rule->tagname, nvlist_get_string(nvl, "tagname"), 7260d71f9f3SKristof Provost PF_TAG_NAME_SIZE); 7270d71f9f3SKristof Provost strlcpy(rule->match_tagname, nvlist_get_string(nvl, "match_tagname"), 7280d71f9f3SKristof Provost PF_TAG_NAME_SIZE); 7290d71f9f3SKristof Provost 7300d71f9f3SKristof Provost strlcpy(rule->overload_tblname, nvlist_get_string(nvl, "overload_tblname"), 7310d71f9f3SKristof Provost PF_TABLE_NAME_SIZE); 7320d71f9f3SKristof Provost 733e11dacbfSKristof Provost pf_nvpool_to_pool(nvlist_get_nvlist(nvl, "rpool"), &rule->rdr); 7340d71f9f3SKristof Provost 7350d71f9f3SKristof Provost rule->evaluations = nvlist_get_number(nvl, "evaluations"); 7360d71f9f3SKristof Provost pf_nvuint_64_array(nvl, "packets", 2, rule->packets, NULL); 7370d71f9f3SKristof Provost pf_nvuint_64_array(nvl, "bytes", 2, rule->bytes, NULL); 7380d71f9f3SKristof Provost 7390abcc1d2SReid Linnemann if (nvlist_exists_number(nvl, "timestamp")) { 7400abcc1d2SReid Linnemann rule->last_active_timestamp = nvlist_get_number(nvl, "timestamp"); 7410abcc1d2SReid Linnemann } 7420abcc1d2SReid Linnemann 7430d71f9f3SKristof Provost rule->os_fingerprint = nvlist_get_number(nvl, "os_fingerprint"); 7440d71f9f3SKristof Provost 7450d71f9f3SKristof Provost rule->rtableid = nvlist_get_number(nvl, "rtableid"); 7460d71f9f3SKristof Provost pf_nvuint_32_array(nvl, "timeout", PFTM_MAX, rule->timeout, NULL); 7470d71f9f3SKristof Provost rule->max_states = nvlist_get_number(nvl, "max_states"); 7480d71f9f3SKristof Provost rule->max_src_nodes = nvlist_get_number(nvl, "max_src_nodes"); 7490d71f9f3SKristof Provost rule->max_src_states = nvlist_get_number(nvl, "max_src_states"); 7500d71f9f3SKristof Provost rule->max_src_conn = nvlist_get_number(nvl, "max_src_conn"); 7510d71f9f3SKristof Provost rule->max_src_conn_rate.limit = 7520d71f9f3SKristof Provost nvlist_get_number(nvl, "max_src_conn_rate.limit"); 7530d71f9f3SKristof Provost rule->max_src_conn_rate.seconds = 7540d71f9f3SKristof Provost nvlist_get_number(nvl, "max_src_conn_rate.seconds"); 7550d71f9f3SKristof Provost rule->qid = nvlist_get_number(nvl, "qid"); 7560d71f9f3SKristof Provost rule->pqid = nvlist_get_number(nvl, "pqid"); 75763b3c1c7SKristof Provost rule->dnpipe = nvlist_get_number(nvl, "dnpipe"); 75863b3c1c7SKristof Provost rule->dnrpipe = nvlist_get_number(nvl, "dnrpipe"); 75963b3c1c7SKristof Provost rule->free_flags = nvlist_get_number(nvl, "dnflags"); 7600d71f9f3SKristof Provost rule->prob = nvlist_get_number(nvl, "prob"); 7610d71f9f3SKristof Provost rule->cuid = nvlist_get_number(nvl, "cuid"); 7620d71f9f3SKristof Provost rule->cpid = nvlist_get_number(nvl, "cpid"); 7630d71f9f3SKristof Provost 7640d71f9f3SKristof Provost rule->return_icmp = nvlist_get_number(nvl, "return_icmp"); 7650d71f9f3SKristof Provost rule->return_icmp6 = nvlist_get_number(nvl, "return_icmp6"); 7660d71f9f3SKristof Provost rule->max_mss = nvlist_get_number(nvl, "max_mss"); 7670d71f9f3SKristof Provost rule->scrub_flags = nvlist_get_number(nvl, "scrub_flags"); 7680d71f9f3SKristof Provost 7690d71f9f3SKristof Provost pf_nvrule_uid_to_rule_uid(nvlist_get_nvlist(nvl, "uid"), &rule->uid); 7700d71f9f3SKristof Provost pf_nvrule_uid_to_rule_uid(nvlist_get_nvlist(nvl, "gid"), 7710d71f9f3SKristof Provost (struct pf_rule_uid *)&rule->gid); 7720d71f9f3SKristof Provost 7730d71f9f3SKristof Provost rule->rule_flag = nvlist_get_number(nvl, "rule_flag"); 7740d71f9f3SKristof Provost rule->action = nvlist_get_number(nvl, "action"); 7750d71f9f3SKristof Provost rule->direction = nvlist_get_number(nvl, "direction"); 7760d71f9f3SKristof Provost rule->log = nvlist_get_number(nvl, "log"); 7770d71f9f3SKristof Provost rule->logif = nvlist_get_number(nvl, "logif"); 7780d71f9f3SKristof Provost rule->quick = nvlist_get_number(nvl, "quick"); 7790d71f9f3SKristof Provost rule->ifnot = nvlist_get_number(nvl, "ifnot"); 7800d71f9f3SKristof Provost rule->match_tag_not = nvlist_get_number(nvl, "match_tag_not"); 7810d71f9f3SKristof Provost rule->natpass = nvlist_get_number(nvl, "natpass"); 7820d71f9f3SKristof Provost 7830d71f9f3SKristof Provost rule->keep_state = nvlist_get_number(nvl, "keep_state"); 7840d71f9f3SKristof Provost rule->af = nvlist_get_number(nvl, "af"); 7850d71f9f3SKristof Provost rule->proto = nvlist_get_number(nvl, "proto"); 7860d71f9f3SKristof Provost rule->type = nvlist_get_number(nvl, "type"); 7870d71f9f3SKristof Provost rule->code = nvlist_get_number(nvl, "code"); 7880d71f9f3SKristof Provost rule->flags = nvlist_get_number(nvl, "flags"); 7890d71f9f3SKristof Provost rule->flagset = nvlist_get_number(nvl, "flagset"); 7900d71f9f3SKristof Provost rule->min_ttl = nvlist_get_number(nvl, "min_ttl"); 7910d71f9f3SKristof Provost rule->allow_opts = nvlist_get_number(nvl, "allow_opts"); 7920d71f9f3SKristof Provost rule->rt = nvlist_get_number(nvl, "rt"); 7930d71f9f3SKristof Provost rule->return_ttl = nvlist_get_number(nvl, "return_ttl"); 7940d71f9f3SKristof Provost rule->tos = nvlist_get_number(nvl, "tos"); 7950d71f9f3SKristof Provost rule->set_tos = nvlist_get_number(nvl, "set_tos"); 7960d71f9f3SKristof Provost rule->anchor_relative = nvlist_get_number(nvl, "anchor_relative"); 7970d71f9f3SKristof Provost rule->anchor_wildcard = nvlist_get_number(nvl, "anchor_wildcard"); 7980d71f9f3SKristof Provost 7990d71f9f3SKristof Provost rule->flush = nvlist_get_number(nvl, "flush"); 8000d71f9f3SKristof Provost rule->prio = nvlist_get_number(nvl, "prio"); 8010d71f9f3SKristof Provost pf_nvuint_8_array(nvl, "set_prio", 2, rule->set_prio, NULL); 8020d71f9f3SKristof Provost 8030d71f9f3SKristof Provost pf_nvdivert_to_divert(nvlist_get_nvlist(nvl, "divert"), rule); 8040d71f9f3SKristof Provost 805ab5707a5SKristof Provost rule->states_cur = nvlist_get_number(nvl, "states_cur"); 806ab5707a5SKristof Provost rule->states_tot = nvlist_get_number(nvl, "states_tot"); 807ab5707a5SKristof Provost rule->src_nodes = nvlist_get_number(nvl, "src_nodes"); 8080d71f9f3SKristof Provost } 8090d71f9f3SKristof Provost 8102b29ceb8SKristof Provost static void 8112b29ceb8SKristof Provost pfctl_nveth_addr_to_eth_addr(const nvlist_t *nvl, struct pfctl_eth_addr *addr) 8122b29ceb8SKristof Provost { 813c696d5c7SKristof Provost static const u_int8_t EMPTY_MAC[ETHER_ADDR_LEN] = { 0 }; 8142b29ceb8SKristof Provost size_t len; 8152b29ceb8SKristof Provost const void *data; 8162b29ceb8SKristof Provost 8172b29ceb8SKristof Provost data = nvlist_get_binary(nvl, "addr", &len); 8182b29ceb8SKristof Provost assert(len == sizeof(addr->addr)); 8192b29ceb8SKristof Provost memcpy(addr->addr, data, sizeof(addr->addr)); 8202b29ceb8SKristof Provost 821b590f17aSKristof Provost data = nvlist_get_binary(nvl, "mask", &len); 822b590f17aSKristof Provost assert(len == sizeof(addr->mask)); 823b590f17aSKristof Provost memcpy(addr->mask, data, sizeof(addr->mask)); 824b590f17aSKristof Provost 8252b29ceb8SKristof Provost addr->neg = nvlist_get_bool(nvl, "neg"); 826c696d5c7SKristof Provost 827c696d5c7SKristof Provost /* To make checks for 'is this address set?' easier. */ 828c696d5c7SKristof Provost addr->isset = memcmp(addr->addr, EMPTY_MAC, ETHER_ADDR_LEN) != 0; 8292b29ceb8SKristof Provost } 8302b29ceb8SKristof Provost 8312b29ceb8SKristof Provost static nvlist_t * 8322b29ceb8SKristof Provost pfctl_eth_addr_to_nveth_addr(const struct pfctl_eth_addr *addr) 8332b29ceb8SKristof Provost { 8342b29ceb8SKristof Provost nvlist_t *nvl; 8352b29ceb8SKristof Provost 8362b29ceb8SKristof Provost nvl = nvlist_create(0); 8372b29ceb8SKristof Provost if (nvl == NULL) 8382b29ceb8SKristof Provost return (NULL); 8392b29ceb8SKristof Provost 8402b29ceb8SKristof Provost nvlist_add_bool(nvl, "neg", addr->neg); 8412b29ceb8SKristof Provost nvlist_add_binary(nvl, "addr", &addr->addr, ETHER_ADDR_LEN); 842b590f17aSKristof Provost nvlist_add_binary(nvl, "mask", &addr->mask, ETHER_ADDR_LEN); 8432b29ceb8SKristof Provost 8442b29ceb8SKristof Provost return (nvl); 8452b29ceb8SKristof Provost } 8462b29ceb8SKristof Provost 8472b29ceb8SKristof Provost static void 8482b29ceb8SKristof Provost pfctl_nveth_rule_to_eth_rule(const nvlist_t *nvl, struct pfctl_eth_rule *rule) 8492b29ceb8SKristof Provost { 850ef661d4aSChristian McDonald const char *const *labels; 851ef661d4aSChristian McDonald size_t labelcount, i; 852ef661d4aSChristian McDonald 8532b29ceb8SKristof Provost rule->nr = nvlist_get_number(nvl, "nr"); 8542b29ceb8SKristof Provost rule->quick = nvlist_get_bool(nvl, "quick"); 8552b29ceb8SKristof Provost strlcpy(rule->ifname, nvlist_get_string(nvl, "ifname"), IFNAMSIZ); 8562b29ceb8SKristof Provost rule->ifnot = nvlist_get_bool(nvl, "ifnot"); 8572b29ceb8SKristof Provost rule->direction = nvlist_get_number(nvl, "direction"); 8582b29ceb8SKristof Provost rule->proto = nvlist_get_number(nvl, "proto"); 8591f61367fSKristof Provost strlcpy(rule->match_tagname, nvlist_get_string(nvl, "match_tagname"), 8601f61367fSKristof Provost PF_TAG_NAME_SIZE); 8611f61367fSKristof Provost rule->match_tag = nvlist_get_number(nvl, "match_tag"); 8621f61367fSKristof Provost rule->match_tag_not = nvlist_get_bool(nvl, "match_tag_not"); 8632b29ceb8SKristof Provost 864ef661d4aSChristian McDonald labels = nvlist_get_string_array(nvl, "labels", &labelcount); 865ef661d4aSChristian McDonald assert(labelcount <= PF_RULE_MAX_LABEL_COUNT); 866ef661d4aSChristian McDonald for (i = 0; i < labelcount; i++) 867ef661d4aSChristian McDonald strlcpy(rule->label[i], labels[i], PF_RULE_LABEL_SIZE); 868ef661d4aSChristian McDonald rule->ridentifier = nvlist_get_number(nvl, "ridentifier"); 869ef661d4aSChristian McDonald 8702b29ceb8SKristof Provost pfctl_nveth_addr_to_eth_addr(nvlist_get_nvlist(nvl, "src"), 8712b29ceb8SKristof Provost &rule->src); 8722b29ceb8SKristof Provost pfctl_nveth_addr_to_eth_addr(nvlist_get_nvlist(nvl, "dst"), 8732b29ceb8SKristof Provost &rule->dst); 8742b29ceb8SKristof Provost 8758a42005dSKristof Provost pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "ipsrc"), 8768a42005dSKristof Provost &rule->ipsrc); 8778a42005dSKristof Provost pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "ipdst"), 8788a42005dSKristof Provost &rule->ipdst); 8798a42005dSKristof Provost 8802b29ceb8SKristof Provost rule->evaluations = nvlist_get_number(nvl, "evaluations"); 8812b29ceb8SKristof Provost rule->packets[0] = nvlist_get_number(nvl, "packets-in"); 8822b29ceb8SKristof Provost rule->packets[1] = nvlist_get_number(nvl, "packets-out"); 8832b29ceb8SKristof Provost rule->bytes[0] = nvlist_get_number(nvl, "bytes-in"); 8842b29ceb8SKristof Provost rule->bytes[1] = nvlist_get_number(nvl, "bytes-out"); 8852b29ceb8SKristof Provost 8860abcc1d2SReid Linnemann if (nvlist_exists_number(nvl, "timestamp")) { 8870abcc1d2SReid Linnemann rule->last_active_timestamp = nvlist_get_number(nvl, "timestamp"); 8880abcc1d2SReid Linnemann } 8890abcc1d2SReid Linnemann 8902b29ceb8SKristof Provost strlcpy(rule->qname, nvlist_get_string(nvl, "qname"), PF_QNAME_SIZE); 8912b29ceb8SKristof Provost strlcpy(rule->tagname, nvlist_get_string(nvl, "tagname"), 8922b29ceb8SKristof Provost PF_TAG_NAME_SIZE); 8932b29ceb8SKristof Provost 894fb330f39SKristof Provost rule->dnpipe = nvlist_get_number(nvl, "dnpipe"); 895fb330f39SKristof Provost rule->dnflags = nvlist_get_number(nvl, "dnflags"); 896fb330f39SKristof Provost 897c5131afeSKristof Provost rule->anchor_relative = nvlist_get_number(nvl, "anchor_relative"); 898c5131afeSKristof Provost rule->anchor_wildcard = nvlist_get_number(nvl, "anchor_wildcard"); 899c5131afeSKristof Provost 9008a8af942SKristof Provost strlcpy(rule->bridge_to, nvlist_get_string(nvl, "bridge_to"), 9018a8af942SKristof Provost IFNAMSIZ); 9028a8af942SKristof Provost 9032b29ceb8SKristof Provost rule->action = nvlist_get_number(nvl, "action"); 9042b29ceb8SKristof Provost } 9052b29ceb8SKristof Provost 9062b29ceb8SKristof Provost int 9079bb06778SKristof Provost pfctl_get_eth_rulesets_info(int dev, struct pfctl_eth_rulesets_info *ri, 9089bb06778SKristof Provost const char *path) 9099bb06778SKristof Provost { 9109bb06778SKristof Provost nvlist_t *nvl; 9117ed19f5cSKristof Provost int ret; 9129bb06778SKristof Provost 9139bb06778SKristof Provost bzero(ri, sizeof(*ri)); 9149bb06778SKristof Provost 9159bb06778SKristof Provost nvl = nvlist_create(0); 9169bb06778SKristof Provost nvlist_add_string(nvl, "path", path); 9179bb06778SKristof Provost 9187ed19f5cSKristof Provost if ((ret = pfctl_do_ioctl(dev, DIOCGETETHRULESETS, 256, &nvl)) != 0) 919498934c5SKristof Provost goto out; 9209bb06778SKristof Provost 9219bb06778SKristof Provost ri->nr = nvlist_get_number(nvl, "nr"); 9229bb06778SKristof Provost 923498934c5SKristof Provost out: 9249bb06778SKristof Provost nvlist_destroy(nvl); 925498934c5SKristof Provost return (ret); 9269bb06778SKristof Provost } 9279bb06778SKristof Provost 9289bb06778SKristof Provost int 9299bb06778SKristof Provost pfctl_get_eth_ruleset(int dev, const char *path, int nr, 9309bb06778SKristof Provost struct pfctl_eth_ruleset_info *ri) 9319bb06778SKristof Provost { 9329bb06778SKristof Provost nvlist_t *nvl; 9337ed19f5cSKristof Provost int ret; 9349bb06778SKristof Provost 9359bb06778SKristof Provost bzero(ri, sizeof(*ri)); 9369bb06778SKristof Provost 9379bb06778SKristof Provost nvl = nvlist_create(0); 9389bb06778SKristof Provost nvlist_add_string(nvl, "path", path); 9399bb06778SKristof Provost nvlist_add_number(nvl, "nr", nr); 9409bb06778SKristof Provost 9417ed19f5cSKristof Provost if ((ret = pfctl_do_ioctl(dev, DIOCGETETHRULESET, 1024, &nvl)) != 0) 942498934c5SKristof Provost goto out; 9439bb06778SKristof Provost 9449bb06778SKristof Provost ri->nr = nvlist_get_number(nvl, "nr"); 9459bb06778SKristof Provost strlcpy(ri->path, nvlist_get_string(nvl, "path"), MAXPATHLEN); 9469bb06778SKristof Provost strlcpy(ri->name, nvlist_get_string(nvl, "name"), 9479bb06778SKristof Provost PF_ANCHOR_NAME_SIZE); 9489bb06778SKristof Provost 949498934c5SKristof Provost out: 9504abc3b48SKristof Provost nvlist_destroy(nvl); 951498934c5SKristof Provost return (ret); 9529bb06778SKristof Provost } 9539bb06778SKristof Provost 9549bb06778SKristof Provost int 955c5131afeSKristof Provost pfctl_get_eth_rules_info(int dev, struct pfctl_eth_rules_info *rules, 956c5131afeSKristof Provost const char *path) 9572b29ceb8SKristof Provost { 9582b29ceb8SKristof Provost nvlist_t *nvl; 9597ed19f5cSKristof Provost int ret; 9602b29ceb8SKristof Provost 9612b29ceb8SKristof Provost bzero(rules, sizeof(*rules)); 9622b29ceb8SKristof Provost 963c5131afeSKristof Provost nvl = nvlist_create(0); 964c5131afeSKristof Provost nvlist_add_string(nvl, "anchor", path); 965c5131afeSKristof Provost 9667ed19f5cSKristof Provost if ((ret = pfctl_do_ioctl(dev, DIOCGETETHRULES, 1024, &nvl)) != 0) 967498934c5SKristof Provost goto out; 9682b29ceb8SKristof Provost 9692b29ceb8SKristof Provost rules->nr = nvlist_get_number(nvl, "nr"); 9702b29ceb8SKristof Provost rules->ticket = nvlist_get_number(nvl, "ticket"); 9712b29ceb8SKristof Provost 972498934c5SKristof Provost out: 9732b29ceb8SKristof Provost nvlist_destroy(nvl); 974498934c5SKristof Provost return (ret); 9752b29ceb8SKristof Provost } 9762b29ceb8SKristof Provost 9772b29ceb8SKristof Provost int 9782b29ceb8SKristof Provost pfctl_get_eth_rule(int dev, uint32_t nr, uint32_t ticket, 979c5131afeSKristof Provost const char *path, struct pfctl_eth_rule *rule, bool clear, 980c5131afeSKristof Provost char *anchor_call) 9812b29ceb8SKristof Provost { 9822b29ceb8SKristof Provost nvlist_t *nvl; 9837ed19f5cSKristof Provost int ret; 9842b29ceb8SKristof Provost 9852b29ceb8SKristof Provost nvl = nvlist_create(0); 9862b29ceb8SKristof Provost 987c5131afeSKristof Provost nvlist_add_string(nvl, "anchor", path); 9882b29ceb8SKristof Provost nvlist_add_number(nvl, "ticket", ticket); 9892b29ceb8SKristof Provost nvlist_add_number(nvl, "nr", nr); 9902b29ceb8SKristof Provost nvlist_add_bool(nvl, "clear", clear); 9912b29ceb8SKristof Provost 9920abcc1d2SReid Linnemann if ((ret = pfctl_do_ioctl(dev, DIOCGETETHRULE, 4096, &nvl)) != 0) 993498934c5SKristof Provost goto out; 9942b29ceb8SKristof Provost 9952b29ceb8SKristof Provost pfctl_nveth_rule_to_eth_rule(nvl, rule); 9962b29ceb8SKristof Provost 997c5131afeSKristof Provost if (anchor_call) 998c5131afeSKristof Provost strlcpy(anchor_call, nvlist_get_string(nvl, "anchor_call"), 999c5131afeSKristof Provost MAXPATHLEN); 1000c5131afeSKristof Provost 1001498934c5SKristof Provost out: 10022b29ceb8SKristof Provost nvlist_destroy(nvl); 1003498934c5SKristof Provost return (ret); 10042b29ceb8SKristof Provost } 10052b29ceb8SKristof Provost 10062b29ceb8SKristof Provost int 1007c5131afeSKristof Provost pfctl_add_eth_rule(int dev, const struct pfctl_eth_rule *r, const char *anchor, 1008c5131afeSKristof Provost const char *anchor_call, uint32_t ticket) 10092b29ceb8SKristof Provost { 10102b29ceb8SKristof Provost struct pfioc_nv nv; 10112b29ceb8SKristof Provost nvlist_t *nvl, *addr; 10122b29ceb8SKristof Provost void *packed; 1013514039bbSKristof Provost int error = 0; 1014ef661d4aSChristian McDonald size_t labelcount, size; 10152b29ceb8SKristof Provost 10162b29ceb8SKristof Provost nvl = nvlist_create(0); 10172b29ceb8SKristof Provost 10182b29ceb8SKristof Provost nvlist_add_number(nvl, "ticket", ticket); 1019c5131afeSKristof Provost nvlist_add_string(nvl, "anchor", anchor); 1020c5131afeSKristof Provost nvlist_add_string(nvl, "anchor_call", anchor_call); 10212b29ceb8SKristof Provost 10222b29ceb8SKristof Provost nvlist_add_number(nvl, "nr", r->nr); 10232b29ceb8SKristof Provost nvlist_add_bool(nvl, "quick", r->quick); 10242b29ceb8SKristof Provost nvlist_add_string(nvl, "ifname", r->ifname); 10252b29ceb8SKristof Provost nvlist_add_bool(nvl, "ifnot", r->ifnot); 10262b29ceb8SKristof Provost nvlist_add_number(nvl, "direction", r->direction); 10272b29ceb8SKristof Provost nvlist_add_number(nvl, "proto", r->proto); 10281f61367fSKristof Provost nvlist_add_string(nvl, "match_tagname", r->match_tagname); 10291f61367fSKristof Provost nvlist_add_bool(nvl, "match_tag_not", r->match_tag_not); 10302b29ceb8SKristof Provost 10312b29ceb8SKristof Provost addr = pfctl_eth_addr_to_nveth_addr(&r->src); 10322b29ceb8SKristof Provost if (addr == NULL) { 10332b29ceb8SKristof Provost nvlist_destroy(nvl); 10342b29ceb8SKristof Provost return (ENOMEM); 10352b29ceb8SKristof Provost } 10362b29ceb8SKristof Provost nvlist_add_nvlist(nvl, "src", addr); 10372b29ceb8SKristof Provost nvlist_destroy(addr); 10382b29ceb8SKristof Provost 10392b29ceb8SKristof Provost addr = pfctl_eth_addr_to_nveth_addr(&r->dst); 10402b29ceb8SKristof Provost if (addr == NULL) { 10412b29ceb8SKristof Provost nvlist_destroy(nvl); 10422b29ceb8SKristof Provost return (ENOMEM); 10432b29ceb8SKristof Provost } 10442b29ceb8SKristof Provost nvlist_add_nvlist(nvl, "dst", addr); 10452b29ceb8SKristof Provost nvlist_destroy(addr); 10462b29ceb8SKristof Provost 10478a42005dSKristof Provost pfctl_nv_add_rule_addr(nvl, "ipsrc", &r->ipsrc); 10488a42005dSKristof Provost pfctl_nv_add_rule_addr(nvl, "ipdst", &r->ipdst); 10498a42005dSKristof Provost 1050ef661d4aSChristian McDonald labelcount = 0; 10514abc3b48SKristof Provost while (labelcount < PF_RULE_MAX_LABEL_COUNT && 10524abc3b48SKristof Provost r->label[labelcount][0] != 0) { 1053ef661d4aSChristian McDonald nvlist_append_string_array(nvl, "labels", 1054ef661d4aSChristian McDonald r->label[labelcount]); 1055ef661d4aSChristian McDonald labelcount++; 1056ef661d4aSChristian McDonald } 1057ef661d4aSChristian McDonald nvlist_add_number(nvl, "ridentifier", r->ridentifier); 1058ef661d4aSChristian McDonald 10592b29ceb8SKristof Provost nvlist_add_string(nvl, "qname", r->qname); 10602b29ceb8SKristof Provost nvlist_add_string(nvl, "tagname", r->tagname); 1061fb330f39SKristof Provost nvlist_add_number(nvl, "dnpipe", r->dnpipe); 1062fb330f39SKristof Provost nvlist_add_number(nvl, "dnflags", r->dnflags); 1063fb330f39SKristof Provost 10648a8af942SKristof Provost nvlist_add_string(nvl, "bridge_to", r->bridge_to); 10658a8af942SKristof Provost 10662b29ceb8SKristof Provost nvlist_add_number(nvl, "action", r->action); 10672b29ceb8SKristof Provost 10682b29ceb8SKristof Provost packed = nvlist_pack(nvl, &size); 10692b29ceb8SKristof Provost if (packed == NULL) { 10702b29ceb8SKristof Provost nvlist_destroy(nvl); 10712b29ceb8SKristof Provost return (ENOMEM); 10722b29ceb8SKristof Provost } 10732b29ceb8SKristof Provost 10742b29ceb8SKristof Provost nv.len = size; 10752b29ceb8SKristof Provost nv.size = size; 10762b29ceb8SKristof Provost nv.data = packed; 10772b29ceb8SKristof Provost 1078514039bbSKristof Provost if (ioctl(dev, DIOCADDETHRULE, &nv) != 0) 1079514039bbSKristof Provost error = errno; 10802b29ceb8SKristof Provost 10812b29ceb8SKristof Provost free(packed); 10822b29ceb8SKristof Provost nvlist_destroy(nvl); 10832b29ceb8SKristof Provost 10842b29ceb8SKristof Provost return (error); 10852b29ceb8SKristof Provost } 10862b29ceb8SKristof Provost 1087ffbf2595SKristof Provost static void 1088ffbf2595SKristof Provost snl_add_msg_attr_addr_wrap(struct snl_writer *nw, uint32_t type, const struct pf_addr_wrap *addr) 1089ffbf2595SKristof Provost { 1090ffbf2595SKristof Provost int off; 1091ffbf2595SKristof Provost 1092ffbf2595SKristof Provost off = snl_add_msg_attr_nested(nw, type); 1093ffbf2595SKristof Provost 1094ffbf2595SKristof Provost snl_add_msg_attr_ip6(nw, PF_AT_ADDR, &addr->v.a.addr.v6); 1095ffbf2595SKristof Provost snl_add_msg_attr_ip6(nw, PF_AT_MASK, &addr->v.a.mask.v6); 1096ffbf2595SKristof Provost 1097ffbf2595SKristof Provost if (addr->type == PF_ADDR_DYNIFTL) 1098ffbf2595SKristof Provost snl_add_msg_attr_string(nw, PF_AT_IFNAME, addr->v.ifname); 1099ffbf2595SKristof Provost if (addr->type == PF_ADDR_TABLE) 1100ffbf2595SKristof Provost snl_add_msg_attr_string(nw, PF_AT_TABLENAME, addr->v.tblname); 1101ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_AT_TYPE, addr->type); 1102ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_AT_IFLAGS, addr->iflags); 1103ffbf2595SKristof Provost 1104ffbf2595SKristof Provost snl_end_attr_nested(nw, off); 1105ffbf2595SKristof Provost } 1106ffbf2595SKristof Provost 1107ffbf2595SKristof Provost static void 1108d909f06bSKristof Provost snl_add_msg_attr_pool_addr(struct snl_writer *nw, uint32_t type, const struct pf_pooladdr *pa) 1109d909f06bSKristof Provost { 1110d909f06bSKristof Provost int off; 1111d909f06bSKristof Provost 1112d909f06bSKristof Provost off = snl_add_msg_attr_nested(nw, type); 1113d909f06bSKristof Provost 1114d909f06bSKristof Provost snl_add_msg_attr_string(nw, PF_PA_IFNAME, pa->ifname); 1115d909f06bSKristof Provost snl_add_msg_attr_addr_wrap(nw, PF_PA_ADDR, &pa->addr); 1116d909f06bSKristof Provost 1117d909f06bSKristof Provost snl_end_attr_nested(nw, off); 1118d909f06bSKristof Provost } 1119d909f06bSKristof Provost 1120d909f06bSKristof Provost static void 1121ffbf2595SKristof Provost snl_add_msg_attr_rule_addr(struct snl_writer *nw, uint32_t type, const struct pf_rule_addr *addr) 1122ffbf2595SKristof Provost { 1123ffbf2595SKristof Provost int off; 1124ffbf2595SKristof Provost 1125ffbf2595SKristof Provost off = snl_add_msg_attr_nested(nw, type); 1126ffbf2595SKristof Provost 1127ffbf2595SKristof Provost snl_add_msg_attr_addr_wrap(nw, PF_RAT_ADDR, &addr->addr); 1128ffbf2595SKristof Provost snl_add_msg_attr_u16(nw, PF_RAT_SRC_PORT, addr->port[0]); 1129ffbf2595SKristof Provost snl_add_msg_attr_u16(nw, PF_RAT_DST_PORT, addr->port[1]); 1130ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RAT_NEG, addr->neg); 1131ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RAT_OP, addr->port_op); 1132ffbf2595SKristof Provost 1133ffbf2595SKristof Provost snl_end_attr_nested(nw, off); 1134ffbf2595SKristof Provost } 1135ffbf2595SKristof Provost 1136ffbf2595SKristof Provost static void 1137ffbf2595SKristof Provost snl_add_msg_attr_rule_labels(struct snl_writer *nw, uint32_t type, const char labels[PF_RULE_MAX_LABEL_COUNT][PF_RULE_LABEL_SIZE]) 1138ffbf2595SKristof Provost { 1139ffbf2595SKristof Provost int off, i = 0; 1140ffbf2595SKristof Provost 1141ffbf2595SKristof Provost off = snl_add_msg_attr_nested(nw, type); 1142ffbf2595SKristof Provost 1143306d3fb2SKristof Provost while (i < PF_RULE_MAX_LABEL_COUNT && 1144306d3fb2SKristof Provost labels[i][0] != 0) { 1145ffbf2595SKristof Provost snl_add_msg_attr_string(nw, PF_LT_LABEL, labels[i]); 1146ffbf2595SKristof Provost i++; 1147ffbf2595SKristof Provost } 1148ffbf2595SKristof Provost 1149ffbf2595SKristof Provost snl_end_attr_nested(nw, off); 1150ffbf2595SKristof Provost } 1151ffbf2595SKristof Provost 1152ffbf2595SKristof Provost static void 1153ffbf2595SKristof Provost snl_add_msg_attr_mape(struct snl_writer *nw, uint32_t type, const struct pf_mape_portset *me) 1154ffbf2595SKristof Provost { 1155ffbf2595SKristof Provost int off; 1156ffbf2595SKristof Provost 1157ffbf2595SKristof Provost off = snl_add_msg_attr_nested(nw, type); 1158ffbf2595SKristof Provost 1159ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_MET_OFFSET, me->offset); 1160ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_MET_PSID_LEN, me->psidlen); 1161ffbf2595SKristof Provost snl_add_msg_attr_u16(nw, PF_MET_PSID, me->psid); 1162ffbf2595SKristof Provost 1163ffbf2595SKristof Provost snl_end_attr_nested(nw, off); 1164ffbf2595SKristof Provost } 1165ffbf2595SKristof Provost 1166ffbf2595SKristof Provost static void 1167ffbf2595SKristof Provost snl_add_msg_attr_rpool(struct snl_writer *nw, uint32_t type, const struct pfctl_pool *pool) 1168ffbf2595SKristof Provost { 1169ffbf2595SKristof Provost int off; 1170ffbf2595SKristof Provost 1171ffbf2595SKristof Provost off = snl_add_msg_attr_nested(nw, type); 1172ffbf2595SKristof Provost 1173ffbf2595SKristof Provost snl_add_msg_attr(nw, PF_PT_KEY, sizeof(pool->key), &pool->key); 1174ffbf2595SKristof Provost snl_add_msg_attr_ip6(nw, PF_PT_COUNTER, &pool->counter.v6); 1175ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_PT_TBLIDX, pool->tblidx); 1176ffbf2595SKristof Provost snl_add_msg_attr_u16(nw, PF_PT_PROXY_SRC_PORT, pool->proxy_port[0]); 1177ffbf2595SKristof Provost snl_add_msg_attr_u16(nw, PF_PT_PROXY_DST_PORT, pool->proxy_port[1]); 1178ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_PT_OPTS, pool->opts); 1179ffbf2595SKristof Provost snl_add_msg_attr_mape(nw, PF_PT_MAPE, &pool->mape); 1180ffbf2595SKristof Provost 1181ffbf2595SKristof Provost snl_end_attr_nested(nw, off); 1182ffbf2595SKristof Provost } 1183ffbf2595SKristof Provost 1184ffbf2595SKristof Provost static void 1185ffbf2595SKristof Provost snl_add_msg_attr_timeouts(struct snl_writer *nw, uint32_t type, const uint32_t *timeouts) 1186ffbf2595SKristof Provost { 1187ffbf2595SKristof Provost int off; 1188ffbf2595SKristof Provost 1189ffbf2595SKristof Provost off = snl_add_msg_attr_nested(nw, type); 1190ffbf2595SKristof Provost 1191ffbf2595SKristof Provost for (int i = 0; i < PFTM_MAX; i++) 1192ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_TT_TIMEOUT, timeouts[i]); 1193ffbf2595SKristof Provost 1194ffbf2595SKristof Provost snl_end_attr_nested(nw, off); 1195ffbf2595SKristof Provost } 1196ffbf2595SKristof Provost 1197ffbf2595SKristof Provost static void 1198ffbf2595SKristof Provost snl_add_msg_attr_uid(struct snl_writer *nw, uint32_t type, const struct pf_rule_uid *uid) 1199ffbf2595SKristof Provost { 1200ffbf2595SKristof Provost int off; 1201ffbf2595SKristof Provost 1202ffbf2595SKristof Provost off = snl_add_msg_attr_nested(nw, type); 1203ffbf2595SKristof Provost 1204ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_RUT_UID_LOW, uid->uid[0]); 1205ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_RUT_UID_HIGH, uid->uid[1]); 1206ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RUT_OP, uid->op); 1207ffbf2595SKristof Provost 1208ffbf2595SKristof Provost snl_end_attr_nested(nw, off); 1209ffbf2595SKristof Provost } 1210ffbf2595SKristof Provost 1211ffbf2595SKristof Provost static void 1212ffbf2595SKristof Provost snl_add_msg_attr_pf_rule(struct snl_writer *nw, uint32_t type, const struct pfctl_rule *r) 1213ffbf2595SKristof Provost { 1214ffbf2595SKristof Provost int off; 1215ffbf2595SKristof Provost 1216ffbf2595SKristof Provost off = snl_add_msg_attr_nested(nw, type); 1217ffbf2595SKristof Provost 1218ffbf2595SKristof Provost snl_add_msg_attr_rule_addr(nw, PF_RT_SRC, &r->src); 1219ffbf2595SKristof Provost snl_add_msg_attr_rule_addr(nw, PF_RT_DST, &r->dst); 1220ffbf2595SKristof Provost snl_add_msg_attr_rule_labels(nw, PF_RT_LABELS, r->label); 1221ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_RT_RIDENTIFIER, r->ridentifier); 1222ffbf2595SKristof Provost snl_add_msg_attr_string(nw, PF_RT_IFNAME, r->ifname); 1223ffbf2595SKristof Provost snl_add_msg_attr_string(nw, PF_RT_QNAME, r->qname); 1224ffbf2595SKristof Provost snl_add_msg_attr_string(nw, PF_RT_PQNAME, r->pqname); 1225ffbf2595SKristof Provost snl_add_msg_attr_string(nw, PF_RT_TAGNAME, r->tagname); 1226ffbf2595SKristof Provost snl_add_msg_attr_string(nw, PF_RT_MATCH_TAGNAME, r->match_tagname); 1227ffbf2595SKristof Provost snl_add_msg_attr_string(nw, PF_RT_OVERLOAD_TBLNAME, r->overload_tblname); 1228e11dacbfSKristof Provost snl_add_msg_attr_rpool(nw, PF_RT_RPOOL_RDR, &r->rdr); 1229e11dacbfSKristof Provost snl_add_msg_attr_rpool(nw, PF_RT_RPOOL_NAT, &r->nat); 1230*0972294eSKristof Provost snl_add_msg_attr_rpool(nw, PF_RT_RPOOL_RT, &r->route); 1231ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_RT_OS_FINGERPRINT, r->os_fingerprint); 1232ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_RT_RTABLEID, r->rtableid); 1233ffbf2595SKristof Provost snl_add_msg_attr_timeouts(nw, PF_RT_TIMEOUT, r->timeout); 1234ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_RT_MAX_STATES, r->max_states); 1235ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_RT_MAX_SRC_NODES, r->max_src_nodes); 1236ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_RT_MAX_SRC_STATES, r->max_src_states); 12377fe42038SKajetan Staszkiewicz snl_add_msg_attr_u32(nw, PF_RT_MAX_SRC_CONN, r->max_src_conn); 1238ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_RT_MAX_SRC_CONN_RATE_LIMIT, r->max_src_conn_rate.limit); 1239ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_RT_MAX_SRC_CONN_RATE_SECS, r->max_src_conn_rate.seconds); 1240ffbf2595SKristof Provost 1241ffbf2595SKristof Provost snl_add_msg_attr_u16(nw, PF_RT_DNPIPE, r->dnpipe); 1242ffbf2595SKristof Provost snl_add_msg_attr_u16(nw, PF_RT_DNRPIPE, r->dnrpipe); 1243ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_RT_DNFLAGS, r->free_flags); 1244ffbf2595SKristof Provost 1245ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_RT_NR, r->nr); 1246ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_RT_PROB, r->prob); 1247ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_RT_CUID, r->cuid); 1248ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_RT_CPID, r->cpid); 1249ffbf2595SKristof Provost 1250ffbf2595SKristof Provost snl_add_msg_attr_u16(nw, PF_RT_RETURN_ICMP, r->return_icmp); 1251ffbf2595SKristof Provost snl_add_msg_attr_u16(nw, PF_RT_RETURN_ICMP6, r->return_icmp6); 1252ffbf2595SKristof Provost snl_add_msg_attr_u16(nw, PF_RT_MAX_MSS, r->max_mss); 1253ffbf2595SKristof Provost snl_add_msg_attr_u16(nw, PF_RT_SCRUB_FLAGS, r->scrub_flags); 1254ffbf2595SKristof Provost 1255ffbf2595SKristof Provost snl_add_msg_attr_uid(nw, PF_RT_UID, &r->uid); 1256ffbf2595SKristof Provost snl_add_msg_attr_uid(nw, PF_RT_GID, (const struct pf_rule_uid *)&r->gid); 12572339ead6SKristof Provost snl_add_msg_attr_string(nw, PF_RT_RCV_IFNAME, r->rcv_ifname); 1258ffbf2595SKristof Provost 1259ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_RT_RULE_FLAG, r->rule_flag); 1260ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_ACTION, r->action); 1261ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_DIRECTION, r->direction); 1262ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_LOG, r->log); 1263ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_LOGIF, r->logif); 1264ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_QUICK, r->quick); 1265ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_IF_NOT, r->ifnot); 1266ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_MATCH_TAG_NOT, r->match_tag_not); 1267ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_NATPASS, r->natpass); 1268ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_KEEP_STATE, r->keep_state); 1269ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_AF, r->af); 1270ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_PROTO, r->proto); 1271ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_TYPE, r->type); 1272ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_CODE, r->code); 1273ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_FLAGS, r->flags); 1274ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_FLAGSET, r->flagset); 1275ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_MIN_TTL, r->min_ttl); 1276ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_ALLOW_OPTS, r->allow_opts); 1277ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_RT, r->rt); 1278ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_RETURN_TTL, r->return_ttl); 1279ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_TOS, r->tos); 1280ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_SET_TOS, r->set_tos); 1281ffbf2595SKristof Provost 1282ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_ANCHOR_RELATIVE, r->anchor_relative); 1283ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_ANCHOR_WILDCARD, r->anchor_wildcard); 1284ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_FLUSH, r->flush); 1285ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_PRIO, r->prio); 1286ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_SET_PRIO, r->set_prio[0]); 1287ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_SET_PRIO_REPLY, r->set_prio[1]); 1288aa69fdf1SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_NAF, r->naf); 1289ffbf2595SKristof Provost 1290ffbf2595SKristof Provost snl_add_msg_attr_ip6(nw, PF_RT_DIVERT_ADDRESS, &r->divert.addr.v6); 1291ffbf2595SKristof Provost snl_add_msg_attr_u16(nw, PF_RT_DIVERT_PORT, r->divert.port); 1292ffbf2595SKristof Provost 1293ffbf2595SKristof Provost snl_end_attr_nested(nw, off); 1294ffbf2595SKristof Provost } 1295ffbf2595SKristof Provost 12960d71f9f3SKristof Provost int 1297ffbf2595SKristof Provost pfctl_add_rule(int dev __unused, const struct pfctl_rule *r, const char *anchor, 12987bb3c927SKristof Provost const char *anchor_call, uint32_t ticket, uint32_t pool_ticket) 12990d71f9f3SKristof Provost { 1300324fd7ecSKristof Provost struct pfctl_handle *h; 1301324fd7ecSKristof Provost int ret; 1302324fd7ecSKristof Provost 1303324fd7ecSKristof Provost h = pfctl_open(PF_DEVICE); 1304324fd7ecSKristof Provost if (h == NULL) 1305324fd7ecSKristof Provost return (ENODEV); 1306324fd7ecSKristof Provost 1307324fd7ecSKristof Provost ret = pfctl_add_rule_h(h, r, anchor, anchor_call, ticket, pool_ticket); 1308324fd7ecSKristof Provost 1309324fd7ecSKristof Provost pfctl_close(h); 1310324fd7ecSKristof Provost 1311324fd7ecSKristof Provost return (ret); 1312324fd7ecSKristof Provost } 1313324fd7ecSKristof Provost 1314324fd7ecSKristof Provost int 1315324fd7ecSKristof Provost pfctl_add_rule_h(struct pfctl_handle *h, const struct pfctl_rule *r, 1316324fd7ecSKristof Provost const char *anchor, const char *anchor_call, uint32_t ticket, 1317324fd7ecSKristof Provost uint32_t pool_ticket) 1318324fd7ecSKristof Provost { 1319ffbf2595SKristof Provost struct snl_writer nw; 1320ffbf2595SKristof Provost struct snl_errmsg_data e = {}; 1321ffbf2595SKristof Provost struct nlmsghdr *hdr; 1322ffbf2595SKristof Provost uint32_t seq_id; 1323ffbf2595SKristof Provost int family_id; 13240d71f9f3SKristof Provost 1325324fd7ecSKristof Provost family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 1326497ccc21SKristof Provost if (family_id == 0) 1327497ccc21SKristof Provost return (ENOTSUP); 13280d71f9f3SKristof Provost 1329324fd7ecSKristof Provost snl_init_writer(&h->ss, &nw); 1330ffbf2595SKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_ADDRULE); 1331ffbf2595SKristof Provost hdr->nlmsg_flags |= NLM_F_DUMP; 1332ffbf2595SKristof Provost snl_add_msg_attr_u32(&nw, PF_ART_TICKET, ticket); 1333ffbf2595SKristof Provost snl_add_msg_attr_u32(&nw, PF_ART_POOL_TICKET, pool_ticket); 1334ffbf2595SKristof Provost snl_add_msg_attr_string(&nw, PF_ART_ANCHOR, anchor); 1335ffbf2595SKristof Provost snl_add_msg_attr_string(&nw, PF_ART_ANCHOR_CALL, anchor_call); 13360d71f9f3SKristof Provost 1337ffbf2595SKristof Provost snl_add_msg_attr_pf_rule(&nw, PF_ART_RULE, r); 13380d71f9f3SKristof Provost 1339ffbf2595SKristof Provost if ((hdr = snl_finalize_msg(&nw)) == NULL) 1340ffbf2595SKristof Provost return (ENXIO); 1341ffbf2595SKristof Provost 1342ffbf2595SKristof Provost seq_id = hdr->nlmsg_seq; 1343ffbf2595SKristof Provost 1344324fd7ecSKristof Provost if (! snl_send_message(&h->ss, hdr)) 1345ffbf2595SKristof Provost return (ENXIO); 13466fcc8e04SKristof Provost 1347324fd7ecSKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 1348ffbf2595SKristof Provost } 13490d71f9f3SKristof Provost 1350ffbf2595SKristof Provost return (e.error); 13510d71f9f3SKristof Provost } 13520d71f9f3SKristof Provost 135344f323ecSKristof Provost #define _IN(_field) offsetof(struct genlmsghdr, _field) 135444f323ecSKristof Provost #define _OUT(_field) offsetof(struct pfctl_rules_info, _field) 135544f323ecSKristof Provost static struct snl_attr_parser ap_getrules[] = { 135644f323ecSKristof Provost { .type = PF_GR_NR, .off = _OUT(nr), .cb = snl_attr_get_uint32 }, 135744f323ecSKristof Provost { .type = PF_GR_TICKET, .off = _OUT(ticket), .cb = snl_attr_get_uint32 }, 135844f323ecSKristof Provost }; 135944f323ecSKristof Provost #undef _IN 136044f323ecSKristof Provost #undef _OUT 13617c882c69SKristof Provost SNL_DECLARE_PARSER(getrules_parser, struct genlmsghdr, snl_f_p_empty, ap_getrules); 136244f323ecSKristof Provost 13630d71f9f3SKristof Provost int 1364f1612e70SKristof Provost pfctl_get_rules_info_h(struct pfctl_handle *h, struct pfctl_rules_info *rules, uint32_t ruleset, 13658c1400b0SKristof Provost const char *path) 13668c1400b0SKristof Provost { 136744f323ecSKristof Provost struct snl_errmsg_data e = {}; 136844f323ecSKristof Provost struct nlmsghdr *hdr; 136944f323ecSKristof Provost struct snl_writer nw; 137044f323ecSKristof Provost uint32_t seq_id; 137144f323ecSKristof Provost int family_id; 13728c1400b0SKristof Provost 1373f1612e70SKristof Provost family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 137444f323ecSKristof Provost if (family_id == 0) 137544f323ecSKristof Provost return (ENOTSUP); 13768c1400b0SKristof Provost 1377f1612e70SKristof Provost snl_init_writer(&h->ss, &nw); 137844f323ecSKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_GETRULES); 137944f323ecSKristof Provost hdr->nlmsg_flags |= NLM_F_DUMP; 13808c1400b0SKristof Provost 138144f323ecSKristof Provost snl_add_msg_attr_string(&nw, PF_GR_ANCHOR, path); 138244f323ecSKristof Provost snl_add_msg_attr_u8(&nw, PF_GR_ACTION, ruleset); 13838c1400b0SKristof Provost 138444f323ecSKristof Provost hdr = snl_finalize_msg(&nw); 138544f323ecSKristof Provost if (hdr == NULL) 138644f323ecSKristof Provost return (ENOMEM); 138744f323ecSKristof Provost 138844f323ecSKristof Provost seq_id = hdr->nlmsg_seq; 1389f1612e70SKristof Provost if (! snl_send_message(&h->ss, hdr)) 139044f323ecSKristof Provost return (ENXIO); 139144f323ecSKristof Provost 1392f1612e70SKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 1393f1612e70SKristof Provost if (! snl_parse_nlmsg(&h->ss, hdr, &getrules_parser, rules)) 139444f323ecSKristof Provost continue; 139544f323ecSKristof Provost } 139644f323ecSKristof Provost 139744f323ecSKristof Provost return (e.error); 13988c1400b0SKristof Provost } 13998c1400b0SKristof Provost 14008c1400b0SKristof Provost int 1401f1612e70SKristof Provost pfctl_get_rules_info(int dev __unused, struct pfctl_rules_info *rules, uint32_t ruleset, 1402f1612e70SKristof Provost const char *path) 1403f1612e70SKristof Provost { 1404f1612e70SKristof Provost struct pfctl_handle *h; 1405f1612e70SKristof Provost int error; 1406f1612e70SKristof Provost 1407f1612e70SKristof Provost h = pfctl_open(PF_DEVICE); 1408f1612e70SKristof Provost if (h == NULL) 1409f1612e70SKristof Provost return (ENOTSUP); 1410f1612e70SKristof Provost error = pfctl_get_rules_info_h(h, rules, ruleset, path); 1411f1612e70SKristof Provost pfctl_close(h); 1412f1612e70SKristof Provost 1413f1612e70SKristof Provost return (error); 1414f1612e70SKristof Provost } 1415f1612e70SKristof Provost 1416f1612e70SKristof Provost int 1417cd2054d4SKristof Provost pfctl_get_rule_h(struct pfctl_handle *h, uint32_t nr, uint32_t ticket, const char *anchor, 1418cd2054d4SKristof Provost uint32_t ruleset, struct pfctl_rule *rule, char *anchor_call) 1419cd2054d4SKristof Provost { 1420cd2054d4SKristof Provost return (pfctl_get_clear_rule_h(h, nr, ticket, anchor, ruleset, rule, 1421cd2054d4SKristof Provost anchor_call, false)); 1422cd2054d4SKristof Provost } 1423cd2054d4SKristof Provost 1424cd2054d4SKristof Provost int 14257bb3c927SKristof Provost pfctl_get_rule(int dev, uint32_t nr, uint32_t ticket, const char *anchor, 14267bb3c927SKristof Provost uint32_t ruleset, struct pfctl_rule *rule, char *anchor_call) 14270d71f9f3SKristof Provost { 14284eabfe46SKristof Provost return (pfctl_get_clear_rule(dev, nr, ticket, anchor, ruleset, rule, 14294eabfe46SKristof Provost anchor_call, false)); 14304eabfe46SKristof Provost } 14314eabfe46SKristof Provost 1432777a4702SKristof Provost #define _OUT(_field) offsetof(struct pf_addr_wrap, _field) 1433777a4702SKristof Provost static const struct snl_attr_parser ap_addr_wrap[] = { 1434777a4702SKristof Provost { .type = PF_AT_ADDR, .off = _OUT(v.a.addr), .cb = snl_attr_get_in6_addr }, 1435777a4702SKristof Provost { .type = PF_AT_MASK, .off = _OUT(v.a.mask), .cb = snl_attr_get_in6_addr }, 1436777a4702SKristof Provost { .type = PF_AT_IFNAME, .off = _OUT(v.ifname), .arg = (void *)IFNAMSIZ,.cb = snl_attr_copy_string }, 1437777a4702SKristof Provost { .type = PF_AT_TABLENAME, .off = _OUT(v.tblname), .arg = (void *)PF_TABLE_NAME_SIZE, .cb = snl_attr_copy_string }, 1438777a4702SKristof Provost { .type = PF_AT_TYPE, .off = _OUT(type), .cb = snl_attr_get_uint8 }, 1439777a4702SKristof Provost { .type = PF_AT_IFLAGS, .off = _OUT(iflags), .cb = snl_attr_get_uint8 }, 1440777a4702SKristof Provost { .type = PF_AT_TBLCNT, .off = _OUT(p.tblcnt), .cb = snl_attr_get_uint32 }, 1441777a4702SKristof Provost { .type = PF_AT_DYNCNT, .off = _OUT(p.dyncnt), .cb = snl_attr_get_uint32 }, 1442777a4702SKristof Provost }; 1443777a4702SKristof Provost SNL_DECLARE_ATTR_PARSER(addr_wrap_parser, ap_addr_wrap); 1444777a4702SKristof Provost #undef _OUT 1445777a4702SKristof Provost 1446777a4702SKristof Provost #define _OUT(_field) offsetof(struct pf_rule_addr, _field) 1447777a4702SKristof Provost static struct snl_attr_parser ap_rule_addr[] = { 1448777a4702SKristof Provost { .type = PF_RAT_ADDR, .off = _OUT(addr), .arg = &addr_wrap_parser, .cb = snl_attr_get_nested }, 1449777a4702SKristof Provost { .type = PF_RAT_SRC_PORT, .off = _OUT(port[0]), .cb = snl_attr_get_uint16 }, 1450777a4702SKristof Provost { .type = PF_RAT_DST_PORT, .off = _OUT(port[1]), .cb = snl_attr_get_uint16 }, 1451777a4702SKristof Provost { .type = PF_RAT_NEG, .off = _OUT(neg), .cb = snl_attr_get_uint8 }, 1452777a4702SKristof Provost { .type = PF_RAT_OP, .off = _OUT(port_op), .cb = snl_attr_get_uint8 }, 1453777a4702SKristof Provost }; 1454777a4702SKristof Provost #undef _OUT 1455777a4702SKristof Provost SNL_DECLARE_ATTR_PARSER(rule_addr_parser, ap_rule_addr); 1456777a4702SKristof Provost 1457777a4702SKristof Provost struct snl_parsed_labels 1458777a4702SKristof Provost { 1459777a4702SKristof Provost char labels[PF_RULE_MAX_LABEL_COUNT][PF_RULE_LABEL_SIZE]; 1460777a4702SKristof Provost uint32_t i; 1461777a4702SKristof Provost }; 1462777a4702SKristof Provost 1463777a4702SKristof Provost static bool 1464777a4702SKristof Provost snl_attr_get_pf_rule_labels(struct snl_state *ss, struct nlattr *nla, 1465777a4702SKristof Provost const void *arg __unused, void *target) 1466777a4702SKristof Provost { 1467777a4702SKristof Provost struct snl_parsed_labels *l = (struct snl_parsed_labels *)target; 1468777a4702SKristof Provost bool ret; 1469777a4702SKristof Provost 1470777a4702SKristof Provost if (l->i >= PF_RULE_MAX_LABEL_COUNT) 1471777a4702SKristof Provost return (E2BIG); 1472777a4702SKristof Provost 1473777a4702SKristof Provost ret = snl_attr_copy_string(ss, nla, (void *)PF_RULE_LABEL_SIZE, 1474777a4702SKristof Provost l->labels[l->i]); 1475777a4702SKristof Provost if (ret) 1476777a4702SKristof Provost l->i++; 1477777a4702SKristof Provost 1478777a4702SKristof Provost return (ret); 1479777a4702SKristof Provost } 1480777a4702SKristof Provost 1481777a4702SKristof Provost #define _OUT(_field) offsetof(struct nl_parsed_labels, _field) 1482777a4702SKristof Provost static const struct snl_attr_parser ap_labels[] = { 1483777a4702SKristof Provost { .type = PF_LT_LABEL, .off = 0, .cb = snl_attr_get_pf_rule_labels }, 1484777a4702SKristof Provost }; 1485777a4702SKristof Provost SNL_DECLARE_ATTR_PARSER(rule_labels_parser, ap_labels); 1486777a4702SKristof Provost #undef _OUT 1487777a4702SKristof Provost 1488777a4702SKristof Provost static bool 1489777a4702SKristof Provost snl_attr_get_nested_pf_rule_labels(struct snl_state *ss, struct nlattr *nla, 1490777a4702SKristof Provost const void *arg __unused, void *target) 1491777a4702SKristof Provost { 1492777a4702SKristof Provost struct snl_parsed_labels parsed_labels = { }; 1493777a4702SKristof Provost bool error; 1494777a4702SKristof Provost 1495777a4702SKristof Provost /* Assumes target points to the beginning of the structure */ 1496777a4702SKristof Provost error = snl_parse_header(ss, NLA_DATA(nla), NLA_DATA_LEN(nla), &rule_labels_parser, &parsed_labels); 1497777a4702SKristof Provost if (! error) 1498777a4702SKristof Provost return (error); 1499777a4702SKristof Provost 150088f557a2SKristof Provost memcpy(target, parsed_labels.labels, sizeof(parsed_labels.labels)); 1501777a4702SKristof Provost 1502777a4702SKristof Provost return (true); 1503777a4702SKristof Provost } 1504777a4702SKristof Provost 1505777a4702SKristof Provost #define _OUT(_field) offsetof(struct pf_mape_portset, _field) 1506777a4702SKristof Provost static const struct snl_attr_parser ap_mape_portset[] = { 1507777a4702SKristof Provost { .type = PF_MET_OFFSET, .off = _OUT(offset), .cb = snl_attr_get_uint8 }, 1508777a4702SKristof Provost { .type = PF_MET_PSID_LEN, .off = _OUT(psidlen), .cb = snl_attr_get_uint8 }, 1509777a4702SKristof Provost {. type = PF_MET_PSID, .off = _OUT(psid), .cb = snl_attr_get_uint16 }, 1510777a4702SKristof Provost }; 1511777a4702SKristof Provost SNL_DECLARE_ATTR_PARSER(mape_portset_parser, ap_mape_portset); 1512777a4702SKristof Provost #undef _OUT 1513777a4702SKristof Provost 1514777a4702SKristof Provost #define _OUT(_field) offsetof(struct pfctl_pool, _field) 1515777a4702SKristof Provost static const struct snl_attr_parser ap_pool[] = { 1516777a4702SKristof Provost { .type = PF_PT_KEY, .off = _OUT(key), .arg = (void *)sizeof(struct pf_poolhashkey), .cb = snl_attr_get_bytes }, 1517777a4702SKristof Provost { .type = PF_PT_COUNTER, .off = _OUT(counter), .cb = snl_attr_get_in6_addr }, 1518777a4702SKristof Provost { .type = PF_PT_TBLIDX, .off = _OUT(tblidx), .cb = snl_attr_get_uint32 }, 1519777a4702SKristof Provost { .type = PF_PT_PROXY_SRC_PORT, .off = _OUT(proxy_port[0]), .cb = snl_attr_get_uint16 }, 1520777a4702SKristof Provost { .type = PF_PT_PROXY_DST_PORT, .off = _OUT(proxy_port[1]), .cb = snl_attr_get_uint16 }, 1521777a4702SKristof Provost { .type = PF_PT_OPTS, .off = _OUT(opts), .cb = snl_attr_get_uint8 }, 1522777a4702SKristof Provost { .type = PF_PT_MAPE, .off = _OUT(mape), .arg = &mape_portset_parser, .cb = snl_attr_get_nested }, 1523777a4702SKristof Provost }; 1524777a4702SKristof Provost SNL_DECLARE_ATTR_PARSER(pool_parser, ap_pool); 1525777a4702SKristof Provost #undef _OUT 1526777a4702SKristof Provost 1527777a4702SKristof Provost struct nl_parsed_timeouts 1528777a4702SKristof Provost { 1529777a4702SKristof Provost uint32_t timeouts[PFTM_MAX]; 1530777a4702SKristof Provost uint32_t i; 1531777a4702SKristof Provost }; 1532777a4702SKristof Provost 1533777a4702SKristof Provost static bool 1534777a4702SKristof Provost snl_attr_get_pf_timeout(struct snl_state *ss, struct nlattr *nla, 1535777a4702SKristof Provost const void *arg __unused, void *target) 1536777a4702SKristof Provost { 1537777a4702SKristof Provost struct nl_parsed_timeouts *t = (struct nl_parsed_timeouts *)target; 1538777a4702SKristof Provost bool ret; 1539777a4702SKristof Provost 1540777a4702SKristof Provost if (t->i >= PFTM_MAX) 1541777a4702SKristof Provost return (E2BIG); 1542777a4702SKristof Provost 1543777a4702SKristof Provost ret = snl_attr_get_uint32(ss, nla, NULL, &t->timeouts[t->i]); 1544777a4702SKristof Provost if (ret) 1545777a4702SKristof Provost t->i++; 1546777a4702SKristof Provost 1547777a4702SKristof Provost return (ret); 1548777a4702SKristof Provost } 1549777a4702SKristof Provost 1550777a4702SKristof Provost #define _OUT(_field) offsetof(struct nl_parsed_timeout, _field) 1551777a4702SKristof Provost static const struct snl_attr_parser ap_timeouts[] = { 1552777a4702SKristof Provost { .type = PF_TT_TIMEOUT, .off = 0, .cb = snl_attr_get_pf_timeout }, 1553777a4702SKristof Provost }; 1554777a4702SKristof Provost SNL_DECLARE_ATTR_PARSER(timeout_parser, ap_timeouts); 1555777a4702SKristof Provost #undef _OUT 1556777a4702SKristof Provost 1557777a4702SKristof Provost static bool 1558777a4702SKristof Provost snl_attr_get_nested_timeouts(struct snl_state *ss, struct nlattr *nla, 1559777a4702SKristof Provost const void *arg __unused, void *target) 1560777a4702SKristof Provost { 1561777a4702SKristof Provost struct nl_parsed_timeouts parsed_timeouts = { }; 1562777a4702SKristof Provost bool error; 1563777a4702SKristof Provost 1564777a4702SKristof Provost /* Assumes target points to the beginning of the structure */ 1565777a4702SKristof Provost error = snl_parse_header(ss, NLA_DATA(nla), NLA_DATA_LEN(nla), &timeout_parser, &parsed_timeouts); 1566777a4702SKristof Provost if (! error) 1567777a4702SKristof Provost return (error); 1568777a4702SKristof Provost 1569777a4702SKristof Provost memcpy(target, parsed_timeouts.timeouts, sizeof(parsed_timeouts.timeouts)); 1570777a4702SKristof Provost 1571777a4702SKristof Provost return (true); 1572777a4702SKristof Provost } 1573777a4702SKristof Provost 1574777a4702SKristof Provost #define _OUT(_field) offsetof(struct pf_rule_uid, _field) 1575777a4702SKristof Provost static const struct snl_attr_parser ap_rule_uid[] = { 1576777a4702SKristof Provost { .type = PF_RUT_UID_LOW, .off = _OUT(uid[0]), .cb = snl_attr_get_uint32 }, 1577777a4702SKristof Provost { .type = PF_RUT_UID_HIGH, .off = _OUT(uid[1]), .cb = snl_attr_get_uint32 }, 1578777a4702SKristof Provost { .type = PF_RUT_OP, .off = _OUT(op), .cb = snl_attr_get_uint8 }, 1579777a4702SKristof Provost }; 1580777a4702SKristof Provost SNL_DECLARE_ATTR_PARSER(rule_uid_parser, ap_rule_uid); 1581777a4702SKristof Provost #undef _OUT 1582777a4702SKristof Provost 1583777a4702SKristof Provost struct pfctl_nl_get_rule { 1584777a4702SKristof Provost struct pfctl_rule r; 1585777a4702SKristof Provost char anchor_call[MAXPATHLEN]; 1586777a4702SKristof Provost }; 1587777a4702SKristof Provost #define _OUT(_field) offsetof(struct pfctl_nl_get_rule, _field) 1588777a4702SKristof Provost static struct snl_attr_parser ap_getrule[] = { 1589777a4702SKristof Provost { .type = PF_RT_SRC, .off = _OUT(r.src), .arg = &rule_addr_parser,.cb = snl_attr_get_nested }, 1590777a4702SKristof Provost { .type = PF_RT_DST, .off = _OUT(r.dst), .arg = &rule_addr_parser,.cb = snl_attr_get_nested }, 1591777a4702SKristof Provost { .type = PF_RT_RIDENTIFIER, .off = _OUT(r.ridentifier), .cb = snl_attr_get_uint32 }, 1592777a4702SKristof Provost { .type = PF_RT_LABELS, .off = _OUT(r.label), .arg = &rule_labels_parser,.cb = snl_attr_get_nested_pf_rule_labels }, 1593777a4702SKristof Provost { .type = PF_RT_IFNAME, .off = _OUT(r.ifname), .arg = (void *)IFNAMSIZ, .cb = snl_attr_copy_string }, 1594777a4702SKristof Provost { .type = PF_RT_QNAME, .off = _OUT(r.qname), .arg = (void *)PF_QNAME_SIZE, .cb = snl_attr_copy_string }, 1595777a4702SKristof Provost { .type = PF_RT_PQNAME, .off = _OUT(r.pqname), .arg = (void *)PF_QNAME_SIZE, .cb = snl_attr_copy_string }, 1596777a4702SKristof Provost { .type = PF_RT_TAGNAME, .off = _OUT(r.tagname), .arg = (void *)PF_TAG_NAME_SIZE, .cb = snl_attr_copy_string }, 1597777a4702SKristof Provost { .type = PF_RT_MATCH_TAGNAME, .off = _OUT(r.match_tagname), .arg = (void *)PF_TAG_NAME_SIZE, .cb = snl_attr_copy_string }, 1598777a4702SKristof Provost { .type = PF_RT_OVERLOAD_TBLNAME, .off = _OUT(r.overload_tblname), .arg = (void *)PF_TABLE_NAME_SIZE, .cb = snl_attr_copy_string }, 1599e11dacbfSKristof Provost { .type = PF_RT_RPOOL_RDR, .off = _OUT(r.rdr), .arg = &pool_parser, .cb = snl_attr_get_nested }, 1600777a4702SKristof Provost { .type = PF_RT_OS_FINGERPRINT, .off = _OUT(r.os_fingerprint), .cb = snl_attr_get_uint32 }, 1601777a4702SKristof Provost { .type = PF_RT_RTABLEID, .off = _OUT(r.rtableid), .cb = snl_attr_get_uint32 }, 1602777a4702SKristof Provost { .type = PF_RT_TIMEOUT, .off = _OUT(r.timeout), .arg = &timeout_parser, .cb = snl_attr_get_nested_timeouts }, 1603777a4702SKristof Provost { .type = PF_RT_MAX_STATES, .off = _OUT(r.max_states), .cb = snl_attr_get_uint32 }, 1604777a4702SKristof Provost { .type = PF_RT_MAX_SRC_NODES, .off = _OUT(r.max_src_nodes), .cb = snl_attr_get_uint32 }, 1605777a4702SKristof Provost { .type = PF_RT_MAX_SRC_STATES, .off = _OUT(r.max_src_states), .cb = snl_attr_get_uint32 }, 1606777a4702SKristof Provost { .type = PF_RT_MAX_SRC_CONN_RATE_LIMIT, .off = _OUT(r.max_src_conn_rate.limit), .cb = snl_attr_get_uint32 }, 1607777a4702SKristof Provost { .type = PF_RT_MAX_SRC_CONN_RATE_SECS, .off = _OUT(r.max_src_conn_rate.seconds), .cb = snl_attr_get_uint32 }, 1608777a4702SKristof Provost { .type = PF_RT_DNPIPE, .off = _OUT(r.dnpipe), .cb = snl_attr_get_uint16 }, 1609777a4702SKristof Provost { .type = PF_RT_DNRPIPE, .off = _OUT(r.dnrpipe), .cb = snl_attr_get_uint16 }, 1610777a4702SKristof Provost { .type = PF_RT_DNFLAGS, .off = _OUT(r.free_flags), .cb = snl_attr_get_uint32 }, 1611777a4702SKristof Provost { .type = PF_RT_NR, .off = _OUT(r.nr), .cb = snl_attr_get_uint32 }, 1612777a4702SKristof Provost { .type = PF_RT_PROB, .off = _OUT(r.prob), .cb = snl_attr_get_uint32 }, 1613777a4702SKristof Provost { .type = PF_RT_CUID, .off = _OUT(r.cuid), .cb = snl_attr_get_uint32 }, 1614777a4702SKristof Provost {. type = PF_RT_CPID, .off = _OUT(r.cpid), .cb = snl_attr_get_uint32 }, 1615777a4702SKristof Provost { .type = PF_RT_RETURN_ICMP, .off = _OUT(r.return_icmp), .cb = snl_attr_get_uint16 }, 1616777a4702SKristof Provost { .type = PF_RT_RETURN_ICMP6, .off = _OUT(r.return_icmp6), .cb = snl_attr_get_uint16 }, 1617777a4702SKristof Provost { .type = PF_RT_MAX_MSS, .off = _OUT(r.max_mss), .cb = snl_attr_get_uint16 }, 1618777a4702SKristof Provost { .type = PF_RT_SCRUB_FLAGS, .off = _OUT(r.scrub_flags), .cb = snl_attr_get_uint16 }, 1619777a4702SKristof Provost { .type = PF_RT_UID, .off = _OUT(r.uid), .arg = &rule_uid_parser, .cb = snl_attr_get_nested }, 1620777a4702SKristof Provost { .type = PF_RT_GID, .off = _OUT(r.gid), .arg = &rule_uid_parser, .cb = snl_attr_get_nested }, 1621777a4702SKristof Provost { .type = PF_RT_RULE_FLAG, .off = _OUT(r.rule_flag), .cb = snl_attr_get_uint32 }, 1622777a4702SKristof Provost { .type = PF_RT_ACTION, .off = _OUT(r.action), .cb = snl_attr_get_uint8 }, 1623777a4702SKristof Provost { .type = PF_RT_DIRECTION, .off = _OUT(r.direction), .cb = snl_attr_get_uint8 }, 1624777a4702SKristof Provost { .type = PF_RT_LOG, .off = _OUT(r.log), .cb = snl_attr_get_uint8 }, 1625777a4702SKristof Provost { .type = PF_RT_LOGIF, .off = _OUT(r.logif), .cb = snl_attr_get_uint8 }, 1626777a4702SKristof Provost { .type = PF_RT_QUICK, .off = _OUT(r.quick), .cb = snl_attr_get_uint8 }, 1627777a4702SKristof Provost { .type = PF_RT_IF_NOT, .off = _OUT(r.ifnot), .cb = snl_attr_get_uint8 }, 1628777a4702SKristof Provost { .type = PF_RT_MATCH_TAG_NOT, .off = _OUT(r.match_tag_not), .cb = snl_attr_get_uint8 }, 1629777a4702SKristof Provost { .type = PF_RT_NATPASS, .off = _OUT(r.natpass), .cb = snl_attr_get_uint8 }, 1630777a4702SKristof Provost { .type = PF_RT_KEEP_STATE, .off = _OUT(r.keep_state), .cb = snl_attr_get_uint8 }, 1631777a4702SKristof Provost { .type = PF_RT_AF, .off = _OUT(r.af), .cb = snl_attr_get_uint8 }, 1632777a4702SKristof Provost { .type = PF_RT_PROTO, .off = _OUT(r.proto), .cb = snl_attr_get_uint8 }, 1633777a4702SKristof Provost { .type = PF_RT_TYPE, .off = _OUT(r.type), .cb = snl_attr_get_uint8 }, 1634777a4702SKristof Provost { .type = PF_RT_CODE, .off = _OUT(r.code), .cb = snl_attr_get_uint8 }, 1635777a4702SKristof Provost { .type = PF_RT_FLAGS, .off = _OUT(r.flags), .cb = snl_attr_get_uint8 }, 1636777a4702SKristof Provost { .type = PF_RT_FLAGSET, .off = _OUT(r.flagset), .cb = snl_attr_get_uint8 }, 1637777a4702SKristof Provost { .type = PF_RT_MIN_TTL, .off = _OUT(r.min_ttl), .cb = snl_attr_get_uint8 }, 1638777a4702SKristof Provost { .type = PF_RT_ALLOW_OPTS, .off = _OUT(r.allow_opts), .cb = snl_attr_get_uint8 }, 1639777a4702SKristof Provost { .type = PF_RT_RT, .off = _OUT(r.rt), .cb = snl_attr_get_uint8 }, 1640777a4702SKristof Provost { .type = PF_RT_RETURN_TTL, .off = _OUT(r.return_ttl), .cb = snl_attr_get_uint8 }, 1641777a4702SKristof Provost { .type = PF_RT_TOS, .off = _OUT(r.tos), .cb = snl_attr_get_uint8 }, 1642777a4702SKristof Provost { .type = PF_RT_SET_TOS, .off = _OUT(r.set_tos), .cb = snl_attr_get_uint8 }, 1643777a4702SKristof Provost { .type = PF_RT_ANCHOR_RELATIVE, .off = _OUT(r.anchor_relative), .cb = snl_attr_get_uint8 }, 1644777a4702SKristof Provost { .type = PF_RT_ANCHOR_WILDCARD, .off = _OUT(r.anchor_wildcard), .cb = snl_attr_get_uint8 }, 1645777a4702SKristof Provost { .type = PF_RT_FLUSH, .off = _OUT(r.flush), .cb = snl_attr_get_uint8 }, 1646777a4702SKristof Provost { .type = PF_RT_PRIO, .off = _OUT(r.prio), .cb = snl_attr_get_uint8 }, 1647777a4702SKristof Provost { .type = PF_RT_SET_PRIO, .off = _OUT(r.set_prio[0]), .cb = snl_attr_get_uint8 }, 1648777a4702SKristof Provost { .type = PF_RT_SET_PRIO_REPLY, .off = _OUT(r.set_prio[1]), .cb = snl_attr_get_uint8 }, 1649777a4702SKristof Provost { .type = PF_RT_DIVERT_ADDRESS, .off = _OUT(r.divert.addr), .cb = snl_attr_get_in6_addr }, 1650777a4702SKristof Provost { .type = PF_RT_DIVERT_PORT, .off = _OUT(r.divert.port), .cb = snl_attr_get_uint16 }, 1651777a4702SKristof Provost { .type = PF_RT_PACKETS_IN, .off = _OUT(r.packets[0]), .cb = snl_attr_get_uint64 }, 1652777a4702SKristof Provost { .type = PF_RT_PACKETS_OUT, .off = _OUT(r.packets[1]), .cb = snl_attr_get_uint64 }, 1653777a4702SKristof Provost { .type = PF_RT_BYTES_IN, .off = _OUT(r.bytes[0]), .cb = snl_attr_get_uint64 }, 1654777a4702SKristof Provost { .type = PF_RT_BYTES_OUT, .off = _OUT(r.bytes[1]), .cb = snl_attr_get_uint64 }, 1655777a4702SKristof Provost { .type = PF_RT_EVALUATIONS, .off = _OUT(r.evaluations), .cb = snl_attr_get_uint64 }, 1656777a4702SKristof Provost { .type = PF_RT_TIMESTAMP, .off = _OUT(r.last_active_timestamp), .cb = snl_attr_get_uint64 }, 1657777a4702SKristof Provost { .type = PF_RT_STATES_CUR, .off = _OUT(r.states_cur), .cb = snl_attr_get_uint64 }, 1658777a4702SKristof Provost { .type = PF_RT_STATES_TOTAL, .off = _OUT(r.states_tot), .cb = snl_attr_get_uint64 }, 1659777a4702SKristof Provost { .type = PF_RT_SRC_NODES, .off = _OUT(r.src_nodes), .cb = snl_attr_get_uint64 }, 1660777a4702SKristof Provost { .type = PF_RT_ANCHOR_CALL, .off = _OUT(anchor_call), .arg = (void*)MAXPATHLEN, .cb = snl_attr_copy_string }, 16612339ead6SKristof Provost { .type = PF_RT_RCV_IFNAME, .off = _OUT(r.rcv_ifname), .arg = (void*)IFNAMSIZ, .cb = snl_attr_copy_string }, 16627fe42038SKajetan Staszkiewicz { .type = PF_RT_MAX_SRC_CONN, .off = _OUT(r.max_src_conn), .cb = snl_attr_get_uint32 }, 1663e11dacbfSKristof Provost { .type = PF_RT_RPOOL_NAT, .off = _OUT(r.nat), .arg = &pool_parser, .cb = snl_attr_get_nested }, 1664aa69fdf1SKristof Provost { .type = PF_RT_NAF, .off = _OUT(r.naf), .cb = snl_attr_get_uint8 }, 1665*0972294eSKristof Provost { .type = PF_RT_RPOOL_RT, .off = _OUT(r.route), .arg = &pool_parser, .cb = snl_attr_get_nested }, 1666777a4702SKristof Provost }; 1667777a4702SKristof Provost #undef _OUT 16687c882c69SKristof Provost SNL_DECLARE_PARSER(getrule_parser, struct genlmsghdr, snl_f_p_empty, ap_getrule); 1669777a4702SKristof Provost 1670777a4702SKristof Provost int 1671777a4702SKristof Provost pfctl_get_clear_rule_h(struct pfctl_handle *h, uint32_t nr, uint32_t ticket, 1672777a4702SKristof Provost const char *anchor, uint32_t ruleset, struct pfctl_rule *rule, 1673777a4702SKristof Provost char *anchor_call, bool clear) 1674777a4702SKristof Provost { 1675777a4702SKristof Provost struct pfctl_nl_get_rule attrs = {}; 1676777a4702SKristof Provost struct snl_errmsg_data e = {}; 1677777a4702SKristof Provost struct nlmsghdr *hdr; 1678777a4702SKristof Provost struct snl_writer nw; 1679777a4702SKristof Provost uint32_t seq_id; 1680777a4702SKristof Provost int family_id; 1681777a4702SKristof Provost 1682777a4702SKristof Provost family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 1683777a4702SKristof Provost if (family_id == 0) 1684777a4702SKristof Provost return (ENOTSUP); 1685777a4702SKristof Provost 1686777a4702SKristof Provost snl_init_writer(&h->ss, &nw); 1687777a4702SKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_GETRULE); 1688777a4702SKristof Provost hdr->nlmsg_flags |= NLM_F_DUMP; 1689777a4702SKristof Provost 1690777a4702SKristof Provost snl_add_msg_attr_string(&nw, PF_GR_ANCHOR, anchor); 1691777a4702SKristof Provost snl_add_msg_attr_u8(&nw, PF_GR_ACTION, ruleset); 1692777a4702SKristof Provost snl_add_msg_attr_u32(&nw, PF_GR_NR, nr); 1693777a4702SKristof Provost snl_add_msg_attr_u32(&nw, PF_GR_TICKET, ticket); 1694777a4702SKristof Provost snl_add_msg_attr_u8(&nw, PF_GR_CLEAR, clear); 1695777a4702SKristof Provost 1696777a4702SKristof Provost hdr = snl_finalize_msg(&nw); 1697777a4702SKristof Provost if (hdr == NULL) 1698777a4702SKristof Provost return (ENOMEM); 1699777a4702SKristof Provost 1700777a4702SKristof Provost seq_id = hdr->nlmsg_seq; 1701777a4702SKristof Provost if (! snl_send_message(&h->ss, hdr)) 1702777a4702SKristof Provost return (ENXIO); 1703777a4702SKristof Provost 1704777a4702SKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 1705777a4702SKristof Provost if (! snl_parse_nlmsg(&h->ss, hdr, &getrule_parser, &attrs)) 1706777a4702SKristof Provost continue; 1707777a4702SKristof Provost } 1708777a4702SKristof Provost 1709777a4702SKristof Provost memcpy(rule, &attrs.r, sizeof(attrs.r)); 1710777a4702SKristof Provost strlcpy(anchor_call, attrs.anchor_call, MAXPATHLEN); 1711777a4702SKristof Provost 1712777a4702SKristof Provost return (e.error); 1713777a4702SKristof Provost } 1714777a4702SKristof Provost 1715777a4702SKristof Provost int 1716777a4702SKristof Provost pfctl_get_clear_rule(int dev, uint32_t nr, uint32_t ticket, 17177bb3c927SKristof Provost const char *anchor, uint32_t ruleset, struct pfctl_rule *rule, 17184eabfe46SKristof Provost char *anchor_call, bool clear) 17194eabfe46SKristof Provost { 17200d71f9f3SKristof Provost nvlist_t *nvl; 17210d71f9f3SKristof Provost int ret; 17220d71f9f3SKristof Provost 17230d71f9f3SKristof Provost nvl = nvlist_create(0); 17240d71f9f3SKristof Provost if (nvl == 0) 17250d71f9f3SKristof Provost return (ENOMEM); 17260d71f9f3SKristof Provost 17270d71f9f3SKristof Provost nvlist_add_number(nvl, "nr", nr); 17280d71f9f3SKristof Provost nvlist_add_number(nvl, "ticket", ticket); 17290d71f9f3SKristof Provost nvlist_add_string(nvl, "anchor", anchor); 17300d71f9f3SKristof Provost nvlist_add_number(nvl, "ruleset", ruleset); 17310d71f9f3SKristof Provost 17324eabfe46SKristof Provost if (clear) 17334eabfe46SKristof Provost nvlist_add_bool(nvl, "clear_counter", true); 17344eabfe46SKristof Provost 17357ed19f5cSKristof Provost if ((ret = pfctl_do_ioctl(dev, DIOCGETRULENV, 8192, &nvl)) != 0) 1736498934c5SKristof Provost goto out; 17370d71f9f3SKristof Provost 17380d71f9f3SKristof Provost pf_nvrule_to_rule(nvlist_get_nvlist(nvl, "rule"), rule); 17390d71f9f3SKristof Provost 17400d71f9f3SKristof Provost if (anchor_call) 17410d71f9f3SKristof Provost strlcpy(anchor_call, nvlist_get_string(nvl, "anchor_call"), 17420d71f9f3SKristof Provost MAXPATHLEN); 17430d71f9f3SKristof Provost 1744498934c5SKristof Provost out: 17450d71f9f3SKristof Provost nvlist_destroy(nvl); 1746498934c5SKristof Provost return (ret); 17470d71f9f3SKristof Provost } 174842ec75f8SKristof Provost 174942ec75f8SKristof Provost int 175042ec75f8SKristof Provost pfctl_set_keepcounters(int dev, bool keep) 175142ec75f8SKristof Provost { 175242ec75f8SKristof Provost struct pfioc_nv nv; 175342ec75f8SKristof Provost nvlist_t *nvl; 175442ec75f8SKristof Provost int ret; 175542ec75f8SKristof Provost 175642ec75f8SKristof Provost nvl = nvlist_create(0); 175742ec75f8SKristof Provost 175842ec75f8SKristof Provost nvlist_add_bool(nvl, "keep_counters", keep); 175942ec75f8SKristof Provost 176042ec75f8SKristof Provost nv.data = nvlist_pack(nvl, &nv.len); 176142ec75f8SKristof Provost nv.size = nv.len; 176242ec75f8SKristof Provost 176342ec75f8SKristof Provost nvlist_destroy(nvl); 176442ec75f8SKristof Provost 176542ec75f8SKristof Provost ret = ioctl(dev, DIOCKEEPCOUNTERS, &nv); 176642ec75f8SKristof Provost 176742ec75f8SKristof Provost free(nv.data); 176842ec75f8SKristof Provost return (ret); 176942ec75f8SKristof Provost } 177053714a58SKristof Provost 1771a7191e5dSKristof Provost struct pfctl_creator { 1772a7191e5dSKristof Provost uint32_t id; 1773a7191e5dSKristof Provost }; 1774a7191e5dSKristof Provost #define _IN(_field) offsetof(struct genlmsghdr, _field) 1775a7191e5dSKristof Provost #define _OUT(_field) offsetof(struct pfctl_creator, _field) 1776a7191e5dSKristof Provost static struct snl_attr_parser ap_creators[] = { 1777a7191e5dSKristof Provost { .type = PF_ST_CREATORID, .off = _OUT(id), .cb = snl_attr_get_uint32 }, 1778a7191e5dSKristof Provost }; 1779a7191e5dSKristof Provost #undef _IN 1780a7191e5dSKristof Provost #undef _OUT 17817c882c69SKristof Provost SNL_DECLARE_PARSER(creator_parser, struct genlmsghdr, snl_f_p_empty, ap_creators); 1782a7191e5dSKristof Provost 1783a7191e5dSKristof Provost static int 1784a7191e5dSKristof Provost pfctl_get_creators_nl(struct snl_state *ss, uint32_t *creators, size_t *len) 1785a7191e5dSKristof Provost { 1786a7191e5dSKristof Provost 1787a7191e5dSKristof Provost int family_id = snl_get_genl_family(ss, PFNL_FAMILY_NAME); 1788a7191e5dSKristof Provost size_t i = 0; 1789a7191e5dSKristof Provost 1790a7191e5dSKristof Provost struct nlmsghdr *hdr; 1791a7191e5dSKristof Provost struct snl_writer nw; 1792a7191e5dSKristof Provost 1793497ccc21SKristof Provost if (family_id == 0) 1794497ccc21SKristof Provost return (ENOTSUP); 1795497ccc21SKristof Provost 1796a7191e5dSKristof Provost snl_init_writer(ss, &nw); 1797a7191e5dSKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_GETCREATORS); 1798a7191e5dSKristof Provost hdr->nlmsg_flags |= NLM_F_DUMP; 17994f8f43b0SKristof Provost hdr = snl_finalize_msg(&nw); 18004abc3b48SKristof Provost if (hdr == NULL) 18014abc3b48SKristof Provost return (ENOMEM); 1802a7191e5dSKristof Provost uint32_t seq_id = hdr->nlmsg_seq; 1803a7191e5dSKristof Provost 1804a7191e5dSKristof Provost snl_send_message(ss, hdr); 1805a7191e5dSKristof Provost 1806a7191e5dSKristof Provost struct snl_errmsg_data e = {}; 1807a7191e5dSKristof Provost while ((hdr = snl_read_reply_multi(ss, seq_id, &e)) != NULL) { 1808a7191e5dSKristof Provost struct pfctl_creator c; 1809a7191e5dSKristof Provost bzero(&c, sizeof(c)); 1810a7191e5dSKristof Provost 1811a7191e5dSKristof Provost if (!snl_parse_nlmsg(ss, hdr, &creator_parser, &c)) 1812a7191e5dSKristof Provost continue; 1813a7191e5dSKristof Provost 1814a7191e5dSKristof Provost creators[i] = c.id; 1815a7191e5dSKristof Provost i++; 1816a7191e5dSKristof Provost if (i > *len) 1817a7191e5dSKristof Provost return (E2BIG); 1818a7191e5dSKristof Provost } 1819a7191e5dSKristof Provost 1820a7191e5dSKristof Provost *len = i; 1821a7191e5dSKristof Provost 1822a7191e5dSKristof Provost return (0); 1823a7191e5dSKristof Provost } 1824a7191e5dSKristof Provost 1825a7191e5dSKristof Provost int 182666cacc14SKristof Provost pfctl_get_creatorids(struct pfctl_handle *h, uint32_t *creators, size_t *len) 1827a7191e5dSKristof Provost { 1828a7191e5dSKristof Provost int error; 1829a7191e5dSKristof Provost 183066cacc14SKristof Provost error = pfctl_get_creators_nl(&h->ss, creators, len); 1831a7191e5dSKristof Provost 1832a7191e5dSKristof Provost return (error); 1833a7191e5dSKristof Provost } 1834a7191e5dSKristof Provost 18352cef6288SAlexander V. Chernikov static inline bool 18362cef6288SAlexander V. Chernikov snl_attr_get_pfaddr(struct snl_state *ss __unused, struct nlattr *nla, 18372cef6288SAlexander V. Chernikov const void *arg __unused, void *target) 1838bc941291SKristof Provost { 18392cef6288SAlexander V. Chernikov memcpy(target, NLA_DATA(nla), NLA_DATA_LEN(nla)); 18402cef6288SAlexander V. Chernikov return (true); 1841bc941291SKristof Provost } 1842bc941291SKristof Provost 18432cef6288SAlexander V. Chernikov static inline bool 18442cef6288SAlexander V. Chernikov snl_attr_store_ifname(struct snl_state *ss __unused, struct nlattr *nla, 18452cef6288SAlexander V. Chernikov const void *arg __unused, void *target) 1846bc941291SKristof Provost { 18472cef6288SAlexander V. Chernikov size_t maxlen = NLA_DATA_LEN(nla); 18482cef6288SAlexander V. Chernikov 18492cef6288SAlexander V. Chernikov if (strnlen((char *)NLA_DATA(nla), maxlen) < maxlen) { 18502cef6288SAlexander V. Chernikov strlcpy(target, (char *)NLA_DATA(nla), maxlen); 18512cef6288SAlexander V. Chernikov return (true); 18522cef6288SAlexander V. Chernikov } 18532cef6288SAlexander V. Chernikov return (false); 1854bc941291SKristof Provost } 1855bc941291SKristof Provost 18562cef6288SAlexander V. Chernikov #define _OUT(_field) offsetof(struct pfctl_state_peer, _field) 18572cef6288SAlexander V. Chernikov static const struct snl_attr_parser nla_p_speer[] = { 18582cef6288SAlexander V. Chernikov { .type = PF_STP_SEQLO, .off = _OUT(seqlo), .cb = snl_attr_get_uint32 }, 18592cef6288SAlexander V. Chernikov { .type = PF_STP_SEQHI, .off = _OUT(seqhi), .cb = snl_attr_get_uint32 }, 18602cef6288SAlexander V. Chernikov { .type = PF_STP_SEQDIFF, .off = _OUT(seqdiff), .cb = snl_attr_get_uint32 }, 18612cef6288SAlexander V. Chernikov { .type = PF_STP_STATE, .off = _OUT(state), .cb = snl_attr_get_uint8 }, 18622cef6288SAlexander V. Chernikov { .type = PF_STP_WSCALE, .off = _OUT(wscale), .cb = snl_attr_get_uint8 }, 18632cef6288SAlexander V. Chernikov }; 18642cef6288SAlexander V. Chernikov SNL_DECLARE_ATTR_PARSER(speer_parser, nla_p_speer); 18652cef6288SAlexander V. Chernikov #undef _OUT 18662cef6288SAlexander V. Chernikov 1867ebe11b46SKristof Provost #define _OUT(_field) offsetof(struct pfctl_state_key, _field) 18682cef6288SAlexander V. Chernikov static const struct snl_attr_parser nla_p_skey[] = { 18692cef6288SAlexander V. Chernikov { .type = PF_STK_ADDR0, .off = _OUT(addr[0]), .cb = snl_attr_get_pfaddr }, 18702cef6288SAlexander V. Chernikov { .type = PF_STK_ADDR1, .off = _OUT(addr[1]), .cb = snl_attr_get_pfaddr }, 18712cef6288SAlexander V. Chernikov { .type = PF_STK_PORT0, .off = _OUT(port[0]), .cb = snl_attr_get_uint16 }, 18722cef6288SAlexander V. Chernikov { .type = PF_STK_PORT1, .off = _OUT(port[1]), .cb = snl_attr_get_uint16 }, 1873ebe11b46SKristof Provost { .type = PF_STK_AF, .off = _OUT(af), .cb = snl_attr_get_uint8 }, 1874ebe11b46SKristof Provost { .type = PF_STK_PROTO, .off = _OUT(proto), .cb = snl_attr_get_uint16 }, 18752cef6288SAlexander V. Chernikov }; 18762cef6288SAlexander V. Chernikov SNL_DECLARE_ATTR_PARSER(skey_parser, nla_p_skey); 18772cef6288SAlexander V. Chernikov #undef _OUT 18782cef6288SAlexander V. Chernikov 18792cef6288SAlexander V. Chernikov #define _IN(_field) offsetof(struct genlmsghdr, _field) 18802cef6288SAlexander V. Chernikov #define _OUT(_field) offsetof(struct pfctl_state, _field) 18812cef6288SAlexander V. Chernikov static struct snl_attr_parser ap_state[] = { 18822cef6288SAlexander V. Chernikov { .type = PF_ST_ID, .off = _OUT(id), .cb = snl_attr_get_uint64 }, 18832cef6288SAlexander V. Chernikov { .type = PF_ST_CREATORID, .off = _OUT(creatorid), .cb = snl_attr_get_uint32 }, 18842cef6288SAlexander V. Chernikov { .type = PF_ST_IFNAME, .off = _OUT(ifname), .cb = snl_attr_store_ifname }, 18852cef6288SAlexander V. Chernikov { .type = PF_ST_ORIG_IFNAME, .off = _OUT(orig_ifname), .cb = snl_attr_store_ifname }, 18862cef6288SAlexander V. Chernikov { .type = PF_ST_KEY_WIRE, .off = _OUT(key[0]), .arg = &skey_parser, .cb = snl_attr_get_nested }, 18872cef6288SAlexander V. Chernikov { .type = PF_ST_KEY_STACK, .off = _OUT(key[1]), .arg = &skey_parser, .cb = snl_attr_get_nested }, 18882cef6288SAlexander V. Chernikov { .type = PF_ST_PEER_SRC, .off = _OUT(src), .arg = &speer_parser, .cb = snl_attr_get_nested }, 18892cef6288SAlexander V. Chernikov { .type = PF_ST_PEER_DST, .off = _OUT(dst), .arg = &speer_parser, .cb = snl_attr_get_nested }, 18902cef6288SAlexander V. Chernikov { .type = PF_ST_RT_ADDR, .off = _OUT(rt_addr), .cb = snl_attr_get_pfaddr }, 18912cef6288SAlexander V. Chernikov { .type = PF_ST_RULE, .off = _OUT(rule), .cb = snl_attr_get_uint32 }, 18922cef6288SAlexander V. Chernikov { .type = PF_ST_ANCHOR, .off = _OUT(anchor), .cb = snl_attr_get_uint32 }, 18932cef6288SAlexander V. Chernikov { .type = PF_ST_NAT_RULE, .off = _OUT(nat_rule), .cb = snl_attr_get_uint32 }, 18942cef6288SAlexander V. Chernikov { .type = PF_ST_CREATION, .off = _OUT(creation), .cb = snl_attr_get_uint32 }, 18952cef6288SAlexander V. Chernikov { .type = PF_ST_EXPIRE, .off = _OUT(expire), .cb = snl_attr_get_uint32 }, 18962cef6288SAlexander V. Chernikov { .type = PF_ST_PACKETS0, .off = _OUT(packets[0]), .cb = snl_attr_get_uint64 }, 18972cef6288SAlexander V. Chernikov { .type = PF_ST_PACKETS1, .off = _OUT(packets[1]), .cb = snl_attr_get_uint64 }, 18982cef6288SAlexander V. Chernikov { .type = PF_ST_BYTES0, .off = _OUT(bytes[0]), .cb = snl_attr_get_uint64 }, 18992cef6288SAlexander V. Chernikov { .type = PF_ST_BYTES1, .off = _OUT(bytes[1]), .cb = snl_attr_get_uint64 }, 19002cef6288SAlexander V. Chernikov { .type = PF_ST_DIRECTION, .off = _OUT(direction), .cb = snl_attr_get_uint8 }, 19012cef6288SAlexander V. Chernikov { .type = PF_ST_LOG, .off = _OUT(log), .cb = snl_attr_get_uint8 }, 19022cef6288SAlexander V. Chernikov { .type = PF_ST_STATE_FLAGS, .off = _OUT(state_flags), .cb = snl_attr_get_uint16 }, 19032cef6288SAlexander V. Chernikov { .type = PF_ST_SYNC_FLAGS, .off = _OUT(sync_flags), .cb = snl_attr_get_uint8 }, 1904881bf881SKristof Provost { .type = PF_ST_RTABLEID, .off = _OUT(rtableid), .cb = snl_attr_get_int32 }, 1905881bf881SKristof Provost { .type = PF_ST_MIN_TTL, .off = _OUT(min_ttl), .cb = snl_attr_get_uint8 }, 1906881bf881SKristof Provost { .type = PF_ST_MAX_MSS, .off = _OUT(max_mss), .cb = snl_attr_get_uint16 }, 1907881bf881SKristof Provost { .type = PF_ST_DNPIPE, .off = _OUT(dnpipe), .cb = snl_attr_get_uint16 }, 1908881bf881SKristof Provost { .type = PF_ST_DNRPIPE, .off = _OUT(dnrpipe), .cb = snl_attr_get_uint16 }, 1909881bf881SKristof Provost { .type = PF_ST_RT, .off = _OUT(rt), .cb = snl_attr_get_uint8 }, 1910881bf881SKristof Provost { .type = PF_ST_RT_IFNAME, .off = _OUT(rt_ifname), .cb = snl_attr_store_ifname }, 19112cef6288SAlexander V. Chernikov }; 19122cef6288SAlexander V. Chernikov #undef _IN 19132cef6288SAlexander V. Chernikov #undef _OUT 19147c882c69SKristof Provost SNL_DECLARE_PARSER(state_parser, struct genlmsghdr, snl_f_p_empty, ap_state); 19152cef6288SAlexander V. Chernikov 19162cef6288SAlexander V. Chernikov static const struct snl_hdr_parser *all_parsers[] = { 1917a7191e5dSKristof Provost &state_parser, &skey_parser, &speer_parser, 191844f323ecSKristof Provost &creator_parser, &getrules_parser 19192cef6288SAlexander V. Chernikov }; 19202cef6288SAlexander V. Chernikov 19212cef6288SAlexander V. Chernikov static int 1922044eef6aSKristof Provost pfctl_get_states_nl(struct pfctl_state_filter *filter, struct snl_state *ss, pfctl_get_state_fn f, void *arg) 1923bc941291SKristof Provost { 19242cef6288SAlexander V. Chernikov SNL_VERIFY_PARSERS(all_parsers); 19252cef6288SAlexander V. Chernikov int family_id = snl_get_genl_family(ss, PFNL_FAMILY_NAME); 1926f218b851SKristof Provost int ret; 1927bc941291SKristof Provost 19282cef6288SAlexander V. Chernikov struct nlmsghdr *hdr; 19292cef6288SAlexander V. Chernikov struct snl_writer nw; 1930bc941291SKristof Provost 1931497ccc21SKristof Provost if (family_id == 0) 1932497ccc21SKristof Provost return (ENOTSUP); 1933497ccc21SKristof Provost 19342cef6288SAlexander V. Chernikov snl_init_writer(ss, &nw); 19352cef6288SAlexander V. Chernikov hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_GETSTATES); 19362cef6288SAlexander V. Chernikov hdr->nlmsg_flags |= NLM_F_DUMP; 1937044eef6aSKristof Provost snl_add_msg_attr_string(&nw, PF_ST_IFNAME, filter->ifname); 1938044eef6aSKristof Provost snl_add_msg_attr_u16(&nw, PF_ST_PROTO, filter->proto); 1939044eef6aSKristof Provost snl_add_msg_attr_u8(&nw, PF_ST_AF, filter->af); 1940044eef6aSKristof Provost snl_add_msg_attr_ip6(&nw, PF_ST_FILTER_ADDR, &filter->addr.v6); 1941044eef6aSKristof Provost snl_add_msg_attr_ip6(&nw, PF_ST_FILTER_MASK, &filter->mask.v6); 1942044eef6aSKristof Provost 19434f8f43b0SKristof Provost hdr = snl_finalize_msg(&nw); 19444abc3b48SKristof Provost if (hdr == NULL) 19454abc3b48SKristof Provost return (ENOMEM); 1946044eef6aSKristof Provost 19472cef6288SAlexander V. Chernikov uint32_t seq_id = hdr->nlmsg_seq; 1948be70c7a5SKristof Provost 19492cef6288SAlexander V. Chernikov snl_send_message(ss, hdr); 1950bc941291SKristof Provost 19512cef6288SAlexander V. Chernikov struct snl_errmsg_data e = {}; 19522cef6288SAlexander V. Chernikov while ((hdr = snl_read_reply_multi(ss, seq_id, &e)) != NULL) { 1953f218b851SKristof Provost struct pfctl_state s; 1954f218b851SKristof Provost bzero(&s, sizeof(s)); 1955f218b851SKristof Provost if (!snl_parse_nlmsg(ss, hdr, &state_parser, &s)) 19562cef6288SAlexander V. Chernikov continue; 1957bc941291SKristof Provost 1958f218b851SKristof Provost ret = f(&s, arg); 1959f218b851SKristof Provost if (ret != 0) 1960f218b851SKristof Provost return (ret); 1961f218b851SKristof Provost } 1962f218b851SKristof Provost 1963f218b851SKristof Provost return (0); 1964f218b851SKristof Provost } 1965f218b851SKristof Provost 1966f218b851SKristof Provost int 1967f218b851SKristof Provost pfctl_get_states_iter(pfctl_get_state_fn f, void *arg) 1968f218b851SKristof Provost { 1969044eef6aSKristof Provost struct pfctl_state_filter filter = {}; 1970044eef6aSKristof Provost return (pfctl_get_filtered_states_iter(&filter, f, arg)); 1971044eef6aSKristof Provost } 1972044eef6aSKristof Provost 1973044eef6aSKristof Provost int 1974044eef6aSKristof Provost pfctl_get_filtered_states_iter(struct pfctl_state_filter *filter, pfctl_get_state_fn f, void *arg) 1975044eef6aSKristof Provost { 1976f218b851SKristof Provost struct snl_state ss = {}; 1977f218b851SKristof Provost int error; 1978f218b851SKristof Provost 1979f218b851SKristof Provost snl_init(&ss, NETLINK_GENERIC); 1980044eef6aSKristof Provost error = pfctl_get_states_nl(filter, &ss, f, arg); 1981f218b851SKristof Provost snl_free(&ss); 1982f218b851SKristof Provost 1983f218b851SKristof Provost return (error); 1984f218b851SKristof Provost } 1985f218b851SKristof Provost 1986f218b851SKristof Provost static int 1987f218b851SKristof Provost pfctl_append_states(struct pfctl_state *s, void *arg) 1988f218b851SKristof Provost { 1989f218b851SKristof Provost struct pfctl_state *new; 1990f218b851SKristof Provost struct pfctl_states *states = (struct pfctl_states *)arg; 1991f218b851SKristof Provost 1992f218b851SKristof Provost new = malloc(sizeof(*s)); 1993f218b851SKristof Provost if (new == NULL) 1994f218b851SKristof Provost return (ENOMEM); 1995f218b851SKristof Provost 1996f218b851SKristof Provost memcpy(new, s, sizeof(*s)); 19972cef6288SAlexander V. Chernikov 19984abc3b48SKristof Provost TAILQ_INSERT_TAIL(&states->states, new, entry); 1999bc941291SKristof Provost 20002cef6288SAlexander V. Chernikov return (0); 20012cef6288SAlexander V. Chernikov } 20022cef6288SAlexander V. Chernikov 20032cef6288SAlexander V. Chernikov int 20042cef6288SAlexander V. Chernikov pfctl_get_states(int dev __unused, struct pfctl_states *states) 20052cef6288SAlexander V. Chernikov { 2006f218b851SKristof Provost int ret; 20072cef6288SAlexander V. Chernikov 2008f218b851SKristof Provost bzero(states, sizeof(*states)); 2009f218b851SKristof Provost TAILQ_INIT(&states->states); 20102cef6288SAlexander V. Chernikov 2011f218b851SKristof Provost ret = pfctl_get_states_iter(pfctl_append_states, states); 2012f218b851SKristof Provost if (ret != 0) { 2013f218b851SKristof Provost pfctl_free_states(states); 2014f218b851SKristof Provost return (ret); 2015f218b851SKristof Provost } 2016f218b851SKristof Provost 2017f218b851SKristof Provost return (0); 2018bc941291SKristof Provost } 2019bc941291SKristof Provost 2020bc941291SKristof Provost void 2021bc941291SKristof Provost pfctl_free_states(struct pfctl_states *states) 2022bc941291SKristof Provost { 2023bc941291SKristof Provost struct pfctl_state *s, *tmp; 2024bc941291SKristof Provost 2025bc941291SKristof Provost TAILQ_FOREACH_SAFE(s, &states->states, entry, tmp) { 2026bc941291SKristof Provost free(s); 2027bc941291SKristof Provost } 2028bc941291SKristof Provost 2029bc941291SKristof Provost bzero(states, sizeof(*states)); 2030bc941291SKristof Provost } 2031bc941291SKristof Provost 2032706d465dSKristof Provost struct pfctl_nl_clear_states { 2033706d465dSKristof Provost uint32_t killed; 2034706d465dSKristof Provost }; 2035706d465dSKristof Provost #define _OUT(_field) offsetof(struct pfctl_nl_clear_states, _field) 2036706d465dSKristof Provost static struct snl_attr_parser ap_clear_states[] = { 2037706d465dSKristof Provost { .type = PF_CS_KILLED, .off = _OUT(killed), .cb = snl_attr_get_uint32 }, 2038706d465dSKristof Provost }; 2039706d465dSKristof Provost #undef _OUT 20407c882c69SKristof Provost SNL_DECLARE_PARSER(clear_states_parser, struct genlmsghdr, snl_f_p_empty, ap_clear_states); 2041706d465dSKristof Provost 20422a00c4dbSKristof Provost static int 2043706d465dSKristof Provost _pfctl_clear_states_h(struct pfctl_handle *h, const struct pfctl_kill *kill, 2044706d465dSKristof Provost unsigned int *killed, int cmd) 204553714a58SKristof Provost { 2046706d465dSKristof Provost struct snl_writer nw; 2047706d465dSKristof Provost struct snl_errmsg_data e = {}; 2048706d465dSKristof Provost struct pfctl_nl_clear_states attrs = {}; 2049706d465dSKristof Provost struct nlmsghdr *hdr; 2050706d465dSKristof Provost uint32_t seq_id; 2051706d465dSKristof Provost int family_id; 205253714a58SKristof Provost 2053706d465dSKristof Provost family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 2054706d465dSKristof Provost if (family_id == 0) 2055706d465dSKristof Provost return (ENOTSUP); 205653714a58SKristof Provost 2057706d465dSKristof Provost snl_init_writer(&h->ss, &nw); 2058706d465dSKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, cmd); 2059706d465dSKristof Provost hdr->nlmsg_flags |= NLM_F_DUMP; 206053714a58SKristof Provost 2061706d465dSKristof Provost snl_add_msg_attr_u64(&nw, PF_CS_CMP_ID, kill->cmp.id); 2062706d465dSKristof Provost snl_add_msg_attr_u32(&nw, PF_CS_CMP_CREATORID, htonl(kill->cmp.creatorid)); 2063706d465dSKristof Provost snl_add_msg_attr_u8(&nw, PF_CS_CMP_DIR, kill->cmp.direction); 2064706d465dSKristof Provost snl_add_msg_attr_u8(&nw, PF_CS_AF, kill->af); 2065706d465dSKristof Provost snl_add_msg_attr_u8(&nw, PF_CS_PROTO, kill->proto); 2066706d465dSKristof Provost snl_add_msg_attr_rule_addr(&nw, PF_CS_SRC, &kill->src); 2067706d465dSKristof Provost snl_add_msg_attr_rule_addr(&nw, PF_CS_DST, &kill->dst); 2068706d465dSKristof Provost snl_add_msg_attr_rule_addr(&nw, PF_CS_RT_ADDR, &kill->rt_addr); 2069706d465dSKristof Provost snl_add_msg_attr_string(&nw, PF_CS_IFNAME, kill->ifname); 2070706d465dSKristof Provost snl_add_msg_attr_string(&nw, PF_CS_LABEL, kill->label); 2071706d465dSKristof Provost snl_add_msg_attr_bool(&nw, PF_CS_KILL_MATCH, kill->kill_match); 2072706d465dSKristof Provost snl_add_msg_attr_bool(&nw, PF_CS_NAT, kill->nat); 2073706d465dSKristof Provost 2074706d465dSKristof Provost if ((hdr = snl_finalize_msg(&nw)) == NULL) 2075706d465dSKristof Provost return (ENXIO); 2076706d465dSKristof Provost 2077706d465dSKristof Provost seq_id = hdr->nlmsg_seq; 2078706d465dSKristof Provost 2079706d465dSKristof Provost if (! snl_send_message(&h->ss, hdr)) 2080706d465dSKristof Provost return (ENXIO); 2081706d465dSKristof Provost 2082706d465dSKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 2083706d465dSKristof Provost if (! snl_parse_nlmsg(&h->ss, hdr, &clear_states_parser, &attrs)) 2084706d465dSKristof Provost continue; 2085706d465dSKristof Provost } 208653714a58SKristof Provost 208753714a58SKristof Provost if (killed) 2088706d465dSKristof Provost *killed = attrs.killed; 208953714a58SKristof Provost 2090706d465dSKristof Provost return (e.error); 2091706d465dSKristof Provost } 2092706d465dSKristof Provost 2093706d465dSKristof Provost int 2094706d465dSKristof Provost pfctl_clear_states_h(struct pfctl_handle *h, const struct pfctl_kill *kill, 2095706d465dSKristof Provost unsigned int *killed) 2096706d465dSKristof Provost { 2097706d465dSKristof Provost return(_pfctl_clear_states_h(h, kill, killed, PFNL_CMD_CLRSTATES)); 2098706d465dSKristof Provost } 2099706d465dSKristof Provost 2100706d465dSKristof Provost int 2101706d465dSKristof Provost pfctl_kill_states_h(struct pfctl_handle *h, const struct pfctl_kill *kill, 2102706d465dSKristof Provost unsigned int *killed) 2103706d465dSKristof Provost { 2104706d465dSKristof Provost return(_pfctl_clear_states_h(h, kill, killed, PFNL_CMD_KILLSTATES)); 2105706d465dSKristof Provost } 2106706d465dSKristof Provost 2107706d465dSKristof Provost static int 2108706d465dSKristof Provost _pfctl_clear_states(int dev __unused, const struct pfctl_kill *kill, 2109706d465dSKristof Provost unsigned int *killed, uint64_t cmd) 2110706d465dSKristof Provost { 2111706d465dSKristof Provost struct pfctl_handle *h; 2112706d465dSKristof Provost int ret; 2113706d465dSKristof Provost 2114706d465dSKristof Provost h = pfctl_open(PF_DEVICE); 2115706d465dSKristof Provost if (h == NULL) 2116706d465dSKristof Provost return (ENODEV); 2117706d465dSKristof Provost 2118706d465dSKristof Provost ret = _pfctl_clear_states_h(h, kill, killed, cmd); 2119706d465dSKristof Provost pfctl_close(h); 2120706d465dSKristof Provost 212153714a58SKristof Provost return (ret); 212253714a58SKristof Provost } 21232a00c4dbSKristof Provost 21242a00c4dbSKristof Provost int 2125706d465dSKristof Provost pfctl_clear_states(int dev __unused, const struct pfctl_kill *kill, 21262a00c4dbSKristof Provost unsigned int *killed) 21272a00c4dbSKristof Provost { 2128706d465dSKristof Provost return (_pfctl_clear_states(dev, kill, killed, PFNL_CMD_CLRSTATES)); 21292a00c4dbSKristof Provost } 21302a00c4dbSKristof Provost 21312a00c4dbSKristof Provost int 2132706d465dSKristof Provost pfctl_kill_states(int dev __unused, const struct pfctl_kill *kill, unsigned int *killed) 21332a00c4dbSKristof Provost { 2134706d465dSKristof Provost return (_pfctl_clear_states(dev, kill, killed, PFNL_CMD_KILLSTATES)); 21352a00c4dbSKristof Provost } 2136c69121c4SKristof Provost 2137f0c334e4SKristof Provost int 2138f0c334e4SKristof Provost pfctl_clear_rules(int dev, const char *anchorname) 2139f0c334e4SKristof Provost { 2140f0c334e4SKristof Provost struct pfioc_trans trans; 2141f0c334e4SKristof Provost struct pfioc_trans_e transe[2]; 2142f0c334e4SKristof Provost int ret; 2143f0c334e4SKristof Provost 2144f0c334e4SKristof Provost bzero(&trans, sizeof(trans)); 2145f0c334e4SKristof Provost bzero(&transe, sizeof(transe)); 2146f0c334e4SKristof Provost 2147f0c334e4SKristof Provost transe[0].rs_num = PF_RULESET_SCRUB; 2148f0c334e4SKristof Provost if (strlcpy(transe[0].anchor, anchorname, sizeof(transe[0].anchor)) 2149f0c334e4SKristof Provost >= sizeof(transe[0].anchor)) 2150f0c334e4SKristof Provost return (E2BIG); 2151f0c334e4SKristof Provost 2152f0c334e4SKristof Provost transe[1].rs_num = PF_RULESET_FILTER; 2153f0c334e4SKristof Provost if (strlcpy(transe[1].anchor, anchorname, sizeof(transe[1].anchor)) 2154f0c334e4SKristof Provost >= sizeof(transe[1].anchor)) 2155f0c334e4SKristof Provost return (E2BIG); 2156f0c334e4SKristof Provost 2157f0c334e4SKristof Provost trans.size = 2; 2158f0c334e4SKristof Provost trans.esize = sizeof(transe[0]); 2159f0c334e4SKristof Provost trans.array = transe; 2160f0c334e4SKristof Provost 2161f0c334e4SKristof Provost ret = ioctl(dev, DIOCXBEGIN, &trans); 2162f0c334e4SKristof Provost if (ret != 0) 216393e96359SKristof Provost return (errno); 216493e96359SKristof Provost ret = ioctl(dev, DIOCXCOMMIT, &trans); 216593e96359SKristof Provost if (ret != 0) 216693e96359SKristof Provost return (errno); 216793e96359SKristof Provost 216893e96359SKristof Provost return (0); 2169f0c334e4SKristof Provost } 2170f0c334e4SKristof Provost 2171f0c334e4SKristof Provost int 2172f0c334e4SKristof Provost pfctl_clear_nat(int dev, const char *anchorname) 2173f0c334e4SKristof Provost { 2174f0c334e4SKristof Provost struct pfioc_trans trans; 2175f0c334e4SKristof Provost struct pfioc_trans_e transe[3]; 2176f0c334e4SKristof Provost int ret; 2177f0c334e4SKristof Provost 2178f0c334e4SKristof Provost bzero(&trans, sizeof(trans)); 2179f0c334e4SKristof Provost bzero(&transe, sizeof(transe)); 2180f0c334e4SKristof Provost 2181f0c334e4SKristof Provost transe[0].rs_num = PF_RULESET_NAT; 2182f0c334e4SKristof Provost if (strlcpy(transe[0].anchor, anchorname, sizeof(transe[0].anchor)) 2183f0c334e4SKristof Provost >= sizeof(transe[0].anchor)) 2184f0c334e4SKristof Provost return (E2BIG); 2185f0c334e4SKristof Provost 2186f0c334e4SKristof Provost transe[1].rs_num = PF_RULESET_BINAT; 2187f0c334e4SKristof Provost if (strlcpy(transe[1].anchor, anchorname, sizeof(transe[1].anchor)) 2188f0c334e4SKristof Provost >= sizeof(transe[0].anchor)) 2189f0c334e4SKristof Provost return (E2BIG); 2190f0c334e4SKristof Provost 2191f0c334e4SKristof Provost transe[2].rs_num = PF_RULESET_RDR; 2192f0c334e4SKristof Provost if (strlcpy(transe[2].anchor, anchorname, sizeof(transe[2].anchor)) 2193f0c334e4SKristof Provost >= sizeof(transe[2].anchor)) 2194f0c334e4SKristof Provost return (E2BIG); 2195f0c334e4SKristof Provost 2196f0c334e4SKristof Provost trans.size = 3; 2197f0c334e4SKristof Provost trans.esize = sizeof(transe[0]); 2198f0c334e4SKristof Provost trans.array = transe; 2199f0c334e4SKristof Provost 2200f0c334e4SKristof Provost ret = ioctl(dev, DIOCXBEGIN, &trans); 2201f0c334e4SKristof Provost if (ret != 0) 220293e96359SKristof Provost return (errno); 220393e96359SKristof Provost ret = ioctl(dev, DIOCXCOMMIT, &trans); 220493e96359SKristof Provost if (ret != 0) 220593e96359SKristof Provost return (errno); 220693e96359SKristof Provost 220793e96359SKristof Provost return (0); 2208f0c334e4SKristof Provost } 220993e96359SKristof Provost 2210f0c334e4SKristof Provost int 2211f0c334e4SKristof Provost pfctl_clear_eth_rules(int dev, const char *anchorname) 2212f0c334e4SKristof Provost { 2213f0c334e4SKristof Provost struct pfioc_trans trans; 2214f0c334e4SKristof Provost struct pfioc_trans_e transe; 2215f0c334e4SKristof Provost int ret; 2216f0c334e4SKristof Provost 2217f0c334e4SKristof Provost bzero(&trans, sizeof(trans)); 2218f0c334e4SKristof Provost bzero(&transe, sizeof(transe)); 2219f0c334e4SKristof Provost 2220f0c334e4SKristof Provost transe.rs_num = PF_RULESET_ETH; 2221f0c334e4SKristof Provost if (strlcpy(transe.anchor, anchorname, sizeof(transe.anchor)) 2222f0c334e4SKristof Provost >= sizeof(transe.anchor)) 2223f0c334e4SKristof Provost return (E2BIG); 2224f0c334e4SKristof Provost 2225f0c334e4SKristof Provost trans.size = 1; 2226f0c334e4SKristof Provost trans.esize = sizeof(transe); 2227f0c334e4SKristof Provost trans.array = &transe; 2228f0c334e4SKristof Provost 2229f0c334e4SKristof Provost ret = ioctl(dev, DIOCXBEGIN, &trans); 2230f0c334e4SKristof Provost if (ret != 0) 223193e96359SKristof Provost return (errno); 223293e96359SKristof Provost ret = ioctl(dev, DIOCXCOMMIT, &trans); 223393e96359SKristof Provost if (ret != 0) 223493e96359SKristof Provost return (errno); 223593e96359SKristof Provost 223693e96359SKristof Provost return (0); 2237f0c334e4SKristof Provost } 2238f0c334e4SKristof Provost 22395062afffSKristof Provost static int 2240d9ab8999SKristof Provost _pfctl_get_limit(int dev, const int index, uint *limit) 22415062afffSKristof Provost { 22425062afffSKristof Provost struct pfioc_limit pl; 22435062afffSKristof Provost 22445062afffSKristof Provost bzero(&pl, sizeof(pl)); 22455062afffSKristof Provost pl.index = index; 22465062afffSKristof Provost 22475062afffSKristof Provost if (ioctl(dev, DIOCGETLIMIT, &pl) == -1) 22485062afffSKristof Provost return (errno); 22495062afffSKristof Provost 22505062afffSKristof Provost *limit = pl.limit; 22515062afffSKristof Provost 22525062afffSKristof Provost return (0); 22535062afffSKristof Provost } 22545062afffSKristof Provost 2255c69121c4SKristof Provost int 2256c69121c4SKristof Provost pfctl_set_syncookies(int dev, const struct pfctl_syncookies *s) 2257c69121c4SKristof Provost { 2258c69121c4SKristof Provost struct pfioc_nv nv; 2259c69121c4SKristof Provost nvlist_t *nvl; 2260c69121c4SKristof Provost int ret; 22617bb3c927SKristof Provost uint state_limit; 22626049ee60SKristof Provost uint64_t lim, hi, lo; 22635062afffSKristof Provost 2264d9ab8999SKristof Provost ret = _pfctl_get_limit(dev, PF_LIMIT_STATES, &state_limit); 22655062afffSKristof Provost if (ret != 0) 22665062afffSKristof Provost return (ret); 2267c69121c4SKristof Provost 22686049ee60SKristof Provost lim = state_limit; 22696049ee60SKristof Provost hi = lim * s->highwater / 100; 22706049ee60SKristof Provost lo = lim * s->lowwater / 100; 22716049ee60SKristof Provost 22726049ee60SKristof Provost if (lo == hi) 22736049ee60SKristof Provost hi++; 22746049ee60SKristof Provost 2275c69121c4SKristof Provost nvl = nvlist_create(0); 2276c69121c4SKristof Provost 2277c69121c4SKristof Provost nvlist_add_bool(nvl, "enabled", s->mode != PFCTL_SYNCOOKIES_NEVER); 22785062afffSKristof Provost nvlist_add_bool(nvl, "adaptive", s->mode == PFCTL_SYNCOOKIES_ADAPTIVE); 22796049ee60SKristof Provost nvlist_add_number(nvl, "highwater", hi); 22806049ee60SKristof Provost nvlist_add_number(nvl, "lowwater", lo); 2281c69121c4SKristof Provost 2282c69121c4SKristof Provost nv.data = nvlist_pack(nvl, &nv.len); 2283c69121c4SKristof Provost nv.size = nv.len; 2284c69121c4SKristof Provost nvlist_destroy(nvl); 2285c69121c4SKristof Provost nvl = NULL; 2286c69121c4SKristof Provost 2287c69121c4SKristof Provost ret = ioctl(dev, DIOCSETSYNCOOKIES, &nv); 2288c69121c4SKristof Provost 2289c69121c4SKristof Provost free(nv.data); 229093e96359SKristof Provost if (ret != 0) 229193e96359SKristof Provost return (errno); 229293e96359SKristof Provost 229393e96359SKristof Provost return (0); 2294c69121c4SKristof Provost } 2295c69121c4SKristof Provost 2296c69121c4SKristof Provost int 2297c69121c4SKristof Provost pfctl_get_syncookies(int dev, struct pfctl_syncookies *s) 2298c69121c4SKristof Provost { 2299c69121c4SKristof Provost nvlist_t *nvl; 23005062afffSKristof Provost int ret; 23017bb3c927SKristof Provost uint state_limit; 2302c69121c4SKristof Provost bool enabled, adaptive; 2303c69121c4SKristof Provost 2304d9ab8999SKristof Provost ret = _pfctl_get_limit(dev, PF_LIMIT_STATES, &state_limit); 23055062afffSKristof Provost if (ret != 0) 23065062afffSKristof Provost return (ret); 23075062afffSKristof Provost 2308c69121c4SKristof Provost bzero(s, sizeof(*s)); 2309c69121c4SKristof Provost 23107ed19f5cSKristof Provost nvl = nvlist_create(0); 2311c69121c4SKristof Provost 2312498934c5SKristof Provost if ((ret = pfctl_do_ioctl(dev, DIOCGETSYNCOOKIES, 256, &nvl)) != 0) { 2313498934c5SKristof Provost ret = errno; 2314498934c5SKristof Provost goto out; 2315498934c5SKristof Provost } 2316c69121c4SKristof Provost 2317c69121c4SKristof Provost enabled = nvlist_get_bool(nvl, "enabled"); 2318c69121c4SKristof Provost adaptive = nvlist_get_bool(nvl, "adaptive"); 2319c69121c4SKristof Provost 23205062afffSKristof Provost if (enabled) { 23215062afffSKristof Provost if (adaptive) 23225062afffSKristof Provost s->mode = PFCTL_SYNCOOKIES_ADAPTIVE; 23235062afffSKristof Provost else 23245062afffSKristof Provost s->mode = PFCTL_SYNCOOKIES_ALWAYS; 23255062afffSKristof Provost } else { 23265062afffSKristof Provost s->mode = PFCTL_SYNCOOKIES_NEVER; 23275062afffSKristof Provost } 23285062afffSKristof Provost 23295062afffSKristof Provost s->highwater = nvlist_get_number(nvl, "highwater") * 100 / state_limit; 23305062afffSKristof Provost s->lowwater = nvlist_get_number(nvl, "lowwater") * 100 / state_limit; 2331a6173e94SKristof Provost s->halfopen_states = nvlist_get_number(nvl, "halfopen_states"); 2332c69121c4SKristof Provost 2333498934c5SKristof Provost out: 2334c69121c4SKristof Provost nvlist_destroy(nvl); 2335498934c5SKristof Provost return (ret); 2336c69121c4SKristof Provost } 23374823489aSReid Linnemann 23384823489aSReid Linnemann int 23394823489aSReid Linnemann pfctl_table_add_addrs(int dev, struct pfr_table *tbl, struct pfr_addr 23404823489aSReid Linnemann *addr, int size, int *nadd, int flags) 23414823489aSReid Linnemann { 23424823489aSReid Linnemann struct pfioc_table io; 23434823489aSReid Linnemann 23444823489aSReid Linnemann if (tbl == NULL || size < 0 || (size && addr == NULL)) { 23454823489aSReid Linnemann return (EINVAL); 23464823489aSReid Linnemann } 23474823489aSReid Linnemann bzero(&io, sizeof io); 23484823489aSReid Linnemann io.pfrio_flags = flags; 23494823489aSReid Linnemann io.pfrio_table = *tbl; 23504823489aSReid Linnemann io.pfrio_buffer = addr; 23514823489aSReid Linnemann io.pfrio_esize = sizeof(*addr); 23524823489aSReid Linnemann io.pfrio_size = size; 23534823489aSReid Linnemann 23544823489aSReid Linnemann if (ioctl(dev, DIOCRADDADDRS, &io)) 23554823489aSReid Linnemann return (errno); 23564823489aSReid Linnemann if (nadd != NULL) 23574823489aSReid Linnemann *nadd = io.pfrio_nadd; 23584823489aSReid Linnemann return (0); 23594823489aSReid Linnemann } 23604823489aSReid Linnemann 23614823489aSReid Linnemann int 23624823489aSReid Linnemann pfctl_table_del_addrs(int dev, struct pfr_table *tbl, struct pfr_addr 23634823489aSReid Linnemann *addr, int size, int *ndel, int flags) 23644823489aSReid Linnemann { 23654823489aSReid Linnemann struct pfioc_table io; 23664823489aSReid Linnemann 23674823489aSReid Linnemann if (tbl == NULL || size < 0 || (size && addr == NULL)) { 23684823489aSReid Linnemann return (EINVAL); 23694823489aSReid Linnemann } 23704823489aSReid Linnemann bzero(&io, sizeof io); 23714823489aSReid Linnemann io.pfrio_flags = flags; 23724823489aSReid Linnemann io.pfrio_table = *tbl; 23734823489aSReid Linnemann io.pfrio_buffer = addr; 23744823489aSReid Linnemann io.pfrio_esize = sizeof(*addr); 23754823489aSReid Linnemann io.pfrio_size = size; 23764823489aSReid Linnemann 23774823489aSReid Linnemann if (ioctl(dev, DIOCRDELADDRS, &io)) 23784823489aSReid Linnemann return (errno); 23794823489aSReid Linnemann if (ndel != NULL) 23804823489aSReid Linnemann *ndel = io.pfrio_ndel; 23814823489aSReid Linnemann return (0); 23824823489aSReid Linnemann } 23834823489aSReid Linnemann 23844823489aSReid Linnemann int 23854823489aSReid Linnemann pfctl_table_set_addrs(int dev, struct pfr_table *tbl, struct pfr_addr 23864823489aSReid Linnemann *addr, int size, int *size2, int *nadd, int *ndel, int *nchange, int flags) 23874823489aSReid Linnemann { 23884823489aSReid Linnemann struct pfioc_table io; 23894823489aSReid Linnemann 23904823489aSReid Linnemann if (tbl == NULL || size < 0 || (size && addr == NULL)) { 23914823489aSReid Linnemann return (EINVAL); 23924823489aSReid Linnemann } 23934823489aSReid Linnemann bzero(&io, sizeof io); 23944823489aSReid Linnemann io.pfrio_flags = flags; 23954823489aSReid Linnemann io.pfrio_table = *tbl; 23964823489aSReid Linnemann io.pfrio_buffer = addr; 23974823489aSReid Linnemann io.pfrio_esize = sizeof(*addr); 23984823489aSReid Linnemann io.pfrio_size = size; 23994823489aSReid Linnemann io.pfrio_size2 = (size2 != NULL) ? *size2 : 0; 24004823489aSReid Linnemann if (ioctl(dev, DIOCRSETADDRS, &io)) 240193e96359SKristof Provost return (errno); 24024823489aSReid Linnemann if (nadd != NULL) 24034823489aSReid Linnemann *nadd = io.pfrio_nadd; 24044823489aSReid Linnemann if (ndel != NULL) 24054823489aSReid Linnemann *ndel = io.pfrio_ndel; 24064823489aSReid Linnemann if (nchange != NULL) 24074823489aSReid Linnemann *nchange = io.pfrio_nchange; 24084823489aSReid Linnemann if (size2 != NULL) 24094823489aSReid Linnemann *size2 = io.pfrio_size2; 24104823489aSReid Linnemann return (0); 24114823489aSReid Linnemann } 24124823489aSReid Linnemann 24134823489aSReid Linnemann int pfctl_table_get_addrs(int dev, struct pfr_table *tbl, struct pfr_addr *addr, 24144823489aSReid Linnemann int *size, int flags) 24154823489aSReid Linnemann { 24164823489aSReid Linnemann struct pfioc_table io; 24174823489aSReid Linnemann 24184823489aSReid Linnemann if (tbl == NULL || size == NULL || *size < 0 || 24194823489aSReid Linnemann (*size && addr == NULL)) { 24204823489aSReid Linnemann return (EINVAL); 24214823489aSReid Linnemann } 24224823489aSReid Linnemann bzero(&io, sizeof io); 24234823489aSReid Linnemann io.pfrio_flags = flags; 24244823489aSReid Linnemann io.pfrio_table = *tbl; 24254823489aSReid Linnemann io.pfrio_buffer = addr; 24264823489aSReid Linnemann io.pfrio_esize = sizeof(*addr); 24274823489aSReid Linnemann io.pfrio_size = *size; 24284823489aSReid Linnemann if (ioctl(dev, DIOCRGETADDRS, &io)) 242993e96359SKristof Provost return (errno); 24304823489aSReid Linnemann *size = io.pfrio_size; 24314823489aSReid Linnemann return (0); 24324823489aSReid Linnemann } 2433470a2b33SKristof Provost 2434470a2b33SKristof Provost int 2435470a2b33SKristof Provost pfctl_set_statusif(struct pfctl_handle *h, const char *ifname) 2436470a2b33SKristof Provost { 2437470a2b33SKristof Provost struct snl_writer nw; 2438470a2b33SKristof Provost struct snl_errmsg_data e = {}; 2439470a2b33SKristof Provost struct nlmsghdr *hdr; 2440470a2b33SKristof Provost uint32_t seq_id; 2441470a2b33SKristof Provost int family_id; 2442470a2b33SKristof Provost 2443470a2b33SKristof Provost family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 2444470a2b33SKristof Provost if (family_id == 0) 2445470a2b33SKristof Provost return (ENOTSUP); 2446470a2b33SKristof Provost 2447470a2b33SKristof Provost snl_init_writer(&h->ss, &nw); 2448470a2b33SKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_SET_STATUSIF); 2449470a2b33SKristof Provost 2450470a2b33SKristof Provost snl_add_msg_attr_string(&nw, PF_SS_IFNAME, ifname); 2451470a2b33SKristof Provost 2452470a2b33SKristof Provost if ((hdr = snl_finalize_msg(&nw)) == NULL) 2453470a2b33SKristof Provost return (ENXIO); 2454470a2b33SKristof Provost 2455470a2b33SKristof Provost seq_id = hdr->nlmsg_seq; 2456470a2b33SKristof Provost 2457470a2b33SKristof Provost if (! snl_send_message(&h->ss, hdr)) 2458470a2b33SKristof Provost return (ENXIO); 2459470a2b33SKristof Provost 2460470a2b33SKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 2461470a2b33SKristof Provost } 2462470a2b33SKristof Provost 2463470a2b33SKristof Provost return (e.error); 2464470a2b33SKristof Provost } 246571d3c704SKristof Provost 246671d3c704SKristof Provost #define _IN(_field) offsetof(struct genlmsghdr, _field) 246771d3c704SKristof Provost #define _OUT(_field) offsetof(struct pfctl_natlook, _field) 246871d3c704SKristof Provost static struct snl_attr_parser ap_natlook[] = { 246971d3c704SKristof Provost { .type = PF_NL_SRC_ADDR, .off = _OUT(saddr), .cb = snl_attr_get_in6_addr }, 247071d3c704SKristof Provost { .type = PF_NL_DST_ADDR, .off = _OUT(daddr), .cb = snl_attr_get_in6_addr }, 247171d3c704SKristof Provost { .type = PF_NL_SRC_PORT, .off = _OUT(sport), .cb = snl_attr_get_uint16 }, 247271d3c704SKristof Provost { .type = PF_NL_DST_PORT, .off = _OUT(dport), .cb = snl_attr_get_uint16 }, 247371d3c704SKristof Provost }; 247471d3c704SKristof Provost #undef _IN 247571d3c704SKristof Provost #undef _OUT 24767c882c69SKristof Provost SNL_DECLARE_PARSER(natlook_parser, struct genlmsghdr, snl_f_p_empty, ap_natlook); 247771d3c704SKristof Provost 247871d3c704SKristof Provost int 247971d3c704SKristof Provost pfctl_natlook(struct pfctl_handle *h, const struct pfctl_natlook_key *k, 248071d3c704SKristof Provost struct pfctl_natlook *r) 248171d3c704SKristof Provost { 248271d3c704SKristof Provost struct snl_writer nw; 248371d3c704SKristof Provost struct snl_errmsg_data e = {}; 248471d3c704SKristof Provost struct nlmsghdr *hdr; 248571d3c704SKristof Provost uint32_t seq_id; 248671d3c704SKristof Provost int family_id; 248771d3c704SKristof Provost 248871d3c704SKristof Provost family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 248971d3c704SKristof Provost if (family_id == 0) 249071d3c704SKristof Provost return (ENOTSUP); 249171d3c704SKristof Provost 249271d3c704SKristof Provost snl_init_writer(&h->ss, &nw); 249371d3c704SKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_NATLOOK); 249471d3c704SKristof Provost hdr->nlmsg_flags |= NLM_F_DUMP; 249571d3c704SKristof Provost 249671d3c704SKristof Provost snl_add_msg_attr_u8(&nw, PF_NL_AF, k->af); 249771d3c704SKristof Provost snl_add_msg_attr_u8(&nw, PF_NL_DIRECTION, k->direction); 249871d3c704SKristof Provost snl_add_msg_attr_u8(&nw, PF_NL_PROTO, k->proto); 249971d3c704SKristof Provost snl_add_msg_attr_ip6(&nw, PF_NL_SRC_ADDR, &k->saddr.v6); 250071d3c704SKristof Provost snl_add_msg_attr_ip6(&nw, PF_NL_DST_ADDR, &k->daddr.v6); 250171d3c704SKristof Provost snl_add_msg_attr_u16(&nw, PF_NL_SRC_PORT, k->sport); 250271d3c704SKristof Provost snl_add_msg_attr_u16(&nw, PF_NL_DST_PORT, k->dport); 250371d3c704SKristof Provost 250471d3c704SKristof Provost if ((hdr = snl_finalize_msg(&nw)) == NULL) 250571d3c704SKristof Provost return (ENXIO); 250671d3c704SKristof Provost 250771d3c704SKristof Provost seq_id = hdr->nlmsg_seq; 250871d3c704SKristof Provost 250971d3c704SKristof Provost if (! snl_send_message(&h->ss, hdr)) 251071d3c704SKristof Provost return (ENXIO); 251171d3c704SKristof Provost 251271d3c704SKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 251371d3c704SKristof Provost if (! snl_parse_nlmsg(&h->ss, hdr, &natlook_parser, r)) 251471d3c704SKristof Provost continue; 251571d3c704SKristof Provost } 251671d3c704SKristof Provost 251771d3c704SKristof Provost return (e.error); 251871d3c704SKristof Provost } 2519c36c90a2SKristof Provost 2520c36c90a2SKristof Provost int 2521c36c90a2SKristof Provost pfctl_set_debug(struct pfctl_handle *h, uint32_t level) 2522c36c90a2SKristof Provost { 2523c36c90a2SKristof Provost struct snl_writer nw; 2524c36c90a2SKristof Provost struct snl_errmsg_data e = {}; 2525c36c90a2SKristof Provost struct nlmsghdr *hdr; 2526c36c90a2SKristof Provost uint32_t seq_id; 2527c36c90a2SKristof Provost int family_id; 2528c36c90a2SKristof Provost 2529c36c90a2SKristof Provost family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 2530c36c90a2SKristof Provost if (family_id == 0) 2531c36c90a2SKristof Provost return (ENOTSUP); 2532c36c90a2SKristof Provost 2533c36c90a2SKristof Provost snl_init_writer(&h->ss, &nw); 2534c36c90a2SKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_SET_DEBUG); 2535c36c90a2SKristof Provost 2536c36c90a2SKristof Provost snl_add_msg_attr_u32(&nw, PF_SD_LEVEL, level); 2537c36c90a2SKristof Provost 2538c36c90a2SKristof Provost if ((hdr = snl_finalize_msg(&nw)) == NULL) 2539c36c90a2SKristof Provost return (ENXIO); 2540c36c90a2SKristof Provost 2541c36c90a2SKristof Provost seq_id = hdr->nlmsg_seq; 2542c36c90a2SKristof Provost 2543c36c90a2SKristof Provost if (! snl_send_message(&h->ss, hdr)) 2544c36c90a2SKristof Provost return (ENXIO); 2545c36c90a2SKristof Provost 2546c36c90a2SKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 2547c36c90a2SKristof Provost } 2548c36c90a2SKristof Provost 2549c36c90a2SKristof Provost return (e.error); 2550c36c90a2SKristof Provost } 255130bad751SKristof Provost 255230bad751SKristof Provost int 255330bad751SKristof Provost pfctl_set_timeout(struct pfctl_handle *h, uint32_t timeout, uint32_t seconds) 255430bad751SKristof Provost { 255530bad751SKristof Provost struct snl_writer nw; 255630bad751SKristof Provost struct snl_errmsg_data e = {}; 255730bad751SKristof Provost struct nlmsghdr *hdr; 255830bad751SKristof Provost uint32_t seq_id; 255930bad751SKristof Provost int family_id; 256030bad751SKristof Provost 256130bad751SKristof Provost family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 256230bad751SKristof Provost if (family_id == 0) 256330bad751SKristof Provost return (ENOTSUP); 256430bad751SKristof Provost 256530bad751SKristof Provost snl_init_writer(&h->ss, &nw); 256630bad751SKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_SET_TIMEOUT); 256730bad751SKristof Provost 256830bad751SKristof Provost snl_add_msg_attr_u32(&nw, PF_TO_TIMEOUT, timeout); 256930bad751SKristof Provost snl_add_msg_attr_u32(&nw, PF_TO_SECONDS, seconds); 257030bad751SKristof Provost 257130bad751SKristof Provost if ((hdr = snl_finalize_msg(&nw)) == NULL) 257230bad751SKristof Provost return (ENXIO); 257330bad751SKristof Provost 257430bad751SKristof Provost seq_id = hdr->nlmsg_seq; 257530bad751SKristof Provost 257630bad751SKristof Provost if (! snl_send_message(&h->ss, hdr)) 257730bad751SKristof Provost return (ENXIO); 257830bad751SKristof Provost 257930bad751SKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 258030bad751SKristof Provost } 258130bad751SKristof Provost 258230bad751SKristof Provost return (e.error); 258330bad751SKristof Provost } 258430bad751SKristof Provost 258530bad751SKristof Provost struct pfctl_nl_timeout { 258630bad751SKristof Provost uint32_t seconds; 258730bad751SKristof Provost }; 258830bad751SKristof Provost #define _OUT(_field) offsetof(struct pfctl_nl_timeout, _field) 258930bad751SKristof Provost static struct snl_attr_parser ap_get_timeout[] = { 259030bad751SKristof Provost { .type = PF_TO_SECONDS, .off = _OUT(seconds), .cb = snl_attr_get_uint32 }, 259130bad751SKristof Provost }; 259230bad751SKristof Provost #undef _OUT 25937c882c69SKristof Provost SNL_DECLARE_PARSER(get_timeout_parser, struct genlmsghdr, snl_f_p_empty, ap_get_timeout); 259430bad751SKristof Provost 259530bad751SKristof Provost int 259630bad751SKristof Provost pfctl_get_timeout(struct pfctl_handle *h, uint32_t timeout, uint32_t *seconds) 259730bad751SKristof Provost { 259830bad751SKristof Provost struct snl_writer nw; 259930bad751SKristof Provost struct pfctl_nl_timeout to = {}; 260030bad751SKristof Provost struct snl_errmsg_data e = {}; 260130bad751SKristof Provost struct nlmsghdr *hdr; 260230bad751SKristof Provost uint32_t seq_id; 260330bad751SKristof Provost int family_id; 260430bad751SKristof Provost 260530bad751SKristof Provost family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 260630bad751SKristof Provost if (family_id == 0) 260730bad751SKristof Provost return (ENOTSUP); 260830bad751SKristof Provost 260930bad751SKristof Provost snl_init_writer(&h->ss, &nw); 261030bad751SKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_GET_TIMEOUT); 261130bad751SKristof Provost hdr->nlmsg_flags |= NLM_F_DUMP; 261230bad751SKristof Provost 261330bad751SKristof Provost snl_add_msg_attr_u32(&nw, PF_TO_TIMEOUT, timeout); 261430bad751SKristof Provost 261530bad751SKristof Provost if ((hdr = snl_finalize_msg(&nw)) == NULL) 261630bad751SKristof Provost return (ENXIO); 261730bad751SKristof Provost 261830bad751SKristof Provost seq_id = hdr->nlmsg_seq; 261930bad751SKristof Provost 262030bad751SKristof Provost if (! snl_send_message(&h->ss, hdr)) 262130bad751SKristof Provost return (ENXIO); 262230bad751SKristof Provost 262330bad751SKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 262430bad751SKristof Provost if (! snl_parse_nlmsg(&h->ss, hdr, &get_timeout_parser, &to)) 262530bad751SKristof Provost continue; 262630bad751SKristof Provost } 262730bad751SKristof Provost 262830bad751SKristof Provost if (seconds != NULL) 262930bad751SKristof Provost *seconds = to.seconds; 263030bad751SKristof Provost 263130bad751SKristof Provost return (e.error); 263230bad751SKristof Provost } 263330bad751SKristof Provost 2634d9ab8999SKristof Provost int 2635d9ab8999SKristof Provost pfctl_set_limit(struct pfctl_handle *h, const int index, const uint limit) 2636d9ab8999SKristof Provost { 2637d9ab8999SKristof Provost struct snl_writer nw; 2638d9ab8999SKristof Provost struct snl_errmsg_data e = {}; 2639d9ab8999SKristof Provost struct nlmsghdr *hdr; 2640d9ab8999SKristof Provost uint32_t seq_id; 2641d9ab8999SKristof Provost int family_id; 2642d9ab8999SKristof Provost 2643d9ab8999SKristof Provost family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 2644d9ab8999SKristof Provost if (family_id == 0) 2645d9ab8999SKristof Provost return (ENOTSUP); 2646d9ab8999SKristof Provost 2647d9ab8999SKristof Provost snl_init_writer(&h->ss, &nw); 2648d9ab8999SKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_SET_LIMIT); 2649d9ab8999SKristof Provost 2650d9ab8999SKristof Provost snl_add_msg_attr_u32(&nw, PF_LI_INDEX, index); 2651d9ab8999SKristof Provost snl_add_msg_attr_u32(&nw, PF_LI_LIMIT, limit); 2652d9ab8999SKristof Provost 2653d9ab8999SKristof Provost if ((hdr = snl_finalize_msg(&nw)) == NULL) 2654d9ab8999SKristof Provost return (ENXIO); 2655d9ab8999SKristof Provost 2656d9ab8999SKristof Provost seq_id = hdr->nlmsg_seq; 2657d9ab8999SKristof Provost 2658d9ab8999SKristof Provost if (! snl_send_message(&h->ss, hdr)) 2659d9ab8999SKristof Provost return (ENXIO); 2660d9ab8999SKristof Provost 2661d9ab8999SKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 2662d9ab8999SKristof Provost } 2663d9ab8999SKristof Provost 2664d9ab8999SKristof Provost return (e.error); 2665d9ab8999SKristof Provost } 2666d9ab8999SKristof Provost 2667d9ab8999SKristof Provost struct pfctl_nl_limit { 2668d9ab8999SKristof Provost unsigned int limit; 2669d9ab8999SKristof Provost }; 2670d9ab8999SKristof Provost #define _OUT(_field) offsetof(struct pfctl_nl_limit, _field) 2671d9ab8999SKristof Provost static struct snl_attr_parser ap_get_limit[] = { 2672d9ab8999SKristof Provost { .type = PF_LI_LIMIT, .off = _OUT(limit), .cb = snl_attr_get_uint32 }, 2673d9ab8999SKristof Provost }; 2674d9ab8999SKristof Provost #undef _OUT 26757c882c69SKristof Provost SNL_DECLARE_PARSER(get_limit_parser, struct genlmsghdr, snl_f_p_empty, ap_get_limit); 2676d9ab8999SKristof Provost 2677d9ab8999SKristof Provost int 2678d9ab8999SKristof Provost pfctl_get_limit(struct pfctl_handle *h, const int index, uint *limit) 2679d9ab8999SKristof Provost { 2680d9ab8999SKristof Provost struct snl_writer nw; 2681d9ab8999SKristof Provost struct pfctl_nl_limit li = {}; 2682d9ab8999SKristof Provost struct snl_errmsg_data e = {}; 2683d9ab8999SKristof Provost struct nlmsghdr *hdr; 2684d9ab8999SKristof Provost uint32_t seq_id; 2685d9ab8999SKristof Provost int family_id; 2686d9ab8999SKristof Provost 2687d9ab8999SKristof Provost family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 2688d9ab8999SKristof Provost if (family_id == 0) 2689d9ab8999SKristof Provost return (ENOTSUP); 2690d9ab8999SKristof Provost 2691d9ab8999SKristof Provost snl_init_writer(&h->ss, &nw); 2692d9ab8999SKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_GET_LIMIT); 2693d9ab8999SKristof Provost hdr->nlmsg_flags |= NLM_F_DUMP; 2694d9ab8999SKristof Provost 2695d9ab8999SKristof Provost snl_add_msg_attr_u32(&nw, PF_LI_INDEX, index); 2696d9ab8999SKristof Provost 2697d9ab8999SKristof Provost if ((hdr = snl_finalize_msg(&nw)) == NULL) 2698d9ab8999SKristof Provost return (ENXIO); 2699d9ab8999SKristof Provost 2700d9ab8999SKristof Provost seq_id = hdr->nlmsg_seq; 2701d9ab8999SKristof Provost 2702d9ab8999SKristof Provost if (! snl_send_message(&h->ss, hdr)) 2703d9ab8999SKristof Provost return (ENXIO); 2704d9ab8999SKristof Provost 2705d9ab8999SKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 2706d9ab8999SKristof Provost if (! snl_parse_nlmsg(&h->ss, hdr, &get_limit_parser, &li)) 2707d9ab8999SKristof Provost continue; 2708d9ab8999SKristof Provost } 2709d9ab8999SKristof Provost 2710d9ab8999SKristof Provost if (limit != NULL) 2711d9ab8999SKristof Provost *limit = li.limit; 2712d9ab8999SKristof Provost 2713d9ab8999SKristof Provost return (e.error); 2714d9ab8999SKristof Provost } 2715ba2a9207SKristof Provost 2716ba2a9207SKristof Provost struct pfctl_nl_begin_addrs { 2717ba2a9207SKristof Provost uint32_t ticket; 2718ba2a9207SKristof Provost }; 2719ba2a9207SKristof Provost #define _OUT(_field) offsetof(struct pfctl_nl_begin_addrs, _field) 2720ba2a9207SKristof Provost static struct snl_attr_parser ap_begin_addrs[] = { 2721ba2a9207SKristof Provost { .type = PF_BA_TICKET, .off = _OUT(ticket), .cb = snl_attr_get_uint32 }, 2722ba2a9207SKristof Provost }; 2723ba2a9207SKristof Provost #undef _OUT 27247c882c69SKristof Provost SNL_DECLARE_PARSER(begin_addrs_parser, struct genlmsghdr, snl_f_p_empty, ap_begin_addrs); 2725ba2a9207SKristof Provost 2726ba2a9207SKristof Provost int 2727ba2a9207SKristof Provost pfctl_begin_addrs(struct pfctl_handle *h, uint32_t *ticket) 2728ba2a9207SKristof Provost { 2729ba2a9207SKristof Provost struct snl_writer nw; 2730ba2a9207SKristof Provost struct pfctl_nl_begin_addrs attrs = {}; 2731ba2a9207SKristof Provost struct snl_errmsg_data e = {}; 2732ba2a9207SKristof Provost struct nlmsghdr *hdr; 2733ba2a9207SKristof Provost uint32_t seq_id; 2734ba2a9207SKristof Provost int family_id; 2735ba2a9207SKristof Provost 2736ba2a9207SKristof Provost family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 2737ba2a9207SKristof Provost if (family_id == 0) 2738ba2a9207SKristof Provost return (ENOTSUP); 2739ba2a9207SKristof Provost 2740ba2a9207SKristof Provost snl_init_writer(&h->ss, &nw); 2741ba2a9207SKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_BEGIN_ADDRS); 2742ba2a9207SKristof Provost hdr->nlmsg_flags |= NLM_F_DUMP; 2743ba2a9207SKristof Provost 2744ba2a9207SKristof Provost if ((hdr = snl_finalize_msg(&nw)) == NULL) 2745ba2a9207SKristof Provost return (ENXIO); 2746ba2a9207SKristof Provost 2747ba2a9207SKristof Provost seq_id = hdr->nlmsg_seq; 2748ba2a9207SKristof Provost 2749ba2a9207SKristof Provost if (! snl_send_message(&h->ss, hdr)) 2750ba2a9207SKristof Provost return (ENXIO); 2751ba2a9207SKristof Provost 2752ba2a9207SKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 2753ba2a9207SKristof Provost if (! snl_parse_nlmsg(&h->ss, hdr, &begin_addrs_parser, &attrs)) 2754ba2a9207SKristof Provost continue; 2755ba2a9207SKristof Provost } 2756ba2a9207SKristof Provost 2757ba2a9207SKristof Provost if (ticket != NULL) 2758ba2a9207SKristof Provost *ticket = attrs.ticket; 2759ba2a9207SKristof Provost 2760ba2a9207SKristof Provost return (e.error); 2761ba2a9207SKristof Provost } 2762ba2a9207SKristof Provost 2763d909f06bSKristof Provost int 2764aa69fdf1SKristof Provost pfctl_add_addr(struct pfctl_handle *h, const struct pfioc_pooladdr *pa, int which) 2765d909f06bSKristof Provost { 2766d909f06bSKristof Provost struct snl_writer nw; 2767d909f06bSKristof Provost struct snl_errmsg_data e = {}; 2768d909f06bSKristof Provost struct nlmsghdr *hdr; 2769d909f06bSKristof Provost uint32_t seq_id; 2770d909f06bSKristof Provost int family_id; 2771d909f06bSKristof Provost 2772d909f06bSKristof Provost family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 2773d909f06bSKristof Provost if (family_id == 0) 2774d909f06bSKristof Provost return (ENOTSUP); 2775d909f06bSKristof Provost 2776d909f06bSKristof Provost snl_init_writer(&h->ss, &nw); 2777d909f06bSKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_ADD_ADDR); 2778d909f06bSKristof Provost 2779d909f06bSKristof Provost snl_add_msg_attr_u32(&nw, PF_AA_ACTION, pa->action); 2780d909f06bSKristof Provost snl_add_msg_attr_u32(&nw, PF_AA_TICKET, pa->ticket); 2781d909f06bSKristof Provost snl_add_msg_attr_u32(&nw, PF_AA_NR, pa->nr); 2782d909f06bSKristof Provost snl_add_msg_attr_u32(&nw, PF_AA_R_NUM, pa->r_num); 2783d909f06bSKristof Provost snl_add_msg_attr_u8(&nw, PF_AA_R_ACTION, pa->r_action); 2784d909f06bSKristof Provost snl_add_msg_attr_u8(&nw, PF_AA_R_LAST, pa->r_last); 2785d909f06bSKristof Provost snl_add_msg_attr_u8(&nw, PF_AA_AF, pa->af); 2786d909f06bSKristof Provost snl_add_msg_attr_string(&nw, PF_AA_ANCHOR, pa->anchor); 2787d909f06bSKristof Provost snl_add_msg_attr_pool_addr(&nw, PF_AA_ADDR, &pa->addr); 2788aa69fdf1SKristof Provost snl_add_msg_attr_u32(&nw, PF_AA_WHICH, which); 2789d909f06bSKristof Provost 2790d909f06bSKristof Provost if ((hdr = snl_finalize_msg(&nw)) == NULL) 2791d909f06bSKristof Provost return (ENXIO); 2792d909f06bSKristof Provost 2793d909f06bSKristof Provost seq_id = hdr->nlmsg_seq; 2794d909f06bSKristof Provost 2795d909f06bSKristof Provost if (! snl_send_message(&h->ss, hdr)) 2796d909f06bSKristof Provost return (ENXIO); 2797d909f06bSKristof Provost 2798d909f06bSKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 2799d909f06bSKristof Provost } 2800d909f06bSKristof Provost 2801d909f06bSKristof Provost return (e.error); 2802d909f06bSKristof Provost } 2803644b7b5aSKristof Provost 2804644b7b5aSKristof Provost static const struct snl_attr_parser ap_get_addrs[] = { 2805644b7b5aSKristof Provost { .type = PF_AA_NR, .off = 0, .cb = snl_attr_get_uint32 }, 2806644b7b5aSKristof Provost }; 28077c882c69SKristof Provost SNL_DECLARE_PARSER(get_addrs_parser, struct genlmsghdr, snl_f_p_empty, ap_get_addrs); 2808644b7b5aSKristof Provost 2809644b7b5aSKristof Provost int 2810644b7b5aSKristof Provost pfctl_get_addrs(struct pfctl_handle *h, uint32_t ticket, uint32_t r_num, 2811aa69fdf1SKristof Provost uint8_t r_action, const char *anchor, uint32_t *nr, int which) 2812644b7b5aSKristof Provost { 2813644b7b5aSKristof Provost struct snl_writer nw; 2814644b7b5aSKristof Provost struct snl_errmsg_data e = {}; 2815644b7b5aSKristof Provost struct nlmsghdr *hdr; 2816644b7b5aSKristof Provost uint32_t seq_id; 2817644b7b5aSKristof Provost int family_id; 2818644b7b5aSKristof Provost 2819644b7b5aSKristof Provost family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 2820644b7b5aSKristof Provost if (family_id == 0) 2821644b7b5aSKristof Provost return (ENOTSUP); 2822644b7b5aSKristof Provost 2823644b7b5aSKristof Provost snl_init_writer(&h->ss, &nw); 2824644b7b5aSKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_GET_ADDRS); 2825644b7b5aSKristof Provost 2826644b7b5aSKristof Provost snl_add_msg_attr_u32(&nw, PF_AA_TICKET, ticket); 2827644b7b5aSKristof Provost snl_add_msg_attr_u32(&nw, PF_AA_R_NUM, r_num); 2828644b7b5aSKristof Provost snl_add_msg_attr_u8(&nw, PF_AA_R_ACTION, r_action); 2829644b7b5aSKristof Provost snl_add_msg_attr_string(&nw, PF_AA_ANCHOR, anchor); 2830aa69fdf1SKristof Provost snl_add_msg_attr_u32(&nw, PF_AA_WHICH, which); 2831644b7b5aSKristof Provost 2832644b7b5aSKristof Provost if ((hdr = snl_finalize_msg(&nw)) == NULL) 2833644b7b5aSKristof Provost return (ENXIO); 2834644b7b5aSKristof Provost 2835644b7b5aSKristof Provost seq_id = hdr->nlmsg_seq; 2836644b7b5aSKristof Provost 2837644b7b5aSKristof Provost if (! snl_send_message(&h->ss, hdr)) 2838644b7b5aSKristof Provost return (ENXIO); 2839644b7b5aSKristof Provost 2840644b7b5aSKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 2841644b7b5aSKristof Provost if (! snl_parse_nlmsg(&h->ss, hdr, &get_addrs_parser, nr)) 2842644b7b5aSKristof Provost continue; 2843644b7b5aSKristof Provost } 2844644b7b5aSKristof Provost 2845644b7b5aSKristof Provost return (e.error); 2846644b7b5aSKristof Provost } 28479ae91f59SKristof Provost 28489ae91f59SKristof Provost #define _OUT(_field) offsetof(struct pf_pooladdr, _field) 28499ae91f59SKristof Provost static const struct snl_attr_parser ap_pool_addr[] = { 28509ae91f59SKristof Provost { .type = PF_PA_ADDR, .off = _OUT(addr), .arg = &addr_wrap_parser, .cb = snl_attr_get_nested }, 28519ae91f59SKristof Provost { .type = PF_PA_IFNAME, .off = _OUT(ifname), .arg_u32 = IFNAMSIZ, .cb = snl_attr_copy_string }, 28529ae91f59SKristof Provost }; 28539ae91f59SKristof Provost SNL_DECLARE_ATTR_PARSER(pool_addr_parser, ap_pool_addr); 28549ae91f59SKristof Provost #undef _OUT 28559ae91f59SKristof Provost 28569ae91f59SKristof Provost #define _OUT(_field) offsetof(struct pfioc_pooladdr, _field) 28579ae91f59SKristof Provost static const struct snl_attr_parser ap_get_addr[] = { 28589ae91f59SKristof Provost { .type = PF_AA_ACTION, .off = _OUT(action), .cb = snl_attr_get_uint32 }, 28599ae91f59SKristof Provost { .type = PF_AA_TICKET, .off = _OUT(ticket), .cb = snl_attr_get_uint32 }, 28609ae91f59SKristof Provost { .type = PF_AA_NR, .off = _OUT(nr), .cb = snl_attr_get_uint32 }, 28619ae91f59SKristof Provost { .type = PF_AA_R_NUM, .off = _OUT(r_num), .cb = snl_attr_get_uint32 }, 28629ae91f59SKristof Provost { .type = PF_AA_R_ACTION, .off = _OUT(r_action), .cb = snl_attr_get_uint8 }, 28639ae91f59SKristof Provost { .type = PF_AA_R_LAST, .off = _OUT(r_last), .cb = snl_attr_get_uint8 }, 28649ae91f59SKristof Provost { .type = PF_AA_AF, .off = _OUT(af), .cb = snl_attr_get_uint8 }, 28659ae91f59SKristof Provost { .type = PF_AA_ANCHOR, .off = _OUT(anchor), .arg_u32 = MAXPATHLEN, .cb = snl_attr_copy_string }, 28669ae91f59SKristof Provost { .type = PF_AA_ADDR, .off = _OUT(addr), .arg = &pool_addr_parser, .cb = snl_attr_get_nested }, 28679ae91f59SKristof Provost }; 28687c882c69SKristof Provost SNL_DECLARE_PARSER(get_addr_parser, struct genlmsghdr, snl_f_p_empty, ap_get_addr); 28699ae91f59SKristof Provost #undef _OUT 28709ae91f59SKristof Provost 28719ae91f59SKristof Provost int 28729ae91f59SKristof Provost pfctl_get_addr(struct pfctl_handle *h, uint32_t ticket, uint32_t r_num, 2873aa69fdf1SKristof Provost uint8_t r_action, const char *anchor, uint32_t nr, struct pfioc_pooladdr *pa, 2874aa69fdf1SKristof Provost int which) 28759ae91f59SKristof Provost { 28769ae91f59SKristof Provost struct snl_writer nw; 28779ae91f59SKristof Provost struct snl_errmsg_data e = {}; 28789ae91f59SKristof Provost struct nlmsghdr *hdr; 28799ae91f59SKristof Provost uint32_t seq_id; 28809ae91f59SKristof Provost int family_id; 28819ae91f59SKristof Provost 28829ae91f59SKristof Provost family_id =snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 28839ae91f59SKristof Provost if (family_id == 0) 28849ae91f59SKristof Provost return (ENOTSUP); 28859ae91f59SKristof Provost 28869ae91f59SKristof Provost snl_init_writer(&h->ss, &nw); 28879ae91f59SKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_GET_ADDR); 28889ae91f59SKristof Provost 28899ae91f59SKristof Provost snl_add_msg_attr_u32(&nw, PF_AA_TICKET, ticket); 28909ae91f59SKristof Provost snl_add_msg_attr_u32(&nw, PF_AA_R_NUM, r_num); 28919ae91f59SKristof Provost snl_add_msg_attr_u8(&nw, PF_AA_R_ACTION, r_action); 28929ae91f59SKristof Provost snl_add_msg_attr_string(&nw, PF_AA_ANCHOR, anchor); 28939ae91f59SKristof Provost snl_add_msg_attr_u32(&nw, PF_AA_NR, nr); 2894aa69fdf1SKristof Provost snl_add_msg_attr_u32(&nw, PF_AA_WHICH, which); 28959ae91f59SKristof Provost 28969ae91f59SKristof Provost if ((hdr = snl_finalize_msg(&nw)) == NULL) 28979ae91f59SKristof Provost return (ENXIO); 28989ae91f59SKristof Provost 28999ae91f59SKristof Provost seq_id = hdr->nlmsg_seq; 29009ae91f59SKristof Provost 29019ae91f59SKristof Provost if (! snl_send_message(&h->ss, hdr)) 29029ae91f59SKristof Provost return (ENXIO); 29039ae91f59SKristof Provost 29049ae91f59SKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 29059ae91f59SKristof Provost if (! snl_parse_nlmsg(&h->ss, hdr, &get_addr_parser, pa)) 29069ae91f59SKristof Provost continue; 29079ae91f59SKristof Provost } 29089ae91f59SKristof Provost 290925e0f8f9SKristof Provost return (e.error); 29109ae91f59SKristof Provost } 291125e0f8f9SKristof Provost 291225e0f8f9SKristof Provost #define _OUT(_field) offsetof(struct pfioc_ruleset, _field) 291325e0f8f9SKristof Provost static const struct snl_attr_parser ap_ruleset[] = { 291425e0f8f9SKristof Provost { .type = PF_RS_NR, .off = _OUT(nr), .cb = snl_attr_get_uint32 }, 291548f5bf8bSKristof Provost { .type = PF_RS_NAME, .off = _OUT(name), .arg = (void *)PF_ANCHOR_NAME_SIZE, .cb = snl_attr_copy_string }, 291625e0f8f9SKristof Provost }; 29177c882c69SKristof Provost SNL_DECLARE_PARSER(ruleset_parser, struct genlmsghdr, snl_f_p_empty, ap_ruleset); 291825e0f8f9SKristof Provost #undef _OUT 291925e0f8f9SKristof Provost 292025e0f8f9SKristof Provost int 292125e0f8f9SKristof Provost pfctl_get_rulesets(struct pfctl_handle *h, const char *path, uint32_t *nr) 292225e0f8f9SKristof Provost { 292325e0f8f9SKristof Provost struct snl_writer nw; 292425e0f8f9SKristof Provost struct snl_errmsg_data e = {}; 292525e0f8f9SKristof Provost struct nlmsghdr *hdr; 292625e0f8f9SKristof Provost struct pfioc_ruleset rs = {}; 292725e0f8f9SKristof Provost uint32_t seq_id; 292825e0f8f9SKristof Provost int family_id; 292925e0f8f9SKristof Provost 293025e0f8f9SKristof Provost family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 293125e0f8f9SKristof Provost if (family_id == 0) 293225e0f8f9SKristof Provost return (ENOTSUP); 293325e0f8f9SKristof Provost 293425e0f8f9SKristof Provost snl_init_writer(&h->ss, &nw); 293525e0f8f9SKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_GET_RULESETS); 293625e0f8f9SKristof Provost 293725e0f8f9SKristof Provost snl_add_msg_attr_string(&nw, PF_RS_PATH, path); 293825e0f8f9SKristof Provost 293925e0f8f9SKristof Provost if ((hdr = snl_finalize_msg(&nw)) == NULL) 294025e0f8f9SKristof Provost return (ENXIO); 294125e0f8f9SKristof Provost 294225e0f8f9SKristof Provost seq_id = hdr->nlmsg_seq; 294325e0f8f9SKristof Provost 294425e0f8f9SKristof Provost if (! snl_send_message(&h->ss, hdr)) 294525e0f8f9SKristof Provost return (ENXIO); 294625e0f8f9SKristof Provost 294725e0f8f9SKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 294825e0f8f9SKristof Provost if (! snl_parse_nlmsg(&h->ss, hdr, &ruleset_parser, &rs)) 294925e0f8f9SKristof Provost continue; 295025e0f8f9SKristof Provost } 295125e0f8f9SKristof Provost 295225e0f8f9SKristof Provost *nr = rs.nr; 295325e0f8f9SKristof Provost 295425e0f8f9SKristof Provost return (e.error); 295525e0f8f9SKristof Provost } 295625e0f8f9SKristof Provost 295748f5bf8bSKristof Provost int 295848f5bf8bSKristof Provost pfctl_get_ruleset(struct pfctl_handle *h, const char *path, uint32_t nr, struct pfioc_ruleset *rs) 295948f5bf8bSKristof Provost { 296048f5bf8bSKristof Provost struct snl_writer nw; 296148f5bf8bSKristof Provost struct snl_errmsg_data e = {}; 296248f5bf8bSKristof Provost struct nlmsghdr *hdr; 296348f5bf8bSKristof Provost uint32_t seq_id; 296448f5bf8bSKristof Provost int family_id; 296548f5bf8bSKristof Provost 296648f5bf8bSKristof Provost family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 296748f5bf8bSKristof Provost if (family_id == 0) 296848f5bf8bSKristof Provost return (ENOTSUP); 296948f5bf8bSKristof Provost 297048f5bf8bSKristof Provost snl_init_writer(&h->ss, &nw); 297148f5bf8bSKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_GET_RULESET); 297248f5bf8bSKristof Provost 297348f5bf8bSKristof Provost snl_add_msg_attr_string(&nw, PF_RS_PATH, path); 297448f5bf8bSKristof Provost snl_add_msg_attr_u32(&nw, PF_RS_NR, nr); 297548f5bf8bSKristof Provost 297648f5bf8bSKristof Provost if ((hdr = snl_finalize_msg(&nw)) == NULL) 297748f5bf8bSKristof Provost return (ENXIO); 297848f5bf8bSKristof Provost 297948f5bf8bSKristof Provost seq_id = hdr->nlmsg_seq; 298048f5bf8bSKristof Provost 298148f5bf8bSKristof Provost if (! snl_send_message(&h->ss, hdr)) 298248f5bf8bSKristof Provost return (ENXIO); 298348f5bf8bSKristof Provost 298448f5bf8bSKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 298548f5bf8bSKristof Provost if (! snl_parse_nlmsg(&h->ss, hdr, &ruleset_parser, rs)) 298648f5bf8bSKristof Provost continue; 298748f5bf8bSKristof Provost } 298848f5bf8bSKristof Provost 298948f5bf8bSKristof Provost return (e.error); 299048f5bf8bSKristof Provost } 299148f5bf8bSKristof Provost 29929c125336SKristof Provost #define _OUT(_field) offsetof(struct pfctl_threshold, _field) 29939c125336SKristof Provost static const struct snl_attr_parser ap_pfctl_threshold[] = { 29949c125336SKristof Provost { .type = PF_TH_LIMIT, .off = _OUT(limit), .cb = snl_attr_get_uint32 }, 29959c125336SKristof Provost { .type = PF_TH_SECONDS, .off = _OUT(seconds), .cb = snl_attr_get_uint32 }, 29969c125336SKristof Provost { .type = PF_TH_COUNT, .off = _OUT(count), .cb = snl_attr_get_uint32 }, 29979c125336SKristof Provost { .type = PF_TH_LAST, .off = _OUT(last), .cb = snl_attr_get_uint32 }, 29989c125336SKristof Provost }; 29999c125336SKristof Provost SNL_DECLARE_ATTR_PARSER(pfctl_threshold_parser, ap_pfctl_threshold); 30009c125336SKristof Provost #undef _OUT 30019c125336SKristof Provost 30029c125336SKristof Provost #define _OUT(_field) offsetof(struct pfctl_src_node, _field) 30039c125336SKristof Provost static struct snl_attr_parser ap_srcnode[] = { 30049c125336SKristof Provost { .type = PF_SN_ADDR, .off = _OUT(addr), .cb = snl_attr_get_in6_addr }, 30059c125336SKristof Provost { .type = PF_SN_RADDR, .off = _OUT(raddr), .cb = snl_attr_get_in6_addr }, 30069c125336SKristof Provost { .type = PF_SN_RULE_NR, .off = _OUT(rule), .cb = snl_attr_get_uint32 }, 30079c125336SKristof Provost { .type = PF_SN_BYTES_IN, .off = _OUT(bytes[0]), .cb = snl_attr_get_uint64 }, 30089c125336SKristof Provost { .type = PF_SN_BYTES_OUT, .off = _OUT(bytes[1]), .cb = snl_attr_get_uint64 }, 30099c125336SKristof Provost { .type = PF_SN_PACKETS_IN, .off = _OUT(packets[0]), .cb = snl_attr_get_uint64 }, 30109c125336SKristof Provost { .type = PF_SN_PACKETS_OUT, .off = _OUT(packets[1]), .cb = snl_attr_get_uint64 }, 30119c125336SKristof Provost { .type = PF_SN_STATES, .off = _OUT(states), .cb = snl_attr_get_uint32 }, 30129c125336SKristof Provost { .type = PF_SN_CONNECTIONS, .off = _OUT(conn), .cb = snl_attr_get_uint32 }, 30139c125336SKristof Provost { .type = PF_SN_AF, .off = _OUT(af), .cb = snl_attr_get_uint8 }, 30149c125336SKristof Provost { .type = PF_SN_RULE_TYPE, .off = _OUT(ruletype), .cb = snl_attr_get_uint8 }, 30159c125336SKristof Provost { .type = PF_SN_CREATION, .off = _OUT(creation), .cb = snl_attr_get_uint64 }, 30169c125336SKristof Provost { .type = PF_SN_EXPIRE, .off = _OUT(expire), .cb = snl_attr_get_uint64 }, 30179c125336SKristof Provost { .type = PF_SN_CONNECTION_RATE, .off = _OUT(conn_rate), .arg = &pfctl_threshold_parser, .cb = snl_attr_get_nested }, 3018aa69fdf1SKristof Provost { .type = PF_SN_NAF, .off = _OUT(naf), .cb = snl_attr_get_uint8 }, 30199c125336SKristof Provost }; 30209c125336SKristof Provost #undef _OUT 30217c882c69SKristof Provost SNL_DECLARE_PARSER(srcnode_parser, struct genlmsghdr, snl_f_p_empty, ap_srcnode); 30229c125336SKristof Provost 30239c125336SKristof Provost int 30249c125336SKristof Provost pfctl_get_srcnodes(struct pfctl_handle *h, pfctl_get_srcnode_fn fn, void *arg) 30259c125336SKristof Provost { 30269c125336SKristof Provost struct snl_writer nw; 30279c125336SKristof Provost struct pfctl_src_node sn; 30289c125336SKristof Provost struct snl_errmsg_data e = {}; 30299c125336SKristof Provost struct nlmsghdr *hdr; 30309c125336SKristof Provost uint32_t seq_id; 30319c125336SKristof Provost int family_id; 30329c125336SKristof Provost int ret; 30339c125336SKristof Provost 30349c125336SKristof Provost family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 30359c125336SKristof Provost if (family_id == 0) 30369c125336SKristof Provost return (ENOTSUP); 30379c125336SKristof Provost 30389c125336SKristof Provost snl_init_writer(&h->ss, &nw); 30399c125336SKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_GET_SRCNODES); 30409c125336SKristof Provost 30419c125336SKristof Provost if ((hdr = snl_finalize_msg(&nw)) == NULL) 30429c125336SKristof Provost return (ENXIO); 30439c125336SKristof Provost 30449c125336SKristof Provost seq_id = hdr->nlmsg_seq; 30459c125336SKristof Provost 30469c125336SKristof Provost if (!snl_send_message(&h->ss, hdr)) 30479c125336SKristof Provost return (ENXIO); 30489c125336SKristof Provost 30499c125336SKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 30509c125336SKristof Provost if (!snl_parse_nlmsg(&h->ss, hdr, &srcnode_parser, &sn)) 30519c125336SKristof Provost continue; 30529c125336SKristof Provost 30539c125336SKristof Provost ret = fn(&sn, arg); 30549c125336SKristof Provost if (ret != 0) 30559c125336SKristof Provost return (ret); 30569c125336SKristof Provost } 30579c125336SKristof Provost 30589c125336SKristof Provost return (e.error); 30599c125336SKristof Provost } 3060441d4894SKristof Provost 3061441d4894SKristof Provost static struct snl_attr_parser ap_ndel[] = { 3062441d4894SKristof Provost { .type = PF_T_NBR_DELETED, .off = 0, .cb = snl_attr_get_uint32 }, 3063441d4894SKristof Provost }; 30647c882c69SKristof Provost SNL_DECLARE_PARSER(ndel_parser, struct genlmsghdr, snl_f_p_empty, ap_ndel); 3065441d4894SKristof Provost 3066441d4894SKristof Provost int 3067441d4894SKristof Provost pfctl_clear_tables(struct pfctl_handle *h, struct pfr_table *filter, 3068441d4894SKristof Provost int *ndel, int flags) 3069441d4894SKristof Provost { 3070441d4894SKristof Provost struct snl_writer nw; 3071441d4894SKristof Provost struct snl_errmsg_data e = {}; 3072441d4894SKristof Provost struct nlmsghdr *hdr; 3073441d4894SKristof Provost uint32_t seq_id; 3074441d4894SKristof Provost int family_id; 3075441d4894SKristof Provost 3076441d4894SKristof Provost family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 3077441d4894SKristof Provost if (family_id == 0) 3078441d4894SKristof Provost return (ENOTSUP); 3079441d4894SKristof Provost 3080441d4894SKristof Provost snl_init_writer(&h->ss, &nw); 3081441d4894SKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_CLEAR_TABLES); 3082441d4894SKristof Provost 3083441d4894SKristof Provost snl_add_msg_attr_string(&nw, PF_T_ANCHOR, filter->pfrt_anchor); 3084441d4894SKristof Provost snl_add_msg_attr_string(&nw, PF_T_NAME, filter->pfrt_name); 3085441d4894SKristof Provost snl_add_msg_attr_u32(&nw, PF_T_TABLE_FLAGS, filter->pfrt_flags); 3086441d4894SKristof Provost snl_add_msg_attr_u32(&nw, PF_T_FLAGS, flags); 3087441d4894SKristof Provost 3088441d4894SKristof Provost if ((hdr = snl_finalize_msg(&nw)) == NULL) 3089441d4894SKristof Provost return (ENXIO); 3090441d4894SKristof Provost 3091441d4894SKristof Provost seq_id = hdr->nlmsg_seq; 3092441d4894SKristof Provost 3093441d4894SKristof Provost if (!snl_send_message(&h->ss, hdr)) 3094441d4894SKristof Provost return (ENXIO); 3095441d4894SKristof Provost 3096441d4894SKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 3097441d4894SKristof Provost if (!snl_parse_nlmsg(&h->ss, hdr, &ndel_parser, ndel)) 3098441d4894SKristof Provost continue; 3099441d4894SKristof Provost } 3100441d4894SKristof Provost 3101441d4894SKristof Provost return (e.error); 3102441d4894SKristof Provost } 3103