1d8aa10ccSGleb Smirnoff /*- 2fe267a55SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause 3fe267a55SPedro F. Giffuni * 43b3a8eb9SGleb Smirnoff * Copyright (c) 2001 Daniel Hartmeier 53b3a8eb9SGleb Smirnoff * Copyright (c) 2002,2003 Henning Brauer 63b3a8eb9SGleb Smirnoff * All rights reserved. 73b3a8eb9SGleb Smirnoff * 83b3a8eb9SGleb Smirnoff * Redistribution and use in source and binary forms, with or without 93b3a8eb9SGleb Smirnoff * modification, are permitted provided that the following conditions 103b3a8eb9SGleb Smirnoff * are met: 113b3a8eb9SGleb Smirnoff * 123b3a8eb9SGleb Smirnoff * - Redistributions of source code must retain the above copyright 133b3a8eb9SGleb Smirnoff * notice, this list of conditions and the following disclaimer. 143b3a8eb9SGleb Smirnoff * - Redistributions in binary form must reproduce the above 153b3a8eb9SGleb Smirnoff * copyright notice, this list of conditions and the following 163b3a8eb9SGleb Smirnoff * disclaimer in the documentation and/or other materials provided 173b3a8eb9SGleb Smirnoff * with the distribution. 183b3a8eb9SGleb Smirnoff * 193b3a8eb9SGleb Smirnoff * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 203b3a8eb9SGleb Smirnoff * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 213b3a8eb9SGleb Smirnoff * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 223b3a8eb9SGleb Smirnoff * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 233b3a8eb9SGleb Smirnoff * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 243b3a8eb9SGleb Smirnoff * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 253b3a8eb9SGleb Smirnoff * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 263b3a8eb9SGleb Smirnoff * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 273b3a8eb9SGleb Smirnoff * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 283b3a8eb9SGleb Smirnoff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 293b3a8eb9SGleb Smirnoff * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 303b3a8eb9SGleb Smirnoff * POSSIBILITY OF SUCH DAMAGE. 313b3a8eb9SGleb Smirnoff * 323b3a8eb9SGleb Smirnoff * Effort sponsored in part by the Defense Advanced Research Projects 333b3a8eb9SGleb Smirnoff * Agency (DARPA) and Air Force Research Laboratory, Air Force 343b3a8eb9SGleb Smirnoff * Materiel Command, USAF, under agreement number F30602-01-2-0537. 353b3a8eb9SGleb Smirnoff * 36d8aa10ccSGleb Smirnoff * $OpenBSD: pf_ruleset.c,v 1.2 2008/12/18 15:31:37 dhill Exp $ 373b3a8eb9SGleb Smirnoff */ 383b3a8eb9SGleb Smirnoff 393b3a8eb9SGleb Smirnoff #include <sys/cdefs.h> 403b3a8eb9SGleb Smirnoff __FBSDID("$FreeBSD$"); 413b3a8eb9SGleb Smirnoff 423b3a8eb9SGleb Smirnoff #include <sys/param.h> 433b3a8eb9SGleb Smirnoff #include <sys/socket.h> 443b3a8eb9SGleb Smirnoff #include <sys/systm.h> 453b3a8eb9SGleb Smirnoff #include <sys/refcount.h> 463b3a8eb9SGleb Smirnoff #include <sys/mbuf.h> 473b3a8eb9SGleb Smirnoff 483b3a8eb9SGleb Smirnoff #include <netinet/in.h> 493b3a8eb9SGleb Smirnoff #include <netinet/in_systm.h> 503b3a8eb9SGleb Smirnoff #include <netinet/ip.h> 513b3a8eb9SGleb Smirnoff #include <netinet/tcp.h> 523b3a8eb9SGleb Smirnoff 533b3a8eb9SGleb Smirnoff #include <net/if.h> 54eedc7fd9SGleb Smirnoff #include <net/vnet.h> 553b3a8eb9SGleb Smirnoff #include <net/pfvar.h> 563b3a8eb9SGleb Smirnoff 573b3a8eb9SGleb Smirnoff #ifdef INET6 583b3a8eb9SGleb Smirnoff #include <netinet/ip6.h> 593b3a8eb9SGleb Smirnoff #endif /* INET6 */ 603b3a8eb9SGleb Smirnoff 61fda7daf0SKristof Provost #ifndef _KERNEL 62fda7daf0SKristof Provost #error "Kernel only file. Please use sbin/pfctl/pf_ruleset.c instead." 63fda7daf0SKristof Provost #endif 64fda7daf0SKristof Provost 653b3a8eb9SGleb Smirnoff #define DPFPRINTF(format, x...) \ 663b3a8eb9SGleb Smirnoff if (V_pf_status.debug >= PF_DEBUG_NOISY) \ 673b3a8eb9SGleb Smirnoff printf(format , ##x) 683b3a8eb9SGleb Smirnoff #define rs_malloc(x) malloc(x, M_TEMP, M_NOWAIT|M_ZERO) 693b3a8eb9SGleb Smirnoff #define rs_free(x) free(x, M_TEMP) 703b3a8eb9SGleb Smirnoff 71e86bddeaSKristof Provost VNET_DEFINE(struct pf_kanchor_global, pf_anchors); 72e86bddeaSKristof Provost VNET_DEFINE(struct pf_kanchor, pf_main_anchor); 733b3a8eb9SGleb Smirnoff 74e86bddeaSKristof Provost static __inline int pf_kanchor_compare(struct pf_kanchor *, 75e86bddeaSKristof Provost struct pf_kanchor *); 76e86bddeaSKristof Provost static struct pf_kanchor *pf_find_kanchor(const char *); 77e86bddeaSKristof Provost 78e86bddeaSKristof Provost RB_GENERATE(pf_kanchor_global, pf_kanchor, entry_global, pf_kanchor_compare); 79e86bddeaSKristof Provost RB_GENERATE(pf_kanchor_node, pf_kanchor, entry_node, pf_kanchor_compare); 803b3a8eb9SGleb Smirnoff 81e86bddeaSKristof Provost static __inline int 82e86bddeaSKristof Provost pf_kanchor_compare(struct pf_kanchor *a, struct pf_kanchor *b) 83e86bddeaSKristof Provost { 84e86bddeaSKristof Provost int c = strcmp(a->path, b->path); 85e86bddeaSKristof Provost 86e86bddeaSKristof Provost return (c ? (c < 0 ? -1 : 1) : 0); 87e86bddeaSKristof Provost } 883b3a8eb9SGleb Smirnoff 893b3a8eb9SGleb Smirnoff int 903b3a8eb9SGleb Smirnoff pf_get_ruleset_number(u_int8_t action) 913b3a8eb9SGleb Smirnoff { 923b3a8eb9SGleb Smirnoff switch (action) { 933b3a8eb9SGleb Smirnoff case PF_SCRUB: 943b3a8eb9SGleb Smirnoff case PF_NOSCRUB: 953b3a8eb9SGleb Smirnoff return (PF_RULESET_SCRUB); 963b3a8eb9SGleb Smirnoff break; 973b3a8eb9SGleb Smirnoff case PF_PASS: 983b3a8eb9SGleb Smirnoff case PF_DROP: 993b3a8eb9SGleb Smirnoff return (PF_RULESET_FILTER); 1003b3a8eb9SGleb Smirnoff break; 1013b3a8eb9SGleb Smirnoff case PF_NAT: 1023b3a8eb9SGleb Smirnoff case PF_NONAT: 1033b3a8eb9SGleb Smirnoff return (PF_RULESET_NAT); 1043b3a8eb9SGleb Smirnoff break; 1053b3a8eb9SGleb Smirnoff case PF_BINAT: 1063b3a8eb9SGleb Smirnoff case PF_NOBINAT: 1073b3a8eb9SGleb Smirnoff return (PF_RULESET_BINAT); 1083b3a8eb9SGleb Smirnoff break; 1093b3a8eb9SGleb Smirnoff case PF_RDR: 1103b3a8eb9SGleb Smirnoff case PF_NORDR: 1113b3a8eb9SGleb Smirnoff return (PF_RULESET_RDR); 1123b3a8eb9SGleb Smirnoff break; 1133b3a8eb9SGleb Smirnoff default: 1143b3a8eb9SGleb Smirnoff return (PF_RULESET_MAX); 1153b3a8eb9SGleb Smirnoff break; 1163b3a8eb9SGleb Smirnoff } 1173b3a8eb9SGleb Smirnoff } 1183b3a8eb9SGleb Smirnoff 119e86bddeaSKristof Provost static struct pf_kanchor * 120e86bddeaSKristof Provost pf_find_kanchor(const char *path) 121e86bddeaSKristof Provost { 122e86bddeaSKristof Provost struct pf_kanchor *key, *found; 123e86bddeaSKristof Provost 124e86bddeaSKristof Provost key = (struct pf_kanchor *)rs_malloc(sizeof(*key)); 125e86bddeaSKristof Provost if (key == NULL) 126e86bddeaSKristof Provost return (NULL); 127e86bddeaSKristof Provost strlcpy(key->path, path, sizeof(key->path)); 128e86bddeaSKristof Provost found = RB_FIND(pf_kanchor_global, &V_pf_anchors, key); 129e86bddeaSKristof Provost rs_free(key); 130e86bddeaSKristof Provost return (found); 131e86bddeaSKristof Provost } 132e86bddeaSKristof Provost 133e86bddeaSKristof Provost void 134e86bddeaSKristof Provost pf_init_kruleset(struct pf_kruleset *ruleset) 135e86bddeaSKristof Provost { 136e86bddeaSKristof Provost int i; 137e86bddeaSKristof Provost 138e86bddeaSKristof Provost memset(ruleset, 0, sizeof(struct pf_kruleset)); 139e86bddeaSKristof Provost for (i = 0; i < PF_RULESET_MAX; i++) { 140e86bddeaSKristof Provost TAILQ_INIT(&ruleset->rules[i].queues[0]); 141e86bddeaSKristof Provost TAILQ_INIT(&ruleset->rules[i].queues[1]); 142e86bddeaSKristof Provost ruleset->rules[i].active.ptr = &ruleset->rules[i].queues[0]; 143e86bddeaSKristof Provost ruleset->rules[i].inactive.ptr = &ruleset->rules[i].queues[1]; 144e86bddeaSKristof Provost } 145e86bddeaSKristof Provost } 146e86bddeaSKristof Provost 147e86bddeaSKristof Provost struct pf_kruleset * 148e86bddeaSKristof Provost pf_find_kruleset(const char *path) 149e86bddeaSKristof Provost { 150e86bddeaSKristof Provost struct pf_kanchor *anchor; 151e86bddeaSKristof Provost 152e86bddeaSKristof Provost while (*path == '/') 153e86bddeaSKristof Provost path++; 154e86bddeaSKristof Provost if (!*path) 155e86bddeaSKristof Provost return (&pf_main_ruleset); 156e86bddeaSKristof Provost anchor = pf_find_kanchor(path); 157e86bddeaSKristof Provost if (anchor == NULL) 158e86bddeaSKristof Provost return (NULL); 159e86bddeaSKristof Provost else 160e86bddeaSKristof Provost return (&anchor->ruleset); 161e86bddeaSKristof Provost } 162e86bddeaSKristof Provost 163e86bddeaSKristof Provost struct pf_kruleset * 164e86bddeaSKristof Provost pf_find_or_create_kruleset(const char *path) 165e86bddeaSKristof Provost { 166e86bddeaSKristof Provost char *p, *q, *r; 167e86bddeaSKristof Provost struct pf_kruleset *ruleset; 168e86bddeaSKristof Provost struct pf_kanchor *anchor = NULL, *dup, *parent = NULL; 169e86bddeaSKristof Provost 170e86bddeaSKristof Provost if (path[0] == 0) 171e86bddeaSKristof Provost return (&pf_main_ruleset); 172e86bddeaSKristof Provost while (*path == '/') 173e86bddeaSKristof Provost path++; 174e86bddeaSKristof Provost ruleset = pf_find_kruleset(path); 175e86bddeaSKristof Provost if (ruleset != NULL) 176e86bddeaSKristof Provost return (ruleset); 177e86bddeaSKristof Provost p = (char *)rs_malloc(MAXPATHLEN); 178e86bddeaSKristof Provost if (p == NULL) 179e86bddeaSKristof Provost return (NULL); 180e86bddeaSKristof Provost strlcpy(p, path, MAXPATHLEN); 181e86bddeaSKristof Provost while (parent == NULL && (q = strrchr(p, '/')) != NULL) { 182e86bddeaSKristof Provost *q = 0; 183e86bddeaSKristof Provost if ((ruleset = pf_find_kruleset(p)) != NULL) { 184e86bddeaSKristof Provost parent = ruleset->anchor; 185e86bddeaSKristof Provost break; 186e86bddeaSKristof Provost } 187e86bddeaSKristof Provost } 188e86bddeaSKristof Provost if (q == NULL) 189e86bddeaSKristof Provost q = p; 190e86bddeaSKristof Provost else 191e86bddeaSKristof Provost q++; 192e86bddeaSKristof Provost strlcpy(p, path, MAXPATHLEN); 193e86bddeaSKristof Provost if (!*q) { 194e86bddeaSKristof Provost rs_free(p); 195e86bddeaSKristof Provost return (NULL); 196e86bddeaSKristof Provost } 197e86bddeaSKristof Provost while ((r = strchr(q, '/')) != NULL || *q) { 198e86bddeaSKristof Provost if (r != NULL) 199e86bddeaSKristof Provost *r = 0; 200e86bddeaSKristof Provost if (!*q || strlen(q) >= PF_ANCHOR_NAME_SIZE || 201e86bddeaSKristof Provost (parent != NULL && strlen(parent->path) >= 202e86bddeaSKristof Provost MAXPATHLEN - PF_ANCHOR_NAME_SIZE - 1)) { 203e86bddeaSKristof Provost rs_free(p); 204e86bddeaSKristof Provost return (NULL); 205e86bddeaSKristof Provost } 206e86bddeaSKristof Provost anchor = (struct pf_kanchor *)rs_malloc(sizeof(*anchor)); 207e86bddeaSKristof Provost if (anchor == NULL) { 208e86bddeaSKristof Provost rs_free(p); 209e86bddeaSKristof Provost return (NULL); 210e86bddeaSKristof Provost } 211e86bddeaSKristof Provost RB_INIT(&anchor->children); 212e86bddeaSKristof Provost strlcpy(anchor->name, q, sizeof(anchor->name)); 213e86bddeaSKristof Provost if (parent != NULL) { 214e86bddeaSKristof Provost strlcpy(anchor->path, parent->path, 215e86bddeaSKristof Provost sizeof(anchor->path)); 216e86bddeaSKristof Provost strlcat(anchor->path, "/", sizeof(anchor->path)); 217e86bddeaSKristof Provost } 218e86bddeaSKristof Provost strlcat(anchor->path, anchor->name, sizeof(anchor->path)); 219e86bddeaSKristof Provost if ((dup = RB_INSERT(pf_kanchor_global, &V_pf_anchors, anchor)) != 220e86bddeaSKristof Provost NULL) { 221e86bddeaSKristof Provost printf("pf_find_or_create_ruleset: RB_INSERT1 " 222e86bddeaSKristof Provost "'%s' '%s' collides with '%s' '%s'\n", 223e86bddeaSKristof Provost anchor->path, anchor->name, dup->path, dup->name); 224e86bddeaSKristof Provost rs_free(anchor); 225e86bddeaSKristof Provost rs_free(p); 226e86bddeaSKristof Provost return (NULL); 227e86bddeaSKristof Provost } 228e86bddeaSKristof Provost if (parent != NULL) { 229e86bddeaSKristof Provost anchor->parent = parent; 230e86bddeaSKristof Provost if ((dup = RB_INSERT(pf_kanchor_node, &parent->children, 231e86bddeaSKristof Provost anchor)) != NULL) { 232e86bddeaSKristof Provost printf("pf_find_or_create_ruleset: " 233e86bddeaSKristof Provost "RB_INSERT2 '%s' '%s' collides with " 234e86bddeaSKristof Provost "'%s' '%s'\n", anchor->path, anchor->name, 235e86bddeaSKristof Provost dup->path, dup->name); 236e86bddeaSKristof Provost RB_REMOVE(pf_kanchor_global, &V_pf_anchors, 237e86bddeaSKristof Provost anchor); 238e86bddeaSKristof Provost rs_free(anchor); 239e86bddeaSKristof Provost rs_free(p); 240e86bddeaSKristof Provost return (NULL); 241e86bddeaSKristof Provost } 242e86bddeaSKristof Provost } 243e86bddeaSKristof Provost pf_init_kruleset(&anchor->ruleset); 244e86bddeaSKristof Provost anchor->ruleset.anchor = anchor; 245e86bddeaSKristof Provost parent = anchor; 246e86bddeaSKristof Provost if (r != NULL) 247e86bddeaSKristof Provost q = r + 1; 248e86bddeaSKristof Provost else 249e86bddeaSKristof Provost *q = 0; 250e86bddeaSKristof Provost } 251e86bddeaSKristof Provost rs_free(p); 252e86bddeaSKristof Provost return (&anchor->ruleset); 253e86bddeaSKristof Provost } 254e86bddeaSKristof Provost 255e86bddeaSKristof Provost void 256e86bddeaSKristof Provost pf_remove_if_empty_kruleset(struct pf_kruleset *ruleset) 257e86bddeaSKristof Provost { 258e86bddeaSKristof Provost struct pf_kanchor *parent; 259e86bddeaSKristof Provost int i; 260e86bddeaSKristof Provost 261e86bddeaSKristof Provost while (ruleset != NULL) { 262e86bddeaSKristof Provost if (ruleset == &pf_main_ruleset || ruleset->anchor == NULL || 263e86bddeaSKristof Provost !RB_EMPTY(&ruleset->anchor->children) || 264e86bddeaSKristof Provost ruleset->anchor->refcnt > 0 || ruleset->tables > 0 || 265e86bddeaSKristof Provost ruleset->topen) 266e86bddeaSKristof Provost return; 267e86bddeaSKristof Provost for (i = 0; i < PF_RULESET_MAX; ++i) 268e86bddeaSKristof Provost if (!TAILQ_EMPTY(ruleset->rules[i].active.ptr) || 269e86bddeaSKristof Provost !TAILQ_EMPTY(ruleset->rules[i].inactive.ptr) || 270e86bddeaSKristof Provost ruleset->rules[i].inactive.open) 271e86bddeaSKristof Provost return; 272e86bddeaSKristof Provost RB_REMOVE(pf_kanchor_global, &V_pf_anchors, ruleset->anchor); 273e86bddeaSKristof Provost if ((parent = ruleset->anchor->parent) != NULL) 274e86bddeaSKristof Provost RB_REMOVE(pf_kanchor_node, &parent->children, 275e86bddeaSKristof Provost ruleset->anchor); 276e86bddeaSKristof Provost rs_free(ruleset->anchor); 277e86bddeaSKristof Provost if (parent == NULL) 278e86bddeaSKristof Provost return; 279e86bddeaSKristof Provost ruleset = &parent->ruleset; 280e86bddeaSKristof Provost } 281e86bddeaSKristof Provost } 282e86bddeaSKristof Provost 283e86bddeaSKristof Provost int 284e86bddeaSKristof Provost pf_kanchor_setup(struct pf_krule *r, const struct pf_kruleset *s, 285e86bddeaSKristof Provost const char *name) 286e86bddeaSKristof Provost { 287e86bddeaSKristof Provost char *p, *path; 288e86bddeaSKristof Provost struct pf_kruleset *ruleset; 289e86bddeaSKristof Provost 290e86bddeaSKristof Provost r->anchor = NULL; 291e86bddeaSKristof Provost r->anchor_relative = 0; 292e86bddeaSKristof Provost r->anchor_wildcard = 0; 293e86bddeaSKristof Provost if (!name[0]) 294e86bddeaSKristof Provost return (0); 295e86bddeaSKristof Provost path = (char *)rs_malloc(MAXPATHLEN); 296e86bddeaSKristof Provost if (path == NULL) 297e86bddeaSKristof Provost return (1); 298e86bddeaSKristof Provost if (name[0] == '/') 299e86bddeaSKristof Provost strlcpy(path, name + 1, MAXPATHLEN); 300e86bddeaSKristof Provost else { 301e86bddeaSKristof Provost /* relative path */ 302e86bddeaSKristof Provost r->anchor_relative = 1; 303e86bddeaSKristof Provost if (s->anchor == NULL || !s->anchor->path[0]) 304e86bddeaSKristof Provost path[0] = 0; 305e86bddeaSKristof Provost else 306e86bddeaSKristof Provost strlcpy(path, s->anchor->path, MAXPATHLEN); 307e86bddeaSKristof Provost while (name[0] == '.' && name[1] == '.' && name[2] == '/') { 308e86bddeaSKristof Provost if (!path[0]) { 30986b653edSKristof Provost DPFPRINTF("pf_anchor_setup: .. beyond root\n"); 310e86bddeaSKristof Provost rs_free(path); 311e86bddeaSKristof Provost return (1); 312e86bddeaSKristof Provost } 313e86bddeaSKristof Provost if ((p = strrchr(path, '/')) != NULL) 314e86bddeaSKristof Provost *p = 0; 315e86bddeaSKristof Provost else 316e86bddeaSKristof Provost path[0] = 0; 317e86bddeaSKristof Provost r->anchor_relative++; 318e86bddeaSKristof Provost name += 3; 319e86bddeaSKristof Provost } 320e86bddeaSKristof Provost if (path[0]) 321e86bddeaSKristof Provost strlcat(path, "/", MAXPATHLEN); 322e86bddeaSKristof Provost strlcat(path, name, MAXPATHLEN); 323e86bddeaSKristof Provost } 324e86bddeaSKristof Provost if ((p = strrchr(path, '/')) != NULL && !strcmp(p, "/*")) { 325e86bddeaSKristof Provost r->anchor_wildcard = 1; 326e86bddeaSKristof Provost *p = 0; 327e86bddeaSKristof Provost } 328e86bddeaSKristof Provost ruleset = pf_find_or_create_kruleset(path); 329e86bddeaSKristof Provost rs_free(path); 330e86bddeaSKristof Provost if (ruleset == NULL || ruleset->anchor == NULL) { 33186b653edSKristof Provost DPFPRINTF("pf_anchor_setup: ruleset\n"); 332e86bddeaSKristof Provost return (1); 333e86bddeaSKristof Provost } 334e86bddeaSKristof Provost r->anchor = ruleset->anchor; 335e86bddeaSKristof Provost r->anchor->refcnt++; 336e86bddeaSKristof Provost return (0); 337e86bddeaSKristof Provost } 338e86bddeaSKristof Provost 339e86bddeaSKristof Provost int 340*d710367dSKristof Provost pf_kanchor_nvcopyout(const struct pf_kruleset *rs, const struct pf_krule *r, 341*d710367dSKristof Provost nvlist_t *nvl) 342*d710367dSKristof Provost { 343*d710367dSKristof Provost char anchor_call[MAXPATHLEN] = { 0 }; 344*d710367dSKristof Provost 345*d710367dSKristof Provost if (r->anchor == NULL) 346*d710367dSKristof Provost goto done; 347*d710367dSKristof Provost if (!r->anchor_relative) { 348*d710367dSKristof Provost strlcpy(anchor_call, "/", sizeof(anchor_call)); 349*d710367dSKristof Provost strlcat(anchor_call, r->anchor->path, 350*d710367dSKristof Provost sizeof(anchor_call)); 351*d710367dSKristof Provost } else { 352*d710367dSKristof Provost char a[MAXPATHLEN]; 353*d710367dSKristof Provost char *p; 354*d710367dSKristof Provost int i; 355*d710367dSKristof Provost if (rs->anchor == NULL) 356*d710367dSKristof Provost a[0] = 0; 357*d710367dSKristof Provost else 358*d710367dSKristof Provost strlcpy(a, rs->anchor->path, MAXPATHLEN); 359*d710367dSKristof Provost for (i = 1; i < r->anchor_relative; ++i) { 360*d710367dSKristof Provost if ((p = strrchr(a, '/')) == NULL) 361*d710367dSKristof Provost p = a; 362*d710367dSKristof Provost *p = 0; 363*d710367dSKristof Provost strlcat(anchor_call, "../", 364*d710367dSKristof Provost sizeof(anchor_call)); 365*d710367dSKristof Provost } 366*d710367dSKristof Provost if (strncmp(a, r->anchor->path, strlen(a))) { 367*d710367dSKristof Provost printf("pf_anchor_copyout: '%s' '%s'\n", a, 368*d710367dSKristof Provost r->anchor->path); 369*d710367dSKristof Provost return (1); 370*d710367dSKristof Provost } 371*d710367dSKristof Provost if (strlen(r->anchor->path) > strlen(a)) 372*d710367dSKristof Provost strlcat(anchor_call, r->anchor->path + (a[0] ? 373*d710367dSKristof Provost strlen(a) + 1 : 0), sizeof(anchor_call)); 374*d710367dSKristof Provost 375*d710367dSKristof Provost } 376*d710367dSKristof Provost if (r->anchor_wildcard) 377*d710367dSKristof Provost strlcat(anchor_call, anchor_call[0] ? "/*" : "*", 378*d710367dSKristof Provost sizeof(anchor_call)); 379*d710367dSKristof Provost 380*d710367dSKristof Provost done: 381*d710367dSKristof Provost nvlist_add_string(nvl, "anchor_call", anchor_call); 382*d710367dSKristof Provost 383*d710367dSKristof Provost return (0); 384*d710367dSKristof Provost } 385*d710367dSKristof Provost 386*d710367dSKristof Provost int 387e86bddeaSKristof Provost pf_kanchor_copyout(const struct pf_kruleset *rs, const struct pf_krule *r, 388e86bddeaSKristof Provost struct pfioc_rule *pr) 389e86bddeaSKristof Provost { 390e86bddeaSKristof Provost pr->anchor_call[0] = 0; 391e86bddeaSKristof Provost if (r->anchor == NULL) 392e86bddeaSKristof Provost return (0); 393e86bddeaSKristof Provost if (!r->anchor_relative) { 394e86bddeaSKristof Provost strlcpy(pr->anchor_call, "/", sizeof(pr->anchor_call)); 395e86bddeaSKristof Provost strlcat(pr->anchor_call, r->anchor->path, 396e86bddeaSKristof Provost sizeof(pr->anchor_call)); 397e86bddeaSKristof Provost } else { 398e86bddeaSKristof Provost char *a, *p; 399e86bddeaSKristof Provost int i; 400e86bddeaSKristof Provost 401e86bddeaSKristof Provost a = (char *)rs_malloc(MAXPATHLEN); 402e86bddeaSKristof Provost if (a == NULL) 403e86bddeaSKristof Provost return (1); 404e86bddeaSKristof Provost if (rs->anchor == NULL) 405e86bddeaSKristof Provost a[0] = 0; 406e86bddeaSKristof Provost else 407e86bddeaSKristof Provost strlcpy(a, rs->anchor->path, MAXPATHLEN); 408e86bddeaSKristof Provost for (i = 1; i < r->anchor_relative; ++i) { 409e86bddeaSKristof Provost if ((p = strrchr(a, '/')) == NULL) 410e86bddeaSKristof Provost p = a; 411e86bddeaSKristof Provost *p = 0; 412e86bddeaSKristof Provost strlcat(pr->anchor_call, "../", 413e86bddeaSKristof Provost sizeof(pr->anchor_call)); 414e86bddeaSKristof Provost } 415e86bddeaSKristof Provost if (strncmp(a, r->anchor->path, strlen(a))) { 416e86bddeaSKristof Provost printf("pf_anchor_copyout: '%s' '%s'\n", a, 417e86bddeaSKristof Provost r->anchor->path); 418e86bddeaSKristof Provost rs_free(a); 419e86bddeaSKristof Provost return (1); 420e86bddeaSKristof Provost } 421e86bddeaSKristof Provost if (strlen(r->anchor->path) > strlen(a)) 422e86bddeaSKristof Provost strlcat(pr->anchor_call, r->anchor->path + (a[0] ? 423e86bddeaSKristof Provost strlen(a) + 1 : 0), sizeof(pr->anchor_call)); 424e86bddeaSKristof Provost rs_free(a); 425e86bddeaSKristof Provost } 426e86bddeaSKristof Provost if (r->anchor_wildcard) 427e86bddeaSKristof Provost strlcat(pr->anchor_call, pr->anchor_call[0] ? "/*" : "*", 428e86bddeaSKristof Provost sizeof(pr->anchor_call)); 429e86bddeaSKristof Provost return (0); 430e86bddeaSKristof Provost } 431e86bddeaSKristof Provost 432e86bddeaSKristof Provost void 433e86bddeaSKristof Provost pf_kanchor_remove(struct pf_krule *r) 434e86bddeaSKristof Provost { 435e86bddeaSKristof Provost if (r->anchor == NULL) 436e86bddeaSKristof Provost return; 437e86bddeaSKristof Provost if (r->anchor->refcnt <= 0) { 438e86bddeaSKristof Provost printf("pf_anchor_remove: broken refcount\n"); 439e86bddeaSKristof Provost r->anchor = NULL; 440e86bddeaSKristof Provost return; 441e86bddeaSKristof Provost } 442e86bddeaSKristof Provost if (!--r->anchor->refcnt) 443e86bddeaSKristof Provost pf_remove_if_empty_kruleset(&r->anchor->ruleset); 444e86bddeaSKristof Provost r->anchor = NULL; 445e86bddeaSKristof Provost } 446