2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2019 Gleb Smirnoff <glebius@FreeBSD.org>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
31 #include <sys/param.h>
32 #include <sys/ioctl.h>
45 static const char * const typenames[] = {
46 [PFIL_TYPE_IP4] = "IPv4",
47 [PFIL_TYPE_IP6] = "IPv6",
48 [PFIL_TYPE_ETHERNET] = "Ethernet",
51 static void listheads(int argc, char *argv[]);
52 static void listhooks(int argc, char *argv[]);
53 static void hook(int argc, char *argv[]);
54 static void help(void);
56 static const struct cmd {
58 void (*cmd_func)(int argc, char *argv[]);
60 { "heads", listheads },
61 { "hooks", listhooks },
68 main(int argc __unused, char *argv[] __unused)
76 for (int i = 0; cmds[i].cmd_name != NULL; i++)
77 if (!strncmp(argv[0], cmds[i].cmd_name, strlen(argv[0]))) {
79 errx(1, "ambiguous command: %s", argv[0]);
83 errx(1, "unknown command: %s", argv[0]);
85 dev = open("/dev/" PFILDEV, O_RDWR);
87 err(1, "open(%s)", "/dev/" PFILDEV);
89 (*cmds[cmd].cmd_func)(argc, argv);
98 fprintf(stderr, "usage: %s (heads|hooks|link|unlink)\n", getprogname());
103 listheads(int argc __unused, char *argv[] __unused)
105 struct pfilioc_list plh;
106 u_int nheads, nhooks, i;
111 if (ioctl(dev, PFILIOC_LISTHEADS, &plh) != 0)
112 err(1, "ioctl(PFILIOC_LISTHEADS)");
115 plh.pio_heads = calloc(plh.pio_nheads, sizeof(struct pfilioc_head));
116 if (plh.pio_heads == NULL)
118 plh.pio_hooks = calloc(plh.pio_nhooks, sizeof(struct pfilioc_hook));
119 if (plh.pio_hooks == NULL)
122 nheads = plh.pio_nheads;
123 nhooks = plh.pio_nhooks;
125 if (ioctl(dev, PFILIOC_LISTHEADS, &plh) != 0)
126 err(1, "ioctl(PFILIOC_LISTHEADS)");
128 if (plh.pio_nheads > nheads || plh.pio_nhooks > nhooks) {
134 #define FMTHD "%16s %8s\n"
135 #define FMTHK "%29s %16s:%s\n"
136 printf("%16s %8s %3s %16s\n", "Intercept point", "Type", "Dir", "Hook");
137 for (i = 0, h = 0; i < plh.pio_nheads; i++) {
138 printf(FMTHD, plh.pio_heads[i].pio_name,
139 typenames[plh.pio_heads[i].pio_type]);
140 for (j = 0; j < plh.pio_heads[i].pio_nhooksin; j++, h++)
141 printf(FMTHK, "In", plh.pio_hooks[h].pio_module,
142 plh.pio_hooks[h].pio_ruleset);
143 for (j = 0; j < plh.pio_heads[i].pio_nhooksout; j++, h++)
144 printf(FMTHK, "Out", plh.pio_hooks[h].pio_module,
145 plh.pio_hooks[h].pio_ruleset);
150 listhooks(int argc __unused, char *argv[] __unused)
152 struct pfilioc_list plh;
156 if (ioctl(dev, PFILIOC_LISTHEADS, &plh) != 0)
157 err(1, "ioctl(PFILIOC_LISTHEADS)");
159 plh.pio_hooks = calloc(plh.pio_nhooks, sizeof(struct pfilioc_hook));
160 if (plh.pio_hooks == NULL)
163 nhooks = plh.pio_nhooks;
165 if (ioctl(dev, PFILIOC_LISTHOOKS, &plh) != 0)
166 err(1, "ioctl(PFILIOC_LISTHOOKS)");
168 if (plh.pio_nhooks > nhooks) {
173 printf("%16s %16s %8s\n", "Hook", "", "Type");
174 for (i = 0; i < plh.pio_nhooks; i++) {
175 printf("%16s:%-16s %8s\n", plh.pio_hooks[i].pio_module,
176 plh.pio_hooks[i].pio_ruleset,
177 typenames[plh.pio_hooks[i].pio_type]);
182 hook(int argc, char *argv[])
184 struct pfilioc_link req;
188 if (argv[0][0] == 'u')
189 req.pio_flags = PFIL_UNLINK;
193 while ((c = getopt(argc, argv, "ioa")) != -1)
196 req.pio_flags |= PFIL_IN;
199 req.pio_flags |= PFIL_OUT;
202 req.pio_flags |= PFIL_APPEND;
208 if (!PFIL_DIR(req.pio_flags))
217 /* link mod:ruleset head */
218 if ((ruleset = strchr(argv[0], ':')) == NULL)
223 strlcpy(req.pio_name, argv[1], sizeof(req.pio_name));
224 strlcpy(req.pio_module, argv[0], sizeof(req.pio_module));
225 strlcpy(req.pio_ruleset, ruleset, sizeof(req.pio_ruleset));
227 if (ioctl(dev, PFILIOC_LINK, &req) != 0)
228 err(1, "ioctl(PFILIOC_LINK)");