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