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