Bug Summary

File:src/sbin/pfctl/../../sys/net/pf_ruleset.c
Warning:line 211, column 7
Although the value stored to 'dup' is used in the enclosing expression, the value is never actually read from 'dup'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name pf_ruleset.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sbin/pfctl/obj -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/sbin/pfctl -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -Wno-uninitialized -fdebug-compilation-dir=/usr/src/sbin/pfctl/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/sbin/pfctl/../../sys/net/pf_ruleset.c
1/* $OpenBSD: pf_ruleset.c,v 1.21 2023/06/30 09:58:30 mvs Exp $ */
2
3/*
4 * Copyright (c) 2001 Daniel Hartmeier
5 * Copyright (c) 2002,2003 Henning Brauer
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * - Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * - Redistributions in binary form must reproduce the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer in the documentation and/or other materials provided
17 * with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 *
32 * Effort sponsored in part by the Defense Advanced Research Projects
33 * Agency (DARPA) and Air Force Research Laboratory, Air Force
34 * Materiel Command, USAF, under agreement number F30602-01-2-0537.
35 *
36 */
37
38#include <sys/param.h>
39#include <sys/socket.h>
40#ifdef _KERNEL
41#include <sys/systm.h>
42#include <sys/mbuf.h>
43#include <sys/pool.h>
44#endif /* _KERNEL */
45#include <sys/syslog.h>
46
47#include <netinet/in.h>
48#include <netinet/ip.h>
49#include <netinet/tcp.h>
50
51#include <net/if.h>
52#include <net/pfvar.h>
53
54#ifdef INET6
55#include <netinet/ip6.h>
56#endif /* INET6 */
57
58
59#ifdef _KERNEL
60#define rs_malloc(x)calloc(1, x) malloc(x, M_PF, M_WAITOK|M_CANFAIL|M_ZERO)
61#define rs_free(x, siz)freezero(x, siz) free(x, M_PF, siz)
62#define rs_pool_get_anchor()calloc(1, sizeof(struct pf_anchor)) pool_get(&pf_anchor_pl, \
63 PR_WAITOK|PR_LIMITFAIL|PR_ZERO)
64#define rs_pool_put_anchor(x)freezero(x, sizeof(struct pf_anchor)) pool_put(&pf_anchor_pl, x)
65
66struct pool pf_anchor_pl;
67
68#else /* !_KERNEL */
69/* Userland equivalents so we can lend code to pfctl et al. */
70
71#include <arpa/inet.h>
72#include <errno(*__errno()).h>
73#include <stdio.h>
74#include <stdlib.h>
75#include <string.h>
76#define rs_malloc(x)calloc(1, x) calloc(1, x)
77#define rs_free(x, siz)freezero(x, siz) freezero(x, siz)
78#define rs_pool_get_anchor()calloc(1, sizeof(struct pf_anchor)) calloc(1, sizeof(struct pf_anchor))
79#define rs_pool_put_anchor(x)freezero(x, sizeof(struct pf_anchor)) freezero(x, sizeof(struct pf_anchor))
80
81#ifdef PFDEBUG
82#include <sys/stdarg.h> /* for DPFPRINTF() */
83#endif /* PFDEBUG */
84#endif /* _KERNEL */
85
86
87struct pf_anchor_global pf_anchors;
88struct pf_anchor pf_main_anchor;
89
90static __inline int pf_anchor_compare(struct pf_anchor *, struct pf_anchor *);
91
92RB_GENERATE(pf_anchor_global, pf_anchor, entry_global, pf_anchor_compare)void pf_anchor_global_RB_INSERT_COLOR(struct pf_anchor_global
*head, struct pf_anchor *elm) { struct pf_anchor *parent, *gparent
, *tmp; while ((parent = (elm)->entry_global.rbe_parent) &&
(parent)->entry_global.rbe_color == 1) { gparent = (parent
)->entry_global.rbe_parent; if (parent == (gparent)->entry_global
.rbe_left) { tmp = (gparent)->entry_global.rbe_right; if (
tmp && (tmp)->entry_global.rbe_color == 1) { (tmp)
->entry_global.rbe_color = 0; do { (parent)->entry_global
.rbe_color = 0; (gparent)->entry_global.rbe_color = 1; } while
(0); elm = gparent; continue; } if ((parent)->entry_global
.rbe_right == elm) { do { (tmp) = (parent)->entry_global.rbe_right
; if (((parent)->entry_global.rbe_right = (tmp)->entry_global
.rbe_left)) { ((tmp)->entry_global.rbe_left)->entry_global
.rbe_parent = (parent); } do {} while (0); if (((tmp)->entry_global
.rbe_parent = (parent)->entry_global.rbe_parent)) { if ((parent
) == ((parent)->entry_global.rbe_parent)->entry_global.
rbe_left) ((parent)->entry_global.rbe_parent)->entry_global
.rbe_left = (tmp); else ((parent)->entry_global.rbe_parent
)->entry_global.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->entry_global.rbe_left = (parent); (parent
)->entry_global.rbe_parent = (tmp); do {} while (0); if ((
(tmp)->entry_global.rbe_parent)) do {} while (0); } while (
0); tmp = parent; parent = elm; elm = tmp; } do { (parent)->
entry_global.rbe_color = 0; (gparent)->entry_global.rbe_color
= 1; } while (0); do { (tmp) = (gparent)->entry_global.rbe_left
; if (((gparent)->entry_global.rbe_left = (tmp)->entry_global
.rbe_right)) { ((tmp)->entry_global.rbe_right)->entry_global
.rbe_parent = (gparent); } do {} while (0); if (((tmp)->entry_global
.rbe_parent = (gparent)->entry_global.rbe_parent)) { if ((
gparent) == ((gparent)->entry_global.rbe_parent)->entry_global
.rbe_left) ((gparent)->entry_global.rbe_parent)->entry_global
.rbe_left = (tmp); else ((gparent)->entry_global.rbe_parent
)->entry_global.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->entry_global.rbe_right = (gparent); (gparent
)->entry_global.rbe_parent = (tmp); do {} while (0); if ((
(tmp)->entry_global.rbe_parent)) do {} while (0); } while (
0); } else { tmp = (gparent)->entry_global.rbe_left; if (tmp
&& (tmp)->entry_global.rbe_color == 1) { (tmp)->
entry_global.rbe_color = 0; do { (parent)->entry_global.rbe_color
= 0; (gparent)->entry_global.rbe_color = 1; } while (0); elm
= gparent; continue; } if ((parent)->entry_global.rbe_left
== elm) { do { (tmp) = (parent)->entry_global.rbe_left; if
(((parent)->entry_global.rbe_left = (tmp)->entry_global
.rbe_right)) { ((tmp)->entry_global.rbe_right)->entry_global
.rbe_parent = (parent); } do {} while (0); if (((tmp)->entry_global
.rbe_parent = (parent)->entry_global.rbe_parent)) { if ((parent
) == ((parent)->entry_global.rbe_parent)->entry_global.
rbe_left) ((parent)->entry_global.rbe_parent)->entry_global
.rbe_left = (tmp); else ((parent)->entry_global.rbe_parent
)->entry_global.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->entry_global.rbe_right = (parent); (parent
)->entry_global.rbe_parent = (tmp); do {} while (0); if ((
(tmp)->entry_global.rbe_parent)) do {} while (0); } while (
0); tmp = parent; parent = elm; elm = tmp; } do { (parent)->
entry_global.rbe_color = 0; (gparent)->entry_global.rbe_color
= 1; } while (0); do { (tmp) = (gparent)->entry_global.rbe_right
; if (((gparent)->entry_global.rbe_right = (tmp)->entry_global
.rbe_left)) { ((tmp)->entry_global.rbe_left)->entry_global
.rbe_parent = (gparent); } do {} while (0); if (((tmp)->entry_global
.rbe_parent = (gparent)->entry_global.rbe_parent)) { if ((
gparent) == ((gparent)->entry_global.rbe_parent)->entry_global
.rbe_left) ((gparent)->entry_global.rbe_parent)->entry_global
.rbe_left = (tmp); else ((gparent)->entry_global.rbe_parent
)->entry_global.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->entry_global.rbe_left = (gparent); (gparent
)->entry_global.rbe_parent = (tmp); do {} while (0); if ((
(tmp)->entry_global.rbe_parent)) do {} while (0); } while (
0); } } (head->rbh_root)->entry_global.rbe_color = 0; }
void pf_anchor_global_RB_REMOVE_COLOR(struct pf_anchor_global
*head, struct pf_anchor *parent, struct pf_anchor *elm) { struct
pf_anchor *tmp; while ((elm == ((void *)0) || (elm)->entry_global
.rbe_color == 0) && elm != (head)->rbh_root) { if (
(parent)->entry_global.rbe_left == elm) { tmp = (parent)->
entry_global.rbe_right; if ((tmp)->entry_global.rbe_color ==
1) { do { (tmp)->entry_global.rbe_color = 0; (parent)->
entry_global.rbe_color = 1; } while (0); do { (tmp) = (parent
)->entry_global.rbe_right; if (((parent)->entry_global.
rbe_right = (tmp)->entry_global.rbe_left)) { ((tmp)->entry_global
.rbe_left)->entry_global.rbe_parent = (parent); } do {} while
(0); if (((tmp)->entry_global.rbe_parent = (parent)->entry_global
.rbe_parent)) { if ((parent) == ((parent)->entry_global.rbe_parent
)->entry_global.rbe_left) ((parent)->entry_global.rbe_parent
)->entry_global.rbe_left = (tmp); else ((parent)->entry_global
.rbe_parent)->entry_global.rbe_right = (tmp); } else (head
)->rbh_root = (tmp); (tmp)->entry_global.rbe_left = (parent
); (parent)->entry_global.rbe_parent = (tmp); do {} while (
0); if (((tmp)->entry_global.rbe_parent)) do {} while (0);
} while (0); tmp = (parent)->entry_global.rbe_right; } if
(((tmp)->entry_global.rbe_left == ((void *)0) || ((tmp)->
entry_global.rbe_left)->entry_global.rbe_color == 0) &&
((tmp)->entry_global.rbe_right == ((void *)0) || ((tmp)->
entry_global.rbe_right)->entry_global.rbe_color == 0)) { (
tmp)->entry_global.rbe_color = 1; elm = parent; parent = (
elm)->entry_global.rbe_parent; } else { if ((tmp)->entry_global
.rbe_right == ((void *)0) || ((tmp)->entry_global.rbe_right
)->entry_global.rbe_color == 0) { struct pf_anchor *oleft;
if ((oleft = (tmp)->entry_global.rbe_left)) (oleft)->entry_global
.rbe_color = 0; (tmp)->entry_global.rbe_color = 1; do { (oleft
) = (tmp)->entry_global.rbe_left; if (((tmp)->entry_global
.rbe_left = (oleft)->entry_global.rbe_right)) { ((oleft)->
entry_global.rbe_right)->entry_global.rbe_parent = (tmp); }
do {} while (0); if (((oleft)->entry_global.rbe_parent = (
tmp)->entry_global.rbe_parent)) { if ((tmp) == ((tmp)->
entry_global.rbe_parent)->entry_global.rbe_left) ((tmp)->
entry_global.rbe_parent)->entry_global.rbe_left = (oleft);
else ((tmp)->entry_global.rbe_parent)->entry_global.rbe_right
= (oleft); } else (head)->rbh_root = (oleft); (oleft)->
entry_global.rbe_right = (tmp); (tmp)->entry_global.rbe_parent
= (oleft); do {} while (0); if (((oleft)->entry_global.rbe_parent
)) do {} while (0); } while (0); tmp = (parent)->entry_global
.rbe_right; } (tmp)->entry_global.rbe_color = (parent)->
entry_global.rbe_color; (parent)->entry_global.rbe_color =
0; if ((tmp)->entry_global.rbe_right) ((tmp)->entry_global
.rbe_right)->entry_global.rbe_color = 0; do { (tmp) = (parent
)->entry_global.rbe_right; if (((parent)->entry_global.
rbe_right = (tmp)->entry_global.rbe_left)) { ((tmp)->entry_global
.rbe_left)->entry_global.rbe_parent = (parent); } do {} while
(0); if (((tmp)->entry_global.rbe_parent = (parent)->entry_global
.rbe_parent)) { if ((parent) == ((parent)->entry_global.rbe_parent
)->entry_global.rbe_left) ((parent)->entry_global.rbe_parent
)->entry_global.rbe_left = (tmp); else ((parent)->entry_global
.rbe_parent)->entry_global.rbe_right = (tmp); } else (head
)->rbh_root = (tmp); (tmp)->entry_global.rbe_left = (parent
); (parent)->entry_global.rbe_parent = (tmp); do {} while (
0); if (((tmp)->entry_global.rbe_parent)) do {} while (0);
} while (0); elm = (head)->rbh_root; break; } } else { tmp
= (parent)->entry_global.rbe_left; if ((tmp)->entry_global
.rbe_color == 1) { do { (tmp)->entry_global.rbe_color = 0;
(parent)->entry_global.rbe_color = 1; } while (0); do { (
tmp) = (parent)->entry_global.rbe_left; if (((parent)->
entry_global.rbe_left = (tmp)->entry_global.rbe_right)) { (
(tmp)->entry_global.rbe_right)->entry_global.rbe_parent
= (parent); } do {} while (0); if (((tmp)->entry_global.rbe_parent
= (parent)->entry_global.rbe_parent)) { if ((parent) == (
(parent)->entry_global.rbe_parent)->entry_global.rbe_left
) ((parent)->entry_global.rbe_parent)->entry_global.rbe_left
= (tmp); else ((parent)->entry_global.rbe_parent)->entry_global
.rbe_right = (tmp); } else (head)->rbh_root = (tmp); (tmp)
->entry_global.rbe_right = (parent); (parent)->entry_global
.rbe_parent = (tmp); do {} while (0); if (((tmp)->entry_global
.rbe_parent)) do {} while (0); } while (0); tmp = (parent)->
entry_global.rbe_left; } if (((tmp)->entry_global.rbe_left
== ((void *)0) || ((tmp)->entry_global.rbe_left)->entry_global
.rbe_color == 0) && ((tmp)->entry_global.rbe_right
== ((void *)0) || ((tmp)->entry_global.rbe_right)->entry_global
.rbe_color == 0)) { (tmp)->entry_global.rbe_color = 1; elm
= parent; parent = (elm)->entry_global.rbe_parent; } else
{ if ((tmp)->entry_global.rbe_left == ((void *)0) || ((tmp
)->entry_global.rbe_left)->entry_global.rbe_color == 0)
{ struct pf_anchor *oright; if ((oright = (tmp)->entry_global
.rbe_right)) (oright)->entry_global.rbe_color = 0; (tmp)->
entry_global.rbe_color = 1; do { (oright) = (tmp)->entry_global
.rbe_right; if (((tmp)->entry_global.rbe_right = (oright)->
entry_global.rbe_left)) { ((oright)->entry_global.rbe_left
)->entry_global.rbe_parent = (tmp); } do {} while (0); if (
((oright)->entry_global.rbe_parent = (tmp)->entry_global
.rbe_parent)) { if ((tmp) == ((tmp)->entry_global.rbe_parent
)->entry_global.rbe_left) ((tmp)->entry_global.rbe_parent
)->entry_global.rbe_left = (oright); else ((tmp)->entry_global
.rbe_parent)->entry_global.rbe_right = (oright); } else (head
)->rbh_root = (oright); (oright)->entry_global.rbe_left
= (tmp); (tmp)->entry_global.rbe_parent = (oright); do {}
while (0); if (((oright)->entry_global.rbe_parent)) do {}
while (0); } while (0); tmp = (parent)->entry_global.rbe_left
; } (tmp)->entry_global.rbe_color = (parent)->entry_global
.rbe_color; (parent)->entry_global.rbe_color = 0; if ((tmp
)->entry_global.rbe_left) ((tmp)->entry_global.rbe_left
)->entry_global.rbe_color = 0; do { (tmp) = (parent)->entry_global
.rbe_left; if (((parent)->entry_global.rbe_left = (tmp)->
entry_global.rbe_right)) { ((tmp)->entry_global.rbe_right)
->entry_global.rbe_parent = (parent); } do {} while (0); if
(((tmp)->entry_global.rbe_parent = (parent)->entry_global
.rbe_parent)) { if ((parent) == ((parent)->entry_global.rbe_parent
)->entry_global.rbe_left) ((parent)->entry_global.rbe_parent
)->entry_global.rbe_left = (tmp); else ((parent)->entry_global
.rbe_parent)->entry_global.rbe_right = (tmp); } else (head
)->rbh_root = (tmp); (tmp)->entry_global.rbe_right = (parent
); (parent)->entry_global.rbe_parent = (tmp); do {} while (
0); if (((tmp)->entry_global.rbe_parent)) do {} while (0);
} while (0); elm = (head)->rbh_root; break; } } } if (elm
) (elm)->entry_global.rbe_color = 0; } struct pf_anchor * pf_anchor_global_RB_REMOVE
(struct pf_anchor_global *head, struct pf_anchor *elm) { struct
pf_anchor *child, *parent, *old = elm; int color; if ((elm)->
entry_global.rbe_left == ((void *)0)) child = (elm)->entry_global
.rbe_right; else if ((elm)->entry_global.rbe_right == ((void
*)0)) child = (elm)->entry_global.rbe_left; else { struct
pf_anchor *left; elm = (elm)->entry_global.rbe_right; while
((left = (elm)->entry_global.rbe_left)) elm = left; child
= (elm)->entry_global.rbe_right; parent = (elm)->entry_global
.rbe_parent; color = (elm)->entry_global.rbe_color; if (child
) (child)->entry_global.rbe_parent = parent; if (parent) {
if ((parent)->entry_global.rbe_left == elm) (parent)->
entry_global.rbe_left = child; else (parent)->entry_global
.rbe_right = child; do {} while (0); } else (head)->rbh_root
= child; if ((elm)->entry_global.rbe_parent == old) parent
= elm; (elm)->entry_global = (old)->entry_global; if (
(old)->entry_global.rbe_parent) { if (((old)->entry_global
.rbe_parent)->entry_global.rbe_left == old) ((old)->entry_global
.rbe_parent)->entry_global.rbe_left = elm; else ((old)->
entry_global.rbe_parent)->entry_global.rbe_right = elm; do
{} while (0); } else (head)->rbh_root = elm; ((old)->entry_global
.rbe_left)->entry_global.rbe_parent = elm; if ((old)->entry_global
.rbe_right) ((old)->entry_global.rbe_right)->entry_global
.rbe_parent = elm; if (parent) { left = parent; do { do {} while
(0); } while ((left = (left)->entry_global.rbe_parent)); }
goto color; } parent = (elm)->entry_global.rbe_parent; color
= (elm)->entry_global.rbe_color; if (child) (child)->entry_global
.rbe_parent = parent; if (parent) { if ((parent)->entry_global
.rbe_left == elm) (parent)->entry_global.rbe_left = child;
else (parent)->entry_global.rbe_right = child; do {} while
(0); } else (head)->rbh_root = child; color: if (color ==
0) pf_anchor_global_RB_REMOVE_COLOR(head, parent, child); return
(old); } struct pf_anchor * pf_anchor_global_RB_INSERT(struct
pf_anchor_global *head, struct pf_anchor *elm) { struct pf_anchor
*tmp; struct pf_anchor *parent = ((void *)0); int comp = 0; tmp
= (head)->rbh_root; while (tmp) { parent = tmp; comp = (pf_anchor_compare
)(elm, parent); if (comp < 0) tmp = (tmp)->entry_global
.rbe_left; else if (comp > 0) tmp = (tmp)->entry_global
.rbe_right; else return (tmp); } do { (elm)->entry_global.
rbe_parent = parent; (elm)->entry_global.rbe_left = (elm)->
entry_global.rbe_right = ((void *)0); (elm)->entry_global.
rbe_color = 1; } while (0); if (parent != ((void *)0)) { if (
comp < 0) (parent)->entry_global.rbe_left = elm; else (
parent)->entry_global.rbe_right = elm; do {} while (0); } else
(head)->rbh_root = elm; pf_anchor_global_RB_INSERT_COLOR(
head, elm); return (((void *)0)); } struct pf_anchor * pf_anchor_global_RB_FIND
(struct pf_anchor_global *head, struct pf_anchor *elm) { struct
pf_anchor *tmp = (head)->rbh_root; int comp; while (tmp) {
comp = pf_anchor_compare(elm, tmp); if (comp < 0) tmp = (
tmp)->entry_global.rbe_left; else if (comp > 0) tmp = (
tmp)->entry_global.rbe_right; else return (tmp); } return (
((void *)0)); } struct pf_anchor * pf_anchor_global_RB_NFIND(
struct pf_anchor_global *head, struct pf_anchor *elm) { struct
pf_anchor *tmp = (head)->rbh_root; struct pf_anchor *res =
((void *)0); int comp; while (tmp) { comp = pf_anchor_compare
(elm, tmp); if (comp < 0) { res = tmp; tmp = (tmp)->entry_global
.rbe_left; } else if (comp > 0) tmp = (tmp)->entry_global
.rbe_right; else return (tmp); } return (res); } struct pf_anchor
* pf_anchor_global_RB_NEXT(struct pf_anchor *elm) { if ((elm
)->entry_global.rbe_right) { elm = (elm)->entry_global.
rbe_right; while ((elm)->entry_global.rbe_left) elm = (elm
)->entry_global.rbe_left; } else { if ((elm)->entry_global
.rbe_parent && (elm == ((elm)->entry_global.rbe_parent
)->entry_global.rbe_left)) elm = (elm)->entry_global.rbe_parent
; else { while ((elm)->entry_global.rbe_parent && (
elm == ((elm)->entry_global.rbe_parent)->entry_global.rbe_right
)) elm = (elm)->entry_global.rbe_parent; elm = (elm)->entry_global
.rbe_parent; } } return (elm); } struct pf_anchor * pf_anchor_global_RB_PREV
(struct pf_anchor *elm) { if ((elm)->entry_global.rbe_left
) { elm = (elm)->entry_global.rbe_left; while ((elm)->entry_global
.rbe_right) elm = (elm)->entry_global.rbe_right; } else { if
((elm)->entry_global.rbe_parent && (elm == ((elm)
->entry_global.rbe_parent)->entry_global.rbe_right)) elm
= (elm)->entry_global.rbe_parent; else { while ((elm)->
entry_global.rbe_parent && (elm == ((elm)->entry_global
.rbe_parent)->entry_global.rbe_left)) elm = (elm)->entry_global
.rbe_parent; elm = (elm)->entry_global.rbe_parent; } } return
(elm); } struct pf_anchor * pf_anchor_global_RB_MINMAX(struct
pf_anchor_global *head, int val) { struct pf_anchor *tmp = (
head)->rbh_root; struct pf_anchor *parent = ((void *)0); while
(tmp) { parent = tmp; if (val < 0) tmp = (tmp)->entry_global
.rbe_left; else tmp = (tmp)->entry_global.rbe_right; } return
(parent); }
;
93RB_GENERATE(pf_anchor_node, pf_anchor, entry_node, pf_anchor_compare)void pf_anchor_node_RB_INSERT_COLOR(struct pf_anchor_node *head
, struct pf_anchor *elm) { struct pf_anchor *parent, *gparent
, *tmp; while ((parent = (elm)->entry_node.rbe_parent) &&
(parent)->entry_node.rbe_color == 1) { gparent = (parent)
->entry_node.rbe_parent; if (parent == (gparent)->entry_node
.rbe_left) { tmp = (gparent)->entry_node.rbe_right; if (tmp
&& (tmp)->entry_node.rbe_color == 1) { (tmp)->
entry_node.rbe_color = 0; do { (parent)->entry_node.rbe_color
= 0; (gparent)->entry_node.rbe_color = 1; } while (0); elm
= gparent; continue; } if ((parent)->entry_node.rbe_right
== elm) { do { (tmp) = (parent)->entry_node.rbe_right; if
(((parent)->entry_node.rbe_right = (tmp)->entry_node.rbe_left
)) { ((tmp)->entry_node.rbe_left)->entry_node.rbe_parent
= (parent); } do {} while (0); if (((tmp)->entry_node.rbe_parent
= (parent)->entry_node.rbe_parent)) { if ((parent) == ((parent
)->entry_node.rbe_parent)->entry_node.rbe_left) ((parent
)->entry_node.rbe_parent)->entry_node.rbe_left = (tmp);
else ((parent)->entry_node.rbe_parent)->entry_node.rbe_right
= (tmp); } else (head)->rbh_root = (tmp); (tmp)->entry_node
.rbe_left = (parent); (parent)->entry_node.rbe_parent = (tmp
); do {} while (0); if (((tmp)->entry_node.rbe_parent)) do
{} while (0); } while (0); tmp = parent; parent = elm; elm =
tmp; } do { (parent)->entry_node.rbe_color = 0; (gparent)
->entry_node.rbe_color = 1; } while (0); do { (tmp) = (gparent
)->entry_node.rbe_left; if (((gparent)->entry_node.rbe_left
= (tmp)->entry_node.rbe_right)) { ((tmp)->entry_node.rbe_right
)->entry_node.rbe_parent = (gparent); } do {} while (0); if
(((tmp)->entry_node.rbe_parent = (gparent)->entry_node
.rbe_parent)) { if ((gparent) == ((gparent)->entry_node.rbe_parent
)->entry_node.rbe_left) ((gparent)->entry_node.rbe_parent
)->entry_node.rbe_left = (tmp); else ((gparent)->entry_node
.rbe_parent)->entry_node.rbe_right = (tmp); } else (head)->
rbh_root = (tmp); (tmp)->entry_node.rbe_right = (gparent);
(gparent)->entry_node.rbe_parent = (tmp); do {} while (0)
; if (((tmp)->entry_node.rbe_parent)) do {} while (0); } while
(0); } else { tmp = (gparent)->entry_node.rbe_left; if (tmp
&& (tmp)->entry_node.rbe_color == 1) { (tmp)->
entry_node.rbe_color = 0; do { (parent)->entry_node.rbe_color
= 0; (gparent)->entry_node.rbe_color = 1; } while (0); elm
= gparent; continue; } if ((parent)->entry_node.rbe_left ==
elm) { do { (tmp) = (parent)->entry_node.rbe_left; if (((
parent)->entry_node.rbe_left = (tmp)->entry_node.rbe_right
)) { ((tmp)->entry_node.rbe_right)->entry_node.rbe_parent
= (parent); } do {} while (0); if (((tmp)->entry_node.rbe_parent
= (parent)->entry_node.rbe_parent)) { if ((parent) == ((parent
)->entry_node.rbe_parent)->entry_node.rbe_left) ((parent
)->entry_node.rbe_parent)->entry_node.rbe_left = (tmp);
else ((parent)->entry_node.rbe_parent)->entry_node.rbe_right
= (tmp); } else (head)->rbh_root = (tmp); (tmp)->entry_node
.rbe_right = (parent); (parent)->entry_node.rbe_parent = (
tmp); do {} while (0); if (((tmp)->entry_node.rbe_parent))
do {} while (0); } while (0); tmp = parent; parent = elm; elm
= tmp; } do { (parent)->entry_node.rbe_color = 0; (gparent
)->entry_node.rbe_color = 1; } while (0); do { (tmp) = (gparent
)->entry_node.rbe_right; if (((gparent)->entry_node.rbe_right
= (tmp)->entry_node.rbe_left)) { ((tmp)->entry_node.rbe_left
)->entry_node.rbe_parent = (gparent); } do {} while (0); if
(((tmp)->entry_node.rbe_parent = (gparent)->entry_node
.rbe_parent)) { if ((gparent) == ((gparent)->entry_node.rbe_parent
)->entry_node.rbe_left) ((gparent)->entry_node.rbe_parent
)->entry_node.rbe_left = (tmp); else ((gparent)->entry_node
.rbe_parent)->entry_node.rbe_right = (tmp); } else (head)->
rbh_root = (tmp); (tmp)->entry_node.rbe_left = (gparent); (
gparent)->entry_node.rbe_parent = (tmp); do {} while (0); if
(((tmp)->entry_node.rbe_parent)) do {} while (0); } while
(0); } } (head->rbh_root)->entry_node.rbe_color = 0; }
void pf_anchor_node_RB_REMOVE_COLOR(struct pf_anchor_node *head
, struct pf_anchor *parent, struct pf_anchor *elm) { struct pf_anchor
*tmp; while ((elm == ((void *)0) || (elm)->entry_node.rbe_color
== 0) && elm != (head)->rbh_root) { if ((parent)->
entry_node.rbe_left == elm) { tmp = (parent)->entry_node.rbe_right
; if ((tmp)->entry_node.rbe_color == 1) { do { (tmp)->entry_node
.rbe_color = 0; (parent)->entry_node.rbe_color = 1; } while
(0); do { (tmp) = (parent)->entry_node.rbe_right; if (((parent
)->entry_node.rbe_right = (tmp)->entry_node.rbe_left)) {
((tmp)->entry_node.rbe_left)->entry_node.rbe_parent = (
parent); } do {} while (0); if (((tmp)->entry_node.rbe_parent
= (parent)->entry_node.rbe_parent)) { if ((parent) == ((parent
)->entry_node.rbe_parent)->entry_node.rbe_left) ((parent
)->entry_node.rbe_parent)->entry_node.rbe_left = (tmp);
else ((parent)->entry_node.rbe_parent)->entry_node.rbe_right
= (tmp); } else (head)->rbh_root = (tmp); (tmp)->entry_node
.rbe_left = (parent); (parent)->entry_node.rbe_parent = (tmp
); do {} while (0); if (((tmp)->entry_node.rbe_parent)) do
{} while (0); } while (0); tmp = (parent)->entry_node.rbe_right
; } if (((tmp)->entry_node.rbe_left == ((void *)0) || ((tmp
)->entry_node.rbe_left)->entry_node.rbe_color == 0) &&
((tmp)->entry_node.rbe_right == ((void *)0) || ((tmp)->
entry_node.rbe_right)->entry_node.rbe_color == 0)) { (tmp)
->entry_node.rbe_color = 1; elm = parent; parent = (elm)->
entry_node.rbe_parent; } else { if ((tmp)->entry_node.rbe_right
== ((void *)0) || ((tmp)->entry_node.rbe_right)->entry_node
.rbe_color == 0) { struct pf_anchor *oleft; if ((oleft = (tmp
)->entry_node.rbe_left)) (oleft)->entry_node.rbe_color =
0; (tmp)->entry_node.rbe_color = 1; do { (oleft) = (tmp)->
entry_node.rbe_left; if (((tmp)->entry_node.rbe_left = (oleft
)->entry_node.rbe_right)) { ((oleft)->entry_node.rbe_right
)->entry_node.rbe_parent = (tmp); } do {} while (0); if ((
(oleft)->entry_node.rbe_parent = (tmp)->entry_node.rbe_parent
)) { if ((tmp) == ((tmp)->entry_node.rbe_parent)->entry_node
.rbe_left) ((tmp)->entry_node.rbe_parent)->entry_node.rbe_left
= (oleft); else ((tmp)->entry_node.rbe_parent)->entry_node
.rbe_right = (oleft); } else (head)->rbh_root = (oleft); (
oleft)->entry_node.rbe_right = (tmp); (tmp)->entry_node
.rbe_parent = (oleft); do {} while (0); if (((oleft)->entry_node
.rbe_parent)) do {} while (0); } while (0); tmp = (parent)->
entry_node.rbe_right; } (tmp)->entry_node.rbe_color = (parent
)->entry_node.rbe_color; (parent)->entry_node.rbe_color
= 0; if ((tmp)->entry_node.rbe_right) ((tmp)->entry_node
.rbe_right)->entry_node.rbe_color = 0; do { (tmp) = (parent
)->entry_node.rbe_right; if (((parent)->entry_node.rbe_right
= (tmp)->entry_node.rbe_left)) { ((tmp)->entry_node.rbe_left
)->entry_node.rbe_parent = (parent); } do {} while (0); if
(((tmp)->entry_node.rbe_parent = (parent)->entry_node.
rbe_parent)) { if ((parent) == ((parent)->entry_node.rbe_parent
)->entry_node.rbe_left) ((parent)->entry_node.rbe_parent
)->entry_node.rbe_left = (tmp); else ((parent)->entry_node
.rbe_parent)->entry_node.rbe_right = (tmp); } else (head)->
rbh_root = (tmp); (tmp)->entry_node.rbe_left = (parent); (
parent)->entry_node.rbe_parent = (tmp); do {} while (0); if
(((tmp)->entry_node.rbe_parent)) do {} while (0); } while
(0); elm = (head)->rbh_root; break; } } else { tmp = (parent
)->entry_node.rbe_left; if ((tmp)->entry_node.rbe_color
== 1) { do { (tmp)->entry_node.rbe_color = 0; (parent)->
entry_node.rbe_color = 1; } while (0); do { (tmp) = (parent)->
entry_node.rbe_left; if (((parent)->entry_node.rbe_left = (
tmp)->entry_node.rbe_right)) { ((tmp)->entry_node.rbe_right
)->entry_node.rbe_parent = (parent); } do {} while (0); if
(((tmp)->entry_node.rbe_parent = (parent)->entry_node.
rbe_parent)) { if ((parent) == ((parent)->entry_node.rbe_parent
)->entry_node.rbe_left) ((parent)->entry_node.rbe_parent
)->entry_node.rbe_left = (tmp); else ((parent)->entry_node
.rbe_parent)->entry_node.rbe_right = (tmp); } else (head)->
rbh_root = (tmp); (tmp)->entry_node.rbe_right = (parent); (
parent)->entry_node.rbe_parent = (tmp); do {} while (0); if
(((tmp)->entry_node.rbe_parent)) do {} while (0); } while
(0); tmp = (parent)->entry_node.rbe_left; } if (((tmp)->
entry_node.rbe_left == ((void *)0) || ((tmp)->entry_node.rbe_left
)->entry_node.rbe_color == 0) && ((tmp)->entry_node
.rbe_right == ((void *)0) || ((tmp)->entry_node.rbe_right)
->entry_node.rbe_color == 0)) { (tmp)->entry_node.rbe_color
= 1; elm = parent; parent = (elm)->entry_node.rbe_parent;
} else { if ((tmp)->entry_node.rbe_left == ((void *)0) ||
((tmp)->entry_node.rbe_left)->entry_node.rbe_color == 0
) { struct pf_anchor *oright; if ((oright = (tmp)->entry_node
.rbe_right)) (oright)->entry_node.rbe_color = 0; (tmp)->
entry_node.rbe_color = 1; do { (oright) = (tmp)->entry_node
.rbe_right; if (((tmp)->entry_node.rbe_right = (oright)->
entry_node.rbe_left)) { ((oright)->entry_node.rbe_left)->
entry_node.rbe_parent = (tmp); } do {} while (0); if (((oright
)->entry_node.rbe_parent = (tmp)->entry_node.rbe_parent
)) { if ((tmp) == ((tmp)->entry_node.rbe_parent)->entry_node
.rbe_left) ((tmp)->entry_node.rbe_parent)->entry_node.rbe_left
= (oright); else ((tmp)->entry_node.rbe_parent)->entry_node
.rbe_right = (oright); } else (head)->rbh_root = (oright);
(oright)->entry_node.rbe_left = (tmp); (tmp)->entry_node
.rbe_parent = (oright); do {} while (0); if (((oright)->entry_node
.rbe_parent)) do {} while (0); } while (0); tmp = (parent)->
entry_node.rbe_left; } (tmp)->entry_node.rbe_color = (parent
)->entry_node.rbe_color; (parent)->entry_node.rbe_color
= 0; if ((tmp)->entry_node.rbe_left) ((tmp)->entry_node
.rbe_left)->entry_node.rbe_color = 0; do { (tmp) = (parent
)->entry_node.rbe_left; if (((parent)->entry_node.rbe_left
= (tmp)->entry_node.rbe_right)) { ((tmp)->entry_node.rbe_right
)->entry_node.rbe_parent = (parent); } do {} while (0); if
(((tmp)->entry_node.rbe_parent = (parent)->entry_node.
rbe_parent)) { if ((parent) == ((parent)->entry_node.rbe_parent
)->entry_node.rbe_left) ((parent)->entry_node.rbe_parent
)->entry_node.rbe_left = (tmp); else ((parent)->entry_node
.rbe_parent)->entry_node.rbe_right = (tmp); } else (head)->
rbh_root = (tmp); (tmp)->entry_node.rbe_right = (parent); (
parent)->entry_node.rbe_parent = (tmp); do {} while (0); if
(((tmp)->entry_node.rbe_parent)) do {} while (0); } while
(0); elm = (head)->rbh_root; break; } } } if (elm) (elm)->
entry_node.rbe_color = 0; } struct pf_anchor * pf_anchor_node_RB_REMOVE
(struct pf_anchor_node *head, struct pf_anchor *elm) { struct
pf_anchor *child, *parent, *old = elm; int color; if ((elm)->
entry_node.rbe_left == ((void *)0)) child = (elm)->entry_node
.rbe_right; else if ((elm)->entry_node.rbe_right == ((void
*)0)) child = (elm)->entry_node.rbe_left; else { struct pf_anchor
*left; elm = (elm)->entry_node.rbe_right; while ((left = (
elm)->entry_node.rbe_left)) elm = left; child = (elm)->
entry_node.rbe_right; parent = (elm)->entry_node.rbe_parent
; color = (elm)->entry_node.rbe_color; if (child) (child)->
entry_node.rbe_parent = parent; if (parent) { if ((parent)->
entry_node.rbe_left == elm) (parent)->entry_node.rbe_left =
child; else (parent)->entry_node.rbe_right = child; do {}
while (0); } else (head)->rbh_root = child; if ((elm)->
entry_node.rbe_parent == old) parent = elm; (elm)->entry_node
= (old)->entry_node; if ((old)->entry_node.rbe_parent)
{ if (((old)->entry_node.rbe_parent)->entry_node.rbe_left
== old) ((old)->entry_node.rbe_parent)->entry_node.rbe_left
= elm; else ((old)->entry_node.rbe_parent)->entry_node
.rbe_right = elm; do {} while (0); } else (head)->rbh_root
= elm; ((old)->entry_node.rbe_left)->entry_node.rbe_parent
= elm; if ((old)->entry_node.rbe_right) ((old)->entry_node
.rbe_right)->entry_node.rbe_parent = elm; if (parent) { left
= parent; do { do {} while (0); } while ((left = (left)->
entry_node.rbe_parent)); } goto color; } parent = (elm)->entry_node
.rbe_parent; color = (elm)->entry_node.rbe_color; if (child
) (child)->entry_node.rbe_parent = parent; if (parent) { if
((parent)->entry_node.rbe_left == elm) (parent)->entry_node
.rbe_left = child; else (parent)->entry_node.rbe_right = child
; do {} while (0); } else (head)->rbh_root = child; color:
if (color == 0) pf_anchor_node_RB_REMOVE_COLOR(head, parent,
child); return (old); } struct pf_anchor * pf_anchor_node_RB_INSERT
(struct pf_anchor_node *head, struct pf_anchor *elm) { struct
pf_anchor *tmp; struct pf_anchor *parent = ((void *)0); int comp
= 0; tmp = (head)->rbh_root; while (tmp) { parent = tmp; comp
= (pf_anchor_compare)(elm, parent); if (comp < 0) tmp = (
tmp)->entry_node.rbe_left; else if (comp > 0) tmp = (tmp
)->entry_node.rbe_right; else return (tmp); } do { (elm)->
entry_node.rbe_parent = parent; (elm)->entry_node.rbe_left
= (elm)->entry_node.rbe_right = ((void *)0); (elm)->entry_node
.rbe_color = 1; } while (0); if (parent != ((void *)0)) { if (
comp < 0) (parent)->entry_node.rbe_left = elm; else (parent
)->entry_node.rbe_right = elm; do {} while (0); } else (head
)->rbh_root = elm; pf_anchor_node_RB_INSERT_COLOR(head, elm
); return (((void *)0)); } struct pf_anchor * pf_anchor_node_RB_FIND
(struct pf_anchor_node *head, struct pf_anchor *elm) { struct
pf_anchor *tmp = (head)->rbh_root; int comp; while (tmp) {
comp = pf_anchor_compare(elm, tmp); if (comp < 0) tmp = (
tmp)->entry_node.rbe_left; else if (comp > 0) tmp = (tmp
)->entry_node.rbe_right; else return (tmp); } return (((void
*)0)); } struct pf_anchor * pf_anchor_node_RB_NFIND(struct pf_anchor_node
*head, struct pf_anchor *elm) { struct pf_anchor *tmp = (head
)->rbh_root; struct pf_anchor *res = ((void *)0); int comp
; while (tmp) { comp = pf_anchor_compare(elm, tmp); if (comp <
0) { res = tmp; tmp = (tmp)->entry_node.rbe_left; } else if
(comp > 0) tmp = (tmp)->entry_node.rbe_right; else return
(tmp); } return (res); } struct pf_anchor * pf_anchor_node_RB_NEXT
(struct pf_anchor *elm) { if ((elm)->entry_node.rbe_right)
{ elm = (elm)->entry_node.rbe_right; while ((elm)->entry_node
.rbe_left) elm = (elm)->entry_node.rbe_left; } else { if (
(elm)->entry_node.rbe_parent && (elm == ((elm)->
entry_node.rbe_parent)->entry_node.rbe_left)) elm = (elm)->
entry_node.rbe_parent; else { while ((elm)->entry_node.rbe_parent
&& (elm == ((elm)->entry_node.rbe_parent)->entry_node
.rbe_right)) elm = (elm)->entry_node.rbe_parent; elm = (elm
)->entry_node.rbe_parent; } } return (elm); } struct pf_anchor
* pf_anchor_node_RB_PREV(struct pf_anchor *elm) { if ((elm)->
entry_node.rbe_left) { elm = (elm)->entry_node.rbe_left; while
((elm)->entry_node.rbe_right) elm = (elm)->entry_node.
rbe_right; } else { if ((elm)->entry_node.rbe_parent &&
(elm == ((elm)->entry_node.rbe_parent)->entry_node.rbe_right
)) elm = (elm)->entry_node.rbe_parent; else { while ((elm)
->entry_node.rbe_parent && (elm == ((elm)->entry_node
.rbe_parent)->entry_node.rbe_left)) elm = (elm)->entry_node
.rbe_parent; elm = (elm)->entry_node.rbe_parent; } } return
(elm); } struct pf_anchor * pf_anchor_node_RB_MINMAX(struct pf_anchor_node
*head, int val) { struct pf_anchor *tmp = (head)->rbh_root
; struct pf_anchor *parent = ((void *)0); while (tmp) { parent
= tmp; if (val < 0) tmp = (tmp)->entry_node.rbe_left; else
tmp = (tmp)->entry_node.rbe_right; } return (parent); }
;
94
95static __inline int
96pf_anchor_compare(struct pf_anchor *a, struct pf_anchor *b)
97{
98 int c = strcmp(a->path, b->path);
99
100 return (c ? (c < 0 ? -1 : 1) : 0);
101}
102
103void
104pf_init_ruleset(struct pf_ruleset *ruleset)
105{
106 memset(ruleset, 0, sizeof(struct pf_ruleset));
107 TAILQ_INIT(&ruleset->rules.queues[0])do { (&ruleset->rules.queues[0])->tqh_first = ((void
*)0); (&ruleset->rules.queues[0])->tqh_last = &
(&ruleset->rules.queues[0])->tqh_first; } while (0)
;
108 TAILQ_INIT(&ruleset->rules.queues[1])do { (&ruleset->rules.queues[1])->tqh_first = ((void
*)0); (&ruleset->rules.queues[1])->tqh_last = &
(&ruleset->rules.queues[1])->tqh_first; } while (0)
;
109 ruleset->rules.active.ptr = &ruleset->rules.queues[0];
110 ruleset->rules.inactive.ptr = &ruleset->rules.queues[1];
111}
112
113struct pf_anchor *
114pf_find_anchor(const char *path)
115{
116 struct pf_anchor *key, *found;
117
118 key = rs_malloc(sizeof(*key))calloc(1, sizeof(*key));
119 if (key == NULL((void *)0))
120 return (NULL((void *)0));
121 strlcpy(key->path, path, sizeof(key->path));
122 found = RB_FIND(pf_anchor_global, &pf_anchors, key)pf_anchor_global_RB_FIND(&pf_anchors, key);
123 rs_free(key, sizeof(*key))freezero(key, sizeof(*key));
124 return (found);
125}
126
127struct pf_ruleset *
128pf_find_ruleset(const char *path)
129{
130 struct pf_anchor *anchor;
131
132 while (*path == '/')
133 path++;
134 if (!*path)
135 return (&pf_main_rulesetpf_main_anchor.ruleset);
136 anchor = pf_find_anchor(path);
137 if (anchor == NULL((void *)0))
138 return (NULL((void *)0));
139 else
140 return (&anchor->ruleset);
141}
142
143struct pf_ruleset *
144pf_get_leaf_ruleset(char *path, char **path_remainder)
145{
146 struct pf_ruleset *ruleset;
147 char *leaf, *p;
148 int i = 0;
149
150 p = path;
151 while (*p == '/')
152 p++;
153
154 ruleset = pf_find_ruleset(p);
155 leaf = p;
156 while (ruleset == NULL((void *)0)) {
157 leaf = strrchr(p, '/');
158 if (leaf != NULL((void *)0)) {
159 *leaf = '\0';
160 i++;
161 ruleset = pf_find_ruleset(p);
162 } else {
163 leaf = path;
164 /*
165 * if no path component exists, then main ruleset is
166 * our parent.
167 */
168 ruleset = &pf_main_rulesetpf_main_anchor.ruleset;
169 }
170 }
171
172 if (path_remainder != NULL((void *)0))
173 *path_remainder = leaf;
174
175 /* restore slashes in path. */
176 while (i != 0) {
177 while (*leaf != '\0')
178 leaf++;
179 *leaf = '/';
180 i--;
181 }
182
183 return (ruleset);
184}
185
186struct pf_anchor *
187pf_create_anchor(struct pf_anchor *parent, const char *aname)
188{
189 struct pf_anchor *anchor, *dup;
190
191 if (!*aname || (strlen(aname) >= PF_ANCHOR_NAME_SIZE64) ||
192 ((parent != NULL((void *)0)) && (strlen(parent->path) >= PF_ANCHOR_MAXPATH(1024 - 64 - 1))))
193 return (NULL((void *)0));
194
195 anchor = rs_pool_get_anchor()calloc(1, sizeof(struct pf_anchor));
196 if (anchor == NULL((void *)0))
197 return (NULL((void *)0));
198
199 RB_INIT(&anchor->children)do { (&anchor->children)->rbh_root = ((void *)0); }
while (0)
;
200 strlcpy(anchor->name, aname, sizeof(anchor->name));
201 if (parent != NULL((void *)0)) {
202 /*
203 * Make sure path for levels 2, 3, ... is terminated by '/':
204 * 1/2/3/...
205 */
206 strlcpy(anchor->path, parent->path, sizeof(anchor->path));
207 strlcat(anchor->path, "/", sizeof(anchor->path));
208 }
209 strlcat(anchor->path, anchor->name, sizeof(anchor->path));
210
211 if ((dup = RB_INSERT(pf_anchor_global, &pf_anchors, anchor)pf_anchor_global_RB_INSERT(&pf_anchors, anchor)) != NULL((void *)0)) {
Although the value stored to 'dup' is used in the enclosing expression, the value is never actually read from 'dup'
212 DPFPRINTF(LOG_NOTICE,((void)0)
213 "%s: RB_INSERT to global '%s' '%s' collides with '%s' '%s'",((void)0)
214 __func__, anchor->path, anchor->name, dup->path, dup->name)((void)0);
215 rs_pool_put_anchor(anchor)freezero(anchor, sizeof(struct pf_anchor));
216 return (NULL((void *)0));
217 }
218
219 if (parent != NULL((void *)0)) {
220 anchor->parent = parent;
221 dup = RB_INSERT(pf_anchor_node, &parent->children, anchor)pf_anchor_node_RB_INSERT(&parent->children, anchor);
222 if (dup != NULL((void *)0)) {
223 DPFPRINTF(LOG_NOTICE,((void)0)
224 "%s: RB_INSERT to parent '%s' '%s' collides with "((void)0)
225 "'%s' '%s'", __func__, anchor->path, anchor->name,((void)0)
226 dup->path, dup->name)((void)0);
227 RB_REMOVE(pf_anchor_global, &pf_anchors,pf_anchor_global_RB_REMOVE(&pf_anchors, anchor)
228 anchor)pf_anchor_global_RB_REMOVE(&pf_anchors, anchor);
229 rs_pool_put_anchor(anchor)freezero(anchor, sizeof(struct pf_anchor));
230 return (NULL((void *)0));
231 }
232 }
233
234 pf_init_ruleset(&anchor->ruleset);
235 anchor->ruleset.anchor = anchor;
236#ifdef _KERNEL
237 refcnt_init(&anchor->ref);
238#endif
239
240 return (anchor);
241}
242
243struct pf_ruleset *
244pf_find_or_create_ruleset(const char *path)
245{
246 char *p, *aname, *r;
247 struct pf_ruleset *ruleset;
248 struct pf_anchor *anchor;
249
250 if (path[0] == 0)
251 return (&pf_main_rulesetpf_main_anchor.ruleset);
252
253 while (*path == '/')
254 path++;
255
256 ruleset = pf_find_ruleset(path);
257 if (ruleset != NULL((void *)0))
258 return (ruleset);
259
260 p = rs_malloc(MAXPATHLEN)calloc(1, 1024);
261 if (p == NULL((void *)0))
262 return (NULL((void *)0));
263 strlcpy(p, path, MAXPATHLEN1024);
264
265 ruleset = pf_get_leaf_ruleset(p, &aname);
266 anchor = ruleset->anchor;
267
268 while (*aname == '/')
269 aname++;
270 /*
271 * aname is a path remainder, which contains nodes we must create. We
272 * process the aname path from left to right, effectively descending
273 * from parents to children.
274 */
275 while ((r = strchr(aname, '/')) != NULL((void *)0) || *aname) {
276 if (r != NULL((void *)0))
277 *r = 0;
278
279 anchor = pf_create_anchor(anchor, aname);
280 if (anchor == NULL((void *)0)) {
281 rs_free(p, MAXPATHLEN)freezero(p, 1024);
282 return (NULL((void *)0));
283 }
284
285 if (r == NULL((void *)0))
286 break;
287 else
288 aname = r + 1;
289 }
290
291 rs_free(p, MAXPATHLEN)freezero(p, 1024);
292 return (&anchor->ruleset);
293}
294
295void
296pf_remove_if_empty_ruleset(struct pf_ruleset *ruleset)
297{
298 struct pf_anchor *parent;
299
300 while (ruleset != NULL((void *)0)) {
301 if (ruleset == &pf_main_rulesetpf_main_anchor.ruleset ||
302 !RB_EMPTY(&ruleset->anchor->children)((&ruleset->anchor->children)->rbh_root == ((void
*)0))
||
303 ruleset->anchor->refcnt > 0 || ruleset->tables > 0 ||
304 ruleset->topen)
305 return;
306 if (!TAILQ_EMPTY(ruleset->rules.active.ptr)(((ruleset->rules.active.ptr)->tqh_first) == ((void *)0
))
||
307 !TAILQ_EMPTY(ruleset->rules.inactive.ptr)(((ruleset->rules.inactive.ptr)->tqh_first) == ((void *
)0))
||
308 ruleset->rules.inactive.open)
309 return;
310 RB_REMOVE(pf_anchor_global, &pf_anchors, ruleset->anchor)pf_anchor_global_RB_REMOVE(&pf_anchors, ruleset->anchor
)
;
311 if ((parent = ruleset->anchor->parent) != NULL((void *)0))
312 RB_REMOVE(pf_anchor_node, &parent->children,pf_anchor_node_RB_REMOVE(&parent->children, ruleset->
anchor)
313 ruleset->anchor)pf_anchor_node_RB_REMOVE(&parent->children, ruleset->
anchor)
;
314 pf_anchor_rele(ruleset->anchor);
315 if (parent == NULL((void *)0))
316 return;
317 ruleset = &parent->ruleset;
318 }
319}
320
321int
322pf_anchor_setup(struct pf_rule *r, const struct pf_ruleset *s,
323 const char *name)
324{
325 char *p, *path;
326 struct pf_ruleset *ruleset;
327
328 r->anchor = NULL((void *)0);
329 r->anchor_relative = 0;
330 r->anchor_wildcard = 0;
331 if (!name[0])
332 return (0);
333 path = rs_malloc(MAXPATHLEN)calloc(1, 1024);
334 if (path == NULL((void *)0))
335 return (1);
336 if (name[0] == '/')
337 strlcpy(path, name + 1, MAXPATHLEN1024);
338 else {
339 /* relative path */
340 r->anchor_relative = 1;
341 if (s->anchor == NULL((void *)0) || !s->anchor->path[0])
342 path[0] = 0;
343 else
344 strlcpy(path, s->anchor->path, MAXPATHLEN1024);
345 while (name[0] == '.' && name[1] == '.' && name[2] == '/') {
346 if (!path[0]) {
347 DPFPRINTF(LOG_NOTICE,((void)0)
348 "pf_anchor_setup: .. beyond root")((void)0);
349 rs_free(path, MAXPATHLEN)freezero(path, 1024);
350 return (1);
351 }
352 if ((p = strrchr(path, '/')) != NULL((void *)0))
353 *p = 0;
354 else
355 path[0] = 0;
356 r->anchor_relative++;
357 name += 3;
358 }
359 if (path[0])
360 strlcat(path, "/", MAXPATHLEN1024);
361 strlcat(path, name, MAXPATHLEN1024);
362 }
363 if ((p = strrchr(path, '/')) != NULL((void *)0) && !strcmp(p, "/*")) {
364 r->anchor_wildcard = 1;
365 *p = 0;
366 }
367 ruleset = pf_find_or_create_ruleset(path);
368 rs_free(path, MAXPATHLEN)freezero(path, 1024);
369 if (ruleset == NULL((void *)0) || ruleset == &pf_main_rulesetpf_main_anchor.ruleset) {
370 DPFPRINTF(LOG_NOTICE,((void)0)
371 "pf_anchor_setup: ruleset")((void)0);
372 return (1);
373 }
374 r->anchor = ruleset->anchor;
375 r->anchor->refcnt++;
376 return (0);
377}
378
379int
380pf_anchor_copyout(const struct pf_ruleset *rs, const struct pf_rule *r,
381 struct pfioc_rule *pr)
382{
383 pr->anchor_call[0] = 0;
384 if (r->anchor == NULL((void *)0))
385 return (0);
386 if (!r->anchor_relative) {
387 strlcpy(pr->anchor_call, "/", sizeof(pr->anchor_call));
388 strlcat(pr->anchor_call, r->anchor->path,
389 sizeof(pr->anchor_call));
390 } else {
391 char *a, *p;
392 int i;
393
394 a = rs_malloc(MAXPATHLEN)calloc(1, 1024);
395 if (a == NULL((void *)0))
396 return (1);
397 if (rs == &pf_main_rulesetpf_main_anchor.ruleset)
398 a[0] = 0;
399 else
400 strlcpy(a, rs->anchor->path, MAXPATHLEN1024);
401 for (i = 1; i < r->anchor_relative; ++i) {
402 if ((p = strrchr(a, '/')) == NULL((void *)0))
403 p = a;
404 *p = 0;
405 strlcat(pr->anchor_call, "../",
406 sizeof(pr->anchor_call));
407 }
408 if (strncmp(a, r->anchor->path, strlen(a))) {
409 DPFPRINTF(LOG_NOTICE,((void)0)
410 "pf_anchor_copyout: '%s' '%s'", a,((void)0)
411 r->anchor->path)((void)0);
412 rs_free(a, MAXPATHLEN)freezero(a, 1024);
413 return (1);
414 }
415 if (strlen(r->anchor->path) > strlen(a))
416 strlcat(pr->anchor_call, r->anchor->path + (a[0] ?
417 strlen(a) + 1 : 0), sizeof(pr->anchor_call));
418 rs_free(a, MAXPATHLEN)freezero(a, 1024);
419 }
420 if (r->anchor_wildcard)
421 strlcat(pr->anchor_call, pr->anchor_call[0] ? "/*" : "*",
422 sizeof(pr->anchor_call));
423 return (0);
424}
425
426void
427pf_remove_anchor(struct pf_rule *r)
428{
429 if (r->anchor == NULL((void *)0))
430 return;
431 if (r->anchor->refcnt <= 0)
432 DPFPRINTF(LOG_NOTICE, "pf_remove_anchor: broken refcount")((void)0);
433 else if (!--r->anchor->refcnt)
434 pf_remove_if_empty_ruleset(&r->anchor->ruleset);
435 r->anchor = NULL((void *)0);
436}
437
438void
439pf_anchor_rele(struct pf_anchor *anchor)
440{
441 if ((anchor == NULL((void *)0)) || (anchor == &pf_main_anchor))
442 return;
443
444#ifdef _KERNEL
445 if (refcnt_rele(&anchor->ref))
446 rs_pool_put_anchor(anchor)freezero(anchor, sizeof(struct pf_anchor));
447#else
448 rs_pool_put_anchor(anchor)freezero(anchor, sizeof(struct pf_anchor));
449#endif
450}
451
452struct pf_anchor *
453pf_anchor_take(struct pf_anchor *anchor)
454{
455#ifdef _KERNEL
456 if (anchor != NULL((void *)0) && anchor != &pf_main_anchor)
457 refcnt_take(&anchor->ref);
458#endif
459 return (anchor);
460}