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_nv.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-FreeBSD
    3  *
    4  * Copyright (c) 2021 Rubicon Communications, LLC (Netgate)
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  *
   27  */
   28 #include <sys/cdefs.h>
   29 __FBSDID("$FreeBSD$");
   30 
   31 #include "opt_inet.h"
   32 #include "opt_inet6.h"
   33 
   34 #include <sys/param.h>
   35 #include <sys/errno.h>
   36 #include <sys/limits.h>
   37 #include <sys/queue.h>
   38 #include <sys/systm.h>
   39 
   40 #include <netpfil/pf/pf_nv.h>
   41 
   42 #define PF_NV_IMPL_UINT(fnname, type, max)                                      \
   43         int                                                                     \
   44         pf_nv ## fnname ## _opt(const nvlist_t *nvl, const char *name,          \
   45             type *val, type dflt)                                               \
   46         {                                                                       \
   47                 uint64_t raw;                                                   \
   48                 if (! nvlist_exists_number(nvl, name)) {                        \
   49                         *val = dflt;                                            \
   50                         return (0);                                             \
   51                 }                                                               \
   52                 raw = nvlist_get_number(nvl, name);                             \
   53                 if (raw > max)                                                  \
   54                         return (ERANGE);                                        \
   55                 *val = (type)raw;                                               \
   56                 return (0);                                                     \
   57         }                                                                       \
   58         int                                                                     \
   59         pf_nv ## fnname(const nvlist_t *nvl, const char *name, type *val)       \
   60         {                                                                       \
   61                 uint64_t raw;                                                   \
   62                 if (! nvlist_exists_number(nvl, name))                          \
   63                         return (EINVAL);                                        \
   64                 raw = nvlist_get_number(nvl, name);                             \
   65                 if (raw > max)                                                  \
   66                         return (ERANGE);                                        \
   67                 *val = (type)raw;                                               \
   68                 return (0);                                                     \
   69         }                                                                       \
   70         int                                                                     \
   71         pf_nv ## fnname ## _array(const nvlist_t *nvl, const char *name,        \
   72             type *array, size_t maxelems, size_t *nelems)                       \
   73         {                                                                       \
   74                 const uint64_t *n;                                              \
   75                 size_t nitems;                                                  \
   76                 bzero(array, sizeof(type) * maxelems);                          \
   77                 if (! nvlist_exists_number_array(nvl, name))                    \
   78                         return (EINVAL);                                        \
   79                 n = nvlist_get_number_array(nvl, name, &nitems);                \
   80                 if (nitems != maxelems)                                         \
   81                         return (E2BIG);                                         \
   82                 if (nelems != NULL)                                             \
   83                         *nelems = nitems;                                       \
   84                 for (size_t i = 0; i < nitems; i++) {                           \
   85                         if (n[i] > max)                                         \
   86                                 return (ERANGE);                                \
   87                         array[i] = (type)n[i];                                  \
   88                 }                                                               \
   89                 return (0);                                                     \
   90         }                                                                       \
   91         void                                                                    \
   92         pf_ ## fnname ## _array_nv(nvlist_t *nvl, const char *name,             \
   93             const type *numbers, size_t count)                                  \
   94         {                                                                       \
   95                 uint64_t tmp;                                                   \
   96                 for (size_t i = 0; i < count; i++) {                            \
   97                         tmp = numbers[i];                                       \
   98                         nvlist_append_number_array(nvl, name, tmp);             \
   99                 }                                                               \
  100         }
  101 
  102 int
  103 pf_nvbool(const nvlist_t *nvl, const char *name, bool *val)
  104 {
  105         if (! nvlist_exists_bool(nvl, name))
  106                 return (EINVAL);
  107 
  108         *val = nvlist_get_bool(nvl, name);
  109 
  110         return (0);
  111 }
  112 
  113 int
  114 pf_nvbinary(const nvlist_t *nvl, const char *name, void *data,
  115     size_t expected_size)
  116 {
  117         const uint8_t *nvdata;
  118         size_t len;
  119 
  120         bzero(data, expected_size);
  121 
  122         if (! nvlist_exists_binary(nvl, name))
  123                 return (EINVAL);
  124 
  125         nvdata = (const uint8_t *)nvlist_get_binary(nvl, name, &len);
  126         if (len > expected_size)
  127                 return (EINVAL);
  128 
  129         memcpy(data, nvdata, len);
  130 
  131         return (0);
  132 }
  133 
  134 PF_NV_IMPL_UINT(uint8, uint8_t, UINT8_MAX);
  135 PF_NV_IMPL_UINT(uint16, uint16_t, UINT16_MAX);
  136 PF_NV_IMPL_UINT(uint32, uint32_t, UINT32_MAX);
  137 PF_NV_IMPL_UINT(uint64, uint64_t, UINT64_MAX);
  138 
  139 int
  140 pf_nvint(const nvlist_t *nvl, const char *name, int *val)
  141 {
  142         int64_t raw;
  143 
  144         if (! nvlist_exists_number(nvl, name))
  145                 return (EINVAL);
  146 
  147         raw = nvlist_get_number(nvl, name);
  148         if (raw > INT_MAX || raw < INT_MIN)
  149                 return (ERANGE);
  150 
  151         *val = (int)raw;
  152 
  153         return (0);
  154 }
  155 
  156 int
  157 pf_nvstring(const nvlist_t *nvl, const char *name, char *str, size_t maxlen)
  158 {
  159         int ret;
  160 
  161         if (! nvlist_exists_string(nvl, name))
  162                 return (EINVAL);
  163 
  164         ret = strlcpy(str, nvlist_get_string(nvl, name), maxlen);
  165         if (ret >= maxlen)
  166                 return (EINVAL);
  167 
  168         return (0);
  169 }
  170 
  171 static int
  172 pf_nvaddr_to_addr(const nvlist_t *nvl, struct pf_addr *paddr)
  173 {
  174         return (pf_nvbinary(nvl, "addr", paddr, sizeof(*paddr)));
  175 }
  176 
  177 static nvlist_t *
  178 pf_addr_to_nvaddr(const struct pf_addr *paddr)
  179 {
  180         nvlist_t *nvl;
  181 
  182         nvl = nvlist_create(0);
  183         if (nvl == NULL)
  184                 return (NULL);
  185 
  186         nvlist_add_binary(nvl, "addr", paddr, sizeof(*paddr));
  187 
  188         return (nvl);
  189 }
  190 
  191 static int
  192 pf_nvmape_to_mape(const nvlist_t *nvl, struct pf_mape_portset *mape)
  193 {
  194         int error = 0;
  195 
  196         bzero(mape, sizeof(*mape));
  197         PFNV_CHK(pf_nvuint8(nvl, "offset", &mape->offset));
  198         PFNV_CHK(pf_nvuint8(nvl, "psidlen", &mape->psidlen));
  199         PFNV_CHK(pf_nvuint16(nvl, "psid", &mape->psid));
  200 
  201 errout:
  202         return (error);
  203 }
  204 
  205 static nvlist_t *
  206 pf_mape_to_nvmape(const struct pf_mape_portset *mape)
  207 {
  208         nvlist_t *nvl;
  209 
  210         nvl = nvlist_create(0);
  211         if (nvl == NULL)
  212                 return (NULL);
  213 
  214         nvlist_add_number(nvl, "offset", mape->offset);
  215         nvlist_add_number(nvl, "psidlen", mape->psidlen);
  216         nvlist_add_number(nvl, "psid", mape->psid);
  217 
  218         return (nvl);
  219 }
  220 
  221 static int
  222 pf_nvpool_to_pool(const nvlist_t *nvl, struct pf_kpool *kpool)
  223 {
  224         int error = 0;
  225 
  226         PFNV_CHK(pf_nvbinary(nvl, "key", &kpool->key, sizeof(kpool->key)));
  227 
  228         if (nvlist_exists_nvlist(nvl, "counter")) {
  229                 PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "counter"),
  230                     &kpool->counter));
  231         }
  232 
  233         PFNV_CHK(pf_nvint(nvl, "tblidx", &kpool->tblidx));
  234         PFNV_CHK(pf_nvuint16_array(nvl, "proxy_port", kpool->proxy_port, 2,
  235             NULL));
  236         PFNV_CHK(pf_nvuint8(nvl, "opts", &kpool->opts));
  237 
  238         if (nvlist_exists_nvlist(nvl, "mape")) {
  239                 PFNV_CHK(pf_nvmape_to_mape(nvlist_get_nvlist(nvl, "mape"),
  240                     &kpool->mape));
  241         }
  242 
  243 errout:
  244         return (error);
  245 }
  246 
  247 static nvlist_t *
  248 pf_pool_to_nvpool(const struct pf_kpool *pool)
  249 {
  250         nvlist_t *nvl;
  251         nvlist_t *tmp;
  252 
  253         nvl = nvlist_create(0);
  254         if (nvl == NULL)
  255                 return (NULL);
  256 
  257         nvlist_add_binary(nvl, "key", &pool->key, sizeof(pool->key));
  258         tmp = pf_addr_to_nvaddr(&pool->counter);
  259         if (tmp == NULL)
  260                 goto error;
  261         nvlist_add_nvlist(nvl, "counter", tmp);
  262         nvlist_destroy(tmp);
  263 
  264         nvlist_add_number(nvl, "tblidx", pool->tblidx);
  265         pf_uint16_array_nv(nvl, "proxy_port", pool->proxy_port, 2);
  266         nvlist_add_number(nvl, "opts", pool->opts);
  267 
  268         tmp = pf_mape_to_nvmape(&pool->mape);
  269         if (tmp == NULL)
  270                 goto error;
  271         nvlist_add_nvlist(nvl, "mape", tmp);
  272         nvlist_destroy(tmp);
  273 
  274         return (nvl);
  275 
  276 error:
  277         nvlist_destroy(nvl);
  278         return (NULL);
  279 }
  280 
  281 static int
  282 pf_nvaddr_wrap_to_addr_wrap(const nvlist_t *nvl, struct pf_addr_wrap *addr)
  283 {
  284         int error = 0;
  285 
  286         bzero(addr, sizeof(*addr));
  287 
  288         PFNV_CHK(pf_nvuint8(nvl, "type", &addr->type));
  289         PFNV_CHK(pf_nvuint8(nvl, "iflags", &addr->iflags));
  290         if (addr->type == PF_ADDR_DYNIFTL)
  291                 PFNV_CHK(pf_nvstring(nvl, "ifname", addr->v.ifname,
  292                     sizeof(addr->v.ifname)));
  293         if (addr->type == PF_ADDR_TABLE)
  294                 PFNV_CHK(pf_nvstring(nvl, "tblname", addr->v.tblname,
  295                     sizeof(addr->v.tblname)));
  296 
  297         if (! nvlist_exists_nvlist(nvl, "addr"))
  298                 return (EINVAL);
  299         PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "addr"),
  300             &addr->v.a.addr));
  301 
  302         if (! nvlist_exists_nvlist(nvl, "mask"))
  303                 return (EINVAL);
  304         PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "mask"),
  305             &addr->v.a.mask));
  306 
  307         switch (addr->type) {
  308         case PF_ADDR_DYNIFTL:
  309         case PF_ADDR_TABLE:
  310         case PF_ADDR_RANGE:
  311         case PF_ADDR_ADDRMASK:
  312         case PF_ADDR_NOROUTE:
  313         case PF_ADDR_URPFFAILED:
  314                 break;
  315         default:
  316                 return (EINVAL);
  317         }
  318 
  319 errout:
  320         return (error);
  321 }
  322 
  323 static nvlist_t *
  324 pf_addr_wrap_to_nvaddr_wrap(const struct pf_addr_wrap *addr)
  325 {
  326         nvlist_t *nvl;
  327         nvlist_t *tmp;
  328         uint64_t num;
  329         struct pfr_ktable *kt;
  330 
  331         nvl = nvlist_create(0);
  332         if (nvl == NULL)
  333                 return (NULL);
  334 
  335         nvlist_add_number(nvl, "type", addr->type);
  336         nvlist_add_number(nvl, "iflags", addr->iflags);
  337         if (addr->type == PF_ADDR_DYNIFTL) {
  338                 nvlist_add_string(nvl, "ifname", addr->v.ifname);
  339                 num = 0;
  340                 if (addr->p.dyn != NULL)
  341                         num = addr->p.dyn->pfid_acnt4 +
  342                             addr->p.dyn->pfid_acnt6;
  343                 nvlist_add_number(nvl, "dyncnt", num);
  344         }
  345         if (addr->type == PF_ADDR_TABLE) {
  346                 nvlist_add_string(nvl, "tblname", addr->v.tblname);
  347                 num = -1;
  348                 kt = addr->p.tbl;
  349                 if ((kt->pfrkt_flags & PFR_TFLAG_ACTIVE) &&
  350                     kt->pfrkt_root != NULL)
  351                         kt = kt->pfrkt_root;
  352                 if (kt->pfrkt_flags & PFR_TFLAG_ACTIVE)
  353                         num = kt->pfrkt_cnt;
  354                 nvlist_add_number(nvl, "tblcnt", num);
  355         }
  356 
  357         tmp = pf_addr_to_nvaddr(&addr->v.a.addr);
  358         if (tmp == NULL)
  359                 goto error;
  360         nvlist_add_nvlist(nvl, "addr", tmp);
  361         nvlist_destroy(tmp);
  362         tmp = pf_addr_to_nvaddr(&addr->v.a.mask);
  363         if (tmp == NULL)
  364                 goto error;
  365         nvlist_add_nvlist(nvl, "mask", tmp);
  366         nvlist_destroy(tmp);
  367 
  368         return (nvl);
  369 
  370 error:
  371         nvlist_destroy(nvl);
  372         return (NULL);
  373 }
  374 
  375 static int
  376 pf_validate_op(uint8_t op)
  377 {
  378         switch (op) {
  379         case PF_OP_NONE:
  380         case PF_OP_IRG:
  381         case PF_OP_EQ:
  382         case PF_OP_NE:
  383         case PF_OP_LT:
  384         case PF_OP_LE:
  385         case PF_OP_GT:
  386         case PF_OP_GE:
  387         case PF_OP_XRG:
  388         case PF_OP_RRG:
  389                 break;
  390         default:
  391                 return (EINVAL);
  392         }
  393 
  394         return (0);
  395 }
  396 
  397 static int
  398 pf_nvrule_addr_to_rule_addr(const nvlist_t *nvl, struct pf_rule_addr *addr)
  399 {
  400         int error = 0;
  401 
  402         if (! nvlist_exists_nvlist(nvl, "addr"))
  403                 return (EINVAL);
  404 
  405         PFNV_CHK(pf_nvaddr_wrap_to_addr_wrap(nvlist_get_nvlist(nvl, "addr"),
  406             &addr->addr));
  407         PFNV_CHK(pf_nvuint16_array(nvl, "port", addr->port, 2, NULL));
  408         PFNV_CHK(pf_nvuint8(nvl, "neg", &addr->neg));
  409         PFNV_CHK(pf_nvuint8(nvl, "port_op", &addr->port_op));
  410 
  411         PFNV_CHK(pf_validate_op(addr->port_op));
  412 
  413 errout:
  414         return (error);
  415 }
  416 
  417 static nvlist_t *
  418 pf_rule_addr_to_nvrule_addr(const struct pf_rule_addr *addr)
  419 {
  420         nvlist_t *nvl;
  421         nvlist_t *tmp;
  422 
  423         nvl = nvlist_create(0);
  424         if (nvl == NULL)
  425                 return (NULL);
  426 
  427         tmp = pf_addr_wrap_to_nvaddr_wrap(&addr->addr);
  428         if (tmp == NULL)
  429                 goto error;
  430         nvlist_add_nvlist(nvl, "addr", tmp);
  431         nvlist_destroy(tmp);
  432         pf_uint16_array_nv(nvl, "port", addr->port, 2);
  433         nvlist_add_number(nvl, "neg", addr->neg);
  434         nvlist_add_number(nvl, "port_op", addr->port_op);
  435 
  436         return (nvl);
  437 
  438 error:
  439         nvlist_destroy(nvl);
  440         return (NULL);
  441 }
  442 
  443 static int
  444 pf_nvrule_uid_to_rule_uid(const nvlist_t *nvl, struct pf_rule_uid *uid)
  445 {
  446         int error = 0;
  447 
  448         bzero(uid, sizeof(*uid));
  449 
  450         PFNV_CHK(pf_nvuint32_array(nvl, "uid", uid->uid, 2, NULL));
  451         PFNV_CHK(pf_nvuint8(nvl, "op", &uid->op));
  452 
  453         PFNV_CHK(pf_validate_op(uid->op));
  454 
  455 errout:
  456         return (error);
  457 }
  458 
  459 static nvlist_t *
  460 pf_rule_uid_to_nvrule_uid(const struct pf_rule_uid *uid)
  461 {
  462         nvlist_t *nvl;
  463 
  464         nvl = nvlist_create(0);
  465         if (nvl == NULL)
  466                 return (NULL);
  467 
  468         pf_uint32_array_nv(nvl, "uid", uid->uid, 2);
  469         nvlist_add_number(nvl, "op", uid->op);
  470 
  471         return (nvl);
  472 }
  473 
  474 static int
  475 pf_nvrule_gid_to_rule_gid(const nvlist_t *nvl, struct pf_rule_gid *gid)
  476 {
  477         /* Cheat a little. These stucts are the same, other than the name of
  478          * the first field. */
  479         return (pf_nvrule_uid_to_rule_uid(nvl, (struct pf_rule_uid *)gid));
  480 }
  481 
  482 int
  483 pf_check_rule_addr(const struct pf_rule_addr *addr)
  484 {
  485 
  486         switch (addr->addr.type) {
  487         case PF_ADDR_ADDRMASK:
  488         case PF_ADDR_NOROUTE:
  489         case PF_ADDR_DYNIFTL:
  490         case PF_ADDR_TABLE:
  491         case PF_ADDR_URPFFAILED:
  492         case PF_ADDR_RANGE:
  493                 break;
  494         default:
  495                 return (EINVAL);
  496         }
  497 
  498         if (addr->addr.p.dyn != NULL) {
  499                 return (EINVAL);
  500         }
  501 
  502         return (0);
  503 }
  504 
  505 
  506 int
  507 pf_nvrule_to_krule(const nvlist_t *nvl, struct pf_krule *rule)
  508 {
  509         int error = 0;
  510 
  511 #define ERROUT(x)       ERROUT_FUNCTION(errout, x)
  512 
  513         PFNV_CHK(pf_nvuint32(nvl, "nr", &rule->nr));
  514 
  515         if (! nvlist_exists_nvlist(nvl, "src"))
  516                 ERROUT(EINVAL);
  517 
  518         error = pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "src"),
  519             &rule->src);
  520         if (error != 0)
  521                 ERROUT(error);
  522 
  523         if (! nvlist_exists_nvlist(nvl, "dst"))
  524                 ERROUT(EINVAL);
  525 
  526         PFNV_CHK(pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "dst"),
  527             &rule->dst));
  528 
  529         if (nvlist_exists_string(nvl, "label")) {
  530                 PFNV_CHK(pf_nvstring(nvl, "label", rule->label[0],
  531                     sizeof(rule->label[0])));
  532         } else if (nvlist_exists_string_array(nvl, "labels")) {
  533                 const char *const *strs;
  534                 size_t items;
  535                 int ret;
  536 
  537                 strs = nvlist_get_string_array(nvl, "labels", &items);
  538                 if (items > PF_RULE_MAX_LABEL_COUNT)
  539                         ERROUT(E2BIG);
  540 
  541                 for (size_t i = 0; i < items; i++) {
  542                         ret = strlcpy(rule->label[i], strs[i],
  543                             sizeof(rule->label[0]));
  544                         if (ret >= sizeof(rule->label[0]))
  545                                 ERROUT(E2BIG);
  546                 }
  547         }
  548 
  549         PFNV_CHK(pf_nvuint32_opt(nvl, "ridentifier", &rule->ridentifier, 0));
  550         PFNV_CHK(pf_nvstring(nvl, "ifname", rule->ifname,
  551             sizeof(rule->ifname)));
  552         PFNV_CHK(pf_nvstring(nvl, "qname", rule->qname, sizeof(rule->qname)));
  553         PFNV_CHK(pf_nvstring(nvl, "pqname", rule->pqname,
  554             sizeof(rule->pqname)));
  555         PFNV_CHK(pf_nvstring(nvl, "tagname", rule->tagname,
  556             sizeof(rule->tagname)));
  557         PFNV_CHK(pf_nvuint16_opt(nvl, "dnpipe", &rule->dnpipe, 0));
  558         PFNV_CHK(pf_nvuint16_opt(nvl, "dnrpipe", &rule->dnrpipe, 0));
  559         PFNV_CHK(pf_nvuint32_opt(nvl, "dnflags", &rule->free_flags, 0));
  560         PFNV_CHK(pf_nvstring(nvl, "match_tagname", rule->match_tagname,
  561             sizeof(rule->match_tagname)));
  562         PFNV_CHK(pf_nvstring(nvl, "overload_tblname", rule->overload_tblname,
  563             sizeof(rule->overload_tblname)));
  564 
  565         if (! nvlist_exists_nvlist(nvl, "rpool"))
  566                 ERROUT(EINVAL);
  567         PFNV_CHK(pf_nvpool_to_pool(nvlist_get_nvlist(nvl, "rpool"),
  568             &rule->rpool));
  569 
  570         PFNV_CHK(pf_nvuint32(nvl, "os_fingerprint", &rule->os_fingerprint));
  571 
  572         PFNV_CHK(pf_nvint(nvl, "rtableid", &rule->rtableid));
  573         PFNV_CHK(pf_nvuint32_array(nvl, "timeout", rule->timeout, PFTM_MAX, NULL));
  574         PFNV_CHK(pf_nvuint32(nvl, "max_states", &rule->max_states));
  575         PFNV_CHK(pf_nvuint32(nvl, "max_src_nodes", &rule->max_src_nodes));
  576         PFNV_CHK(pf_nvuint32(nvl, "max_src_states", &rule->max_src_states));
  577         PFNV_CHK(pf_nvuint32(nvl, "max_src_conn", &rule->max_src_conn));
  578         PFNV_CHK(pf_nvuint32(nvl, "max_src_conn_rate.limit",
  579             &rule->max_src_conn_rate.limit));
  580         PFNV_CHK(pf_nvuint32(nvl, "max_src_conn_rate.seconds",
  581             &rule->max_src_conn_rate.seconds));
  582         PFNV_CHK(pf_nvuint32(nvl, "prob", &rule->prob));
  583         PFNV_CHK(pf_nvuint32(nvl, "cuid", &rule->cuid));
  584         PFNV_CHK(pf_nvuint32(nvl, "cpid", &rule->cpid));
  585 
  586         PFNV_CHK(pf_nvuint16(nvl, "return_icmp", &rule->return_icmp));
  587         PFNV_CHK(pf_nvuint16(nvl, "return_icmp6", &rule->return_icmp6));
  588 
  589         PFNV_CHK(pf_nvuint16(nvl, "max_mss", &rule->max_mss));
  590         PFNV_CHK(pf_nvuint16(nvl, "scrub_flags", &rule->scrub_flags));
  591 
  592         if (! nvlist_exists_nvlist(nvl, "uid"))
  593                 ERROUT(EINVAL);
  594         PFNV_CHK(pf_nvrule_uid_to_rule_uid(nvlist_get_nvlist(nvl, "uid"),
  595             &rule->uid));
  596 
  597         if (! nvlist_exists_nvlist(nvl, "gid"))
  598                 ERROUT(EINVAL);
  599         PFNV_CHK(pf_nvrule_gid_to_rule_gid(nvlist_get_nvlist(nvl, "gid"),
  600             &rule->gid));
  601 
  602         PFNV_CHK(pf_nvuint32(nvl, "rule_flag", &rule->rule_flag));
  603         PFNV_CHK(pf_nvuint8(nvl, "action", &rule->action));
  604         PFNV_CHK(pf_nvuint8(nvl, "direction", &rule->direction));
  605         PFNV_CHK(pf_nvuint8(nvl, "log", &rule->log));
  606         PFNV_CHK(pf_nvuint8(nvl, "logif", &rule->logif));
  607         PFNV_CHK(pf_nvuint8(nvl, "quick", &rule->quick));
  608         PFNV_CHK(pf_nvuint8(nvl, "ifnot", &rule->ifnot));
  609         PFNV_CHK(pf_nvuint8(nvl, "match_tag_not", &rule->match_tag_not));
  610         PFNV_CHK(pf_nvuint8(nvl, "natpass", &rule->natpass));
  611 
  612         PFNV_CHK(pf_nvuint8(nvl, "keep_state", &rule->keep_state));
  613         PFNV_CHK(pf_nvuint8(nvl, "af", &rule->af));
  614         PFNV_CHK(pf_nvuint8(nvl, "proto", &rule->proto));
  615         PFNV_CHK(pf_nvuint8(nvl, "type", &rule->type));
  616         PFNV_CHK(pf_nvuint8(nvl, "code", &rule->code));
  617         PFNV_CHK(pf_nvuint8(nvl, "flags", &rule->flags));
  618         PFNV_CHK(pf_nvuint8(nvl, "flagset", &rule->flagset));
  619         PFNV_CHK(pf_nvuint8(nvl, "min_ttl", &rule->min_ttl));
  620         PFNV_CHK(pf_nvuint8(nvl, "allow_opts", &rule->allow_opts));
  621         PFNV_CHK(pf_nvuint8(nvl, "rt", &rule->rt));
  622         PFNV_CHK(pf_nvuint8(nvl, "return_ttl", &rule->return_ttl));
  623         PFNV_CHK(pf_nvuint8(nvl, "tos", &rule->tos));
  624         PFNV_CHK(pf_nvuint8(nvl, "set_tos", &rule->set_tos));
  625 
  626         PFNV_CHK(pf_nvuint8(nvl, "flush", &rule->flush));
  627         PFNV_CHK(pf_nvuint8(nvl, "prio", &rule->prio));
  628 
  629         PFNV_CHK(pf_nvuint8_array(nvl, "set_prio", rule->set_prio, 2, NULL));
  630 
  631         if (nvlist_exists_nvlist(nvl, "divert")) {
  632                 const nvlist_t *nvldivert = nvlist_get_nvlist(nvl, "divert");
  633 
  634                 if (! nvlist_exists_nvlist(nvldivert, "addr"))
  635                         ERROUT(EINVAL);
  636                 PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvldivert, "addr"),
  637                     &rule->divert.addr));
  638                 PFNV_CHK(pf_nvuint16(nvldivert, "port", &rule->divert.port));
  639         }
  640 
  641         /* Validation */
  642 #ifndef INET
  643         if (rule->af == AF_INET)
  644                 ERROUT(EAFNOSUPPORT);
  645 #endif /* INET */
  646 #ifndef INET6
  647         if (rule->af == AF_INET6)
  648                 ERROUT(EAFNOSUPPORT);
  649 #endif /* INET6 */
  650 
  651         PFNV_CHK(pf_check_rule_addr(&rule->src));
  652         PFNV_CHK(pf_check_rule_addr(&rule->dst));
  653 
  654         return (0);
  655 
  656 #undef ERROUT
  657 errout:
  658         return (error);
  659 }
  660 
  661 static nvlist_t *
  662 pf_divert_to_nvdivert(const struct pf_krule *rule)
  663 {
  664         nvlist_t *nvl;
  665         nvlist_t *tmp;
  666 
  667         nvl = nvlist_create(0);
  668         if (nvl == NULL)
  669                 return (NULL);
  670 
  671         tmp = pf_addr_to_nvaddr(&rule->divert.addr);
  672         if (tmp == NULL)
  673                 goto error;
  674         nvlist_add_nvlist(nvl, "addr", tmp);
  675         nvlist_destroy(tmp);
  676         nvlist_add_number(nvl, "port", rule->divert.port);
  677 
  678         return (nvl);
  679 
  680 error:
  681         nvlist_destroy(nvl);
  682         return (NULL);
  683 }
  684 
  685 nvlist_t *
  686 pf_krule_to_nvrule(struct pf_krule *rule)
  687 {
  688         nvlist_t *nvl, *tmp;
  689 
  690         nvl = nvlist_create(0);
  691         if (nvl == NULL)
  692                 return (nvl);
  693 
  694         nvlist_add_number(nvl, "nr", rule->nr);
  695         tmp = pf_rule_addr_to_nvrule_addr(&rule->src);
  696         if (tmp == NULL)
  697                 goto error;
  698         nvlist_add_nvlist(nvl, "src", tmp);
  699         nvlist_destroy(tmp);
  700         tmp = pf_rule_addr_to_nvrule_addr(&rule->dst);
  701         if (tmp == NULL)
  702                 goto error;
  703         nvlist_add_nvlist(nvl, "dst", tmp);
  704         nvlist_destroy(tmp);
  705 
  706         for (int i = 0; i < PF_SKIP_COUNT; i++) {
  707                 nvlist_append_number_array(nvl, "skip",
  708                     rule->skip[i].ptr ? rule->skip[i].ptr->nr : -1);
  709         }
  710 
  711         for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++) {
  712                 nvlist_append_string_array(nvl, "labels", rule->label[i]);
  713         }
  714         nvlist_add_string(nvl, "label", rule->label[0]);
  715         nvlist_add_number(nvl, "ridentifier", rule->ridentifier);
  716         nvlist_add_string(nvl, "ifname", rule->ifname);
  717         nvlist_add_string(nvl, "qname", rule->qname);
  718         nvlist_add_string(nvl, "pqname", rule->pqname);
  719         nvlist_add_number(nvl, "dnpipe", rule->dnpipe);
  720         nvlist_add_number(nvl, "dnrpipe", rule->dnrpipe);
  721         nvlist_add_number(nvl, "dnflags", rule->free_flags);
  722         nvlist_add_string(nvl, "tagname", rule->tagname);
  723         nvlist_add_string(nvl, "match_tagname", rule->match_tagname);
  724         nvlist_add_string(nvl, "overload_tblname", rule->overload_tblname);
  725 
  726         tmp = pf_pool_to_nvpool(&rule->rpool);
  727         if (tmp == NULL)
  728                 goto error;
  729         nvlist_add_nvlist(nvl, "rpool", tmp);
  730         nvlist_destroy(tmp);
  731 
  732         nvlist_add_number(nvl, "evaluations",
  733             pf_counter_u64_fetch(&rule->evaluations));
  734         for (int i = 0; i < 2; i++) {
  735                 nvlist_append_number_array(nvl, "packets",
  736                     pf_counter_u64_fetch(&rule->packets[i]));
  737                 nvlist_append_number_array(nvl, "bytes",
  738                     pf_counter_u64_fetch(&rule->bytes[i]));
  739         }
  740         nvlist_add_number(nvl, "timestamp", pf_get_timestamp(rule));
  741 
  742         nvlist_add_number(nvl, "os_fingerprint", rule->os_fingerprint);
  743 
  744         nvlist_add_number(nvl, "rtableid", rule->rtableid);
  745         pf_uint32_array_nv(nvl, "timeout", rule->timeout, PFTM_MAX);
  746         nvlist_add_number(nvl, "max_states", rule->max_states);
  747         nvlist_add_number(nvl, "max_src_nodes", rule->max_src_nodes);
  748         nvlist_add_number(nvl, "max_src_states", rule->max_src_states);
  749         nvlist_add_number(nvl, "max_src_conn", rule->max_src_conn);
  750         nvlist_add_number(nvl, "max_src_conn_rate.limit",
  751             rule->max_src_conn_rate.limit);
  752         nvlist_add_number(nvl, "max_src_conn_rate.seconds",
  753             rule->max_src_conn_rate.seconds);
  754         nvlist_add_number(nvl, "qid", rule->qid);
  755         nvlist_add_number(nvl, "pqid", rule->pqid);
  756         nvlist_add_number(nvl, "prob", rule->prob);
  757         nvlist_add_number(nvl, "cuid", rule->cuid);
  758         nvlist_add_number(nvl, "cpid", rule->cpid);
  759 
  760         nvlist_add_number(nvl, "states_cur",
  761             counter_u64_fetch(rule->states_cur));
  762         nvlist_add_number(nvl, "states_tot",
  763             counter_u64_fetch(rule->states_tot));
  764         nvlist_add_number(nvl, "src_nodes",
  765             counter_u64_fetch(rule->src_nodes));
  766 
  767         nvlist_add_number(nvl, "return_icmp", rule->return_icmp);
  768         nvlist_add_number(nvl, "return_icmp6", rule->return_icmp6);
  769 
  770         nvlist_add_number(nvl, "max_mss", rule->max_mss);
  771         nvlist_add_number(nvl, "scrub_flags", rule->scrub_flags);
  772 
  773         tmp = pf_rule_uid_to_nvrule_uid(&rule->uid);
  774         if (tmp == NULL)
  775                 goto error;
  776         nvlist_add_nvlist(nvl, "uid", tmp);
  777         nvlist_destroy(tmp);
  778         tmp = pf_rule_uid_to_nvrule_uid((const struct pf_rule_uid *)&rule->gid);
  779         if (tmp == NULL)
  780                 goto error;
  781         nvlist_add_nvlist(nvl, "gid", tmp);
  782         nvlist_destroy(tmp);
  783 
  784         nvlist_add_number(nvl, "rule_flag", rule->rule_flag);
  785         nvlist_add_number(nvl, "action", rule->action);
  786         nvlist_add_number(nvl, "direction", rule->direction);
  787         nvlist_add_number(nvl, "log", rule->log);
  788         nvlist_add_number(nvl, "logif", rule->logif);
  789         nvlist_add_number(nvl, "quick", rule->quick);
  790         nvlist_add_number(nvl, "ifnot", rule->ifnot);
  791         nvlist_add_number(nvl, "match_tag_not", rule->match_tag_not);
  792         nvlist_add_number(nvl, "natpass", rule->natpass);
  793 
  794         nvlist_add_number(nvl, "keep_state", rule->keep_state);
  795         nvlist_add_number(nvl, "af", rule->af);
  796         nvlist_add_number(nvl, "proto", rule->proto);
  797         nvlist_add_number(nvl, "type", rule->type);
  798         nvlist_add_number(nvl, "code", rule->code);
  799         nvlist_add_number(nvl, "flags", rule->flags);
  800         nvlist_add_number(nvl, "flagset", rule->flagset);
  801         nvlist_add_number(nvl, "min_ttl", rule->min_ttl);
  802         nvlist_add_number(nvl, "allow_opts", rule->allow_opts);
  803         nvlist_add_number(nvl, "rt", rule->rt);
  804         nvlist_add_number(nvl, "return_ttl", rule->return_ttl);
  805         nvlist_add_number(nvl, "tos", rule->tos);
  806         nvlist_add_number(nvl, "set_tos", rule->set_tos);
  807         nvlist_add_number(nvl, "anchor_relative", rule->anchor_relative);
  808         nvlist_add_number(nvl, "anchor_wildcard", rule->anchor_wildcard);
  809 
  810         nvlist_add_number(nvl, "flush", rule->flush);
  811         nvlist_add_number(nvl, "prio", rule->prio);
  812 
  813         pf_uint8_array_nv(nvl, "set_prio", rule->set_prio, 2);
  814 
  815         tmp = pf_divert_to_nvdivert(rule);
  816         if (tmp == NULL)
  817                 goto error;
  818         nvlist_add_nvlist(nvl, "divert", tmp);
  819         nvlist_destroy(tmp);
  820 
  821         return (nvl);
  822 
  823 error:
  824         nvlist_destroy(nvl);
  825         return (NULL);
  826 }
  827 
  828 static int
  829 pf_nvstate_cmp_to_state_cmp(const nvlist_t *nvl, struct pf_state_cmp *cmp)
  830 {
  831         int error = 0;
  832 
  833         bzero(cmp, sizeof(*cmp));
  834 
  835         PFNV_CHK(pf_nvuint64(nvl, "id", &cmp->id));
  836         PFNV_CHK(pf_nvuint32(nvl, "creatorid", &cmp->creatorid));
  837         PFNV_CHK(pf_nvuint8(nvl, "direction", &cmp->direction));
  838 
  839 errout:
  840         return (error);
  841 }
  842 
  843 int
  844 pf_nvstate_kill_to_kstate_kill(const nvlist_t *nvl,
  845     struct pf_kstate_kill *kill)
  846 {
  847         int error = 0;
  848 
  849         bzero(kill, sizeof(*kill));
  850 
  851         if (! nvlist_exists_nvlist(nvl, "cmp"))
  852                 return (EINVAL);
  853 
  854         PFNV_CHK(pf_nvstate_cmp_to_state_cmp(nvlist_get_nvlist(nvl, "cmp"),
  855             &kill->psk_pfcmp));
  856         PFNV_CHK(pf_nvuint8(nvl, "af", &kill->psk_af));
  857         PFNV_CHK(pf_nvint(nvl, "proto", &kill->psk_proto));
  858 
  859         if (! nvlist_exists_nvlist(nvl, "src"))
  860                 return (EINVAL);
  861         PFNV_CHK(pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "src"),
  862             &kill->psk_src));
  863         if (! nvlist_exists_nvlist(nvl, "dst"))
  864                 return (EINVAL);
  865         PFNV_CHK(pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "dst"),
  866             &kill->psk_dst));
  867         if (nvlist_exists_nvlist(nvl, "rt_addr")) {
  868                 PFNV_CHK(pf_nvrule_addr_to_rule_addr(
  869                     nvlist_get_nvlist(nvl, "rt_addr"), &kill->psk_rt_addr));
  870         }
  871 
  872         PFNV_CHK(pf_nvstring(nvl, "ifname", kill->psk_ifname,
  873             sizeof(kill->psk_ifname)));
  874         PFNV_CHK(pf_nvstring(nvl, "label", kill->psk_label,
  875             sizeof(kill->psk_label)));
  876         PFNV_CHK(pf_nvbool(nvl, "kill_match", &kill->psk_kill_match));
  877 
  878 errout:
  879         return (error);
  880 }
  881 
  882 static nvlist_t *
  883 pf_state_key_to_nvstate_key(const struct pf_state_key *key)
  884 {
  885         nvlist_t        *nvl, *tmp;
  886 
  887         nvl = nvlist_create(0);
  888         if (nvl == NULL)
  889                 return (NULL);
  890 
  891         for (int i = 0; i < 2; i++) {
  892                 tmp = pf_addr_to_nvaddr(&key->addr[i]);
  893                 if (tmp == NULL)
  894                         goto errout;
  895                 nvlist_append_nvlist_array(nvl, "addr", tmp);
  896                 nvlist_destroy(tmp);
  897                 nvlist_append_number_array(nvl, "port", key->port[i]);
  898         }
  899         nvlist_add_number(nvl, "af", key->af);
  900         nvlist_add_number(nvl, "proto", key->proto);
  901 
  902         return (nvl);
  903 
  904 errout:
  905         nvlist_destroy(nvl);
  906         return (NULL);
  907 }
  908 
  909 static nvlist_t *
  910 pf_state_peer_to_nvstate_peer(const struct pf_state_peer *peer)
  911 {
  912         nvlist_t *nvl;
  913 
  914         nvl = nvlist_create(0);
  915         if (nvl == NULL)
  916                 return (NULL);
  917 
  918         nvlist_add_number(nvl, "seqlo", peer->seqlo);
  919         nvlist_add_number(nvl, "seqhi", peer->seqhi);
  920         nvlist_add_number(nvl, "seqdiff", peer->seqdiff);
  921         nvlist_add_number(nvl, "state", peer->state);
  922         nvlist_add_number(nvl, "wscale", peer->wscale);
  923 
  924         return (nvl);
  925 }
  926 
  927 nvlist_t *
  928 pf_state_to_nvstate(const struct pf_kstate *s)
  929 {
  930         nvlist_t        *nvl, *tmp;
  931         uint32_t         expire, flags = 0;
  932 
  933         nvl = nvlist_create(0);
  934         if (nvl == NULL)
  935                 return (NULL);
  936 
  937         nvlist_add_number(nvl, "id", s->id);
  938         nvlist_add_string(nvl, "ifname", s->kif->pfik_name);
  939         nvlist_add_string(nvl, "orig_ifname", s->orig_kif->pfik_name);
  940 
  941         tmp = pf_state_key_to_nvstate_key(s->key[PF_SK_STACK]);
  942         if (tmp == NULL)
  943                 goto errout;
  944         nvlist_add_nvlist(nvl, "stack_key", tmp);
  945         nvlist_destroy(tmp);
  946 
  947         tmp = pf_state_key_to_nvstate_key(s->key[PF_SK_WIRE]);
  948         if (tmp == NULL)
  949                 goto errout;
  950         nvlist_add_nvlist(nvl, "wire_key", tmp);
  951         nvlist_destroy(tmp);
  952 
  953         tmp = pf_state_peer_to_nvstate_peer(&s->src);
  954         if (tmp == NULL)
  955                 goto errout;
  956         nvlist_add_nvlist(nvl, "src", tmp);
  957         nvlist_destroy(tmp);
  958 
  959         tmp = pf_state_peer_to_nvstate_peer(&s->dst);
  960         if (tmp == NULL)
  961                 goto errout;
  962         nvlist_add_nvlist(nvl, "dst", tmp);
  963         nvlist_destroy(tmp);
  964 
  965         tmp = pf_addr_to_nvaddr(&s->rt_addr);
  966         if (tmp == NULL)
  967                 goto errout;
  968         nvlist_add_nvlist(nvl, "rt_addr", tmp);
  969         nvlist_destroy(tmp);
  970 
  971         nvlist_add_number(nvl, "rule", s->rule.ptr ? s->rule.ptr->nr : -1);
  972         nvlist_add_number(nvl, "anchor",
  973             s->anchor.ptr ? s->anchor.ptr->nr : -1);
  974         nvlist_add_number(nvl, "nat_rule",
  975             s->nat_rule.ptr ? s->nat_rule.ptr->nr : -1);
  976         nvlist_add_number(nvl, "creation", s->creation);
  977 
  978         expire = pf_state_expires(s);
  979         if (expire <= time_uptime)
  980                 expire = 0;
  981         else
  982                 expire = expire - time_uptime;
  983         nvlist_add_number(nvl, "expire", expire);
  984 
  985         for (int i = 0; i < 2; i++) {
  986                 nvlist_append_number_array(nvl, "packets",
  987                     s->packets[i]);
  988                 nvlist_append_number_array(nvl, "bytes",
  989                     s->bytes[i]);
  990         }
  991 
  992         nvlist_add_number(nvl, "creatorid", s->creatorid);
  993         nvlist_add_number(nvl, "direction", s->direction);
  994         nvlist_add_number(nvl, "state_flags", s->state_flags);
  995         if (s->src_node)
  996                 flags |= PFSYNC_FLAG_SRCNODE;
  997         if (s->nat_src_node)
  998                 flags |= PFSYNC_FLAG_NATSRCNODE;
  999         nvlist_add_number(nvl, "sync_flags", flags);
 1000 
 1001         return (nvl);
 1002 
 1003 errout:
 1004         nvlist_destroy(nvl);
 1005         return (NULL);
 1006 }
 1007 
 1008 static int
 1009 pf_nveth_rule_addr_to_keth_rule_addr(const nvlist_t *nvl,
 1010     struct pf_keth_rule_addr *krule)
 1011 {
 1012         static const u_int8_t EMPTY_MAC[ETHER_ADDR_LEN] = { 0 };
 1013         int error = 0;
 1014 
 1015         PFNV_CHK(pf_nvbinary(nvl, "addr", &krule->addr, sizeof(krule->addr)));
 1016         PFNV_CHK(pf_nvbool(nvl, "neg", &krule->neg));
 1017         if (nvlist_exists_binary(nvl, "mask"))
 1018                 PFNV_CHK(pf_nvbinary(nvl, "mask", &krule->mask,
 1019                     sizeof(krule->mask)));
 1020 
 1021         /* To make checks for 'is this address set?' easier. */
 1022         if (memcmp(krule->addr, EMPTY_MAC, ETHER_ADDR_LEN) != 0)
 1023                 krule->isset = 1;
 1024 
 1025 errout:
 1026         return (error);
 1027 }
 1028 
 1029 static nvlist_t*
 1030 pf_keth_rule_addr_to_nveth_rule_addr(const struct pf_keth_rule_addr *krule)
 1031 {
 1032         nvlist_t *nvl;
 1033 
 1034         nvl = nvlist_create(0);
 1035         if (nvl == NULL)
 1036                 return (NULL);
 1037 
 1038         nvlist_add_binary(nvl, "addr", &krule->addr, sizeof(krule->addr));
 1039         nvlist_add_binary(nvl, "mask", &krule->mask, sizeof(krule->mask));
 1040         nvlist_add_bool(nvl, "neg", krule->neg);
 1041 
 1042         return (nvl);
 1043 }
 1044 
 1045 nvlist_t*
 1046 pf_keth_rule_to_nveth_rule(const struct pf_keth_rule *krule)
 1047 {
 1048         nvlist_t *nvl, *addr;
 1049 
 1050         nvl = nvlist_create(0);
 1051         if (nvl == NULL)
 1052                 return (NULL);
 1053 
 1054         nvlist_add_number(nvl, "nr", krule->nr);
 1055         nvlist_add_bool(nvl, "quick", krule->quick);
 1056         nvlist_add_string(nvl, "ifname", krule->ifname);
 1057         nvlist_add_bool(nvl, "ifnot", krule->ifnot);
 1058         nvlist_add_number(nvl, "direction", krule->direction);
 1059         nvlist_add_number(nvl, "proto", krule->proto);
 1060         nvlist_add_string(nvl, "match_tagname", krule->match_tagname);
 1061         nvlist_add_number(nvl, "match_tag", krule->match_tag);
 1062         nvlist_add_bool(nvl, "match_tag_not", krule->match_tag_not);
 1063 
 1064         addr = pf_keth_rule_addr_to_nveth_rule_addr(&krule->src);
 1065         if (addr == NULL) {
 1066                 nvlist_destroy(nvl);
 1067                 return (NULL);
 1068         }
 1069         nvlist_add_nvlist(nvl, "src", addr);
 1070         nvlist_destroy(addr);
 1071 
 1072         addr = pf_keth_rule_addr_to_nveth_rule_addr(&krule->dst);
 1073         if (addr == NULL) {
 1074                 nvlist_destroy(nvl);
 1075                 return (NULL);
 1076         }
 1077         nvlist_add_nvlist(nvl, "dst", addr);
 1078         nvlist_destroy(addr);
 1079 
 1080         addr = pf_rule_addr_to_nvrule_addr(&krule->ipsrc);
 1081         if (addr == NULL) {
 1082                 nvlist_destroy(nvl);
 1083                 return (NULL);
 1084         }
 1085         nvlist_add_nvlist(nvl, "ipsrc", addr);
 1086         nvlist_destroy(addr);
 1087 
 1088         addr = pf_rule_addr_to_nvrule_addr(&krule->ipdst);
 1089         if (addr == NULL) {
 1090                 nvlist_destroy(nvl);
 1091                 return (NULL);
 1092         }
 1093         nvlist_add_nvlist(nvl, "ipdst", addr);
 1094         nvlist_destroy(addr);
 1095 
 1096         nvlist_add_number(nvl, "evaluations",
 1097             counter_u64_fetch(krule->evaluations));
 1098         nvlist_add_number(nvl, "packets-in",
 1099             counter_u64_fetch(krule->packets[0]));
 1100         nvlist_add_number(nvl, "packets-out",
 1101             counter_u64_fetch(krule->packets[1]));
 1102         nvlist_add_number(nvl, "bytes-in",
 1103             counter_u64_fetch(krule->bytes[0]));
 1104         nvlist_add_number(nvl, "bytes-out",
 1105             counter_u64_fetch(krule->bytes[1]));
 1106 
 1107         nvlist_add_number(nvl, "timestamp", pf_get_timestamp(krule));
 1108         nvlist_add_string(nvl, "qname", krule->qname);
 1109         nvlist_add_string(nvl, "tagname", krule->tagname);
 1110 
 1111         nvlist_add_number(nvl, "dnpipe", krule->dnpipe);
 1112         nvlist_add_number(nvl, "dnflags", krule->dnflags);
 1113 
 1114         nvlist_add_number(nvl, "anchor_relative", krule->anchor_relative);
 1115         nvlist_add_number(nvl, "anchor_wildcard", krule->anchor_wildcard);
 1116 
 1117         nvlist_add_string(nvl, "bridge_to", krule->bridge_to_name);
 1118         nvlist_add_number(nvl, "action", krule->action);
 1119 
 1120         return (nvl);
 1121 }
 1122 
 1123 int
 1124 pf_nveth_rule_to_keth_rule(const nvlist_t *nvl,
 1125     struct pf_keth_rule *krule)
 1126 {
 1127         int error = 0;
 1128 
 1129         bzero(krule, sizeof(*krule));
 1130 
 1131         PFNV_CHK(pf_nvuint32(nvl, "nr", &krule->nr));
 1132         PFNV_CHK(pf_nvbool(nvl, "quick", &krule->quick));
 1133         PFNV_CHK(pf_nvstring(nvl, "ifname", krule->ifname,
 1134             sizeof(krule->ifname)));
 1135         PFNV_CHK(pf_nvbool(nvl, "ifnot", &krule->ifnot));
 1136         PFNV_CHK(pf_nvuint8(nvl, "direction", &krule->direction));
 1137         PFNV_CHK(pf_nvuint16(nvl, "proto", &krule->proto));
 1138 
 1139         if (nvlist_exists_nvlist(nvl, "src")) {
 1140                 error = pf_nveth_rule_addr_to_keth_rule_addr(
 1141                     nvlist_get_nvlist(nvl, "src"), &krule->src);
 1142                 if (error)
 1143                         return (error);
 1144         }
 1145         if (nvlist_exists_nvlist(nvl, "dst")) {
 1146                 error = pf_nveth_rule_addr_to_keth_rule_addr(
 1147                     nvlist_get_nvlist(nvl, "dst"), &krule->dst);
 1148                 if (error)
 1149                         return (error);
 1150         }
 1151 
 1152         if (nvlist_exists_nvlist(nvl, "ipsrc")) {
 1153                 error = pf_nvrule_addr_to_rule_addr(
 1154                     nvlist_get_nvlist(nvl, "ipsrc"), &krule->ipsrc);
 1155                 if (error != 0)
 1156                         return (error);
 1157 
 1158                 if (krule->ipsrc.addr.type != PF_ADDR_ADDRMASK &&
 1159                     krule->ipsrc.addr.type != PF_ADDR_TABLE)
 1160                         return (EINVAL);
 1161         }
 1162 
 1163         if (nvlist_exists_nvlist(nvl, "ipdst")) {
 1164                 error = pf_nvrule_addr_to_rule_addr(
 1165                     nvlist_get_nvlist(nvl, "ipdst"), &krule->ipdst);
 1166                 if (error != 0)
 1167                         return (error);
 1168 
 1169                 if (krule->ipdst.addr.type != PF_ADDR_ADDRMASK &&
 1170                     krule->ipdst.addr.type != PF_ADDR_TABLE)
 1171                         return (EINVAL);
 1172         }
 1173 
 1174         if (nvlist_exists_string(nvl, "match_tagname")) {
 1175                 PFNV_CHK(pf_nvstring(nvl, "match_tagname", krule->match_tagname,
 1176                     sizeof(krule->match_tagname)));
 1177                 PFNV_CHK(pf_nvbool(nvl, "match_tag_not", &krule->match_tag_not));
 1178         }
 1179 
 1180         PFNV_CHK(pf_nvstring(nvl, "qname", krule->qname, sizeof(krule->qname)));
 1181         PFNV_CHK(pf_nvstring(nvl, "tagname", krule->tagname,
 1182             sizeof(krule->tagname)));
 1183 
 1184         PFNV_CHK(pf_nvuint16_opt(nvl, "dnpipe", &krule->dnpipe, 0));
 1185         PFNV_CHK(pf_nvuint32_opt(nvl, "dnflags", &krule->dnflags, 0));
 1186         PFNV_CHK(pf_nvstring(nvl, "bridge_to", krule->bridge_to_name,
 1187             sizeof(krule->bridge_to_name)));
 1188 
 1189         PFNV_CHK(pf_nvuint8(nvl, "action", &krule->action));
 1190 
 1191         if (krule->action != PF_PASS && krule->action != PF_DROP &&
 1192             krule->action != PF_MATCH)
 1193                 return (EBADMSG);
 1194 
 1195 errout:
 1196         return (error);
 1197 }

Cache object: 7ae66e7ad3a341ed63b2faa2f2c91393


[ 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.