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