From 0d71f9f36e6c1849fdaf6c1edc1178be07357034 Mon Sep 17 00:00:00 2001 From: Kristof Provost Date: Fri, 26 Mar 2021 11:38:58 +0100 Subject: pfctl: Move ioctl abstraction functions into libpfctl Introduce a library to wrap the pf ioctl interface. MFC after: 4 weeks Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D29562 --- lib/Makefile | 1 + lib/libpfctl/Makefile | 12 + lib/libpfctl/libpfctl.c | 536 ++++++++++++++++++++++++++++++++++++++++++++ lib/libpfctl/libpfctl.h | 45 ++++ sbin/pfctl/Makefile | 5 +- sbin/pfctl/parse.y | 6 +- sbin/pfctl/pfctl.c | 212 +----------------- sbin/pfctl/pfctl_ioctl.c | 339 ---------------------------- sbin/pfctl/pfctl_ioctl.h | 43 ---- sbin/pfctl/pfctl_optimize.c | 2 +- sbin/pfctl/pfctl_parser.h | 2 +- share/mk/src.libnames.mk | 5 + 12 files changed, 614 insertions(+), 594 deletions(-) create mode 100644 lib/libpfctl/Makefile create mode 100644 lib/libpfctl/libpfctl.c create mode 100644 lib/libpfctl/libpfctl.h delete mode 100644 sbin/pfctl/pfctl_ioctl.c diff --git a/lib/Makefile b/lib/Makefile index 80b77f1fd704..26b867ec00e1 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -210,6 +210,7 @@ SUBDIR.${MK_BHYVE}+= libvmmapi SUBDIR.${MK_OPENMP}+= libomp .endif SUBDIR.${MK_OPENSSL}+= libmp +SUBDIR.${MK_PF}+= libpfctl SUBDIR.${MK_PMC}+= libpmc libpmcstat SUBDIR.${MK_RADIUS_SUPPORT}+= libradius SUBDIR.${MK_SENDMAIL}+= libmilter libsm libsmdb libsmutil diff --git a/lib/libpfctl/Makefile b/lib/libpfctl/Makefile new file mode 100644 index 000000000000..d7a00a94b349 --- /dev/null +++ b/lib/libpfctl/Makefile @@ -0,0 +1,12 @@ +# $FreeBSD$ + +PACKAGE= lib${LIB} +LIB= pfctl +INTERNALLIB= true + +SRCS= libpfctl.c +INCS= libpfctl.h + +CFLAGS+= -fPIC + +.include diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c new file mode 100644 index 000000000000..e0d429112f5b --- /dev/null +++ b/lib/libpfctl/libpfctl.c @@ -0,0 +1,536 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2021 Rubicon Communications, LLC (Netgate) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "libpfctl.h" + +static void +pf_nvuint_8_array(const nvlist_t *nvl, const char *name, size_t maxelems, + u_int8_t *numbers, size_t *nelems) +{ + const uint64_t *tmp; + size_t elems; + + tmp = nvlist_get_number_array(nvl, name, &elems); + assert(elems <= maxelems); + + for (size_t i = 0; i < elems; i++) + numbers[i] = tmp[i]; + + if (nelems) + *nelems = elems; +} + +static void +pf_nvuint_16_array(const nvlist_t *nvl, const char *name, size_t maxelems, + u_int16_t *numbers, size_t *nelems) +{ + const uint64_t *tmp; + size_t elems; + + tmp = nvlist_get_number_array(nvl, name, &elems); + assert(elems <= maxelems); + + for (size_t i = 0; i < elems; i++) + numbers[i] = tmp[i]; + + if (nelems) + *nelems = elems; +} + +static void +pf_nvuint_32_array(const nvlist_t *nvl, const char *name, size_t maxelems, + u_int32_t *numbers, size_t *nelems) +{ + const uint64_t *tmp; + size_t elems; + + tmp = nvlist_get_number_array(nvl, name, &elems); + assert(elems <= maxelems); + + for (size_t i = 0; i < elems; i++) + numbers[i] = tmp[i]; + + if (nelems) + *nelems = elems; +} + +static void +pf_nvuint_64_array(const nvlist_t *nvl, const char *name, size_t maxelems, + u_int64_t *numbers, size_t *nelems) +{ + const uint64_t *tmp; + size_t elems; + + tmp = nvlist_get_number_array(nvl, name, &elems); + assert(elems <= maxelems); + + for (size_t i = 0; i < elems; i++) + numbers[i] = tmp[i]; + + if (nelems) + *nelems = elems; +} + +static void +pfctl_nv_add_addr(nvlist_t *nvparent, const char *name, + const struct pf_addr *addr) +{ + nvlist_t *nvl = nvlist_create(0); + + nvlist_add_binary(nvl, "addr", addr, sizeof(*addr)); + + nvlist_add_nvlist(nvparent, name, nvl); +} + +static void +pf_nvaddr_to_addr(const nvlist_t *nvl, struct pf_addr *addr) +{ + size_t len; + const void *data; + + data = nvlist_get_binary(nvl, "addr", &len); + assert(len == sizeof(struct pf_addr)); + memcpy(addr, data, len); +} + +static void +pfctl_nv_add_addr_wrap(nvlist_t *nvparent, const char *name, + const struct pf_addr_wrap *addr) +{ + nvlist_t *nvl = nvlist_create(0); + + nvlist_add_number(nvl, "type", addr->type); + nvlist_add_number(nvl, "iflags", addr->iflags); + nvlist_add_string(nvl, "ifname", addr->v.ifname); + nvlist_add_string(nvl, "tblname", addr->v.tblname); + pfctl_nv_add_addr(nvl, "addr", &addr->v.a.addr); + pfctl_nv_add_addr(nvl, "mask", &addr->v.a.mask); + + nvlist_add_nvlist(nvparent, name, nvl); +} + +static void +pf_nvaddr_wrap_to_addr_wrap(const nvlist_t *nvl, struct pf_addr_wrap *addr) +{ + addr->type = nvlist_get_number(nvl, "type"); + addr->iflags = nvlist_get_number(nvl, "iflags"); + strlcpy(addr->v.ifname, nvlist_get_string(nvl, "ifname"), IFNAMSIZ); + strlcpy(addr->v.tblname, nvlist_get_string(nvl, "tblname"), + PF_TABLE_NAME_SIZE); + + pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "addr"), &addr->v.a.addr); + pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "mask"), &addr->v.a.mask); +} + +static void +pfctl_nv_add_rule_addr(nvlist_t *nvparent, const char *name, + const struct pf_rule_addr *addr) +{ + u_int64_t ports[2]; + nvlist_t *nvl = nvlist_create(0); + + pfctl_nv_add_addr_wrap(nvl, "addr", &addr->addr); + ports[0] = addr->port[0]; + ports[1] = addr->port[1]; + nvlist_add_number_array(nvl, "port", ports, 2); + nvlist_add_number(nvl, "neg", addr->neg); + nvlist_add_number(nvl, "port_op", addr->port_op); + + nvlist_add_nvlist(nvparent, name, nvl); +} + +static void +pf_nvrule_addr_to_rule_addr(const nvlist_t *nvl, struct pf_rule_addr *addr) +{ + pf_nvaddr_wrap_to_addr_wrap(nvlist_get_nvlist(nvl, "addr"), &addr->addr); + + pf_nvuint_16_array(nvl, "port", 2, addr->port, NULL); + addr->neg = nvlist_get_number(nvl, "neg"); + addr->port_op = nvlist_get_number(nvl, "port_op"); +} + +static void +pfctl_nv_add_pool(nvlist_t *nvparent, const char *name, + const struct pf_pool *pool) +{ + u_int64_t ports[2]; + nvlist_t *nvl = nvlist_create(0); + + nvlist_add_binary(nvl, "key", &pool->key, sizeof(pool->key)); + pfctl_nv_add_addr(nvl, "counter", &pool->counter); + nvlist_add_number(nvl, "tblidx", pool->tblidx); + + ports[0] = pool->proxy_port[0]; + ports[1] = pool->proxy_port[1]; + nvlist_add_number_array(nvl, "proxy_port", ports, 2); + nvlist_add_number(nvl, "opts", pool->opts); + + nvlist_add_nvlist(nvparent, name, nvl); +} + +static void +pf_nvpool_to_pool(const nvlist_t *nvl, struct pf_pool *pool) +{ + size_t len; + const void *data; + + data = nvlist_get_binary(nvl, "key", &len); + assert(len == sizeof(pool->key)); + memcpy(&pool->key, data, len); + + pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "counter"), &pool->counter); + + pool->tblidx = nvlist_get_number(nvl, "tblidx"); + pf_nvuint_16_array(nvl, "proxy_port", 2, pool->proxy_port, NULL); + pool->opts = nvlist_get_number(nvl, "opts"); +} + +static void +pfctl_nv_add_uid(nvlist_t *nvparent, const char *name, + const struct pf_rule_uid *uid) +{ + u_int64_t uids[2]; + nvlist_t *nvl = nvlist_create(0); + + uids[0] = uid->uid[0]; + uids[1] = uid->uid[1]; + nvlist_add_number_array(nvl, "uid", uids, 2); + nvlist_add_number(nvl, "op", uid->op); + + nvlist_add_nvlist(nvparent, name, nvl); +} + +static void +pf_nvrule_uid_to_rule_uid(const nvlist_t *nvl, struct pf_rule_uid *uid) +{ + pf_nvuint_32_array(nvl, "uid", 2, uid->uid, NULL); + uid->op = nvlist_get_number(nvl, "op"); +} + +static void +pfctl_nv_add_divert(nvlist_t *nvparent, const char *name, + const struct pf_rule *r) +{ + nvlist_t *nvl = nvlist_create(0); + + pfctl_nv_add_addr(nvl, "addr", &r->divert.addr); + nvlist_add_number(nvl, "port", r->divert.port); + + nvlist_add_nvlist(nvparent, name, nvl); +} + +static void +pf_nvdivert_to_divert(const nvlist_t *nvl, struct pf_rule *rule) +{ + pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "addr"), &rule->divert.addr); + rule->divert.port = nvlist_get_number(nvl, "port"); +} + +static void +pf_nvrule_to_rule(const nvlist_t *nvl, struct pf_rule *rule) +{ + const uint64_t *skip; + size_t skipcount; + + rule->nr = nvlist_get_number(nvl, "nr"); + + pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "src"), &rule->src); + pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "dst"), &rule->dst); + + skip = nvlist_get_number_array(nvl, "skip", &skipcount); + assert(skip); + assert(skipcount == PF_SKIP_COUNT); + for (int i = 0; i < PF_SKIP_COUNT; i++) + rule->skip[i].nr = skip[i]; + + strlcpy(rule->label, nvlist_get_string(nvl, "label"), PF_RULE_LABEL_SIZE); + strlcpy(rule->ifname, nvlist_get_string(nvl, "ifname"), IFNAMSIZ); + strlcpy(rule->qname, nvlist_get_string(nvl, "qname"), PF_QNAME_SIZE); + strlcpy(rule->pqname, nvlist_get_string(nvl, "pqname"), PF_QNAME_SIZE); + strlcpy(rule->tagname, nvlist_get_string(nvl, "tagname"), + PF_TAG_NAME_SIZE); + strlcpy(rule->match_tagname, nvlist_get_string(nvl, "match_tagname"), + PF_TAG_NAME_SIZE); + + strlcpy(rule->overload_tblname, nvlist_get_string(nvl, "overload_tblname"), + PF_TABLE_NAME_SIZE); + + pf_nvpool_to_pool(nvlist_get_nvlist(nvl, "rpool"), &rule->rpool); + + rule->evaluations = nvlist_get_number(nvl, "evaluations"); + pf_nvuint_64_array(nvl, "packets", 2, rule->packets, NULL); + pf_nvuint_64_array(nvl, "bytes", 2, rule->bytes, NULL); + + rule->os_fingerprint = nvlist_get_number(nvl, "os_fingerprint"); + + rule->rtableid = nvlist_get_number(nvl, "rtableid"); + pf_nvuint_32_array(nvl, "timeout", PFTM_MAX, rule->timeout, NULL); + rule->max_states = nvlist_get_number(nvl, "max_states"); + rule->max_src_nodes = nvlist_get_number(nvl, "max_src_nodes"); + rule->max_src_states = nvlist_get_number(nvl, "max_src_states"); + rule->max_src_conn = nvlist_get_number(nvl, "max_src_conn"); + rule->max_src_conn_rate.limit = + nvlist_get_number(nvl, "max_src_conn_rate.limit"); + rule->max_src_conn_rate.seconds = + nvlist_get_number(nvl, "max_src_conn_rate.seconds"); + rule->qid = nvlist_get_number(nvl, "qid"); + rule->pqid = nvlist_get_number(nvl, "pqid"); + rule->prob = nvlist_get_number(nvl, "prob"); + rule->cuid = nvlist_get_number(nvl, "cuid"); + rule->cpid = nvlist_get_number(nvl, "cpid"); + + rule->return_icmp = nvlist_get_number(nvl, "return_icmp"); + rule->return_icmp6 = nvlist_get_number(nvl, "return_icmp6"); + rule->max_mss = nvlist_get_number(nvl, "max_mss"); + rule->scrub_flags = nvlist_get_number(nvl, "scrub_flags"); + + pf_nvrule_uid_to_rule_uid(nvlist_get_nvlist(nvl, "uid"), &rule->uid); + pf_nvrule_uid_to_rule_uid(nvlist_get_nvlist(nvl, "gid"), + (struct pf_rule_uid *)&rule->gid); + + rule->rule_flag = nvlist_get_number(nvl, "rule_flag"); + rule->action = nvlist_get_number(nvl, "action"); + rule->direction = nvlist_get_number(nvl, "direction"); + rule->log = nvlist_get_number(nvl, "log"); + rule->logif = nvlist_get_number(nvl, "logif"); + rule->quick = nvlist_get_number(nvl, "quick"); + rule->ifnot = nvlist_get_number(nvl, "ifnot"); + rule->match_tag_not = nvlist_get_number(nvl, "match_tag_not"); + rule->natpass = nvlist_get_number(nvl, "natpass"); + + rule->keep_state = nvlist_get_number(nvl, "keep_state"); + rule->af = nvlist_get_number(nvl, "af"); + rule->proto = nvlist_get_number(nvl, "proto"); + rule->type = nvlist_get_number(nvl, "type"); + rule->code = nvlist_get_number(nvl, "code"); + rule->flags = nvlist_get_number(nvl, "flags"); + rule->flagset = nvlist_get_number(nvl, "flagset"); + rule->min_ttl = nvlist_get_number(nvl, "min_ttl"); + rule->allow_opts = nvlist_get_number(nvl, "allow_opts"); + rule->rt = nvlist_get_number(nvl, "rt"); + rule->return_ttl = nvlist_get_number(nvl, "return_ttl"); + rule->tos = nvlist_get_number(nvl, "tos"); + rule->set_tos = nvlist_get_number(nvl, "set_tos"); + rule->anchor_relative = nvlist_get_number(nvl, "anchor_relative"); + rule->anchor_wildcard = nvlist_get_number(nvl, "anchor_wildcard"); + + rule->flush = nvlist_get_number(nvl, "flush"); + rule->prio = nvlist_get_number(nvl, "prio"); + pf_nvuint_8_array(nvl, "set_prio", 2, rule->set_prio, NULL); + + pf_nvdivert_to_divert(nvlist_get_nvlist(nvl, "divert"), rule); + + rule->u_states_cur = nvlist_get_number(nvl, "states_cur"); + rule->u_states_tot = nvlist_get_number(nvl, "states_tot"); + rule->u_src_nodes = nvlist_get_number(nvl, "src_nodes"); +} + +int +pfctl_add_rule(int dev, const struct pf_rule *r, const char *anchor, + const char *anchor_call, u_int32_t ticket, u_int32_t pool_ticket) +{ + struct pfioc_nv nv; + u_int64_t timeouts[PFTM_MAX]; + u_int64_t set_prio[2]; + nvlist_t *nvl, *nvlr; + int ret; + + nvl = nvlist_create(0); + nvlr = nvlist_create(0); + + nvlist_add_number(nvl, "ticket", ticket); + nvlist_add_number(nvl, "pool_ticket", pool_ticket); + nvlist_add_string(nvl, "anchor", anchor); + nvlist_add_string(nvl, "anchor_call", anchor_call); + + nvlist_add_number(nvlr, "nr", r->nr); + pfctl_nv_add_rule_addr(nvlr, "src", &r->src); + pfctl_nv_add_rule_addr(nvlr, "dst", &r->dst); + + nvlist_add_string(nvlr, "label", r->label); + nvlist_add_string(nvlr, "ifname", r->ifname); + nvlist_add_string(nvlr, "qname", r->qname); + nvlist_add_string(nvlr, "pqname", r->pqname); + nvlist_add_string(nvlr, "tagname", r->tagname); + nvlist_add_string(nvlr, "match_tagname", r->match_tagname); + nvlist_add_string(nvlr, "overload_tblname", r->overload_tblname); + + pfctl_nv_add_pool(nvlr, "rpool", &r->rpool); + + nvlist_add_number(nvlr, "os_fingerprint", r->os_fingerprint); + + nvlist_add_number(nvlr, "rtableid", r->rtableid); + for (int i = 0; i < PFTM_MAX; i++) + timeouts[i] = r->timeout[i]; + nvlist_add_number_array(nvlr, "timeout", timeouts, PFTM_MAX); + nvlist_add_number(nvlr, "max_states", r->max_states); + nvlist_add_number(nvlr, "max_src_nodes", r->max_src_nodes); + nvlist_add_number(nvlr, "max_src_states", r->max_src_states); + nvlist_add_number(nvlr, "max_src_conn", r->max_src_conn); + nvlist_add_number(nvlr, "max_src_conn_rate.limit", + r->max_src_conn_rate.limit); + nvlist_add_number(nvlr, "max_src_conn_rate.seconds", + r->max_src_conn_rate.seconds); + nvlist_add_number(nvlr, "prob", r->prob); + nvlist_add_number(nvlr, "cuid", r->cuid); + nvlist_add_number(nvlr, "cpid", r->cpid); + + nvlist_add_number(nvlr, "return_icmp", r->return_icmp); + nvlist_add_number(nvlr, "return_icmp6", r->return_icmp6); + + nvlist_add_number(nvlr, "max_mss", r->max_mss); + nvlist_add_number(nvlr, "scrub_flags", r->scrub_flags); + + pfctl_nv_add_uid(nvlr, "uid", &r->uid); + pfctl_nv_add_uid(nvlr, "gid", (const struct pf_rule_uid *)&r->gid); + + nvlist_add_number(nvlr, "rule_flag", r->rule_flag); + nvlist_add_number(nvlr, "action", r->action); + nvlist_add_number(nvlr, "direction", r->direction); + nvlist_add_number(nvlr, "log", r->log); + nvlist_add_number(nvlr, "logif", r->logif); + nvlist_add_number(nvlr, "quick", r->quick); + nvlist_add_number(nvlr, "ifnot", r->ifnot); + nvlist_add_number(nvlr, "match_tag_not", r->match_tag_not); + nvlist_add_number(nvlr, "natpass", r->natpass); + + nvlist_add_number(nvlr, "keep_state", r->keep_state); + nvlist_add_number(nvlr, "af", r->af); + nvlist_add_number(nvlr, "proto", r->proto); + nvlist_add_number(nvlr, "type", r->type); + nvlist_add_number(nvlr, "code", r->code); + nvlist_add_number(nvlr, "flags", r->flags); + nvlist_add_number(nvlr, "flagset", r->flagset); + nvlist_add_number(nvlr, "min_ttl", r->min_ttl); + nvlist_add_number(nvlr, "allow_opts", r->allow_opts); + nvlist_add_number(nvlr, "rt", r->rt); + nvlist_add_number(nvlr, "return_ttl", r->return_ttl); + nvlist_add_number(nvlr, "tos", r->tos); + nvlist_add_number(nvlr, "set_tos", r->set_tos); + nvlist_add_number(nvlr, "anchor_relative", r->anchor_relative); + nvlist_add_number(nvlr, "anchor_wildcard", r->anchor_wildcard); + + nvlist_add_number(nvlr, "flush", r->flush); + + nvlist_add_number(nvlr, "prio", r->prio); + set_prio[0] = r->set_prio[0]; + set_prio[1] = r->set_prio[1]; + nvlist_add_number_array(nvlr, "set_prio", set_prio, 2); + + pfctl_nv_add_divert(nvlr, "divert", r); + + nvlist_add_nvlist(nvl, "rule", nvlr); + + /* Now do the call. */ + nv.data = nvlist_pack(nvl, &nv.len); + nv.size = nv.len; + + ret = ioctl(dev, DIOCADDRULENV, &nv); + + free(nv.data); + nvlist_destroy(nvl); + + return (ret); +} + +int +pfctl_get_rule(int dev, u_int32_t nr, u_int32_t ticket, const char *anchor, + u_int32_t ruleset, struct pf_rule *rule, char *anchor_call) +{ + struct pfioc_nv nv; + nvlist_t *nvl; + void *nvlpacked; + int ret; + + nvl = nvlist_create(0); + if (nvl == 0) + return (ENOMEM); + + nvlist_add_number(nvl, "nr", nr); + nvlist_add_number(nvl, "ticket", ticket); + nvlist_add_string(nvl, "anchor", anchor); + nvlist_add_number(nvl, "ruleset", ruleset); + + nvlpacked = nvlist_pack(nvl, &nv.len); + if (nvlpacked == NULL) { + nvlist_destroy(nvl); + return (ENOMEM); + } + nv.data = malloc(8182); + nv.size = 8192; + assert(nv.len <= nv.size); + memcpy(nv.data, nvlpacked, nv.len); + nvlist_destroy(nvl); + nvl = NULL; + free(nvlpacked); + + ret = ioctl(dev, DIOCGETRULENV, &nv); + if (ret != 0) { + free(nv.data); + return (ret); + } + + nvl = nvlist_unpack(nv.data, nv.len, 0); + if (nvl == NULL) { + free(nv.data); + return (EIO); + } + + pf_nvrule_to_rule(nvlist_get_nvlist(nvl, "rule"), rule); + + if (anchor_call) + strlcpy(anchor_call, nvlist_get_string(nvl, "anchor_call"), + MAXPATHLEN); + + free(nv.data); + nvlist_destroy(nvl); + + return (0); +} diff --git a/lib/libpfctl/libpfctl.h b/lib/libpfctl/libpfctl.h new file mode 100644 index 000000000000..65ff2179f23d --- /dev/null +++ b/lib/libpfctl/libpfctl.h @@ -0,0 +1,45 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2021 Rubicon Communications, LLC (Netgate) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _PFCTL_IOCTL_H_ +#define _PFCTL_IOCTL_H_ + +#include + +int pfctl_get_rule(int dev, u_int32_t nr, u_int32_t ticket, + const char *anchor, u_int32_t ruleset, struct pf_rule *rule, + char *anchor_call); +int pfctl_add_rule(int dev, const struct pf_rule *r, const char *anchor, + const char *anchor_call, u_int32_t ticket, u_int32_t pool_ticket); + +#endif diff --git a/sbin/pfctl/Makefile b/sbin/pfctl/Makefile index c84d558c989d..49bdfb9e3733 100644 --- a/sbin/pfctl/Makefile +++ b/sbin/pfctl/Makefile @@ -9,13 +9,14 @@ MAN= pfctl.8 SRCS = pfctl.c parse.y pfctl_parser.c pf_print_state.c pfctl_altq.c SRCS+= pfctl_osfp.c pfctl_radix.c pfctl_table.c pfctl_qstats.c -SRCS+= pfctl_optimize.c pfctl_ioctl.c +SRCS+= pfctl_optimize.c SRCS+= pf_ruleset.c WARNS?= 2 CFLAGS+= -Wall -Wmissing-prototypes -Wno-uninitialized CFLAGS+= -Wstrict-prototypes CFLAGS+= -DENABLE_ALTQ -I${.CURDIR} +CFLAGS+= -I${SRCTOP}/lib/libpfctl -I${OBJTOP}/lib/libpfctl # Need to use "WITH_" prefix to not conflict with the l/y INET/INET6 keywords .if ${MK_INET6_SUPPORT} != "no" @@ -27,7 +28,7 @@ CFLAGS+= -DWITH_INET YFLAGS= -LIBADD= m md nv +LIBADD= m md pfctl HAS_TESTS= SUBDIR.${MK_TESTS}+= tests diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y index 9db85538feaf..89e421e6b5ad 100644 --- a/sbin/pfctl/parse.y +++ b/sbin/pfctl/parse.y @@ -1040,7 +1040,7 @@ anchorrule : ANCHOR anchorname dir quick interface af proto fromto decide_address_family($6.src.host, &r.af); decide_address_family($6.dst.host, &r.af); - pfctl_add_rule(pf, &r, $2); + pfctl_append_rule(pf, &r, $2); free($2); } ; @@ -4390,7 +4390,7 @@ binatrule : no BINAT natpasslog interface af proto FROM ipspec toipspec tag free($13); } - pfctl_add_rule(pf, &binat, ""); + pfctl_append_rule(pf, &binat, ""); } ; @@ -5407,7 +5407,7 @@ expand_rule(struct pf_rule *r, yyerror("skipping rule due to errors"); else { r->nr = pf->astack[pf->asd]->match++; - pfctl_add_rule(pf, r, anchor_call); + pfctl_append_rule(pf, r, anchor_call); added++; } diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c index 1aa17065597b..fde9d61260ef 100644 --- a/sbin/pfctl/pfctl.c +++ b/sbin/pfctl/pfctl.c @@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -63,7 +64,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include "pfctl_ioctl.h" #include "pfctl_parser.h" #include "pfctl.h" @@ -1291,7 +1291,7 @@ pfctl_add_pool(struct pfctl *pf, struct pf_pool *p, sa_family_t af) } int -pfctl_add_rule(struct pfctl *pf, struct pf_rule *r, const char *anchor_call) +pfctl_append_rule(struct pfctl *pf, struct pf_rule *r, const char *anchor_call) { u_int8_t rs_num; struct pf_rule *rule; @@ -1309,22 +1309,22 @@ pfctl_add_rule(struct pfctl *pf, struct pf_rule *r, const char *anchor_call) * Don't make non-brace anchors part of the main anchor pool. */ if ((r->anchor = calloc(1, sizeof(*r->anchor))) == NULL) - err(1, "pfctl_add_rule: calloc"); + err(1, "pfctl_append_rule: calloc"); pf_init_ruleset(&r->anchor->ruleset); r->anchor->ruleset.anchor = r->anchor; if (strlcpy(r->anchor->path, anchor_call, sizeof(rule->anchor->path)) >= sizeof(rule->anchor->path)) - errx(1, "pfctl_add_rule: strlcpy"); + errx(1, "pfctl_append_rule: strlcpy"); if ((p = strrchr(anchor_call, '/')) != NULL) { if (!strlen(p)) - err(1, "pfctl_add_rule: bad anchor name %s", + err(1, "pfctl_append_rule: bad anchor name %s", anchor_call); } else p = (char *)anchor_call; if (strlcpy(r->anchor->name, p, sizeof(rule->anchor->name)) >= sizeof(rule->anchor->name)) - errx(1, "pfctl_add_rule: strlcpy"); + errx(1, "pfctl_append_rule: strlcpy"); } if ((rule = calloc(1, sizeof(*rule))) == NULL) @@ -1427,204 +1427,6 @@ pfctl_load_ruleset(struct pfctl *pf, char *path, struct pf_ruleset *rs, } -static void -pfctl_nv_add_addr(nvlist_t *nvparent, const char *name, - const struct pf_addr *addr) -{ - nvlist_t *nvl = nvlist_create(0); - - nvlist_add_binary(nvl, "addr", addr, sizeof(*addr)); - - nvlist_add_nvlist(nvparent, name, nvl); -} - -static void -pfctl_nv_add_addr_wrap(nvlist_t *nvparent, const char *name, - const struct pf_addr_wrap *addr) -{ - nvlist_t *nvl = nvlist_create(0); - - nvlist_add_number(nvl, "type", addr->type); - nvlist_add_number(nvl, "iflags", addr->iflags); - nvlist_add_string(nvl, "ifname", addr->v.ifname); - nvlist_add_string(nvl, "tblname", addr->v.tblname); - pfctl_nv_add_addr(nvl, "addr", &addr->v.a.addr); - pfctl_nv_add_addr(nvl, "mask", &addr->v.a.mask); - - nvlist_add_nvlist(nvparent, name, nvl); -} - -static void -pfctl_nv_add_rule_addr(nvlist_t *nvparent, const char *name, - const struct pf_rule_addr *addr) -{ - u_int64_t ports[2]; - nvlist_t *nvl = nvlist_create(0); - - pfctl_nv_add_addr_wrap(nvl, "addr", &addr->addr); - ports[0] = addr->port[0]; - ports[1] = addr->port[1]; - nvlist_add_number_array(nvl, "port", ports, 2); - nvlist_add_number(nvl, "neg", addr->neg); - nvlist_add_number(nvl, "port_op", addr->port_op); - - nvlist_add_nvlist(nvparent, name, nvl); -} - -static void -pfctl_nv_add_pool(nvlist_t *nvparent, const char *name, - const struct pf_pool *pool) -{ - u_int64_t ports[2]; - nvlist_t *nvl = nvlist_create(0); - - nvlist_add_binary(nvl, "key", &pool->key, sizeof(pool->key)); - pfctl_nv_add_addr(nvl, "counter", &pool->counter); - nvlist_add_number(nvl, "tblidx", pool->tblidx); - - ports[0] = pool->proxy_port[0]; - ports[1] = pool->proxy_port[1]; - nvlist_add_number_array(nvl, "proxy_port", ports, 2); - nvlist_add_number(nvl, "opts", pool->opts); - - nvlist_add_nvlist(nvparent, name, nvl); -} - -static void -pfctl_nv_add_uid(nvlist_t *nvparent, const char *name, - const struct pf_rule_uid *uid) -{ - u_int64_t uids[2]; - nvlist_t *nvl = nvlist_create(0); - - uids[0] = uid->uid[0]; - uids[1] = uid->uid[1]; - nvlist_add_number_array(nvl, "uid", uids, 2); - nvlist_add_number(nvl, "op", uid->op); - - nvlist_add_nvlist(nvparent, name, nvl); -} - -static void -pfctl_nv_add_divert(nvlist_t *nvparent, const char *name, - const struct pf_rule *r) -{ - nvlist_t *nvl = nvlist_create(0); - - pfctl_nv_add_addr(nvl, "addr", &r->divert.addr); - nvlist_add_number(nvl, "port", r->divert.port); - - nvlist_add_nvlist(nvparent, name, nvl); -} - -static int -pfctl_addrule(struct pfctl *pf, const struct pf_rule *r, const char *anchor, - const char *anchor_call, u_int32_t ticket, u_int32_t pool_ticket) -{ - struct pfioc_nv nv; - u_int64_t timeouts[PFTM_MAX]; - u_int64_t set_prio[2]; - nvlist_t *nvl, *nvlr; - int ret; - - nvl = nvlist_create(0); - nvlr = nvlist_create(0); - - nvlist_add_number(nvl, "ticket", ticket); - nvlist_add_number(nvl, "pool_ticket", pool_ticket); - nvlist_add_string(nvl, "anchor", anchor); - nvlist_add_string(nvl, "anchor_call", anchor_call); - - nvlist_add_number(nvlr, "nr", r->nr); - pfctl_nv_add_rule_addr(nvlr, "src", &r->src); - pfctl_nv_add_rule_addr(nvlr, "dst", &r->dst); - - nvlist_add_string(nvlr, "label", r->label); - nvlist_add_string(nvlr, "ifname", r->ifname); - nvlist_add_string(nvlr, "qname", r->qname); - nvlist_add_string(nvlr, "pqname", r->pqname); - nvlist_add_string(nvlr, "tagname", r->tagname); - nvlist_add_string(nvlr, "match_tagname", r->match_tagname); - nvlist_add_string(nvlr, "overload_tblname", r->overload_tblname); - - pfctl_nv_add_pool(nvlr, "rpool", &r->rpool); - - nvlist_add_number(nvlr, "os_fingerprint", r->os_fingerprint); - - nvlist_add_number(nvlr, "rtableid", r->rtableid); - for (int i = 0; i < PFTM_MAX; i++) - timeouts[i] = r->timeout[i]; - nvlist_add_number_array(nvlr, "timeout", timeouts, PFTM_MAX); - nvlist_add_number(nvlr, "max_states", r->max_states); - nvlist_add_number(nvlr, "max_src_nodes", r->max_src_nodes); - nvlist_add_number(nvlr, "max_src_states", r->max_src_states); - nvlist_add_number(nvlr, "max_src_conn", r->max_src_conn); - nvlist_add_number(nvlr, "max_src_conn_rate.limit", - r->max_src_conn_rate.limit); - nvlist_add_number(nvlr, "max_src_conn_rate.seconds", - r->max_src_conn_rate.seconds); - nvlist_add_number(nvlr, "prob", r->prob); - nvlist_add_number(nvlr, "cuid", r->cuid); - nvlist_add_number(nvlr, "cpid", r->cpid); - - nvlist_add_number(nvlr, "return_icmp", r->return_icmp); - nvlist_add_number(nvlr, "return_icmp6", r->return_icmp6); - - nvlist_add_number(nvlr, "max_mss", r->max_mss); - nvlist_add_number(nvlr, "scrub_flags", r->scrub_flags); - - pfctl_nv_add_uid(nvlr, "uid", &r->uid); - pfctl_nv_add_uid(nvlr, "gid", (struct pf_rule_uid *)&r->gid); - - nvlist_add_number(nvlr, "rule_flag", r->rule_flag); - nvlist_add_number(nvlr, "action", r->action); - nvlist_add_number(nvlr, "direction", r->direction); - nvlist_add_number(nvlr, "log", r->log); - nvlist_add_number(nvlr, "logif", r->logif); - nvlist_add_number(nvlr, "quick", r->quick); - nvlist_add_number(nvlr, "ifnot", r->ifnot); - nvlist_add_number(nvlr, "match_tag_not", r->match_tag_not); - nvlist_add_number(nvlr, "natpass", r->natpass); - - nvlist_add_number(nvlr, "keep_state", r->keep_state); - nvlist_add_number(nvlr, "af", r->af); - nvlist_add_number(nvlr, "proto", r->proto); - nvlist_add_number(nvlr, "type", r->type); - nvlist_add_number(nvlr, "code", r->code); - nvlist_add_number(nvlr, "flags", r->flags); - nvlist_add_number(nvlr, "flagset", r->flagset); - nvlist_add_number(nvlr, "min_ttl", r->min_ttl); - nvlist_add_number(nvlr, "allow_opts", r->allow_opts); - nvlist_add_number(nvlr, "rt", r->rt); - nvlist_add_number(nvlr, "return_ttl", r->return_ttl); - nvlist_add_number(nvlr, "tos", r->tos); - nvlist_add_number(nvlr, "set_tos", r->set_tos); - nvlist_add_number(nvlr, "anchor_relative", r->anchor_relative); - nvlist_add_number(nvlr, "anchor_wildcard", r->anchor_wildcard); - - nvlist_add_number(nvlr, "flush", r->flush); - - nvlist_add_number(nvlr, "prio", r->prio); - set_prio[0] = r->set_prio[0]; - set_prio[1] = r->set_prio[1]; - nvlist_add_number_array(nvlr, "set_prio", set_prio, 2); - - pfctl_nv_add_divert(nvlr, "divert", r); - - nvlist_add_nvlist(nvl, "rule", nvlr); - - /* Now do the call. */ - nv.data = nvlist_pack(nvl, &nv.len); - nv.size = nv.len; - - ret = ioctl(pf->dev, DIOCADDRULENV, &nv); - - free(nv.data); - nvlist_destroy(nvl); - - return (ret); -} - int pfctl_load_rule(struct pfctl *pf, char *path, struct pf_rule *r, int depth) { @@ -1657,7 +1459,7 @@ pfctl_load_rule(struct pfctl *pf, char *path, struct pf_rule *r, int depth) if ((pf->opts & PF_OPT_NOACTION) == 0) { if (pfctl_add_pool(pf, &r->rpool, r->af)) return (1); - if (pfctl_addrule(pf, r, anchor, name, ticket, + if (pfctl_add_rule(pf->dev, r, anchor, name, ticket, pf->paddr.ticket)) err(1, "DIOCADDRULENV"); } diff --git a/sbin/pfctl/pfctl_ioctl.c b/sbin/pfctl/pfctl_ioctl.c deleted file mode 100644 index 878a57de0fe4..000000000000 --- a/sbin/pfctl/pfctl_ioctl.c +++ /dev/null @@ -1,339 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2021 Rubicon Communications, LLC (Netgate) - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "pfctl_ioctl.h" - -static void -pf_nvuint_8_array(const nvlist_t *nvl, const char *name, size_t maxelems, - u_int8_t *numbers, size_t *nelems) -{ - const uint64_t *tmp; - size_t elems; - - tmp = nvlist_get_number_array(nvl, name, &elems); - assert(elems <= maxelems); - - for (size_t i = 0; i < elems; i++) - numbers[i] = tmp[i]; - - if (nelems) - *nelems = elems; -} - -static void -pf_nvuint_16_array(const nvlist_t *nvl, const char *name, size_t maxelems, - u_int16_t *numbers, size_t *nelems) -{ - const uint64_t *tmp; - size_t elems; - - tmp = nvlist_get_number_array(nvl, name, &elems); - assert(elems <= maxelems); - - for (size_t i = 0; i < elems; i++) - numbers[i] = tmp[i]; - - if (nelems) - *nelems = elems; -} - -static void -pf_nvuint_32_array(const nvlist_t *nvl, const char *name, size_t maxelems, - u_int32_t *numbers, size_t *nelems) -{ - const uint64_t *tmp; - size_t elems; - - tmp = nvlist_get_number_array(nvl, name, &elems); - assert(elems <= maxelems); - - for (size_t i = 0; i < elems; i++) - numbers[i] = tmp[i]; - - if (nelems) - *nelems = elems; -} - -static void -pf_nvuint_64_array(const nvlist_t *nvl, const char *name, size_t maxelems, - u_int64_t *numbers, size_t *nelems) -{ - const uint64_t *tmp; - size_t elems; - - tmp = nvlist_get_number_array(nvl, name, &elems); - assert(elems <= maxelems); - - for (size_t i = 0; i < elems; i++) - numbers[i] = tmp[i]; - - if (nelems) - *nelems = elems; -} - -static void -pf_nvaddr_to_addr(const nvlist_t *nvl, struct pf_addr *addr) -{ - size_t len; - const void *data; - - data = nvlist_get_binary(nvl, "addr", &len); - assert(len == sizeof(struct pf_addr)); - memcpy(addr, data, len); -} - -static void -pf_nvaddr_wrap_to_addr_wrap(const nvlist_t *nvl, struct pf_addr_wrap *addr) -{ - addr->type = nvlist_get_number(nvl, "type"); - addr->iflags = nvlist_get_number(nvl, "iflags"); - strlcpy(addr->v.ifname, nvlist_get_string(nvl, "ifname"), IFNAMSIZ); - strlcpy(addr->v.tblname, nvlist_get_string(nvl, "tblname"), - PF_TABLE_NAME_SIZE); - - pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "addr"), &addr->v.a.addr); - pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "mask"), &addr->v.a.mask); -} - -static void -pf_nvrule_addr_to_rule_addr(const nvlist_t *nvl, struct pf_rule_addr *addr) -{ - pf_nvaddr_wrap_to_addr_wrap(nvlist_get_nvlist(nvl, "addr"), &addr->addr); - - pf_nvuint_16_array(nvl, "port", 2, addr->port, NULL); - addr->neg = nvlist_get_number(nvl, "neg"); - addr->port_op = nvlist_get_number(nvl, "port_op"); -} - -static void -pf_nvpool_to_pool(const nvlist_t *nvl, struct pf_pool *pool) -{ - size_t len; - const void *data; - - data = nvlist_get_binary(nvl, "key", &len); - assert(len == sizeof(pool->key)); - memcpy(&pool->key, data, len); - - pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "counter"), &pool->counter); - - pool->tblidx = nvlist_get_number(nvl, "tblidx"); - pf_nvuint_16_array(nvl, "proxy_port", 2, pool->proxy_port, NULL); - pool->opts = nvlist_get_number(nvl, "opts"); -} - -static void -pf_nvrule_uid_to_rule_uid(const nvlist_t *nvl, struct pf_rule_uid *uid) -{ - pf_nvuint_32_array(nvl, "uid", 2, uid->uid, NULL); - uid->op = nvlist_get_number(nvl, "op"); -} - -static void -pf_nvdivert_to_divert(const nvlist_t *nvl, struct pf_rule *rule) -{ - pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "addr"), &rule->divert.addr); - rule->divert.port = nvlist_get_number(nvl, "port"); -} - -static void -pf_nvrule_to_rule(const nvlist_t *nvl, struct pf_rule *rule) -{ - const uint64_t *skip; - size_t skipcount; - - rule->nr = nvlist_get_number(nvl, "nr"); - - pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "src"), &rule->src); - pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "dst"), &rule->dst); - - skip = nvlist_get_number_array(nvl, "skip", &skipcount); - assert(skip); - assert(skipcount == PF_SKIP_COUNT); - for (int i = 0; i < PF_SKIP_COUNT; i++) - rule->skip[i].nr = skip[i]; - - strlcpy(rule->label, nvlist_get_string(nvl, "label"), PF_RULE_LABEL_SIZE); - strlcpy(rule->ifname, nvlist_get_string(nvl, "ifname"), IFNAMSIZ); - strlcpy(rule->qname, nvlist_get_string(nvl, "qname"), PF_QNAME_SIZE); - strlcpy(rule->pqname, nvlist_get_string(nvl, "pqname"), PF_QNAME_SIZE); - strlcpy(rule->tagname, nvlist_get_string(nvl, "tagname"), - PF_TAG_NAME_SIZE); - strlcpy(rule->match_tagname, nvlist_get_string(nvl, "match_tagname"), - PF_TAG_NAME_SIZE); - - strlcpy(rule->overload_tblname, nvlist_get_string(nvl, "overload_tblname"), - PF_TABLE_NAME_SIZE); - - pf_nvpool_to_pool(nvlist_get_nvlist(nvl, "rpool"), &rule->rpool); - - rule->evaluations = nvlist_get_number(nvl, "evaluations"); - pf_nvuint_64_array(nvl, "packets", 2, rule->packets, NULL); - pf_nvuint_64_array(nvl, "bytes", 2, rule->bytes, NULL); - - rule->os_fingerprint = nvlist_get_number(nvl, "os_fingerprint"); - - rule->rtableid = nvlist_get_number(nvl, "rtableid"); - pf_nvuint_32_array(nvl, "timeout", PFTM_MAX, rule->timeout, NULL); - rule->max_states = nvlist_get_number(nvl, "max_states"); - rule->max_src_nodes = nvlist_get_number(nvl, "max_src_nodes"); - rule->max_src_states = nvlist_get_number(nvl, "max_src_states"); - rule->max_src_conn = nvlist_get_number(nvl, "max_src_conn"); - rule->max_src_conn_rate.limit = - nvlist_get_number(nvl, "max_src_conn_rate.limit"); - rule->max_src_conn_rate.seconds = - nvlist_get_number(nvl, "max_src_conn_rate.seconds"); - rule->qid = nvlist_get_number(nvl, "qid"); - rule->pqid = nvlist_get_number(nvl, "pqid"); - rule->prob = nvlist_get_number(nvl, "prob"); - rule->cuid = nvlist_get_number(nvl, "cuid"); - rule->cpid = nvlist_get_number(nvl, "cpid"); - - rule->return_icmp = nvlist_get_number(nvl, "return_icmp"); - rule->return_icmp6 = nvlist_get_number(nvl, "return_icmp6"); - rule->max_mss = nvlist_get_number(nvl, "max_mss"); - rule->scrub_flags = nvlist_get_number(nvl, "scrub_flags"); - - pf_nvrule_uid_to_rule_uid(nvlist_get_nvlist(nvl, "uid"), &rule->uid); - pf_nvrule_uid_to_rule_uid(nvlist_get_nvlist(nvl, "gid"), - (struct pf_rule_uid *)&rule->gid); - - rule->rule_flag = nvlist_get_number(nvl, "rule_flag"); - rule->action = nvlist_get_number(nvl, "action"); - rule->direction = nvlist_get_number(nvl, "direction"); - rule->log = nvlist_get_number(nvl, "log"); - rule->logif = nvlist_get_number(nvl, "logif"); - rule->quick = nvlist_get_number(nvl, "quick"); - rule->ifnot = nvlist_get_number(nvl, "ifnot"); - rule->match_tag_not = nvlist_get_number(nvl, "match_tag_not"); - rule->natpass = nvlist_get_number(nvl, "natpass"); - - rule->keep_state = nvlist_get_number(nvl, "keep_state"); - rule->af = nvlist_get_number(nvl, "af"); - rule->proto = nvlist_get_number(nvl, "proto"); - rule->type = nvlist_get_number(nvl, "type"); - rule->code = nvlist_get_number(nvl, "code"); - rule->flags = nvlist_get_number(nvl, "flags"); - rule->flagset = nvlist_get_number(nvl, "flagset"); - rule->min_ttl = nvlist_get_number(nvl, "min_ttl"); - rule->allow_opts = nvlist_get_number(nvl, "allow_opts"); - rule->rt = nvlist_get_number(nvl, "rt"); - rule->return_ttl = nvlist_get_number(nvl, "return_ttl"); - rule->tos = nvlist_get_number(nvl, "tos"); - rule->set_tos = nvlist_get_number(nvl, "set_tos"); - rule->anchor_relative = nvlist_get_number(nvl, "anchor_relative"); - rule->anchor_wildcard = nvlist_get_number(nvl, "anchor_wildcard"); - - rule->flush = nvlist_get_number(nvl, "flush"); - rule->prio = nvlist_get_number(nvl, "prio"); - pf_nvuint_8_array(nvl, "set_prio", 2, rule->set_prio, NULL); - - pf_nvdivert_to_divert(nvlist_get_nvlist(nvl, "divert"), rule); - - rule->u_states_cur = nvlist_get_number(nvl, "states_cur"); - rule->u_states_tot = nvlist_get_number(nvl, "states_tot"); - rule->u_src_nodes = nvlist_get_number(nvl, "src_nodes"); -} - - -int -pfctl_get_rule(int dev, u_int32_t nr, u_int32_t ticket, const char *anchor, - u_int32_t ruleset, struct pf_rule *rule, char *anchor_call) -{ - struct pfioc_nv nv; - nvlist_t *nvl; - void *nvlpacked; - int ret; - - nvl = nvlist_create(0); - if (nvl == 0) - return (ENOMEM); - - nvlist_add_number(nvl, "nr", nr); - nvlist_add_number(nvl, "ticket", ticket); - nvlist_add_string(nvl, "anchor", anchor); - nvlist_add_number(nvl, "ruleset", ruleset); - - nvlpacked = nvlist_pack(nvl, &nv.len); - if (nvlpacked == NULL) { - nvlist_destroy(nvl); - return (ENOMEM); - } - nv.data = malloc(8182); - nv.size = 8192; - assert(nv.len <= nv.size); - memcpy(nv.data, nvlpacked, nv.len); - nvlist_destroy(nvl); - nvl = NULL; - free(nvlpacked); - - ret = ioctl(dev, DIOCGETRULENV, &nv); - if (ret != 0) { - free(nv.data); - return (ret); - } - - nvl = nvlist_unpack(nv.data, nv.len, 0); - if (nvl == NULL) { - free(nv.data); - return (EIO); - } - - pf_nvrule_to_rule(nvlist_get_nvlist(nvl, "rule"), rule); - - if (anchor_call) - strlcpy(anchor_call, nvlist_get_string(nvl, "anchor_call"), - MAXPATHLEN); - - free(nv.data); - nvlist_destroy(nvl); - - return (0); -} diff --git a/sbin/pfctl/pfctl_ioctl.h b/sbin/pfctl/pfctl_ioctl.h index 41dd0776854a..e69de29bb2d1 100644 --- a/sbin/pfctl/pfctl_ioctl.h +++ b/sbin/pfctl/pfctl_ioctl.h @@ -1,43 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2021 Rubicon Communications, LLC (Netgate) - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef _PFCTL_IOCTL_H_ -#define _PFCTL_IOCTL_H_ - -#include - -int pfctl_get_rule(int dev, u_int32_t nr, u_int32_t ticket, - const char *anchor, u_int32_t ruleset, struct pf_rule *rule, - char *anchor_call); - -#endif diff --git a/sbin/pfctl/pfctl_optimize.c b/sbin/pfctl/pfctl_optimize.c index d3f0aa1bf3a4..821a528932f3 100644 --- a/sbin/pfctl/pfctl_optimize.c +++ b/sbin/pfctl/pfctl_optimize.c @@ -33,12 +33,12 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include #include -#include "pfctl_ioctl.h" #include "pfctl_parser.h" #include "pfctl.h" diff --git a/sbin/pfctl/pfctl_parser.h b/sbin/pfctl/pfctl_parser.h index aa6d98d7cf91..2547caa1a8ce 100644 --- a/sbin/pfctl/pfctl_parser.h +++ b/sbin/pfctl/pfctl_parser.h @@ -252,7 +252,7 @@ TAILQ_HEAD(pf_opt_queue, pf_opt_rule); int pfctl_rules(int, char *, int, int, char *, struct pfr_buffer *); int pfctl_optimize_ruleset(struct pfctl *, struct pf_ruleset *); -int pfctl_add_rule(struct pfctl *, struct pf_rule *, const char *); +int pfctl_append_rule(struct pfctl *, struct pf_rule *, const char *); int pfctl_add_altq(struct pfctl *, struct pf_altq *); int pfctl_add_pool(struct pfctl *, struct pf_pool *, sa_family_t); void pfctl_move_pool(struct pf_pool *, struct pf_pool *); diff --git a/share/mk/src.libnames.mk b/share/mk/src.libnames.mk index 1d3195f53eb1..259a65a7afd4 100644 --- a/share/mk/src.libnames.mk +++ b/share/mk/src.libnames.mk @@ -57,6 +57,7 @@ _INTERNALLIBS= \ opts \ parse \ pe \ + pfctl \ pmcstat \ sl \ sm \ @@ -387,6 +388,7 @@ _DP_zutil= avl tpool _DP_be= zfs spl nvpair zfsbootenv _DP_netmap= _DP_ifconfig= m +_DP_pfctl= nv # OFED support .if ${MK_OFED} != "no" @@ -564,6 +566,9 @@ LIBOPTS?= ${LIBOPTSDIR}/libopts${PIE_SUFFIX}.a LIBPARSEDIR= ${_LIB_OBJTOP}/usr.sbin/ntp/libparse LIBPARSE?= ${LIBPARSEDIR}/libparse${PIE_SUFFIX}.a +LIBPFCTL= ${_LIB_OBJTOP}/lib/libpfctl +LIBPFCTL?= ${LIBPFCTLDIR}/libpfctl${PIE_SUFFIX}.a + LIBLPRDIR= ${_LIB_OBJTOP}/usr.sbin/lpr/common_source LIBLPR?= ${LIBLPRDIR}/liblpr${PIE_SUFFIX}.a -- cgit v1.2.3