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_nvbinary(const nvlist_t *nvl, const char *name, void *data, 104 size_t expected_size) 105 { 106 const uint8_t *nvdata; 107 size_t len; 108 109 bzero(data, expected_size); 110 111 if (! nvlist_exists_binary(nvl, name)) 112 return (EINVAL); 113 114 nvdata = (const uint8_t *)nvlist_get_binary(nvl, name, &len); 115 if (len > expected_size) 116 return (EINVAL); 117 118 memcpy(data, nvdata, len); 119 120 return (0); 121 } 122 123 PF_NV_IMPL_UINT(uint8, uint8_t, UINT8_MAX); 124 PF_NV_IMPL_UINT(uint16, uint16_t, UINT16_MAX); 125 PF_NV_IMPL_UINT(uint32, uint32_t, UINT32_MAX); 126 PF_NV_IMPL_UINT(uint64, uint64_t, UINT64_MAX); 127 128 int 129 pf_nvint(const nvlist_t *nvl, const char *name, int *val) 130 { 131 int64_t raw; 132 133 if (! nvlist_exists_number(nvl, name)) 134 return (EINVAL); 135 136 raw = nvlist_get_number(nvl, name); 137 if (raw > INT_MAX || raw < INT_MIN) 138 return (ERANGE); 139 140 *val = (int)raw; 141 142 return (0); 143 } 144 145 int 146 pf_nvstring(const nvlist_t *nvl, const char *name, char *str, size_t maxlen) 147 { 148 int ret; 149 150 if (! nvlist_exists_string(nvl, name)) 151 return (EINVAL); 152 153 ret = strlcpy(str, nvlist_get_string(nvl, name), maxlen); 154 if (ret >= maxlen) 155 return (EINVAL); 156 157 return (0); 158 } 159 160 static int 161 pf_nvaddr_to_addr(const nvlist_t *nvl, struct pf_addr *paddr) 162 { 163 return (pf_nvbinary(nvl, "addr", paddr, sizeof(*paddr))); 164 } 165 166 static nvlist_t * 167 pf_addr_to_nvaddr(const struct pf_addr *paddr) 168 { 169 nvlist_t *nvl; 170 171 nvl = nvlist_create(0); 172 if (nvl == NULL) 173 return (NULL); 174 175 nvlist_add_binary(nvl, "addr", paddr, sizeof(*paddr)); 176 177 return (nvl); 178 } 179 180 static int 181 pf_nvmape_to_mape(const nvlist_t *nvl, struct pf_mape_portset *mape) 182 { 183 int error = 0; 184 185 bzero(mape, sizeof(*mape)); 186 PFNV_CHK(pf_nvuint8(nvl, "offset", &mape->offset)); 187 PFNV_CHK(pf_nvuint8(nvl, "psidlen", &mape->psidlen)); 188 PFNV_CHK(pf_nvuint16(nvl, "psid", &mape->psid)); 189 190 errout: 191 return (error); 192 } 193 194 static nvlist_t * 195 pf_mape_to_nvmape(const struct pf_mape_portset *mape) 196 { 197 nvlist_t *nvl; 198 199 nvl = nvlist_create(0); 200 if (nvl == NULL) 201 return (NULL); 202 203 nvlist_add_number(nvl, "offset", mape->offset); 204 nvlist_add_number(nvl, "psidlen", mape->psidlen); 205 nvlist_add_number(nvl, "psid", mape->psid); 206 207 return (nvl); 208 } 209 210 static int 211 pf_nvpool_to_pool(const nvlist_t *nvl, struct pf_kpool *kpool) 212 { 213 int error = 0; 214 215 bzero(kpool, sizeof(*kpool)); 216 217 PFNV_CHK(pf_nvbinary(nvl, "key", &kpool->key, sizeof(kpool->key))); 218 219 if (nvlist_exists_nvlist(nvl, "counter")) { 220 PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "counter"), 221 &kpool->counter)); 222 } 223 224 PFNV_CHK(pf_nvint(nvl, "tblidx", &kpool->tblidx)); 225 PFNV_CHK(pf_nvuint16_array(nvl, "proxy_port", kpool->proxy_port, 2, 226 NULL)); 227 PFNV_CHK(pf_nvuint8(nvl, "opts", &kpool->opts)); 228 229 if (nvlist_exists_nvlist(nvl, "mape")) { 230 PFNV_CHK(pf_nvmape_to_mape(nvlist_get_nvlist(nvl, "mape"), 231 &kpool->mape)); 232 } 233 234 errout: 235 return (error); 236 } 237 238 static nvlist_t * 239 pf_pool_to_nvpool(const struct pf_kpool *pool) 240 { 241 nvlist_t *nvl; 242 nvlist_t *tmp; 243 244 nvl = nvlist_create(0); 245 if (nvl == NULL) 246 return (NULL); 247 248 nvlist_add_binary(nvl, "key", &pool->key, sizeof(pool->key)); 249 tmp = pf_addr_to_nvaddr(&pool->counter); 250 if (tmp == NULL) 251 goto error; 252 nvlist_add_nvlist(nvl, "counter", tmp); 253 nvlist_destroy(tmp); 254 255 nvlist_add_number(nvl, "tblidx", pool->tblidx); 256 pf_uint16_array_nv(nvl, "proxy_port", pool->proxy_port, 2); 257 nvlist_add_number(nvl, "opts", pool->opts); 258 259 tmp = pf_mape_to_nvmape(&pool->mape); 260 if (tmp == NULL) 261 goto error; 262 nvlist_add_nvlist(nvl, "mape", tmp); 263 nvlist_destroy(tmp); 264 265 return (nvl); 266 267 error: 268 nvlist_destroy(nvl); 269 return (NULL); 270 } 271 272 static int 273 pf_nvaddr_wrap_to_addr_wrap(const nvlist_t *nvl, struct pf_addr_wrap *addr) 274 { 275 int error = 0; 276 277 bzero(addr, sizeof(*addr)); 278 279 PFNV_CHK(pf_nvuint8(nvl, "type", &addr->type)); 280 PFNV_CHK(pf_nvuint8(nvl, "iflags", &addr->iflags)); 281 if (addr->type == PF_ADDR_DYNIFTL) 282 PFNV_CHK(pf_nvstring(nvl, "ifname", addr->v.ifname, 283 sizeof(addr->v.ifname))); 284 if (addr->type == PF_ADDR_TABLE) 285 PFNV_CHK(pf_nvstring(nvl, "tblname", addr->v.tblname, 286 sizeof(addr->v.tblname))); 287 288 if (! nvlist_exists_nvlist(nvl, "addr")) 289 return (EINVAL); 290 PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "addr"), 291 &addr->v.a.addr)); 292 293 if (! nvlist_exists_nvlist(nvl, "mask")) 294 return (EINVAL); 295 PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "mask"), 296 &addr->v.a.mask)); 297 298 switch (addr->type) { 299 case PF_ADDR_DYNIFTL: 300 case PF_ADDR_TABLE: 301 case PF_ADDR_RANGE: 302 case PF_ADDR_ADDRMASK: 303 case PF_ADDR_NOROUTE: 304 case PF_ADDR_URPFFAILED: 305 break; 306 default: 307 return (EINVAL); 308 } 309 310 errout: 311 return (error); 312 } 313 314 static nvlist_t * 315 pf_addr_wrap_to_nvaddr_wrap(const struct pf_addr_wrap *addr) 316 { 317 nvlist_t *nvl; 318 nvlist_t *tmp; 319 320 nvl = nvlist_create(0); 321 if (nvl == NULL) 322 return (NULL); 323 324 nvlist_add_number(nvl, "type", addr->type); 325 nvlist_add_number(nvl, "iflags", addr->iflags); 326 if (addr->type == PF_ADDR_DYNIFTL) 327 nvlist_add_string(nvl, "ifname", addr->v.ifname); 328 if (addr->type == PF_ADDR_TABLE) 329 nvlist_add_string(nvl, "tblname", addr->v.tblname); 330 331 tmp = pf_addr_to_nvaddr(&addr->v.a.addr); 332 if (tmp == NULL) 333 goto error; 334 nvlist_add_nvlist(nvl, "addr", tmp); 335 nvlist_destroy(tmp); 336 tmp = pf_addr_to_nvaddr(&addr->v.a.mask); 337 if (tmp == NULL) 338 goto error; 339 nvlist_add_nvlist(nvl, "mask", tmp); 340 nvlist_destroy(tmp); 341 342 return (nvl); 343 344 error: 345 nvlist_destroy(nvl); 346 return (NULL); 347 } 348 349 static int 350 pf_validate_op(uint8_t op) 351 { 352 switch (op) { 353 case PF_OP_NONE: 354 case PF_OP_IRG: 355 case PF_OP_EQ: 356 case PF_OP_NE: 357 case PF_OP_LT: 358 case PF_OP_LE: 359 case PF_OP_GT: 360 case PF_OP_GE: 361 case PF_OP_XRG: 362 case PF_OP_RRG: 363 break; 364 default: 365 return (EINVAL); 366 } 367 368 return (0); 369 } 370 371 static int 372 pf_nvrule_addr_to_rule_addr(const nvlist_t *nvl, struct pf_rule_addr *addr) 373 { 374 int error = 0; 375 376 if (! nvlist_exists_nvlist(nvl, "addr")) 377 return (EINVAL); 378 379 PFNV_CHK(pf_nvaddr_wrap_to_addr_wrap(nvlist_get_nvlist(nvl, "addr"), 380 &addr->addr)); 381 PFNV_CHK(pf_nvuint16_array(nvl, "port", addr->port, 2, NULL)); 382 PFNV_CHK(pf_nvuint8(nvl, "neg", &addr->neg)); 383 PFNV_CHK(pf_nvuint8(nvl, "port_op", &addr->port_op)); 384 385 PFNV_CHK(pf_validate_op(addr->port_op)); 386 387 errout: 388 return (error); 389 } 390 391 static nvlist_t * 392 pf_rule_addr_to_nvrule_addr(const struct pf_rule_addr *addr) 393 { 394 nvlist_t *nvl; 395 nvlist_t *tmp; 396 397 nvl = nvlist_create(0); 398 if (nvl == NULL) 399 return (NULL); 400 401 tmp = pf_addr_wrap_to_nvaddr_wrap(&addr->addr); 402 if (tmp == NULL) 403 goto error; 404 nvlist_add_nvlist(nvl, "addr", tmp); 405 nvlist_destroy(tmp); 406 pf_uint16_array_nv(nvl, "port", addr->port, 2); 407 nvlist_add_number(nvl, "neg", addr->neg); 408 nvlist_add_number(nvl, "port_op", addr->port_op); 409 410 return (nvl); 411 412 error: 413 nvlist_destroy(nvl); 414 return (NULL); 415 } 416 417 static int 418 pf_nvrule_uid_to_rule_uid(const nvlist_t *nvl, struct pf_rule_uid *uid) 419 { 420 int error = 0; 421 422 bzero(uid, sizeof(*uid)); 423 424 PFNV_CHK(pf_nvuint32_array(nvl, "uid", uid->uid, 2, NULL)); 425 PFNV_CHK(pf_nvuint8(nvl, "op", &uid->op)); 426 427 PFNV_CHK(pf_validate_op(uid->op)); 428 429 errout: 430 return (error); 431 } 432 433 static nvlist_t * 434 pf_rule_uid_to_nvrule_uid(const struct pf_rule_uid *uid) 435 { 436 nvlist_t *nvl; 437 438 nvl = nvlist_create(0); 439 if (nvl == NULL) 440 return (NULL); 441 442 pf_uint32_array_nv(nvl, "uid", uid->uid, 2); 443 nvlist_add_number(nvl, "op", uid->op); 444 445 return (nvl); 446 } 447 448 static int 449 pf_nvrule_gid_to_rule_gid(const nvlist_t *nvl, struct pf_rule_gid *gid) 450 { 451 /* Cheat a little. These stucts are the same, other than the name of 452 * the first field. */ 453 return (pf_nvrule_uid_to_rule_uid(nvl, (struct pf_rule_uid *)gid)); 454 } 455 456 int 457 pf_check_rule_addr(const struct pf_rule_addr *addr) 458 { 459 460 switch (addr->addr.type) { 461 case PF_ADDR_ADDRMASK: 462 case PF_ADDR_NOROUTE: 463 case PF_ADDR_DYNIFTL: 464 case PF_ADDR_TABLE: 465 case PF_ADDR_URPFFAILED: 466 case PF_ADDR_RANGE: 467 break; 468 default: 469 return (EINVAL); 470 } 471 472 if (addr->addr.p.dyn != NULL) { 473 return (EINVAL); 474 } 475 476 return (0); 477 } 478 479 480 int 481 pf_nvrule_to_krule(const nvlist_t *nvl, struct pf_krule *rule) 482 { 483 int error = 0; 484 485 #define ERROUT(x) ERROUT_FUNCTION(errout, x) 486 487 PFNV_CHK(pf_nvuint32(nvl, "nr", &rule->nr)); 488 489 if (! nvlist_exists_nvlist(nvl, "src")) 490 ERROUT(EINVAL); 491 492 error = pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "src"), 493 &rule->src); 494 if (error != 0) 495 ERROUT(error); 496 497 if (! nvlist_exists_nvlist(nvl, "dst")) 498 ERROUT(EINVAL); 499 500 PFNV_CHK(pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "dst"), 501 &rule->dst)); 502 503 if (nvlist_exists_string(nvl, "label")) { 504 PFNV_CHK(pf_nvstring(nvl, "label", rule->label[0], 505 sizeof(rule->label[0]))); 506 } else if (nvlist_exists_string_array(nvl, "labels")) { 507 const char *const *strs; 508 size_t items; 509 int ret; 510 511 strs = nvlist_get_string_array(nvl, "labels", &items); 512 if (items > PF_RULE_MAX_LABEL_COUNT) 513 ERROUT(E2BIG); 514 515 for (size_t i = 0; i < items; i++) { 516 ret = strlcpy(rule->label[i], strs[i], 517 sizeof(rule->label[0])); 518 if (ret >= sizeof(rule->label[0])) 519 ERROUT(E2BIG); 520 } 521 } 522 523 PFNV_CHK(pf_nvstring(nvl, "ifname", rule->ifname, 524 sizeof(rule->ifname))); 525 PFNV_CHK(pf_nvstring(nvl, "qname", rule->qname, sizeof(rule->qname))); 526 PFNV_CHK(pf_nvstring(nvl, "pqname", rule->pqname, 527 sizeof(rule->pqname))); 528 PFNV_CHK(pf_nvstring(nvl, "tagname", rule->tagname, 529 sizeof(rule->tagname))); 530 PFNV_CHK(pf_nvuint16_opt(nvl, "dnpipe", &rule->dnpipe, 0)); 531 PFNV_CHK(pf_nvuint16_opt(nvl, "dnrpipe", &rule->dnrpipe, 0)); 532 PFNV_CHK(pf_nvuint32_opt(nvl, "dnflags", &rule->free_flags, 0)); 533 PFNV_CHK(pf_nvstring(nvl, "match_tagname", rule->match_tagname, 534 sizeof(rule->match_tagname))); 535 PFNV_CHK(pf_nvstring(nvl, "overload_tblname", rule->overload_tblname, 536 sizeof(rule->overload_tblname))); 537 538 if (! nvlist_exists_nvlist(nvl, "rpool")) 539 ERROUT(EINVAL); 540 PFNV_CHK(pf_nvpool_to_pool(nvlist_get_nvlist(nvl, "rpool"), 541 &rule->rpool)); 542 543 PFNV_CHK(pf_nvuint32(nvl, "os_fingerprint", &rule->os_fingerprint)); 544 545 PFNV_CHK(pf_nvint(nvl, "rtableid", &rule->rtableid)); 546 PFNV_CHK(pf_nvuint32_array(nvl, "timeout", rule->timeout, PFTM_MAX, NULL)); 547 PFNV_CHK(pf_nvuint32(nvl, "max_states", &rule->max_states)); 548 PFNV_CHK(pf_nvuint32(nvl, "max_src_nodes", &rule->max_src_nodes)); 549 PFNV_CHK(pf_nvuint32(nvl, "max_src_states", &rule->max_src_states)); 550 PFNV_CHK(pf_nvuint32(nvl, "max_src_conn", &rule->max_src_conn)); 551 PFNV_CHK(pf_nvuint32(nvl, "max_src_conn_rate.limit", 552 &rule->max_src_conn_rate.limit)); 553 PFNV_CHK(pf_nvuint32(nvl, "max_src_conn_rate.seconds", 554 &rule->max_src_conn_rate.seconds)); 555 PFNV_CHK(pf_nvuint32(nvl, "prob", &rule->prob)); 556 PFNV_CHK(pf_nvuint32(nvl, "cuid", &rule->cuid)); 557 PFNV_CHK(pf_nvuint32(nvl, "cpid", &rule->cpid)); 558 559 PFNV_CHK(pf_nvuint16(nvl, "return_icmp", &rule->return_icmp)); 560 PFNV_CHK(pf_nvuint16(nvl, "return_icmp6", &rule->return_icmp6)); 561 562 PFNV_CHK(pf_nvuint16(nvl, "max_mss", &rule->max_mss)); 563 PFNV_CHK(pf_nvuint16(nvl, "scrub_flags", &rule->scrub_flags)); 564 565 if (! nvlist_exists_nvlist(nvl, "uid")) 566 ERROUT(EINVAL); 567 PFNV_CHK(pf_nvrule_uid_to_rule_uid(nvlist_get_nvlist(nvl, "uid"), 568 &rule->uid)); 569 570 if (! nvlist_exists_nvlist(nvl, "gid")) 571 ERROUT(EINVAL); 572 PFNV_CHK(pf_nvrule_gid_to_rule_gid(nvlist_get_nvlist(nvl, "gid"), 573 &rule->gid)); 574 575 PFNV_CHK(pf_nvuint32(nvl, "rule_flag", &rule->rule_flag)); 576 PFNV_CHK(pf_nvuint8(nvl, "action", &rule->action)); 577 PFNV_CHK(pf_nvuint8(nvl, "direction", &rule->direction)); 578 PFNV_CHK(pf_nvuint8(nvl, "log", &rule->log)); 579 PFNV_CHK(pf_nvuint8(nvl, "logif", &rule->logif)); 580 PFNV_CHK(pf_nvuint8(nvl, "quick", &rule->quick)); 581 PFNV_CHK(pf_nvuint8(nvl, "ifnot", &rule->ifnot)); 582 PFNV_CHK(pf_nvuint8(nvl, "match_tag_not", &rule->match_tag_not)); 583 PFNV_CHK(pf_nvuint8(nvl, "natpass", &rule->natpass)); 584 585 PFNV_CHK(pf_nvuint8(nvl, "keep_state", &rule->keep_state)); 586 PFNV_CHK(pf_nvuint8(nvl, "af", &rule->af)); 587 PFNV_CHK(pf_nvuint8(nvl, "proto", &rule->proto)); 588 PFNV_CHK(pf_nvuint8(nvl, "type", &rule->type)); 589 PFNV_CHK(pf_nvuint8(nvl, "code", &rule->code)); 590 PFNV_CHK(pf_nvuint8(nvl, "flags", &rule->flags)); 591 PFNV_CHK(pf_nvuint8(nvl, "flagset", &rule->flagset)); 592 PFNV_CHK(pf_nvuint8(nvl, "min_ttl", &rule->min_ttl)); 593 PFNV_CHK(pf_nvuint8(nvl, "allow_opts", &rule->allow_opts)); 594 PFNV_CHK(pf_nvuint8(nvl, "rt", &rule->rt)); 595 PFNV_CHK(pf_nvuint8(nvl, "return_ttl", &rule->return_ttl)); 596 PFNV_CHK(pf_nvuint8(nvl, "tos", &rule->tos)); 597 PFNV_CHK(pf_nvuint8(nvl, "set_tos", &rule->set_tos)); 598 PFNV_CHK(pf_nvuint8(nvl, "anchor_relative", &rule->anchor_relative)); 599 PFNV_CHK(pf_nvuint8(nvl, "anchor_wildcard", &rule->anchor_wildcard)); 600 601 PFNV_CHK(pf_nvuint8(nvl, "flush", &rule->flush)); 602 PFNV_CHK(pf_nvuint8(nvl, "prio", &rule->prio)); 603 604 PFNV_CHK(pf_nvuint8_array(nvl, "set_prio", &rule->prio, 2, NULL)); 605 606 if (nvlist_exists_nvlist(nvl, "divert")) { 607 const nvlist_t *nvldivert = nvlist_get_nvlist(nvl, "divert"); 608 609 if (! nvlist_exists_nvlist(nvldivert, "addr")) 610 ERROUT(EINVAL); 611 PFNV_CHK(pf_nvaddr_to_addr(nvlist_get_nvlist(nvldivert, "addr"), 612 &rule->divert.addr)); 613 PFNV_CHK(pf_nvuint16(nvldivert, "port", &rule->divert.port)); 614 } 615 616 /* Validation */ 617 #ifndef INET 618 if (rule->af == AF_INET) 619 ERROUT(EAFNOSUPPORT); 620 #endif /* INET */ 621 #ifndef INET6 622 if (rule->af == AF_INET6) 623 ERROUT(EAFNOSUPPORT); 624 #endif /* INET6 */ 625 626 PFNV_CHK(pf_check_rule_addr(&rule->src)); 627 PFNV_CHK(pf_check_rule_addr(&rule->dst)); 628 629 return (0); 630 631 #undef ERROUT 632 errout: 633 return (error); 634 } 635 636 static nvlist_t * 637 pf_divert_to_nvdivert(const struct pf_krule *rule) 638 { 639 nvlist_t *nvl; 640 nvlist_t *tmp; 641 642 nvl = nvlist_create(0); 643 if (nvl == NULL) 644 return (NULL); 645 646 tmp = pf_addr_to_nvaddr(&rule->divert.addr); 647 if (tmp == NULL) 648 goto error; 649 nvlist_add_nvlist(nvl, "addr", tmp); 650 nvlist_destroy(tmp); 651 nvlist_add_number(nvl, "port", rule->divert.port); 652 653 return (nvl); 654 655 error: 656 nvlist_destroy(nvl); 657 return (NULL); 658 } 659 660 nvlist_t * 661 pf_krule_to_nvrule(struct pf_krule *rule) 662 { 663 nvlist_t *nvl, *tmp; 664 665 nvl = nvlist_create(0); 666 if (nvl == NULL) 667 return (nvl); 668 669 nvlist_add_number(nvl, "nr", rule->nr); 670 tmp = pf_rule_addr_to_nvrule_addr(&rule->src); 671 if (tmp == NULL) 672 goto error; 673 nvlist_add_nvlist(nvl, "src", tmp); 674 nvlist_destroy(tmp); 675 tmp = pf_rule_addr_to_nvrule_addr(&rule->dst); 676 if (tmp == NULL) 677 goto error; 678 nvlist_add_nvlist(nvl, "dst", tmp); 679 nvlist_destroy(tmp); 680 681 for (int i = 0; i < PF_SKIP_COUNT; i++) { 682 nvlist_append_number_array(nvl, "skip", 683 rule->skip[i].ptr ? rule->skip[i].ptr->nr : -1); 684 } 685 686 for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++) { 687 nvlist_append_string_array(nvl, "labels", rule->label[i]); 688 } 689 nvlist_add_string(nvl, "label", rule->label[0]); 690 nvlist_add_string(nvl, "ifname", rule->ifname); 691 nvlist_add_string(nvl, "qname", rule->qname); 692 nvlist_add_string(nvl, "pqname", rule->pqname); 693 nvlist_add_number(nvl, "dnpipe", rule->dnpipe); 694 nvlist_add_number(nvl, "dnrpipe", rule->dnrpipe); 695 nvlist_add_number(nvl, "dnflags", rule->free_flags); 696 nvlist_add_string(nvl, "tagname", rule->tagname); 697 nvlist_add_string(nvl, "match_tagname", rule->match_tagname); 698 nvlist_add_string(nvl, "overload_tblname", rule->overload_tblname); 699 700 tmp = pf_pool_to_nvpool(&rule->rpool); 701 if (tmp == NULL) 702 goto error; 703 nvlist_add_nvlist(nvl, "rpool", tmp); 704 nvlist_destroy(tmp); 705 706 nvlist_add_number(nvl, "evaluations", 707 pf_counter_u64_fetch(&rule->evaluations)); 708 for (int i = 0; i < 2; i++) { 709 nvlist_append_number_array(nvl, "packets", 710 pf_counter_u64_fetch(&rule->packets[i])); 711 nvlist_append_number_array(nvl, "bytes", 712 pf_counter_u64_fetch(&rule->bytes[i])); 713 } 714 715 nvlist_add_number(nvl, "os_fingerprint", rule->os_fingerprint); 716 717 nvlist_add_number(nvl, "rtableid", rule->rtableid); 718 pf_uint32_array_nv(nvl, "timeout", rule->timeout, PFTM_MAX); 719 nvlist_add_number(nvl, "max_states", rule->max_states); 720 nvlist_add_number(nvl, "max_src_nodes", rule->max_src_nodes); 721 nvlist_add_number(nvl, "max_src_states", rule->max_src_states); 722 nvlist_add_number(nvl, "max_src_conn", rule->max_src_conn); 723 nvlist_add_number(nvl, "max_src_conn_rate.limit", 724 rule->max_src_conn_rate.limit); 725 nvlist_add_number(nvl, "max_src_conn_rate.seconds", 726 rule->max_src_conn_rate.seconds); 727 nvlist_add_number(nvl, "qid", rule->qid); 728 nvlist_add_number(nvl, "pqid", rule->pqid); 729 nvlist_add_number(nvl, "prob", rule->prob); 730 nvlist_add_number(nvl, "cuid", rule->cuid); 731 nvlist_add_number(nvl, "cpid", rule->cpid); 732 733 nvlist_add_number(nvl, "states_cur", 734 counter_u64_fetch(rule->states_cur)); 735 nvlist_add_number(nvl, "states_tot", 736 counter_u64_fetch(rule->states_tot)); 737 nvlist_add_number(nvl, "src_nodes", 738 counter_u64_fetch(rule->src_nodes)); 739 740 nvlist_add_number(nvl, "return_icmp", rule->return_icmp); 741 nvlist_add_number(nvl, "return_icmp6", rule->return_icmp6); 742 743 nvlist_add_number(nvl, "max_mss", rule->max_mss); 744 nvlist_add_number(nvl, "scrub_flags", rule->scrub_flags); 745 746 tmp = pf_rule_uid_to_nvrule_uid(&rule->uid); 747 if (tmp == NULL) 748 goto error; 749 nvlist_add_nvlist(nvl, "uid", tmp); 750 nvlist_destroy(tmp); 751 tmp = pf_rule_uid_to_nvrule_uid((const struct pf_rule_uid *)&rule->gid); 752 if (tmp == NULL) 753 goto error; 754 nvlist_add_nvlist(nvl, "gid", tmp); 755 nvlist_destroy(tmp); 756 757 nvlist_add_number(nvl, "rule_flag", rule->rule_flag); 758 nvlist_add_number(nvl, "action", rule->action); 759 nvlist_add_number(nvl, "direction", rule->direction); 760 nvlist_add_number(nvl, "log", rule->log); 761 nvlist_add_number(nvl, "logif", rule->logif); 762 nvlist_add_number(nvl, "quick", rule->quick); 763 nvlist_add_number(nvl, "ifnot", rule->ifnot); 764 nvlist_add_number(nvl, "match_tag_not", rule->match_tag_not); 765 nvlist_add_number(nvl, "natpass", rule->natpass); 766 767 nvlist_add_number(nvl, "keep_state", rule->keep_state); 768 nvlist_add_number(nvl, "af", rule->af); 769 nvlist_add_number(nvl, "proto", rule->proto); 770 nvlist_add_number(nvl, "type", rule->type); 771 nvlist_add_number(nvl, "code", rule->code); 772 nvlist_add_number(nvl, "flags", rule->flags); 773 nvlist_add_number(nvl, "flagset", rule->flagset); 774 nvlist_add_number(nvl, "min_ttl", rule->min_ttl); 775 nvlist_add_number(nvl, "allow_opts", rule->allow_opts); 776 nvlist_add_number(nvl, "rt", rule->rt); 777 nvlist_add_number(nvl, "return_ttl", rule->return_ttl); 778 nvlist_add_number(nvl, "tos", rule->tos); 779 nvlist_add_number(nvl, "set_tos", rule->set_tos); 780 nvlist_add_number(nvl, "anchor_relative", rule->anchor_relative); 781 nvlist_add_number(nvl, "anchor_wildcard", rule->anchor_wildcard); 782 783 nvlist_add_number(nvl, "flush", rule->flush); 784 nvlist_add_number(nvl, "prio", rule->prio); 785 786 pf_uint8_array_nv(nvl, "set_prio", &rule->prio, 2); 787 788 tmp = pf_divert_to_nvdivert(rule); 789 if (tmp == NULL) 790 goto error; 791 nvlist_add_nvlist(nvl, "divert", tmp); 792 nvlist_destroy(tmp); 793 794 return (nvl); 795 796 error: 797 nvlist_destroy(nvl); 798 return (NULL); 799 } 800 801 static int 802 pf_nvstate_cmp_to_state_cmp(const nvlist_t *nvl, struct pf_state_cmp *cmp) 803 { 804 int error = 0; 805 806 bzero(cmp, sizeof(*cmp)); 807 808 PFNV_CHK(pf_nvuint64(nvl, "id", &cmp->id)); 809 PFNV_CHK(pf_nvuint32(nvl, "creatorid", &cmp->creatorid)); 810 PFNV_CHK(pf_nvuint8(nvl, "direction", &cmp->direction)); 811 812 errout: 813 return (error); 814 } 815 816 int 817 pf_nvstate_kill_to_kstate_kill(const nvlist_t *nvl, 818 struct pf_kstate_kill *kill) 819 { 820 int error = 0; 821 822 bzero(kill, sizeof(*kill)); 823 824 if (! nvlist_exists_nvlist(nvl, "cmp")) 825 return (EINVAL); 826 827 PFNV_CHK(pf_nvstate_cmp_to_state_cmp(nvlist_get_nvlist(nvl, "cmp"), 828 &kill->psk_pfcmp)); 829 PFNV_CHK(pf_nvuint8(nvl, "af", &kill->psk_af)); 830 PFNV_CHK(pf_nvint(nvl, "proto", &kill->psk_proto)); 831 832 if (! nvlist_exists_nvlist(nvl, "src")) 833 return (EINVAL); 834 PFNV_CHK(pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "src"), 835 &kill->psk_src)); 836 if (! nvlist_exists_nvlist(nvl, "dst")) 837 return (EINVAL); 838 PFNV_CHK(pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "dst"), 839 &kill->psk_dst)); 840 if (nvlist_exists_nvlist(nvl, "rt_addr")) { 841 PFNV_CHK(pf_nvrule_addr_to_rule_addr( 842 nvlist_get_nvlist(nvl, "rt_addr"), &kill->psk_rt_addr)); 843 } 844 845 PFNV_CHK(pf_nvstring(nvl, "ifname", kill->psk_ifname, 846 sizeof(kill->psk_ifname))); 847 PFNV_CHK(pf_nvstring(nvl, "label", kill->psk_label, 848 sizeof(kill->psk_label))); 849 if (nvlist_exists_bool(nvl, "kill_match")) 850 kill->psk_kill_match = nvlist_get_bool(nvl, "kill_match"); 851 852 errout: 853 return (error); 854 } 855 856 static nvlist_t * 857 pf_state_key_to_nvstate_key(const struct pf_state_key *key) 858 { 859 nvlist_t *nvl, *tmp; 860 861 nvl = nvlist_create(0); 862 if (nvl == NULL) 863 return (NULL); 864 865 for (int i = 0; i < 2; i++) { 866 tmp = pf_addr_to_nvaddr(&key->addr[i]); 867 if (tmp == NULL) 868 goto errout; 869 nvlist_append_nvlist_array(nvl, "addr", tmp); 870 nvlist_destroy(tmp); 871 nvlist_append_number_array(nvl, "port", key->port[i]); 872 } 873 nvlist_add_number(nvl, "af", key->af); 874 nvlist_add_number(nvl, "proto", key->proto); 875 876 return (nvl); 877 878 errout: 879 nvlist_destroy(nvl); 880 return (NULL); 881 } 882 883 static nvlist_t * 884 pf_state_peer_to_nvstate_peer(const struct pf_state_peer *peer) 885 { 886 nvlist_t *nvl; 887 888 nvl = nvlist_create(0); 889 if (nvl == NULL) 890 return (NULL); 891 892 nvlist_add_number(nvl, "seqlo", peer->seqlo); 893 nvlist_add_number(nvl, "seqhi", peer->seqhi); 894 nvlist_add_number(nvl, "seqdiff", peer->seqdiff); 895 nvlist_add_number(nvl, "state", peer->state); 896 nvlist_add_number(nvl, "wscale", peer->wscale); 897 898 return (nvl); 899 } 900 901 nvlist_t * 902 pf_state_to_nvstate(const struct pf_kstate *s) 903 { 904 nvlist_t *nvl, *tmp; 905 uint32_t expire, flags = 0; 906 907 nvl = nvlist_create(0); 908 if (nvl == NULL) 909 return (NULL); 910 911 nvlist_add_number(nvl, "id", s->id); 912 nvlist_add_string(nvl, "ifname", s->kif->pfik_name); 913 nvlist_add_string(nvl, "orig_ifname", s->orig_kif->pfik_name); 914 915 tmp = pf_state_key_to_nvstate_key(s->key[PF_SK_STACK]); 916 if (tmp == NULL) 917 goto errout; 918 nvlist_add_nvlist(nvl, "stack_key", tmp); 919 nvlist_destroy(tmp); 920 921 tmp = pf_state_key_to_nvstate_key(s->key[PF_SK_WIRE]); 922 if (tmp == NULL) 923 goto errout; 924 nvlist_add_nvlist(nvl, "wire_key", tmp); 925 nvlist_destroy(tmp); 926 927 tmp = pf_state_peer_to_nvstate_peer(&s->src); 928 if (tmp == NULL) 929 goto errout; 930 nvlist_add_nvlist(nvl, "src", tmp); 931 nvlist_destroy(tmp); 932 933 tmp = pf_state_peer_to_nvstate_peer(&s->dst); 934 if (tmp == NULL) 935 goto errout; 936 nvlist_add_nvlist(nvl, "dst", tmp); 937 nvlist_destroy(tmp); 938 939 tmp = pf_addr_to_nvaddr(&s->rt_addr); 940 if (tmp == NULL) 941 goto errout; 942 nvlist_add_nvlist(nvl, "rt_addr", tmp); 943 nvlist_destroy(tmp); 944 945 nvlist_add_number(nvl, "rule", s->rule.ptr ? s->rule.ptr->nr : -1); 946 nvlist_add_number(nvl, "anchor", 947 s->anchor.ptr ? s->anchor.ptr->nr : -1); 948 nvlist_add_number(nvl, "nat_rule", 949 s->nat_rule.ptr ? s->nat_rule.ptr->nr : -1); 950 nvlist_add_number(nvl, "creation", s->creation); 951 952 expire = pf_state_expires(s); 953 if (expire <= time_uptime) 954 expire = 0; 955 else 956 expire = expire - time_uptime; 957 nvlist_add_number(nvl, "expire", expire); 958 959 for (int i = 0; i < 2; i++) { 960 nvlist_append_number_array(nvl, "packets", 961 s->packets[i]); 962 nvlist_append_number_array(nvl, "bytes", 963 s->bytes[i]); 964 } 965 966 nvlist_add_number(nvl, "creatorid", s->creatorid); 967 nvlist_add_number(nvl, "direction", s->direction); 968 nvlist_add_number(nvl, "state_flags", s->state_flags); 969 if (s->src_node) 970 flags |= PFSYNC_FLAG_SRCNODE; 971 if (s->nat_src_node) 972 flags |= PFSYNC_FLAG_NATSRCNODE; 973 nvlist_add_number(nvl, "sync_flags", flags); 974 975 return (nvl); 976 977 errout: 978 nvlist_destroy(nvl); 979 return (NULL); 980 } 981