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