10d6c8174SKristof Provost /*- 20d6c8174SKristof Provost * SPDX-License-Identifier: BSD-2-Clause 30d6c8174SKristof Provost * 40d6c8174SKristof Provost * Copyright (c) 2021 Rubicon Communications, LLC (Netgate) 50d6c8174SKristof Provost * All rights reserved. 60d6c8174SKristof Provost * 70d6c8174SKristof Provost * Redistribution and use in source and binary forms, with or without 80d6c8174SKristof Provost * modification, are permitted provided that the following conditions 90d6c8174SKristof Provost * are met: 100d6c8174SKristof Provost * 110d6c8174SKristof Provost * - Redistributions of source code must retain the above copyright 120d6c8174SKristof Provost * notice, this list of conditions and the following disclaimer. 130d6c8174SKristof Provost * - Redistributions in binary form must reproduce the above 140d6c8174SKristof Provost * copyright notice, this list of conditions and the following 150d6c8174SKristof Provost * disclaimer in the documentation and/or other materials provided 160d6c8174SKristof Provost * with the distribution. 170d6c8174SKristof Provost * 180d6c8174SKristof Provost * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 190d6c8174SKristof Provost * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 200d6c8174SKristof Provost * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 210d6c8174SKristof Provost * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 220d6c8174SKristof Provost * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 230d6c8174SKristof Provost * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 240d6c8174SKristof Provost * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 250d6c8174SKristof Provost * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 260d6c8174SKristof Provost * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 270d6c8174SKristof Provost * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 280d6c8174SKristof Provost * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 290d6c8174SKristof Provost * POSSIBILITY OF SUCH DAMAGE. 300d6c8174SKristof Provost */ 310d6c8174SKristof Provost 320d6c8174SKristof Provost #include <sys/cdefs.h> 330d6c8174SKristof Provost 340d6c8174SKristof Provost #include <sys/ioctl.h> 350d6c8174SKristof Provost #include <sys/nv.h> 360d6c8174SKristof Provost #include <sys/queue.h> 370d6c8174SKristof Provost #include <sys/types.h> 380d6c8174SKristof Provost 390d6c8174SKristof Provost #include <net/if.h> 400d6c8174SKristof Provost #include <net/pfvar.h> 410d6c8174SKristof Provost #include <netinet/in.h> 420d6c8174SKristof 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 500d6c8174SKristof Provost #include <assert.h> 510d6c8174SKristof Provost #include <err.h> 520d6c8174SKristof Provost #include <errno.h> 5366cacc14SKristof Provost #include <fcntl.h> 540d6c8174SKristof Provost #include <stdlib.h> 550d6c8174SKristof Provost #include <string.h> 560d6c8174SKristof Provost 570d71f9f3SKristof Provost #include "libpfctl.h" 580d6c8174SKristof 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 1910d6c8174SKristof Provost static void 1920d6c8174SKristof Provost pf_nvuint_8_array(const nvlist_t *nvl, const char *name, size_t maxelems, 1937bb3c927SKristof Provost uint8_t *numbers, size_t *nelems) 1940d6c8174SKristof Provost { 1950d6c8174SKristof Provost const uint64_t *tmp; 1960d6c8174SKristof Provost size_t elems; 1970d6c8174SKristof Provost 1980d6c8174SKristof Provost tmp = nvlist_get_number_array(nvl, name, &elems); 1990d6c8174SKristof Provost assert(elems <= maxelems); 2000d6c8174SKristof Provost 2010d6c8174SKristof Provost for (size_t i = 0; i < elems; i++) 2020d6c8174SKristof Provost numbers[i] = tmp[i]; 2030d6c8174SKristof Provost 2040d6c8174SKristof Provost if (nelems) 2050d6c8174SKristof Provost *nelems = elems; 2060d6c8174SKristof Provost } 2070d6c8174SKristof Provost 2080d6c8174SKristof Provost static void 2090d6c8174SKristof Provost pf_nvuint_16_array(const nvlist_t *nvl, const char *name, size_t maxelems, 2107bb3c927SKristof Provost uint16_t *numbers, size_t *nelems) 2110d6c8174SKristof Provost { 2120d6c8174SKristof Provost const uint64_t *tmp; 2130d6c8174SKristof Provost size_t elems; 2140d6c8174SKristof Provost 2150d6c8174SKristof Provost tmp = nvlist_get_number_array(nvl, name, &elems); 2160d6c8174SKristof Provost assert(elems <= maxelems); 2170d6c8174SKristof Provost 2180d6c8174SKristof Provost for (size_t i = 0; i < elems; i++) 2190d6c8174SKristof Provost numbers[i] = tmp[i]; 2200d6c8174SKristof Provost 2210d6c8174SKristof Provost if (nelems) 2220d6c8174SKristof Provost *nelems = elems; 2230d6c8174SKristof Provost } 2240d6c8174SKristof Provost 2250d6c8174SKristof Provost static void 2260d6c8174SKristof Provost pf_nvuint_32_array(const nvlist_t *nvl, const char *name, size_t maxelems, 2277bb3c927SKristof Provost uint32_t *numbers, size_t *nelems) 2280d6c8174SKristof Provost { 2290d6c8174SKristof Provost const uint64_t *tmp; 2300d6c8174SKristof Provost size_t elems; 2310d6c8174SKristof Provost 2320d6c8174SKristof Provost tmp = nvlist_get_number_array(nvl, name, &elems); 2330d6c8174SKristof Provost 2342b1eb63fSKristof Provost for (size_t i = 0; i < elems && i < maxelems; i++) 2350d6c8174SKristof Provost numbers[i] = tmp[i]; 2360d6c8174SKristof Provost 2370d6c8174SKristof Provost if (nelems) 2380d6c8174SKristof Provost *nelems = elems; 2390d6c8174SKristof Provost } 2400d6c8174SKristof Provost 2410d6c8174SKristof Provost static void 2420d6c8174SKristof Provost pf_nvuint_64_array(const nvlist_t *nvl, const char *name, size_t maxelems, 2437bb3c927SKristof Provost uint64_t *numbers, size_t *nelems) 2440d6c8174SKristof Provost { 2450d6c8174SKristof Provost const uint64_t *tmp; 2460d6c8174SKristof Provost size_t elems; 2470d6c8174SKristof Provost 2480d6c8174SKristof Provost tmp = nvlist_get_number_array(nvl, name, &elems); 2490d6c8174SKristof Provost assert(elems <= maxelems); 2500d6c8174SKristof Provost 2510d6c8174SKristof Provost for (size_t i = 0; i < elems; i++) 2520d6c8174SKristof Provost numbers[i] = tmp[i]; 2530d6c8174SKristof Provost 2540d6c8174SKristof Provost if (nelems) 2550d6c8174SKristof Provost *nelems = elems; 2560d6c8174SKristof Provost } 2570d6c8174SKristof 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 2640d6c8174SKristof 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 }; 3955824df8dSKristof Provost static struct snl_field_parser fp_getstatus[] = {}; 3965824df8dSKristof Provost SNL_DECLARE_PARSER(getstatus_parser, struct genlmsghdr, fp_getstatus, ap_getstatus); 3975824df8dSKristof Provost #undef _OUT 3985824df8dSKristof Provost 3995824df8dSKristof Provost struct pfctl_status * 4005824df8dSKristof Provost pfctl_get_status_h(struct pfctl_handle *h __unused) 4015824df8dSKristof Provost { 4025824df8dSKristof Provost struct pfctl_status *status; 4035824df8dSKristof Provost struct snl_errmsg_data e = {}; 4045824df8dSKristof Provost struct nlmsghdr *hdr; 4055824df8dSKristof Provost struct snl_writer nw; 4065824df8dSKristof Provost uint32_t seq_id; 4075824df8dSKristof Provost int family_id; 4085824df8dSKristof Provost 4095824df8dSKristof Provost family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 4105824df8dSKristof Provost if (family_id == 0) 4115824df8dSKristof Provost return (NULL); 4125824df8dSKristof Provost 4135824df8dSKristof Provost snl_init_writer(&h->ss, &nw); 4145824df8dSKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_GET_STATUS); 4155824df8dSKristof Provost hdr->nlmsg_flags |= NLM_F_DUMP; 4165824df8dSKristof Provost 4175824df8dSKristof Provost hdr = snl_finalize_msg(&nw); 4185824df8dSKristof Provost if (hdr == NULL) { 4195824df8dSKristof Provost return (NULL); 4205824df8dSKristof Provost } 4215824df8dSKristof Provost 4225824df8dSKristof Provost seq_id = hdr->nlmsg_seq; 4235824df8dSKristof Provost if (! snl_send_message(&h->ss, hdr)) 4245824df8dSKristof Provost return (NULL); 4255824df8dSKristof Provost 4265824df8dSKristof Provost status = calloc(1, sizeof(*status)); 4275824df8dSKristof Provost if (status == NULL) 4285824df8dSKristof Provost return (NULL); 4295824df8dSKristof Provost TAILQ_INIT(&status->counters); 4305824df8dSKristof Provost TAILQ_INIT(&status->lcounters); 4315824df8dSKristof Provost TAILQ_INIT(&status->fcounters); 4325824df8dSKristof Provost TAILQ_INIT(&status->scounters); 4335824df8dSKristof Provost 4345824df8dSKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 4355824df8dSKristof Provost if (! snl_parse_nlmsg(&h->ss, hdr, &getstatus_parser, status)) 4365824df8dSKristof Provost continue; 4375824df8dSKristof Provost } 4385824df8dSKristof Provost 4395824df8dSKristof Provost return (status); 4405824df8dSKristof Provost } 4415824df8dSKristof Provost 44246fb68b1SKristof Provost struct pfctl_status * 44346fb68b1SKristof Provost pfctl_get_status(int dev) 44446fb68b1SKristof Provost { 44546fb68b1SKristof Provost struct pfctl_status *status; 44646fb68b1SKristof Provost nvlist_t *nvl; 44746fb68b1SKristof Provost size_t len; 44846fb68b1SKristof Provost const void *chksum; 44946fb68b1SKristof Provost 45046fb68b1SKristof Provost status = calloc(1, sizeof(*status)); 45146fb68b1SKristof Provost if (status == NULL) 45246fb68b1SKristof Provost return (NULL); 45346fb68b1SKristof Provost 4547ed19f5cSKristof Provost nvl = nvlist_create(0); 45546fb68b1SKristof Provost 4567ed19f5cSKristof Provost if (pfctl_do_ioctl(dev, DIOCGETSTATUSNV, 4096, &nvl)) { 457498934c5SKristof Provost nvlist_destroy(nvl); 45846fb68b1SKristof Provost free(status); 45946fb68b1SKristof Provost return (NULL); 46046fb68b1SKristof Provost } 46146fb68b1SKristof Provost 46246fb68b1SKristof Provost status->running = nvlist_get_bool(nvl, "running"); 46346fb68b1SKristof Provost status->since = nvlist_get_number(nvl, "since"); 46446fb68b1SKristof Provost status->debug = nvlist_get_number(nvl, "debug"); 465735748f3SKristof Provost status->hostid = ntohl(nvlist_get_number(nvl, "hostid")); 46646fb68b1SKristof Provost status->states = nvlist_get_number(nvl, "states"); 46746fb68b1SKristof Provost status->src_nodes = nvlist_get_number(nvl, "src_nodes"); 468444a77caSKristof Provost status->syncookies_active = nvlist_get_bool(nvl, "syncookies_active"); 46939282ef3SKajetan Staszkiewicz status->reass = nvlist_get_number(nvl, "reass"); 47046fb68b1SKristof Provost 47146fb68b1SKristof Provost strlcpy(status->ifname, nvlist_get_string(nvl, "ifname"), 47246fb68b1SKristof Provost IFNAMSIZ); 47346fb68b1SKristof Provost chksum = nvlist_get_binary(nvl, "chksum", &len); 47446fb68b1SKristof Provost assert(len == PF_MD5_DIGEST_LENGTH); 47546fb68b1SKristof Provost memcpy(status->pf_chksum, chksum, len); 47646fb68b1SKristof Provost 47746fb68b1SKristof Provost _pfctl_get_status_counters(nvlist_get_nvlist(nvl, "counters"), 47846fb68b1SKristof Provost &status->counters); 47946fb68b1SKristof Provost _pfctl_get_status_counters(nvlist_get_nvlist(nvl, "lcounters"), 48046fb68b1SKristof Provost &status->lcounters); 48146fb68b1SKristof Provost _pfctl_get_status_counters(nvlist_get_nvlist(nvl, "fcounters"), 48246fb68b1SKristof Provost &status->fcounters); 48346fb68b1SKristof Provost _pfctl_get_status_counters(nvlist_get_nvlist(nvl, "scounters"), 48446fb68b1SKristof Provost &status->scounters); 48546fb68b1SKristof Provost 486a3f71765SKristof Provost pf_nvuint_64_array(nvl, "pcounters", 2 * 2 * 2, 48746fb68b1SKristof Provost (uint64_t *)status->pcounters, NULL); 48846fb68b1SKristof Provost pf_nvuint_64_array(nvl, "bcounters", 2 * 2, 48946fb68b1SKristof Provost (uint64_t *)status->bcounters, NULL); 49046fb68b1SKristof Provost 49146fb68b1SKristof Provost nvlist_destroy(nvl); 49246fb68b1SKristof Provost 49346fb68b1SKristof Provost return (status); 49446fb68b1SKristof Provost } 4959dbbe68bSKristof Provost int 4969dbbe68bSKristof Provost pfctl_clear_status(struct pfctl_handle *h) 4979dbbe68bSKristof Provost { 4989dbbe68bSKristof Provost return (pfctl_do_netlink_cmd(h, PFNL_CMD_CLEAR_STATUS)); 4999dbbe68bSKristof Provost } 50046fb68b1SKristof Provost 501e3d3d61aSKristof Provost static uint64_t 502e3d3d61aSKristof Provost _pfctl_status_counter(struct pfctl_status_counters *counters, uint64_t id) 503e3d3d61aSKristof Provost { 504e3d3d61aSKristof Provost struct pfctl_status_counter *c; 505e3d3d61aSKristof Provost 506e3d3d61aSKristof Provost TAILQ_FOREACH(c, counters, entry) { 507e3d3d61aSKristof Provost if (c->id == id) 508e3d3d61aSKristof Provost return (c->counter); 509e3d3d61aSKristof Provost } 510e3d3d61aSKristof Provost 511e3d3d61aSKristof Provost return (0); 512e3d3d61aSKristof Provost } 513e3d3d61aSKristof Provost 514e3d3d61aSKristof Provost uint64_t 515e3d3d61aSKristof Provost pfctl_status_counter(struct pfctl_status *status, int id) 516e3d3d61aSKristof Provost { 517e3d3d61aSKristof Provost return (_pfctl_status_counter(&status->counters, id)); 518e3d3d61aSKristof Provost } 519e3d3d61aSKristof Provost 520e3d3d61aSKristof Provost uint64_t 5211c824f43SKristof Provost pfctl_status_lcounter(struct pfctl_status *status, int id) 5221c824f43SKristof Provost { 5231c824f43SKristof Provost return (_pfctl_status_counter(&status->lcounters, id)); 5241c824f43SKristof Provost } 5251c824f43SKristof Provost 5261c824f43SKristof Provost uint64_t 527e3d3d61aSKristof Provost pfctl_status_fcounter(struct pfctl_status *status, int id) 528e3d3d61aSKristof Provost { 529e3d3d61aSKristof Provost return (_pfctl_status_counter(&status->fcounters, id)); 530e3d3d61aSKristof Provost } 531e3d3d61aSKristof Provost 532e3d3d61aSKristof Provost uint64_t 533e3d3d61aSKristof Provost pfctl_status_scounter(struct pfctl_status *status, int id) 534e3d3d61aSKristof Provost { 535e3d3d61aSKristof Provost return (_pfctl_status_counter(&status->scounters, id)); 536e3d3d61aSKristof Provost } 537e3d3d61aSKristof Provost 53846fb68b1SKristof Provost void 53946fb68b1SKristof Provost pfctl_free_status(struct pfctl_status *status) 54046fb68b1SKristof Provost { 54146fb68b1SKristof Provost struct pfctl_status_counter *c, *tmp; 54246fb68b1SKristof Provost 5430b01878fSKristof Provost if (status == NULL) 5440b01878fSKristof Provost return; 5450b01878fSKristof Provost 54646fb68b1SKristof Provost TAILQ_FOREACH_SAFE(c, &status->counters, entry, tmp) { 54746fb68b1SKristof Provost free(c->name); 54846fb68b1SKristof Provost free(c); 54946fb68b1SKristof Provost } 55046fb68b1SKristof Provost TAILQ_FOREACH_SAFE(c, &status->lcounters, entry, tmp) { 55146fb68b1SKristof Provost free(c->name); 55246fb68b1SKristof Provost free(c); 55346fb68b1SKristof Provost } 55446fb68b1SKristof Provost TAILQ_FOREACH_SAFE(c, &status->fcounters, entry, tmp) { 55546fb68b1SKristof Provost free(c->name); 55646fb68b1SKristof Provost free(c); 55746fb68b1SKristof Provost } 55846fb68b1SKristof Provost TAILQ_FOREACH_SAFE(c, &status->scounters, entry, tmp) { 55946fb68b1SKristof Provost free(c->name); 56046fb68b1SKristof Provost free(c); 56146fb68b1SKristof Provost } 56246fb68b1SKristof Provost 56346fb68b1SKristof Provost free(status); 56446fb68b1SKristof Provost } 56546fb68b1SKristof Provost 56646fb68b1SKristof Provost static void 5670d71f9f3SKristof Provost pfctl_nv_add_addr(nvlist_t *nvparent, const char *name, 5680d71f9f3SKristof Provost const struct pf_addr *addr) 5690d71f9f3SKristof Provost { 5700d71f9f3SKristof Provost nvlist_t *nvl = nvlist_create(0); 5710d71f9f3SKristof Provost 5720d71f9f3SKristof Provost nvlist_add_binary(nvl, "addr", addr, sizeof(*addr)); 5730d71f9f3SKristof Provost 5740d71f9f3SKristof Provost nvlist_add_nvlist(nvparent, name, nvl); 5756dbb729dSKristof Provost nvlist_destroy(nvl); 5760d71f9f3SKristof Provost } 5770d71f9f3SKristof Provost 5780d71f9f3SKristof Provost static void 5790d6c8174SKristof Provost pf_nvaddr_to_addr(const nvlist_t *nvl, struct pf_addr *addr) 5800d6c8174SKristof Provost { 5810d6c8174SKristof Provost size_t len; 5820d6c8174SKristof Provost const void *data; 5830d6c8174SKristof Provost 5840d6c8174SKristof Provost data = nvlist_get_binary(nvl, "addr", &len); 5850d6c8174SKristof Provost assert(len == sizeof(struct pf_addr)); 5860d6c8174SKristof Provost memcpy(addr, data, len); 5870d6c8174SKristof Provost } 5880d6c8174SKristof Provost 5890d6c8174SKristof Provost static void 5900d71f9f3SKristof Provost pfctl_nv_add_addr_wrap(nvlist_t *nvparent, const char *name, 5910d71f9f3SKristof Provost const struct pf_addr_wrap *addr) 5920d71f9f3SKristof Provost { 5930d71f9f3SKristof Provost nvlist_t *nvl = nvlist_create(0); 5940d71f9f3SKristof Provost 5950d71f9f3SKristof Provost nvlist_add_number(nvl, "type", addr->type); 5960d71f9f3SKristof Provost nvlist_add_number(nvl, "iflags", addr->iflags); 597402dfb0aSKristof Provost if (addr->type == PF_ADDR_DYNIFTL) 5980d71f9f3SKristof Provost nvlist_add_string(nvl, "ifname", addr->v.ifname); 599402dfb0aSKristof Provost if (addr->type == PF_ADDR_TABLE) 6000d71f9f3SKristof Provost nvlist_add_string(nvl, "tblname", addr->v.tblname); 6010d71f9f3SKristof Provost pfctl_nv_add_addr(nvl, "addr", &addr->v.a.addr); 6020d71f9f3SKristof Provost pfctl_nv_add_addr(nvl, "mask", &addr->v.a.mask); 6030d71f9f3SKristof Provost 6040d71f9f3SKristof Provost nvlist_add_nvlist(nvparent, name, nvl); 6056dbb729dSKristof Provost nvlist_destroy(nvl); 6060d71f9f3SKristof Provost } 6070d71f9f3SKristof Provost 6080d71f9f3SKristof Provost static void 6090d6c8174SKristof Provost pf_nvaddr_wrap_to_addr_wrap(const nvlist_t *nvl, struct pf_addr_wrap *addr) 6100d6c8174SKristof Provost { 611218a8a49SKristof Provost bzero(addr, sizeof(*addr)); 612218a8a49SKristof Provost 6130d6c8174SKristof Provost addr->type = nvlist_get_number(nvl, "type"); 6140d6c8174SKristof Provost addr->iflags = nvlist_get_number(nvl, "iflags"); 615218a8a49SKristof Provost if (addr->type == PF_ADDR_DYNIFTL) { 616402dfb0aSKristof Provost strlcpy(addr->v.ifname, nvlist_get_string(nvl, "ifname"), 617402dfb0aSKristof Provost IFNAMSIZ); 6182de49deeSKristof Provost addr->p.dyncnt = nvlist_get_number(nvl, "dyncnt"); 619218a8a49SKristof Provost } 620218a8a49SKristof Provost if (addr->type == PF_ADDR_TABLE) { 6210d6c8174SKristof Provost strlcpy(addr->v.tblname, nvlist_get_string(nvl, "tblname"), 6220d6c8174SKristof Provost PF_TABLE_NAME_SIZE); 623218a8a49SKristof Provost addr->p.tblcnt = nvlist_get_number(nvl, "tblcnt"); 624218a8a49SKristof Provost } 6250d6c8174SKristof Provost 6260d6c8174SKristof Provost pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "addr"), &addr->v.a.addr); 6270d6c8174SKristof Provost pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "mask"), &addr->v.a.mask); 6280d6c8174SKristof Provost } 6290d6c8174SKristof Provost 6300d6c8174SKristof Provost static void 6310d71f9f3SKristof Provost pfctl_nv_add_rule_addr(nvlist_t *nvparent, const char *name, 6320d71f9f3SKristof Provost const struct pf_rule_addr *addr) 6330d71f9f3SKristof Provost { 6347bb3c927SKristof Provost uint64_t ports[2]; 6350d71f9f3SKristof Provost nvlist_t *nvl = nvlist_create(0); 6360d71f9f3SKristof Provost 6370d71f9f3SKristof Provost pfctl_nv_add_addr_wrap(nvl, "addr", &addr->addr); 6380d71f9f3SKristof Provost ports[0] = addr->port[0]; 6390d71f9f3SKristof Provost ports[1] = addr->port[1]; 6400d71f9f3SKristof Provost nvlist_add_number_array(nvl, "port", ports, 2); 6410d71f9f3SKristof Provost nvlist_add_number(nvl, "neg", addr->neg); 6420d71f9f3SKristof Provost nvlist_add_number(nvl, "port_op", addr->port_op); 6430d71f9f3SKristof Provost 6440d71f9f3SKristof Provost nvlist_add_nvlist(nvparent, name, nvl); 6456dbb729dSKristof Provost nvlist_destroy(nvl); 6460d71f9f3SKristof Provost } 6470d71f9f3SKristof Provost 6480d71f9f3SKristof Provost static void 6490d6c8174SKristof Provost pf_nvrule_addr_to_rule_addr(const nvlist_t *nvl, struct pf_rule_addr *addr) 6500d6c8174SKristof Provost { 6510d6c8174SKristof Provost pf_nvaddr_wrap_to_addr_wrap(nvlist_get_nvlist(nvl, "addr"), &addr->addr); 6520d6c8174SKristof Provost 6530d6c8174SKristof Provost pf_nvuint_16_array(nvl, "port", 2, addr->port, NULL); 6540d6c8174SKristof Provost addr->neg = nvlist_get_number(nvl, "neg"); 6550d6c8174SKristof Provost addr->port_op = nvlist_get_number(nvl, "port_op"); 6560d6c8174SKristof Provost } 6570d6c8174SKristof Provost 6580d6c8174SKristof Provost static void 6592aa21096SKurosawa Takahiro pf_nvmape_to_mape(const nvlist_t *nvl, struct pf_mape_portset *mape) 6602aa21096SKurosawa Takahiro { 6612aa21096SKurosawa Takahiro mape->offset = nvlist_get_number(nvl, "offset"); 6622aa21096SKurosawa Takahiro mape->psidlen = nvlist_get_number(nvl, "psidlen"); 6632aa21096SKurosawa Takahiro mape->psid = nvlist_get_number(nvl, "psid"); 6642aa21096SKurosawa Takahiro } 6652aa21096SKurosawa Takahiro 6662aa21096SKurosawa Takahiro static void 667600bd6ceSKurosawa Takahiro pf_nvpool_to_pool(const nvlist_t *nvl, struct pfctl_pool *pool) 6680d6c8174SKristof Provost { 6690d6c8174SKristof Provost size_t len; 6700d6c8174SKristof Provost const void *data; 6710d6c8174SKristof Provost 6720d6c8174SKristof Provost data = nvlist_get_binary(nvl, "key", &len); 6730d6c8174SKristof Provost assert(len == sizeof(pool->key)); 6740d6c8174SKristof Provost memcpy(&pool->key, data, len); 6750d6c8174SKristof Provost 6760d6c8174SKristof Provost pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "counter"), &pool->counter); 6770d6c8174SKristof Provost 6780d6c8174SKristof Provost pool->tblidx = nvlist_get_number(nvl, "tblidx"); 6790d6c8174SKristof Provost pf_nvuint_16_array(nvl, "proxy_port", 2, pool->proxy_port, NULL); 6800d6c8174SKristof Provost pool->opts = nvlist_get_number(nvl, "opts"); 6812aa21096SKurosawa Takahiro 6822aa21096SKurosawa Takahiro if (nvlist_exists_nvlist(nvl, "mape")) 6832aa21096SKurosawa Takahiro pf_nvmape_to_mape(nvlist_get_nvlist(nvl, "mape"), &pool->mape); 6840d6c8174SKristof Provost } 6850d6c8174SKristof Provost 6860d6c8174SKristof Provost static void 6870d6c8174SKristof Provost pf_nvrule_uid_to_rule_uid(const nvlist_t *nvl, struct pf_rule_uid *uid) 6880d6c8174SKristof Provost { 6890d6c8174SKristof Provost pf_nvuint_32_array(nvl, "uid", 2, uid->uid, NULL); 6900d6c8174SKristof Provost uid->op = nvlist_get_number(nvl, "op"); 6910d6c8174SKristof Provost } 6920d6c8174SKristof Provost 6930d6c8174SKristof Provost static void 694e9eb0941SKristof Provost pf_nvdivert_to_divert(const nvlist_t *nvl, struct pfctl_rule *rule) 6950d6c8174SKristof Provost { 6960d6c8174SKristof Provost pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "addr"), &rule->divert.addr); 6970d6c8174SKristof Provost rule->divert.port = nvlist_get_number(nvl, "port"); 6980d6c8174SKristof Provost } 6990d6c8174SKristof Provost 7000d6c8174SKristof Provost static void 701e9eb0941SKristof Provost pf_nvrule_to_rule(const nvlist_t *nvl, struct pfctl_rule *rule) 7020d6c8174SKristof Provost { 7030d6c8174SKristof Provost const uint64_t *skip; 7046fcc8e04SKristof Provost const char *const *labels; 7056fcc8e04SKristof Provost size_t skipcount, labelcount; 7060d6c8174SKristof Provost 7070d6c8174SKristof Provost rule->nr = nvlist_get_number(nvl, "nr"); 7080d6c8174SKristof Provost 7090d6c8174SKristof Provost pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "src"), &rule->src); 7100d6c8174SKristof Provost pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "dst"), &rule->dst); 7110d6c8174SKristof Provost 7120d6c8174SKristof Provost skip = nvlist_get_number_array(nvl, "skip", &skipcount); 7130d6c8174SKristof Provost assert(skip); 7140d6c8174SKristof Provost assert(skipcount == PF_SKIP_COUNT); 7150d6c8174SKristof Provost for (int i = 0; i < PF_SKIP_COUNT; i++) 7160d6c8174SKristof Provost rule->skip[i].nr = skip[i]; 7170d6c8174SKristof Provost 7186fcc8e04SKristof Provost labels = nvlist_get_string_array(nvl, "labels", &labelcount); 7196fcc8e04SKristof Provost assert(labelcount <= PF_RULE_MAX_LABEL_COUNT); 7206fcc8e04SKristof Provost for (size_t i = 0; i < labelcount; i++) 7216fcc8e04SKristof Provost strlcpy(rule->label[i], labels[i], PF_RULE_LABEL_SIZE); 72276c5eeccSKristof Provost rule->ridentifier = nvlist_get_number(nvl, "ridentifier"); 7230d6c8174SKristof Provost strlcpy(rule->ifname, nvlist_get_string(nvl, "ifname"), IFNAMSIZ); 7240d6c8174SKristof Provost strlcpy(rule->qname, nvlist_get_string(nvl, "qname"), PF_QNAME_SIZE); 7250d6c8174SKristof Provost strlcpy(rule->pqname, nvlist_get_string(nvl, "pqname"), PF_QNAME_SIZE); 7260d6c8174SKristof Provost strlcpy(rule->tagname, nvlist_get_string(nvl, "tagname"), 7270d6c8174SKristof Provost PF_TAG_NAME_SIZE); 7280d6c8174SKristof Provost strlcpy(rule->match_tagname, nvlist_get_string(nvl, "match_tagname"), 7290d6c8174SKristof Provost PF_TAG_NAME_SIZE); 7300d6c8174SKristof Provost 7310d6c8174SKristof Provost strlcpy(rule->overload_tblname, nvlist_get_string(nvl, "overload_tblname"), 7320d6c8174SKristof Provost PF_TABLE_NAME_SIZE); 7330d6c8174SKristof Provost 7340d6c8174SKristof Provost pf_nvpool_to_pool(nvlist_get_nvlist(nvl, "rpool"), &rule->rpool); 7350d6c8174SKristof Provost 7360d6c8174SKristof Provost rule->evaluations = nvlist_get_number(nvl, "evaluations"); 7370d6c8174SKristof Provost pf_nvuint_64_array(nvl, "packets", 2, rule->packets, NULL); 7380d6c8174SKristof Provost pf_nvuint_64_array(nvl, "bytes", 2, rule->bytes, NULL); 7390d6c8174SKristof Provost 7400abcc1d2SReid Linnemann if (nvlist_exists_number(nvl, "timestamp")) { 7410abcc1d2SReid Linnemann rule->last_active_timestamp = nvlist_get_number(nvl, "timestamp"); 7420abcc1d2SReid Linnemann } 7430abcc1d2SReid Linnemann 7440d6c8174SKristof Provost rule->os_fingerprint = nvlist_get_number(nvl, "os_fingerprint"); 7450d6c8174SKristof Provost 7460d6c8174SKristof Provost rule->rtableid = nvlist_get_number(nvl, "rtableid"); 7470d6c8174SKristof Provost pf_nvuint_32_array(nvl, "timeout", PFTM_MAX, rule->timeout, NULL); 7480d6c8174SKristof Provost rule->max_states = nvlist_get_number(nvl, "max_states"); 7490d6c8174SKristof Provost rule->max_src_nodes = nvlist_get_number(nvl, "max_src_nodes"); 7500d6c8174SKristof Provost rule->max_src_states = nvlist_get_number(nvl, "max_src_states"); 7510d6c8174SKristof Provost rule->max_src_conn = nvlist_get_number(nvl, "max_src_conn"); 7520d6c8174SKristof Provost rule->max_src_conn_rate.limit = 7530d6c8174SKristof Provost nvlist_get_number(nvl, "max_src_conn_rate.limit"); 7540d6c8174SKristof Provost rule->max_src_conn_rate.seconds = 7550d6c8174SKristof Provost nvlist_get_number(nvl, "max_src_conn_rate.seconds"); 7560d6c8174SKristof Provost rule->qid = nvlist_get_number(nvl, "qid"); 7570d6c8174SKristof Provost rule->pqid = nvlist_get_number(nvl, "pqid"); 75863b3c1c7SKristof Provost rule->dnpipe = nvlist_get_number(nvl, "dnpipe"); 75963b3c1c7SKristof Provost rule->dnrpipe = nvlist_get_number(nvl, "dnrpipe"); 76063b3c1c7SKristof Provost rule->free_flags = nvlist_get_number(nvl, "dnflags"); 7610d6c8174SKristof Provost rule->prob = nvlist_get_number(nvl, "prob"); 7620d6c8174SKristof Provost rule->cuid = nvlist_get_number(nvl, "cuid"); 7630d6c8174SKristof Provost rule->cpid = nvlist_get_number(nvl, "cpid"); 7640d6c8174SKristof Provost 7650d6c8174SKristof Provost rule->return_icmp = nvlist_get_number(nvl, "return_icmp"); 7660d6c8174SKristof Provost rule->return_icmp6 = nvlist_get_number(nvl, "return_icmp6"); 7670d6c8174SKristof Provost rule->max_mss = nvlist_get_number(nvl, "max_mss"); 7680d6c8174SKristof Provost rule->scrub_flags = nvlist_get_number(nvl, "scrub_flags"); 7690d6c8174SKristof Provost 7700d6c8174SKristof Provost pf_nvrule_uid_to_rule_uid(nvlist_get_nvlist(nvl, "uid"), &rule->uid); 7710d6c8174SKristof Provost pf_nvrule_uid_to_rule_uid(nvlist_get_nvlist(nvl, "gid"), 7720d6c8174SKristof Provost (struct pf_rule_uid *)&rule->gid); 7730d6c8174SKristof Provost 7740d6c8174SKristof Provost rule->rule_flag = nvlist_get_number(nvl, "rule_flag"); 7750d6c8174SKristof Provost rule->action = nvlist_get_number(nvl, "action"); 7760d6c8174SKristof Provost rule->direction = nvlist_get_number(nvl, "direction"); 7770d6c8174SKristof Provost rule->log = nvlist_get_number(nvl, "log"); 7780d6c8174SKristof Provost rule->logif = nvlist_get_number(nvl, "logif"); 7790d6c8174SKristof Provost rule->quick = nvlist_get_number(nvl, "quick"); 7800d6c8174SKristof Provost rule->ifnot = nvlist_get_number(nvl, "ifnot"); 7810d6c8174SKristof Provost rule->match_tag_not = nvlist_get_number(nvl, "match_tag_not"); 7820d6c8174SKristof Provost rule->natpass = nvlist_get_number(nvl, "natpass"); 7830d6c8174SKristof Provost 7840d6c8174SKristof Provost rule->keep_state = nvlist_get_number(nvl, "keep_state"); 7850d6c8174SKristof Provost rule->af = nvlist_get_number(nvl, "af"); 7860d6c8174SKristof Provost rule->proto = nvlist_get_number(nvl, "proto"); 7870d6c8174SKristof Provost rule->type = nvlist_get_number(nvl, "type"); 7880d6c8174SKristof Provost rule->code = nvlist_get_number(nvl, "code"); 7890d6c8174SKristof Provost rule->flags = nvlist_get_number(nvl, "flags"); 7900d6c8174SKristof Provost rule->flagset = nvlist_get_number(nvl, "flagset"); 7910d6c8174SKristof Provost rule->min_ttl = nvlist_get_number(nvl, "min_ttl"); 7920d6c8174SKristof Provost rule->allow_opts = nvlist_get_number(nvl, "allow_opts"); 7930d6c8174SKristof Provost rule->rt = nvlist_get_number(nvl, "rt"); 7940d6c8174SKristof Provost rule->return_ttl = nvlist_get_number(nvl, "return_ttl"); 7950d6c8174SKristof Provost rule->tos = nvlist_get_number(nvl, "tos"); 7960d6c8174SKristof Provost rule->set_tos = nvlist_get_number(nvl, "set_tos"); 7970d6c8174SKristof Provost rule->anchor_relative = nvlist_get_number(nvl, "anchor_relative"); 7980d6c8174SKristof Provost rule->anchor_wildcard = nvlist_get_number(nvl, "anchor_wildcard"); 7990d6c8174SKristof Provost 8000d6c8174SKristof Provost rule->flush = nvlist_get_number(nvl, "flush"); 8010d6c8174SKristof Provost rule->prio = nvlist_get_number(nvl, "prio"); 8020d6c8174SKristof Provost pf_nvuint_8_array(nvl, "set_prio", 2, rule->set_prio, NULL); 8030d6c8174SKristof Provost 8040d6c8174SKristof Provost pf_nvdivert_to_divert(nvlist_get_nvlist(nvl, "divert"), rule); 8050d6c8174SKristof Provost 806ab5707a5SKristof Provost rule->states_cur = nvlist_get_number(nvl, "states_cur"); 807ab5707a5SKristof Provost rule->states_tot = nvlist_get_number(nvl, "states_tot"); 808ab5707a5SKristof Provost rule->src_nodes = nvlist_get_number(nvl, "src_nodes"); 8090d6c8174SKristof Provost } 8100d6c8174SKristof Provost 8112b29ceb8SKristof Provost static void 8122b29ceb8SKristof Provost pfctl_nveth_addr_to_eth_addr(const nvlist_t *nvl, struct pfctl_eth_addr *addr) 8132b29ceb8SKristof Provost { 814c696d5c7SKristof Provost static const u_int8_t EMPTY_MAC[ETHER_ADDR_LEN] = { 0 }; 8152b29ceb8SKristof Provost size_t len; 8162b29ceb8SKristof Provost const void *data; 8172b29ceb8SKristof Provost 8182b29ceb8SKristof Provost data = nvlist_get_binary(nvl, "addr", &len); 8192b29ceb8SKristof Provost assert(len == sizeof(addr->addr)); 8202b29ceb8SKristof Provost memcpy(addr->addr, data, sizeof(addr->addr)); 8212b29ceb8SKristof Provost 822b590f17aSKristof Provost data = nvlist_get_binary(nvl, "mask", &len); 823b590f17aSKristof Provost assert(len == sizeof(addr->mask)); 824b590f17aSKristof Provost memcpy(addr->mask, data, sizeof(addr->mask)); 825b590f17aSKristof Provost 8262b29ceb8SKristof Provost addr->neg = nvlist_get_bool(nvl, "neg"); 827c696d5c7SKristof Provost 828c696d5c7SKristof Provost /* To make checks for 'is this address set?' easier. */ 829c696d5c7SKristof Provost addr->isset = memcmp(addr->addr, EMPTY_MAC, ETHER_ADDR_LEN) != 0; 8302b29ceb8SKristof Provost } 8312b29ceb8SKristof Provost 8322b29ceb8SKristof Provost static nvlist_t * 8332b29ceb8SKristof Provost pfctl_eth_addr_to_nveth_addr(const struct pfctl_eth_addr *addr) 8342b29ceb8SKristof Provost { 8352b29ceb8SKristof Provost nvlist_t *nvl; 8362b29ceb8SKristof Provost 8372b29ceb8SKristof Provost nvl = nvlist_create(0); 8382b29ceb8SKristof Provost if (nvl == NULL) 8392b29ceb8SKristof Provost return (NULL); 8402b29ceb8SKristof Provost 8412b29ceb8SKristof Provost nvlist_add_bool(nvl, "neg", addr->neg); 8422b29ceb8SKristof Provost nvlist_add_binary(nvl, "addr", &addr->addr, ETHER_ADDR_LEN); 843b590f17aSKristof Provost nvlist_add_binary(nvl, "mask", &addr->mask, ETHER_ADDR_LEN); 8442b29ceb8SKristof Provost 8452b29ceb8SKristof Provost return (nvl); 8462b29ceb8SKristof Provost } 8472b29ceb8SKristof Provost 8482b29ceb8SKristof Provost static void 8492b29ceb8SKristof Provost pfctl_nveth_rule_to_eth_rule(const nvlist_t *nvl, struct pfctl_eth_rule *rule) 8502b29ceb8SKristof Provost { 851ef661d4aSChristian McDonald const char *const *labels; 852ef661d4aSChristian McDonald size_t labelcount, i; 853ef661d4aSChristian McDonald 8542b29ceb8SKristof Provost rule->nr = nvlist_get_number(nvl, "nr"); 8552b29ceb8SKristof Provost rule->quick = nvlist_get_bool(nvl, "quick"); 8562b29ceb8SKristof Provost strlcpy(rule->ifname, nvlist_get_string(nvl, "ifname"), IFNAMSIZ); 8572b29ceb8SKristof Provost rule->ifnot = nvlist_get_bool(nvl, "ifnot"); 8582b29ceb8SKristof Provost rule->direction = nvlist_get_number(nvl, "direction"); 8592b29ceb8SKristof Provost rule->proto = nvlist_get_number(nvl, "proto"); 8601f61367fSKristof Provost strlcpy(rule->match_tagname, nvlist_get_string(nvl, "match_tagname"), 8611f61367fSKristof Provost PF_TAG_NAME_SIZE); 8621f61367fSKristof Provost rule->match_tag = nvlist_get_number(nvl, "match_tag"); 8631f61367fSKristof Provost rule->match_tag_not = nvlist_get_bool(nvl, "match_tag_not"); 8642b29ceb8SKristof Provost 865ef661d4aSChristian McDonald labels = nvlist_get_string_array(nvl, "labels", &labelcount); 866ef661d4aSChristian McDonald assert(labelcount <= PF_RULE_MAX_LABEL_COUNT); 867ef661d4aSChristian McDonald for (i = 0; i < labelcount; i++) 868ef661d4aSChristian McDonald strlcpy(rule->label[i], labels[i], PF_RULE_LABEL_SIZE); 869ef661d4aSChristian McDonald rule->ridentifier = nvlist_get_number(nvl, "ridentifier"); 870ef661d4aSChristian McDonald 8712b29ceb8SKristof Provost pfctl_nveth_addr_to_eth_addr(nvlist_get_nvlist(nvl, "src"), 8722b29ceb8SKristof Provost &rule->src); 8732b29ceb8SKristof Provost pfctl_nveth_addr_to_eth_addr(nvlist_get_nvlist(nvl, "dst"), 8742b29ceb8SKristof Provost &rule->dst); 8752b29ceb8SKristof Provost 8768a42005dSKristof Provost pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "ipsrc"), 8778a42005dSKristof Provost &rule->ipsrc); 8788a42005dSKristof Provost pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "ipdst"), 8798a42005dSKristof Provost &rule->ipdst); 8808a42005dSKristof Provost 8812b29ceb8SKristof Provost rule->evaluations = nvlist_get_number(nvl, "evaluations"); 8822b29ceb8SKristof Provost rule->packets[0] = nvlist_get_number(nvl, "packets-in"); 8832b29ceb8SKristof Provost rule->packets[1] = nvlist_get_number(nvl, "packets-out"); 8842b29ceb8SKristof Provost rule->bytes[0] = nvlist_get_number(nvl, "bytes-in"); 8852b29ceb8SKristof Provost rule->bytes[1] = nvlist_get_number(nvl, "bytes-out"); 8862b29ceb8SKristof Provost 8870abcc1d2SReid Linnemann if (nvlist_exists_number(nvl, "timestamp")) { 8880abcc1d2SReid Linnemann rule->last_active_timestamp = nvlist_get_number(nvl, "timestamp"); 8890abcc1d2SReid Linnemann } 8900abcc1d2SReid Linnemann 8912b29ceb8SKristof Provost strlcpy(rule->qname, nvlist_get_string(nvl, "qname"), PF_QNAME_SIZE); 8922b29ceb8SKristof Provost strlcpy(rule->tagname, nvlist_get_string(nvl, "tagname"), 8932b29ceb8SKristof Provost PF_TAG_NAME_SIZE); 8942b29ceb8SKristof Provost 895fb330f39SKristof Provost rule->dnpipe = nvlist_get_number(nvl, "dnpipe"); 896fb330f39SKristof Provost rule->dnflags = nvlist_get_number(nvl, "dnflags"); 897fb330f39SKristof Provost 898c5131afeSKristof Provost rule->anchor_relative = nvlist_get_number(nvl, "anchor_relative"); 899c5131afeSKristof Provost rule->anchor_wildcard = nvlist_get_number(nvl, "anchor_wildcard"); 900c5131afeSKristof Provost 9018a8af942SKristof Provost strlcpy(rule->bridge_to, nvlist_get_string(nvl, "bridge_to"), 9028a8af942SKristof Provost IFNAMSIZ); 9038a8af942SKristof Provost 9042b29ceb8SKristof Provost rule->action = nvlist_get_number(nvl, "action"); 9052b29ceb8SKristof Provost } 9062b29ceb8SKristof Provost 9072b29ceb8SKristof Provost int 9089bb06778SKristof Provost pfctl_get_eth_rulesets_info(int dev, struct pfctl_eth_rulesets_info *ri, 9099bb06778SKristof Provost const char *path) 9109bb06778SKristof Provost { 9119bb06778SKristof Provost nvlist_t *nvl; 9127ed19f5cSKristof Provost int ret; 9139bb06778SKristof Provost 9149bb06778SKristof Provost bzero(ri, sizeof(*ri)); 9159bb06778SKristof Provost 9169bb06778SKristof Provost nvl = nvlist_create(0); 9179bb06778SKristof Provost nvlist_add_string(nvl, "path", path); 9189bb06778SKristof Provost 9197ed19f5cSKristof Provost if ((ret = pfctl_do_ioctl(dev, DIOCGETETHRULESETS, 256, &nvl)) != 0) 920498934c5SKristof Provost goto out; 9219bb06778SKristof Provost 9229bb06778SKristof Provost ri->nr = nvlist_get_number(nvl, "nr"); 9239bb06778SKristof Provost 924498934c5SKristof Provost out: 9259bb06778SKristof Provost nvlist_destroy(nvl); 926498934c5SKristof Provost return (ret); 9279bb06778SKristof Provost } 9289bb06778SKristof Provost 9299bb06778SKristof Provost int 9309bb06778SKristof Provost pfctl_get_eth_ruleset(int dev, const char *path, int nr, 9319bb06778SKristof Provost struct pfctl_eth_ruleset_info *ri) 9329bb06778SKristof Provost { 9339bb06778SKristof Provost nvlist_t *nvl; 9347ed19f5cSKristof Provost int ret; 9359bb06778SKristof Provost 9369bb06778SKristof Provost bzero(ri, sizeof(*ri)); 9379bb06778SKristof Provost 9389bb06778SKristof Provost nvl = nvlist_create(0); 9399bb06778SKristof Provost nvlist_add_string(nvl, "path", path); 9409bb06778SKristof Provost nvlist_add_number(nvl, "nr", nr); 9419bb06778SKristof Provost 9427ed19f5cSKristof Provost if ((ret = pfctl_do_ioctl(dev, DIOCGETETHRULESET, 1024, &nvl)) != 0) 943498934c5SKristof Provost goto out; 9449bb06778SKristof Provost 9459bb06778SKristof Provost ri->nr = nvlist_get_number(nvl, "nr"); 9469bb06778SKristof Provost strlcpy(ri->path, nvlist_get_string(nvl, "path"), MAXPATHLEN); 9479bb06778SKristof Provost strlcpy(ri->name, nvlist_get_string(nvl, "name"), 9489bb06778SKristof Provost PF_ANCHOR_NAME_SIZE); 9499bb06778SKristof Provost 950498934c5SKristof Provost out: 9514abc3b48SKristof Provost nvlist_destroy(nvl); 952498934c5SKristof Provost return (ret); 9539bb06778SKristof Provost } 9549bb06778SKristof Provost 9559bb06778SKristof Provost int 956c5131afeSKristof Provost pfctl_get_eth_rules_info(int dev, struct pfctl_eth_rules_info *rules, 957c5131afeSKristof Provost const char *path) 9582b29ceb8SKristof Provost { 9592b29ceb8SKristof Provost nvlist_t *nvl; 9607ed19f5cSKristof Provost int ret; 9612b29ceb8SKristof Provost 9622b29ceb8SKristof Provost bzero(rules, sizeof(*rules)); 9632b29ceb8SKristof Provost 964c5131afeSKristof Provost nvl = nvlist_create(0); 965c5131afeSKristof Provost nvlist_add_string(nvl, "anchor", path); 966c5131afeSKristof Provost 9677ed19f5cSKristof Provost if ((ret = pfctl_do_ioctl(dev, DIOCGETETHRULES, 1024, &nvl)) != 0) 968498934c5SKristof Provost goto out; 9692b29ceb8SKristof Provost 9702b29ceb8SKristof Provost rules->nr = nvlist_get_number(nvl, "nr"); 9712b29ceb8SKristof Provost rules->ticket = nvlist_get_number(nvl, "ticket"); 9722b29ceb8SKristof Provost 973498934c5SKristof Provost out: 9742b29ceb8SKristof Provost nvlist_destroy(nvl); 975498934c5SKristof Provost return (ret); 9762b29ceb8SKristof Provost } 9772b29ceb8SKristof Provost 9782b29ceb8SKristof Provost int 9792b29ceb8SKristof Provost pfctl_get_eth_rule(int dev, uint32_t nr, uint32_t ticket, 980c5131afeSKristof Provost const char *path, struct pfctl_eth_rule *rule, bool clear, 981c5131afeSKristof Provost char *anchor_call) 9822b29ceb8SKristof Provost { 9832b29ceb8SKristof Provost nvlist_t *nvl; 9847ed19f5cSKristof Provost int ret; 9852b29ceb8SKristof Provost 9862b29ceb8SKristof Provost nvl = nvlist_create(0); 9872b29ceb8SKristof Provost 988c5131afeSKristof Provost nvlist_add_string(nvl, "anchor", path); 9892b29ceb8SKristof Provost nvlist_add_number(nvl, "ticket", ticket); 9902b29ceb8SKristof Provost nvlist_add_number(nvl, "nr", nr); 9912b29ceb8SKristof Provost nvlist_add_bool(nvl, "clear", clear); 9922b29ceb8SKristof Provost 9930abcc1d2SReid Linnemann if ((ret = pfctl_do_ioctl(dev, DIOCGETETHRULE, 4096, &nvl)) != 0) 994498934c5SKristof Provost goto out; 9952b29ceb8SKristof Provost 9962b29ceb8SKristof Provost pfctl_nveth_rule_to_eth_rule(nvl, rule); 9972b29ceb8SKristof Provost 998c5131afeSKristof Provost if (anchor_call) 999c5131afeSKristof Provost strlcpy(anchor_call, nvlist_get_string(nvl, "anchor_call"), 1000c5131afeSKristof Provost MAXPATHLEN); 1001c5131afeSKristof Provost 1002498934c5SKristof Provost out: 10032b29ceb8SKristof Provost nvlist_destroy(nvl); 1004498934c5SKristof Provost return (ret); 10052b29ceb8SKristof Provost } 10062b29ceb8SKristof Provost 10072b29ceb8SKristof Provost int 1008c5131afeSKristof Provost pfctl_add_eth_rule(int dev, const struct pfctl_eth_rule *r, const char *anchor, 1009c5131afeSKristof Provost const char *anchor_call, uint32_t ticket) 10102b29ceb8SKristof Provost { 10112b29ceb8SKristof Provost struct pfioc_nv nv; 10122b29ceb8SKristof Provost nvlist_t *nvl, *addr; 10132b29ceb8SKristof Provost void *packed; 1014514039bbSKristof Provost int error = 0; 1015ef661d4aSChristian McDonald size_t labelcount, size; 10162b29ceb8SKristof Provost 10172b29ceb8SKristof Provost nvl = nvlist_create(0); 10182b29ceb8SKristof Provost 10192b29ceb8SKristof Provost nvlist_add_number(nvl, "ticket", ticket); 1020c5131afeSKristof Provost nvlist_add_string(nvl, "anchor", anchor); 1021c5131afeSKristof Provost nvlist_add_string(nvl, "anchor_call", anchor_call); 10222b29ceb8SKristof Provost 10232b29ceb8SKristof Provost nvlist_add_number(nvl, "nr", r->nr); 10242b29ceb8SKristof Provost nvlist_add_bool(nvl, "quick", r->quick); 10252b29ceb8SKristof Provost nvlist_add_string(nvl, "ifname", r->ifname); 10262b29ceb8SKristof Provost nvlist_add_bool(nvl, "ifnot", r->ifnot); 10272b29ceb8SKristof Provost nvlist_add_number(nvl, "direction", r->direction); 10282b29ceb8SKristof Provost nvlist_add_number(nvl, "proto", r->proto); 10291f61367fSKristof Provost nvlist_add_string(nvl, "match_tagname", r->match_tagname); 10301f61367fSKristof Provost nvlist_add_bool(nvl, "match_tag_not", r->match_tag_not); 10312b29ceb8SKristof Provost 10322b29ceb8SKristof Provost addr = pfctl_eth_addr_to_nveth_addr(&r->src); 10332b29ceb8SKristof Provost if (addr == NULL) { 10342b29ceb8SKristof Provost nvlist_destroy(nvl); 10352b29ceb8SKristof Provost return (ENOMEM); 10362b29ceb8SKristof Provost } 10372b29ceb8SKristof Provost nvlist_add_nvlist(nvl, "src", addr); 10382b29ceb8SKristof Provost nvlist_destroy(addr); 10392b29ceb8SKristof Provost 10402b29ceb8SKristof Provost addr = pfctl_eth_addr_to_nveth_addr(&r->dst); 10412b29ceb8SKristof Provost if (addr == NULL) { 10422b29ceb8SKristof Provost nvlist_destroy(nvl); 10432b29ceb8SKristof Provost return (ENOMEM); 10442b29ceb8SKristof Provost } 10452b29ceb8SKristof Provost nvlist_add_nvlist(nvl, "dst", addr); 10462b29ceb8SKristof Provost nvlist_destroy(addr); 10472b29ceb8SKristof Provost 10488a42005dSKristof Provost pfctl_nv_add_rule_addr(nvl, "ipsrc", &r->ipsrc); 10498a42005dSKristof Provost pfctl_nv_add_rule_addr(nvl, "ipdst", &r->ipdst); 10508a42005dSKristof Provost 1051ef661d4aSChristian McDonald labelcount = 0; 10524abc3b48SKristof Provost while (labelcount < PF_RULE_MAX_LABEL_COUNT && 10534abc3b48SKristof Provost r->label[labelcount][0] != 0) { 1054ef661d4aSChristian McDonald nvlist_append_string_array(nvl, "labels", 1055ef661d4aSChristian McDonald r->label[labelcount]); 1056ef661d4aSChristian McDonald labelcount++; 1057ef661d4aSChristian McDonald } 1058ef661d4aSChristian McDonald nvlist_add_number(nvl, "ridentifier", r->ridentifier); 1059ef661d4aSChristian McDonald 10602b29ceb8SKristof Provost nvlist_add_string(nvl, "qname", r->qname); 10612b29ceb8SKristof Provost nvlist_add_string(nvl, "tagname", r->tagname); 1062fb330f39SKristof Provost nvlist_add_number(nvl, "dnpipe", r->dnpipe); 1063fb330f39SKristof Provost nvlist_add_number(nvl, "dnflags", r->dnflags); 1064fb330f39SKristof Provost 10658a8af942SKristof Provost nvlist_add_string(nvl, "bridge_to", r->bridge_to); 10668a8af942SKristof Provost 10672b29ceb8SKristof Provost nvlist_add_number(nvl, "action", r->action); 10682b29ceb8SKristof Provost 10692b29ceb8SKristof Provost packed = nvlist_pack(nvl, &size); 10702b29ceb8SKristof Provost if (packed == NULL) { 10712b29ceb8SKristof Provost nvlist_destroy(nvl); 10722b29ceb8SKristof Provost return (ENOMEM); 10732b29ceb8SKristof Provost } 10742b29ceb8SKristof Provost 10752b29ceb8SKristof Provost nv.len = size; 10762b29ceb8SKristof Provost nv.size = size; 10772b29ceb8SKristof Provost nv.data = packed; 10782b29ceb8SKristof Provost 1079514039bbSKristof Provost if (ioctl(dev, DIOCADDETHRULE, &nv) != 0) 1080514039bbSKristof Provost error = errno; 10812b29ceb8SKristof Provost 10822b29ceb8SKristof Provost free(packed); 10832b29ceb8SKristof Provost nvlist_destroy(nvl); 10842b29ceb8SKristof Provost 10852b29ceb8SKristof Provost return (error); 10862b29ceb8SKristof Provost } 10872b29ceb8SKristof Provost 1088ffbf2595SKristof Provost static void 1089ffbf2595SKristof Provost snl_add_msg_attr_addr_wrap(struct snl_writer *nw, uint32_t type, const struct pf_addr_wrap *addr) 1090ffbf2595SKristof Provost { 1091ffbf2595SKristof Provost int off; 1092ffbf2595SKristof Provost 1093ffbf2595SKristof Provost off = snl_add_msg_attr_nested(nw, type); 1094ffbf2595SKristof Provost 1095ffbf2595SKristof Provost snl_add_msg_attr_ip6(nw, PF_AT_ADDR, &addr->v.a.addr.v6); 1096ffbf2595SKristof Provost snl_add_msg_attr_ip6(nw, PF_AT_MASK, &addr->v.a.mask.v6); 1097ffbf2595SKristof Provost 1098ffbf2595SKristof Provost if (addr->type == PF_ADDR_DYNIFTL) 1099ffbf2595SKristof Provost snl_add_msg_attr_string(nw, PF_AT_IFNAME, addr->v.ifname); 1100ffbf2595SKristof Provost if (addr->type == PF_ADDR_TABLE) 1101ffbf2595SKristof Provost snl_add_msg_attr_string(nw, PF_AT_TABLENAME, addr->v.tblname); 1102ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_AT_TYPE, addr->type); 1103ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_AT_IFLAGS, addr->iflags); 1104ffbf2595SKristof Provost 1105ffbf2595SKristof Provost snl_end_attr_nested(nw, off); 1106ffbf2595SKristof Provost } 1107ffbf2595SKristof Provost 1108ffbf2595SKristof Provost static void 1109d909f06bSKristof Provost snl_add_msg_attr_pool_addr(struct snl_writer *nw, uint32_t type, const struct pf_pooladdr *pa) 1110d909f06bSKristof Provost { 1111d909f06bSKristof Provost int off; 1112d909f06bSKristof Provost 1113d909f06bSKristof Provost off = snl_add_msg_attr_nested(nw, type); 1114d909f06bSKristof Provost 1115d909f06bSKristof Provost snl_add_msg_attr_string(nw, PF_PA_IFNAME, pa->ifname); 1116d909f06bSKristof Provost snl_add_msg_attr_addr_wrap(nw, PF_PA_ADDR, &pa->addr); 1117d909f06bSKristof Provost 1118d909f06bSKristof Provost snl_end_attr_nested(nw, off); 1119d909f06bSKristof Provost } 1120d909f06bSKristof Provost 1121d909f06bSKristof Provost static void 1122ffbf2595SKristof Provost snl_add_msg_attr_rule_addr(struct snl_writer *nw, uint32_t type, const struct pf_rule_addr *addr) 1123ffbf2595SKristof Provost { 1124ffbf2595SKristof Provost int off; 1125ffbf2595SKristof Provost 1126ffbf2595SKristof Provost off = snl_add_msg_attr_nested(nw, type); 1127ffbf2595SKristof Provost 1128ffbf2595SKristof Provost snl_add_msg_attr_addr_wrap(nw, PF_RAT_ADDR, &addr->addr); 1129ffbf2595SKristof Provost snl_add_msg_attr_u16(nw, PF_RAT_SRC_PORT, addr->port[0]); 1130ffbf2595SKristof Provost snl_add_msg_attr_u16(nw, PF_RAT_DST_PORT, addr->port[1]); 1131ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RAT_NEG, addr->neg); 1132ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RAT_OP, addr->port_op); 1133ffbf2595SKristof Provost 1134ffbf2595SKristof Provost snl_end_attr_nested(nw, off); 1135ffbf2595SKristof Provost } 1136ffbf2595SKristof Provost 1137ffbf2595SKristof Provost static void 1138ffbf2595SKristof 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]) 1139ffbf2595SKristof Provost { 1140ffbf2595SKristof Provost int off, i = 0; 1141ffbf2595SKristof Provost 1142ffbf2595SKristof Provost off = snl_add_msg_attr_nested(nw, type); 1143ffbf2595SKristof Provost 1144306d3fb2SKristof Provost while (i < PF_RULE_MAX_LABEL_COUNT && 1145306d3fb2SKristof Provost labels[i][0] != 0) { 1146ffbf2595SKristof Provost snl_add_msg_attr_string(nw, PF_LT_LABEL, labels[i]); 1147ffbf2595SKristof Provost i++; 1148ffbf2595SKristof Provost } 1149ffbf2595SKristof Provost 1150ffbf2595SKristof Provost snl_end_attr_nested(nw, off); 1151ffbf2595SKristof Provost } 1152ffbf2595SKristof Provost 1153ffbf2595SKristof Provost static void 1154ffbf2595SKristof Provost snl_add_msg_attr_mape(struct snl_writer *nw, uint32_t type, const struct pf_mape_portset *me) 1155ffbf2595SKristof Provost { 1156ffbf2595SKristof Provost int off; 1157ffbf2595SKristof Provost 1158ffbf2595SKristof Provost off = snl_add_msg_attr_nested(nw, type); 1159ffbf2595SKristof Provost 1160ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_MET_OFFSET, me->offset); 1161ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_MET_PSID_LEN, me->psidlen); 1162ffbf2595SKristof Provost snl_add_msg_attr_u16(nw, PF_MET_PSID, me->psid); 1163ffbf2595SKristof Provost 1164ffbf2595SKristof Provost snl_end_attr_nested(nw, off); 1165ffbf2595SKristof Provost } 1166ffbf2595SKristof Provost 1167ffbf2595SKristof Provost static void 1168ffbf2595SKristof Provost snl_add_msg_attr_rpool(struct snl_writer *nw, uint32_t type, const struct pfctl_pool *pool) 1169ffbf2595SKristof Provost { 1170ffbf2595SKristof Provost int off; 1171ffbf2595SKristof Provost 1172ffbf2595SKristof Provost off = snl_add_msg_attr_nested(nw, type); 1173ffbf2595SKristof Provost 1174ffbf2595SKristof Provost snl_add_msg_attr(nw, PF_PT_KEY, sizeof(pool->key), &pool->key); 1175ffbf2595SKristof Provost snl_add_msg_attr_ip6(nw, PF_PT_COUNTER, &pool->counter.v6); 1176ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_PT_TBLIDX, pool->tblidx); 1177ffbf2595SKristof Provost snl_add_msg_attr_u16(nw, PF_PT_PROXY_SRC_PORT, pool->proxy_port[0]); 1178ffbf2595SKristof Provost snl_add_msg_attr_u16(nw, PF_PT_PROXY_DST_PORT, pool->proxy_port[1]); 1179ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_PT_OPTS, pool->opts); 1180ffbf2595SKristof Provost snl_add_msg_attr_mape(nw, PF_PT_MAPE, &pool->mape); 1181ffbf2595SKristof Provost 1182ffbf2595SKristof Provost snl_end_attr_nested(nw, off); 1183ffbf2595SKristof Provost } 1184ffbf2595SKristof Provost 1185ffbf2595SKristof Provost static void 1186ffbf2595SKristof Provost snl_add_msg_attr_timeouts(struct snl_writer *nw, uint32_t type, const uint32_t *timeouts) 1187ffbf2595SKristof Provost { 1188ffbf2595SKristof Provost int off; 1189ffbf2595SKristof Provost 1190ffbf2595SKristof Provost off = snl_add_msg_attr_nested(nw, type); 1191ffbf2595SKristof Provost 1192ffbf2595SKristof Provost for (int i = 0; i < PFTM_MAX; i++) 1193ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_TT_TIMEOUT, timeouts[i]); 1194ffbf2595SKristof Provost 1195ffbf2595SKristof Provost snl_end_attr_nested(nw, off); 1196ffbf2595SKristof Provost } 1197ffbf2595SKristof Provost 1198ffbf2595SKristof Provost static void 1199ffbf2595SKristof Provost snl_add_msg_attr_uid(struct snl_writer *nw, uint32_t type, const struct pf_rule_uid *uid) 1200ffbf2595SKristof Provost { 1201ffbf2595SKristof Provost int off; 1202ffbf2595SKristof Provost 1203ffbf2595SKristof Provost off = snl_add_msg_attr_nested(nw, type); 1204ffbf2595SKristof Provost 1205ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_RUT_UID_LOW, uid->uid[0]); 1206ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_RUT_UID_HIGH, uid->uid[1]); 1207ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RUT_OP, uid->op); 1208ffbf2595SKristof Provost 1209ffbf2595SKristof Provost snl_end_attr_nested(nw, off); 1210ffbf2595SKristof Provost } 1211ffbf2595SKristof Provost 1212ffbf2595SKristof Provost static void 1213ffbf2595SKristof Provost snl_add_msg_attr_pf_rule(struct snl_writer *nw, uint32_t type, const struct pfctl_rule *r) 1214ffbf2595SKristof Provost { 1215ffbf2595SKristof Provost int off; 1216ffbf2595SKristof Provost 1217ffbf2595SKristof Provost off = snl_add_msg_attr_nested(nw, type); 1218ffbf2595SKristof Provost 1219ffbf2595SKristof Provost snl_add_msg_attr_rule_addr(nw, PF_RT_SRC, &r->src); 1220ffbf2595SKristof Provost snl_add_msg_attr_rule_addr(nw, PF_RT_DST, &r->dst); 1221ffbf2595SKristof Provost snl_add_msg_attr_rule_labels(nw, PF_RT_LABELS, r->label); 1222ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_RT_RIDENTIFIER, r->ridentifier); 1223ffbf2595SKristof Provost snl_add_msg_attr_string(nw, PF_RT_IFNAME, r->ifname); 1224ffbf2595SKristof Provost snl_add_msg_attr_string(nw, PF_RT_QNAME, r->qname); 1225ffbf2595SKristof Provost snl_add_msg_attr_string(nw, PF_RT_PQNAME, r->pqname); 1226ffbf2595SKristof Provost snl_add_msg_attr_string(nw, PF_RT_TAGNAME, r->tagname); 1227ffbf2595SKristof Provost snl_add_msg_attr_string(nw, PF_RT_MATCH_TAGNAME, r->match_tagname); 1228ffbf2595SKristof Provost snl_add_msg_attr_string(nw, PF_RT_OVERLOAD_TBLNAME, r->overload_tblname); 1229ffbf2595SKristof Provost snl_add_msg_attr_rpool(nw, PF_RT_RPOOL, &r->rpool); 1230ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_RT_OS_FINGERPRINT, r->os_fingerprint); 1231ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_RT_RTABLEID, r->rtableid); 1232ffbf2595SKristof Provost snl_add_msg_attr_timeouts(nw, PF_RT_TIMEOUT, r->timeout); 1233ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_RT_MAX_STATES, r->max_states); 1234ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_RT_MAX_SRC_NODES, r->max_src_nodes); 1235ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_RT_MAX_SRC_STATES, r->max_src_states); 1236*7fe42038SKajetan Staszkiewicz snl_add_msg_attr_u32(nw, PF_RT_MAX_SRC_CONN, r->max_src_conn); 1237ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_RT_MAX_SRC_CONN_RATE_LIMIT, r->max_src_conn_rate.limit); 1238ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_RT_MAX_SRC_CONN_RATE_SECS, r->max_src_conn_rate.seconds); 1239ffbf2595SKristof Provost 1240ffbf2595SKristof Provost snl_add_msg_attr_u16(nw, PF_RT_DNPIPE, r->dnpipe); 1241ffbf2595SKristof Provost snl_add_msg_attr_u16(nw, PF_RT_DNRPIPE, r->dnrpipe); 1242ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_RT_DNFLAGS, r->free_flags); 1243ffbf2595SKristof Provost 1244ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_RT_NR, r->nr); 1245ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_RT_PROB, r->prob); 1246ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_RT_CUID, r->cuid); 1247ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_RT_CPID, r->cpid); 1248ffbf2595SKristof Provost 1249ffbf2595SKristof Provost snl_add_msg_attr_u16(nw, PF_RT_RETURN_ICMP, r->return_icmp); 1250ffbf2595SKristof Provost snl_add_msg_attr_u16(nw, PF_RT_RETURN_ICMP6, r->return_icmp6); 1251ffbf2595SKristof Provost snl_add_msg_attr_u16(nw, PF_RT_MAX_MSS, r->max_mss); 1252ffbf2595SKristof Provost snl_add_msg_attr_u16(nw, PF_RT_SCRUB_FLAGS, r->scrub_flags); 1253ffbf2595SKristof Provost 1254ffbf2595SKristof Provost snl_add_msg_attr_uid(nw, PF_RT_UID, &r->uid); 1255ffbf2595SKristof Provost snl_add_msg_attr_uid(nw, PF_RT_GID, (const struct pf_rule_uid *)&r->gid); 12562339ead6SKristof Provost snl_add_msg_attr_string(nw, PF_RT_RCV_IFNAME, r->rcv_ifname); 1257ffbf2595SKristof Provost 1258ffbf2595SKristof Provost snl_add_msg_attr_u32(nw, PF_RT_RULE_FLAG, r->rule_flag); 1259ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_ACTION, r->action); 1260ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_DIRECTION, r->direction); 1261ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_LOG, r->log); 1262ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_LOGIF, r->logif); 1263ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_QUICK, r->quick); 1264ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_IF_NOT, r->ifnot); 1265ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_MATCH_TAG_NOT, r->match_tag_not); 1266ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_NATPASS, r->natpass); 1267ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_KEEP_STATE, r->keep_state); 1268ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_AF, r->af); 1269ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_PROTO, r->proto); 1270ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_TYPE, r->type); 1271ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_CODE, r->code); 1272ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_FLAGS, r->flags); 1273ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_FLAGSET, r->flagset); 1274ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_MIN_TTL, r->min_ttl); 1275ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_ALLOW_OPTS, r->allow_opts); 1276ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_RT, r->rt); 1277ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_RETURN_TTL, r->return_ttl); 1278ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_TOS, r->tos); 1279ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_SET_TOS, r->set_tos); 1280ffbf2595SKristof Provost 1281ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_ANCHOR_RELATIVE, r->anchor_relative); 1282ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_ANCHOR_WILDCARD, r->anchor_wildcard); 1283ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_FLUSH, r->flush); 1284ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_PRIO, r->prio); 1285ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_SET_PRIO, r->set_prio[0]); 1286ffbf2595SKristof Provost snl_add_msg_attr_u8(nw, PF_RT_SET_PRIO_REPLY, r->set_prio[1]); 1287ffbf2595SKristof Provost 1288ffbf2595SKristof Provost snl_add_msg_attr_ip6(nw, PF_RT_DIVERT_ADDRESS, &r->divert.addr.v6); 1289ffbf2595SKristof Provost snl_add_msg_attr_u16(nw, PF_RT_DIVERT_PORT, r->divert.port); 1290ffbf2595SKristof Provost 1291ffbf2595SKristof Provost snl_end_attr_nested(nw, off); 1292ffbf2595SKristof Provost } 1293ffbf2595SKristof Provost 12940d71f9f3SKristof Provost int 1295ffbf2595SKristof Provost pfctl_add_rule(int dev __unused, const struct pfctl_rule *r, const char *anchor, 12967bb3c927SKristof Provost const char *anchor_call, uint32_t ticket, uint32_t pool_ticket) 12970d71f9f3SKristof Provost { 1298324fd7ecSKristof Provost struct pfctl_handle *h; 1299324fd7ecSKristof Provost int ret; 1300324fd7ecSKristof Provost 1301324fd7ecSKristof Provost h = pfctl_open(PF_DEVICE); 1302324fd7ecSKristof Provost if (h == NULL) 1303324fd7ecSKristof Provost return (ENODEV); 1304324fd7ecSKristof Provost 1305324fd7ecSKristof Provost ret = pfctl_add_rule_h(h, r, anchor, anchor_call, ticket, pool_ticket); 1306324fd7ecSKristof Provost 1307324fd7ecSKristof Provost pfctl_close(h); 1308324fd7ecSKristof Provost 1309324fd7ecSKristof Provost return (ret); 1310324fd7ecSKristof Provost } 1311324fd7ecSKristof Provost 1312324fd7ecSKristof Provost int 1313324fd7ecSKristof Provost pfctl_add_rule_h(struct pfctl_handle *h, const struct pfctl_rule *r, 1314324fd7ecSKristof Provost const char *anchor, const char *anchor_call, uint32_t ticket, 1315324fd7ecSKristof Provost uint32_t pool_ticket) 1316324fd7ecSKristof Provost { 1317ffbf2595SKristof Provost struct snl_writer nw; 1318ffbf2595SKristof Provost struct snl_errmsg_data e = {}; 1319ffbf2595SKristof Provost struct nlmsghdr *hdr; 1320ffbf2595SKristof Provost uint32_t seq_id; 1321ffbf2595SKristof Provost int family_id; 13220d71f9f3SKristof Provost 1323324fd7ecSKristof Provost family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 1324497ccc21SKristof Provost if (family_id == 0) 1325497ccc21SKristof Provost return (ENOTSUP); 13260d71f9f3SKristof Provost 1327324fd7ecSKristof Provost snl_init_writer(&h->ss, &nw); 1328ffbf2595SKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_ADDRULE); 1329ffbf2595SKristof Provost hdr->nlmsg_flags |= NLM_F_DUMP; 1330ffbf2595SKristof Provost snl_add_msg_attr_u32(&nw, PF_ART_TICKET, ticket); 1331ffbf2595SKristof Provost snl_add_msg_attr_u32(&nw, PF_ART_POOL_TICKET, pool_ticket); 1332ffbf2595SKristof Provost snl_add_msg_attr_string(&nw, PF_ART_ANCHOR, anchor); 1333ffbf2595SKristof Provost snl_add_msg_attr_string(&nw, PF_ART_ANCHOR_CALL, anchor_call); 13340d71f9f3SKristof Provost 1335ffbf2595SKristof Provost snl_add_msg_attr_pf_rule(&nw, PF_ART_RULE, r); 13360d71f9f3SKristof Provost 1337ffbf2595SKristof Provost if ((hdr = snl_finalize_msg(&nw)) == NULL) 1338ffbf2595SKristof Provost return (ENXIO); 1339ffbf2595SKristof Provost 1340ffbf2595SKristof Provost seq_id = hdr->nlmsg_seq; 1341ffbf2595SKristof Provost 1342324fd7ecSKristof Provost if (! snl_send_message(&h->ss, hdr)) 1343ffbf2595SKristof Provost return (ENXIO); 13446fcc8e04SKristof Provost 1345324fd7ecSKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 1346ffbf2595SKristof Provost } 13470d71f9f3SKristof Provost 1348ffbf2595SKristof Provost return (e.error); 13490d71f9f3SKristof Provost } 13500d6c8174SKristof Provost 135144f323ecSKristof Provost #define _IN(_field) offsetof(struct genlmsghdr, _field) 135244f323ecSKristof Provost #define _OUT(_field) offsetof(struct pfctl_rules_info, _field) 135344f323ecSKristof Provost static struct snl_attr_parser ap_getrules[] = { 135444f323ecSKristof Provost { .type = PF_GR_NR, .off = _OUT(nr), .cb = snl_attr_get_uint32 }, 135544f323ecSKristof Provost { .type = PF_GR_TICKET, .off = _OUT(ticket), .cb = snl_attr_get_uint32 }, 135644f323ecSKristof Provost }; 135744f323ecSKristof Provost static struct snl_field_parser fp_getrules[] = { 135844f323ecSKristof Provost }; 135944f323ecSKristof Provost #undef _IN 136044f323ecSKristof Provost #undef _OUT 136144f323ecSKristof Provost SNL_DECLARE_PARSER(getrules_parser, struct genlmsghdr, fp_getrules, ap_getrules); 136244f323ecSKristof Provost 13630d6c8174SKristof 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) 14270d6c8174SKristof 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 }, 1599777a4702SKristof Provost { .type = PF_RT_RPOOL, .off = _OUT(r.rpool), .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 }, 1662*7fe42038SKajetan Staszkiewicz { .type = PF_RT_MAX_SRC_CONN, .off = _OUT(r.max_src_conn), .cb = snl_attr_get_uint32 }, 1663777a4702SKristof Provost }; 1664777a4702SKristof Provost static struct snl_field_parser fp_getrule[] = {}; 1665777a4702SKristof Provost #undef _OUT 1666777a4702SKristof Provost SNL_DECLARE_PARSER(getrule_parser, struct genlmsghdr, fp_getrule, ap_getrule); 1667777a4702SKristof Provost 1668777a4702SKristof Provost int 1669777a4702SKristof Provost pfctl_get_clear_rule_h(struct pfctl_handle *h, uint32_t nr, uint32_t ticket, 1670777a4702SKristof Provost const char *anchor, uint32_t ruleset, struct pfctl_rule *rule, 1671777a4702SKristof Provost char *anchor_call, bool clear) 1672777a4702SKristof Provost { 1673777a4702SKristof Provost struct pfctl_nl_get_rule attrs = {}; 1674777a4702SKristof Provost struct snl_errmsg_data e = {}; 1675777a4702SKristof Provost struct nlmsghdr *hdr; 1676777a4702SKristof Provost struct snl_writer nw; 1677777a4702SKristof Provost uint32_t seq_id; 1678777a4702SKristof Provost int family_id; 1679777a4702SKristof Provost 1680777a4702SKristof Provost family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 1681777a4702SKristof Provost if (family_id == 0) 1682777a4702SKristof Provost return (ENOTSUP); 1683777a4702SKristof Provost 1684777a4702SKristof Provost snl_init_writer(&h->ss, &nw); 1685777a4702SKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_GETRULE); 1686777a4702SKristof Provost hdr->nlmsg_flags |= NLM_F_DUMP; 1687777a4702SKristof Provost 1688777a4702SKristof Provost snl_add_msg_attr_string(&nw, PF_GR_ANCHOR, anchor); 1689777a4702SKristof Provost snl_add_msg_attr_u8(&nw, PF_GR_ACTION, ruleset); 1690777a4702SKristof Provost snl_add_msg_attr_u32(&nw, PF_GR_NR, nr); 1691777a4702SKristof Provost snl_add_msg_attr_u32(&nw, PF_GR_TICKET, ticket); 1692777a4702SKristof Provost snl_add_msg_attr_u8(&nw, PF_GR_CLEAR, clear); 1693777a4702SKristof Provost 1694777a4702SKristof Provost hdr = snl_finalize_msg(&nw); 1695777a4702SKristof Provost if (hdr == NULL) 1696777a4702SKristof Provost return (ENOMEM); 1697777a4702SKristof Provost 1698777a4702SKristof Provost seq_id = hdr->nlmsg_seq; 1699777a4702SKristof Provost if (! snl_send_message(&h->ss, hdr)) 1700777a4702SKristof Provost return (ENXIO); 1701777a4702SKristof Provost 1702777a4702SKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 1703777a4702SKristof Provost if (! snl_parse_nlmsg(&h->ss, hdr, &getrule_parser, &attrs)) 1704777a4702SKristof Provost continue; 1705777a4702SKristof Provost } 1706777a4702SKristof Provost 1707777a4702SKristof Provost memcpy(rule, &attrs.r, sizeof(attrs.r)); 1708777a4702SKristof Provost strlcpy(anchor_call, attrs.anchor_call, MAXPATHLEN); 1709777a4702SKristof Provost 1710777a4702SKristof Provost return (e.error); 1711777a4702SKristof Provost } 1712777a4702SKristof Provost 1713777a4702SKristof Provost int 1714777a4702SKristof Provost pfctl_get_clear_rule(int dev, uint32_t nr, uint32_t ticket, 17157bb3c927SKristof Provost const char *anchor, uint32_t ruleset, struct pfctl_rule *rule, 17164eabfe46SKristof Provost char *anchor_call, bool clear) 17174eabfe46SKristof Provost { 17180d6c8174SKristof Provost nvlist_t *nvl; 17190d6c8174SKristof Provost int ret; 17200d6c8174SKristof Provost 17210d6c8174SKristof Provost nvl = nvlist_create(0); 17220d6c8174SKristof Provost if (nvl == 0) 17230d6c8174SKristof Provost return (ENOMEM); 17240d6c8174SKristof Provost 17250d6c8174SKristof Provost nvlist_add_number(nvl, "nr", nr); 17260d6c8174SKristof Provost nvlist_add_number(nvl, "ticket", ticket); 17270d6c8174SKristof Provost nvlist_add_string(nvl, "anchor", anchor); 17280d6c8174SKristof Provost nvlist_add_number(nvl, "ruleset", ruleset); 17290d6c8174SKristof Provost 17304eabfe46SKristof Provost if (clear) 17314eabfe46SKristof Provost nvlist_add_bool(nvl, "clear_counter", true); 17324eabfe46SKristof Provost 17337ed19f5cSKristof Provost if ((ret = pfctl_do_ioctl(dev, DIOCGETRULENV, 8192, &nvl)) != 0) 1734498934c5SKristof Provost goto out; 17350d6c8174SKristof Provost 17360d6c8174SKristof Provost pf_nvrule_to_rule(nvlist_get_nvlist(nvl, "rule"), rule); 17370d6c8174SKristof Provost 17380d6c8174SKristof Provost if (anchor_call) 17390d6c8174SKristof Provost strlcpy(anchor_call, nvlist_get_string(nvl, "anchor_call"), 17400d6c8174SKristof Provost MAXPATHLEN); 17410d6c8174SKristof Provost 1742498934c5SKristof Provost out: 17430d6c8174SKristof Provost nvlist_destroy(nvl); 1744498934c5SKristof Provost return (ret); 17450d6c8174SKristof Provost } 174642ec75f8SKristof Provost 174742ec75f8SKristof Provost int 174842ec75f8SKristof Provost pfctl_set_keepcounters(int dev, bool keep) 174942ec75f8SKristof Provost { 175042ec75f8SKristof Provost struct pfioc_nv nv; 175142ec75f8SKristof Provost nvlist_t *nvl; 175242ec75f8SKristof Provost int ret; 175342ec75f8SKristof Provost 175442ec75f8SKristof Provost nvl = nvlist_create(0); 175542ec75f8SKristof Provost 175642ec75f8SKristof Provost nvlist_add_bool(nvl, "keep_counters", keep); 175742ec75f8SKristof Provost 175842ec75f8SKristof Provost nv.data = nvlist_pack(nvl, &nv.len); 175942ec75f8SKristof Provost nv.size = nv.len; 176042ec75f8SKristof Provost 176142ec75f8SKristof Provost nvlist_destroy(nvl); 176242ec75f8SKristof Provost 176342ec75f8SKristof Provost ret = ioctl(dev, DIOCKEEPCOUNTERS, &nv); 176442ec75f8SKristof Provost 176542ec75f8SKristof Provost free(nv.data); 176642ec75f8SKristof Provost return (ret); 176742ec75f8SKristof Provost } 176853714a58SKristof Provost 1769a7191e5dSKristof Provost struct pfctl_creator { 1770a7191e5dSKristof Provost uint32_t id; 1771a7191e5dSKristof Provost }; 1772a7191e5dSKristof Provost #define _IN(_field) offsetof(struct genlmsghdr, _field) 1773a7191e5dSKristof Provost #define _OUT(_field) offsetof(struct pfctl_creator, _field) 1774a7191e5dSKristof Provost static struct snl_attr_parser ap_creators[] = { 1775a7191e5dSKristof Provost { .type = PF_ST_CREATORID, .off = _OUT(id), .cb = snl_attr_get_uint32 }, 1776a7191e5dSKristof Provost }; 1777a7191e5dSKristof Provost static struct snl_field_parser fp_creators[] = { 1778a7191e5dSKristof Provost }; 1779a7191e5dSKristof Provost #undef _IN 1780a7191e5dSKristof Provost #undef _OUT 1781a7191e5dSKristof Provost SNL_DECLARE_PARSER(creator_parser, struct genlmsghdr, fp_creators, 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 18672cef6288SAlexander V. Chernikov #define _OUT(_field) offsetof(struct pf_state_key_export, _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 }, 18732cef6288SAlexander V. Chernikov }; 18742cef6288SAlexander V. Chernikov SNL_DECLARE_ATTR_PARSER(skey_parser, nla_p_skey); 18752cef6288SAlexander V. Chernikov #undef _OUT 18762cef6288SAlexander V. Chernikov 18772cef6288SAlexander V. Chernikov #define _IN(_field) offsetof(struct genlmsghdr, _field) 18782cef6288SAlexander V. Chernikov #define _OUT(_field) offsetof(struct pfctl_state, _field) 18792cef6288SAlexander V. Chernikov static struct snl_attr_parser ap_state[] = { 18802cef6288SAlexander V. Chernikov { .type = PF_ST_ID, .off = _OUT(id), .cb = snl_attr_get_uint64 }, 18812cef6288SAlexander V. Chernikov { .type = PF_ST_CREATORID, .off = _OUT(creatorid), .cb = snl_attr_get_uint32 }, 18822cef6288SAlexander V. Chernikov { .type = PF_ST_IFNAME, .off = _OUT(ifname), .cb = snl_attr_store_ifname }, 18832cef6288SAlexander V. Chernikov { .type = PF_ST_ORIG_IFNAME, .off = _OUT(orig_ifname), .cb = snl_attr_store_ifname }, 18842cef6288SAlexander V. Chernikov { .type = PF_ST_KEY_WIRE, .off = _OUT(key[0]), .arg = &skey_parser, .cb = snl_attr_get_nested }, 18852cef6288SAlexander V. Chernikov { .type = PF_ST_KEY_STACK, .off = _OUT(key[1]), .arg = &skey_parser, .cb = snl_attr_get_nested }, 18862cef6288SAlexander V. Chernikov { .type = PF_ST_PEER_SRC, .off = _OUT(src), .arg = &speer_parser, .cb = snl_attr_get_nested }, 18872cef6288SAlexander V. Chernikov { .type = PF_ST_PEER_DST, .off = _OUT(dst), .arg = &speer_parser, .cb = snl_attr_get_nested }, 18882cef6288SAlexander V. Chernikov { .type = PF_ST_RT_ADDR, .off = _OUT(rt_addr), .cb = snl_attr_get_pfaddr }, 18892cef6288SAlexander V. Chernikov { .type = PF_ST_RULE, .off = _OUT(rule), .cb = snl_attr_get_uint32 }, 18902cef6288SAlexander V. Chernikov { .type = PF_ST_ANCHOR, .off = _OUT(anchor), .cb = snl_attr_get_uint32 }, 18912cef6288SAlexander V. Chernikov { .type = PF_ST_NAT_RULE, .off = _OUT(nat_rule), .cb = snl_attr_get_uint32 }, 18922cef6288SAlexander V. Chernikov { .type = PF_ST_CREATION, .off = _OUT(creation), .cb = snl_attr_get_uint32 }, 18932cef6288SAlexander V. Chernikov { .type = PF_ST_EXPIRE, .off = _OUT(expire), .cb = snl_attr_get_uint32 }, 18942cef6288SAlexander V. Chernikov { .type = PF_ST_PACKETS0, .off = _OUT(packets[0]), .cb = snl_attr_get_uint64 }, 18952cef6288SAlexander V. Chernikov { .type = PF_ST_PACKETS1, .off = _OUT(packets[1]), .cb = snl_attr_get_uint64 }, 18962cef6288SAlexander V. Chernikov { .type = PF_ST_BYTES0, .off = _OUT(bytes[0]), .cb = snl_attr_get_uint64 }, 18972cef6288SAlexander V. Chernikov { .type = PF_ST_BYTES1, .off = _OUT(bytes[1]), .cb = snl_attr_get_uint64 }, 18982cef6288SAlexander V. Chernikov { .type = PF_ST_AF, .off = _OUT(key[0].af), .cb = snl_attr_get_uint8 }, 18992cef6288SAlexander V. Chernikov { .type = PF_ST_PROTO, .off = _OUT(key[0].proto), .cb = snl_attr_get_uint8 }, 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 static struct snl_field_parser fp_state[] = { 19132cef6288SAlexander V. Chernikov }; 19142cef6288SAlexander V. Chernikov #undef _IN 19152cef6288SAlexander V. Chernikov #undef _OUT 19162cef6288SAlexander V. Chernikov SNL_DECLARE_PARSER(state_parser, struct genlmsghdr, fp_state, ap_state); 19172cef6288SAlexander V. Chernikov 19182cef6288SAlexander V. Chernikov static const struct snl_hdr_parser *all_parsers[] = { 1919a7191e5dSKristof Provost &state_parser, &skey_parser, &speer_parser, 192044f323ecSKristof Provost &creator_parser, &getrules_parser 19212cef6288SAlexander V. Chernikov }; 19222cef6288SAlexander V. Chernikov 19232cef6288SAlexander V. Chernikov static int 1924044eef6aSKristof Provost pfctl_get_states_nl(struct pfctl_state_filter *filter, struct snl_state *ss, pfctl_get_state_fn f, void *arg) 1925bc941291SKristof Provost { 19262cef6288SAlexander V. Chernikov SNL_VERIFY_PARSERS(all_parsers); 19272cef6288SAlexander V. Chernikov int family_id = snl_get_genl_family(ss, PFNL_FAMILY_NAME); 1928f218b851SKristof Provost int ret; 1929bc941291SKristof Provost 19302cef6288SAlexander V. Chernikov struct nlmsghdr *hdr; 19312cef6288SAlexander V. Chernikov struct snl_writer nw; 1932bc941291SKristof Provost 1933497ccc21SKristof Provost if (family_id == 0) 1934497ccc21SKristof Provost return (ENOTSUP); 1935497ccc21SKristof Provost 19362cef6288SAlexander V. Chernikov snl_init_writer(ss, &nw); 19372cef6288SAlexander V. Chernikov hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_GETSTATES); 19382cef6288SAlexander V. Chernikov hdr->nlmsg_flags |= NLM_F_DUMP; 1939044eef6aSKristof Provost snl_add_msg_attr_string(&nw, PF_ST_IFNAME, filter->ifname); 1940044eef6aSKristof Provost snl_add_msg_attr_u16(&nw, PF_ST_PROTO, filter->proto); 1941044eef6aSKristof Provost snl_add_msg_attr_u8(&nw, PF_ST_AF, filter->af); 1942044eef6aSKristof Provost snl_add_msg_attr_ip6(&nw, PF_ST_FILTER_ADDR, &filter->addr.v6); 1943044eef6aSKristof Provost snl_add_msg_attr_ip6(&nw, PF_ST_FILTER_MASK, &filter->mask.v6); 1944044eef6aSKristof Provost 19454f8f43b0SKristof Provost hdr = snl_finalize_msg(&nw); 19464abc3b48SKristof Provost if (hdr == NULL) 19474abc3b48SKristof Provost return (ENOMEM); 1948044eef6aSKristof Provost 19492cef6288SAlexander V. Chernikov uint32_t seq_id = hdr->nlmsg_seq; 1950be70c7a5SKristof Provost 19512cef6288SAlexander V. Chernikov snl_send_message(ss, hdr); 1952bc941291SKristof Provost 19532cef6288SAlexander V. Chernikov struct snl_errmsg_data e = {}; 19542cef6288SAlexander V. Chernikov while ((hdr = snl_read_reply_multi(ss, seq_id, &e)) != NULL) { 1955f218b851SKristof Provost struct pfctl_state s; 1956f218b851SKristof Provost bzero(&s, sizeof(s)); 1957f218b851SKristof Provost if (!snl_parse_nlmsg(ss, hdr, &state_parser, &s)) 19582cef6288SAlexander V. Chernikov continue; 1959bc941291SKristof Provost 1960f218b851SKristof Provost s.key[1].af = s.key[0].af; 1961f218b851SKristof Provost s.key[1].proto = s.key[0].proto; 1962f218b851SKristof Provost 1963f218b851SKristof Provost ret = f(&s, arg); 1964f218b851SKristof Provost if (ret != 0) 1965f218b851SKristof Provost return (ret); 1966f218b851SKristof Provost } 1967f218b851SKristof Provost 1968f218b851SKristof Provost return (0); 1969f218b851SKristof Provost } 1970f218b851SKristof Provost 1971f218b851SKristof Provost int 1972f218b851SKristof Provost pfctl_get_states_iter(pfctl_get_state_fn f, void *arg) 1973f218b851SKristof Provost { 1974044eef6aSKristof Provost struct pfctl_state_filter filter = {}; 1975044eef6aSKristof Provost return (pfctl_get_filtered_states_iter(&filter, f, arg)); 1976044eef6aSKristof Provost } 1977044eef6aSKristof Provost 1978044eef6aSKristof Provost int 1979044eef6aSKristof Provost pfctl_get_filtered_states_iter(struct pfctl_state_filter *filter, pfctl_get_state_fn f, void *arg) 1980044eef6aSKristof Provost { 1981f218b851SKristof Provost struct snl_state ss = {}; 1982f218b851SKristof Provost int error; 1983f218b851SKristof Provost 1984f218b851SKristof Provost snl_init(&ss, NETLINK_GENERIC); 1985044eef6aSKristof Provost error = pfctl_get_states_nl(filter, &ss, f, arg); 1986f218b851SKristof Provost snl_free(&ss); 1987f218b851SKristof Provost 1988f218b851SKristof Provost return (error); 1989f218b851SKristof Provost } 1990f218b851SKristof Provost 1991f218b851SKristof Provost static int 1992f218b851SKristof Provost pfctl_append_states(struct pfctl_state *s, void *arg) 1993f218b851SKristof Provost { 1994f218b851SKristof Provost struct pfctl_state *new; 1995f218b851SKristof Provost struct pfctl_states *states = (struct pfctl_states *)arg; 1996f218b851SKristof Provost 1997f218b851SKristof Provost new = malloc(sizeof(*s)); 1998f218b851SKristof Provost if (new == NULL) 1999f218b851SKristof Provost return (ENOMEM); 2000f218b851SKristof Provost 2001f218b851SKristof Provost memcpy(new, s, sizeof(*s)); 20022cef6288SAlexander V. Chernikov 20034abc3b48SKristof Provost TAILQ_INSERT_TAIL(&states->states, new, entry); 2004bc941291SKristof Provost 20052cef6288SAlexander V. Chernikov return (0); 20062cef6288SAlexander V. Chernikov } 20072cef6288SAlexander V. Chernikov 20082cef6288SAlexander V. Chernikov int 20092cef6288SAlexander V. Chernikov pfctl_get_states(int dev __unused, struct pfctl_states *states) 20102cef6288SAlexander V. Chernikov { 2011f218b851SKristof Provost int ret; 20122cef6288SAlexander V. Chernikov 2013f218b851SKristof Provost bzero(states, sizeof(*states)); 2014f218b851SKristof Provost TAILQ_INIT(&states->states); 20152cef6288SAlexander V. Chernikov 2016f218b851SKristof Provost ret = pfctl_get_states_iter(pfctl_append_states, states); 2017f218b851SKristof Provost if (ret != 0) { 2018f218b851SKristof Provost pfctl_free_states(states); 2019f218b851SKristof Provost return (ret); 2020f218b851SKristof Provost } 2021f218b851SKristof Provost 2022f218b851SKristof Provost return (0); 2023bc941291SKristof Provost } 2024bc941291SKristof Provost 2025bc941291SKristof Provost void 2026bc941291SKristof Provost pfctl_free_states(struct pfctl_states *states) 2027bc941291SKristof Provost { 2028bc941291SKristof Provost struct pfctl_state *s, *tmp; 2029bc941291SKristof Provost 2030bc941291SKristof Provost TAILQ_FOREACH_SAFE(s, &states->states, entry, tmp) { 2031bc941291SKristof Provost free(s); 2032bc941291SKristof Provost } 2033bc941291SKristof Provost 2034bc941291SKristof Provost bzero(states, sizeof(*states)); 2035bc941291SKristof Provost } 2036bc941291SKristof Provost 2037706d465dSKristof Provost struct pfctl_nl_clear_states { 2038706d465dSKristof Provost uint32_t killed; 2039706d465dSKristof Provost }; 2040706d465dSKristof Provost #define _OUT(_field) offsetof(struct pfctl_nl_clear_states, _field) 2041706d465dSKristof Provost static struct snl_attr_parser ap_clear_states[] = { 2042706d465dSKristof Provost { .type = PF_CS_KILLED, .off = _OUT(killed), .cb = snl_attr_get_uint32 }, 2043706d465dSKristof Provost }; 2044706d465dSKristof Provost static struct snl_field_parser fp_clear_states[] = {}; 2045706d465dSKristof Provost #undef _OUT 2046706d465dSKristof Provost SNL_DECLARE_PARSER(clear_states_parser, struct genlmsghdr, fp_clear_states, ap_clear_states); 2047706d465dSKristof Provost 20482a00c4dbSKristof Provost static int 2049706d465dSKristof Provost _pfctl_clear_states_h(struct pfctl_handle *h, const struct pfctl_kill *kill, 2050706d465dSKristof Provost unsigned int *killed, int cmd) 205153714a58SKristof Provost { 2052706d465dSKristof Provost struct snl_writer nw; 2053706d465dSKristof Provost struct snl_errmsg_data e = {}; 2054706d465dSKristof Provost struct pfctl_nl_clear_states attrs = {}; 2055706d465dSKristof Provost struct nlmsghdr *hdr; 2056706d465dSKristof Provost uint32_t seq_id; 2057706d465dSKristof Provost int family_id; 205853714a58SKristof Provost 2059706d465dSKristof Provost family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 2060706d465dSKristof Provost if (family_id == 0) 2061706d465dSKristof Provost return (ENOTSUP); 206253714a58SKristof Provost 2063706d465dSKristof Provost snl_init_writer(&h->ss, &nw); 2064706d465dSKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, cmd); 2065706d465dSKristof Provost hdr->nlmsg_flags |= NLM_F_DUMP; 206653714a58SKristof Provost 2067706d465dSKristof Provost snl_add_msg_attr_u64(&nw, PF_CS_CMP_ID, kill->cmp.id); 2068706d465dSKristof Provost snl_add_msg_attr_u32(&nw, PF_CS_CMP_CREATORID, htonl(kill->cmp.creatorid)); 2069706d465dSKristof Provost snl_add_msg_attr_u8(&nw, PF_CS_CMP_DIR, kill->cmp.direction); 2070706d465dSKristof Provost snl_add_msg_attr_u8(&nw, PF_CS_AF, kill->af); 2071706d465dSKristof Provost snl_add_msg_attr_u8(&nw, PF_CS_PROTO, kill->proto); 2072706d465dSKristof Provost snl_add_msg_attr_rule_addr(&nw, PF_CS_SRC, &kill->src); 2073706d465dSKristof Provost snl_add_msg_attr_rule_addr(&nw, PF_CS_DST, &kill->dst); 2074706d465dSKristof Provost snl_add_msg_attr_rule_addr(&nw, PF_CS_RT_ADDR, &kill->rt_addr); 2075706d465dSKristof Provost snl_add_msg_attr_string(&nw, PF_CS_IFNAME, kill->ifname); 2076706d465dSKristof Provost snl_add_msg_attr_string(&nw, PF_CS_LABEL, kill->label); 2077706d465dSKristof Provost snl_add_msg_attr_bool(&nw, PF_CS_KILL_MATCH, kill->kill_match); 2078706d465dSKristof Provost snl_add_msg_attr_bool(&nw, PF_CS_NAT, kill->nat); 2079706d465dSKristof Provost 2080706d465dSKristof Provost if ((hdr = snl_finalize_msg(&nw)) == NULL) 2081706d465dSKristof Provost return (ENXIO); 2082706d465dSKristof Provost 2083706d465dSKristof Provost seq_id = hdr->nlmsg_seq; 2084706d465dSKristof Provost 2085706d465dSKristof Provost if (! snl_send_message(&h->ss, hdr)) 2086706d465dSKristof Provost return (ENXIO); 2087706d465dSKristof Provost 2088706d465dSKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 2089706d465dSKristof Provost if (! snl_parse_nlmsg(&h->ss, hdr, &clear_states_parser, &attrs)) 2090706d465dSKristof Provost continue; 2091706d465dSKristof Provost } 209253714a58SKristof Provost 209353714a58SKristof Provost if (killed) 2094706d465dSKristof Provost *killed = attrs.killed; 209553714a58SKristof Provost 2096706d465dSKristof Provost return (e.error); 2097706d465dSKristof Provost } 2098706d465dSKristof Provost 2099706d465dSKristof Provost int 2100706d465dSKristof Provost pfctl_clear_states_h(struct pfctl_handle *h, const struct pfctl_kill *kill, 2101706d465dSKristof Provost unsigned int *killed) 2102706d465dSKristof Provost { 2103706d465dSKristof Provost return(_pfctl_clear_states_h(h, kill, killed, PFNL_CMD_CLRSTATES)); 2104706d465dSKristof Provost } 2105706d465dSKristof Provost 2106706d465dSKristof Provost int 2107706d465dSKristof Provost pfctl_kill_states_h(struct pfctl_handle *h, const struct pfctl_kill *kill, 2108706d465dSKristof Provost unsigned int *killed) 2109706d465dSKristof Provost { 2110706d465dSKristof Provost return(_pfctl_clear_states_h(h, kill, killed, PFNL_CMD_KILLSTATES)); 2111706d465dSKristof Provost } 2112706d465dSKristof Provost 2113706d465dSKristof Provost static int 2114706d465dSKristof Provost _pfctl_clear_states(int dev __unused, const struct pfctl_kill *kill, 2115706d465dSKristof Provost unsigned int *killed, uint64_t cmd) 2116706d465dSKristof Provost { 2117706d465dSKristof Provost struct pfctl_handle *h; 2118706d465dSKristof Provost int ret; 2119706d465dSKristof Provost 2120706d465dSKristof Provost h = pfctl_open(PF_DEVICE); 2121706d465dSKristof Provost if (h == NULL) 2122706d465dSKristof Provost return (ENODEV); 2123706d465dSKristof Provost 2124706d465dSKristof Provost ret = _pfctl_clear_states_h(h, kill, killed, cmd); 2125706d465dSKristof Provost pfctl_close(h); 2126706d465dSKristof Provost 212753714a58SKristof Provost return (ret); 212853714a58SKristof Provost } 21292a00c4dbSKristof Provost 21302a00c4dbSKristof Provost int 2131706d465dSKristof Provost pfctl_clear_states(int dev __unused, const struct pfctl_kill *kill, 21322a00c4dbSKristof Provost unsigned int *killed) 21332a00c4dbSKristof Provost { 2134706d465dSKristof Provost return (_pfctl_clear_states(dev, kill, killed, PFNL_CMD_CLRSTATES)); 21352a00c4dbSKristof Provost } 21362a00c4dbSKristof Provost 21372a00c4dbSKristof Provost int 2138706d465dSKristof Provost pfctl_kill_states(int dev __unused, const struct pfctl_kill *kill, unsigned int *killed) 21392a00c4dbSKristof Provost { 2140706d465dSKristof Provost return (_pfctl_clear_states(dev, kill, killed, PFNL_CMD_KILLSTATES)); 21412a00c4dbSKristof Provost } 2142c69121c4SKristof Provost 2143f0c334e4SKristof Provost int 2144f0c334e4SKristof Provost pfctl_clear_rules(int dev, const char *anchorname) 2145f0c334e4SKristof Provost { 2146f0c334e4SKristof Provost struct pfioc_trans trans; 2147f0c334e4SKristof Provost struct pfioc_trans_e transe[2]; 2148f0c334e4SKristof Provost int ret; 2149f0c334e4SKristof Provost 2150f0c334e4SKristof Provost bzero(&trans, sizeof(trans)); 2151f0c334e4SKristof Provost bzero(&transe, sizeof(transe)); 2152f0c334e4SKristof Provost 2153f0c334e4SKristof Provost transe[0].rs_num = PF_RULESET_SCRUB; 2154f0c334e4SKristof Provost if (strlcpy(transe[0].anchor, anchorname, sizeof(transe[0].anchor)) 2155f0c334e4SKristof Provost >= sizeof(transe[0].anchor)) 2156f0c334e4SKristof Provost return (E2BIG); 2157f0c334e4SKristof Provost 2158f0c334e4SKristof Provost transe[1].rs_num = PF_RULESET_FILTER; 2159f0c334e4SKristof Provost if (strlcpy(transe[1].anchor, anchorname, sizeof(transe[1].anchor)) 2160f0c334e4SKristof Provost >= sizeof(transe[1].anchor)) 2161f0c334e4SKristof Provost return (E2BIG); 2162f0c334e4SKristof Provost 2163f0c334e4SKristof Provost trans.size = 2; 2164f0c334e4SKristof Provost trans.esize = sizeof(transe[0]); 2165f0c334e4SKristof Provost trans.array = transe; 2166f0c334e4SKristof Provost 2167f0c334e4SKristof Provost ret = ioctl(dev, DIOCXBEGIN, &trans); 2168f0c334e4SKristof Provost if (ret != 0) 216993e96359SKristof Provost return (errno); 217093e96359SKristof Provost ret = ioctl(dev, DIOCXCOMMIT, &trans); 217193e96359SKristof Provost if (ret != 0) 217293e96359SKristof Provost return (errno); 217393e96359SKristof Provost 217493e96359SKristof Provost return (0); 2175f0c334e4SKristof Provost } 2176f0c334e4SKristof Provost 2177f0c334e4SKristof Provost int 2178f0c334e4SKristof Provost pfctl_clear_nat(int dev, const char *anchorname) 2179f0c334e4SKristof Provost { 2180f0c334e4SKristof Provost struct pfioc_trans trans; 2181f0c334e4SKristof Provost struct pfioc_trans_e transe[3]; 2182f0c334e4SKristof Provost int ret; 2183f0c334e4SKristof Provost 2184f0c334e4SKristof Provost bzero(&trans, sizeof(trans)); 2185f0c334e4SKristof Provost bzero(&transe, sizeof(transe)); 2186f0c334e4SKristof Provost 2187f0c334e4SKristof Provost transe[0].rs_num = PF_RULESET_NAT; 2188f0c334e4SKristof Provost if (strlcpy(transe[0].anchor, anchorname, sizeof(transe[0].anchor)) 2189f0c334e4SKristof Provost >= sizeof(transe[0].anchor)) 2190f0c334e4SKristof Provost return (E2BIG); 2191f0c334e4SKristof Provost 2192f0c334e4SKristof Provost transe[1].rs_num = PF_RULESET_BINAT; 2193f0c334e4SKristof Provost if (strlcpy(transe[1].anchor, anchorname, sizeof(transe[1].anchor)) 2194f0c334e4SKristof Provost >= sizeof(transe[0].anchor)) 2195f0c334e4SKristof Provost return (E2BIG); 2196f0c334e4SKristof Provost 2197f0c334e4SKristof Provost transe[2].rs_num = PF_RULESET_RDR; 2198f0c334e4SKristof Provost if (strlcpy(transe[2].anchor, anchorname, sizeof(transe[2].anchor)) 2199f0c334e4SKristof Provost >= sizeof(transe[2].anchor)) 2200f0c334e4SKristof Provost return (E2BIG); 2201f0c334e4SKristof Provost 2202f0c334e4SKristof Provost trans.size = 3; 2203f0c334e4SKristof Provost trans.esize = sizeof(transe[0]); 2204f0c334e4SKristof Provost trans.array = transe; 2205f0c334e4SKristof Provost 2206f0c334e4SKristof Provost ret = ioctl(dev, DIOCXBEGIN, &trans); 2207f0c334e4SKristof Provost if (ret != 0) 220893e96359SKristof Provost return (errno); 220993e96359SKristof Provost ret = ioctl(dev, DIOCXCOMMIT, &trans); 221093e96359SKristof Provost if (ret != 0) 221193e96359SKristof Provost return (errno); 221293e96359SKristof Provost 221393e96359SKristof Provost return (0); 2214f0c334e4SKristof Provost } 221593e96359SKristof Provost 2216f0c334e4SKristof Provost int 2217f0c334e4SKristof Provost pfctl_clear_eth_rules(int dev, const char *anchorname) 2218f0c334e4SKristof Provost { 2219f0c334e4SKristof Provost struct pfioc_trans trans; 2220f0c334e4SKristof Provost struct pfioc_trans_e transe; 2221f0c334e4SKristof Provost int ret; 2222f0c334e4SKristof Provost 2223f0c334e4SKristof Provost bzero(&trans, sizeof(trans)); 2224f0c334e4SKristof Provost bzero(&transe, sizeof(transe)); 2225f0c334e4SKristof Provost 2226f0c334e4SKristof Provost transe.rs_num = PF_RULESET_ETH; 2227f0c334e4SKristof Provost if (strlcpy(transe.anchor, anchorname, sizeof(transe.anchor)) 2228f0c334e4SKristof Provost >= sizeof(transe.anchor)) 2229f0c334e4SKristof Provost return (E2BIG); 2230f0c334e4SKristof Provost 2231f0c334e4SKristof Provost trans.size = 1; 2232f0c334e4SKristof Provost trans.esize = sizeof(transe); 2233f0c334e4SKristof Provost trans.array = &transe; 2234f0c334e4SKristof Provost 2235f0c334e4SKristof Provost ret = ioctl(dev, DIOCXBEGIN, &trans); 2236f0c334e4SKristof Provost if (ret != 0) 223793e96359SKristof Provost return (errno); 223893e96359SKristof Provost ret = ioctl(dev, DIOCXCOMMIT, &trans); 223993e96359SKristof Provost if (ret != 0) 224093e96359SKristof Provost return (errno); 224193e96359SKristof Provost 224293e96359SKristof Provost return (0); 2243f0c334e4SKristof Provost } 2244f0c334e4SKristof Provost 22455062afffSKristof Provost static int 2246d9ab8999SKristof Provost _pfctl_get_limit(int dev, const int index, uint *limit) 22475062afffSKristof Provost { 22485062afffSKristof Provost struct pfioc_limit pl; 22495062afffSKristof Provost 22505062afffSKristof Provost bzero(&pl, sizeof(pl)); 22515062afffSKristof Provost pl.index = index; 22525062afffSKristof Provost 22535062afffSKristof Provost if (ioctl(dev, DIOCGETLIMIT, &pl) == -1) 22545062afffSKristof Provost return (errno); 22555062afffSKristof Provost 22565062afffSKristof Provost *limit = pl.limit; 22575062afffSKristof Provost 22585062afffSKristof Provost return (0); 22595062afffSKristof Provost } 22605062afffSKristof Provost 2261c69121c4SKristof Provost int 2262c69121c4SKristof Provost pfctl_set_syncookies(int dev, const struct pfctl_syncookies *s) 2263c69121c4SKristof Provost { 2264c69121c4SKristof Provost struct pfioc_nv nv; 2265c69121c4SKristof Provost nvlist_t *nvl; 2266c69121c4SKristof Provost int ret; 22677bb3c927SKristof Provost uint state_limit; 22686049ee60SKristof Provost uint64_t lim, hi, lo; 22695062afffSKristof Provost 2270d9ab8999SKristof Provost ret = _pfctl_get_limit(dev, PF_LIMIT_STATES, &state_limit); 22715062afffSKristof Provost if (ret != 0) 22725062afffSKristof Provost return (ret); 2273c69121c4SKristof Provost 22746049ee60SKristof Provost lim = state_limit; 22756049ee60SKristof Provost hi = lim * s->highwater / 100; 22766049ee60SKristof Provost lo = lim * s->lowwater / 100; 22776049ee60SKristof Provost 22786049ee60SKristof Provost if (lo == hi) 22796049ee60SKristof Provost hi++; 22806049ee60SKristof Provost 2281c69121c4SKristof Provost nvl = nvlist_create(0); 2282c69121c4SKristof Provost 2283c69121c4SKristof Provost nvlist_add_bool(nvl, "enabled", s->mode != PFCTL_SYNCOOKIES_NEVER); 22845062afffSKristof Provost nvlist_add_bool(nvl, "adaptive", s->mode == PFCTL_SYNCOOKIES_ADAPTIVE); 22856049ee60SKristof Provost nvlist_add_number(nvl, "highwater", hi); 22866049ee60SKristof Provost nvlist_add_number(nvl, "lowwater", lo); 2287c69121c4SKristof Provost 2288c69121c4SKristof Provost nv.data = nvlist_pack(nvl, &nv.len); 2289c69121c4SKristof Provost nv.size = nv.len; 2290c69121c4SKristof Provost nvlist_destroy(nvl); 2291c69121c4SKristof Provost nvl = NULL; 2292c69121c4SKristof Provost 2293c69121c4SKristof Provost ret = ioctl(dev, DIOCSETSYNCOOKIES, &nv); 2294c69121c4SKristof Provost 2295c69121c4SKristof Provost free(nv.data); 229693e96359SKristof Provost if (ret != 0) 229793e96359SKristof Provost return (errno); 229893e96359SKristof Provost 229993e96359SKristof Provost return (0); 2300c69121c4SKristof Provost } 2301c69121c4SKristof Provost 2302c69121c4SKristof Provost int 2303c69121c4SKristof Provost pfctl_get_syncookies(int dev, struct pfctl_syncookies *s) 2304c69121c4SKristof Provost { 2305c69121c4SKristof Provost nvlist_t *nvl; 23065062afffSKristof Provost int ret; 23077bb3c927SKristof Provost uint state_limit; 2308c69121c4SKristof Provost bool enabled, adaptive; 2309c69121c4SKristof Provost 2310d9ab8999SKristof Provost ret = _pfctl_get_limit(dev, PF_LIMIT_STATES, &state_limit); 23115062afffSKristof Provost if (ret != 0) 23125062afffSKristof Provost return (ret); 23135062afffSKristof Provost 2314c69121c4SKristof Provost bzero(s, sizeof(*s)); 2315c69121c4SKristof Provost 23167ed19f5cSKristof Provost nvl = nvlist_create(0); 2317c69121c4SKristof Provost 2318498934c5SKristof Provost if ((ret = pfctl_do_ioctl(dev, DIOCGETSYNCOOKIES, 256, &nvl)) != 0) { 2319498934c5SKristof Provost ret = errno; 2320498934c5SKristof Provost goto out; 2321498934c5SKristof Provost } 2322c69121c4SKristof Provost 2323c69121c4SKristof Provost enabled = nvlist_get_bool(nvl, "enabled"); 2324c69121c4SKristof Provost adaptive = nvlist_get_bool(nvl, "adaptive"); 2325c69121c4SKristof Provost 23265062afffSKristof Provost if (enabled) { 23275062afffSKristof Provost if (adaptive) 23285062afffSKristof Provost s->mode = PFCTL_SYNCOOKIES_ADAPTIVE; 23295062afffSKristof Provost else 23305062afffSKristof Provost s->mode = PFCTL_SYNCOOKIES_ALWAYS; 23315062afffSKristof Provost } else { 23325062afffSKristof Provost s->mode = PFCTL_SYNCOOKIES_NEVER; 23335062afffSKristof Provost } 23345062afffSKristof Provost 23355062afffSKristof Provost s->highwater = nvlist_get_number(nvl, "highwater") * 100 / state_limit; 23365062afffSKristof Provost s->lowwater = nvlist_get_number(nvl, "lowwater") * 100 / state_limit; 2337a6173e94SKristof Provost s->halfopen_states = nvlist_get_number(nvl, "halfopen_states"); 2338c69121c4SKristof Provost 2339498934c5SKristof Provost out: 2340c69121c4SKristof Provost nvlist_destroy(nvl); 2341498934c5SKristof Provost return (ret); 2342c69121c4SKristof Provost } 23434823489aSReid Linnemann 23444823489aSReid Linnemann int 23454823489aSReid Linnemann pfctl_table_add_addrs(int dev, struct pfr_table *tbl, struct pfr_addr 23464823489aSReid Linnemann *addr, int size, int *nadd, int flags) 23474823489aSReid Linnemann { 23484823489aSReid Linnemann struct pfioc_table io; 23494823489aSReid Linnemann 23504823489aSReid Linnemann if (tbl == NULL || size < 0 || (size && addr == NULL)) { 23514823489aSReid Linnemann return (EINVAL); 23524823489aSReid Linnemann } 23534823489aSReid Linnemann bzero(&io, sizeof io); 23544823489aSReid Linnemann io.pfrio_flags = flags; 23554823489aSReid Linnemann io.pfrio_table = *tbl; 23564823489aSReid Linnemann io.pfrio_buffer = addr; 23574823489aSReid Linnemann io.pfrio_esize = sizeof(*addr); 23584823489aSReid Linnemann io.pfrio_size = size; 23594823489aSReid Linnemann 23604823489aSReid Linnemann if (ioctl(dev, DIOCRADDADDRS, &io)) 23614823489aSReid Linnemann return (errno); 23624823489aSReid Linnemann if (nadd != NULL) 23634823489aSReid Linnemann *nadd = io.pfrio_nadd; 23644823489aSReid Linnemann return (0); 23654823489aSReid Linnemann } 23664823489aSReid Linnemann 23674823489aSReid Linnemann int 23684823489aSReid Linnemann pfctl_table_del_addrs(int dev, struct pfr_table *tbl, struct pfr_addr 23694823489aSReid Linnemann *addr, int size, int *ndel, int flags) 23704823489aSReid Linnemann { 23714823489aSReid Linnemann struct pfioc_table io; 23724823489aSReid Linnemann 23734823489aSReid Linnemann if (tbl == NULL || size < 0 || (size && addr == NULL)) { 23744823489aSReid Linnemann return (EINVAL); 23754823489aSReid Linnemann } 23764823489aSReid Linnemann bzero(&io, sizeof io); 23774823489aSReid Linnemann io.pfrio_flags = flags; 23784823489aSReid Linnemann io.pfrio_table = *tbl; 23794823489aSReid Linnemann io.pfrio_buffer = addr; 23804823489aSReid Linnemann io.pfrio_esize = sizeof(*addr); 23814823489aSReid Linnemann io.pfrio_size = size; 23824823489aSReid Linnemann 23834823489aSReid Linnemann if (ioctl(dev, DIOCRDELADDRS, &io)) 23844823489aSReid Linnemann return (errno); 23854823489aSReid Linnemann if (ndel != NULL) 23864823489aSReid Linnemann *ndel = io.pfrio_ndel; 23874823489aSReid Linnemann return (0); 23884823489aSReid Linnemann } 23894823489aSReid Linnemann 23904823489aSReid Linnemann int 23914823489aSReid Linnemann pfctl_table_set_addrs(int dev, struct pfr_table *tbl, struct pfr_addr 23924823489aSReid Linnemann *addr, int size, int *size2, int *nadd, int *ndel, int *nchange, int flags) 23934823489aSReid Linnemann { 23944823489aSReid Linnemann struct pfioc_table io; 23954823489aSReid Linnemann 23964823489aSReid Linnemann if (tbl == NULL || size < 0 || (size && addr == NULL)) { 23974823489aSReid Linnemann return (EINVAL); 23984823489aSReid Linnemann } 23994823489aSReid Linnemann bzero(&io, sizeof io); 24004823489aSReid Linnemann io.pfrio_flags = flags; 24014823489aSReid Linnemann io.pfrio_table = *tbl; 24024823489aSReid Linnemann io.pfrio_buffer = addr; 24034823489aSReid Linnemann io.pfrio_esize = sizeof(*addr); 24044823489aSReid Linnemann io.pfrio_size = size; 24054823489aSReid Linnemann io.pfrio_size2 = (size2 != NULL) ? *size2 : 0; 24064823489aSReid Linnemann if (ioctl(dev, DIOCRSETADDRS, &io)) 240793e96359SKristof Provost return (errno); 24084823489aSReid Linnemann if (nadd != NULL) 24094823489aSReid Linnemann *nadd = io.pfrio_nadd; 24104823489aSReid Linnemann if (ndel != NULL) 24114823489aSReid Linnemann *ndel = io.pfrio_ndel; 24124823489aSReid Linnemann if (nchange != NULL) 24134823489aSReid Linnemann *nchange = io.pfrio_nchange; 24144823489aSReid Linnemann if (size2 != NULL) 24154823489aSReid Linnemann *size2 = io.pfrio_size2; 24164823489aSReid Linnemann return (0); 24174823489aSReid Linnemann } 24184823489aSReid Linnemann 24194823489aSReid Linnemann int pfctl_table_get_addrs(int dev, struct pfr_table *tbl, struct pfr_addr *addr, 24204823489aSReid Linnemann int *size, int flags) 24214823489aSReid Linnemann { 24224823489aSReid Linnemann struct pfioc_table io; 24234823489aSReid Linnemann 24244823489aSReid Linnemann if (tbl == NULL || size == NULL || *size < 0 || 24254823489aSReid Linnemann (*size && addr == NULL)) { 24264823489aSReid Linnemann return (EINVAL); 24274823489aSReid Linnemann } 24284823489aSReid Linnemann bzero(&io, sizeof io); 24294823489aSReid Linnemann io.pfrio_flags = flags; 24304823489aSReid Linnemann io.pfrio_table = *tbl; 24314823489aSReid Linnemann io.pfrio_buffer = addr; 24324823489aSReid Linnemann io.pfrio_esize = sizeof(*addr); 24334823489aSReid Linnemann io.pfrio_size = *size; 24344823489aSReid Linnemann if (ioctl(dev, DIOCRGETADDRS, &io)) 243593e96359SKristof Provost return (errno); 24364823489aSReid Linnemann *size = io.pfrio_size; 24374823489aSReid Linnemann return (0); 24384823489aSReid Linnemann } 2439470a2b33SKristof Provost 2440470a2b33SKristof Provost int 2441470a2b33SKristof Provost pfctl_set_statusif(struct pfctl_handle *h, const char *ifname) 2442470a2b33SKristof Provost { 2443470a2b33SKristof Provost struct snl_writer nw; 2444470a2b33SKristof Provost struct snl_errmsg_data e = {}; 2445470a2b33SKristof Provost struct nlmsghdr *hdr; 2446470a2b33SKristof Provost uint32_t seq_id; 2447470a2b33SKristof Provost int family_id; 2448470a2b33SKristof Provost 2449470a2b33SKristof Provost family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 2450470a2b33SKristof Provost if (family_id == 0) 2451470a2b33SKristof Provost return (ENOTSUP); 2452470a2b33SKristof Provost 2453470a2b33SKristof Provost snl_init_writer(&h->ss, &nw); 2454470a2b33SKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_SET_STATUSIF); 2455470a2b33SKristof Provost 2456470a2b33SKristof Provost snl_add_msg_attr_string(&nw, PF_SS_IFNAME, ifname); 2457470a2b33SKristof Provost 2458470a2b33SKristof Provost if ((hdr = snl_finalize_msg(&nw)) == NULL) 2459470a2b33SKristof Provost return (ENXIO); 2460470a2b33SKristof Provost 2461470a2b33SKristof Provost seq_id = hdr->nlmsg_seq; 2462470a2b33SKristof Provost 2463470a2b33SKristof Provost if (! snl_send_message(&h->ss, hdr)) 2464470a2b33SKristof Provost return (ENXIO); 2465470a2b33SKristof Provost 2466470a2b33SKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 2467470a2b33SKristof Provost } 2468470a2b33SKristof Provost 2469470a2b33SKristof Provost return (e.error); 2470470a2b33SKristof Provost } 247171d3c704SKristof Provost 247271d3c704SKristof Provost #define _IN(_field) offsetof(struct genlmsghdr, _field) 247371d3c704SKristof Provost #define _OUT(_field) offsetof(struct pfctl_natlook, _field) 247471d3c704SKristof Provost static struct snl_attr_parser ap_natlook[] = { 247571d3c704SKristof Provost { .type = PF_NL_SRC_ADDR, .off = _OUT(saddr), .cb = snl_attr_get_in6_addr }, 247671d3c704SKristof Provost { .type = PF_NL_DST_ADDR, .off = _OUT(daddr), .cb = snl_attr_get_in6_addr }, 247771d3c704SKristof Provost { .type = PF_NL_SRC_PORT, .off = _OUT(sport), .cb = snl_attr_get_uint16 }, 247871d3c704SKristof Provost { .type = PF_NL_DST_PORT, .off = _OUT(dport), .cb = snl_attr_get_uint16 }, 247971d3c704SKristof Provost }; 248071d3c704SKristof Provost static struct snl_field_parser fp_natlook[] = {}; 248171d3c704SKristof Provost #undef _IN 248271d3c704SKristof Provost #undef _OUT 248371d3c704SKristof Provost SNL_DECLARE_PARSER(natlook_parser, struct genlmsghdr, fp_natlook, ap_natlook); 248471d3c704SKristof Provost 248571d3c704SKristof Provost int 248671d3c704SKristof Provost pfctl_natlook(struct pfctl_handle *h, const struct pfctl_natlook_key *k, 248771d3c704SKristof Provost struct pfctl_natlook *r) 248871d3c704SKristof Provost { 248971d3c704SKristof Provost struct snl_writer nw; 249071d3c704SKristof Provost struct snl_errmsg_data e = {}; 249171d3c704SKristof Provost struct nlmsghdr *hdr; 249271d3c704SKristof Provost uint32_t seq_id; 249371d3c704SKristof Provost int family_id; 249471d3c704SKristof Provost 249571d3c704SKristof Provost family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 249671d3c704SKristof Provost if (family_id == 0) 249771d3c704SKristof Provost return (ENOTSUP); 249871d3c704SKristof Provost 249971d3c704SKristof Provost snl_init_writer(&h->ss, &nw); 250071d3c704SKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_NATLOOK); 250171d3c704SKristof Provost hdr->nlmsg_flags |= NLM_F_DUMP; 250271d3c704SKristof Provost 250371d3c704SKristof Provost snl_add_msg_attr_u8(&nw, PF_NL_AF, k->af); 250471d3c704SKristof Provost snl_add_msg_attr_u8(&nw, PF_NL_DIRECTION, k->direction); 250571d3c704SKristof Provost snl_add_msg_attr_u8(&nw, PF_NL_PROTO, k->proto); 250671d3c704SKristof Provost snl_add_msg_attr_ip6(&nw, PF_NL_SRC_ADDR, &k->saddr.v6); 250771d3c704SKristof Provost snl_add_msg_attr_ip6(&nw, PF_NL_DST_ADDR, &k->daddr.v6); 250871d3c704SKristof Provost snl_add_msg_attr_u16(&nw, PF_NL_SRC_PORT, k->sport); 250971d3c704SKristof Provost snl_add_msg_attr_u16(&nw, PF_NL_DST_PORT, k->dport); 251071d3c704SKristof Provost 251171d3c704SKristof Provost if ((hdr = snl_finalize_msg(&nw)) == NULL) 251271d3c704SKristof Provost return (ENXIO); 251371d3c704SKristof Provost 251471d3c704SKristof Provost seq_id = hdr->nlmsg_seq; 251571d3c704SKristof Provost 251671d3c704SKristof Provost if (! snl_send_message(&h->ss, hdr)) 251771d3c704SKristof Provost return (ENXIO); 251871d3c704SKristof Provost 251971d3c704SKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 252071d3c704SKristof Provost if (! snl_parse_nlmsg(&h->ss, hdr, &natlook_parser, r)) 252171d3c704SKristof Provost continue; 252271d3c704SKristof Provost } 252371d3c704SKristof Provost 252471d3c704SKristof Provost return (e.error); 252571d3c704SKristof Provost } 2526c36c90a2SKristof Provost 2527c36c90a2SKristof Provost int 2528c36c90a2SKristof Provost pfctl_set_debug(struct pfctl_handle *h, uint32_t level) 2529c36c90a2SKristof Provost { 2530c36c90a2SKristof Provost struct snl_writer nw; 2531c36c90a2SKristof Provost struct snl_errmsg_data e = {}; 2532c36c90a2SKristof Provost struct nlmsghdr *hdr; 2533c36c90a2SKristof Provost uint32_t seq_id; 2534c36c90a2SKristof Provost int family_id; 2535c36c90a2SKristof Provost 2536c36c90a2SKristof Provost family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 2537c36c90a2SKristof Provost if (family_id == 0) 2538c36c90a2SKristof Provost return (ENOTSUP); 2539c36c90a2SKristof Provost 2540c36c90a2SKristof Provost snl_init_writer(&h->ss, &nw); 2541c36c90a2SKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_SET_DEBUG); 2542c36c90a2SKristof Provost 2543c36c90a2SKristof Provost snl_add_msg_attr_u32(&nw, PF_SD_LEVEL, level); 2544c36c90a2SKristof Provost 2545c36c90a2SKristof Provost if ((hdr = snl_finalize_msg(&nw)) == NULL) 2546c36c90a2SKristof Provost return (ENXIO); 2547c36c90a2SKristof Provost 2548c36c90a2SKristof Provost seq_id = hdr->nlmsg_seq; 2549c36c90a2SKristof Provost 2550c36c90a2SKristof Provost if (! snl_send_message(&h->ss, hdr)) 2551c36c90a2SKristof Provost return (ENXIO); 2552c36c90a2SKristof Provost 2553c36c90a2SKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 2554c36c90a2SKristof Provost } 2555c36c90a2SKristof Provost 2556c36c90a2SKristof Provost return (e.error); 2557c36c90a2SKristof Provost } 255830bad751SKristof Provost 255930bad751SKristof Provost int 256030bad751SKristof Provost pfctl_set_timeout(struct pfctl_handle *h, uint32_t timeout, uint32_t seconds) 256130bad751SKristof Provost { 256230bad751SKristof Provost struct snl_writer nw; 256330bad751SKristof Provost struct snl_errmsg_data e = {}; 256430bad751SKristof Provost struct nlmsghdr *hdr; 256530bad751SKristof Provost uint32_t seq_id; 256630bad751SKristof Provost int family_id; 256730bad751SKristof Provost 256830bad751SKristof Provost family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 256930bad751SKristof Provost if (family_id == 0) 257030bad751SKristof Provost return (ENOTSUP); 257130bad751SKristof Provost 257230bad751SKristof Provost snl_init_writer(&h->ss, &nw); 257330bad751SKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_SET_TIMEOUT); 257430bad751SKristof Provost 257530bad751SKristof Provost snl_add_msg_attr_u32(&nw, PF_TO_TIMEOUT, timeout); 257630bad751SKristof Provost snl_add_msg_attr_u32(&nw, PF_TO_SECONDS, seconds); 257730bad751SKristof Provost 257830bad751SKristof Provost if ((hdr = snl_finalize_msg(&nw)) == NULL) 257930bad751SKristof Provost return (ENXIO); 258030bad751SKristof Provost 258130bad751SKristof Provost seq_id = hdr->nlmsg_seq; 258230bad751SKristof Provost 258330bad751SKristof Provost if (! snl_send_message(&h->ss, hdr)) 258430bad751SKristof Provost return (ENXIO); 258530bad751SKristof Provost 258630bad751SKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 258730bad751SKristof Provost } 258830bad751SKristof Provost 258930bad751SKristof Provost return (e.error); 259030bad751SKristof Provost } 259130bad751SKristof Provost 259230bad751SKristof Provost struct pfctl_nl_timeout { 259330bad751SKristof Provost uint32_t seconds; 259430bad751SKristof Provost }; 259530bad751SKristof Provost #define _OUT(_field) offsetof(struct pfctl_nl_timeout, _field) 259630bad751SKristof Provost static struct snl_attr_parser ap_get_timeout[] = { 259730bad751SKristof Provost { .type = PF_TO_SECONDS, .off = _OUT(seconds), .cb = snl_attr_get_uint32 }, 259830bad751SKristof Provost }; 259930bad751SKristof Provost static struct snl_field_parser fp_get_timeout[] = {}; 260030bad751SKristof Provost #undef _OUT 260130bad751SKristof Provost SNL_DECLARE_PARSER(get_timeout_parser, struct genlmsghdr, fp_get_timeout, ap_get_timeout); 260230bad751SKristof Provost 260330bad751SKristof Provost int 260430bad751SKristof Provost pfctl_get_timeout(struct pfctl_handle *h, uint32_t timeout, uint32_t *seconds) 260530bad751SKristof Provost { 260630bad751SKristof Provost struct snl_writer nw; 260730bad751SKristof Provost struct pfctl_nl_timeout to = {}; 260830bad751SKristof Provost struct snl_errmsg_data e = {}; 260930bad751SKristof Provost struct nlmsghdr *hdr; 261030bad751SKristof Provost uint32_t seq_id; 261130bad751SKristof Provost int family_id; 261230bad751SKristof Provost 261330bad751SKristof Provost family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 261430bad751SKristof Provost if (family_id == 0) 261530bad751SKristof Provost return (ENOTSUP); 261630bad751SKristof Provost 261730bad751SKristof Provost snl_init_writer(&h->ss, &nw); 261830bad751SKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_GET_TIMEOUT); 261930bad751SKristof Provost hdr->nlmsg_flags |= NLM_F_DUMP; 262030bad751SKristof Provost 262130bad751SKristof Provost snl_add_msg_attr_u32(&nw, PF_TO_TIMEOUT, timeout); 262230bad751SKristof Provost 262330bad751SKristof Provost if ((hdr = snl_finalize_msg(&nw)) == NULL) 262430bad751SKristof Provost return (ENXIO); 262530bad751SKristof Provost 262630bad751SKristof Provost seq_id = hdr->nlmsg_seq; 262730bad751SKristof Provost 262830bad751SKristof Provost if (! snl_send_message(&h->ss, hdr)) 262930bad751SKristof Provost return (ENXIO); 263030bad751SKristof Provost 263130bad751SKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 263230bad751SKristof Provost if (! snl_parse_nlmsg(&h->ss, hdr, &get_timeout_parser, &to)) 263330bad751SKristof Provost continue; 263430bad751SKristof Provost } 263530bad751SKristof Provost 263630bad751SKristof Provost if (seconds != NULL) 263730bad751SKristof Provost *seconds = to.seconds; 263830bad751SKristof Provost 263930bad751SKristof Provost return (e.error); 264030bad751SKristof Provost } 264130bad751SKristof Provost 2642d9ab8999SKristof Provost int 2643d9ab8999SKristof Provost pfctl_set_limit(struct pfctl_handle *h, const int index, const uint limit) 2644d9ab8999SKristof Provost { 2645d9ab8999SKristof Provost struct snl_writer nw; 2646d9ab8999SKristof Provost struct snl_errmsg_data e = {}; 2647d9ab8999SKristof Provost struct nlmsghdr *hdr; 2648d9ab8999SKristof Provost uint32_t seq_id; 2649d9ab8999SKristof Provost int family_id; 2650d9ab8999SKristof Provost 2651d9ab8999SKristof Provost family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 2652d9ab8999SKristof Provost if (family_id == 0) 2653d9ab8999SKristof Provost return (ENOTSUP); 2654d9ab8999SKristof Provost 2655d9ab8999SKristof Provost snl_init_writer(&h->ss, &nw); 2656d9ab8999SKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_SET_LIMIT); 2657d9ab8999SKristof Provost 2658d9ab8999SKristof Provost snl_add_msg_attr_u32(&nw, PF_LI_INDEX, index); 2659d9ab8999SKristof Provost snl_add_msg_attr_u32(&nw, PF_LI_LIMIT, limit); 2660d9ab8999SKristof Provost 2661d9ab8999SKristof Provost if ((hdr = snl_finalize_msg(&nw)) == NULL) 2662d9ab8999SKristof Provost return (ENXIO); 2663d9ab8999SKristof Provost 2664d9ab8999SKristof Provost seq_id = hdr->nlmsg_seq; 2665d9ab8999SKristof Provost 2666d9ab8999SKristof Provost if (! snl_send_message(&h->ss, hdr)) 2667d9ab8999SKristof Provost return (ENXIO); 2668d9ab8999SKristof Provost 2669d9ab8999SKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 2670d9ab8999SKristof Provost } 2671d9ab8999SKristof Provost 2672d9ab8999SKristof Provost return (e.error); 2673d9ab8999SKristof Provost } 2674d9ab8999SKristof Provost 2675d9ab8999SKristof Provost struct pfctl_nl_limit { 2676d9ab8999SKristof Provost unsigned int limit; 2677d9ab8999SKristof Provost }; 2678d9ab8999SKristof Provost #define _OUT(_field) offsetof(struct pfctl_nl_limit, _field) 2679d9ab8999SKristof Provost static struct snl_attr_parser ap_get_limit[] = { 2680d9ab8999SKristof Provost { .type = PF_LI_LIMIT, .off = _OUT(limit), .cb = snl_attr_get_uint32 }, 2681d9ab8999SKristof Provost }; 2682d9ab8999SKristof Provost static struct snl_field_parser fp_get_limit[] = {}; 2683d9ab8999SKristof Provost #undef _OUT 2684d9ab8999SKristof Provost SNL_DECLARE_PARSER(get_limit_parser, struct genlmsghdr, fp_get_limit, ap_get_limit); 2685d9ab8999SKristof Provost 2686d9ab8999SKristof Provost int 2687d9ab8999SKristof Provost pfctl_get_limit(struct pfctl_handle *h, const int index, uint *limit) 2688d9ab8999SKristof Provost { 2689d9ab8999SKristof Provost struct snl_writer nw; 2690d9ab8999SKristof Provost struct pfctl_nl_limit li = {}; 2691d9ab8999SKristof Provost struct snl_errmsg_data e = {}; 2692d9ab8999SKristof Provost struct nlmsghdr *hdr; 2693d9ab8999SKristof Provost uint32_t seq_id; 2694d9ab8999SKristof Provost int family_id; 2695d9ab8999SKristof Provost 2696d9ab8999SKristof Provost family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 2697d9ab8999SKristof Provost if (family_id == 0) 2698d9ab8999SKristof Provost return (ENOTSUP); 2699d9ab8999SKristof Provost 2700d9ab8999SKristof Provost snl_init_writer(&h->ss, &nw); 2701d9ab8999SKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_GET_LIMIT); 2702d9ab8999SKristof Provost hdr->nlmsg_flags |= NLM_F_DUMP; 2703d9ab8999SKristof Provost 2704d9ab8999SKristof Provost snl_add_msg_attr_u32(&nw, PF_LI_INDEX, index); 2705d9ab8999SKristof Provost 2706d9ab8999SKristof Provost if ((hdr = snl_finalize_msg(&nw)) == NULL) 2707d9ab8999SKristof Provost return (ENXIO); 2708d9ab8999SKristof Provost 2709d9ab8999SKristof Provost seq_id = hdr->nlmsg_seq; 2710d9ab8999SKristof Provost 2711d9ab8999SKristof Provost if (! snl_send_message(&h->ss, hdr)) 2712d9ab8999SKristof Provost return (ENXIO); 2713d9ab8999SKristof Provost 2714d9ab8999SKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 2715d9ab8999SKristof Provost if (! snl_parse_nlmsg(&h->ss, hdr, &get_limit_parser, &li)) 2716d9ab8999SKristof Provost continue; 2717d9ab8999SKristof Provost } 2718d9ab8999SKristof Provost 2719d9ab8999SKristof Provost if (limit != NULL) 2720d9ab8999SKristof Provost *limit = li.limit; 2721d9ab8999SKristof Provost 2722d9ab8999SKristof Provost return (e.error); 2723d9ab8999SKristof Provost } 2724ba2a9207SKristof Provost 2725ba2a9207SKristof Provost struct pfctl_nl_begin_addrs { 2726ba2a9207SKristof Provost uint32_t ticket; 2727ba2a9207SKristof Provost }; 2728ba2a9207SKristof Provost #define _OUT(_field) offsetof(struct pfctl_nl_begin_addrs, _field) 2729ba2a9207SKristof Provost static struct snl_attr_parser ap_begin_addrs[] = { 2730ba2a9207SKristof Provost { .type = PF_BA_TICKET, .off = _OUT(ticket), .cb = snl_attr_get_uint32 }, 2731ba2a9207SKristof Provost }; 2732ba2a9207SKristof Provost static struct snl_field_parser fp_begin_addrs[] = {}; 2733ba2a9207SKristof Provost #undef _OUT 2734ba2a9207SKristof Provost SNL_DECLARE_PARSER(begin_addrs_parser, struct genlmsghdr, fp_begin_addrs, ap_begin_addrs); 2735ba2a9207SKristof Provost 2736ba2a9207SKristof Provost int 2737ba2a9207SKristof Provost pfctl_begin_addrs(struct pfctl_handle *h, uint32_t *ticket) 2738ba2a9207SKristof Provost { 2739ba2a9207SKristof Provost struct snl_writer nw; 2740ba2a9207SKristof Provost struct pfctl_nl_begin_addrs attrs = {}; 2741ba2a9207SKristof Provost struct snl_errmsg_data e = {}; 2742ba2a9207SKristof Provost struct nlmsghdr *hdr; 2743ba2a9207SKristof Provost uint32_t seq_id; 2744ba2a9207SKristof Provost int family_id; 2745ba2a9207SKristof Provost 2746ba2a9207SKristof Provost family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 2747ba2a9207SKristof Provost if (family_id == 0) 2748ba2a9207SKristof Provost return (ENOTSUP); 2749ba2a9207SKristof Provost 2750ba2a9207SKristof Provost snl_init_writer(&h->ss, &nw); 2751ba2a9207SKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_BEGIN_ADDRS); 2752ba2a9207SKristof Provost hdr->nlmsg_flags |= NLM_F_DUMP; 2753ba2a9207SKristof Provost 2754ba2a9207SKristof Provost if ((hdr = snl_finalize_msg(&nw)) == NULL) 2755ba2a9207SKristof Provost return (ENXIO); 2756ba2a9207SKristof Provost 2757ba2a9207SKristof Provost seq_id = hdr->nlmsg_seq; 2758ba2a9207SKristof Provost 2759ba2a9207SKristof Provost if (! snl_send_message(&h->ss, hdr)) 2760ba2a9207SKristof Provost return (ENXIO); 2761ba2a9207SKristof Provost 2762ba2a9207SKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 2763ba2a9207SKristof Provost if (! snl_parse_nlmsg(&h->ss, hdr, &begin_addrs_parser, &attrs)) 2764ba2a9207SKristof Provost continue; 2765ba2a9207SKristof Provost } 2766ba2a9207SKristof Provost 2767ba2a9207SKristof Provost if (ticket != NULL) 2768ba2a9207SKristof Provost *ticket = attrs.ticket; 2769ba2a9207SKristof Provost 2770ba2a9207SKristof Provost return (e.error); 2771ba2a9207SKristof Provost } 2772ba2a9207SKristof Provost 2773d909f06bSKristof Provost int 2774d909f06bSKristof Provost pfctl_add_addr(struct pfctl_handle *h, const struct pfioc_pooladdr *pa) 2775d909f06bSKristof Provost { 2776d909f06bSKristof Provost struct snl_writer nw; 2777d909f06bSKristof Provost struct snl_errmsg_data e = {}; 2778d909f06bSKristof Provost struct nlmsghdr *hdr; 2779d909f06bSKristof Provost uint32_t seq_id; 2780d909f06bSKristof Provost int family_id; 2781d909f06bSKristof Provost 2782d909f06bSKristof Provost family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 2783d909f06bSKristof Provost if (family_id == 0) 2784d909f06bSKristof Provost return (ENOTSUP); 2785d909f06bSKristof Provost 2786d909f06bSKristof Provost snl_init_writer(&h->ss, &nw); 2787d909f06bSKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_ADD_ADDR); 2788d909f06bSKristof Provost 2789d909f06bSKristof Provost snl_add_msg_attr_u32(&nw, PF_AA_ACTION, pa->action); 2790d909f06bSKristof Provost snl_add_msg_attr_u32(&nw, PF_AA_TICKET, pa->ticket); 2791d909f06bSKristof Provost snl_add_msg_attr_u32(&nw, PF_AA_NR, pa->nr); 2792d909f06bSKristof Provost snl_add_msg_attr_u32(&nw, PF_AA_R_NUM, pa->r_num); 2793d909f06bSKristof Provost snl_add_msg_attr_u8(&nw, PF_AA_R_ACTION, pa->r_action); 2794d909f06bSKristof Provost snl_add_msg_attr_u8(&nw, PF_AA_R_LAST, pa->r_last); 2795d909f06bSKristof Provost snl_add_msg_attr_u8(&nw, PF_AA_AF, pa->af); 2796d909f06bSKristof Provost snl_add_msg_attr_string(&nw, PF_AA_ANCHOR, pa->anchor); 2797d909f06bSKristof Provost snl_add_msg_attr_pool_addr(&nw, PF_AA_ADDR, &pa->addr); 2798d909f06bSKristof Provost 2799d909f06bSKristof Provost if ((hdr = snl_finalize_msg(&nw)) == NULL) 2800d909f06bSKristof Provost return (ENXIO); 2801d909f06bSKristof Provost 2802d909f06bSKristof Provost seq_id = hdr->nlmsg_seq; 2803d909f06bSKristof Provost 2804d909f06bSKristof Provost if (! snl_send_message(&h->ss, hdr)) 2805d909f06bSKristof Provost return (ENXIO); 2806d909f06bSKristof Provost 2807d909f06bSKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 2808d909f06bSKristof Provost } 2809d909f06bSKristof Provost 2810d909f06bSKristof Provost return (e.error); 2811d909f06bSKristof Provost } 2812644b7b5aSKristof Provost 2813644b7b5aSKristof Provost static const struct snl_attr_parser ap_get_addrs[] = { 2814644b7b5aSKristof Provost { .type = PF_AA_NR, .off = 0, .cb = snl_attr_get_uint32 }, 2815644b7b5aSKristof Provost }; 2816644b7b5aSKristof Provost static struct snl_field_parser fp_get_addrs[] = {}; 2817644b7b5aSKristof Provost SNL_DECLARE_PARSER(get_addrs_parser, struct genlmsghdr, fp_get_addrs, ap_get_addrs); 2818644b7b5aSKristof Provost 2819644b7b5aSKristof Provost int 2820644b7b5aSKristof Provost pfctl_get_addrs(struct pfctl_handle *h, uint32_t ticket, uint32_t r_num, 2821644b7b5aSKristof Provost uint8_t r_action, const char *anchor, uint32_t *nr) 2822644b7b5aSKristof Provost { 2823644b7b5aSKristof Provost struct snl_writer nw; 2824644b7b5aSKristof Provost struct snl_errmsg_data e = {}; 2825644b7b5aSKristof Provost struct nlmsghdr *hdr; 2826644b7b5aSKristof Provost uint32_t seq_id; 2827644b7b5aSKristof Provost int family_id; 2828644b7b5aSKristof Provost 2829644b7b5aSKristof Provost family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 2830644b7b5aSKristof Provost if (family_id == 0) 2831644b7b5aSKristof Provost return (ENOTSUP); 2832644b7b5aSKristof Provost 2833644b7b5aSKristof Provost snl_init_writer(&h->ss, &nw); 2834644b7b5aSKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_GET_ADDRS); 2835644b7b5aSKristof Provost 2836644b7b5aSKristof Provost snl_add_msg_attr_u32(&nw, PF_AA_TICKET, ticket); 2837644b7b5aSKristof Provost snl_add_msg_attr_u32(&nw, PF_AA_R_NUM, r_num); 2838644b7b5aSKristof Provost snl_add_msg_attr_u8(&nw, PF_AA_R_ACTION, r_action); 2839644b7b5aSKristof Provost snl_add_msg_attr_string(&nw, PF_AA_ANCHOR, anchor); 2840644b7b5aSKristof Provost 2841644b7b5aSKristof Provost if ((hdr = snl_finalize_msg(&nw)) == NULL) 2842644b7b5aSKristof Provost return (ENXIO); 2843644b7b5aSKristof Provost 2844644b7b5aSKristof Provost seq_id = hdr->nlmsg_seq; 2845644b7b5aSKristof Provost 2846644b7b5aSKristof Provost if (! snl_send_message(&h->ss, hdr)) 2847644b7b5aSKristof Provost return (ENXIO); 2848644b7b5aSKristof Provost 2849644b7b5aSKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 2850644b7b5aSKristof Provost if (! snl_parse_nlmsg(&h->ss, hdr, &get_addrs_parser, nr)) 2851644b7b5aSKristof Provost continue; 2852644b7b5aSKristof Provost } 2853644b7b5aSKristof Provost 2854644b7b5aSKristof Provost return (e.error); 2855644b7b5aSKristof Provost } 28569ae91f59SKristof Provost 28579ae91f59SKristof Provost #define _OUT(_field) offsetof(struct pf_pooladdr, _field) 28589ae91f59SKristof Provost static const struct snl_attr_parser ap_pool_addr[] = { 28599ae91f59SKristof Provost { .type = PF_PA_ADDR, .off = _OUT(addr), .arg = &addr_wrap_parser, .cb = snl_attr_get_nested }, 28609ae91f59SKristof Provost { .type = PF_PA_IFNAME, .off = _OUT(ifname), .arg_u32 = IFNAMSIZ, .cb = snl_attr_copy_string }, 28619ae91f59SKristof Provost }; 28629ae91f59SKristof Provost SNL_DECLARE_ATTR_PARSER(pool_addr_parser, ap_pool_addr); 28639ae91f59SKristof Provost #undef _OUT 28649ae91f59SKristof Provost 28659ae91f59SKristof Provost #define _OUT(_field) offsetof(struct pfioc_pooladdr, _field) 28669ae91f59SKristof Provost static const struct snl_attr_parser ap_get_addr[] = { 28679ae91f59SKristof Provost { .type = PF_AA_ACTION, .off = _OUT(action), .cb = snl_attr_get_uint32 }, 28689ae91f59SKristof Provost { .type = PF_AA_TICKET, .off = _OUT(ticket), .cb = snl_attr_get_uint32 }, 28699ae91f59SKristof Provost { .type = PF_AA_NR, .off = _OUT(nr), .cb = snl_attr_get_uint32 }, 28709ae91f59SKristof Provost { .type = PF_AA_R_NUM, .off = _OUT(r_num), .cb = snl_attr_get_uint32 }, 28719ae91f59SKristof Provost { .type = PF_AA_R_ACTION, .off = _OUT(r_action), .cb = snl_attr_get_uint8 }, 28729ae91f59SKristof Provost { .type = PF_AA_R_LAST, .off = _OUT(r_last), .cb = snl_attr_get_uint8 }, 28739ae91f59SKristof Provost { .type = PF_AA_AF, .off = _OUT(af), .cb = snl_attr_get_uint8 }, 28749ae91f59SKristof Provost { .type = PF_AA_ANCHOR, .off = _OUT(anchor), .arg_u32 = MAXPATHLEN, .cb = snl_attr_copy_string }, 28759ae91f59SKristof Provost { .type = PF_AA_ADDR, .off = _OUT(addr), .arg = &pool_addr_parser, .cb = snl_attr_get_nested }, 28769ae91f59SKristof Provost }; 28779ae91f59SKristof Provost static struct snl_field_parser fp_get_addr[] = {}; 28789ae91f59SKristof Provost SNL_DECLARE_PARSER(get_addr_parser, struct genlmsghdr, fp_get_addr, ap_get_addr); 28799ae91f59SKristof Provost #undef _OUT 28809ae91f59SKristof Provost 28819ae91f59SKristof Provost int 28829ae91f59SKristof Provost pfctl_get_addr(struct pfctl_handle *h, uint32_t ticket, uint32_t r_num, 28839ae91f59SKristof Provost uint8_t r_action, const char *anchor, uint32_t nr, struct pfioc_pooladdr *pa) 28849ae91f59SKristof Provost { 28859ae91f59SKristof Provost struct snl_writer nw; 28869ae91f59SKristof Provost struct snl_errmsg_data e = {}; 28879ae91f59SKristof Provost struct nlmsghdr *hdr; 28889ae91f59SKristof Provost uint32_t seq_id; 28899ae91f59SKristof Provost int family_id; 28909ae91f59SKristof Provost 28919ae91f59SKristof Provost family_id =snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); 28929ae91f59SKristof Provost if (family_id == 0) 28939ae91f59SKristof Provost return (ENOTSUP); 28949ae91f59SKristof Provost 28959ae91f59SKristof Provost snl_init_writer(&h->ss, &nw); 28969ae91f59SKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_GET_ADDR); 28979ae91f59SKristof Provost 28989ae91f59SKristof Provost snl_add_msg_attr_u32(&nw, PF_AA_TICKET, ticket); 28999ae91f59SKristof Provost snl_add_msg_attr_u32(&nw, PF_AA_R_NUM, r_num); 29009ae91f59SKristof Provost snl_add_msg_attr_u8(&nw, PF_AA_R_ACTION, r_action); 29019ae91f59SKristof Provost snl_add_msg_attr_string(&nw, PF_AA_ANCHOR, anchor); 29029ae91f59SKristof Provost snl_add_msg_attr_u32(&nw, PF_AA_NR, nr); 29039ae91f59SKristof Provost 29049ae91f59SKristof Provost if ((hdr = snl_finalize_msg(&nw)) == NULL) 29059ae91f59SKristof Provost return (ENXIO); 29069ae91f59SKristof Provost 29079ae91f59SKristof Provost seq_id = hdr->nlmsg_seq; 29089ae91f59SKristof Provost 29099ae91f59SKristof Provost if (! snl_send_message(&h->ss, hdr)) 29109ae91f59SKristof Provost return (ENXIO); 29119ae91f59SKristof Provost 29129ae91f59SKristof Provost while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { 29139ae91f59SKristof Provost if (! snl_parse_nlmsg(&h->ss, hdr, &get_addr_parser, pa)) 29149ae91f59SKristof Provost continue; 29159ae91f59SKristof Provost } 29169ae91f59SKristof Provost 29179ae91f59SKristof Provost return (0); 29189ae91f59SKristof Provost } 2919