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