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); 73*e732e742SKristof Provost VNET_DEFINE(struct pf_keth_settings*, pf_keth); 74*e732e742SKristof Provost VNET_DEFINE(struct pf_keth_settings*, pf_keth_inactive); 753b3a8eb9SGleb Smirnoff 76e86bddeaSKristof Provost static __inline int pf_kanchor_compare(struct pf_kanchor *, 77e86bddeaSKristof Provost struct pf_kanchor *); 78e86bddeaSKristof Provost static struct pf_kanchor *pf_find_kanchor(const char *); 79e86bddeaSKristof Provost 80e86bddeaSKristof Provost RB_GENERATE(pf_kanchor_global, pf_kanchor, entry_global, pf_kanchor_compare); 81e86bddeaSKristof Provost RB_GENERATE(pf_kanchor_node, pf_kanchor, entry_node, pf_kanchor_compare); 823b3a8eb9SGleb Smirnoff 83e86bddeaSKristof Provost static __inline int 84e86bddeaSKristof Provost pf_kanchor_compare(struct pf_kanchor *a, struct pf_kanchor *b) 85e86bddeaSKristof Provost { 86e86bddeaSKristof Provost int c = strcmp(a->path, b->path); 87e86bddeaSKristof Provost 88e86bddeaSKristof Provost return (c ? (c < 0 ? -1 : 1) : 0); 89e86bddeaSKristof Provost } 903b3a8eb9SGleb Smirnoff 913b3a8eb9SGleb Smirnoff int 923b3a8eb9SGleb Smirnoff pf_get_ruleset_number(u_int8_t action) 933b3a8eb9SGleb Smirnoff { 943b3a8eb9SGleb Smirnoff switch (action) { 953b3a8eb9SGleb Smirnoff case PF_SCRUB: 963b3a8eb9SGleb Smirnoff case PF_NOSCRUB: 973b3a8eb9SGleb Smirnoff return (PF_RULESET_SCRUB); 983b3a8eb9SGleb Smirnoff break; 993b3a8eb9SGleb Smirnoff case PF_PASS: 100ef950daaSKristof Provost case PF_MATCH: 1013b3a8eb9SGleb Smirnoff case PF_DROP: 1023b3a8eb9SGleb Smirnoff return (PF_RULESET_FILTER); 1033b3a8eb9SGleb Smirnoff break; 1043b3a8eb9SGleb Smirnoff case PF_NAT: 1053b3a8eb9SGleb Smirnoff case PF_NONAT: 1063b3a8eb9SGleb Smirnoff return (PF_RULESET_NAT); 1073b3a8eb9SGleb Smirnoff break; 1083b3a8eb9SGleb Smirnoff case PF_BINAT: 1093b3a8eb9SGleb Smirnoff case PF_NOBINAT: 1103b3a8eb9SGleb Smirnoff return (PF_RULESET_BINAT); 1113b3a8eb9SGleb Smirnoff break; 1123b3a8eb9SGleb Smirnoff case PF_RDR: 1133b3a8eb9SGleb Smirnoff case PF_NORDR: 1143b3a8eb9SGleb Smirnoff return (PF_RULESET_RDR); 1153b3a8eb9SGleb Smirnoff break; 1163b3a8eb9SGleb Smirnoff default: 1173b3a8eb9SGleb Smirnoff return (PF_RULESET_MAX); 1183b3a8eb9SGleb Smirnoff break; 1193b3a8eb9SGleb Smirnoff } 1203b3a8eb9SGleb Smirnoff } 1213b3a8eb9SGleb Smirnoff 122e86bddeaSKristof Provost static struct pf_kanchor * 123e86bddeaSKristof Provost pf_find_kanchor(const char *path) 124e86bddeaSKristof Provost { 125e86bddeaSKristof Provost struct pf_kanchor *key, *found; 126e86bddeaSKristof Provost 127e86bddeaSKristof Provost key = (struct pf_kanchor *)rs_malloc(sizeof(*key)); 128e86bddeaSKristof Provost if (key == NULL) 129e86bddeaSKristof Provost return (NULL); 130e86bddeaSKristof Provost strlcpy(key->path, path, sizeof(key->path)); 131e86bddeaSKristof Provost found = RB_FIND(pf_kanchor_global, &V_pf_anchors, key); 132e86bddeaSKristof Provost rs_free(key); 133e86bddeaSKristof Provost return (found); 134e86bddeaSKristof Provost } 135e86bddeaSKristof Provost 136e86bddeaSKristof Provost void 137e86bddeaSKristof Provost pf_init_kruleset(struct pf_kruleset *ruleset) 138e86bddeaSKristof Provost { 139e86bddeaSKristof Provost int i; 140e86bddeaSKristof Provost 141e86bddeaSKristof Provost memset(ruleset, 0, sizeof(struct pf_kruleset)); 142e86bddeaSKristof Provost for (i = 0; i < PF_RULESET_MAX; i++) { 143e86bddeaSKristof Provost TAILQ_INIT(&ruleset->rules[i].queues[0]); 144e86bddeaSKristof Provost TAILQ_INIT(&ruleset->rules[i].queues[1]); 145e86bddeaSKristof Provost ruleset->rules[i].active.ptr = &ruleset->rules[i].queues[0]; 146e86bddeaSKristof Provost ruleset->rules[i].inactive.ptr = &ruleset->rules[i].queues[1]; 147e86bddeaSKristof Provost } 148e86bddeaSKristof Provost } 149e86bddeaSKristof Provost 150*e732e742SKristof Provost void 151*e732e742SKristof Provost pf_init_keth(struct pf_keth_settings *settings) 152*e732e742SKristof Provost { 153*e732e742SKristof Provost 154*e732e742SKristof Provost TAILQ_INIT(&settings->rules); 155*e732e742SKristof Provost settings->ticket = 0; 156*e732e742SKristof Provost settings->open = 0; 157*e732e742SKristof Provost } 158*e732e742SKristof Provost 159e86bddeaSKristof Provost struct pf_kruleset * 160e86bddeaSKristof Provost pf_find_kruleset(const char *path) 161e86bddeaSKristof Provost { 162e86bddeaSKristof Provost struct pf_kanchor *anchor; 163e86bddeaSKristof Provost 164e86bddeaSKristof Provost while (*path == '/') 165e86bddeaSKristof Provost path++; 166e86bddeaSKristof Provost if (!*path) 167e86bddeaSKristof Provost return (&pf_main_ruleset); 168e86bddeaSKristof Provost anchor = pf_find_kanchor(path); 169e86bddeaSKristof Provost if (anchor == NULL) 170e86bddeaSKristof Provost return (NULL); 171e86bddeaSKristof Provost else 172e86bddeaSKristof Provost return (&anchor->ruleset); 173e86bddeaSKristof Provost } 174e86bddeaSKristof Provost 175e86bddeaSKristof Provost struct pf_kruleset * 176e86bddeaSKristof Provost pf_find_or_create_kruleset(const char *path) 177e86bddeaSKristof Provost { 178e86bddeaSKristof Provost char *p, *q, *r; 179e86bddeaSKristof Provost struct pf_kruleset *ruleset; 180e86bddeaSKristof Provost struct pf_kanchor *anchor = NULL, *dup, *parent = NULL; 181e86bddeaSKristof Provost 182e86bddeaSKristof Provost if (path[0] == 0) 183e86bddeaSKristof Provost return (&pf_main_ruleset); 184e86bddeaSKristof Provost while (*path == '/') 185e86bddeaSKristof Provost path++; 186e86bddeaSKristof Provost ruleset = pf_find_kruleset(path); 187e86bddeaSKristof Provost if (ruleset != NULL) 188e86bddeaSKristof Provost return (ruleset); 189e86bddeaSKristof Provost p = (char *)rs_malloc(MAXPATHLEN); 190e86bddeaSKristof Provost if (p == NULL) 191e86bddeaSKristof Provost return (NULL); 192e86bddeaSKristof Provost strlcpy(p, path, MAXPATHLEN); 193e86bddeaSKristof Provost while (parent == NULL && (q = strrchr(p, '/')) != NULL) { 194e86bddeaSKristof Provost *q = 0; 195e86bddeaSKristof Provost if ((ruleset = pf_find_kruleset(p)) != NULL) { 196e86bddeaSKristof Provost parent = ruleset->anchor; 197e86bddeaSKristof Provost break; 198e86bddeaSKristof Provost } 199e86bddeaSKristof Provost } 200e86bddeaSKristof Provost if (q == NULL) 201e86bddeaSKristof Provost q = p; 202e86bddeaSKristof Provost else 203e86bddeaSKristof Provost q++; 204e86bddeaSKristof Provost strlcpy(p, path, MAXPATHLEN); 205e86bddeaSKristof Provost if (!*q) { 206e86bddeaSKristof Provost rs_free(p); 207e86bddeaSKristof Provost return (NULL); 208e86bddeaSKristof Provost } 209e86bddeaSKristof Provost while ((r = strchr(q, '/')) != NULL || *q) { 210e86bddeaSKristof Provost if (r != NULL) 211e86bddeaSKristof Provost *r = 0; 212e86bddeaSKristof Provost if (!*q || strlen(q) >= PF_ANCHOR_NAME_SIZE || 213e86bddeaSKristof Provost (parent != NULL && strlen(parent->path) >= 214e86bddeaSKristof Provost MAXPATHLEN - PF_ANCHOR_NAME_SIZE - 1)) { 215e86bddeaSKristof Provost rs_free(p); 216e86bddeaSKristof Provost return (NULL); 217e86bddeaSKristof Provost } 218e86bddeaSKristof Provost anchor = (struct pf_kanchor *)rs_malloc(sizeof(*anchor)); 219e86bddeaSKristof Provost if (anchor == NULL) { 220e86bddeaSKristof Provost rs_free(p); 221e86bddeaSKristof Provost return (NULL); 222e86bddeaSKristof Provost } 223e86bddeaSKristof Provost RB_INIT(&anchor->children); 224e86bddeaSKristof Provost strlcpy(anchor->name, q, sizeof(anchor->name)); 225e86bddeaSKristof Provost if (parent != NULL) { 226e86bddeaSKristof Provost strlcpy(anchor->path, parent->path, 227e86bddeaSKristof Provost sizeof(anchor->path)); 228e86bddeaSKristof Provost strlcat(anchor->path, "/", sizeof(anchor->path)); 229e86bddeaSKristof Provost } 230e86bddeaSKristof Provost strlcat(anchor->path, anchor->name, sizeof(anchor->path)); 231e86bddeaSKristof Provost if ((dup = RB_INSERT(pf_kanchor_global, &V_pf_anchors, anchor)) != 232e86bddeaSKristof Provost NULL) { 233e86bddeaSKristof Provost printf("pf_find_or_create_ruleset: RB_INSERT1 " 234e86bddeaSKristof Provost "'%s' '%s' collides with '%s' '%s'\n", 235e86bddeaSKristof Provost anchor->path, anchor->name, dup->path, dup->name); 236e86bddeaSKristof Provost rs_free(anchor); 237e86bddeaSKristof Provost rs_free(p); 238e86bddeaSKristof Provost return (NULL); 239e86bddeaSKristof Provost } 240e86bddeaSKristof Provost if (parent != NULL) { 241e86bddeaSKristof Provost anchor->parent = parent; 242e86bddeaSKristof Provost if ((dup = RB_INSERT(pf_kanchor_node, &parent->children, 243e86bddeaSKristof Provost anchor)) != NULL) { 244e86bddeaSKristof Provost printf("pf_find_or_create_ruleset: " 245e86bddeaSKristof Provost "RB_INSERT2 '%s' '%s' collides with " 246e86bddeaSKristof Provost "'%s' '%s'\n", anchor->path, anchor->name, 247e86bddeaSKristof Provost dup->path, dup->name); 248e86bddeaSKristof Provost RB_REMOVE(pf_kanchor_global, &V_pf_anchors, 249e86bddeaSKristof Provost anchor); 250e86bddeaSKristof Provost rs_free(anchor); 251e86bddeaSKristof Provost rs_free(p); 252e86bddeaSKristof Provost return (NULL); 253e86bddeaSKristof Provost } 254e86bddeaSKristof Provost } 255e86bddeaSKristof Provost pf_init_kruleset(&anchor->ruleset); 256e86bddeaSKristof Provost anchor->ruleset.anchor = anchor; 257e86bddeaSKristof Provost parent = anchor; 258e86bddeaSKristof Provost if (r != NULL) 259e86bddeaSKristof Provost q = r + 1; 260e86bddeaSKristof Provost else 261e86bddeaSKristof Provost *q = 0; 262e86bddeaSKristof Provost } 263e86bddeaSKristof Provost rs_free(p); 264e86bddeaSKristof Provost return (&anchor->ruleset); 265e86bddeaSKristof Provost } 266e86bddeaSKristof Provost 267e86bddeaSKristof Provost void 268e86bddeaSKristof Provost pf_remove_if_empty_kruleset(struct pf_kruleset *ruleset) 269e86bddeaSKristof Provost { 270e86bddeaSKristof Provost struct pf_kanchor *parent; 271e86bddeaSKristof Provost int i; 272e86bddeaSKristof Provost 273e86bddeaSKristof Provost while (ruleset != NULL) { 274e86bddeaSKristof Provost if (ruleset == &pf_main_ruleset || ruleset->anchor == NULL || 275e86bddeaSKristof Provost !RB_EMPTY(&ruleset->anchor->children) || 276e86bddeaSKristof Provost ruleset->anchor->refcnt > 0 || ruleset->tables > 0 || 277e86bddeaSKristof Provost ruleset->topen) 278e86bddeaSKristof Provost return; 279e86bddeaSKristof Provost for (i = 0; i < PF_RULESET_MAX; ++i) 280e86bddeaSKristof Provost if (!TAILQ_EMPTY(ruleset->rules[i].active.ptr) || 281e86bddeaSKristof Provost !TAILQ_EMPTY(ruleset->rules[i].inactive.ptr) || 282e86bddeaSKristof Provost ruleset->rules[i].inactive.open) 283e86bddeaSKristof Provost return; 284e86bddeaSKristof Provost RB_REMOVE(pf_kanchor_global, &V_pf_anchors, ruleset->anchor); 285e86bddeaSKristof Provost if ((parent = ruleset->anchor->parent) != NULL) 286e86bddeaSKristof Provost RB_REMOVE(pf_kanchor_node, &parent->children, 287e86bddeaSKristof Provost ruleset->anchor); 288e86bddeaSKristof Provost rs_free(ruleset->anchor); 289e86bddeaSKristof Provost if (parent == NULL) 290e86bddeaSKristof Provost return; 291e86bddeaSKristof Provost ruleset = &parent->ruleset; 292e86bddeaSKristof Provost } 293e86bddeaSKristof Provost } 294e86bddeaSKristof Provost 295e86bddeaSKristof Provost int 296e86bddeaSKristof Provost pf_kanchor_setup(struct pf_krule *r, const struct pf_kruleset *s, 297e86bddeaSKristof Provost const char *name) 298e86bddeaSKristof Provost { 299e86bddeaSKristof Provost char *p, *path; 300e86bddeaSKristof Provost struct pf_kruleset *ruleset; 301e86bddeaSKristof Provost 302e86bddeaSKristof Provost r->anchor = NULL; 303e86bddeaSKristof Provost r->anchor_relative = 0; 304e86bddeaSKristof Provost r->anchor_wildcard = 0; 305e86bddeaSKristof Provost if (!name[0]) 306e86bddeaSKristof Provost return (0); 307e86bddeaSKristof Provost path = (char *)rs_malloc(MAXPATHLEN); 308e86bddeaSKristof Provost if (path == NULL) 309e86bddeaSKristof Provost return (1); 310e86bddeaSKristof Provost if (name[0] == '/') 311e86bddeaSKristof Provost strlcpy(path, name + 1, MAXPATHLEN); 312e86bddeaSKristof Provost else { 313e86bddeaSKristof Provost /* relative path */ 314e86bddeaSKristof Provost r->anchor_relative = 1; 315e86bddeaSKristof Provost if (s->anchor == NULL || !s->anchor->path[0]) 316e86bddeaSKristof Provost path[0] = 0; 317e86bddeaSKristof Provost else 318e86bddeaSKristof Provost strlcpy(path, s->anchor->path, MAXPATHLEN); 319e86bddeaSKristof Provost while (name[0] == '.' && name[1] == '.' && name[2] == '/') { 320e86bddeaSKristof Provost if (!path[0]) { 32186b653edSKristof Provost DPFPRINTF("pf_anchor_setup: .. beyond root\n"); 322e86bddeaSKristof Provost rs_free(path); 323e86bddeaSKristof Provost return (1); 324e86bddeaSKristof Provost } 325e86bddeaSKristof Provost if ((p = strrchr(path, '/')) != NULL) 326e86bddeaSKristof Provost *p = 0; 327e86bddeaSKristof Provost else 328e86bddeaSKristof Provost path[0] = 0; 329e86bddeaSKristof Provost r->anchor_relative++; 330e86bddeaSKristof Provost name += 3; 331e86bddeaSKristof Provost } 332e86bddeaSKristof Provost if (path[0]) 333e86bddeaSKristof Provost strlcat(path, "/", MAXPATHLEN); 334e86bddeaSKristof Provost strlcat(path, name, MAXPATHLEN); 335e86bddeaSKristof Provost } 336e86bddeaSKristof Provost if ((p = strrchr(path, '/')) != NULL && !strcmp(p, "/*")) { 337e86bddeaSKristof Provost r->anchor_wildcard = 1; 338e86bddeaSKristof Provost *p = 0; 339e86bddeaSKristof Provost } 340e86bddeaSKristof Provost ruleset = pf_find_or_create_kruleset(path); 341e86bddeaSKristof Provost rs_free(path); 342e86bddeaSKristof Provost if (ruleset == NULL || ruleset->anchor == NULL) { 34386b653edSKristof Provost DPFPRINTF("pf_anchor_setup: ruleset\n"); 344e86bddeaSKristof Provost return (1); 345e86bddeaSKristof Provost } 346e86bddeaSKristof Provost r->anchor = ruleset->anchor; 347e86bddeaSKristof Provost r->anchor->refcnt++; 348e86bddeaSKristof Provost return (0); 349e86bddeaSKristof Provost } 350e86bddeaSKristof Provost 351e86bddeaSKristof Provost int 352d710367dSKristof Provost pf_kanchor_nvcopyout(const struct pf_kruleset *rs, const struct pf_krule *r, 353d710367dSKristof Provost nvlist_t *nvl) 354d710367dSKristof Provost { 355d710367dSKristof Provost char anchor_call[MAXPATHLEN] = { 0 }; 356d710367dSKristof Provost 357d710367dSKristof Provost if (r->anchor == NULL) 358d710367dSKristof Provost goto done; 359d710367dSKristof Provost if (!r->anchor_relative) { 360d710367dSKristof Provost strlcpy(anchor_call, "/", sizeof(anchor_call)); 361d710367dSKristof Provost strlcat(anchor_call, r->anchor->path, 362d710367dSKristof Provost sizeof(anchor_call)); 363d710367dSKristof Provost } else { 364d710367dSKristof Provost char a[MAXPATHLEN]; 365d710367dSKristof Provost char *p; 366d710367dSKristof Provost int i; 367d710367dSKristof Provost if (rs->anchor == NULL) 368d710367dSKristof Provost a[0] = 0; 369d710367dSKristof Provost else 370d710367dSKristof Provost strlcpy(a, rs->anchor->path, MAXPATHLEN); 371d710367dSKristof Provost for (i = 1; i < r->anchor_relative; ++i) { 372d710367dSKristof Provost if ((p = strrchr(a, '/')) == NULL) 373d710367dSKristof Provost p = a; 374d710367dSKristof Provost *p = 0; 375d710367dSKristof Provost strlcat(anchor_call, "../", 376d710367dSKristof Provost sizeof(anchor_call)); 377d710367dSKristof Provost } 378d710367dSKristof Provost if (strncmp(a, r->anchor->path, strlen(a))) { 379d710367dSKristof Provost printf("pf_anchor_copyout: '%s' '%s'\n", a, 380d710367dSKristof Provost r->anchor->path); 381d710367dSKristof Provost return (1); 382d710367dSKristof Provost } 383d710367dSKristof Provost if (strlen(r->anchor->path) > strlen(a)) 384d710367dSKristof Provost strlcat(anchor_call, r->anchor->path + (a[0] ? 385d710367dSKristof Provost strlen(a) + 1 : 0), sizeof(anchor_call)); 386d710367dSKristof Provost 387d710367dSKristof Provost } 388d710367dSKristof Provost if (r->anchor_wildcard) 389d710367dSKristof Provost strlcat(anchor_call, anchor_call[0] ? "/*" : "*", 390d710367dSKristof Provost sizeof(anchor_call)); 391d710367dSKristof Provost 392d710367dSKristof Provost done: 393d710367dSKristof Provost nvlist_add_string(nvl, "anchor_call", anchor_call); 394d710367dSKristof Provost 395d710367dSKristof Provost return (0); 396d710367dSKristof Provost } 397d710367dSKristof Provost 398d710367dSKristof Provost int 399e86bddeaSKristof Provost pf_kanchor_copyout(const struct pf_kruleset *rs, const struct pf_krule *r, 400e86bddeaSKristof Provost struct pfioc_rule *pr) 401e86bddeaSKristof Provost { 402e86bddeaSKristof Provost pr->anchor_call[0] = 0; 403e86bddeaSKristof Provost if (r->anchor == NULL) 404e86bddeaSKristof Provost return (0); 405e86bddeaSKristof Provost if (!r->anchor_relative) { 406e86bddeaSKristof Provost strlcpy(pr->anchor_call, "/", sizeof(pr->anchor_call)); 407e86bddeaSKristof Provost strlcat(pr->anchor_call, r->anchor->path, 408e86bddeaSKristof Provost sizeof(pr->anchor_call)); 409e86bddeaSKristof Provost } else { 410e86bddeaSKristof Provost char *a, *p; 411e86bddeaSKristof Provost int i; 412e86bddeaSKristof Provost 413e86bddeaSKristof Provost a = (char *)rs_malloc(MAXPATHLEN); 414e86bddeaSKristof Provost if (a == NULL) 415e86bddeaSKristof Provost return (1); 416e86bddeaSKristof Provost if (rs->anchor == NULL) 417e86bddeaSKristof Provost a[0] = 0; 418e86bddeaSKristof Provost else 419e86bddeaSKristof Provost strlcpy(a, rs->anchor->path, MAXPATHLEN); 420e86bddeaSKristof Provost for (i = 1; i < r->anchor_relative; ++i) { 421e86bddeaSKristof Provost if ((p = strrchr(a, '/')) == NULL) 422e86bddeaSKristof Provost p = a; 423e86bddeaSKristof Provost *p = 0; 424e86bddeaSKristof Provost strlcat(pr->anchor_call, "../", 425e86bddeaSKristof Provost sizeof(pr->anchor_call)); 426e86bddeaSKristof Provost } 427e86bddeaSKristof Provost if (strncmp(a, r->anchor->path, strlen(a))) { 428e86bddeaSKristof Provost printf("pf_anchor_copyout: '%s' '%s'\n", a, 429e86bddeaSKristof Provost r->anchor->path); 430e86bddeaSKristof Provost rs_free(a); 431e86bddeaSKristof Provost return (1); 432e86bddeaSKristof Provost } 433e86bddeaSKristof Provost if (strlen(r->anchor->path) > strlen(a)) 434e86bddeaSKristof Provost strlcat(pr->anchor_call, r->anchor->path + (a[0] ? 435e86bddeaSKristof Provost strlen(a) + 1 : 0), sizeof(pr->anchor_call)); 436e86bddeaSKristof Provost rs_free(a); 437e86bddeaSKristof Provost } 438e86bddeaSKristof Provost if (r->anchor_wildcard) 439e86bddeaSKristof Provost strlcat(pr->anchor_call, pr->anchor_call[0] ? "/*" : "*", 440e86bddeaSKristof Provost sizeof(pr->anchor_call)); 441e86bddeaSKristof Provost return (0); 442e86bddeaSKristof Provost } 443e86bddeaSKristof Provost 444e86bddeaSKristof Provost void 445e86bddeaSKristof Provost pf_kanchor_remove(struct pf_krule *r) 446e86bddeaSKristof Provost { 447e86bddeaSKristof Provost if (r->anchor == NULL) 448e86bddeaSKristof Provost return; 449e86bddeaSKristof Provost if (r->anchor->refcnt <= 0) { 450e86bddeaSKristof Provost printf("pf_anchor_remove: broken refcount\n"); 451e86bddeaSKristof Provost r->anchor = NULL; 452e86bddeaSKristof Provost return; 453e86bddeaSKristof Provost } 454e86bddeaSKristof Provost if (!--r->anchor->refcnt) 455e86bddeaSKristof Provost pf_remove_if_empty_kruleset(&r->anchor->ruleset); 456e86bddeaSKristof Provost r->anchor = NULL; 457e86bddeaSKristof Provost } 458