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' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | |
79 | struct pf_anchor_global pf_anchors; |
80 | struct pf_anchor pf_main_anchor; |
81 | |
82 | static __inline int pf_anchor_compare(struct pf_anchor *, struct pf_anchor *); |
83 | |
84 | RB_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); }; |
85 | RB_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 | |
87 | static __inline int |
88 | pf_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 | |
95 | void |
96 | pf_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 | |
105 | struct pf_anchor * |
106 | pf_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 | |
119 | struct pf_ruleset * |
120 | pf_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 | |
135 | struct pf_ruleset * |
136 | pf_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 | |
178 | struct pf_anchor * |
179 | pf_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 | |
232 | struct pf_ruleset * |
233 | pf_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 | |
284 | void |
285 | pf_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 | |
310 | int |
311 | pf_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 | |
368 | int |
369 | pf_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 | |
415 | void |
416 | pf_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 | } |