The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netpfil/pf/pf_ruleset.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause
    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  *      $OpenBSD: pf_ruleset.c,v 1.2 2008/12/18 15:31:37 dhill Exp $
   37  */
   38 
   39 #include <sys/cdefs.h>
   40 __FBSDID("$FreeBSD$");
   41 
   42 #include <sys/param.h>
   43 #include <sys/socket.h>
   44 #include <sys/systm.h>
   45 #include <sys/refcount.h>
   46 #include <sys/mbuf.h>
   47 
   48 #include <netinet/in.h>
   49 #include <netinet/in_systm.h>
   50 #include <netinet/ip.h>
   51 #include <netinet/tcp.h>
   52 
   53 #include <net/if.h>
   54 #include <net/vnet.h>
   55 #include <net/pfvar.h>
   56 
   57 #ifdef INET6
   58 #include <netinet/ip6.h>
   59 #endif /* INET6 */
   60 
   61 #ifndef _KERNEL
   62 #error "Kernel only file. Please use sbin/pfctl/pf_ruleset.c instead."
   63 #endif
   64 
   65 #define DPFPRINTF(format, x...)                         \
   66         if (V_pf_status.debug >= PF_DEBUG_NOISY)        \
   67                 printf(format , ##x)
   68 #define rs_malloc(x)            malloc(x, M_TEMP, M_NOWAIT|M_ZERO)
   69 #define rs_free(x)              free(x, M_TEMP)
   70 
   71 VNET_DEFINE(struct pf_kanchor_global,   pf_anchors);
   72 VNET_DEFINE(struct pf_kanchor,          pf_main_anchor);
   73 VNET_DEFINE(struct pf_keth_ruleset*,    pf_keth);
   74 VNET_DEFINE(struct pf_keth_anchor,      pf_main_keth_anchor);
   75 VNET_DEFINE(struct pf_keth_anchor_global,        pf_keth_anchors);
   76 
   77 static __inline int             pf_kanchor_compare(struct pf_kanchor *,
   78                                     struct pf_kanchor *);
   79 static __inline int             pf_keth_anchor_compare(struct pf_keth_anchor *,
   80                                     struct pf_keth_anchor *);
   81 static struct pf_kanchor        *pf_find_kanchor(const char *);
   82 
   83 RB_GENERATE(pf_kanchor_global, pf_kanchor, entry_global, pf_kanchor_compare);
   84 RB_GENERATE(pf_kanchor_node, pf_kanchor, entry_node, pf_kanchor_compare);
   85 RB_GENERATE(pf_keth_anchor_global, pf_keth_anchor, entry_global,
   86     pf_keth_anchor_compare);
   87 RB_GENERATE(pf_keth_anchor_node, pf_keth_anchor, entry_node,
   88     pf_keth_anchor_compare);
   89 
   90 static __inline int
   91 pf_kanchor_compare(struct pf_kanchor *a, struct pf_kanchor *b)
   92 {
   93         int c = strcmp(a->path, b->path);
   94 
   95         return (c ? (c < 0 ? -1 : 1) : 0);
   96 }
   97 
   98 static __inline int
   99 pf_keth_anchor_compare(struct pf_keth_anchor *a, struct pf_keth_anchor *b)
  100 {
  101         int c = strcmp(a->path, b->path);
  102 
  103         return (c ? (c < 0 ? -1 : 1) : 0);
  104 }
  105 
  106 int
  107 pf_get_ruleset_number(u_int8_t action)
  108 {
  109         switch (action) {
  110         case PF_SCRUB:
  111         case PF_NOSCRUB:
  112                 return (PF_RULESET_SCRUB);
  113                 break;
  114         case PF_PASS:
  115         case PF_MATCH:
  116         case PF_DROP:
  117                 return (PF_RULESET_FILTER);
  118                 break;
  119         case PF_NAT:
  120         case PF_NONAT:
  121                 return (PF_RULESET_NAT);
  122                 break;
  123         case PF_BINAT:
  124         case PF_NOBINAT:
  125                 return (PF_RULESET_BINAT);
  126                 break;
  127         case PF_RDR:
  128         case PF_NORDR:
  129                 return (PF_RULESET_RDR);
  130                 break;
  131         default:
  132                 return (PF_RULESET_MAX);
  133                 break;
  134         }
  135 }
  136 
  137 static struct pf_kanchor *
  138 pf_find_kanchor(const char *path)
  139 {
  140         struct pf_kanchor       *key, *found;
  141 
  142         key = (struct pf_kanchor *)rs_malloc(sizeof(*key));
  143         if (key == NULL)
  144                 return (NULL);
  145         strlcpy(key->path, path, sizeof(key->path));
  146         found = RB_FIND(pf_kanchor_global, &V_pf_anchors, key);
  147         rs_free(key);
  148         return (found);
  149 }
  150 
  151 void
  152 pf_init_kruleset(struct pf_kruleset *ruleset)
  153 {
  154         int     i;
  155 
  156         memset(ruleset, 0, sizeof(struct pf_kruleset));
  157         for (i = 0; i < PF_RULESET_MAX; i++) {
  158                 TAILQ_INIT(&ruleset->rules[i].queues[0]);
  159                 TAILQ_INIT(&ruleset->rules[i].queues[1]);
  160                 ruleset->rules[i].active.ptr = &ruleset->rules[i].queues[0];
  161                 ruleset->rules[i].inactive.ptr = &ruleset->rules[i].queues[1];
  162         }
  163 }
  164 
  165 void
  166 pf_init_keth(struct pf_keth_ruleset *rs)
  167 {
  168 
  169         bzero(rs, sizeof(*rs));
  170         TAILQ_INIT(&rs->rules[0]);
  171         TAILQ_INIT(&rs->rules[1]);
  172         rs->active.rules = &rs->rules[0];
  173         rs->active.open = 0;
  174         rs->inactive.rules = &rs->rules[1];
  175         rs->inactive.open = 0;
  176 
  177         rs->vnet = curvnet;
  178 }
  179 
  180 struct pf_kruleset *
  181 pf_find_kruleset(const char *path)
  182 {
  183         struct pf_kanchor       *anchor;
  184 
  185         while (*path == '/')
  186                 path++;
  187         if (!*path)
  188                 return (&pf_main_ruleset);
  189         anchor = pf_find_kanchor(path);
  190         if (anchor == NULL)
  191                 return (NULL);
  192         else
  193                 return (&anchor->ruleset);
  194 }
  195 
  196 struct pf_kruleset *
  197 pf_find_or_create_kruleset(const char *path)
  198 {
  199         char                    *p, *q, *r;
  200         struct pf_kruleset      *ruleset;
  201         struct pf_kanchor       *anchor = NULL, *dup, *parent = NULL;
  202 
  203         if (path[0] == 0)
  204                 return (&pf_main_ruleset);
  205         while (*path == '/')
  206                 path++;
  207         ruleset = pf_find_kruleset(path);
  208         if (ruleset != NULL)
  209                 return (ruleset);
  210         p = (char *)rs_malloc(MAXPATHLEN);
  211         if (p == NULL)
  212                 return (NULL);
  213         strlcpy(p, path, MAXPATHLEN);
  214         while (parent == NULL && (q = strrchr(p, '/')) != NULL) {
  215                 *q = 0;
  216                 if ((ruleset = pf_find_kruleset(p)) != NULL) {
  217                         parent = ruleset->anchor;
  218                         break;
  219                 }
  220         }
  221         if (q == NULL)
  222                 q = p;
  223         else
  224                 q++;
  225         strlcpy(p, path, MAXPATHLEN);
  226         if (!*q) {
  227                 rs_free(p);
  228                 return (NULL);
  229         }
  230         while ((r = strchr(q, '/')) != NULL || *q) {
  231                 if (r != NULL)
  232                         *r = 0;
  233                 if (!*q || strlen(q) >= PF_ANCHOR_NAME_SIZE ||
  234                     (parent != NULL && strlen(parent->path) >=
  235                     MAXPATHLEN - PF_ANCHOR_NAME_SIZE - 1)) {
  236                         rs_free(p);
  237                         return (NULL);
  238                 }
  239                 anchor = (struct pf_kanchor *)rs_malloc(sizeof(*anchor));
  240                 if (anchor == NULL) {
  241                         rs_free(p);
  242                         return (NULL);
  243                 }
  244                 RB_INIT(&anchor->children);
  245                 strlcpy(anchor->name, q, sizeof(anchor->name));
  246                 if (parent != NULL) {
  247                         strlcpy(anchor->path, parent->path,
  248                             sizeof(anchor->path));
  249                         strlcat(anchor->path, "/", sizeof(anchor->path));
  250                 }
  251                 strlcat(anchor->path, anchor->name, sizeof(anchor->path));
  252                 if ((dup = RB_INSERT(pf_kanchor_global, &V_pf_anchors, anchor)) !=
  253                     NULL) {
  254                         printf("pf_find_or_create_ruleset: RB_INSERT1 "
  255                             "'%s' '%s' collides with '%s' '%s'\n",
  256                             anchor->path, anchor->name, dup->path, dup->name);
  257                         rs_free(anchor);
  258                         rs_free(p);
  259                         return (NULL);
  260                 }
  261                 if (parent != NULL) {
  262                         anchor->parent = parent;
  263                         if ((dup = RB_INSERT(pf_kanchor_node, &parent->children,
  264                             anchor)) != NULL) {
  265                                 printf("pf_find_or_create_ruleset: "
  266                                     "RB_INSERT2 '%s' '%s' collides with "
  267                                     "'%s' '%s'\n", anchor->path, anchor->name,
  268                                     dup->path, dup->name);
  269                                 RB_REMOVE(pf_kanchor_global, &V_pf_anchors,
  270                                     anchor);
  271                                 rs_free(anchor);
  272                                 rs_free(p);
  273                                 return (NULL);
  274                         }
  275                 }
  276                 pf_init_kruleset(&anchor->ruleset);
  277                 anchor->ruleset.anchor = anchor;
  278                 parent = anchor;
  279                 if (r != NULL)
  280                         q = r + 1;
  281                 else
  282                         *q = 0;
  283         }
  284         rs_free(p);
  285         return (&anchor->ruleset);
  286 }
  287 
  288 void
  289 pf_remove_if_empty_kruleset(struct pf_kruleset *ruleset)
  290 {
  291         struct pf_kanchor       *parent;
  292         int                      i;
  293 
  294         while (ruleset != NULL) {
  295                 if (ruleset == &pf_main_ruleset || ruleset->anchor == NULL ||
  296                     !RB_EMPTY(&ruleset->anchor->children) ||
  297                     ruleset->anchor->refcnt > 0 || ruleset->tables > 0 ||
  298                     ruleset->topen)
  299                         return;
  300                 for (i = 0; i < PF_RULESET_MAX; ++i)
  301                         if (!TAILQ_EMPTY(ruleset->rules[i].active.ptr) ||
  302                             !TAILQ_EMPTY(ruleset->rules[i].inactive.ptr) ||
  303                             ruleset->rules[i].inactive.open)
  304                                 return;
  305                 RB_REMOVE(pf_kanchor_global, &V_pf_anchors, ruleset->anchor);
  306                 if ((parent = ruleset->anchor->parent) != NULL)
  307                         RB_REMOVE(pf_kanchor_node, &parent->children,
  308                             ruleset->anchor);
  309                 rs_free(ruleset->anchor);
  310                 if (parent == NULL)
  311                         return;
  312                 ruleset = &parent->ruleset;
  313         }
  314 }
  315 
  316 int
  317 pf_kanchor_setup(struct pf_krule *r, const struct pf_kruleset *s,
  318     const char *name)
  319 {
  320         char                    *p, *path;
  321         struct pf_kruleset      *ruleset;
  322 
  323         r->anchor = NULL;
  324         r->anchor_relative = 0;
  325         r->anchor_wildcard = 0;
  326         if (!name[0])
  327                 return (0);
  328         path = (char *)rs_malloc(MAXPATHLEN);
  329         if (path == NULL)
  330                 return (1);
  331         if (name[0] == '/')
  332                 strlcpy(path, name + 1, MAXPATHLEN);
  333         else {
  334                 /* relative path */
  335                 r->anchor_relative = 1;
  336                 if (s->anchor == NULL || !s->anchor->path[0])
  337                         path[0] = 0;
  338                 else
  339                         strlcpy(path, s->anchor->path, MAXPATHLEN);
  340                 while (name[0] == '.' && name[1] == '.' && name[2] == '/') {
  341                         if (!path[0]) {
  342                                 DPFPRINTF("pf_anchor_setup: .. beyond root\n");
  343                                 rs_free(path);
  344                                 return (1);
  345                         }
  346                         if ((p = strrchr(path, '/')) != NULL)
  347                                 *p = 0;
  348                         else
  349                                 path[0] = 0;
  350                         r->anchor_relative++;
  351                         name += 3;
  352                 }
  353                 if (path[0])
  354                         strlcat(path, "/", MAXPATHLEN);
  355                 strlcat(path, name, MAXPATHLEN);
  356         }
  357         if ((p = strrchr(path, '/')) != NULL && !strcmp(p, "/*")) {
  358                 r->anchor_wildcard = 1;
  359                 *p = 0;
  360         }
  361         ruleset = pf_find_or_create_kruleset(path);
  362         rs_free(path);
  363         if (ruleset == NULL || ruleset->anchor == NULL) {
  364                 DPFPRINTF("pf_anchor_setup: ruleset\n");
  365                 return (1);
  366         }
  367         r->anchor = ruleset->anchor;
  368         r->anchor->refcnt++;
  369         return (0);
  370 }
  371 
  372 int
  373 pf_kanchor_nvcopyout(const struct pf_kruleset *rs, const struct pf_krule *r,
  374     nvlist_t *nvl)
  375 {
  376         char anchor_call[MAXPATHLEN] = { 0 };
  377 
  378         if (r->anchor == NULL)
  379                 goto done;
  380         if (!r->anchor_relative) {
  381                 strlcpy(anchor_call, "/", sizeof(anchor_call));
  382                 strlcat(anchor_call, r->anchor->path,
  383                     sizeof(anchor_call));
  384         } else {
  385                 char     a[MAXPATHLEN];
  386                 char    *p;
  387                 int      i;
  388                 if (rs->anchor == NULL)
  389                         a[0] = 0;
  390                 else
  391                         strlcpy(a, rs->anchor->path, MAXPATHLEN);
  392                 for (i = 1; i < r->anchor_relative; ++i) {
  393                         if ((p = strrchr(a, '/')) == NULL)
  394                                 p = a;
  395                         *p = 0;
  396                         strlcat(anchor_call, "../",
  397                             sizeof(anchor_call));
  398                 }
  399                 if (strncmp(a, r->anchor->path, strlen(a))) {
  400                         printf("pf_anchor_copyout: '%s' '%s'\n", a,
  401                             r->anchor->path);
  402                         return (1);
  403                 }
  404                 if (strlen(r->anchor->path) > strlen(a))
  405                         strlcat(anchor_call, r->anchor->path + (a[0] ?
  406                             strlen(a) + 1 : 0), sizeof(anchor_call));
  407 
  408         }
  409         if (r->anchor_wildcard)
  410                 strlcat(anchor_call, anchor_call[0] ? "/*" : "*",
  411                     sizeof(anchor_call));
  412 
  413 done:
  414         nvlist_add_string(nvl, "anchor_call", anchor_call);
  415 
  416         return (0);
  417 }
  418 
  419 int
  420 pf_keth_anchor_nvcopyout(const struct pf_keth_ruleset *rs,
  421     const struct pf_keth_rule *r, nvlist_t *nvl)
  422 {
  423         char anchor_call[MAXPATHLEN] = { 0 };
  424 
  425         if (r->anchor == NULL)
  426                 goto done;
  427         if (!r->anchor_relative) {
  428                 strlcpy(anchor_call, "/", sizeof(anchor_call));
  429                 strlcat(anchor_call, r->anchor->path,
  430                     sizeof(anchor_call));
  431         } else {
  432                 char     a[MAXPATHLEN];
  433                 char    *p;
  434                 int      i;
  435                 if (rs->anchor == NULL)
  436                         a[0] = 0;
  437                 else
  438                         strlcpy(a, rs->anchor->path, MAXPATHLEN);
  439                 for (i = 1; i < r->anchor_relative; ++i) {
  440                         if ((p = strrchr(a, '/')) == NULL)
  441                                 p = a;
  442                         *p = 0;
  443                         strlcat(anchor_call, "../",
  444                             sizeof(anchor_call));
  445                 }
  446                 if (strncmp(a, r->anchor->path, strlen(a))) {
  447                         printf("%s(): '%s' '%s'\n", __func__, a,
  448                             r->anchor->path);
  449                         return (1);
  450                 }
  451                 if (strlen(r->anchor->path) > strlen(a))
  452                         strlcat(anchor_call, r->anchor->path + (a[0] ?
  453                             strlen(a) + 1 : 0), sizeof(anchor_call));
  454 
  455         }
  456         if (r->anchor_wildcard)
  457                 strlcat(anchor_call, anchor_call[0] ? "/*" : "*",
  458                     sizeof(anchor_call));
  459 
  460 done:
  461         nvlist_add_string(nvl, "anchor_call", anchor_call);
  462 
  463         return (0);
  464 }
  465 
  466 int
  467 pf_kanchor_copyout(const struct pf_kruleset *rs, const struct pf_krule *r,
  468     struct pfioc_rule *pr)
  469 {
  470         pr->anchor_call[0] = 0;
  471         if (r->anchor == NULL)
  472                 return (0);
  473         if (!r->anchor_relative) {
  474                 strlcpy(pr->anchor_call, "/", sizeof(pr->anchor_call));
  475                 strlcat(pr->anchor_call, r->anchor->path,
  476                     sizeof(pr->anchor_call));
  477         } else {
  478                 char    *a, *p;
  479                 int      i;
  480 
  481                 a = (char *)rs_malloc(MAXPATHLEN);
  482                 if (a == NULL)
  483                         return (1);
  484                 if (rs->anchor == NULL)
  485                         a[0] = 0;
  486                 else
  487                         strlcpy(a, rs->anchor->path, MAXPATHLEN);
  488                 for (i = 1; i < r->anchor_relative; ++i) {
  489                         if ((p = strrchr(a, '/')) == NULL)
  490                                 p = a;
  491                         *p = 0;
  492                         strlcat(pr->anchor_call, "../",
  493                             sizeof(pr->anchor_call));
  494                 }
  495                 if (strncmp(a, r->anchor->path, strlen(a))) {
  496                         printf("pf_anchor_copyout: '%s' '%s'\n", a,
  497                             r->anchor->path);
  498                         rs_free(a);
  499                         return (1);
  500                 }
  501                 if (strlen(r->anchor->path) > strlen(a))
  502                         strlcat(pr->anchor_call, r->anchor->path + (a[0] ?
  503                             strlen(a) + 1 : 0), sizeof(pr->anchor_call));
  504                 rs_free(a);
  505         }
  506         if (r->anchor_wildcard)
  507                 strlcat(pr->anchor_call, pr->anchor_call[0] ? "/*" : "*",
  508                     sizeof(pr->anchor_call));
  509         return (0);
  510 }
  511 
  512 void
  513 pf_kanchor_remove(struct pf_krule *r)
  514 {
  515         if (r->anchor == NULL)
  516                 return;
  517         if (r->anchor->refcnt <= 0) {
  518                 printf("pf_anchor_remove: broken refcount\n");
  519                 r->anchor = NULL;
  520                 return;
  521         }
  522         if (!--r->anchor->refcnt)
  523                 pf_remove_if_empty_kruleset(&r->anchor->ruleset);
  524         r->anchor = NULL;
  525 }
  526 
  527 struct pf_keth_ruleset *
  528 pf_find_keth_ruleset(const char *path)
  529 {
  530         struct pf_keth_anchor   *anchor;
  531 
  532         while (*path == '/')
  533                 path++;
  534         if (!*path)
  535                 return (V_pf_keth);
  536         anchor = pf_find_keth_anchor(path);
  537         if (anchor == NULL)
  538                 return (NULL);
  539         else
  540                 return (&anchor->ruleset);
  541 }
  542 
  543 static struct pf_keth_anchor *
  544 _pf_find_keth_anchor(struct pf_keth_ruleset *rs, const char *path)
  545 {
  546         struct pf_keth_anchor   *key, *found;
  547 
  548         key = (struct pf_keth_anchor *)rs_malloc(sizeof(*key));
  549         if (key == NULL)
  550                 return (NULL);
  551         strlcpy(key->path, path, sizeof(key->path));
  552         found = RB_FIND(pf_keth_anchor_global, &V_pf_keth_anchors, key);
  553         rs_free(key);
  554         return (found);
  555 }
  556 
  557 struct pf_keth_anchor *
  558 pf_find_keth_anchor(const char *path)
  559 {
  560         return (_pf_find_keth_anchor(V_pf_keth, path));
  561 }
  562 
  563 struct pf_keth_ruleset *
  564 pf_find_or_create_keth_ruleset(const char *path)
  565 {
  566         char                    *p, *q, *r;
  567         struct pf_keth_anchor   *anchor = NULL, *dup = NULL, *parent = NULL;
  568         struct pf_keth_ruleset  *ruleset;
  569 
  570         if (path[0] == 0)
  571                 return (V_pf_keth);
  572         while (*path == '/')
  573                 path++;
  574         ruleset = pf_find_keth_ruleset(path);
  575         if (ruleset != NULL)
  576                 return (ruleset);
  577         p = (char *)rs_malloc(MAXPATHLEN);
  578         if (p == NULL)
  579                 return (NULL);
  580         strlcpy(p, path, MAXPATHLEN);
  581         while (parent == NULL && (q = strrchr(p, '/')) != NULL) {
  582                 *q = 0;
  583                 if ((ruleset = pf_find_keth_ruleset(p)) != NULL) {
  584                         parent = ruleset->anchor;
  585                         break;
  586                 }
  587         }
  588         if (q == NULL)
  589                 q = p;
  590         else
  591                 q++;
  592         strlcpy(p, path, MAXPATHLEN);
  593         if (!*q) {
  594                 rs_free(p);
  595                 return (NULL);
  596         }
  597         while ((r = strchr(q, '/')) != NULL || *q) {
  598                 if (r != NULL)
  599                         *r = 0;
  600                 if (!*q || strlen(q) >= PF_ANCHOR_NAME_SIZE ||
  601                     (parent != NULL && strlen(parent->path) >=
  602                     MAXPATHLEN - PF_ANCHOR_NAME_SIZE - 1)) {
  603                         rs_free(p);
  604                         return (NULL);
  605                 }
  606                 anchor = (struct pf_keth_anchor *)rs_malloc(sizeof(*anchor));
  607                 if (anchor == NULL) {
  608                         rs_free(p);
  609                         return (NULL);
  610                 }
  611                 RB_INIT(&anchor->children);
  612                 strlcpy(anchor->name, q, sizeof(anchor->name));
  613                 if (parent != NULL) {
  614                         strlcpy(anchor->path, parent->path,
  615                             sizeof(anchor->path));
  616                         strlcat(anchor->path, "/", sizeof(anchor->path));
  617                 }
  618                 strlcat(anchor->path, anchor->name, sizeof(anchor->path));
  619                 if ((dup = RB_INSERT(pf_keth_anchor_global, &V_pf_keth_anchors, anchor)) !=
  620                     NULL) {
  621                         printf("%s: RB_INSERT1 "
  622                             "'%s' '%s' collides with '%s' '%s'\n", __func__,
  623                             anchor->path, anchor->name, dup->path, dup->name);
  624                         rs_free(anchor);
  625                         rs_free(p);
  626                         return (NULL);
  627                 }
  628                 if (parent != NULL) {
  629                         anchor->parent = parent;
  630                         if ((dup = RB_INSERT(pf_keth_anchor_node, &parent->children,
  631                             anchor)) != NULL) {
  632                                 printf("%s: "
  633                                     "RB_INSERT2 '%s' '%s' collides with "
  634                                     "'%s' '%s'\n", __func__, anchor->path,
  635                                     anchor->name, dup->path, dup->name);
  636                                 RB_REMOVE(pf_keth_anchor_global, &V_pf_keth_anchors,
  637                                     anchor);
  638                                 rs_free(anchor);
  639                                 rs_free(p);
  640                                 return (NULL);
  641                         }
  642                 }
  643                 pf_init_keth(&anchor->ruleset);
  644                 anchor->ruleset.anchor = anchor;
  645                 parent = anchor;
  646                 if (r != NULL)
  647                         q = r + 1;
  648                 else
  649                         *q = 0;
  650         }
  651         rs_free(p);
  652         return (&anchor->ruleset);
  653 }
  654 
  655 int
  656 pf_keth_anchor_setup(struct pf_keth_rule *r, const struct pf_keth_ruleset *s,
  657     const char *name)
  658 {
  659         char                    *p, *path;
  660         struct pf_keth_ruleset  *ruleset;
  661 
  662         r->anchor = NULL;
  663         r->anchor_relative = 0;
  664         r->anchor_wildcard = 0;
  665         if (!name[0])
  666                 return (0);
  667         path = (char *)rs_malloc(MAXPATHLEN);
  668         if (path == NULL)
  669                 return (1);
  670         if (name[0] == '/')
  671                 strlcpy(path, name + 1, MAXPATHLEN);
  672         else {
  673                 /* relative path */
  674                 r->anchor_relative = 1;
  675                 if (s->anchor == NULL || !s->anchor->path[0])
  676                         path[0] = 0;
  677                 else
  678                         strlcpy(path, s->anchor->path, MAXPATHLEN);
  679                 while (name[0] == '.' && name[1] == '.' && name[2] == '/') {
  680                         if (!path[0]) {
  681                                 DPFPRINTF("pf_anchor_setup: .. beyond root\n");
  682                                 rs_free(path);
  683                                 return (1);
  684                         }
  685                         if ((p = strrchr(path, '/')) != NULL)
  686                                 *p = 0;
  687                         else
  688                                 path[0] = 0;
  689                         r->anchor_relative++;
  690                         name += 3;
  691                 }
  692                 if (path[0])
  693                         strlcat(path, "/", MAXPATHLEN);
  694                 strlcat(path, name, MAXPATHLEN);
  695         }
  696         if ((p = strrchr(path, '/')) != NULL && !strcmp(p, "/*")) {
  697                 r->anchor_wildcard = 1;
  698                 *p = 0;
  699         }
  700         ruleset = pf_find_or_create_keth_ruleset(path);
  701         rs_free(path);
  702         if (ruleset == NULL || ruleset->anchor == NULL) {
  703                 DPFPRINTF("pf_anchor_setup: ruleset\n");
  704                 return (1);
  705         }
  706         r->anchor = ruleset->anchor;
  707         r->anchor->refcnt++;
  708         return (0);
  709 }
  710 
  711 void
  712 pf_keth_anchor_remove(struct pf_keth_rule *r)
  713 {
  714         if (r->anchor == NULL)
  715                 return;
  716         if (r->anchor->refcnt <= 0) {
  717                 printf("%s: broken refcount\n", __func__);
  718                 r->anchor = NULL;
  719                 return;
  720         }
  721         if (!--r->anchor->refcnt)
  722                 pf_remove_if_empty_keth_ruleset(&r->anchor->ruleset);
  723         r->anchor = NULL;
  724 }
  725 
  726 void
  727 pf_remove_if_empty_keth_ruleset(struct pf_keth_ruleset *ruleset)
  728 {
  729         struct pf_keth_anchor   *parent;
  730         int                      i;
  731 
  732         while (ruleset != NULL) {
  733                 if (ruleset == V_pf_keth || ruleset->anchor == NULL ||
  734                     !RB_EMPTY(&ruleset->anchor->children) ||
  735                     ruleset->anchor->refcnt > 0)
  736                         return;
  737                 for (i = 0; i < PF_RULESET_MAX; ++i)
  738                         if (!TAILQ_EMPTY(ruleset->active.rules) ||
  739                             !TAILQ_EMPTY(ruleset->inactive.rules) ||
  740                             ruleset->inactive.open)
  741                                 return;
  742                 RB_REMOVE(pf_keth_anchor_global, &V_pf_keth_anchors, ruleset->anchor);
  743                 if ((parent = ruleset->anchor->parent) != NULL)
  744                         RB_REMOVE(pf_keth_anchor_node, &parent->children,
  745                             ruleset->anchor);
  746                 rs_free(ruleset->anchor);
  747                 if (parent == NULL)
  748                         return;
  749                 ruleset = &parent->ruleset;
  750         }
  751 }

Cache object: fdf7d36c7b5417c520d01d503e73b7fb


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.