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