1fda7daf0SKristof Provost /*-
2fda7daf0SKristof Provost * SPDX-License-Identifier: BSD-2-Clause
3fda7daf0SKristof Provost *
4fda7daf0SKristof Provost * Copyright (c) 2001 Daniel Hartmeier
5fda7daf0SKristof Provost * Copyright (c) 2002,2003 Henning Brauer
6fda7daf0SKristof Provost * All rights reserved.
7fda7daf0SKristof Provost *
8fda7daf0SKristof Provost * Redistribution and use in source and binary forms, with or without
9fda7daf0SKristof Provost * modification, are permitted provided that the following conditions
10fda7daf0SKristof Provost * are met:
11fda7daf0SKristof Provost *
12fda7daf0SKristof Provost * - Redistributions of source code must retain the above copyright
13fda7daf0SKristof Provost * notice, this list of conditions and the following disclaimer.
14fda7daf0SKristof Provost * - Redistributions in binary form must reproduce the above
15fda7daf0SKristof Provost * copyright notice, this list of conditions and the following
16fda7daf0SKristof Provost * disclaimer in the documentation and/or other materials provided
17fda7daf0SKristof Provost * with the distribution.
18fda7daf0SKristof Provost *
19fda7daf0SKristof Provost * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20fda7daf0SKristof Provost * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21fda7daf0SKristof Provost * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22fda7daf0SKristof Provost * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23fda7daf0SKristof Provost * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24fda7daf0SKristof Provost * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25fda7daf0SKristof Provost * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26fda7daf0SKristof Provost * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27fda7daf0SKristof Provost * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28fda7daf0SKristof Provost * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29fda7daf0SKristof Provost * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30fda7daf0SKristof Provost * POSSIBILITY OF SUCH DAMAGE.
31fda7daf0SKristof Provost *
32fda7daf0SKristof Provost * Effort sponsored in part by the Defense Advanced Research Projects
33fda7daf0SKristof Provost * Agency (DARPA) and Air Force Research Laboratory, Air Force
34fda7daf0SKristof Provost * Materiel Command, USAF, under agreement number F30602-01-2-0537.
35fda7daf0SKristof Provost *
36fda7daf0SKristof Provost * $OpenBSD: pf_ruleset.c,v 1.2 2008/12/18 15:31:37 dhill Exp $
37fda7daf0SKristof Provost */
38fda7daf0SKristof Provost
39fda7daf0SKristof Provost #include <sys/param.h>
40fda7daf0SKristof Provost #include <sys/socket.h>
41fda7daf0SKristof Provost #include <sys/mbuf.h>
42fda7daf0SKristof Provost
43fda7daf0SKristof Provost #include <netinet/in.h>
44fda7daf0SKristof Provost #include <netinet/in_systm.h>
45fda7daf0SKristof Provost #include <netinet/ip.h>
46fda7daf0SKristof Provost #include <netinet/tcp.h>
47fda7daf0SKristof Provost
48fda7daf0SKristof Provost #include <net/if.h>
49fda7daf0SKristof Provost #include <net/vnet.h>
50fda7daf0SKristof Provost #include <net/pfvar.h>
51fda7daf0SKristof Provost
52fda7daf0SKristof Provost #ifdef INET6
53fda7daf0SKristof Provost #include <netinet/ip6.h>
54fda7daf0SKristof Provost #endif /* INET6 */
55fda7daf0SKristof Provost
56fda7daf0SKristof Provost #include <arpa/inet.h>
57fda7daf0SKristof Provost #include <errno.h>
58fda7daf0SKristof Provost #include <stdio.h>
59fda7daf0SKristof Provost #include <stdlib.h>
60fda7daf0SKristof Provost #include <string.h>
61fda7daf0SKristof Provost #define rs_malloc(x) calloc(1, x)
62fda7daf0SKristof Provost #define rs_free(x) free(x)
63fda7daf0SKristof Provost
64a9b338b2SKristof Provost #include "pfctl.h"
65*c5131afeSKristof Provost #include "pfctl_parser.h"
66a9b338b2SKristof Provost
67fda7daf0SKristof Provost #ifdef PFDEBUG
68fda7daf0SKristof Provost #include <sys/stdarg.h>
69fda7daf0SKristof Provost #define DPFPRINTF(format, x...) fprintf(stderr, format , ##x)
70fda7daf0SKristof Provost #else
71fda7daf0SKristof Provost #define DPFPRINTF(format, x...) ((void)0)
72fda7daf0SKristof Provost #endif /* PFDEBUG */
73fda7daf0SKristof Provost
74e9eb0941SKristof Provost struct pfctl_anchor_global pf_anchors;
75*c5131afeSKristof Provost extern struct pfctl_anchor pf_main_anchor;
76*c5131afeSKristof Provost extern struct pfctl_eth_anchor pf_eth_main_anchor;
77fda7daf0SKristof Provost #undef V_pf_anchors
78fda7daf0SKristof Provost #define V_pf_anchors pf_anchors
79fda7daf0SKristof Provost #undef pf_main_ruleset
80fda7daf0SKristof Provost #define pf_main_ruleset pf_main_anchor.ruleset
81fda7daf0SKristof Provost
82e9eb0941SKristof Provost static __inline int pf_anchor_compare(struct pfctl_anchor *,
83e9eb0941SKristof Provost struct pfctl_anchor *);
84e9eb0941SKristof Provost static struct pfctl_anchor *pf_find_anchor(const char *);
85fda7daf0SKristof Provost
86e9eb0941SKristof Provost RB_GENERATE(pfctl_anchor_global, pfctl_anchor, entry_global,
87e9eb0941SKristof Provost pf_anchor_compare);
88e9eb0941SKristof Provost RB_GENERATE(pfctl_anchor_node, pfctl_anchor, entry_node, pf_anchor_compare);
89fda7daf0SKristof Provost
90fda7daf0SKristof Provost static __inline int
pf_anchor_compare(struct pfctl_anchor * a,struct pfctl_anchor * b)91e9eb0941SKristof Provost pf_anchor_compare(struct pfctl_anchor *a, struct pfctl_anchor *b)
92fda7daf0SKristof Provost {
93fda7daf0SKristof Provost int c = strcmp(a->path, b->path);
94fda7daf0SKristof Provost
95fda7daf0SKristof Provost return (c ? (c < 0 ? -1 : 1) : 0);
96fda7daf0SKristof Provost }
97fda7daf0SKristof Provost
98fda7daf0SKristof Provost int
pf_get_ruleset_number(u_int8_t action)99fda7daf0SKristof Provost pf_get_ruleset_number(u_int8_t action)
100fda7daf0SKristof Provost {
101fda7daf0SKristof Provost switch (action) {
102fda7daf0SKristof Provost case PF_SCRUB:
103fda7daf0SKristof Provost case PF_NOSCRUB:
104fda7daf0SKristof Provost return (PF_RULESET_SCRUB);
105fda7daf0SKristof Provost break;
106fda7daf0SKristof Provost case PF_PASS:
107fda7daf0SKristof Provost case PF_DROP:
108ef950daaSKristof Provost case PF_MATCH:
109fda7daf0SKristof Provost return (PF_RULESET_FILTER);
110fda7daf0SKristof Provost break;
111fda7daf0SKristof Provost case PF_NAT:
112fda7daf0SKristof Provost case PF_NONAT:
113fda7daf0SKristof Provost return (PF_RULESET_NAT);
114fda7daf0SKristof Provost break;
115fda7daf0SKristof Provost case PF_BINAT:
116fda7daf0SKristof Provost case PF_NOBINAT:
117fda7daf0SKristof Provost return (PF_RULESET_BINAT);
118fda7daf0SKristof Provost break;
119fda7daf0SKristof Provost case PF_RDR:
120fda7daf0SKristof Provost case PF_NORDR:
121fda7daf0SKristof Provost return (PF_RULESET_RDR);
122fda7daf0SKristof Provost break;
123fda7daf0SKristof Provost default:
124fda7daf0SKristof Provost return (PF_RULESET_MAX);
125fda7daf0SKristof Provost break;
126fda7daf0SKristof Provost }
127fda7daf0SKristof Provost }
128fda7daf0SKristof Provost
129fda7daf0SKristof Provost void
pf_init_ruleset(struct pfctl_ruleset * ruleset)130e9eb0941SKristof Provost pf_init_ruleset(struct pfctl_ruleset *ruleset)
131fda7daf0SKristof Provost {
132fda7daf0SKristof Provost int i;
133fda7daf0SKristof Provost
134e9eb0941SKristof Provost memset(ruleset, 0, sizeof(struct pfctl_ruleset));
135fda7daf0SKristof Provost for (i = 0; i < PF_RULESET_MAX; i++) {
136fda7daf0SKristof Provost TAILQ_INIT(&ruleset->rules[i].queues[0]);
137fda7daf0SKristof Provost TAILQ_INIT(&ruleset->rules[i].queues[1]);
138fda7daf0SKristof Provost ruleset->rules[i].active.ptr = &ruleset->rules[i].queues[0];
139fda7daf0SKristof Provost ruleset->rules[i].inactive.ptr = &ruleset->rules[i].queues[1];
140fda7daf0SKristof Provost }
141fda7daf0SKristof Provost }
142fda7daf0SKristof Provost
143e9eb0941SKristof Provost static struct pfctl_anchor *
pf_find_anchor(const char * path)144fda7daf0SKristof Provost pf_find_anchor(const char *path)
145fda7daf0SKristof Provost {
146e9eb0941SKristof Provost struct pfctl_anchor *key, *found;
147fda7daf0SKristof Provost
148e9eb0941SKristof Provost key = (struct pfctl_anchor *)rs_malloc(sizeof(*key));
149fda7daf0SKristof Provost if (key == NULL)
150fda7daf0SKristof Provost return (NULL);
151fda7daf0SKristof Provost strlcpy(key->path, path, sizeof(key->path));
152e9eb0941SKristof Provost found = RB_FIND(pfctl_anchor_global, &V_pf_anchors, key);
153fda7daf0SKristof Provost rs_free(key);
154fda7daf0SKristof Provost return (found);
155fda7daf0SKristof Provost }
156fda7daf0SKristof Provost
157e9eb0941SKristof Provost struct pfctl_ruleset *
pf_find_ruleset(const char * path)158fda7daf0SKristof Provost pf_find_ruleset(const char *path)
159fda7daf0SKristof Provost {
160e9eb0941SKristof Provost struct pfctl_anchor *anchor;
161fda7daf0SKristof Provost
162fda7daf0SKristof Provost while (*path == '/')
163fda7daf0SKristof Provost path++;
164fda7daf0SKristof Provost if (!*path)
165fda7daf0SKristof Provost return (&pf_main_ruleset);
166fda7daf0SKristof Provost anchor = pf_find_anchor(path);
167fda7daf0SKristof Provost if (anchor == NULL)
168fda7daf0SKristof Provost return (NULL);
169fda7daf0SKristof Provost else
170fda7daf0SKristof Provost return (&anchor->ruleset);
171fda7daf0SKristof Provost }
172fda7daf0SKristof Provost
173e9eb0941SKristof Provost struct pfctl_ruleset *
pf_find_or_create_ruleset(const char * path)174fda7daf0SKristof Provost pf_find_or_create_ruleset(const char *path)
175fda7daf0SKristof Provost {
176fda7daf0SKristof Provost char *p, *q, *r;
177e9eb0941SKristof Provost struct pfctl_ruleset *ruleset;
178e9eb0941SKristof Provost struct pfctl_anchor *anchor = NULL, *dup, *parent = NULL;
179fda7daf0SKristof Provost
180fda7daf0SKristof Provost if (path[0] == 0)
181fda7daf0SKristof Provost return (&pf_main_ruleset);
182fda7daf0SKristof Provost while (*path == '/')
183fda7daf0SKristof Provost path++;
184fda7daf0SKristof Provost ruleset = pf_find_ruleset(path);
185fda7daf0SKristof Provost if (ruleset != NULL)
186fda7daf0SKristof Provost return (ruleset);
187fda7daf0SKristof Provost p = (char *)rs_malloc(MAXPATHLEN);
188fda7daf0SKristof Provost if (p == NULL)
189fda7daf0SKristof Provost return (NULL);
190fda7daf0SKristof Provost strlcpy(p, path, MAXPATHLEN);
191fda7daf0SKristof Provost while (parent == NULL && (q = strrchr(p, '/')) != NULL) {
192fda7daf0SKristof Provost *q = 0;
193fda7daf0SKristof Provost if ((ruleset = pf_find_ruleset(p)) != NULL) {
194fda7daf0SKristof Provost parent = ruleset->anchor;
195fda7daf0SKristof Provost break;
196fda7daf0SKristof Provost }
197fda7daf0SKristof Provost }
198fda7daf0SKristof Provost if (q == NULL)
199fda7daf0SKristof Provost q = p;
200fda7daf0SKristof Provost else
201fda7daf0SKristof Provost q++;
202fda7daf0SKristof Provost strlcpy(p, path, MAXPATHLEN);
203fda7daf0SKristof Provost if (!*q) {
204fda7daf0SKristof Provost rs_free(p);
205fda7daf0SKristof Provost return (NULL);
206fda7daf0SKristof Provost }
207fda7daf0SKristof Provost while ((r = strchr(q, '/')) != NULL || *q) {
208fda7daf0SKristof Provost if (r != NULL)
209fda7daf0SKristof Provost *r = 0;
210fda7daf0SKristof Provost if (!*q || strlen(q) >= PF_ANCHOR_NAME_SIZE ||
211fda7daf0SKristof Provost (parent != NULL && strlen(parent->path) >=
212fda7daf0SKristof Provost MAXPATHLEN - PF_ANCHOR_NAME_SIZE - 1)) {
213fda7daf0SKristof Provost rs_free(p);
214fda7daf0SKristof Provost return (NULL);
215fda7daf0SKristof Provost }
216e9eb0941SKristof Provost anchor = (struct pfctl_anchor *)rs_malloc(sizeof(*anchor));
217fda7daf0SKristof Provost if (anchor == NULL) {
218fda7daf0SKristof Provost rs_free(p);
219fda7daf0SKristof Provost return (NULL);
220fda7daf0SKristof Provost }
221fda7daf0SKristof Provost RB_INIT(&anchor->children);
222fda7daf0SKristof Provost strlcpy(anchor->name, q, sizeof(anchor->name));
223fda7daf0SKristof Provost if (parent != NULL) {
224fda7daf0SKristof Provost strlcpy(anchor->path, parent->path,
225fda7daf0SKristof Provost sizeof(anchor->path));
226fda7daf0SKristof Provost strlcat(anchor->path, "/", sizeof(anchor->path));
227fda7daf0SKristof Provost }
228fda7daf0SKristof Provost strlcat(anchor->path, anchor->name, sizeof(anchor->path));
229e9eb0941SKristof Provost if ((dup = RB_INSERT(pfctl_anchor_global, &V_pf_anchors, anchor)) !=
230fda7daf0SKristof Provost NULL) {
231fda7daf0SKristof Provost printf("pf_find_or_create_ruleset: RB_INSERT1 "
232fda7daf0SKristof Provost "'%s' '%s' collides with '%s' '%s'\n",
233fda7daf0SKristof Provost anchor->path, anchor->name, dup->path, dup->name);
234fda7daf0SKristof Provost rs_free(anchor);
235fda7daf0SKristof Provost rs_free(p);
236fda7daf0SKristof Provost return (NULL);
237fda7daf0SKristof Provost }
238fda7daf0SKristof Provost if (parent != NULL) {
239fda7daf0SKristof Provost anchor->parent = parent;
240e9eb0941SKristof Provost if ((dup = RB_INSERT(pfctl_anchor_node, &parent->children,
241fda7daf0SKristof Provost anchor)) != NULL) {
242fda7daf0SKristof Provost printf("pf_find_or_create_ruleset: "
243fda7daf0SKristof Provost "RB_INSERT2 '%s' '%s' collides with "
244fda7daf0SKristof Provost "'%s' '%s'\n", anchor->path, anchor->name,
245fda7daf0SKristof Provost dup->path, dup->name);
246e9eb0941SKristof Provost RB_REMOVE(pfctl_anchor_global, &V_pf_anchors,
247fda7daf0SKristof Provost anchor);
248fda7daf0SKristof Provost rs_free(anchor);
249fda7daf0SKristof Provost rs_free(p);
250fda7daf0SKristof Provost return (NULL);
251fda7daf0SKristof Provost }
252fda7daf0SKristof Provost }
253fda7daf0SKristof Provost pf_init_ruleset(&anchor->ruleset);
254fda7daf0SKristof Provost anchor->ruleset.anchor = anchor;
255fda7daf0SKristof Provost parent = anchor;
256fda7daf0SKristof Provost if (r != NULL)
257fda7daf0SKristof Provost q = r + 1;
258fda7daf0SKristof Provost else
259fda7daf0SKristof Provost *q = 0;
260fda7daf0SKristof Provost }
261fda7daf0SKristof Provost rs_free(p);
262fda7daf0SKristof Provost return (&anchor->ruleset);
263fda7daf0SKristof Provost }
264fda7daf0SKristof Provost
265fda7daf0SKristof Provost void
pf_remove_if_empty_ruleset(struct pfctl_ruleset * ruleset)266e9eb0941SKristof Provost pf_remove_if_empty_ruleset(struct pfctl_ruleset *ruleset)
267fda7daf0SKristof Provost {
268e9eb0941SKristof Provost struct pfctl_anchor *parent;
269fda7daf0SKristof Provost int i;
270fda7daf0SKristof Provost
271fda7daf0SKristof Provost while (ruleset != NULL) {
272fda7daf0SKristof Provost if (ruleset == &pf_main_ruleset || ruleset->anchor == NULL ||
273fda7daf0SKristof Provost !RB_EMPTY(&ruleset->anchor->children) ||
274fda7daf0SKristof Provost ruleset->anchor->refcnt > 0 || ruleset->tables > 0 ||
275fda7daf0SKristof Provost ruleset->topen)
276fda7daf0SKristof Provost return;
277fda7daf0SKristof Provost for (i = 0; i < PF_RULESET_MAX; ++i)
278fda7daf0SKristof Provost if (!TAILQ_EMPTY(ruleset->rules[i].active.ptr) ||
279fda7daf0SKristof Provost !TAILQ_EMPTY(ruleset->rules[i].inactive.ptr) ||
280fda7daf0SKristof Provost ruleset->rules[i].inactive.open)
281fda7daf0SKristof Provost return;
282e9eb0941SKristof Provost RB_REMOVE(pfctl_anchor_global, &V_pf_anchors, ruleset->anchor);
283fda7daf0SKristof Provost if ((parent = ruleset->anchor->parent) != NULL)
284e9eb0941SKristof Provost RB_REMOVE(pfctl_anchor_node, &parent->children,
285fda7daf0SKristof Provost ruleset->anchor);
286fda7daf0SKristof Provost rs_free(ruleset->anchor);
287fda7daf0SKristof Provost if (parent == NULL)
288fda7daf0SKristof Provost return;
289fda7daf0SKristof Provost ruleset = &parent->ruleset;
290fda7daf0SKristof Provost }
291fda7daf0SKristof Provost }
292*c5131afeSKristof Provost
293*c5131afeSKristof Provost void
pf_remove_if_empty_eth_ruleset(struct pfctl_eth_ruleset * ruleset)294*c5131afeSKristof Provost pf_remove_if_empty_eth_ruleset(struct pfctl_eth_ruleset *ruleset)
295*c5131afeSKristof Provost {
296*c5131afeSKristof Provost struct pfctl_eth_anchor *parent;
297*c5131afeSKristof Provost
298*c5131afeSKristof Provost return;
299*c5131afeSKristof Provost while (ruleset != NULL) {
300*c5131afeSKristof Provost if (ruleset == &pf_eth_main_anchor.ruleset ||
301*c5131afeSKristof Provost ruleset->anchor == NULL || ruleset->anchor->refcnt > 0)
302*c5131afeSKristof Provost return;
303*c5131afeSKristof Provost if (!TAILQ_EMPTY(&ruleset->rules))
304*c5131afeSKristof Provost return;
305*c5131afeSKristof Provost rs_free(ruleset->anchor);
306*c5131afeSKristof Provost if (parent == NULL)
307*c5131afeSKristof Provost return;
308*c5131afeSKristof Provost ruleset = &parent->ruleset;
309*c5131afeSKristof Provost }
310*c5131afeSKristof Provost }
311*c5131afeSKristof Provost
312*c5131afeSKristof Provost void
pf_init_eth_ruleset(struct pfctl_eth_ruleset * ruleset)313*c5131afeSKristof Provost pf_init_eth_ruleset(struct pfctl_eth_ruleset *ruleset)
314*c5131afeSKristof Provost {
315*c5131afeSKristof Provost
316*c5131afeSKristof Provost memset(ruleset, 0, sizeof(*ruleset));
317*c5131afeSKristof Provost TAILQ_INIT(&ruleset->rules);
318*c5131afeSKristof Provost }
319*c5131afeSKristof Provost
320*c5131afeSKristof Provost
321*c5131afeSKristof Provost static struct pfctl_eth_anchor*
_pf_find_eth_anchor(struct pfctl_eth_anchor * anchor,const char * path)322*c5131afeSKristof Provost _pf_find_eth_anchor(struct pfctl_eth_anchor *anchor, const char *path)
323*c5131afeSKristof Provost {
324*c5131afeSKristof Provost struct pfctl_eth_rule *r;
325*c5131afeSKristof Provost struct pfctl_eth_anchor *a;
326*c5131afeSKristof Provost
327*c5131afeSKristof Provost if (strcmp(path, anchor->path) == 0)
328*c5131afeSKristof Provost return (anchor);
329*c5131afeSKristof Provost
330*c5131afeSKristof Provost TAILQ_FOREACH(r, &anchor->ruleset.rules, entries) {
331*c5131afeSKristof Provost if (! r->anchor)
332*c5131afeSKristof Provost continue;
333*c5131afeSKristof Provost
334*c5131afeSKristof Provost /* Step into anchor */
335*c5131afeSKristof Provost a = _pf_find_eth_anchor(r->anchor, path);
336*c5131afeSKristof Provost if (a)
337*c5131afeSKristof Provost return (a);
338*c5131afeSKristof Provost }
339*c5131afeSKristof Provost
340*c5131afeSKristof Provost return (NULL);
341*c5131afeSKristof Provost }
342*c5131afeSKristof Provost
343*c5131afeSKristof Provost static struct pfctl_eth_anchor*
pf_find_eth_anchor(const char * path)344*c5131afeSKristof Provost pf_find_eth_anchor(const char *path)
345*c5131afeSKristof Provost {
346*c5131afeSKristof Provost return (_pf_find_eth_anchor(&pf_eth_main_anchor, path));
347*c5131afeSKristof Provost }
348*c5131afeSKristof Provost
349*c5131afeSKristof Provost static struct pfctl_eth_ruleset*
pf_find_eth_ruleset(const char * path)350*c5131afeSKristof Provost pf_find_eth_ruleset(const char *path)
351*c5131afeSKristof Provost {
352*c5131afeSKristof Provost struct pfctl_eth_anchor *anchor;
353*c5131afeSKristof Provost
354*c5131afeSKristof Provost while (*path == '/')
355*c5131afeSKristof Provost path++;
356*c5131afeSKristof Provost if (!*path)
357*c5131afeSKristof Provost return (&pf_eth_main_anchor.ruleset);
358*c5131afeSKristof Provost anchor = pf_find_eth_anchor(path);
359*c5131afeSKristof Provost if (anchor == NULL)
360*c5131afeSKristof Provost return (NULL);
361*c5131afeSKristof Provost else
362*c5131afeSKristof Provost return (&anchor->ruleset);
363*c5131afeSKristof Provost }
364*c5131afeSKristof Provost
365*c5131afeSKristof Provost struct pfctl_eth_ruleset *
pf_find_or_create_eth_ruleset(const char * path)366*c5131afeSKristof Provost pf_find_or_create_eth_ruleset(const char *path)
367*c5131afeSKristof Provost {
368*c5131afeSKristof Provost char *p, *q, *r;
369*c5131afeSKristof Provost struct pfctl_eth_ruleset *ruleset;
370*c5131afeSKristof Provost struct pfctl_eth_anchor *anchor = NULL, *parent = NULL;
371*c5131afeSKristof Provost
372*c5131afeSKristof Provost if (path[0] == 0)
373*c5131afeSKristof Provost return (&pf_eth_main_anchor.ruleset);
374*c5131afeSKristof Provost while (*path == '/')
375*c5131afeSKristof Provost path++;
376*c5131afeSKristof Provost ruleset = pf_find_eth_ruleset(path);
377*c5131afeSKristof Provost if (ruleset != NULL)
378*c5131afeSKristof Provost return (ruleset);
379*c5131afeSKristof Provost p = (char *)rs_malloc(MAXPATHLEN);
380*c5131afeSKristof Provost if (p == NULL)
381*c5131afeSKristof Provost return (NULL);
382*c5131afeSKristof Provost strlcpy(p, path, MAXPATHLEN);
383*c5131afeSKristof Provost while (parent == NULL && (q = strrchr(p, '/')) != NULL) {
384*c5131afeSKristof Provost *q = 0;
385*c5131afeSKristof Provost if ((ruleset = pf_find_eth_ruleset(p)) != NULL) {
386*c5131afeSKristof Provost parent = ruleset->anchor;
387*c5131afeSKristof Provost break;
388*c5131afeSKristof Provost }
389*c5131afeSKristof Provost }
390*c5131afeSKristof Provost if (q == NULL)
391*c5131afeSKristof Provost q = p;
392*c5131afeSKristof Provost else
393*c5131afeSKristof Provost q++;
394*c5131afeSKristof Provost strlcpy(p, path, MAXPATHLEN);
395*c5131afeSKristof Provost if (!*q) {
396*c5131afeSKristof Provost rs_free(p);
397*c5131afeSKristof Provost return (NULL);
398*c5131afeSKristof Provost }
399*c5131afeSKristof Provost while ((r = strchr(q, '/')) != NULL || *q) {
400*c5131afeSKristof Provost if (r != NULL)
401*c5131afeSKristof Provost *r = 0;
402*c5131afeSKristof Provost if (!*q || strlen(q) >= PF_ANCHOR_NAME_SIZE ||
403*c5131afeSKristof Provost (parent != NULL && strlen(parent->path) >=
404*c5131afeSKristof Provost MAXPATHLEN - PF_ANCHOR_NAME_SIZE - 1)) {
405*c5131afeSKristof Provost rs_free(p);
406*c5131afeSKristof Provost return (NULL);
407*c5131afeSKristof Provost }
408*c5131afeSKristof Provost anchor = (struct pfctl_eth_anchor *)rs_malloc(sizeof(*anchor));
409*c5131afeSKristof Provost if (anchor == NULL) {
410*c5131afeSKristof Provost rs_free(p);
411*c5131afeSKristof Provost return (NULL);
412*c5131afeSKristof Provost }
413*c5131afeSKristof Provost strlcpy(anchor->name, q, sizeof(anchor->name));
414*c5131afeSKristof Provost if (parent != NULL) {
415*c5131afeSKristof Provost strlcpy(anchor->path, parent->path,
416*c5131afeSKristof Provost sizeof(anchor->path));
417*c5131afeSKristof Provost strlcat(anchor->path, "/", sizeof(anchor->path));
418*c5131afeSKristof Provost }
419*c5131afeSKristof Provost strlcat(anchor->path, anchor->name, sizeof(anchor->path));
420*c5131afeSKristof Provost if (parent != NULL)
421*c5131afeSKristof Provost anchor->parent = parent;
422*c5131afeSKristof Provost pf_init_eth_ruleset(&anchor->ruleset);
423*c5131afeSKristof Provost anchor->ruleset.anchor = anchor;
424*c5131afeSKristof Provost parent = anchor;
425*c5131afeSKristof Provost if (r != NULL)
426*c5131afeSKristof Provost q = r + 1;
427*c5131afeSKristof Provost else
428*c5131afeSKristof Provost *q = 0;
429*c5131afeSKristof Provost }
430*c5131afeSKristof Provost rs_free(p);
431*c5131afeSKristof Provost return (&anchor->ruleset);
432*c5131afeSKristof Provost }
433*c5131afeSKristof Provost
434fda7daf0SKristof Provost int
pfctl_anchor_setup(struct pfctl_rule * r,const struct pfctl_ruleset * s,const char * name)435e9eb0941SKristof Provost pfctl_anchor_setup(struct pfctl_rule *r, const struct pfctl_ruleset *s,
436fda7daf0SKristof Provost const char *name)
437fda7daf0SKristof Provost {
438fda7daf0SKristof Provost char *p, *path;
439e9eb0941SKristof Provost struct pfctl_ruleset *ruleset;
440fda7daf0SKristof Provost
441fda7daf0SKristof Provost r->anchor = NULL;
442fda7daf0SKristof Provost r->anchor_relative = 0;
443fda7daf0SKristof Provost r->anchor_wildcard = 0;
444fda7daf0SKristof Provost if (!name[0])
445fda7daf0SKristof Provost return (0);
446fda7daf0SKristof Provost path = (char *)rs_malloc(MAXPATHLEN);
447fda7daf0SKristof Provost if (path == NULL)
448fda7daf0SKristof Provost return (1);
449fda7daf0SKristof Provost if (name[0] == '/')
450fda7daf0SKristof Provost strlcpy(path, name + 1, MAXPATHLEN);
451fda7daf0SKristof Provost else {
452fda7daf0SKristof Provost /* relative path */
453fda7daf0SKristof Provost r->anchor_relative = 1;
454fda7daf0SKristof Provost if (s->anchor == NULL || !s->anchor->path[0])
455fda7daf0SKristof Provost path[0] = 0;
456fda7daf0SKristof Provost else
457fda7daf0SKristof Provost strlcpy(path, s->anchor->path, MAXPATHLEN);
458fda7daf0SKristof Provost while (name[0] == '.' && name[1] == '.' && name[2] == '/') {
459fda7daf0SKristof Provost if (!path[0]) {
460e9eb0941SKristof Provost printf("pfctl_anchor_setup: .. beyond root\n");
461fda7daf0SKristof Provost rs_free(path);
462fda7daf0SKristof Provost return (1);
463fda7daf0SKristof Provost }
464fda7daf0SKristof Provost if ((p = strrchr(path, '/')) != NULL)
465fda7daf0SKristof Provost *p = 0;
466fda7daf0SKristof Provost else
467fda7daf0SKristof Provost path[0] = 0;
468fda7daf0SKristof Provost r->anchor_relative++;
469fda7daf0SKristof Provost name += 3;
470fda7daf0SKristof Provost }
471fda7daf0SKristof Provost if (path[0])
472fda7daf0SKristof Provost strlcat(path, "/", MAXPATHLEN);
473fda7daf0SKristof Provost strlcat(path, name, MAXPATHLEN);
474fda7daf0SKristof Provost }
475fda7daf0SKristof Provost if ((p = strrchr(path, '/')) != NULL && !strcmp(p, "/*")) {
476fda7daf0SKristof Provost r->anchor_wildcard = 1;
477fda7daf0SKristof Provost *p = 0;
478fda7daf0SKristof Provost }
479fda7daf0SKristof Provost ruleset = pf_find_or_create_ruleset(path);
480fda7daf0SKristof Provost rs_free(path);
481fda7daf0SKristof Provost if (ruleset == NULL || ruleset->anchor == NULL) {
482e9eb0941SKristof Provost printf("pfctl_anchor_setup: ruleset\n");
483fda7daf0SKristof Provost return (1);
484fda7daf0SKristof Provost }
485fda7daf0SKristof Provost r->anchor = ruleset->anchor;
486fda7daf0SKristof Provost r->anchor->refcnt++;
487fda7daf0SKristof Provost return (0);
488fda7daf0SKristof Provost }
489*c5131afeSKristof Provost
490*c5131afeSKristof Provost int
pfctl_eth_anchor_setup(struct pfctl * pf,struct pfctl_eth_rule * r,const struct pfctl_eth_ruleset * s,const char * name)491*c5131afeSKristof Provost pfctl_eth_anchor_setup(struct pfctl *pf, struct pfctl_eth_rule *r,
492*c5131afeSKristof Provost const struct pfctl_eth_ruleset *s, const char *name)
493*c5131afeSKristof Provost {
494*c5131afeSKristof Provost char *p, *path;
495*c5131afeSKristof Provost struct pfctl_eth_ruleset *ruleset;
496*c5131afeSKristof Provost
497*c5131afeSKristof Provost r->anchor = NULL;
498*c5131afeSKristof Provost if (!name[0])
499*c5131afeSKristof Provost return (0);
500*c5131afeSKristof Provost path = (char *)rs_malloc(MAXPATHLEN);
501*c5131afeSKristof Provost if (path == NULL)
502*c5131afeSKristof Provost return (1);
503*c5131afeSKristof Provost if (name[0] == '/')
504*c5131afeSKristof Provost strlcpy(path, name + 1, MAXPATHLEN);
505*c5131afeSKristof Provost else {
506*c5131afeSKristof Provost /* relative path */
507*c5131afeSKristof Provost if (s->anchor == NULL || !s->anchor->path[0])
508*c5131afeSKristof Provost path[0] = 0;
509*c5131afeSKristof Provost else
510*c5131afeSKristof Provost strlcpy(path, s->anchor->path, MAXPATHLEN);
511*c5131afeSKristof Provost while (name[0] == '.' && name[1] == '.' && name[2] == '/') {
512*c5131afeSKristof Provost if (!path[0]) {
513*c5131afeSKristof Provost printf("%s: .. beyond root\n", __func__);
514*c5131afeSKristof Provost rs_free(path);
515*c5131afeSKristof Provost return (1);
516*c5131afeSKristof Provost }
517*c5131afeSKristof Provost if ((p = strrchr(path, '/')) != NULL)
518*c5131afeSKristof Provost *p = 0;
519*c5131afeSKristof Provost else
520*c5131afeSKristof Provost path[0] = 0;
521*c5131afeSKristof Provost name += 3;
522*c5131afeSKristof Provost }
523*c5131afeSKristof Provost if (path[0])
524*c5131afeSKristof Provost strlcat(path, "/", MAXPATHLEN);
525*c5131afeSKristof Provost strlcat(path, name, MAXPATHLEN);
526*c5131afeSKristof Provost }
527*c5131afeSKristof Provost if ((p = strrchr(path, '/')) != NULL && !strcmp(p, "/*")) {
528*c5131afeSKristof Provost *p = 0;
529*c5131afeSKristof Provost }
530*c5131afeSKristof Provost ruleset = pf_find_or_create_eth_ruleset(path);
531*c5131afeSKristof Provost rs_free(path);
532*c5131afeSKristof Provost if (ruleset == NULL || ruleset->anchor == NULL) {
533*c5131afeSKristof Provost printf("%s: ruleset\n", __func__);
534*c5131afeSKristof Provost return (1);
535*c5131afeSKristof Provost }
536*c5131afeSKristof Provost r->anchor = ruleset->anchor;
537*c5131afeSKristof Provost r->anchor->refcnt++;
538*c5131afeSKristof Provost return (0);
539*c5131afeSKristof Provost }
540