Bug Summary

File:src/sbin/pfctl/../../sys/net/pf_ruleset.c
Warning:line 203, 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.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name pf_ruleset.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -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 -fno-rounding-math -mconstructor-aliases -munwind-tables -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/lib/clang/13.0.0 -I /usr/src/sbin/pfctl -internal-isystem /usr/local/lib/clang/13.0.0/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 -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/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/sbin/pfctl/../../sys/net/pf_ruleset.c
1/* $OpenBSD: pf_ruleset.c,v 1.18 2018/12/27 16:54:01 kn 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#endif /* _KERNEL */
44#include <sys/syslog.h>
45
46#include <netinet/in.h>
47#include <netinet/ip.h>
48#include <netinet/tcp.h>
49
50#include <net/if.h>
51#include <net/pfvar.h>
52
53#ifdef INET6
54#include <netinet/ip6.h>
55#endif /* INET6 */
56
57
58#ifdef _KERNEL
59#define rs_malloc(x)calloc(1, x) malloc(x, M_TEMP, M_WAITOK|M_CANFAIL|M_ZERO)
60#define rs_free(x, siz)freezero(x, siz) free(x, M_TEMP, siz)
61
62#else /* !_KERNEL */
63/* Userland equivalents so we can lend code to pfctl et al. */
64
65#include <arpa/inet.h>
66#include <errno(*__errno()).h>
67#include <stdio.h>
68#include <stdlib.h>
69#include <string.h>
70#define rs_malloc(x)calloc(1, x) calloc(1, x)
71#define rs_free(x, siz)freezero(x, siz) freezero(x, siz)
72
73#ifdef PFDEBUG
74#include <sys/stdarg.h> /* for DPFPRINTF() */
75#endif /* PFDEBUG */
76#endif /* _KERNEL */
77
78
79struct pf_anchor_global pf_anchors;
80struct pf_anchor pf_main_anchor;
81
82static __inline int pf_anchor_compare(struct pf_anchor *, struct pf_anchor *);
83
84RB_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); }
;
85RB_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); }
;
86
87static __inline int
88pf_anchor_compare(struct pf_anchor *a, struct pf_anchor *b)
89{
90 int c = strcmp(a->path, b->path);
91
92 return (c ? (c < 0 ? -1 : 1) : 0);
93}
94
95void
96pf_init_ruleset(struct pf_ruleset *ruleset)
97{
98 memset(ruleset, 0, sizeof(struct pf_ruleset));
99 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)
;
100 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)
;
101 ruleset->rules.active.ptr = &ruleset->rules.queues[0];
102 ruleset->rules.inactive.ptr = &ruleset->rules.queues[1];
103}
104
105struct pf_anchor *
106pf_find_anchor(const char *path)
107{
108 struct pf_anchor *key, *found;
109
110 key = rs_malloc(sizeof(*key))calloc(1, sizeof(*key));
111 if (key == NULL((void *)0))
112 return (NULL((void *)0));
113 strlcpy(key->path, path, sizeof(key->path));
114 found = RB_FIND(pf_anchor_global, &pf_anchors, key)pf_anchor_global_RB_FIND(&pf_anchors, key);
115 rs_free(key, sizeof(*key))freezero(key, sizeof(*key));
116 return (found);
117}
118
119struct pf_ruleset *
120pf_find_ruleset(const char *path)
121{
122 struct pf_anchor *anchor;
123
124 while (*path == '/')
125 path++;
126 if (!*path)
127 return (&pf_main_rulesetpf_main_anchor.ruleset);
128 anchor = pf_find_anchor(path);
129 if (anchor == NULL((void *)0))
130 return (NULL((void *)0));
131 else
132 return (&anchor->ruleset);
133}
134
135struct pf_ruleset *
136pf_get_leaf_ruleset(char *path, char **path_remainder)
137{
138 struct pf_ruleset *ruleset;
139 char *leaf, *p;
140 int i = 0;
141
142 p = path;
143 while (*p == '/')
144 p++;
145
146 ruleset = pf_find_ruleset(p);
147 leaf = p;
148 while (ruleset == NULL((void *)0)) {
149 leaf = strrchr(p, '/');
150 if (leaf != NULL((void *)0)) {
151 *leaf = '\0';
152 i++;
153 ruleset = pf_find_ruleset(p);
154 } else {
155 leaf = path;
156 /*
157 * if no path component exists, then main ruleset is
158 * our parent.
159 */
160 ruleset = &pf_main_rulesetpf_main_anchor.ruleset;
161 }
162 }
163
164 if (path_remainder != NULL((void *)0))
165 *path_remainder = leaf;
166
167 /* restore slashes in path. */
168 while (i != 0) {
169 while (*leaf != '\0')
170 leaf++;
171 *leaf = '/';
172 i--;
173 }
174
175 return (ruleset);
176}
177
178struct pf_anchor *
179pf_create_anchor(struct pf_anchor *parent, const char *aname)
180{
181 struct pf_anchor *anchor, *dup;
182
183 if (!*aname || (strlen(aname) >= PF_ANCHOR_NAME_SIZE64) ||
184 ((parent != NULL((void *)0)) && (strlen(parent->path) >= PF_ANCHOR_MAXPATH(1024 - 64 - 1))))
185 return (NULL((void *)0));
186
187 anchor = rs_malloc(sizeof(*anchor))calloc(1, sizeof(*anchor));
188 if (anchor == NULL((void *)0))
189 return (NULL((void *)0));
190
191 RB_INIT(&anchor->children)do { (&anchor->children)->rbh_root = ((void *)0); }
while (0)
;
192 strlcpy(anchor->name, aname, sizeof(anchor->name));
193 if (parent != NULL((void *)0)) {
194 /*
195 * Make sure path for levels 2, 3, ... is terminated by '/':
196 * 1/2/3/...
197 */
198 strlcpy(anchor->path, parent->path, sizeof(anchor->path));
199 strlcat(anchor->path, "/", sizeof(anchor->path));
200 }
201 strlcat(anchor->path, anchor->name, sizeof(anchor->path));
202
203 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'
204 DPFPRINTF(LOG_NOTICE,((void)0)
205 "%s: RB_INSERT to global '%s' '%s' collides with '%s' '%s'",((void)0)
206 __func__, anchor->path, anchor->name, dup->path, dup->name)((void)0);
207 rs_free(anchor, sizeof(*anchor))freezero(anchor, sizeof(*anchor));
208 return (NULL((void *)0));
209 }
210
211 if (parent != NULL((void *)0)) {
212 anchor->parent = parent;
213 dup = RB_INSERT(pf_anchor_node, &parent->children, anchor)pf_anchor_node_RB_INSERT(&parent->children, anchor);
214 if (dup != NULL((void *)0)) {
215 DPFPRINTF(LOG_NOTICE,((void)0)
216 "%s: RB_INSERT to parent '%s' '%s' collides with "((void)0)
217 "'%s' '%s'", __func__, anchor->path, anchor->name,((void)0)
218 dup->path, dup->name)((void)0);
219 RB_REMOVE(pf_anchor_global, &pf_anchors,pf_anchor_global_RB_REMOVE(&pf_anchors, anchor)
220 anchor)pf_anchor_global_RB_REMOVE(&pf_anchors, anchor);
221 rs_free(anchor, sizeof(*anchor))freezero(anchor, sizeof(*anchor));
222 return (NULL((void *)0));
223 }
224 }
225
226 pf_init_ruleset(&anchor->ruleset);
227 anchor->ruleset.anchor = anchor;
228
229 return (anchor);
230}
231
232struct pf_ruleset *
233pf_find_or_create_ruleset(const char *path)
234{
235 char *p, *aname, *r;
236 struct pf_ruleset *ruleset;
237 struct pf_anchor *anchor;
238
239 if (path[0] == 0)
240 return (&pf_main_rulesetpf_main_anchor.ruleset);
241
242 while (*path == '/')
243 path++;
244
245 ruleset = pf_find_ruleset(path);
246 if (ruleset != NULL((void *)0))
247 return (ruleset);
248
249 p = rs_malloc(MAXPATHLEN)calloc(1, 1024);
250 if (p == NULL((void *)0))
251 return (NULL((void *)0));
252 strlcpy(p, path, MAXPATHLEN1024);
253
254 ruleset = pf_get_leaf_ruleset(p, &aname);
255 anchor = ruleset->anchor;
256
257 while (*aname == '/')
258 aname++;
259 /*
260 * aname is a path remainder, which contains nodes we must create. We
261 * process the aname path from left to right, effectively descending
262 * from parents to children.
263 */
264 while ((r = strchr(aname, '/')) != NULL((void *)0) || *aname) {
265 if (r != NULL((void *)0))
266 *r = 0;
267
268 anchor = pf_create_anchor(anchor, aname);
269 if (anchor == NULL((void *)0)) {
270 rs_free(p, MAXPATHLEN)freezero(p, 1024);
271 return (NULL((void *)0));
272 }
273
274 if (r == NULL((void *)0))
275 break;
276 else
277 aname = r + 1;
278 }
279
280 rs_free(p, MAXPATHLEN)freezero(p, 1024);
281 return (&anchor->ruleset);
282}
283
284void
285pf_remove_if_empty_ruleset(struct pf_ruleset *ruleset)
286{
287 struct pf_anchor *parent;
288
289 while (ruleset != NULL((void *)0)) {
290 if (ruleset == &pf_main_rulesetpf_main_anchor.ruleset ||
291 !RB_EMPTY(&ruleset->anchor->children)((&ruleset->anchor->children)->rbh_root == ((void
*)0))
||
292 ruleset->anchor->refcnt > 0 || ruleset->tables > 0 ||
293 ruleset->topen)
294 return;
295 if (!TAILQ_EMPTY(ruleset->rules.active.ptr)(((ruleset->rules.active.ptr)->tqh_first) == ((void *)0
))
||
296 !TAILQ_EMPTY(ruleset->rules.inactive.ptr)(((ruleset->rules.inactive.ptr)->tqh_first) == ((void *
)0))
||
297 ruleset->rules.inactive.open)
298 return;
299 RB_REMOVE(pf_anchor_global, &pf_anchors, ruleset->anchor)pf_anchor_global_RB_REMOVE(&pf_anchors, ruleset->anchor
)
;
300 if ((parent = ruleset->anchor->parent) != NULL((void *)0))
301 RB_REMOVE(pf_anchor_node, &parent->children,pf_anchor_node_RB_REMOVE(&parent->children, ruleset->
anchor)
302 ruleset->anchor)pf_anchor_node_RB_REMOVE(&parent->children, ruleset->
anchor)
;
303 rs_free(ruleset->anchor, sizeof(*(ruleset->anchor)))freezero(ruleset->anchor, sizeof(*(ruleset->anchor)));
304 if (parent == NULL((void *)0))
305 return;
306 ruleset = &parent->ruleset;
307 }
308}
309
310int
311pf_anchor_setup(struct pf_rule *r, const struct pf_ruleset *s,
312 const char *name)
313{
314 char *p, *path;
315 struct pf_ruleset *ruleset;
316
317 r->anchor = NULL((void *)0);
318 r->anchor_relative = 0;
319 r->anchor_wildcard = 0;
320 if (!name[0])
321 return (0);
322 path = rs_malloc(MAXPATHLEN)calloc(1, 1024);
323 if (path == NULL((void *)0))
324 return (1);
325 if (name[0] == '/')
326 strlcpy(path, name + 1, MAXPATHLEN1024);
327 else {
328 /* relative path */
329 r->anchor_relative = 1;
330 if (s->anchor == NULL((void *)0) || !s->anchor->path[0])
331 path[0] = 0;
332 else
333 strlcpy(path, s->anchor->path, MAXPATHLEN1024);
334 while (name[0] == '.' && name[1] == '.' && name[2] == '/') {
335 if (!path[0]) {
336 DPFPRINTF(LOG_NOTICE,((void)0)
337 "pf_anchor_setup: .. beyond root")((void)0);
338 rs_free(path, MAXPATHLEN)freezero(path, 1024);
339 return (1);
340 }
341 if ((p = strrchr(path, '/')) != NULL((void *)0))
342 *p = 0;
343 else
344 path[0] = 0;
345 r->anchor_relative++;
346 name += 3;
347 }
348 if (path[0])
349 strlcat(path, "/", MAXPATHLEN1024);
350 strlcat(path, name, MAXPATHLEN1024);
351 }
352 if ((p = strrchr(path, '/')) != NULL((void *)0) && !strcmp(p, "/*")) {
353 r->anchor_wildcard = 1;
354 *p = 0;
355 }
356 ruleset = pf_find_or_create_ruleset(path);
357 rs_free(path, MAXPATHLEN)freezero(path, 1024);
358 if (ruleset == NULL((void *)0) || ruleset == &pf_main_rulesetpf_main_anchor.ruleset) {
359 DPFPRINTF(LOG_NOTICE,((void)0)
360 "pf_anchor_setup: ruleset")((void)0);
361 return (1);
362 }
363 r->anchor = ruleset->anchor;
364 r->anchor->refcnt++;
365 return (0);
366}
367
368int
369pf_anchor_copyout(const struct pf_ruleset *rs, const struct pf_rule *r,
370 struct pfioc_rule *pr)
371{
372 pr->anchor_call[0] = 0;
373 if (r->anchor == NULL((void *)0))
374 return (0);
375 if (!r->anchor_relative) {
376 strlcpy(pr->anchor_call, "/", sizeof(pr->anchor_call));
377 strlcat(pr->anchor_call, r->anchor->path,
378 sizeof(pr->anchor_call));
379 } else {
380 char *a, *p;
381 int i;
382
383 a = rs_malloc(MAXPATHLEN)calloc(1, 1024);
384 if (a == NULL((void *)0))
385 return (1);
386 if (rs == &pf_main_rulesetpf_main_anchor.ruleset)
387 a[0] = 0;
388 else
389 strlcpy(a, rs->anchor->path, MAXPATHLEN1024);
390 for (i = 1; i < r->anchor_relative; ++i) {
391 if ((p = strrchr(a, '/')) == NULL((void *)0))
392 p = a;
393 *p = 0;
394 strlcat(pr->anchor_call, "../",
395 sizeof(pr->anchor_call));
396 }
397 if (strncmp(a, r->anchor->path, strlen(a))) {
398 DPFPRINTF(LOG_NOTICE,((void)0)
399 "pf_anchor_copyout: '%s' '%s'", a,((void)0)
400 r->anchor->path)((void)0);
401 rs_free(a, MAXPATHLEN)freezero(a, 1024);
402 return (1);
403 }
404 if (strlen(r->anchor->path) > strlen(a))
405 strlcat(pr->anchor_call, r->anchor->path + (a[0] ?
406 strlen(a) + 1 : 0), sizeof(pr->anchor_call));
407 rs_free(a, MAXPATHLEN)freezero(a, 1024);
408 }
409 if (r->anchor_wildcard)
410 strlcat(pr->anchor_call, pr->anchor_call[0] ? "/*" : "*",
411 sizeof(pr->anchor_call));
412 return (0);
413}
414
415void
416pf_remove_anchor(struct pf_rule *r)
417{
418 if (r->anchor == NULL((void *)0))
419 return;
420 if (r->anchor->refcnt <= 0)
421 DPFPRINTF(LOG_NOTICE, "pf_remove_anchor: broken refcount")((void)0);
422 else if (!--r->anchor->refcnt)
423 pf_remove_if_empty_ruleset(&r->anchor->ruleset);
424 r->anchor = NULL((void *)0);
425}