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 bzero(kpool, sizeof(*kpool)); 227 228 PFNV_CHK(pf_nvbinary(nvl, "key", &kpool->key, sizeof(kpool->key))); 229 230 if (nvlist_exists_nvlist(nvl, "counter")) { 231 PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "counter"), 232 &kpool->counter)); 233 } 234 235 PFNV_CHK(pf_nvint(nvl, "tblidx", &kpool->tblidx)); 236 PFNV_CHK(pf_nvuint16_array(nvl, "proxy_port", kpool->proxy_port, 2, 237 NULL)); 238 PFNV_CHK(pf_nvuint8(nvl, "opts", &kpool->opts)); 239 240 if (nvlist_exists_nvlist(nvl, "mape")) { 241 PFNV_CHK(pf_nvmape_to_mape(nvlist_get_nvlist(nvl, "mape"), 242 &kpool->mape)); 243 } 244 245 errout: 246 return (error); 247 } 248 249 static nvlist_t * 250 pf_pool_to_nvpool(const struct pf_kpool *pool) 251 { 252 nvlist_t *nvl; 253 nvlist_t *tmp; 254 255 nvl = nvlist_create(0); 256 if (nvl == NULL) 257 return (NULL); 258 259 nvlist_add_binary(nvl, "key", &pool->key, sizeof(pool->key)); 260 tmp = pf_addr_to_nvaddr(&pool->counter); 261 if (tmp == NULL) 262 goto error; 263 nvlist_add_nvlist(nvl, "counter", tmp); 264 nvlist_destroy(tmp); 265 266 nvlist_add_number(nvl, "tblidx", pool->tblidx); 267 pf_uint16_array_nv(nvl, "proxy_port", pool->proxy_port, 2); 268 nvlist_add_number(nvl, "opts", pool->opts); 269 270 tmp = pf_mape_to_nvmape(&pool->mape); 271 if (tmp == NULL) 272 goto error; 273 nvlist_add_nvlist(nvl, "mape", tmp); 274 nvlist_destroy(tmp); 275 276 return (nvl); 277 278 error: 279 nvlist_destroy(nvl); 280 return (NULL); 281 } 282 283 static int 284 pf_nvaddr_wrap_to_addr_wrap(const nvlist_t *nvl, struct pf_addr_wrap *addr) 285 { 286 int error = 0; 287 288 bzero(addr, sizeof(*addr)); 289 290 PFNV_CHK(pf_nvuint8(nvl, "type", &addr->type)); 291 PFNV_CHK(pf_nvuint8(nvl, "iflags", &addr->iflags)); 292 if (addr->type == PF_ADDR_DYNIFTL) 293 PFNV_CHK(pf_nvstring(nvl, "ifname", addr->v.ifname, 294 sizeof(addr->v.ifname))); 295 if (addr->type == PF_ADDR_TABLE) 296 PFNV_CHK(pf_nvstring(nvl, "tblname", addr->v.tblname, 297 sizeof(addr->v.tblname))); 298 299 if (! nvlist_exists_nvlist(nvl, "addr")) 300 return (EINVAL); 301 PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "addr"), 302 &addr->v.a.addr)); 303 304 if (! nvlist_exists_nvlist(nvl, "mask")) 305 return (EINVAL); 306 PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "mask"), 307 &addr->v.a.mask)); 308 309 switch (addr->type) { 310 case PF_ADDR_DYNIFTL: 311 case PF_ADDR_TABLE: 312 case PF_ADDR_RANGE: 313 case PF_ADDR_ADDRMASK: 314 case PF_ADDR_NOROUTE: 315 case PF_ADDR_URPFFAILED: 316 break; 317 default: 318 return (EINVAL); 319 } 320 321 errout: 322 return (error); 323 } 324 325 static nvlist_t * 326 pf_addr_wrap_to_nvaddr_wrap(const struct pf_addr_wrap *addr) 327 { 328 nvlist_t *nvl; 329 nvlist_t *tmp; 330 uint64_t num; 331 struct pfr_ktable *kt; 332 333 nvl = nvlist_create(0); 334 if (nvl == NULL) 335 return (NULL); 336 337 nvlist_add_number(nvl, "type", addr->type); 338 nvlist_add_number(nvl, "iflags", addr->iflags); 339 if (addr->type == PF_ADDR_DYNIFTL) { 340 nvlist_add_string(nvl, "ifname", addr->v.ifname); 341 num = 0; 342 if (addr->p.dyn != NULL) 343 num = addr->p.dyn->pfid_acnt4 + 344 addr->p.dyn->pfid_acnt6; 345 nvlist_add_number(nvl, "dyncnt", num); 346 } 347 if (addr->type == PF_ADDR_TABLE) { 348 nvlist_add_string(nvl, "tblname", addr->v.tblname); 349 num = -1; 350 kt = addr->p.tbl; 351 if ((kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && 352 kt->pfrkt_root != NULL) 353 kt = kt->pfrkt_root; 354 if (kt->pfrkt_flags & PFR_TFLAG_ACTIVE) 355 num = kt->pfrkt_cnt; 356 nvlist_add_number(nvl, "tblcnt", num); 357 } 358 359 tmp = pf_addr_to_nvaddr(&addr->v.a.addr); 360 if (tmp == NULL) 361 goto error; 362 nvlist_add_nvlist(nvl, "addr", tmp); 363 nvlist_destroy(tmp); 364 tmp = pf_addr_to_nvaddr(&addr->v.a.mask); 365 if (tmp == NULL) 366 goto error; 367 nvlist_add_nvlist(nvl, "mask", tmp); 368 nvlist_destroy(tmp); 369 370 return (nvl); 371 372 error: 373 nvlist_destroy(nvl); 374 return (NULL); 375 } 376 377 static int 378 pf_validate_op(uint8_t op) 379 { 380 switch (op) { 381 case PF_OP_NONE: 382 case PF_OP_IRG: 383 case PF_OP_EQ: 384 case PF_OP_NE: 385 case PF_OP_LT: 386 case PF_OP_LE: 387 case PF_OP_GT: 388 case PF_OP_GE: 389 case PF_OP_XRG: 390 case PF_OP_RRG: 391 break; 392 default: 393 return (EINVAL); 394 } 395 396 return (0); 397 } 398 399 static int 400 pf_nvrule_addr_to_rule_addr(const nvlist_t *nvl, struct pf_rule_addr *addr) 401 { 402 int error = 0; 403 404 if (! nvlist_exists_nvlist(nvl, "addr")) 405 return (EINVAL); 406 407 PFNV_CHK(pf_nvaddr_wrap_to_addr_wrap(nvlist_get_nvlist(nvl, "addr"), 408 &addr->addr)); 409 PFNV_CHK(pf_nvuint16_array(nvl, "port", addr->port, 2, NULL)); 410 PFNV_CHK(pf_nvuint8(nvl, "neg", &addr->neg)); 411 PFNV_CHK(pf_nvuint8(nvl, "port_op", &addr->port_op)); 412 413 PFNV_CHK(pf_validate_op(addr->port_op)); 414 415 errout: 416 return (error); 417 } 418 419 static nvlist_t * 420 pf_rule_addr_to_nvrule_addr(const struct pf_rule_addr *addr) 421 { 422 nvlist_t *nvl; 423 nvlist_t *tmp; 424 425 nvl = nvlist_create(0); 426 if (nvl == NULL) 427 return (NULL); 428 429 tmp = pf_addr_wrap_to_nvaddr_wrap(&addr->addr); 430 if (tmp == NULL) 431 goto error; 432 nvlist_add_nvlist(nvl, "addr", tmp); 433 nvlist_destroy(tmp); 434 pf_uint16_array_nv(nvl, "port", addr->port, 2); 435 nvlist_add_number(nvl, "neg", addr->neg); 436 nvlist_add_number(nvl, "port_op", addr->port_op); 437 438 return (nvl); 439 440 error: 441 nvlist_destroy(nvl); 442 return (NULL); 443 } 444 445 static int 446 pf_nvrule_uid_to_rule_uid(const nvlist_t *nvl, struct pf_rule_uid *uid) 447 { 448 int error = 0; 449 450 bzero(uid, sizeof(*uid)); 451 452 PFNV_CHK(pf_nvuint32_array(nvl, "uid", uid->uid, 2, NULL)); 453 PFNV_CHK(pf_nvuint8(nvl, "op", &uid->op)); 454 455 PFNV_CHK(pf_validate_op(uid->op)); 456 457 errout: 458 return (error); 459 } 460 461 static nvlist_t * 462 pf_rule_uid_to_nvrule_uid(const struct pf_rule_uid *uid) 463 { 464 nvlist_t *nvl; 465 466 nvl = nvlist_create(0); 467 if (nvl == NULL) 468 return (NULL); 469 470 pf_uint32_array_nv(nvl, "uid", uid->uid, 2); 471 nvlist_add_number(nvl, "op", uid->op); 472 473 return (nvl); 474 } 475 476 static int 477 pf_nvrule_gid_to_rule_gid(const nvlist_t *nvl, struct pf_rule_gid *gid) 478 { 479 /* Cheat a little. These stucts are the same, other than the name of 480 * the first field. */ 481 return (pf_nvrule_uid_to_rule_uid(nvl, (struct pf_rule_uid *)gid)); 482 } 483 484 int 485 pf_check_rule_addr(const struct pf_rule_addr *addr) 486 { 487 488 switch (addr->addr.type) { 489 case PF_ADDR_ADDRMASK: 490 case PF_ADDR_NOROUTE: 491 case PF_ADDR_DYNIFTL: 492 case PF_ADDR_TABLE: 493 case PF_ADDR_URPFFAILED: 494 case PF_ADDR_RANGE: 495 break; 496 default: 497 return (EINVAL); 498 } 499 500 if (addr->addr.p.dyn != NULL) { 501 return (EINVAL); 502 } 503 504 return (0); 505 } 506 507 508 int 509 pf_nvrule_to_krule(const nvlist_t *nvl, struct pf_krule *rule) 510 { 511 int error = 0; 512 513 #define ERROUT(x) ERROUT_FUNCTION(errout, x) 514 515 PFNV_CHK(pf_nvuint32(nvl, "nr", &rule->nr)); 516 517 if (! nvlist_exists_nvlist(nvl, "src")) 518 ERROUT(EINVAL); 519 520 error = pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "src"), 521 &rule->src); 522 if (error != 0) 523 ERROUT(error); 524 525 if (! nvlist_exists_nvlist(nvl, "dst")) 526 ERROUT(EINVAL); 527 528 PFNV_CHK(pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "dst"), 529 &rule->dst)); 530 531 if (nvlist_exists_string(nvl, "label")) { 532 PFNV_CHK(pf_nvstring(nvl, "label", rule->label[0], 533 sizeof(rule->label[0]))); 534 } else if (nvlist_exists_string_array(nvl, "labels")) { 535 const char *const *strs; 536 size_t items; 537 int ret; 538 539 strs = nvlist_get_string_array(nvl, "labels", &items); 540 if (items > PF_RULE_MAX_LABEL_COUNT) 541 ERROUT(E2BIG); 542 543 for (size_t i = 0; i < items; i++) { 544 ret = strlcpy(rule->label[i], strs[i], 545 sizeof(rule->label[0])); 546 if (ret >= sizeof(rule->label[0])) 547 ERROUT(E2BIG); 548 } 549 } 550 551 PFNV_CHK(pf_nvuint32_opt(nvl, "ridentifier", &rule->ridentifier, 0)); 552 PFNV_CHK(pf_nvstring(nvl, "ifname", rule->ifname, 553 sizeof(rule->ifname))); 554 PFNV_CHK(pf_nvstring(nvl, "qname", rule->qname, sizeof(rule->qname))); 555 PFNV_CHK(pf_nvstring(nvl, "pqname", rule->pqname, 556 sizeof(rule->pqname))); 557 PFNV_CHK(pf_nvstring(nvl, "tagname", rule->tagname, 558 sizeof(rule->tagname))); 559 PFNV_CHK(pf_nvuint16_opt(nvl, "dnpipe", &rule->dnpipe, 0)); 560 PFNV_CHK(pf_nvuint16_opt(nvl, "dnrpipe", &rule->dnrpipe, 0)); 561 PFNV_CHK(pf_nvuint32_opt(nvl, "dnflags", &rule->free_flags, 0)); 562 PFNV_CHK(pf_nvstring(nvl, "match_tagname", rule->match_tagname, 563 sizeof(rule->match_tagname))); 564 PFNV_CHK(pf_nvstring(nvl, "overload_tblname", rule->overload_tblname, 565 sizeof(rule->overload_tblname))); 566 567 if (! nvlist_exists_nvlist(nvl, "rpool")) 568 ERROUT(EINVAL); 569 PFNV_CHK(pf_nvpool_to_pool(nvlist_get_nvlist(nvl, "rpool"), 570 &rule->rpool)); 571 572 PFNV_CHK(pf_nvuint32(nvl, "os_fingerprint", &rule->os_fingerprint)); 573 574 PFNV_CHK(pf_nvint(nvl, "rtableid", &rule->rtableid)); 575 PFNV_CHK(pf_nvuint32_array(nvl, "timeout", rule->timeout, PFTM_MAX, NULL)); 576 PFNV_CHK(pf_nvuint32(nvl, "max_states", &rule->max_states)); 577 PFNV_CHK(pf_nvuint32(nvl, "max_src_nodes", &rule->max_src_nodes)); 578 PFNV_CHK(pf_nvuint32(nvl, "max_src_states", &rule->max_src_states)); 579 PFNV_CHK(pf_nvuint32(nvl, "max_src_conn", &rule->max_src_conn)); 580 PFNV_CHK(pf_nvuint32(nvl, "max_src_conn_rate.limit", 581 &rule->max_src_conn_rate.limit)); 582 PFNV_CHK(pf_nvuint32(nvl, "max_src_conn_rate.seconds", 583 &rule->max_src_conn_rate.seconds)); 584 PFNV_CHK(pf_nvuint32(nvl, "prob", &rule->prob)); 585 PFNV_CHK(pf_nvuint32(nvl, "cuid", &rule->cuid)); 586 PFNV_CHK(pf_nvuint32(nvl, "cpid", &rule->cpid)); 587 588 PFNV_CHK(pf_nvuint16(nvl, "return_icmp", &rule->return_icmp)); 589 PFNV_CHK(pf_nvuint16(nvl, "return_icmp6", &rule->return_icmp6)); 590 591 PFNV_CHK(pf_nvuint16(nvl, "max_mss", &rule->max_mss)); 592 PFNV_CHK(pf_nvuint16(nvl, "scrub_flags", &rule->scrub_flags)); 593 594 if (! nvlist_exists_nvlist(nvl, "uid")) 595 ERROUT(EINVAL); 596 PFNV_CHK(pf_nvrule_uid_to_rule_uid(nvlist_get_nvlist(nvl, "uid"), 597 &rule->uid)); 598 599 if (! nvlist_exists_nvlist(nvl, "gid")) 600 ERROUT(EINVAL); 601 PFNV_CHK(pf_nvrule_gid_to_rule_gid(nvlist_get_nvlist(nvl, "gid"), 602 &rule->gid)); 603 604 PFNV_CHK(pf_nvuint32(nvl, "rule_flag", &rule->rule_flag)); 605 PFNV_CHK(pf_nvuint8(nvl, "action", &rule->action)); 606 PFNV_CHK(pf_nvuint8(nvl, "direction", &rule->direction)); 607 PFNV_CHK(pf_nvuint8(nvl, "log", &rule->log)); 608 PFNV_CHK(pf_nvuint8(nvl, "logif", &rule->logif)); 609 PFNV_CHK(pf_nvuint8(nvl, "quick", &rule->quick)); 610 PFNV_CHK(pf_nvuint8(nvl, "ifnot", &rule->ifnot)); 611 PFNV_CHK(pf_nvuint8(nvl, "match_tag_not", &rule->match_tag_not)); 612 PFNV_CHK(pf_nvuint8(nvl, "natpass", &rule->natpass)); 613 614 PFNV_CHK(pf_nvuint8(nvl, "keep_state", &rule->keep_state)); 615 PFNV_CHK(pf_nvuint8(nvl, "af", &rule->af)); 616 PFNV_CHK(pf_nvuint8(nvl, "proto", &rule->proto)); 617 PFNV_CHK(pf_nvuint8(nvl, "type", &rule->type)); 618 PFNV_CHK(pf_nvuint8(nvl, "code", &rule->code)); 619 PFNV_CHK(pf_nvuint8(nvl, "flags", &rule->flags)); 620 PFNV_CHK(pf_nvuint8(nvl, "flagset", &rule->flagset)); 621 PFNV_CHK(pf_nvuint8(nvl, "min_ttl", &rule->min_ttl)); 622 PFNV_CHK(pf_nvuint8(nvl, "allow_opts", &rule->allow_opts)); 623 PFNV_CHK(pf_nvuint8(nvl, "rt", &rule->rt)); 624 PFNV_CHK(pf_nvuint8(nvl, "return_ttl", &rule->return_ttl)); 625 PFNV_CHK(pf_nvuint8(nvl, "tos", &rule->tos)); 626 PFNV_CHK(pf_nvuint8(nvl, "set_tos", &rule->set_tos)); 627 628 PFNV_CHK(pf_nvuint8(nvl, "flush", &rule->flush)); 629 PFNV_CHK(pf_nvuint8(nvl, "prio", &rule->prio)); 630 631 PFNV_CHK(pf_nvuint8_array(nvl, "set_prio", &rule->prio, 2, NULL)); 632 633 if (nvlist_exists_nvlist(nvl, "divert")) { 634 const nvlist_t *nvldivert = nvlist_get_nvlist(nvl, "divert"); 635 636 if (! nvlist_exists_nvlist(nvldivert, "addr")) 637 ERROUT(EINVAL); 638 PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvldivert, "addr"), 639 &rule->divert.addr)); 640 PFNV_CHK(pf_nvuint16(nvldivert, "port", &rule->divert.port)); 641 } 642 643 /* Validation */ 644 #ifndef INET 645 if (rule->af == AF_INET) 646 ERROUT(EAFNOSUPPORT); 647 #endif /* INET */ 648 #ifndef INET6 649 if (rule->af == AF_INET6) 650 ERROUT(EAFNOSUPPORT); 651 #endif /* INET6 */ 652 653 PFNV_CHK(pf_check_rule_addr(&rule->src)); 654 PFNV_CHK(pf_check_rule_addr(&rule->dst)); 655 656 return (0); 657 658 #undef ERROUT 659 errout: 660 return (error); 661 } 662 663 static nvlist_t * 664 pf_divert_to_nvdivert(const struct pf_krule *rule) 665 { 666 nvlist_t *nvl; 667 nvlist_t *tmp; 668 669 nvl = nvlist_create(0); 670 if (nvl == NULL) 671 return (NULL); 672 673 tmp = pf_addr_to_nvaddr(&rule->divert.addr); 674 if (tmp == NULL) 675 goto error; 676 nvlist_add_nvlist(nvl, "addr", tmp); 677 nvlist_destroy(tmp); 678 nvlist_add_number(nvl, "port", rule->divert.port); 679 680 return (nvl); 681 682 error: 683 nvlist_destroy(nvl); 684 return (NULL); 685 } 686 687 nvlist_t * 688 pf_krule_to_nvrule(struct pf_krule *rule) 689 { 690 nvlist_t *nvl, *tmp; 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].ptr ? rule->skip[i].ptr->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->rpool); 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 743 nvlist_add_number(nvl, "os_fingerprint", rule->os_fingerprint); 744 745 nvlist_add_number(nvl, "rtableid", rule->rtableid); 746 pf_uint32_array_nv(nvl, "timeout", rule->timeout, PFTM_MAX); 747 nvlist_add_number(nvl, "max_states", rule->max_states); 748 nvlist_add_number(nvl, "max_src_nodes", rule->max_src_nodes); 749 nvlist_add_number(nvl, "max_src_states", rule->max_src_states); 750 nvlist_add_number(nvl, "max_src_conn", rule->max_src_conn); 751 nvlist_add_number(nvl, "max_src_conn_rate.limit", 752 rule->max_src_conn_rate.limit); 753 nvlist_add_number(nvl, "max_src_conn_rate.seconds", 754 rule->max_src_conn_rate.seconds); 755 nvlist_add_number(nvl, "qid", rule->qid); 756 nvlist_add_number(nvl, "pqid", rule->pqid); 757 nvlist_add_number(nvl, "prob", rule->prob); 758 nvlist_add_number(nvl, "cuid", rule->cuid); 759 nvlist_add_number(nvl, "cpid", rule->cpid); 760 761 nvlist_add_number(nvl, "states_cur", 762 counter_u64_fetch(rule->states_cur)); 763 nvlist_add_number(nvl, "states_tot", 764 counter_u64_fetch(rule->states_tot)); 765 nvlist_add_number(nvl, "src_nodes", 766 counter_u64_fetch(rule->src_nodes)); 767 768 nvlist_add_number(nvl, "return_icmp", rule->return_icmp); 769 nvlist_add_number(nvl, "return_icmp6", rule->return_icmp6); 770 771 nvlist_add_number(nvl, "max_mss", rule->max_mss); 772 nvlist_add_number(nvl, "scrub_flags", rule->scrub_flags); 773 774 tmp = pf_rule_uid_to_nvrule_uid(&rule->uid); 775 if (tmp == NULL) 776 goto error; 777 nvlist_add_nvlist(nvl, "uid", tmp); 778 nvlist_destroy(tmp); 779 tmp = pf_rule_uid_to_nvrule_uid((const struct pf_rule_uid *)&rule->gid); 780 if (tmp == NULL) 781 goto error; 782 nvlist_add_nvlist(nvl, "gid", tmp); 783 nvlist_destroy(tmp); 784 785 nvlist_add_number(nvl, "rule_flag", rule->rule_flag); 786 nvlist_add_number(nvl, "action", rule->action); 787 nvlist_add_number(nvl, "direction", rule->direction); 788 nvlist_add_number(nvl, "log", rule->log); 789 nvlist_add_number(nvl, "logif", rule->logif); 790 nvlist_add_number(nvl, "quick", rule->quick); 791 nvlist_add_number(nvl, "ifnot", rule->ifnot); 792 nvlist_add_number(nvl, "match_tag_not", rule->match_tag_not); 793 nvlist_add_number(nvl, "natpass", rule->natpass); 794 795 nvlist_add_number(nvl, "keep_state", rule->keep_state); 796 nvlist_add_number(nvl, "af", rule->af); 797 nvlist_add_number(nvl, "proto", rule->proto); 798 nvlist_add_number(nvl, "type", rule->type); 799 nvlist_add_number(nvl, "code", rule->code); 800 nvlist_add_number(nvl, "flags", rule->flags); 801 nvlist_add_number(nvl, "flagset", rule->flagset); 802 nvlist_add_number(nvl, "min_ttl", rule->min_ttl); 803 nvlist_add_number(nvl, "allow_opts", rule->allow_opts); 804 nvlist_add_number(nvl, "rt", rule->rt); 805 nvlist_add_number(nvl, "return_ttl", rule->return_ttl); 806 nvlist_add_number(nvl, "tos", rule->tos); 807 nvlist_add_number(nvl, "set_tos", rule->set_tos); 808 nvlist_add_number(nvl, "anchor_relative", rule->anchor_relative); 809 nvlist_add_number(nvl, "anchor_wildcard", rule->anchor_wildcard); 810 811 nvlist_add_number(nvl, "flush", rule->flush); 812 nvlist_add_number(nvl, "prio", rule->prio); 813 814 pf_uint8_array_nv(nvl, "set_prio", &rule->prio, 2); 815 816 tmp = pf_divert_to_nvdivert(rule); 817 if (tmp == NULL) 818 goto error; 819 nvlist_add_nvlist(nvl, "divert", tmp); 820 nvlist_destroy(tmp); 821 822 return (nvl); 823 824 error: 825 nvlist_destroy(nvl); 826 return (NULL); 827 } 828 829 static int 830 pf_nvstate_cmp_to_state_cmp(const nvlist_t *nvl, struct pf_state_cmp *cmp) 831 { 832 int error = 0; 833 834 bzero(cmp, sizeof(*cmp)); 835 836 PFNV_CHK(pf_nvuint64(nvl, "id", &cmp->id)); 837 PFNV_CHK(pf_nvuint32(nvl, "creatorid", &cmp->creatorid)); 838 PFNV_CHK(pf_nvuint8(nvl, "direction", &cmp->direction)); 839 840 errout: 841 return (error); 842 } 843 844 int 845 pf_nvstate_kill_to_kstate_kill(const nvlist_t *nvl, 846 struct pf_kstate_kill *kill) 847 { 848 int error = 0; 849 850 bzero(kill, sizeof(*kill)); 851 852 if (! nvlist_exists_nvlist(nvl, "cmp")) 853 return (EINVAL); 854 855 PFNV_CHK(pf_nvstate_cmp_to_state_cmp(nvlist_get_nvlist(nvl, "cmp"), 856 &kill->psk_pfcmp)); 857 PFNV_CHK(pf_nvuint8(nvl, "af", &kill->psk_af)); 858 PFNV_CHK(pf_nvint(nvl, "proto", &kill->psk_proto)); 859 860 if (! nvlist_exists_nvlist(nvl, "src")) 861 return (EINVAL); 862 PFNV_CHK(pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "src"), 863 &kill->psk_src)); 864 if (! nvlist_exists_nvlist(nvl, "dst")) 865 return (EINVAL); 866 PFNV_CHK(pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "dst"), 867 &kill->psk_dst)); 868 if (nvlist_exists_nvlist(nvl, "rt_addr")) { 869 PFNV_CHK(pf_nvrule_addr_to_rule_addr( 870 nvlist_get_nvlist(nvl, "rt_addr"), &kill->psk_rt_addr)); 871 } 872 873 PFNV_CHK(pf_nvstring(nvl, "ifname", kill->psk_ifname, 874 sizeof(kill->psk_ifname))); 875 PFNV_CHK(pf_nvstring(nvl, "label", kill->psk_label, 876 sizeof(kill->psk_label))); 877 PFNV_CHK(pf_nvbool(nvl, "kill_match", &kill->psk_kill_match)); 878 879 errout: 880 return (error); 881 } 882 883 static nvlist_t * 884 pf_state_key_to_nvstate_key(const struct pf_state_key *key) 885 { 886 nvlist_t *nvl, *tmp; 887 888 nvl = nvlist_create(0); 889 if (nvl == NULL) 890 return (NULL); 891 892 for (int i = 0; i < 2; i++) { 893 tmp = pf_addr_to_nvaddr(&key->addr[i]); 894 if (tmp == NULL) 895 goto errout; 896 nvlist_append_nvlist_array(nvl, "addr", tmp); 897 nvlist_destroy(tmp); 898 nvlist_append_number_array(nvl, "port", key->port[i]); 899 } 900 nvlist_add_number(nvl, "af", key->af); 901 nvlist_add_number(nvl, "proto", key->proto); 902 903 return (nvl); 904 905 errout: 906 nvlist_destroy(nvl); 907 return (NULL); 908 } 909 910 static nvlist_t * 911 pf_state_peer_to_nvstate_peer(const struct pf_state_peer *peer) 912 { 913 nvlist_t *nvl; 914 915 nvl = nvlist_create(0); 916 if (nvl == NULL) 917 return (NULL); 918 919 nvlist_add_number(nvl, "seqlo", peer->seqlo); 920 nvlist_add_number(nvl, "seqhi", peer->seqhi); 921 nvlist_add_number(nvl, "seqdiff", peer->seqdiff); 922 nvlist_add_number(nvl, "state", peer->state); 923 nvlist_add_number(nvl, "wscale", peer->wscale); 924 925 return (nvl); 926 } 927 928 nvlist_t * 929 pf_state_to_nvstate(const struct pf_kstate *s) 930 { 931 nvlist_t *nvl, *tmp; 932 uint32_t expire, flags = 0; 933 934 nvl = nvlist_create(0); 935 if (nvl == NULL) 936 return (NULL); 937 938 nvlist_add_number(nvl, "id", s->id); 939 nvlist_add_string(nvl, "ifname", s->kif->pfik_name); 940 nvlist_add_string(nvl, "orig_ifname", s->orig_kif->pfik_name); 941 942 tmp = pf_state_key_to_nvstate_key(s->key[PF_SK_STACK]); 943 if (tmp == NULL) 944 goto errout; 945 nvlist_add_nvlist(nvl, "stack_key", tmp); 946 nvlist_destroy(tmp); 947 948 tmp = pf_state_key_to_nvstate_key(s->key[PF_SK_WIRE]); 949 if (tmp == NULL) 950 goto errout; 951 nvlist_add_nvlist(nvl, "wire_key", tmp); 952 nvlist_destroy(tmp); 953 954 tmp = pf_state_peer_to_nvstate_peer(&s->src); 955 if (tmp == NULL) 956 goto errout; 957 nvlist_add_nvlist(nvl, "src", tmp); 958 nvlist_destroy(tmp); 959 960 tmp = pf_state_peer_to_nvstate_peer(&s->dst); 961 if (tmp == NULL) 962 goto errout; 963 nvlist_add_nvlist(nvl, "dst", tmp); 964 nvlist_destroy(tmp); 965 966 tmp = pf_addr_to_nvaddr(&s->rt_addr); 967 if (tmp == NULL) 968 goto errout; 969 nvlist_add_nvlist(nvl, "rt_addr", tmp); 970 nvlist_destroy(tmp); 971 972 nvlist_add_number(nvl, "rule", s->rule.ptr ? s->rule.ptr->nr : -1); 973 nvlist_add_number(nvl, "anchor", 974 s->anchor.ptr ? s->anchor.ptr->nr : -1); 975 nvlist_add_number(nvl, "nat_rule", 976 s->nat_rule.ptr ? s->nat_rule.ptr->nr : -1); 977 nvlist_add_number(nvl, "creation", s->creation); 978 979 expire = pf_state_expires(s); 980 if (expire <= time_uptime) 981 expire = 0; 982 else 983 expire = expire - time_uptime; 984 nvlist_add_number(nvl, "expire", expire); 985 986 for (int i = 0; i < 2; i++) { 987 nvlist_append_number_array(nvl, "packets", 988 s->packets[i]); 989 nvlist_append_number_array(nvl, "bytes", 990 s->bytes[i]); 991 } 992 993 nvlist_add_number(nvl, "creatorid", s->creatorid); 994 nvlist_add_number(nvl, "direction", s->direction); 995 nvlist_add_number(nvl, "state_flags", s->state_flags); 996 if (s->src_node) 997 flags |= PFSYNC_FLAG_SRCNODE; 998 if (s->nat_src_node) 999 flags |= PFSYNC_FLAG_NATSRCNODE; 1000 nvlist_add_number(nvl, "sync_flags", flags); 1001 1002 return (nvl); 1003 1004 errout: 1005 nvlist_destroy(nvl); 1006 return (NULL); 1007 } 1008