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