| 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 | } |