Page MenuHomeFreeBSD

D29560.diff
No OneTemporary

D29560.diff

diff --git a/sbin/pfctl/Makefile b/sbin/pfctl/Makefile
--- a/sbin/pfctl/Makefile
+++ b/sbin/pfctl/Makefile
@@ -9,7 +9,7 @@
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
+SRCS+= pfctl_optimize.c pfctl_ioctl.c
SRCS+= pf_ruleset.c
WARNS?= 2
diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
--- a/sbin/pfctl/pfctl.c
+++ b/sbin/pfctl/pfctl.c
@@ -63,6 +63,7 @@
#include <string.h>
#include <unistd.h>
+#include "pfctl_ioctl.h"
#include "pfctl_parser.h"
#include "pfctl.h"
@@ -952,8 +953,9 @@
for (nr = 0; nr < mnr; ++nr) {
pr.nr = nr;
- if (ioctl(dev, DIOCGETRULE, &pr)) {
- warn("DIOCGETRULE");
+ if (pfctl_get_rule(dev, nr, pr.ticket, path, PF_SCRUB,
+ &pr.rule, pr.anchor_call)) {
+ warn("DIOCGETRULENV");
goto error;
}
@@ -984,7 +986,8 @@
mnr = pr.nr;
for (nr = 0; nr < mnr; ++nr) {
pr.nr = nr;
- if (ioctl(dev, DIOCGETRULE, &pr)) {
+ if (pfctl_get_rule(dev, nr, pr.ticket, path, PF_PASS,
+ &pr.rule, pr.anchor_call)) {
warn("DIOCGETRULE");
goto error;
}
@@ -1074,7 +1077,8 @@
mnr = pr.nr;
for (nr = 0; nr < mnr; ++nr) {
pr.nr = nr;
- if (ioctl(dev, DIOCGETRULE, &pr)) {
+ if (pfctl_get_rule(dev, nr, pr.ticket, anchorname,
+ nattype[i], &pr.rule, pr.anchor_call)) {
warn("DIOCGETRULE");
return (-1);
}
diff --git a/sbin/pfctl/pfctl_ioctl.h b/sbin/pfctl/pfctl_ioctl.h
new file mode 100644
--- /dev/null
+++ b/sbin/pfctl/pfctl_ioctl.h
@@ -0,0 +1,43 @@
+/*-
+ * 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 <netpfil/pf/pf.h>
+
+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_ioctl.c b/sbin/pfctl/pfctl_ioctl.c
new file mode 100644
--- /dev/null
+++ b/sbin/pfctl/pfctl_ioctl.c
@@ -0,0 +1,339 @@
+/*-
+ * 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 <sys/cdefs.h>
+
+#include <sys/ioctl.h>
+#include <sys/nv.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+
+#include <net/if.h>
+#include <net/pfvar.h>
+#include <netinet/in.h>
+
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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_optimize.c b/sbin/pfctl/pfctl_optimize.c
--- a/sbin/pfctl/pfctl_optimize.c
+++ b/sbin/pfctl/pfctl_optimize.c
@@ -38,6 +38,7 @@
#include <stdlib.h>
#include <string.h>
+#include "pfctl_ioctl.h"
#include "pfctl_parser.h"
#include "pfctl.h"
@@ -909,8 +910,10 @@
return (1);
}
pr.nr = nr;
- if (ioctl(pf->dev, DIOCGETRULE, &pr)) {
- warn("DIOCGETRULES");
+
+ if (pfctl_get_rule(pf->dev, nr, pr.ticket, "", PF_PASS,
+ &pr.rule, pr.anchor_call)) {
+ warn("DIOCGETRULENV");
return (1);
}
memcpy(&por->por_rule, &pr.rule, sizeof(por->por_rule));

File Metadata

Mime Type
text/plain
Expires
Tue, Dec 24, 6:19 AM (19 h, 20 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15585998
Default Alt Text
D29560.diff (14 KB)

Event Timeline