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 1071 addr = pf_keth_rule_addr_to_nveth_rule_addr(&krule->dst); 1072 if (addr == NULL) { 1073 nvlist_destroy(nvl); 1074 return (NULL); 1075 } 1076 nvlist_add_nvlist(nvl, "dst", addr); 1077 1078 addr = pf_rule_addr_to_nvrule_addr(&krule->ipsrc); 1079 if (addr == NULL) { 1080 nvlist_destroy(nvl); 1081 return (NULL); 1082 } 1083 nvlist_add_nvlist(nvl, "ipsrc", addr); 1084 nvlist_destroy(addr); 1085 1086 addr = pf_rule_addr_to_nvrule_addr(&krule->ipdst); 1087 if (addr == NULL) { 1088 nvlist_destroy(nvl); 1089 return (NULL); 1090 } 1091 nvlist_add_nvlist(nvl, "ipdst", addr); 1092 nvlist_destroy(addr); 1093 1094 nvlist_add_number(nvl, "evaluations", 1095 counter_u64_fetch(krule->evaluations)); 1096 nvlist_add_number(nvl, "packets-in", 1097 counter_u64_fetch(krule->packets[0])); 1098 nvlist_add_number(nvl, "packets-out", 1099 counter_u64_fetch(krule->packets[1])); 1100 nvlist_add_number(nvl, "bytes-in", 1101 counter_u64_fetch(krule->bytes[0])); 1102 nvlist_add_number(nvl, "bytes-out", 1103 counter_u64_fetch(krule->bytes[1])); 1104 1105 nvlist_add_number(nvl, "timestamp", pf_get_timestamp(krule)); 1106 nvlist_add_string(nvl, "qname", krule->qname); 1107 nvlist_add_string(nvl, "tagname", krule->tagname); 1108 1109 nvlist_add_number(nvl, "dnpipe", krule->dnpipe); 1110 nvlist_add_number(nvl, "dnflags", krule->dnflags); 1111 1112 nvlist_add_number(nvl, "anchor_relative", krule->anchor_relative); 1113 nvlist_add_number(nvl, "anchor_wildcard", krule->anchor_wildcard); 1114 1115 nvlist_add_number(nvl, "action", krule->action); 1116 1117 return (nvl); 1118 } 1119 1120 int 1121 pf_nveth_rule_to_keth_rule(const nvlist_t *nvl, 1122 struct pf_keth_rule *krule) 1123 { 1124 int error = 0; 1125 1126 bzero(krule, sizeof(*krule)); 1127 1128 PFNV_CHK(pf_nvuint32(nvl, "nr", &krule->nr)); 1129 PFNV_CHK(pf_nvbool(nvl, "quick", &krule->quick)); 1130 PFNV_CHK(pf_nvstring(nvl, "ifname", krule->ifname, 1131 sizeof(krule->ifname))); 1132 PFNV_CHK(pf_nvbool(nvl, "ifnot", &krule->ifnot)); 1133 PFNV_CHK(pf_nvuint8(nvl, "direction", &krule->direction)); 1134 PFNV_CHK(pf_nvuint16(nvl, "proto", &krule->proto)); 1135 1136 if (nvlist_exists_nvlist(nvl, "src")) { 1137 error = pf_nveth_rule_addr_to_keth_rule_addr( 1138 nvlist_get_nvlist(nvl, "src"), &krule->src); 1139 if (error) 1140 return (error); 1141 } 1142 if (nvlist_exists_nvlist(nvl, "dst")) { 1143 error = pf_nveth_rule_addr_to_keth_rule_addr( 1144 nvlist_get_nvlist(nvl, "dst"), &krule->dst); 1145 if (error) 1146 return (error); 1147 } 1148 1149 if (nvlist_exists_nvlist(nvl, "ipsrc")) { 1150 error = pf_nvrule_addr_to_rule_addr( 1151 nvlist_get_nvlist(nvl, "ipsrc"), &krule->ipsrc); 1152 if (error != 0) 1153 return (error); 1154 1155 if (krule->ipsrc.addr.type != PF_ADDR_ADDRMASK && 1156 krule->ipsrc.addr.type != PF_ADDR_TABLE) 1157 return (EINVAL); 1158 } 1159 1160 if (nvlist_exists_nvlist(nvl, "ipdst")) { 1161 error = pf_nvrule_addr_to_rule_addr( 1162 nvlist_get_nvlist(nvl, "ipdst"), &krule->ipdst); 1163 if (error != 0) 1164 return (error); 1165 1166 if (krule->ipdst.addr.type != PF_ADDR_ADDRMASK && 1167 krule->ipdst.addr.type != PF_ADDR_TABLE) 1168 return (EINVAL); 1169 } 1170 1171 if (nvlist_exists_string(nvl, "match_tagname")) { 1172 PFNV_CHK(pf_nvstring(nvl, "match_tagname", krule->match_tagname, 1173 sizeof(krule->match_tagname))); 1174 PFNV_CHK(pf_nvbool(nvl, "match_tag_not", &krule->match_tag_not)); 1175 } 1176 1177 PFNV_CHK(pf_nvstring(nvl, "qname", krule->qname, sizeof(krule->qname))); 1178 PFNV_CHK(pf_nvstring(nvl, "tagname", krule->tagname, 1179 sizeof(krule->tagname))); 1180 1181 PFNV_CHK(pf_nvuint16_opt(nvl, "dnpipe", &krule->dnpipe, 0)); 1182 PFNV_CHK(pf_nvuint32_opt(nvl, "dnflags", &krule->dnflags, 0)); 1183 1184 PFNV_CHK(pf_nvuint8(nvl, "action", &krule->action)); 1185 1186 if (krule->action != PF_PASS && krule->action != PF_DROP && 1187 krule->action != PF_MATCH) 1188 return (EBADMSG); 1189 1190 errout: 1191 return (error); 1192 } 1193