1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2002 Cedric Berger 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * - Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * - Redistributions in binary form must reproduce the above 14 * copyright notice, this list of conditions and the following 15 * disclaimer in the documentation and/or other materials provided 16 * with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 28 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 * 31 * $OpenBSD: pf_table.c,v 1.79 2008/10/08 06:24:50 mcbride Exp $ 32 */ 33 34 #include <sys/cdefs.h> 35 #include "opt_inet.h" 36 #include "opt_inet6.h" 37 38 #include <sys/param.h> 39 #include <sys/kernel.h> 40 #include <sys/lock.h> 41 #include <sys/malloc.h> 42 #include <sys/mbuf.h> 43 #include <sys/mutex.h> 44 #include <sys/refcount.h> 45 #include <sys/socket.h> 46 #include <vm/uma.h> 47 48 #include <net/if.h> 49 #include <net/vnet.h> 50 #include <net/pfvar.h> 51 52 #define ACCEPT_FLAGS(flags, oklist) \ 53 do { \ 54 if ((flags & ~(oklist)) & \ 55 PFR_FLAG_ALLMASK) \ 56 return (EINVAL); \ 57 } while (0) 58 59 #define FILLIN_SIN(sin, addr) \ 60 do { \ 61 (sin).sin_len = sizeof(sin); \ 62 (sin).sin_family = AF_INET; \ 63 (sin).sin_addr = (addr); \ 64 } while (0) 65 66 #define FILLIN_SIN6(sin6, addr) \ 67 do { \ 68 (sin6).sin6_len = sizeof(sin6); \ 69 (sin6).sin6_family = AF_INET6; \ 70 (sin6).sin6_addr = (addr); \ 71 } while (0) 72 73 #define SWAP(type, a1, a2) \ 74 do { \ 75 type tmp = a1; \ 76 a1 = a2; \ 77 a2 = tmp; \ 78 } while (0) 79 80 #define AF_BITS(af) (((af)==AF_INET)?32:128) 81 #define ADDR_NETWORK(ad) ((ad)->pfra_net < AF_BITS((ad)->pfra_af)) 82 #define KENTRY_NETWORK(ke) ((ke)->pfrke_net < AF_BITS((ke)->pfrke_af)) 83 #define KENTRY_RNF_ROOT(ke) \ 84 ((((struct radix_node *)(ke))->rn_flags & RNF_ROOT) != 0) 85 86 #define NO_ADDRESSES (-1) 87 #define ENQUEUE_UNMARKED_ONLY (1) 88 #define INVERT_NEG_FLAG (1) 89 90 struct pfr_walktree { 91 enum pfrw_op { 92 PFRW_MARK, 93 PFRW_SWEEP, 94 PFRW_ENQUEUE, 95 PFRW_GET_ADDRS, 96 PFRW_GET_ASTATS, 97 PFRW_POOL_GET, 98 PFRW_DYNADDR_UPDATE, 99 PFRW_COUNTERS 100 } pfrw_op; 101 union { 102 struct pfr_addr *pfrw_addr; 103 struct pfr_astats *pfrw_astats; 104 struct pfr_kentryworkq *pfrw_workq; 105 struct pfr_kentry *pfrw_kentry; 106 struct pfi_dynaddr *pfrw_dyn; 107 }; 108 int pfrw_free; 109 int pfrw_flags; 110 }; 111 112 #define senderr(e) do { rv = (e); goto _bad; } while (0) 113 114 static MALLOC_DEFINE(M_PFTABLE, "pf_table", "pf(4) tables structures"); 115 VNET_DEFINE_STATIC(uma_zone_t, pfr_kentry_z); 116 #define V_pfr_kentry_z VNET(pfr_kentry_z) 117 VNET_DEFINE_STATIC(uma_zone_t, pfr_kentry_counter_z); 118 #define V_pfr_kentry_counter_z VNET(pfr_kentry_counter_z) 119 120 static struct pf_addr pfr_ffaddr = { 121 .addr32 = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff } 122 }; 123 124 static void pfr_copyout_astats(struct pfr_astats *, 125 const struct pfr_kentry *, 126 const struct pfr_walktree *); 127 static void pfr_copyout_addr(struct pfr_addr *, 128 const struct pfr_kentry *ke); 129 static int pfr_validate_addr(struct pfr_addr *); 130 static void pfr_enqueue_addrs(struct pfr_ktable *, 131 struct pfr_kentryworkq *, int *, int); 132 static void pfr_mark_addrs(struct pfr_ktable *); 133 static struct pfr_kentry 134 *pfr_lookup_addr(struct pfr_ktable *, 135 struct pfr_addr *, int); 136 static struct pfr_kentry *pfr_create_kentry(struct pfr_addr *, bool); 137 static void pfr_destroy_kentries(struct pfr_kentryworkq *); 138 static void pfr_destroy_kentry(struct pfr_kentry *); 139 static void pfr_insert_kentries(struct pfr_ktable *, 140 struct pfr_kentryworkq *, time_t); 141 static void pfr_remove_kentries(struct pfr_ktable *, 142 struct pfr_kentryworkq *); 143 static void pfr_clstats_kentries(struct pfr_ktable *, 144 struct pfr_kentryworkq *, time_t, int); 145 static void pfr_reset_feedback(struct pfr_addr *, int); 146 static void pfr_prepare_network(union sockaddr_union *, int, int); 147 static int pfr_route_kentry(struct pfr_ktable *, 148 struct pfr_kentry *); 149 static int pfr_unroute_kentry(struct pfr_ktable *, 150 struct pfr_kentry *); 151 static int pfr_walktree(struct radix_node *, void *); 152 static int pfr_validate_table(struct pfr_table *, int, int); 153 static int pfr_fix_anchor(char *); 154 static void pfr_commit_ktable(struct pfr_ktable *, time_t); 155 static void pfr_insert_ktables(struct pfr_ktableworkq *); 156 static void pfr_insert_ktable(struct pfr_ktable *); 157 static void pfr_setflags_ktables(struct pfr_ktableworkq *); 158 static void pfr_setflags_ktable(struct pfr_ktable *, int); 159 static void pfr_clstats_ktables(struct pfr_ktableworkq *, time_t, 160 int); 161 static void pfr_clstats_ktable(struct pfr_ktable *, time_t, int); 162 static struct pfr_ktable 163 *pfr_create_ktable(struct pfr_table *, time_t, int); 164 static void pfr_destroy_ktables(struct pfr_ktableworkq *, int); 165 static void pfr_destroy_ktable(struct pfr_ktable *, int); 166 static int pfr_ktable_compare(struct pfr_ktable *, 167 struct pfr_ktable *); 168 static struct pfr_ktable 169 *pfr_lookup_table(struct pfr_table *); 170 static void pfr_clean_node_mask(struct pfr_ktable *, 171 struct pfr_kentryworkq *); 172 static int pfr_skip_table(struct pfr_table *, 173 struct pfr_ktable *, int); 174 static struct pfr_kentry 175 *pfr_kentry_byidx(struct pfr_ktable *, int, int); 176 177 static RB_PROTOTYPE(pfr_ktablehead, pfr_ktable, pfrkt_tree, pfr_ktable_compare); 178 static RB_GENERATE(pfr_ktablehead, pfr_ktable, pfrkt_tree, pfr_ktable_compare); 179 180 VNET_DEFINE_STATIC(struct pfr_ktablehead, pfr_ktables); 181 #define V_pfr_ktables VNET(pfr_ktables) 182 183 VNET_DEFINE_STATIC(struct pfr_table, pfr_nulltable); 184 #define V_pfr_nulltable VNET(pfr_nulltable) 185 186 VNET_DEFINE_STATIC(int, pfr_ktable_cnt); 187 #define V_pfr_ktable_cnt VNET(pfr_ktable_cnt) 188 189 void 190 pfr_initialize(void) 191 { 192 193 V_pfr_kentry_counter_z = uma_zcreate("pf table entry counters", 194 PFR_NUM_COUNTERS * sizeof(uint64_t), NULL, NULL, NULL, NULL, 195 UMA_ALIGN_PTR, UMA_ZONE_PCPU); 196 V_pfr_kentry_z = uma_zcreate("pf table entries", 197 sizeof(struct pfr_kentry), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 198 0); 199 uma_zone_set_max(V_pfr_kentry_z, PFR_KENTRY_HIWAT); 200 V_pf_limits[PF_LIMIT_TABLE_ENTRIES].zone = V_pfr_kentry_z; 201 V_pf_limits[PF_LIMIT_TABLE_ENTRIES].limit = PFR_KENTRY_HIWAT; 202 } 203 204 void 205 pfr_cleanup(void) 206 { 207 208 uma_zdestroy(V_pfr_kentry_z); 209 uma_zdestroy(V_pfr_kentry_counter_z); 210 } 211 212 int 213 pfr_clr_addrs(struct pfr_table *tbl, int *ndel, int flags) 214 { 215 struct pfr_ktable *kt; 216 struct pfr_kentryworkq workq; 217 218 PF_RULES_WASSERT(); 219 220 ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY); 221 if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL)) 222 return (EINVAL); 223 kt = pfr_lookup_table(tbl); 224 if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) 225 return (ESRCH); 226 if (kt->pfrkt_flags & PFR_TFLAG_CONST) 227 return (EPERM); 228 pfr_enqueue_addrs(kt, &workq, ndel, 0); 229 230 if (!(flags & PFR_FLAG_DUMMY)) { 231 pfr_remove_kentries(kt, &workq); 232 KASSERT(kt->pfrkt_cnt == 0, ("%s: non-null pfrkt_cnt", __func__)); 233 } 234 return (0); 235 } 236 237 int 238 pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, 239 int *nadd, int flags) 240 { 241 struct pfr_ktable *kt, *tmpkt; 242 struct pfr_kentryworkq workq; 243 struct pfr_kentry *p, *q; 244 struct pfr_addr *ad; 245 int i, rv, xadd = 0; 246 time_t tzero = time_second; 247 248 PF_RULES_WASSERT(); 249 250 ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY | PFR_FLAG_FEEDBACK); 251 if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL)) 252 return (EINVAL); 253 kt = pfr_lookup_table(tbl); 254 if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) 255 return (ESRCH); 256 if (kt->pfrkt_flags & PFR_TFLAG_CONST) 257 return (EPERM); 258 tmpkt = pfr_create_ktable(&V_pfr_nulltable, 0, 0); 259 if (tmpkt == NULL) 260 return (ENOMEM); 261 SLIST_INIT(&workq); 262 for (i = 0, ad = addr; i < size; i++, ad++) { 263 if (pfr_validate_addr(ad)) 264 senderr(EINVAL); 265 p = pfr_lookup_addr(kt, ad, 1); 266 q = pfr_lookup_addr(tmpkt, ad, 1); 267 if (flags & PFR_FLAG_FEEDBACK) { 268 if (q != NULL) 269 ad->pfra_fback = PFR_FB_DUPLICATE; 270 else if (p == NULL) 271 ad->pfra_fback = PFR_FB_ADDED; 272 else if (p->pfrke_not != ad->pfra_not) 273 ad->pfra_fback = PFR_FB_CONFLICT; 274 else 275 ad->pfra_fback = PFR_FB_NONE; 276 } 277 if (p == NULL && q == NULL) { 278 p = pfr_create_kentry(ad, 279 (kt->pfrkt_flags & PFR_TFLAG_COUNTERS) != 0); 280 if (p == NULL) 281 senderr(ENOMEM); 282 if (pfr_route_kentry(tmpkt, p)) { 283 pfr_destroy_kentry(p); 284 ad->pfra_fback = PFR_FB_NONE; 285 } else { 286 SLIST_INSERT_HEAD(&workq, p, pfrke_workq); 287 xadd++; 288 } 289 } 290 } 291 pfr_clean_node_mask(tmpkt, &workq); 292 if (!(flags & PFR_FLAG_DUMMY)) 293 pfr_insert_kentries(kt, &workq, tzero); 294 else 295 pfr_destroy_kentries(&workq); 296 if (nadd != NULL) 297 *nadd += xadd; 298 pfr_destroy_ktable(tmpkt, 0); 299 return (0); 300 _bad: 301 pfr_clean_node_mask(tmpkt, &workq); 302 pfr_destroy_kentries(&workq); 303 if (flags & PFR_FLAG_FEEDBACK) 304 pfr_reset_feedback(addr, size); 305 pfr_destroy_ktable(tmpkt, 0); 306 return (rv); 307 } 308 309 int 310 pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, 311 int *ndel, int flags) 312 { 313 struct pfr_ktable *kt; 314 struct pfr_kentryworkq workq; 315 struct pfr_kentry *p; 316 struct pfr_addr *ad; 317 int i, rv, xdel = 0, log = 1; 318 319 PF_RULES_WASSERT(); 320 321 ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY | PFR_FLAG_FEEDBACK); 322 if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL)) 323 return (EINVAL); 324 kt = pfr_lookup_table(tbl); 325 if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) 326 return (ESRCH); 327 if (kt->pfrkt_flags & PFR_TFLAG_CONST) 328 return (EPERM); 329 /* 330 * there are two algorithms to choose from here. 331 * with: 332 * n: number of addresses to delete 333 * N: number of addresses in the table 334 * 335 * one is O(N) and is better for large 'n' 336 * one is O(n*LOG(N)) and is better for small 'n' 337 * 338 * following code try to decide which one is best. 339 */ 340 for (i = kt->pfrkt_cnt; i > 0; i >>= 1) 341 log++; 342 if (size > kt->pfrkt_cnt/log) { 343 /* full table scan */ 344 pfr_mark_addrs(kt); 345 } else { 346 /* iterate over addresses to delete */ 347 for (i = 0, ad = addr; i < size; i++, ad++) { 348 if (pfr_validate_addr(ad)) 349 return (EINVAL); 350 p = pfr_lookup_addr(kt, ad, 1); 351 if (p != NULL) 352 p->pfrke_mark = 0; 353 } 354 } 355 SLIST_INIT(&workq); 356 for (i = 0, ad = addr; i < size; i++, ad++) { 357 if (pfr_validate_addr(ad)) 358 senderr(EINVAL); 359 p = pfr_lookup_addr(kt, ad, 1); 360 if (flags & PFR_FLAG_FEEDBACK) { 361 if (p == NULL) 362 ad->pfra_fback = PFR_FB_NONE; 363 else if (p->pfrke_not != ad->pfra_not) 364 ad->pfra_fback = PFR_FB_CONFLICT; 365 else if (p->pfrke_mark) 366 ad->pfra_fback = PFR_FB_DUPLICATE; 367 else 368 ad->pfra_fback = PFR_FB_DELETED; 369 } 370 if (p != NULL && p->pfrke_not == ad->pfra_not && 371 !p->pfrke_mark) { 372 p->pfrke_mark = 1; 373 SLIST_INSERT_HEAD(&workq, p, pfrke_workq); 374 xdel++; 375 } 376 } 377 if (!(flags & PFR_FLAG_DUMMY)) 378 pfr_remove_kentries(kt, &workq); 379 if (ndel != NULL) 380 *ndel = xdel; 381 return (0); 382 _bad: 383 if (flags & PFR_FLAG_FEEDBACK) 384 pfr_reset_feedback(addr, size); 385 return (rv); 386 } 387 388 int 389 pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, 390 int *size2, int *nadd, int *ndel, int *nchange, int flags, 391 u_int32_t ignore_pfrt_flags) 392 { 393 struct pfr_ktable *kt, *tmpkt; 394 struct pfr_kentryworkq addq, delq, changeq; 395 struct pfr_kentry *p, *q; 396 struct pfr_addr ad; 397 int i, rv, xadd = 0, xdel = 0, xchange = 0; 398 time_t tzero = time_second; 399 400 PF_RULES_WASSERT(); 401 402 ACCEPT_FLAGS(flags, PFR_FLAG_START | PFR_FLAG_DONE | 403 PFR_FLAG_DUMMY | PFR_FLAG_FEEDBACK); 404 if (pfr_validate_table(tbl, ignore_pfrt_flags, flags & 405 PFR_FLAG_USERIOCTL)) 406 return (EINVAL); 407 kt = pfr_lookup_table(tbl); 408 if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) 409 return (ESRCH); 410 if (kt->pfrkt_flags & PFR_TFLAG_CONST) 411 return (EPERM); 412 tmpkt = pfr_create_ktable(&V_pfr_nulltable, 0, 0); 413 if (tmpkt == NULL) 414 return (ENOMEM); 415 if (flags & PFR_FLAG_START) 416 pfr_mark_addrs(kt); 417 SLIST_INIT(&addq); 418 SLIST_INIT(&delq); 419 SLIST_INIT(&changeq); 420 for (i = 0; i < size; i++) { 421 /* 422 * XXXGL: undertand pf_if usage of this function 423 * and make ad a moving pointer 424 */ 425 bcopy(addr + i, &ad, sizeof(ad)); 426 if (pfr_validate_addr(&ad)) 427 senderr(EINVAL); 428 ad.pfra_fback = PFR_FB_NONE; 429 p = pfr_lookup_addr(kt, &ad, 1); 430 if (p != NULL) { 431 if (p->pfrke_mark) { 432 ad.pfra_fback = PFR_FB_DUPLICATE; 433 goto _skip; 434 } 435 p->pfrke_mark = 1; 436 if (p->pfrke_not != ad.pfra_not) { 437 SLIST_INSERT_HEAD(&changeq, p, pfrke_workq); 438 ad.pfra_fback = PFR_FB_CHANGED; 439 xchange++; 440 } 441 } else { 442 q = pfr_lookup_addr(tmpkt, &ad, 1); 443 if (q != NULL) { 444 ad.pfra_fback = PFR_FB_DUPLICATE; 445 goto _skip; 446 } 447 p = pfr_create_kentry(&ad, 448 (kt->pfrkt_flags & PFR_TFLAG_COUNTERS) != 0); 449 p->pfrke_mark = PFR_FB_ADDED; 450 if (p == NULL) 451 senderr(ENOMEM); 452 if (pfr_route_kentry(tmpkt, p)) { 453 pfr_destroy_kentry(p); 454 ad.pfra_fback = PFR_FB_NONE; 455 } else { 456 SLIST_INSERT_HEAD(&addq, p, pfrke_workq); 457 ad.pfra_fback = PFR_FB_ADDED; 458 xadd++; 459 } 460 } 461 _skip: 462 if (flags & PFR_FLAG_FEEDBACK) 463 bcopy(&ad, addr + i, sizeof(ad)); 464 } 465 if (flags & PFR_FLAG_DONE) 466 pfr_enqueue_addrs(kt, &delq, &xdel, ENQUEUE_UNMARKED_ONLY); 467 if ((flags & PFR_FLAG_FEEDBACK) && *size2) { 468 if (*size2 < size+xdel) { 469 *size2 = size+xdel; 470 senderr(0); 471 } 472 i = 0; 473 SLIST_FOREACH(p, &delq, pfrke_workq) { 474 pfr_copyout_addr(&ad, p); 475 ad.pfra_fback = PFR_FB_DELETED; 476 bcopy(&ad, addr + size + i, sizeof(ad)); 477 i++; 478 } 479 } 480 pfr_clean_node_mask(tmpkt, &addq); 481 if (!(flags & PFR_FLAG_DUMMY)) { 482 pfr_insert_kentries(kt, &addq, tzero); 483 pfr_remove_kentries(kt, &delq); 484 pfr_clstats_kentries(kt, &changeq, tzero, INVERT_NEG_FLAG); 485 } else 486 pfr_destroy_kentries(&addq); 487 if (nadd != NULL) 488 *nadd = xadd; 489 if (ndel != NULL) 490 *ndel = xdel; 491 if (nchange != NULL) 492 *nchange = xchange; 493 if ((flags & PFR_FLAG_FEEDBACK) && size2) 494 *size2 = size+xdel; 495 pfr_destroy_ktable(tmpkt, 0); 496 return (0); 497 _bad: 498 pfr_clean_node_mask(tmpkt, &addq); 499 pfr_destroy_kentries(&addq); 500 if (flags & PFR_FLAG_FEEDBACK) 501 pfr_reset_feedback(addr, size); 502 pfr_destroy_ktable(tmpkt, 0); 503 return (rv); 504 } 505 506 int 507 pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, 508 int *nmatch, int flags) 509 { 510 struct pfr_ktable *kt; 511 struct pfr_kentry *p; 512 struct pfr_addr *ad; 513 int i, xmatch = 0; 514 515 PF_RULES_RASSERT(); 516 517 ACCEPT_FLAGS(flags, PFR_FLAG_REPLACE); 518 if (pfr_validate_table(tbl, 0, 0)) 519 return (EINVAL); 520 kt = pfr_lookup_table(tbl); 521 if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) 522 return (ESRCH); 523 524 for (i = 0, ad = addr; i < size; i++, ad++) { 525 if (pfr_validate_addr(ad)) 526 return (EINVAL); 527 if (ADDR_NETWORK(ad)) 528 return (EINVAL); 529 p = pfr_lookup_addr(kt, ad, 0); 530 if (flags & PFR_FLAG_REPLACE) 531 pfr_copyout_addr(ad, p); 532 ad->pfra_fback = (p == NULL) ? PFR_FB_NONE : 533 (p->pfrke_not ? PFR_FB_NOTMATCH : PFR_FB_MATCH); 534 if (p != NULL && !p->pfrke_not) 535 xmatch++; 536 } 537 if (nmatch != NULL) 538 *nmatch = xmatch; 539 return (0); 540 } 541 542 int 543 pfr_get_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int *size, 544 int flags) 545 { 546 struct pfr_ktable *kt; 547 struct pfr_walktree w; 548 int rv; 549 550 PF_RULES_RASSERT(); 551 552 ACCEPT_FLAGS(flags, 0); 553 if (pfr_validate_table(tbl, 0, 0)) 554 return (EINVAL); 555 kt = pfr_lookup_table(tbl); 556 if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) 557 return (ESRCH); 558 if (kt->pfrkt_cnt > *size) { 559 *size = kt->pfrkt_cnt; 560 return (0); 561 } 562 563 bzero(&w, sizeof(w)); 564 w.pfrw_op = PFRW_GET_ADDRS; 565 w.pfrw_addr = addr; 566 w.pfrw_free = kt->pfrkt_cnt; 567 rv = kt->pfrkt_ip4->rnh_walktree(&kt->pfrkt_ip4->rh, pfr_walktree, &w); 568 if (!rv) 569 rv = kt->pfrkt_ip6->rnh_walktree(&kt->pfrkt_ip6->rh, 570 pfr_walktree, &w); 571 if (rv) 572 return (rv); 573 574 KASSERT(w.pfrw_free == 0, ("%s: corruption detected (%d)", __func__, 575 w.pfrw_free)); 576 577 *size = kt->pfrkt_cnt; 578 return (0); 579 } 580 581 int 582 pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size, 583 int flags) 584 { 585 struct pfr_ktable *kt; 586 struct pfr_walktree w; 587 struct pfr_kentryworkq workq; 588 int rv; 589 time_t tzero = time_second; 590 591 PF_RULES_RASSERT(); 592 593 /* XXX PFR_FLAG_CLSTATS disabled */ 594 ACCEPT_FLAGS(flags, 0); 595 if (pfr_validate_table(tbl, 0, 0)) 596 return (EINVAL); 597 kt = pfr_lookup_table(tbl); 598 if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) 599 return (ESRCH); 600 if (kt->pfrkt_cnt > *size) { 601 *size = kt->pfrkt_cnt; 602 return (0); 603 } 604 605 bzero(&w, sizeof(w)); 606 w.pfrw_op = PFRW_GET_ASTATS; 607 w.pfrw_astats = addr; 608 w.pfrw_free = kt->pfrkt_cnt; 609 /* 610 * Flags below are for backward compatibility. It was possible to have 611 * a table without per-entry counters. Now they are always allocated, 612 * we just discard data when reading it if table is not configured to 613 * have counters. 614 */ 615 w.pfrw_flags = kt->pfrkt_flags; 616 rv = kt->pfrkt_ip4->rnh_walktree(&kt->pfrkt_ip4->rh, pfr_walktree, &w); 617 if (!rv) 618 rv = kt->pfrkt_ip6->rnh_walktree(&kt->pfrkt_ip6->rh, 619 pfr_walktree, &w); 620 if (!rv && (flags & PFR_FLAG_CLSTATS)) { 621 pfr_enqueue_addrs(kt, &workq, NULL, 0); 622 pfr_clstats_kentries(kt, &workq, tzero, 0); 623 } 624 if (rv) 625 return (rv); 626 627 if (w.pfrw_free) { 628 printf("pfr_get_astats: corruption detected (%d).\n", 629 w.pfrw_free); 630 return (ENOTTY); 631 } 632 *size = kt->pfrkt_cnt; 633 return (0); 634 } 635 636 int 637 pfr_clr_astats(struct pfr_table *tbl, struct pfr_addr *addr, int size, 638 int *nzero, int flags) 639 { 640 struct pfr_ktable *kt; 641 struct pfr_kentryworkq workq; 642 struct pfr_kentry *p; 643 struct pfr_addr *ad; 644 int i, rv, xzero = 0; 645 646 PF_RULES_WASSERT(); 647 648 ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY | PFR_FLAG_FEEDBACK); 649 if (pfr_validate_table(tbl, 0, 0)) 650 return (EINVAL); 651 kt = pfr_lookup_table(tbl); 652 if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) 653 return (ESRCH); 654 SLIST_INIT(&workq); 655 for (i = 0, ad = addr; i < size; i++, ad++) { 656 if (pfr_validate_addr(ad)) 657 senderr(EINVAL); 658 p = pfr_lookup_addr(kt, ad, 1); 659 if (flags & PFR_FLAG_FEEDBACK) { 660 ad->pfra_fback = (p != NULL) ? 661 PFR_FB_CLEARED : PFR_FB_NONE; 662 } 663 if (p != NULL) { 664 SLIST_INSERT_HEAD(&workq, p, pfrke_workq); 665 xzero++; 666 } 667 } 668 669 if (!(flags & PFR_FLAG_DUMMY)) 670 pfr_clstats_kentries(kt, &workq, time_second, 0); 671 if (nzero != NULL) 672 *nzero = xzero; 673 return (0); 674 _bad: 675 if (flags & PFR_FLAG_FEEDBACK) 676 pfr_reset_feedback(addr, size); 677 return (rv); 678 } 679 680 static int 681 pfr_validate_addr(struct pfr_addr *ad) 682 { 683 int i; 684 685 switch (ad->pfra_af) { 686 #ifdef INET 687 case AF_INET: 688 if (ad->pfra_net > 32) 689 return (-1); 690 break; 691 #endif /* INET */ 692 #ifdef INET6 693 case AF_INET6: 694 if (ad->pfra_net > 128) 695 return (-1); 696 break; 697 #endif /* INET6 */ 698 default: 699 return (-1); 700 } 701 if (ad->pfra_net < 128 && 702 (((caddr_t)ad)[ad->pfra_net/8] & (0xFF >> (ad->pfra_net%8)))) 703 return (-1); 704 for (i = (ad->pfra_net+7)/8; i < sizeof(ad->pfra_u); i++) 705 if (((caddr_t)ad)[i]) 706 return (-1); 707 if (ad->pfra_not && ad->pfra_not != 1) 708 return (-1); 709 if (ad->pfra_fback != PFR_FB_NONE) 710 return (-1); 711 return (0); 712 } 713 714 static void 715 pfr_enqueue_addrs(struct pfr_ktable *kt, struct pfr_kentryworkq *workq, 716 int *naddr, int sweep) 717 { 718 struct pfr_walktree w; 719 720 SLIST_INIT(workq); 721 bzero(&w, sizeof(w)); 722 w.pfrw_op = sweep ? PFRW_SWEEP : PFRW_ENQUEUE; 723 w.pfrw_workq = workq; 724 if (kt->pfrkt_ip4 != NULL) 725 if (kt->pfrkt_ip4->rnh_walktree(&kt->pfrkt_ip4->rh, 726 pfr_walktree, &w)) 727 printf("pfr_enqueue_addrs: IPv4 walktree failed.\n"); 728 if (kt->pfrkt_ip6 != NULL) 729 if (kt->pfrkt_ip6->rnh_walktree(&kt->pfrkt_ip6->rh, 730 pfr_walktree, &w)) 731 printf("pfr_enqueue_addrs: IPv6 walktree failed.\n"); 732 if (naddr != NULL) 733 *naddr = w.pfrw_free; 734 } 735 736 static void 737 pfr_mark_addrs(struct pfr_ktable *kt) 738 { 739 struct pfr_walktree w; 740 741 bzero(&w, sizeof(w)); 742 w.pfrw_op = PFRW_MARK; 743 if (kt->pfrkt_ip4->rnh_walktree(&kt->pfrkt_ip4->rh, pfr_walktree, &w)) 744 printf("pfr_mark_addrs: IPv4 walktree failed.\n"); 745 if (kt->pfrkt_ip6->rnh_walktree(&kt->pfrkt_ip6->rh, pfr_walktree, &w)) 746 printf("pfr_mark_addrs: IPv6 walktree failed.\n"); 747 } 748 749 static struct pfr_kentry * 750 pfr_lookup_addr(struct pfr_ktable *kt, struct pfr_addr *ad, int exact) 751 { 752 union sockaddr_union sa, mask; 753 struct radix_head *head = NULL; 754 struct pfr_kentry *ke; 755 756 PF_RULES_ASSERT(); 757 758 bzero(&sa, sizeof(sa)); 759 switch (ad->pfra_af) { 760 case AF_INET: 761 FILLIN_SIN(sa.sin, ad->pfra_ip4addr); 762 head = &kt->pfrkt_ip4->rh; 763 break; 764 case AF_INET6: 765 FILLIN_SIN6(sa.sin6, ad->pfra_ip6addr); 766 head = &kt->pfrkt_ip6->rh; 767 break; 768 default: 769 unhandled_af(ad->pfra_af); 770 } 771 if (ADDR_NETWORK(ad)) { 772 pfr_prepare_network(&mask, ad->pfra_af, ad->pfra_net); 773 ke = (struct pfr_kentry *)rn_lookup(&sa, &mask, head); 774 if (ke && KENTRY_RNF_ROOT(ke)) 775 ke = NULL; 776 } else { 777 ke = (struct pfr_kentry *)rn_match(&sa, head); 778 if (ke && KENTRY_RNF_ROOT(ke)) 779 ke = NULL; 780 if (exact && ke && KENTRY_NETWORK(ke)) 781 ke = NULL; 782 } 783 return (ke); 784 } 785 786 static struct pfr_kentry * 787 pfr_create_kentry(struct pfr_addr *ad, bool counters) 788 { 789 struct pfr_kentry *ke; 790 counter_u64_t c; 791 792 ke = uma_zalloc(V_pfr_kentry_z, M_NOWAIT | M_ZERO); 793 if (ke == NULL) 794 return (NULL); 795 796 switch (ad->pfra_af) { 797 case AF_INET: 798 FILLIN_SIN(ke->pfrke_sa.sin, ad->pfra_ip4addr); 799 break; 800 case AF_INET6: 801 FILLIN_SIN6(ke->pfrke_sa.sin6, ad->pfra_ip6addr); 802 break; 803 default: 804 unhandled_af(ad->pfra_af); 805 } 806 ke->pfrke_af = ad->pfra_af; 807 ke->pfrke_net = ad->pfra_net; 808 ke->pfrke_not = ad->pfra_not; 809 ke->pfrke_counters.pfrkc_tzero = 0; 810 if (counters) { 811 c = uma_zalloc_pcpu(V_pfr_kentry_counter_z, M_NOWAIT | M_ZERO); 812 if (c == NULL) { 813 pfr_destroy_kentry(ke); 814 return (NULL); 815 } 816 ke->pfrke_counters.pfrkc_counters = c; 817 } 818 return (ke); 819 } 820 821 static void 822 pfr_destroy_kentries(struct pfr_kentryworkq *workq) 823 { 824 struct pfr_kentry *p; 825 826 while ((p = SLIST_FIRST(workq)) != NULL) { 827 SLIST_REMOVE_HEAD(workq, pfrke_workq); 828 pfr_destroy_kentry(p); 829 } 830 } 831 832 static void 833 pfr_destroy_kentry(struct pfr_kentry *ke) 834 { 835 counter_u64_t c; 836 837 if ((c = ke->pfrke_counters.pfrkc_counters) != NULL) 838 uma_zfree_pcpu(V_pfr_kentry_counter_z, c); 839 uma_zfree(V_pfr_kentry_z, ke); 840 } 841 842 static void 843 pfr_insert_kentries(struct pfr_ktable *kt, 844 struct pfr_kentryworkq *workq, time_t tzero) 845 { 846 struct pfr_kentry *p; 847 int rv, n = 0; 848 849 SLIST_FOREACH(p, workq, pfrke_workq) { 850 rv = pfr_route_kentry(kt, p); 851 if (rv) { 852 printf("pfr_insert_kentries: cannot route entry " 853 "(code=%d).\n", rv); 854 break; 855 } 856 p->pfrke_counters.pfrkc_tzero = tzero; 857 n++; 858 } 859 kt->pfrkt_cnt += n; 860 } 861 862 int 863 pfr_insert_kentry(struct pfr_ktable *kt, struct pfr_addr *ad, time_t tzero) 864 { 865 struct pfr_kentry *p; 866 int rv; 867 868 p = pfr_lookup_addr(kt, ad, 1); 869 if (p != NULL) 870 return (0); 871 p = pfr_create_kentry(ad, (kt->pfrkt_flags & PFR_TFLAG_COUNTERS) != 0); 872 if (p == NULL) 873 return (ENOMEM); 874 875 rv = pfr_route_kentry(kt, p); 876 if (rv) 877 return (rv); 878 879 p->pfrke_counters.pfrkc_tzero = tzero; 880 kt->pfrkt_cnt++; 881 882 return (0); 883 } 884 885 static void 886 pfr_remove_kentries(struct pfr_ktable *kt, 887 struct pfr_kentryworkq *workq) 888 { 889 struct pfr_kentry *p; 890 int n = 0; 891 892 SLIST_FOREACH(p, workq, pfrke_workq) { 893 pfr_unroute_kentry(kt, p); 894 n++; 895 } 896 kt->pfrkt_cnt -= n; 897 pfr_destroy_kentries(workq); 898 } 899 900 static void 901 pfr_clean_node_mask(struct pfr_ktable *kt, 902 struct pfr_kentryworkq *workq) 903 { 904 struct pfr_kentry *p; 905 906 SLIST_FOREACH(p, workq, pfrke_workq) 907 pfr_unroute_kentry(kt, p); 908 } 909 910 static void 911 pfr_clstats_kentries(struct pfr_ktable *kt, struct pfr_kentryworkq *workq, 912 time_t tzero, int negchange) 913 { 914 struct pfr_kentry *p; 915 int i; 916 917 SLIST_FOREACH(p, workq, pfrke_workq) { 918 if (negchange) 919 p->pfrke_not = !p->pfrke_not; 920 if ((kt->pfrkt_flags & PFR_TFLAG_COUNTERS) != 0) 921 for (i = 0; i < PFR_NUM_COUNTERS; i++) 922 counter_u64_zero( 923 p->pfrke_counters.pfrkc_counters + i); 924 p->pfrke_counters.pfrkc_tzero = tzero; 925 } 926 } 927 928 static void 929 pfr_reset_feedback(struct pfr_addr *addr, int size) 930 { 931 struct pfr_addr *ad; 932 int i; 933 934 for (i = 0, ad = addr; i < size; i++, ad++) 935 ad->pfra_fback = PFR_FB_NONE; 936 } 937 938 static void 939 pfr_prepare_network(union sockaddr_union *sa, int af, int net) 940 { 941 int i; 942 943 bzero(sa, sizeof(*sa)); 944 switch (af) { 945 case AF_INET: 946 sa->sin.sin_len = sizeof(sa->sin); 947 sa->sin.sin_family = AF_INET; 948 sa->sin.sin_addr.s_addr = net ? htonl(-1 << (32-net)) : 0; 949 break; 950 case AF_INET6: 951 sa->sin6.sin6_len = sizeof(sa->sin6); 952 sa->sin6.sin6_family = AF_INET6; 953 for (i = 0; i < 4; i++) { 954 if (net <= 32) { 955 sa->sin6.sin6_addr.s6_addr32[i] = 956 net ? htonl(-1 << (32-net)) : 0; 957 break; 958 } 959 sa->sin6.sin6_addr.s6_addr32[i] = 0xFFFFFFFF; 960 net -= 32; 961 } 962 break; 963 default: 964 unhandled_af(af); 965 } 966 } 967 968 static int 969 pfr_route_kentry(struct pfr_ktable *kt, struct pfr_kentry *ke) 970 { 971 union sockaddr_union mask; 972 struct radix_node *rn; 973 struct radix_head *head = NULL; 974 975 PF_RULES_WASSERT(); 976 977 bzero(ke->pfrke_node, sizeof(ke->pfrke_node)); 978 switch (ke->pfrke_af) { 979 case AF_INET: 980 head = &kt->pfrkt_ip4->rh; 981 break; 982 case AF_INET6: 983 head = &kt->pfrkt_ip6->rh; 984 break; 985 default: 986 unhandled_af(ke->pfrke_af); 987 } 988 989 if (KENTRY_NETWORK(ke)) { 990 pfr_prepare_network(&mask, ke->pfrke_af, ke->pfrke_net); 991 rn = rn_addroute(&ke->pfrke_sa, &mask, head, ke->pfrke_node); 992 } else 993 rn = rn_addroute(&ke->pfrke_sa, NULL, head, ke->pfrke_node); 994 995 return (rn == NULL ? -1 : 0); 996 } 997 998 static int 999 pfr_unroute_kentry(struct pfr_ktable *kt, struct pfr_kentry *ke) 1000 { 1001 union sockaddr_union mask; 1002 struct radix_node *rn; 1003 struct radix_head *head = NULL; 1004 1005 switch (ke->pfrke_af) { 1006 case AF_INET: 1007 head = &kt->pfrkt_ip4->rh; 1008 break; 1009 case AF_INET6: 1010 head = &kt->pfrkt_ip6->rh; 1011 break; 1012 default: 1013 unhandled_af(ke->pfrke_af); 1014 } 1015 1016 if (KENTRY_NETWORK(ke)) { 1017 pfr_prepare_network(&mask, ke->pfrke_af, ke->pfrke_net); 1018 rn = rn_delete(&ke->pfrke_sa, &mask, head); 1019 } else 1020 rn = rn_delete(&ke->pfrke_sa, NULL, head); 1021 1022 if (rn == NULL) { 1023 printf("pfr_unroute_kentry: delete failed.\n"); 1024 return (-1); 1025 } 1026 return (0); 1027 } 1028 1029 static void 1030 pfr_copyout_addr(struct pfr_addr *ad, const struct pfr_kentry *ke) 1031 { 1032 bzero(ad, sizeof(*ad)); 1033 if (ke == NULL) 1034 return; 1035 ad->pfra_af = ke->pfrke_af; 1036 ad->pfra_net = ke->pfrke_net; 1037 ad->pfra_not = ke->pfrke_not; 1038 switch (ad->pfra_af) { 1039 case AF_INET: 1040 ad->pfra_ip4addr = ke->pfrke_sa.sin.sin_addr; 1041 break; 1042 case AF_INET6: 1043 ad->pfra_ip6addr = ke->pfrke_sa.sin6.sin6_addr; 1044 break; 1045 default: 1046 unhandled_af(ad->pfra_af); 1047 } 1048 } 1049 1050 static void 1051 pfr_copyout_astats(struct pfr_astats *as, const struct pfr_kentry *ke, 1052 const struct pfr_walktree *w) 1053 { 1054 int dir, op; 1055 const struct pfr_kcounters *kc = &ke->pfrke_counters; 1056 1057 bzero(as, sizeof(*as)); 1058 pfr_copyout_addr(&as->pfras_a, ke); 1059 as->pfras_tzero = kc->pfrkc_tzero; 1060 1061 if (! (w->pfrw_flags & PFR_TFLAG_COUNTERS) || 1062 kc->pfrkc_counters == NULL) { 1063 bzero(as->pfras_packets, sizeof(as->pfras_packets)); 1064 bzero(as->pfras_bytes, sizeof(as->pfras_bytes)); 1065 as->pfras_a.pfra_fback = PFR_FB_NOCOUNT; 1066 return; 1067 } 1068 1069 for (dir = 0; dir < PFR_DIR_MAX; dir++) { 1070 for (op = 0; op < PFR_OP_ADDR_MAX; op ++) { 1071 as->pfras_packets[dir][op] = counter_u64_fetch( 1072 pfr_kentry_counter(kc, dir, op, PFR_TYPE_PACKETS)); 1073 as->pfras_bytes[dir][op] = counter_u64_fetch( 1074 pfr_kentry_counter(kc, dir, op, PFR_TYPE_BYTES)); 1075 } 1076 } 1077 } 1078 1079 static void 1080 pfr_sockaddr_to_pf_addr(const union sockaddr_union *sa, struct pf_addr *a) 1081 { 1082 switch (sa->sa.sa_family) { 1083 case AF_INET: 1084 memcpy(&a->v4, &sa->sin.sin_addr, sizeof(a->v4)); 1085 break; 1086 case AF_INET6: 1087 memcpy(&a->v6, &sa->sin6.sin6_addr, sizeof(a->v6)); 1088 break; 1089 default: 1090 unhandled_af(sa->sa.sa_family); 1091 } 1092 } 1093 1094 static int 1095 pfr_walktree(struct radix_node *rn, void *arg) 1096 { 1097 struct pfr_kentry *ke = (struct pfr_kentry *)rn; 1098 struct pfr_walktree *w = arg; 1099 1100 switch (w->pfrw_op) { 1101 case PFRW_MARK: 1102 ke->pfrke_mark = 0; 1103 break; 1104 case PFRW_SWEEP: 1105 if (ke->pfrke_mark) 1106 break; 1107 /* FALLTHROUGH */ 1108 case PFRW_ENQUEUE: 1109 SLIST_INSERT_HEAD(w->pfrw_workq, ke, pfrke_workq); 1110 w->pfrw_free++; 1111 break; 1112 case PFRW_GET_ADDRS: 1113 if (w->pfrw_free-- > 0) { 1114 pfr_copyout_addr(w->pfrw_addr, ke); 1115 w->pfrw_addr++; 1116 } 1117 break; 1118 case PFRW_GET_ASTATS: 1119 if (w->pfrw_free-- > 0) { 1120 struct pfr_astats as; 1121 1122 pfr_copyout_astats(&as, ke, w); 1123 1124 bcopy(&as, w->pfrw_astats, sizeof(as)); 1125 w->pfrw_astats++; 1126 } 1127 break; 1128 case PFRW_POOL_GET: 1129 if (ke->pfrke_not) 1130 break; /* negative entries are ignored */ 1131 if (!w->pfrw_free--) { 1132 w->pfrw_kentry = ke; 1133 return (1); /* finish search */ 1134 } 1135 break; 1136 case PFRW_DYNADDR_UPDATE: 1137 { 1138 union sockaddr_union pfr_mask; 1139 1140 switch (ke->pfrke_af) { 1141 case AF_INET: 1142 if (w->pfrw_dyn->pfid_acnt4++ > 0) 1143 break; 1144 pfr_prepare_network(&pfr_mask, AF_INET, ke->pfrke_net); 1145 pfr_sockaddr_to_pf_addr(&ke->pfrke_sa, &w->pfrw_dyn->pfid_addr4); 1146 pfr_sockaddr_to_pf_addr(&pfr_mask, &w->pfrw_dyn->pfid_mask4); 1147 break; 1148 case AF_INET6: 1149 if (w->pfrw_dyn->pfid_acnt6++ > 0) 1150 break; 1151 pfr_prepare_network(&pfr_mask, AF_INET6, ke->pfrke_net); 1152 pfr_sockaddr_to_pf_addr(&ke->pfrke_sa, &w->pfrw_dyn->pfid_addr6); 1153 pfr_sockaddr_to_pf_addr(&pfr_mask, &w->pfrw_dyn->pfid_mask6); 1154 break; 1155 default: 1156 unhandled_af(ke->pfrke_af); 1157 } 1158 break; 1159 } 1160 case PFRW_COUNTERS: 1161 { 1162 if (w->pfrw_flags & PFR_TFLAG_COUNTERS) { 1163 if (ke->pfrke_counters.pfrkc_counters != NULL) 1164 break; 1165 ke->pfrke_counters.pfrkc_counters = 1166 uma_zalloc_pcpu(V_pfr_kentry_counter_z, 1167 M_NOWAIT | M_ZERO); 1168 } else { 1169 uma_zfree_pcpu(V_pfr_kentry_counter_z, 1170 ke->pfrke_counters.pfrkc_counters); 1171 ke->pfrke_counters.pfrkc_counters = NULL; 1172 } 1173 break; 1174 } 1175 } 1176 return (0); 1177 } 1178 1179 int 1180 pfr_clr_tables(struct pfr_table *filter, int *ndel, int flags) 1181 { 1182 struct pfr_ktableworkq workq; 1183 struct pfr_ktable *p; 1184 int xdel = 0; 1185 1186 ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY | PFR_FLAG_ALLRSETS); 1187 if (pfr_fix_anchor(filter->pfrt_anchor)) 1188 return (EINVAL); 1189 if (pfr_table_count(filter, flags) < 0) 1190 return (ENOENT); 1191 1192 SLIST_INIT(&workq); 1193 RB_FOREACH(p, pfr_ktablehead, &V_pfr_ktables) { 1194 if (pfr_skip_table(filter, p, flags)) 1195 continue; 1196 if (!strcmp(p->pfrkt_anchor, PF_RESERVED_ANCHOR)) 1197 continue; 1198 if (!(p->pfrkt_flags & PFR_TFLAG_ACTIVE)) 1199 continue; 1200 p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_ACTIVE; 1201 SLIST_INSERT_HEAD(&workq, p, pfrkt_workq); 1202 xdel++; 1203 } 1204 if (!(flags & PFR_FLAG_DUMMY)) 1205 pfr_setflags_ktables(&workq); 1206 if (ndel != NULL) 1207 *ndel = xdel; 1208 return (0); 1209 } 1210 1211 int 1212 pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags) 1213 { 1214 struct pfr_ktableworkq addq, changeq; 1215 struct pfr_ktable *p, *q, *r, key; 1216 int i, rv, xadd = 0; 1217 time_t tzero = time_second; 1218 1219 ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY); 1220 SLIST_INIT(&addq); 1221 SLIST_INIT(&changeq); 1222 for (i = 0; i < size; i++) { 1223 bcopy(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)); 1224 if (pfr_validate_table(&key.pfrkt_t, PFR_TFLAG_USRMASK, 1225 flags & PFR_FLAG_USERIOCTL)) 1226 senderr(EINVAL); 1227 key.pfrkt_flags |= PFR_TFLAG_ACTIVE; 1228 p = RB_FIND(pfr_ktablehead, &V_pfr_ktables, &key); 1229 if (p == NULL) { 1230 p = pfr_create_ktable(&key.pfrkt_t, tzero, 1); 1231 if (p == NULL) 1232 senderr(ENOMEM); 1233 SLIST_FOREACH(q, &addq, pfrkt_workq) { 1234 if (!pfr_ktable_compare(p, q)) { 1235 pfr_destroy_ktable(p, 0); 1236 goto _skip; 1237 } 1238 } 1239 SLIST_INSERT_HEAD(&addq, p, pfrkt_workq); 1240 xadd++; 1241 if (!key.pfrkt_anchor[0]) 1242 goto _skip; 1243 1244 /* find or create root table */ 1245 bzero(key.pfrkt_anchor, sizeof(key.pfrkt_anchor)); 1246 r = RB_FIND(pfr_ktablehead, &V_pfr_ktables, &key); 1247 if (r != NULL) { 1248 p->pfrkt_root = r; 1249 goto _skip; 1250 } 1251 SLIST_FOREACH(q, &addq, pfrkt_workq) { 1252 if (!pfr_ktable_compare(&key, q)) { 1253 p->pfrkt_root = q; 1254 goto _skip; 1255 } 1256 } 1257 key.pfrkt_flags = 0; 1258 r = pfr_create_ktable(&key.pfrkt_t, 0, 1); 1259 if (r == NULL) 1260 senderr(ENOMEM); 1261 SLIST_INSERT_HEAD(&addq, r, pfrkt_workq); 1262 p->pfrkt_root = r; 1263 } else if (!(p->pfrkt_flags & PFR_TFLAG_ACTIVE)) { 1264 SLIST_FOREACH(q, &changeq, pfrkt_workq) 1265 if (!pfr_ktable_compare(&key, q)) 1266 goto _skip; 1267 p->pfrkt_nflags = (p->pfrkt_flags & 1268 ~PFR_TFLAG_USRMASK) | key.pfrkt_flags; 1269 SLIST_INSERT_HEAD(&changeq, p, pfrkt_workq); 1270 xadd++; 1271 } 1272 _skip: 1273 ; 1274 } 1275 if (!(flags & PFR_FLAG_DUMMY)) { 1276 pfr_insert_ktables(&addq); 1277 pfr_setflags_ktables(&changeq); 1278 } else 1279 pfr_destroy_ktables(&addq, 0); 1280 if (nadd != NULL) 1281 *nadd = xadd; 1282 return (0); 1283 _bad: 1284 pfr_destroy_ktables(&addq, 0); 1285 return (rv); 1286 } 1287 1288 int 1289 pfr_del_tables(struct pfr_table *tbl, int size, int *ndel, int flags) 1290 { 1291 struct pfr_ktableworkq workq; 1292 struct pfr_ktable *p, *q, key; 1293 int i, xdel = 0; 1294 1295 ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY); 1296 SLIST_INIT(&workq); 1297 for (i = 0; i < size; i++) { 1298 bcopy(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)); 1299 if (pfr_validate_table(&key.pfrkt_t, 0, 1300 flags & PFR_FLAG_USERIOCTL)) 1301 return (EINVAL); 1302 p = RB_FIND(pfr_ktablehead, &V_pfr_ktables, &key); 1303 if (p != NULL && (p->pfrkt_flags & PFR_TFLAG_ACTIVE)) { 1304 SLIST_FOREACH(q, &workq, pfrkt_workq) 1305 if (!pfr_ktable_compare(p, q)) 1306 goto _skip; 1307 p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_ACTIVE; 1308 SLIST_INSERT_HEAD(&workq, p, pfrkt_workq); 1309 xdel++; 1310 } 1311 _skip: 1312 ; 1313 } 1314 1315 if (!(flags & PFR_FLAG_DUMMY)) 1316 pfr_setflags_ktables(&workq); 1317 if (ndel != NULL) 1318 *ndel = xdel; 1319 return (0); 1320 } 1321 1322 int 1323 pfr_get_tables(struct pfr_table *filter, struct pfr_table *tbl, int *size, 1324 int flags) 1325 { 1326 struct pfr_ktable *p; 1327 int n, nn; 1328 1329 PF_RULES_RASSERT(); 1330 1331 ACCEPT_FLAGS(flags, PFR_FLAG_ALLRSETS); 1332 if (pfr_fix_anchor(filter->pfrt_anchor)) 1333 return (EINVAL); 1334 n = nn = pfr_table_count(filter, flags); 1335 if (n < 0) 1336 return (ENOENT); 1337 if (n > *size) { 1338 *size = n; 1339 return (0); 1340 } 1341 RB_FOREACH(p, pfr_ktablehead, &V_pfr_ktables) { 1342 if (pfr_skip_table(filter, p, flags)) 1343 continue; 1344 if (n-- <= 0) 1345 continue; 1346 bcopy(&p->pfrkt_t, tbl++, sizeof(*tbl)); 1347 } 1348 1349 KASSERT(n == 0, ("%s: corruption detected (%d)", __func__, n)); 1350 1351 *size = nn; 1352 return (0); 1353 } 1354 1355 int 1356 pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size, 1357 int flags) 1358 { 1359 struct pfr_ktable *p; 1360 struct pfr_ktableworkq workq; 1361 int n, nn; 1362 time_t tzero = time_second; 1363 int pfr_dir, pfr_op; 1364 1365 /* XXX PFR_FLAG_CLSTATS disabled */ 1366 ACCEPT_FLAGS(flags, PFR_FLAG_ALLRSETS); 1367 if (pfr_fix_anchor(filter->pfrt_anchor)) 1368 return (EINVAL); 1369 n = nn = pfr_table_count(filter, flags); 1370 if (n < 0) 1371 return (ENOENT); 1372 if (n > *size) { 1373 *size = n; 1374 return (0); 1375 } 1376 SLIST_INIT(&workq); 1377 RB_FOREACH(p, pfr_ktablehead, &V_pfr_ktables) { 1378 if (pfr_skip_table(filter, p, flags)) 1379 continue; 1380 if (n-- <= 0) 1381 continue; 1382 bcopy(&p->pfrkt_kts.pfrts_t, &tbl->pfrts_t, 1383 sizeof(struct pfr_table)); 1384 for (pfr_dir = 0; pfr_dir < PFR_DIR_MAX; pfr_dir ++) { 1385 for (pfr_op = 0; pfr_op < PFR_OP_TABLE_MAX; pfr_op ++) { 1386 tbl->pfrts_packets[pfr_dir][pfr_op] = 1387 pfr_kstate_counter_fetch( 1388 &p->pfrkt_packets[pfr_dir][pfr_op]); 1389 tbl->pfrts_bytes[pfr_dir][pfr_op] = 1390 pfr_kstate_counter_fetch( 1391 &p->pfrkt_bytes[pfr_dir][pfr_op]); 1392 } 1393 } 1394 tbl->pfrts_match = pfr_kstate_counter_fetch(&p->pfrkt_match); 1395 tbl->pfrts_nomatch = pfr_kstate_counter_fetch(&p->pfrkt_nomatch); 1396 tbl->pfrts_tzero = p->pfrkt_tzero; 1397 tbl->pfrts_cnt = p->pfrkt_cnt; 1398 for (pfr_op = 0; pfr_op < PFR_REFCNT_MAX; pfr_op++) 1399 tbl->pfrts_refcnt[pfr_op] = p->pfrkt_refcnt[pfr_op]; 1400 tbl++; 1401 SLIST_INSERT_HEAD(&workq, p, pfrkt_workq); 1402 } 1403 if (flags & PFR_FLAG_CLSTATS) 1404 pfr_clstats_ktables(&workq, tzero, 1405 flags & PFR_FLAG_ADDRSTOO); 1406 1407 KASSERT(n == 0, ("%s: corruption detected (%d)", __func__, n)); 1408 1409 *size = nn; 1410 return (0); 1411 } 1412 1413 int 1414 pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags) 1415 { 1416 struct pfr_ktableworkq workq; 1417 struct pfr_ktable *p, key; 1418 int i, xzero = 0; 1419 time_t tzero = time_second; 1420 1421 ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY | PFR_FLAG_ADDRSTOO); 1422 SLIST_INIT(&workq); 1423 for (i = 0; i < size; i++) { 1424 bcopy(tbl + i, &key.pfrkt_t, sizeof(key.pfrkt_t)); 1425 if (pfr_validate_table(&key.pfrkt_t, 0, 0)) 1426 return (EINVAL); 1427 p = RB_FIND(pfr_ktablehead, &V_pfr_ktables, &key); 1428 if (p != NULL) { 1429 SLIST_INSERT_HEAD(&workq, p, pfrkt_workq); 1430 xzero++; 1431 } 1432 } 1433 if (!(flags & PFR_FLAG_DUMMY)) 1434 pfr_clstats_ktables(&workq, tzero, flags & PFR_FLAG_ADDRSTOO); 1435 if (nzero != NULL) 1436 *nzero = xzero; 1437 return (0); 1438 } 1439 1440 int 1441 pfr_set_tflags(struct pfr_table *tbl, int size, int setflag, int clrflag, 1442 int *nchange, int *ndel, int flags) 1443 { 1444 struct pfr_ktableworkq workq; 1445 struct pfr_ktable *p, *q, key; 1446 int i, xchange = 0, xdel = 0; 1447 1448 ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY); 1449 if ((setflag & ~PFR_TFLAG_USRMASK) || 1450 (clrflag & ~PFR_TFLAG_USRMASK) || 1451 (setflag & clrflag)) 1452 return (EINVAL); 1453 SLIST_INIT(&workq); 1454 for (i = 0; i < size; i++) { 1455 bcopy(tbl + i, &key.pfrkt_t, sizeof(key.pfrkt_t)); 1456 if (pfr_validate_table(&key.pfrkt_t, 0, 1457 flags & PFR_FLAG_USERIOCTL)) 1458 return (EINVAL); 1459 p = RB_FIND(pfr_ktablehead, &V_pfr_ktables, &key); 1460 if (p != NULL && (p->pfrkt_flags & PFR_TFLAG_ACTIVE)) { 1461 p->pfrkt_nflags = (p->pfrkt_flags | setflag) & 1462 ~clrflag; 1463 if (p->pfrkt_nflags == p->pfrkt_flags) 1464 goto _skip; 1465 SLIST_FOREACH(q, &workq, pfrkt_workq) 1466 if (!pfr_ktable_compare(p, q)) 1467 goto _skip; 1468 SLIST_INSERT_HEAD(&workq, p, pfrkt_workq); 1469 if ((p->pfrkt_flags & PFR_TFLAG_PERSIST) && 1470 (clrflag & PFR_TFLAG_PERSIST) && 1471 !(p->pfrkt_flags & PFR_TFLAG_REFERENCED)) 1472 xdel++; 1473 else 1474 xchange++; 1475 } 1476 _skip: 1477 ; 1478 } 1479 if (!(flags & PFR_FLAG_DUMMY)) 1480 pfr_setflags_ktables(&workq); 1481 if (nchange != NULL) 1482 *nchange = xchange; 1483 if (ndel != NULL) 1484 *ndel = xdel; 1485 return (0); 1486 } 1487 1488 int 1489 pfr_ina_begin(struct pfr_table *trs, u_int32_t *ticket, int *ndel, int flags) 1490 { 1491 struct pfr_ktableworkq workq; 1492 struct pfr_ktable *p; 1493 struct pf_kruleset *rs; 1494 int xdel = 0; 1495 1496 ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY); 1497 rs = pf_find_or_create_kruleset(trs->pfrt_anchor); 1498 if (rs == NULL) 1499 return (ENOMEM); 1500 SLIST_INIT(&workq); 1501 RB_FOREACH(p, pfr_ktablehead, &V_pfr_ktables) { 1502 if (!(p->pfrkt_flags & PFR_TFLAG_INACTIVE) || 1503 pfr_skip_table(trs, p, 0)) 1504 continue; 1505 p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_INACTIVE; 1506 SLIST_INSERT_HEAD(&workq, p, pfrkt_workq); 1507 xdel++; 1508 } 1509 if (!(flags & PFR_FLAG_DUMMY)) { 1510 pfr_setflags_ktables(&workq); 1511 if (ticket != NULL) 1512 *ticket = ++rs->tticket; 1513 rs->topen = 1; 1514 } else 1515 pf_remove_if_empty_kruleset(rs); 1516 if (ndel != NULL) 1517 *ndel = xdel; 1518 return (0); 1519 } 1520 1521 int 1522 pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size, 1523 int *nadd, int *naddr, u_int32_t ticket, int flags) 1524 { 1525 struct pfr_ktableworkq tableq; 1526 struct pfr_kentryworkq addrq; 1527 struct pfr_ktable *kt, *rt, *shadow, key; 1528 struct pfr_kentry *p; 1529 struct pfr_addr *ad; 1530 struct pf_kruleset *rs; 1531 int i, rv, xadd = 0, xaddr = 0; 1532 1533 PF_RULES_WASSERT(); 1534 1535 ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY | PFR_FLAG_ADDRSTOO); 1536 if (size && !(flags & PFR_FLAG_ADDRSTOO)) 1537 return (EINVAL); 1538 if (pfr_validate_table(tbl, PFR_TFLAG_USRMASK, 1539 flags & PFR_FLAG_USERIOCTL)) 1540 return (EINVAL); 1541 rs = pf_find_kruleset(tbl->pfrt_anchor); 1542 if (rs == NULL || !rs->topen || ticket != rs->tticket) 1543 return (EBUSY); 1544 tbl->pfrt_flags |= PFR_TFLAG_INACTIVE; 1545 SLIST_INIT(&tableq); 1546 kt = RB_FIND(pfr_ktablehead, &V_pfr_ktables, (struct pfr_ktable *)tbl); 1547 if (kt == NULL) { 1548 kt = pfr_create_ktable(tbl, 0, 1); 1549 if (kt == NULL) 1550 return (ENOMEM); 1551 SLIST_INSERT_HEAD(&tableq, kt, pfrkt_workq); 1552 xadd++; 1553 if (!tbl->pfrt_anchor[0]) 1554 goto _skip; 1555 1556 /* find or create root table */ 1557 bzero(&key, sizeof(key)); 1558 strlcpy(key.pfrkt_name, tbl->pfrt_name, sizeof(key.pfrkt_name)); 1559 rt = RB_FIND(pfr_ktablehead, &V_pfr_ktables, &key); 1560 if (rt != NULL) { 1561 kt->pfrkt_root = rt; 1562 goto _skip; 1563 } 1564 rt = pfr_create_ktable(&key.pfrkt_t, 0, 1); 1565 if (rt == NULL) { 1566 pfr_destroy_ktables(&tableq, 0); 1567 return (ENOMEM); 1568 } 1569 SLIST_INSERT_HEAD(&tableq, rt, pfrkt_workq); 1570 kt->pfrkt_root = rt; 1571 } else if (!(kt->pfrkt_flags & PFR_TFLAG_INACTIVE)) 1572 xadd++; 1573 _skip: 1574 shadow = pfr_create_ktable(tbl, 0, 0); 1575 if (shadow == NULL) { 1576 pfr_destroy_ktables(&tableq, 0); 1577 return (ENOMEM); 1578 } 1579 SLIST_INIT(&addrq); 1580 for (i = 0, ad = addr; i < size; i++, ad++) { 1581 if (pfr_validate_addr(ad)) 1582 senderr(EINVAL); 1583 if (pfr_lookup_addr(shadow, ad, 1) != NULL) 1584 continue; 1585 p = pfr_create_kentry(ad, 1586 (shadow->pfrkt_flags & PFR_TFLAG_COUNTERS) != 0); 1587 if (p == NULL) 1588 senderr(ENOMEM); 1589 if (pfr_route_kentry(shadow, p)) { 1590 pfr_destroy_kentry(p); 1591 continue; 1592 } 1593 SLIST_INSERT_HEAD(&addrq, p, pfrke_workq); 1594 xaddr++; 1595 } 1596 if (!(flags & PFR_FLAG_DUMMY)) { 1597 if (kt->pfrkt_shadow != NULL) 1598 pfr_destroy_ktable(kt->pfrkt_shadow, 1); 1599 kt->pfrkt_flags |= PFR_TFLAG_INACTIVE; 1600 pfr_insert_ktables(&tableq); 1601 shadow->pfrkt_cnt = (flags & PFR_FLAG_ADDRSTOO) ? 1602 xaddr : NO_ADDRESSES; 1603 kt->pfrkt_shadow = shadow; 1604 } else { 1605 pfr_clean_node_mask(shadow, &addrq); 1606 pfr_destroy_ktable(shadow, 0); 1607 pfr_destroy_ktables(&tableq, 0); 1608 pfr_destroy_kentries(&addrq); 1609 } 1610 if (nadd != NULL) 1611 *nadd = xadd; 1612 if (naddr != NULL) 1613 *naddr = xaddr; 1614 return (0); 1615 _bad: 1616 pfr_destroy_ktable(shadow, 0); 1617 pfr_destroy_ktables(&tableq, 0); 1618 pfr_destroy_kentries(&addrq); 1619 return (rv); 1620 } 1621 1622 int 1623 pfr_ina_rollback(struct pfr_table *trs, u_int32_t ticket, int *ndel, int flags) 1624 { 1625 struct pfr_ktableworkq workq; 1626 struct pfr_ktable *p; 1627 struct pf_kruleset *rs; 1628 int xdel = 0; 1629 1630 PF_RULES_WASSERT(); 1631 1632 ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY); 1633 rs = pf_find_kruleset(trs->pfrt_anchor); 1634 if (rs == NULL || !rs->topen || ticket != rs->tticket) 1635 return (0); 1636 SLIST_INIT(&workq); 1637 RB_FOREACH(p, pfr_ktablehead, &V_pfr_ktables) { 1638 if (!(p->pfrkt_flags & PFR_TFLAG_INACTIVE) || 1639 pfr_skip_table(trs, p, 0)) 1640 continue; 1641 p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_INACTIVE; 1642 SLIST_INSERT_HEAD(&workq, p, pfrkt_workq); 1643 xdel++; 1644 } 1645 if (!(flags & PFR_FLAG_DUMMY)) { 1646 pfr_setflags_ktables(&workq); 1647 rs->topen = 0; 1648 pf_remove_if_empty_kruleset(rs); 1649 } 1650 if (ndel != NULL) 1651 *ndel = xdel; 1652 return (0); 1653 } 1654 1655 int 1656 pfr_ina_commit(struct pfr_table *trs, u_int32_t ticket, int *nadd, 1657 int *nchange, int flags) 1658 { 1659 struct pfr_ktable *p, *q; 1660 struct pfr_ktableworkq workq; 1661 struct pf_kruleset *rs; 1662 int xadd = 0, xchange = 0; 1663 time_t tzero = time_second; 1664 1665 PF_RULES_WASSERT(); 1666 1667 ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY); 1668 rs = pf_find_kruleset(trs->pfrt_anchor); 1669 if (rs == NULL || !rs->topen || ticket != rs->tticket) 1670 return (EBUSY); 1671 1672 SLIST_INIT(&workq); 1673 RB_FOREACH(p, pfr_ktablehead, &V_pfr_ktables) { 1674 if (!(p->pfrkt_flags & PFR_TFLAG_INACTIVE) || 1675 pfr_skip_table(trs, p, 0)) 1676 continue; 1677 SLIST_INSERT_HEAD(&workq, p, pfrkt_workq); 1678 if (p->pfrkt_flags & PFR_TFLAG_ACTIVE) 1679 xchange++; 1680 else 1681 xadd++; 1682 } 1683 1684 if (!(flags & PFR_FLAG_DUMMY)) { 1685 SLIST_FOREACH_SAFE(p, &workq, pfrkt_workq, q) { 1686 pfr_commit_ktable(p, tzero); 1687 } 1688 rs->topen = 0; 1689 pf_remove_if_empty_kruleset(rs); 1690 } 1691 if (nadd != NULL) 1692 *nadd = xadd; 1693 if (nchange != NULL) 1694 *nchange = xchange; 1695 1696 return (0); 1697 } 1698 1699 static void 1700 pfr_commit_ktable(struct pfr_ktable *kt, time_t tzero) 1701 { 1702 counter_u64_t *pkc, *qkc; 1703 struct pfr_ktable *shadow = kt->pfrkt_shadow; 1704 int nflags; 1705 1706 PF_RULES_WASSERT(); 1707 1708 if (shadow->pfrkt_cnt == NO_ADDRESSES) { 1709 if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) 1710 pfr_clstats_ktable(kt, tzero, 1); 1711 } else if (kt->pfrkt_flags & PFR_TFLAG_ACTIVE) { 1712 /* kt might contain addresses */ 1713 struct pfr_kentryworkq addrq, addq, changeq, delq, garbageq; 1714 struct pfr_kentry *p, *q; 1715 struct pfr_addr ad; 1716 1717 pfr_enqueue_addrs(shadow, &addrq, NULL, 0); 1718 pfr_mark_addrs(kt); 1719 SLIST_INIT(&addq); 1720 SLIST_INIT(&changeq); 1721 SLIST_INIT(&delq); 1722 SLIST_INIT(&garbageq); 1723 pfr_clean_node_mask(shadow, &addrq); 1724 while ((p = SLIST_FIRST(&addrq)) != NULL) { 1725 SLIST_REMOVE_HEAD(&addrq, pfrke_workq); 1726 pfr_copyout_addr(&ad, p); 1727 q = pfr_lookup_addr(kt, &ad, 1); 1728 if (q != NULL) { 1729 if (q->pfrke_not != p->pfrke_not) 1730 SLIST_INSERT_HEAD(&changeq, q, 1731 pfrke_workq); 1732 pkc = &p->pfrke_counters.pfrkc_counters; 1733 qkc = &q->pfrke_counters.pfrkc_counters; 1734 if ((*pkc == NULL) != (*qkc == NULL)) 1735 SWAP(counter_u64_t, *pkc, *qkc); 1736 q->pfrke_mark = 1; 1737 SLIST_INSERT_HEAD(&garbageq, p, pfrke_workq); 1738 } else { 1739 p->pfrke_counters.pfrkc_tzero = tzero; 1740 SLIST_INSERT_HEAD(&addq, p, pfrke_workq); 1741 } 1742 } 1743 pfr_enqueue_addrs(kt, &delq, NULL, ENQUEUE_UNMARKED_ONLY); 1744 pfr_insert_kentries(kt, &addq, tzero); 1745 pfr_remove_kentries(kt, &delq); 1746 pfr_clstats_kentries(kt, &changeq, tzero, INVERT_NEG_FLAG); 1747 pfr_destroy_kentries(&garbageq); 1748 } else { 1749 /* kt cannot contain addresses */ 1750 SWAP(struct radix_node_head *, kt->pfrkt_ip4, 1751 shadow->pfrkt_ip4); 1752 SWAP(struct radix_node_head *, kt->pfrkt_ip6, 1753 shadow->pfrkt_ip6); 1754 SWAP(int, kt->pfrkt_cnt, shadow->pfrkt_cnt); 1755 pfr_clstats_ktable(kt, tzero, 1); 1756 } 1757 nflags = ((shadow->pfrkt_flags & PFR_TFLAG_USRMASK) | 1758 (kt->pfrkt_flags & PFR_TFLAG_SETMASK) | PFR_TFLAG_ACTIVE) 1759 & ~PFR_TFLAG_INACTIVE; 1760 pfr_destroy_ktable(shadow, 0); 1761 kt->pfrkt_shadow = NULL; 1762 pfr_setflags_ktable(kt, nflags); 1763 } 1764 1765 static int 1766 pfr_validate_table(struct pfr_table *tbl, int allowedflags, int no_reserved) 1767 { 1768 int i; 1769 1770 if (!tbl->pfrt_name[0]) 1771 return (-1); 1772 if (no_reserved && !strcmp(tbl->pfrt_anchor, PF_RESERVED_ANCHOR)) 1773 return (-1); 1774 if (tbl->pfrt_name[PF_TABLE_NAME_SIZE-1]) 1775 return (-1); 1776 for (i = strlen(tbl->pfrt_name); i < PF_TABLE_NAME_SIZE; i++) 1777 if (tbl->pfrt_name[i]) 1778 return (-1); 1779 if (pfr_fix_anchor(tbl->pfrt_anchor)) 1780 return (-1); 1781 if (tbl->pfrt_flags & ~allowedflags) 1782 return (-1); 1783 return (0); 1784 } 1785 1786 /* 1787 * Rewrite anchors referenced by tables to remove slashes 1788 * and check for validity. 1789 */ 1790 static int 1791 pfr_fix_anchor(char *anchor) 1792 { 1793 size_t siz = MAXPATHLEN; 1794 int i; 1795 1796 if (anchor[0] == '/') { 1797 char *path; 1798 int off; 1799 1800 path = anchor; 1801 off = 1; 1802 while (*++path == '/') 1803 off++; 1804 bcopy(path, anchor, siz - off); 1805 memset(anchor + siz - off, 0, off); 1806 } 1807 if (anchor[siz - 1]) 1808 return (-1); 1809 for (i = strlen(anchor); i < siz; i++) 1810 if (anchor[i]) 1811 return (-1); 1812 return (0); 1813 } 1814 1815 int 1816 pfr_table_count(struct pfr_table *filter, int flags) 1817 { 1818 struct pf_kruleset *rs; 1819 1820 PF_RULES_ASSERT(); 1821 1822 if (flags & PFR_FLAG_ALLRSETS) 1823 return (V_pfr_ktable_cnt); 1824 if (filter->pfrt_anchor[0]) { 1825 rs = pf_find_kruleset(filter->pfrt_anchor); 1826 return ((rs != NULL) ? rs->tables : -1); 1827 } 1828 return (pf_main_ruleset.tables); 1829 } 1830 1831 static int 1832 pfr_skip_table(struct pfr_table *filter, struct pfr_ktable *kt, int flags) 1833 { 1834 if (flags & PFR_FLAG_ALLRSETS) 1835 return (0); 1836 if (strcmp(filter->pfrt_anchor, kt->pfrkt_anchor)) 1837 return (1); 1838 return (0); 1839 } 1840 1841 static void 1842 pfr_insert_ktables(struct pfr_ktableworkq *workq) 1843 { 1844 struct pfr_ktable *p; 1845 1846 SLIST_FOREACH(p, workq, pfrkt_workq) 1847 pfr_insert_ktable(p); 1848 } 1849 1850 static void 1851 pfr_insert_ktable(struct pfr_ktable *kt) 1852 { 1853 1854 PF_RULES_WASSERT(); 1855 1856 RB_INSERT(pfr_ktablehead, &V_pfr_ktables, kt); 1857 V_pfr_ktable_cnt++; 1858 if (kt->pfrkt_root != NULL) 1859 if (!kt->pfrkt_root->pfrkt_refcnt[PFR_REFCNT_ANCHOR]++) 1860 pfr_setflags_ktable(kt->pfrkt_root, 1861 kt->pfrkt_root->pfrkt_flags|PFR_TFLAG_REFDANCHOR); 1862 } 1863 1864 static void 1865 pfr_setflags_ktables(struct pfr_ktableworkq *workq) 1866 { 1867 struct pfr_ktable *p, *q; 1868 1869 SLIST_FOREACH_SAFE(p, workq, pfrkt_workq, q) { 1870 pfr_setflags_ktable(p, p->pfrkt_nflags); 1871 } 1872 } 1873 1874 static void 1875 pfr_setflags_ktable(struct pfr_ktable *kt, int newf) 1876 { 1877 struct pfr_kentryworkq addrq; 1878 struct pfr_walktree w; 1879 1880 PF_RULES_WASSERT(); 1881 1882 if (!(newf & PFR_TFLAG_REFERENCED) && 1883 !(newf & PFR_TFLAG_REFDANCHOR) && 1884 !(newf & PFR_TFLAG_PERSIST)) 1885 newf &= ~PFR_TFLAG_ACTIVE; 1886 if (!(newf & PFR_TFLAG_ACTIVE)) 1887 newf &= ~PFR_TFLAG_USRMASK; 1888 if (!(newf & PFR_TFLAG_SETMASK)) { 1889 RB_REMOVE(pfr_ktablehead, &V_pfr_ktables, kt); 1890 if (kt->pfrkt_root != NULL) 1891 if (!--kt->pfrkt_root->pfrkt_refcnt[PFR_REFCNT_ANCHOR]) 1892 pfr_setflags_ktable(kt->pfrkt_root, 1893 kt->pfrkt_root->pfrkt_flags & 1894 ~PFR_TFLAG_REFDANCHOR); 1895 pfr_destroy_ktable(kt, 1); 1896 V_pfr_ktable_cnt--; 1897 return; 1898 } 1899 if (newf & PFR_TFLAG_COUNTERS && ! (kt->pfrkt_flags & PFR_TFLAG_COUNTERS)) { 1900 bzero(&w, sizeof(w)); 1901 w.pfrw_op = PFRW_COUNTERS; 1902 w.pfrw_flags |= PFR_TFLAG_COUNTERS; 1903 kt->pfrkt_ip4->rnh_walktree(&kt->pfrkt_ip4->rh, pfr_walktree, &w); 1904 kt->pfrkt_ip6->rnh_walktree(&kt->pfrkt_ip6->rh, pfr_walktree, &w); 1905 } 1906 if (! (newf & PFR_TFLAG_COUNTERS) && (kt->pfrkt_flags & PFR_TFLAG_COUNTERS)) { 1907 bzero(&w, sizeof(w)); 1908 w.pfrw_op = PFRW_COUNTERS; 1909 w.pfrw_flags |= 0; 1910 kt->pfrkt_ip4->rnh_walktree(&kt->pfrkt_ip4->rh, pfr_walktree, &w); 1911 kt->pfrkt_ip6->rnh_walktree(&kt->pfrkt_ip6->rh, pfr_walktree, &w); 1912 } 1913 if (!(newf & PFR_TFLAG_ACTIVE) && kt->pfrkt_cnt) { 1914 pfr_enqueue_addrs(kt, &addrq, NULL, 0); 1915 pfr_remove_kentries(kt, &addrq); 1916 } 1917 if (!(newf & PFR_TFLAG_INACTIVE) && kt->pfrkt_shadow != NULL) { 1918 pfr_destroy_ktable(kt->pfrkt_shadow, 1); 1919 kt->pfrkt_shadow = NULL; 1920 } 1921 kt->pfrkt_flags = newf; 1922 } 1923 1924 static void 1925 pfr_clstats_ktables(struct pfr_ktableworkq *workq, time_t tzero, int recurse) 1926 { 1927 struct pfr_ktable *p; 1928 1929 SLIST_FOREACH(p, workq, pfrkt_workq) 1930 pfr_clstats_ktable(p, tzero, recurse); 1931 } 1932 1933 static void 1934 pfr_clstats_ktable(struct pfr_ktable *kt, time_t tzero, int recurse) 1935 { 1936 struct pfr_kentryworkq addrq; 1937 int pfr_dir, pfr_op; 1938 1939 MPASS(PF_TABLE_STATS_OWNED() || PF_RULES_WOWNED()); 1940 1941 if (recurse) { 1942 pfr_enqueue_addrs(kt, &addrq, NULL, 0); 1943 pfr_clstats_kentries(kt, &addrq, tzero, 0); 1944 } 1945 for (pfr_dir = 0; pfr_dir < PFR_DIR_MAX; pfr_dir ++) { 1946 for (pfr_op = 0; pfr_op < PFR_OP_TABLE_MAX; pfr_op ++) { 1947 pfr_kstate_counter_zero(&kt->pfrkt_packets[pfr_dir][pfr_op]); 1948 pfr_kstate_counter_zero(&kt->pfrkt_bytes[pfr_dir][pfr_op]); 1949 } 1950 } 1951 pfr_kstate_counter_zero(&kt->pfrkt_match); 1952 pfr_kstate_counter_zero(&kt->pfrkt_nomatch); 1953 kt->pfrkt_tzero = tzero; 1954 } 1955 1956 static struct pfr_ktable * 1957 pfr_create_ktable(struct pfr_table *tbl, time_t tzero, int attachruleset) 1958 { 1959 struct pfr_ktable *kt; 1960 struct pf_kruleset *rs; 1961 int pfr_dir, pfr_op; 1962 1963 PF_RULES_WASSERT(); 1964 1965 kt = malloc(sizeof(*kt), M_PFTABLE, M_NOWAIT|M_ZERO); 1966 if (kt == NULL) 1967 return (NULL); 1968 kt->pfrkt_t = *tbl; 1969 1970 if (attachruleset) { 1971 rs = pf_find_or_create_kruleset(tbl->pfrt_anchor); 1972 if (!rs) { 1973 pfr_destroy_ktable(kt, 0); 1974 return (NULL); 1975 } 1976 kt->pfrkt_rs = rs; 1977 rs->tables++; 1978 } 1979 1980 for (pfr_dir = 0; pfr_dir < PFR_DIR_MAX; pfr_dir ++) { 1981 for (pfr_op = 0; pfr_op < PFR_OP_TABLE_MAX; pfr_op ++) { 1982 if (pfr_kstate_counter_init( 1983 &kt->pfrkt_packets[pfr_dir][pfr_op], M_NOWAIT) != 0) { 1984 pfr_destroy_ktable(kt, 0); 1985 return (NULL); 1986 } 1987 if (pfr_kstate_counter_init( 1988 &kt->pfrkt_bytes[pfr_dir][pfr_op], M_NOWAIT) != 0) { 1989 pfr_destroy_ktable(kt, 0); 1990 return (NULL); 1991 } 1992 } 1993 } 1994 if (pfr_kstate_counter_init(&kt->pfrkt_match, M_NOWAIT) != 0) { 1995 pfr_destroy_ktable(kt, 0); 1996 return (NULL); 1997 } 1998 1999 if (pfr_kstate_counter_init(&kt->pfrkt_nomatch, M_NOWAIT) != 0) { 2000 pfr_destroy_ktable(kt, 0); 2001 return (NULL); 2002 } 2003 2004 if (!rn_inithead((void **)&kt->pfrkt_ip4, 2005 offsetof(struct sockaddr_in, sin_addr) * 8) || 2006 !rn_inithead((void **)&kt->pfrkt_ip6, 2007 offsetof(struct sockaddr_in6, sin6_addr) * 8)) { 2008 pfr_destroy_ktable(kt, 0); 2009 return (NULL); 2010 } 2011 kt->pfrkt_tzero = tzero; 2012 2013 return (kt); 2014 } 2015 2016 static void 2017 pfr_destroy_ktables(struct pfr_ktableworkq *workq, int flushaddr) 2018 { 2019 struct pfr_ktable *p; 2020 2021 while ((p = SLIST_FIRST(workq)) != NULL) { 2022 SLIST_REMOVE_HEAD(workq, pfrkt_workq); 2023 pfr_destroy_ktable(p, flushaddr); 2024 } 2025 } 2026 2027 static void 2028 pfr_destroy_ktable(struct pfr_ktable *kt, int flushaddr) 2029 { 2030 struct pfr_kentryworkq addrq; 2031 int pfr_dir, pfr_op; 2032 2033 if (flushaddr) { 2034 pfr_enqueue_addrs(kt, &addrq, NULL, 0); 2035 pfr_clean_node_mask(kt, &addrq); 2036 pfr_destroy_kentries(&addrq); 2037 } 2038 if (kt->pfrkt_ip4 != NULL) 2039 rn_detachhead((void **)&kt->pfrkt_ip4); 2040 if (kt->pfrkt_ip6 != NULL) 2041 rn_detachhead((void **)&kt->pfrkt_ip6); 2042 if (kt->pfrkt_shadow != NULL) 2043 pfr_destroy_ktable(kt->pfrkt_shadow, flushaddr); 2044 if (kt->pfrkt_rs != NULL) { 2045 kt->pfrkt_rs->tables--; 2046 pf_remove_if_empty_kruleset(kt->pfrkt_rs); 2047 } 2048 for (pfr_dir = 0; pfr_dir < PFR_DIR_MAX; pfr_dir ++) { 2049 for (pfr_op = 0; pfr_op < PFR_OP_TABLE_MAX; pfr_op ++) { 2050 pfr_kstate_counter_deinit(&kt->pfrkt_packets[pfr_dir][pfr_op]); 2051 pfr_kstate_counter_deinit(&kt->pfrkt_bytes[pfr_dir][pfr_op]); 2052 } 2053 } 2054 pfr_kstate_counter_deinit(&kt->pfrkt_match); 2055 pfr_kstate_counter_deinit(&kt->pfrkt_nomatch); 2056 2057 free(kt, M_PFTABLE); 2058 } 2059 2060 static int 2061 pfr_ktable_compare(struct pfr_ktable *p, struct pfr_ktable *q) 2062 { 2063 int d; 2064 2065 if ((d = strncmp(p->pfrkt_name, q->pfrkt_name, PF_TABLE_NAME_SIZE))) 2066 return (d); 2067 return (strcmp(p->pfrkt_anchor, q->pfrkt_anchor)); 2068 } 2069 2070 static struct pfr_ktable * 2071 pfr_lookup_table(struct pfr_table *tbl) 2072 { 2073 /* struct pfr_ktable start like a struct pfr_table */ 2074 return (RB_FIND(pfr_ktablehead, &V_pfr_ktables, 2075 (struct pfr_ktable *)tbl)); 2076 } 2077 2078 struct pfr_kentry * 2079 pfr_kentry_byaddr(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af, 2080 int exact) 2081 { 2082 struct pfr_kentry *ke = NULL; 2083 2084 PF_RULES_RASSERT(); 2085 2086 kt = pfr_ktable_select_active(kt); 2087 if (kt == NULL) 2088 return (0); 2089 2090 switch (af) { 2091 #ifdef INET 2092 case AF_INET: 2093 { 2094 struct sockaddr_in sin; 2095 2096 bzero(&sin, sizeof(sin)); 2097 sin.sin_len = sizeof(sin); 2098 sin.sin_family = AF_INET; 2099 sin.sin_addr.s_addr = a->addr32[0]; 2100 ke = (struct pfr_kentry *)rn_match(&sin, &kt->pfrkt_ip4->rh); 2101 if (ke && KENTRY_RNF_ROOT(ke)) 2102 ke = NULL; 2103 break; 2104 } 2105 #endif /* INET */ 2106 #ifdef INET6 2107 case AF_INET6: 2108 { 2109 struct sockaddr_in6 sin6; 2110 2111 bzero(&sin6, sizeof(sin6)); 2112 sin6.sin6_len = sizeof(sin6); 2113 sin6.sin6_family = AF_INET6; 2114 bcopy(a, &sin6.sin6_addr, sizeof(sin6.sin6_addr)); 2115 ke = (struct pfr_kentry *)rn_match(&sin6, &kt->pfrkt_ip6->rh); 2116 if (ke && KENTRY_RNF_ROOT(ke)) 2117 ke = NULL; 2118 break; 2119 } 2120 #endif /* INET6 */ 2121 default: 2122 unhandled_af(af); 2123 } 2124 if (exact && ke && KENTRY_NETWORK(ke)) 2125 ke = NULL; 2126 2127 return (ke); 2128 } 2129 2130 int 2131 pfr_match_addr(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af) 2132 { 2133 struct pfr_kentry *ke = NULL; 2134 int match; 2135 2136 ke = pfr_kentry_byaddr(kt, a, af, 0); 2137 2138 match = (ke && !ke->pfrke_not); 2139 if (match) 2140 pfr_kstate_counter_add(&kt->pfrkt_match, 1); 2141 else 2142 pfr_kstate_counter_add(&kt->pfrkt_nomatch, 1); 2143 2144 return (match); 2145 } 2146 2147 void 2148 pfr_update_stats(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af, 2149 u_int64_t len, int dir_out, int op_pass, int notrule) 2150 { 2151 struct pfr_kentry *ke = NULL; 2152 2153 kt = pfr_ktable_select_active(kt); 2154 if (kt == NULL) 2155 return; 2156 2157 switch (af) { 2158 #ifdef INET 2159 case AF_INET: 2160 { 2161 struct sockaddr_in sin; 2162 2163 bzero(&sin, sizeof(sin)); 2164 sin.sin_len = sizeof(sin); 2165 sin.sin_family = AF_INET; 2166 sin.sin_addr.s_addr = a->addr32[0]; 2167 ke = (struct pfr_kentry *)rn_match(&sin, &kt->pfrkt_ip4->rh); 2168 if (ke && KENTRY_RNF_ROOT(ke)) 2169 ke = NULL; 2170 break; 2171 } 2172 #endif /* INET */ 2173 #ifdef INET6 2174 case AF_INET6: 2175 { 2176 struct sockaddr_in6 sin6; 2177 2178 bzero(&sin6, sizeof(sin6)); 2179 sin6.sin6_len = sizeof(sin6); 2180 sin6.sin6_family = AF_INET6; 2181 bcopy(a, &sin6.sin6_addr, sizeof(sin6.sin6_addr)); 2182 ke = (struct pfr_kentry *)rn_match(&sin6, &kt->pfrkt_ip6->rh); 2183 if (ke && KENTRY_RNF_ROOT(ke)) 2184 ke = NULL; 2185 break; 2186 } 2187 #endif /* INET6 */ 2188 default: 2189 unhandled_af(af); 2190 } 2191 if ((ke == NULL || ke->pfrke_not) != notrule) { 2192 if (op_pass != PFR_OP_PASS) 2193 DPFPRINTF(PF_DEBUG_URGENT, 2194 "pfr_update_stats: assertion failed."); 2195 op_pass = PFR_OP_XPASS; 2196 } 2197 pfr_kstate_counter_add(&kt->pfrkt_packets[dir_out][op_pass], 1); 2198 pfr_kstate_counter_add(&kt->pfrkt_bytes[dir_out][op_pass], len); 2199 if (ke != NULL && op_pass != PFR_OP_XPASS && 2200 (kt->pfrkt_flags & PFR_TFLAG_COUNTERS)) { 2201 counter_u64_add(pfr_kentry_counter(&ke->pfrke_counters, 2202 dir_out, op_pass, PFR_TYPE_PACKETS), 1); 2203 counter_u64_add(pfr_kentry_counter(&ke->pfrke_counters, 2204 dir_out, op_pass, PFR_TYPE_BYTES), len); 2205 } 2206 } 2207 2208 struct pfr_ktable * 2209 pfr_eth_attach_table(struct pf_keth_ruleset *rs, char *name) 2210 { 2211 struct pfr_ktable *kt, *rt; 2212 struct pfr_table tbl; 2213 struct pf_keth_anchor *ac = rs->anchor; 2214 2215 PF_RULES_WASSERT(); 2216 2217 bzero(&tbl, sizeof(tbl)); 2218 strlcpy(tbl.pfrt_name, name, sizeof(tbl.pfrt_name)); 2219 if (ac != NULL) 2220 strlcpy(tbl.pfrt_anchor, ac->path, sizeof(tbl.pfrt_anchor)); 2221 kt = pfr_lookup_table(&tbl); 2222 if (kt == NULL) { 2223 kt = pfr_create_ktable(&tbl, time_second, 1); 2224 if (kt == NULL) 2225 return (NULL); 2226 if (ac != NULL) { 2227 bzero(tbl.pfrt_anchor, sizeof(tbl.pfrt_anchor)); 2228 rt = pfr_lookup_table(&tbl); 2229 if (rt == NULL) { 2230 rt = pfr_create_ktable(&tbl, 0, 1); 2231 if (rt == NULL) { 2232 pfr_destroy_ktable(kt, 0); 2233 return (NULL); 2234 } 2235 pfr_insert_ktable(rt); 2236 } 2237 kt->pfrkt_root = rt; 2238 } 2239 pfr_insert_ktable(kt); 2240 } 2241 if (!kt->pfrkt_refcnt[PFR_REFCNT_RULE]++) 2242 pfr_setflags_ktable(kt, kt->pfrkt_flags|PFR_TFLAG_REFERENCED); 2243 return (kt); 2244 } 2245 2246 struct pfr_ktable * 2247 pfr_attach_table(struct pf_kruleset *rs, char *name) 2248 { 2249 struct pfr_ktable *kt, *rt; 2250 struct pfr_table tbl; 2251 struct pf_kanchor *ac = rs->anchor; 2252 2253 PF_RULES_WASSERT(); 2254 2255 bzero(&tbl, sizeof(tbl)); 2256 strlcpy(tbl.pfrt_name, name, sizeof(tbl.pfrt_name)); 2257 if (ac != NULL) 2258 strlcpy(tbl.pfrt_anchor, ac->path, sizeof(tbl.pfrt_anchor)); 2259 kt = pfr_lookup_table(&tbl); 2260 if (kt == NULL) { 2261 kt = pfr_create_ktable(&tbl, time_second, 1); 2262 if (kt == NULL) 2263 return (NULL); 2264 if (ac != NULL) { 2265 bzero(tbl.pfrt_anchor, sizeof(tbl.pfrt_anchor)); 2266 rt = pfr_lookup_table(&tbl); 2267 if (rt == NULL) { 2268 rt = pfr_create_ktable(&tbl, 0, 1); 2269 if (rt == NULL) { 2270 pfr_destroy_ktable(kt, 0); 2271 return (NULL); 2272 } 2273 pfr_insert_ktable(rt); 2274 } 2275 kt->pfrkt_root = rt; 2276 } 2277 pfr_insert_ktable(kt); 2278 } 2279 if (!kt->pfrkt_refcnt[PFR_REFCNT_RULE]++) 2280 pfr_setflags_ktable(kt, kt->pfrkt_flags|PFR_TFLAG_REFERENCED); 2281 return (kt); 2282 } 2283 2284 void 2285 pfr_detach_table(struct pfr_ktable *kt) 2286 { 2287 2288 PF_RULES_WASSERT(); 2289 KASSERT(kt->pfrkt_refcnt[PFR_REFCNT_RULE] > 0, ("%s: refcount %d\n", 2290 __func__, kt->pfrkt_refcnt[PFR_REFCNT_RULE])); 2291 2292 if (!--kt->pfrkt_refcnt[PFR_REFCNT_RULE]) 2293 pfr_setflags_ktable(kt, kt->pfrkt_flags&~PFR_TFLAG_REFERENCED); 2294 } 2295 2296 int 2297 pfr_pool_get(struct pfr_ktable *kt, int *pidx, struct pf_addr *counter, 2298 sa_family_t af, pf_addr_filter_func_t filter, bool loop_once) 2299 { 2300 struct pf_addr *addr, cur, mask, umask_addr; 2301 union sockaddr_union uaddr, umask; 2302 struct pfr_kentry *ke, *ke2 = NULL; 2303 int startidx, idx = -1, loop = 0, use_counter = 0; 2304 2305 MPASS(pidx != NULL); 2306 MPASS(counter != NULL); 2307 2308 switch (af) { 2309 case AF_INET: 2310 uaddr.sin.sin_len = sizeof(struct sockaddr_in); 2311 uaddr.sin.sin_family = AF_INET; 2312 addr = (struct pf_addr *)&uaddr.sin.sin_addr; 2313 break; 2314 case AF_INET6: 2315 uaddr.sin6.sin6_len = sizeof(struct sockaddr_in6); 2316 uaddr.sin6.sin6_family = AF_INET6; 2317 addr = (struct pf_addr *)&uaddr.sin6.sin6_addr; 2318 break; 2319 default: 2320 unhandled_af(af); 2321 } 2322 2323 kt = pfr_ktable_select_active(kt); 2324 if (kt == NULL) 2325 return (-1); 2326 2327 idx = *pidx; 2328 if (idx < 0 || idx >= kt->pfrkt_cnt) 2329 idx = 0; 2330 else if (counter != NULL) 2331 use_counter = 1; 2332 startidx = idx; 2333 2334 _next_block: 2335 if (loop && startidx == idx) { 2336 pfr_kstate_counter_add(&kt->pfrkt_nomatch, 1); 2337 return (1); 2338 } 2339 2340 ke = pfr_kentry_byidx(kt, idx, af); 2341 if (ke == NULL) { 2342 /* we don't have this idx, try looping */ 2343 if ((loop || loop_once) || (ke = pfr_kentry_byidx(kt, 0, af)) == NULL) { 2344 pfr_kstate_counter_add(&kt->pfrkt_nomatch, 1); 2345 return (1); 2346 } 2347 idx = 0; 2348 loop++; 2349 } 2350 pfr_prepare_network(&umask, af, ke->pfrke_net); 2351 pfr_sockaddr_to_pf_addr(&ke->pfrke_sa, &cur); 2352 pfr_sockaddr_to_pf_addr(&umask, &mask); 2353 2354 if (use_counter && !PF_AZERO(counter, af)) { 2355 /* is supplied address within block? */ 2356 if (!pf_match_addr(0, &cur, &mask, counter, af)) { 2357 /* no, go to next block in table */ 2358 idx++; 2359 use_counter = 0; 2360 goto _next_block; 2361 } 2362 pf_addrcpy(addr, counter, af); 2363 } else { 2364 /* use first address of block */ 2365 pf_addrcpy(addr, &cur, af); 2366 } 2367 2368 if (!KENTRY_NETWORK(ke)) { 2369 /* this is a single IP address - no possible nested block */ 2370 if (filter && filter(af, addr)) { 2371 idx++; 2372 goto _next_block; 2373 } 2374 pf_addrcpy(counter, addr, af); 2375 *pidx = idx; 2376 pfr_kstate_counter_add(&kt->pfrkt_match, 1); 2377 return (0); 2378 } 2379 for (;;) { 2380 /* we don't want to use a nested block */ 2381 switch (af) { 2382 case AF_INET: 2383 ke2 = (struct pfr_kentry *)rn_match(&uaddr, 2384 &kt->pfrkt_ip4->rh); 2385 break; 2386 case AF_INET6: 2387 ke2 = (struct pfr_kentry *)rn_match(&uaddr, 2388 &kt->pfrkt_ip6->rh); 2389 break; 2390 default: 2391 unhandled_af(af); 2392 } 2393 /* no need to check KENTRY_RNF_ROOT() here */ 2394 if (ke2 == ke) { 2395 /* lookup return the same block - perfect */ 2396 if (filter && filter(af, addr)) 2397 goto _next_entry; 2398 pf_addrcpy(counter, addr, af); 2399 *pidx = idx; 2400 pfr_kstate_counter_add(&kt->pfrkt_match, 1); 2401 return (0); 2402 } 2403 2404 _next_entry: 2405 /* we need to increase the counter past the nested block */ 2406 pfr_prepare_network(&umask, AF_INET, ke2->pfrke_net); 2407 pfr_sockaddr_to_pf_addr(&umask, &umask_addr); 2408 pf_poolmask(addr, addr, &umask_addr, &pfr_ffaddr, af); 2409 pf_addr_inc(addr, af); 2410 if (!pf_match_addr(0, &cur, &mask, addr, af)) { 2411 /* ok, we reached the end of our main block */ 2412 /* go to next block in table */ 2413 idx++; 2414 use_counter = 0; 2415 goto _next_block; 2416 } 2417 } 2418 } 2419 2420 static struct pfr_kentry * 2421 pfr_kentry_byidx(struct pfr_ktable *kt, int idx, int af) 2422 { 2423 struct pfr_walktree w; 2424 2425 bzero(&w, sizeof(w)); 2426 w.pfrw_op = PFRW_POOL_GET; 2427 w.pfrw_free = idx; 2428 2429 switch (af) { 2430 #ifdef INET 2431 case AF_INET: 2432 kt->pfrkt_ip4->rnh_walktree(&kt->pfrkt_ip4->rh, pfr_walktree, &w); 2433 return (w.pfrw_kentry); 2434 #endif /* INET */ 2435 #ifdef INET6 2436 case AF_INET6: 2437 kt->pfrkt_ip6->rnh_walktree(&kt->pfrkt_ip6->rh, pfr_walktree, &w); 2438 return (w.pfrw_kentry); 2439 #endif /* INET6 */ 2440 default: 2441 return (NULL); 2442 } 2443 } 2444 2445 void 2446 pfr_dynaddr_update(struct pfr_ktable *kt, struct pfi_dynaddr *dyn) 2447 { 2448 struct pfr_walktree w; 2449 2450 bzero(&w, sizeof(w)); 2451 w.pfrw_op = PFRW_DYNADDR_UPDATE; 2452 w.pfrw_dyn = dyn; 2453 2454 dyn->pfid_acnt4 = 0; 2455 dyn->pfid_acnt6 = 0; 2456 switch (dyn->pfid_af) { 2457 case AF_UNSPEC: /* look up all both addresses IPv4 + IPv6 */ 2458 kt->pfrkt_ip4->rnh_walktree(&kt->pfrkt_ip4->rh, pfr_walktree, &w); 2459 kt->pfrkt_ip6->rnh_walktree(&kt->pfrkt_ip6->rh, pfr_walktree, &w); 2460 break; 2461 case AF_INET: 2462 kt->pfrkt_ip4->rnh_walktree(&kt->pfrkt_ip4->rh, pfr_walktree, &w); 2463 break; 2464 case AF_INET6: 2465 kt->pfrkt_ip6->rnh_walktree(&kt->pfrkt_ip6->rh, pfr_walktree, &w); 2466 break; 2467 default: 2468 unhandled_af(dyn->pfid_af); 2469 } 2470 } 2471 2472 struct pfr_ktable * 2473 pfr_ktable_select_active(struct pfr_ktable *kt) 2474 { 2475 if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && kt->pfrkt_root != NULL) 2476 kt = kt->pfrkt_root; 2477 if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) 2478 return (NULL); 2479 2480 return (kt); 2481 } 2482