1 /* $OpenBSD: pf_table.c,v 1.127 2017/08/16 14:19:57 mikeb 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 = time_second; 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 = time_second; 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 = time_second; 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, time_second, 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) 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 = time_second; 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 goto _skip; 1310 } 1311 SLIST_INSERT_HEAD(&addq, p, pfrkt_workq); 1312 xadd++; 1313 if (!key.pfrkt_anchor[0]) 1314 goto _skip; 1315 1316 /* find or create root table */ 1317 bzero(key.pfrkt_anchor, sizeof(key.pfrkt_anchor)); 1318 r = RB_FIND(pfr_ktablehead, &pfr_ktables, &key); 1319 if (r != NULL) { 1320 p->pfrkt_root = r; 1321 goto _skip; 1322 } 1323 SLIST_FOREACH(q, &addq, pfrkt_workq) { 1324 if (!pfr_ktable_compare(&key, q)) { 1325 p->pfrkt_root = q; 1326 goto _skip; 1327 } 1328 } 1329 key.pfrkt_flags = 0; 1330 r = pfr_create_ktable(&key.pfrkt_t, 0, 1, 1331 !(flags & PFR_FLAG_USERIOCTL)); 1332 if (r == NULL) 1333 senderr(ENOMEM); 1334 SLIST_INSERT_HEAD(&addq, r, pfrkt_workq); 1335 p->pfrkt_root = r; 1336 } else if (!(p->pfrkt_flags & PFR_TFLAG_ACTIVE)) { 1337 SLIST_FOREACH(q, &changeq, pfrkt_workq) 1338 if (!pfr_ktable_compare(&key, q)) 1339 goto _skip; 1340 p->pfrkt_nflags = (p->pfrkt_flags & 1341 ~PFR_TFLAG_USRMASK) | key.pfrkt_flags; 1342 SLIST_INSERT_HEAD(&changeq, p, pfrkt_workq); 1343 xadd++; 1344 } 1345 _skip: 1346 ; 1347 } 1348 if (!(flags & PFR_FLAG_DUMMY)) { 1349 pfr_insert_ktables(&addq); 1350 pfr_setflags_ktables(&changeq); 1351 } else 1352 pfr_destroy_ktables(&addq, 0); 1353 if (nadd != NULL) 1354 *nadd = xadd; 1355 return (0); 1356 _bad: 1357 pfr_destroy_ktables(&addq, 0); 1358 return (rv); 1359 } 1360 1361 int 1362 pfr_del_tables(struct pfr_table *tbl, int size, int *ndel, int flags) 1363 { 1364 struct pfr_ktableworkq workq; 1365 struct pfr_ktable *p, *q, key; 1366 int i, xdel = 0; 1367 1368 ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY); 1369 SLIST_INIT(&workq); 1370 for (i = 0; i < size; i++) { 1371 YIELD(i, flags & PFR_FLAG_USERIOCTL); 1372 if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t), flags)) 1373 return (EFAULT); 1374 if (pfr_validate_table(&key.pfrkt_t, 0, 1375 flags & PFR_FLAG_USERIOCTL)) 1376 return (EINVAL); 1377 p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key); 1378 if (p != NULL && (p->pfrkt_flags & PFR_TFLAG_ACTIVE)) { 1379 SLIST_FOREACH(q, &workq, pfrkt_workq) 1380 if (!pfr_ktable_compare(p, q)) 1381 goto _skip; 1382 p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_ACTIVE; 1383 SLIST_INSERT_HEAD(&workq, p, pfrkt_workq); 1384 xdel++; 1385 } 1386 _skip: 1387 ; 1388 } 1389 1390 if (!(flags & PFR_FLAG_DUMMY)) { 1391 pfr_setflags_ktables(&workq); 1392 } 1393 if (ndel != NULL) 1394 *ndel = xdel; 1395 return (0); 1396 } 1397 1398 int 1399 pfr_get_tables(struct pfr_table *filter, struct pfr_table *tbl, int *size, 1400 int flags) 1401 { 1402 struct pfr_ktable *p; 1403 int n, nn; 1404 1405 ACCEPT_FLAGS(flags, PFR_FLAG_ALLRSETS); 1406 if (pfr_fix_anchor(filter->pfrt_anchor)) 1407 return (EINVAL); 1408 n = nn = pfr_table_count(filter, flags); 1409 if (n < 0) 1410 return (ENOENT); 1411 if (n > *size) { 1412 *size = n; 1413 return (0); 1414 } 1415 RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) { 1416 if (pfr_skip_table(filter, p, flags)) 1417 continue; 1418 if (n-- <= 0) 1419 continue; 1420 if (COPYOUT(&p->pfrkt_t, tbl++, sizeof(*tbl), flags)) 1421 return (EFAULT); 1422 } 1423 if (n) { 1424 DPFPRINTF(LOG_ERR, 1425 "pfr_get_tables: corruption detected (%d).", n); 1426 return (ENOTTY); 1427 } 1428 *size = nn; 1429 return (0); 1430 } 1431 1432 int 1433 pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size, 1434 int flags) 1435 { 1436 struct pfr_ktable *p; 1437 struct pfr_ktableworkq workq; 1438 int n, nn; 1439 time_t tzero = time_second; 1440 1441 /* XXX PFR_FLAG_CLSTATS disabled */ 1442 ACCEPT_FLAGS(flags, PFR_FLAG_ALLRSETS); 1443 if (pfr_fix_anchor(filter->pfrt_anchor)) 1444 return (EINVAL); 1445 n = nn = pfr_table_count(filter, flags); 1446 if (n < 0) 1447 return (ENOENT); 1448 if (n > *size) { 1449 *size = n; 1450 return (0); 1451 } 1452 SLIST_INIT(&workq); 1453 RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) { 1454 if (pfr_skip_table(filter, p, flags)) 1455 continue; 1456 if (n-- <= 0) 1457 continue; 1458 if (COPYOUT(&p->pfrkt_ts, tbl++, sizeof(*tbl), flags)) 1459 return (EFAULT); 1460 SLIST_INSERT_HEAD(&workq, p, pfrkt_workq); 1461 } 1462 if (flags & PFR_FLAG_CLSTATS) 1463 pfr_clstats_ktables(&workq, tzero, 1464 flags & PFR_FLAG_ADDRSTOO); 1465 if (n) { 1466 DPFPRINTF(LOG_ERR, 1467 "pfr_get_tstats: corruption detected (%d).", n); 1468 return (ENOTTY); 1469 } 1470 *size = nn; 1471 return (0); 1472 } 1473 1474 int 1475 pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags) 1476 { 1477 struct pfr_ktableworkq workq; 1478 struct pfr_ktable *p, key; 1479 int i, xzero = 0; 1480 time_t tzero = time_second; 1481 1482 ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY | PFR_FLAG_ADDRSTOO); 1483 SLIST_INIT(&workq); 1484 for (i = 0; i < size; i++) { 1485 YIELD(i, flags & PFR_FLAG_USERIOCTL); 1486 if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t), flags)) 1487 return (EFAULT); 1488 if (pfr_validate_table(&key.pfrkt_t, 0, 0)) 1489 return (EINVAL); 1490 p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key); 1491 if (p != NULL) { 1492 SLIST_INSERT_HEAD(&workq, p, pfrkt_workq); 1493 xzero++; 1494 } 1495 } 1496 if (!(flags & PFR_FLAG_DUMMY)) { 1497 pfr_clstats_ktables(&workq, tzero, flags & PFR_FLAG_ADDRSTOO); 1498 } 1499 if (nzero != NULL) 1500 *nzero = xzero; 1501 return (0); 1502 } 1503 1504 int 1505 pfr_set_tflags(struct pfr_table *tbl, int size, int setflag, int clrflag, 1506 int *nchange, int *ndel, int flags) 1507 { 1508 struct pfr_ktableworkq workq; 1509 struct pfr_ktable *p, *q, key; 1510 int i, xchange = 0, xdel = 0; 1511 1512 ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY); 1513 if ((setflag & ~PFR_TFLAG_USRMASK) || 1514 (clrflag & ~PFR_TFLAG_USRMASK) || 1515 (setflag & clrflag)) 1516 return (EINVAL); 1517 SLIST_INIT(&workq); 1518 for (i = 0; i < size; i++) { 1519 YIELD(i, flags & PFR_FLAG_USERIOCTL); 1520 if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t), flags)) 1521 return (EFAULT); 1522 if (pfr_validate_table(&key.pfrkt_t, 0, 1523 flags & PFR_FLAG_USERIOCTL)) 1524 return (EINVAL); 1525 p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key); 1526 if (p != NULL && (p->pfrkt_flags & PFR_TFLAG_ACTIVE)) { 1527 p->pfrkt_nflags = (p->pfrkt_flags | setflag) & 1528 ~clrflag; 1529 if (p->pfrkt_nflags == p->pfrkt_flags) 1530 goto _skip; 1531 SLIST_FOREACH(q, &workq, pfrkt_workq) 1532 if (!pfr_ktable_compare(p, q)) 1533 goto _skip; 1534 SLIST_INSERT_HEAD(&workq, p, pfrkt_workq); 1535 if ((p->pfrkt_flags & PFR_TFLAG_PERSIST) && 1536 (clrflag & PFR_TFLAG_PERSIST) && 1537 !(p->pfrkt_flags & PFR_TFLAG_REFERENCED)) 1538 xdel++; 1539 else 1540 xchange++; 1541 } 1542 _skip: 1543 ; 1544 } 1545 if (!(flags & PFR_FLAG_DUMMY)) { 1546 pfr_setflags_ktables(&workq); 1547 } 1548 if (nchange != NULL) 1549 *nchange = xchange; 1550 if (ndel != NULL) 1551 *ndel = xdel; 1552 return (0); 1553 } 1554 1555 int 1556 pfr_ina_begin(struct pfr_table *trs, u_int32_t *ticket, int *ndel, int flags) 1557 { 1558 struct pfr_ktableworkq workq; 1559 struct pfr_ktable *p; 1560 struct pf_ruleset *rs; 1561 int xdel = 0; 1562 1563 ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY); 1564 rs = pf_find_or_create_ruleset(trs->pfrt_anchor); 1565 if (rs == NULL) 1566 return (ENOMEM); 1567 SLIST_INIT(&workq); 1568 RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) { 1569 if (!(p->pfrkt_flags & PFR_TFLAG_INACTIVE) || 1570 pfr_skip_table(trs, p, 0)) 1571 continue; 1572 p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_INACTIVE; 1573 SLIST_INSERT_HEAD(&workq, p, pfrkt_workq); 1574 xdel++; 1575 } 1576 if (!(flags & PFR_FLAG_DUMMY)) { 1577 pfr_setflags_ktables(&workq); 1578 if (ticket != NULL) 1579 *ticket = ++rs->tticket; 1580 rs->topen = 1; 1581 } else 1582 pf_remove_if_empty_ruleset(rs); 1583 if (ndel != NULL) 1584 *ndel = xdel; 1585 return (0); 1586 } 1587 1588 int 1589 pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size, 1590 int *nadd, int *naddr, u_int32_t ticket, int flags) 1591 { 1592 struct pfr_ktableworkq tableq; 1593 struct pfr_kentryworkq addrq; 1594 struct pfr_ktable *kt, *rt, *shadow, key; 1595 struct pfr_kentry *p; 1596 struct pfr_addr ad; 1597 struct pf_ruleset *rs; 1598 int i, rv, xadd = 0, xaddr = 0; 1599 1600 ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY | PFR_FLAG_ADDRSTOO); 1601 if (size && !(flags & PFR_FLAG_ADDRSTOO)) 1602 return (EINVAL); 1603 if (pfr_validate_table(tbl, PFR_TFLAG_USRMASK, 1604 flags & PFR_FLAG_USERIOCTL)) 1605 return (EINVAL); 1606 rs = pf_find_ruleset(tbl->pfrt_anchor); 1607 if (rs == NULL || !rs->topen || ticket != rs->tticket) 1608 return (EBUSY); 1609 tbl->pfrt_flags |= PFR_TFLAG_INACTIVE; 1610 SLIST_INIT(&tableq); 1611 kt = RB_FIND(pfr_ktablehead, &pfr_ktables, (struct pfr_ktable *)tbl); 1612 if (kt == NULL) { 1613 kt = pfr_create_ktable(tbl, 0, 1, 1614 !(flags & PFR_FLAG_USERIOCTL)); 1615 if (kt == NULL) 1616 return (ENOMEM); 1617 SLIST_INSERT_HEAD(&tableq, kt, pfrkt_workq); 1618 xadd++; 1619 if (!tbl->pfrt_anchor[0]) 1620 goto _skip; 1621 1622 /* find or create root table */ 1623 bzero(&key, sizeof(key)); 1624 strlcpy(key.pfrkt_name, tbl->pfrt_name, sizeof(key.pfrkt_name)); 1625 rt = RB_FIND(pfr_ktablehead, &pfr_ktables, &key); 1626 if (rt != NULL) { 1627 kt->pfrkt_root = rt; 1628 goto _skip; 1629 } 1630 rt = pfr_create_ktable(&key.pfrkt_t, 0, 1, 1631 !(flags & PFR_FLAG_USERIOCTL)); 1632 if (rt == NULL) { 1633 pfr_destroy_ktables(&tableq, 0); 1634 return (ENOMEM); 1635 } 1636 SLIST_INSERT_HEAD(&tableq, rt, pfrkt_workq); 1637 kt->pfrkt_root = rt; 1638 } else if (!(kt->pfrkt_flags & PFR_TFLAG_INACTIVE)) 1639 xadd++; 1640 _skip: 1641 shadow = pfr_create_ktable(tbl, 0, 0, !(flags & PFR_FLAG_USERIOCTL)); 1642 if (shadow == NULL) { 1643 pfr_destroy_ktables(&tableq, 0); 1644 return (ENOMEM); 1645 } 1646 SLIST_INIT(&addrq); 1647 for (i = 0; i < size; i++) { 1648 YIELD(i, flags & PFR_FLAG_USERIOCTL); 1649 if (COPYIN(addr+i, &ad, sizeof(ad), flags)) 1650 senderr(EFAULT); 1651 if (pfr_validate_addr(&ad)) 1652 senderr(EINVAL); 1653 if (pfr_lookup_addr(shadow, &ad, 1) != NULL) 1654 continue; 1655 p = pfr_create_kentry(&ad); 1656 if (p == NULL) 1657 senderr(ENOMEM); 1658 if (pfr_route_kentry(shadow, p)) { 1659 pfr_destroy_kentry(p); 1660 continue; 1661 } 1662 SLIST_INSERT_HEAD(&addrq, p, pfrke_workq); 1663 xaddr++; 1664 if (p->pfrke_type == PFRKE_COST) 1665 kt->pfrkt_refcntcost++; 1666 pfr_ktable_winfo_update(kt, p); 1667 } 1668 if (!(flags & PFR_FLAG_DUMMY)) { 1669 if (kt->pfrkt_shadow != NULL) 1670 pfr_destroy_ktable(kt->pfrkt_shadow, 1); 1671 kt->pfrkt_flags |= PFR_TFLAG_INACTIVE; 1672 pfr_insert_ktables(&tableq); 1673 shadow->pfrkt_cnt = (flags & PFR_FLAG_ADDRSTOO) ? 1674 xaddr : NO_ADDRESSES; 1675 kt->pfrkt_shadow = shadow; 1676 } else { 1677 pfr_clean_node_mask(shadow, &addrq); 1678 pfr_destroy_ktable(shadow, 0); 1679 pfr_destroy_ktables(&tableq, 0); 1680 pfr_destroy_kentries(&addrq); 1681 } 1682 if (nadd != NULL) 1683 *nadd = xadd; 1684 if (naddr != NULL) 1685 *naddr = xaddr; 1686 return (0); 1687 _bad: 1688 pfr_destroy_ktable(shadow, 0); 1689 pfr_destroy_ktables(&tableq, 0); 1690 pfr_destroy_kentries(&addrq); 1691 return (rv); 1692 } 1693 1694 int 1695 pfr_ina_rollback(struct pfr_table *trs, u_int32_t ticket, int *ndel, int flags) 1696 { 1697 struct pfr_ktableworkq workq; 1698 struct pfr_ktable *p; 1699 struct pf_ruleset *rs; 1700 int xdel = 0; 1701 1702 ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY); 1703 rs = pf_find_ruleset(trs->pfrt_anchor); 1704 if (rs == NULL || !rs->topen || ticket != rs->tticket) 1705 return (0); 1706 SLIST_INIT(&workq); 1707 RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) { 1708 if (!(p->pfrkt_flags & PFR_TFLAG_INACTIVE) || 1709 pfr_skip_table(trs, p, 0)) 1710 continue; 1711 p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_INACTIVE; 1712 SLIST_INSERT_HEAD(&workq, p, pfrkt_workq); 1713 xdel++; 1714 } 1715 if (!(flags & PFR_FLAG_DUMMY)) { 1716 pfr_setflags_ktables(&workq); 1717 rs->topen = 0; 1718 pf_remove_if_empty_ruleset(rs); 1719 } 1720 if (ndel != NULL) 1721 *ndel = xdel; 1722 return (0); 1723 } 1724 1725 int 1726 pfr_ina_commit(struct pfr_table *trs, u_int32_t ticket, int *nadd, 1727 int *nchange, int flags) 1728 { 1729 struct pfr_ktable *p, *q; 1730 struct pfr_ktableworkq workq; 1731 struct pf_ruleset *rs; 1732 int xadd = 0, xchange = 0; 1733 time_t tzero = time_second; 1734 1735 ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY); 1736 rs = pf_find_ruleset(trs->pfrt_anchor); 1737 if (rs == NULL || !rs->topen || ticket != rs->tticket) 1738 return (EBUSY); 1739 1740 SLIST_INIT(&workq); 1741 RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) { 1742 if (!(p->pfrkt_flags & PFR_TFLAG_INACTIVE) || 1743 pfr_skip_table(trs, p, 0)) 1744 continue; 1745 SLIST_INSERT_HEAD(&workq, p, pfrkt_workq); 1746 if (p->pfrkt_flags & PFR_TFLAG_ACTIVE) 1747 xchange++; 1748 else 1749 xadd++; 1750 } 1751 1752 if (!(flags & PFR_FLAG_DUMMY)) { 1753 for (p = SLIST_FIRST(&workq); p != NULL; p = q) { 1754 q = SLIST_NEXT(p, pfrkt_workq); 1755 pfr_commit_ktable(p, tzero); 1756 } 1757 rs->topen = 0; 1758 pf_remove_if_empty_ruleset(rs); 1759 } 1760 if (nadd != NULL) 1761 *nadd = xadd; 1762 if (nchange != NULL) 1763 *nchange = xchange; 1764 1765 return (0); 1766 } 1767 1768 void 1769 pfr_commit_ktable(struct pfr_ktable *kt, time_t tzero) 1770 { 1771 struct pfr_ktable *shadow = kt->pfrkt_shadow; 1772 int nflags; 1773 1774 if (shadow->pfrkt_cnt == NO_ADDRESSES) { 1775 if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) 1776 pfr_clstats_ktable(kt, tzero, 1); 1777 } else if (kt->pfrkt_flags & PFR_TFLAG_ACTIVE) { 1778 /* kt might contain addresses */ 1779 struct pfr_kentryworkq addrq, addq, changeq, delq, garbageq; 1780 struct pfr_kentry *p, *q, *next; 1781 struct pfr_addr ad; 1782 1783 pfr_enqueue_addrs(shadow, &addrq, NULL, 0); 1784 pfr_mark_addrs(kt); 1785 SLIST_INIT(&addq); 1786 SLIST_INIT(&changeq); 1787 SLIST_INIT(&delq); 1788 SLIST_INIT(&garbageq); 1789 pfr_clean_node_mask(shadow, &addrq); 1790 for (p = SLIST_FIRST(&addrq); p != NULL; p = next) { 1791 next = SLIST_NEXT(p, pfrke_workq); /* XXX */ 1792 pfr_copyout_addr(&ad, p); 1793 q = pfr_lookup_addr(kt, &ad, 1); 1794 if (q != NULL) { 1795 if ((q->pfrke_flags & PFRKE_FLAG_NOT) != 1796 (p->pfrke_flags & PFRKE_FLAG_NOT)) 1797 SLIST_INSERT_HEAD(&changeq, q, 1798 pfrke_workq); 1799 q->pfrke_flags |= PFRKE_FLAG_MARK; 1800 SLIST_INSERT_HEAD(&garbageq, p, pfrke_workq); 1801 } else { 1802 p->pfrke_tzero = tzero; 1803 SLIST_INSERT_HEAD(&addq, p, pfrke_workq); 1804 } 1805 } 1806 pfr_enqueue_addrs(kt, &delq, NULL, ENQUEUE_UNMARKED_ONLY); 1807 pfr_insert_kentries(kt, &addq, tzero); 1808 pfr_remove_kentries(kt, &delq); 1809 pfr_clstats_kentries(&changeq, tzero, INVERT_NEG_FLAG); 1810 pfr_destroy_kentries(&garbageq); 1811 } else { 1812 /* kt cannot contain addresses */ 1813 SWAP(struct radix_node_head *, kt->pfrkt_ip4, 1814 shadow->pfrkt_ip4); 1815 SWAP(struct radix_node_head *, kt->pfrkt_ip6, 1816 shadow->pfrkt_ip6); 1817 SWAP(int, kt->pfrkt_cnt, shadow->pfrkt_cnt); 1818 pfr_clstats_ktable(kt, tzero, 1); 1819 } 1820 nflags = ((shadow->pfrkt_flags & PFR_TFLAG_USRMASK) | 1821 (kt->pfrkt_flags & PFR_TFLAG_SETMASK) | PFR_TFLAG_ACTIVE) 1822 & ~PFR_TFLAG_INACTIVE; 1823 pfr_destroy_ktable(shadow, 0); 1824 kt->pfrkt_shadow = NULL; 1825 pfr_setflags_ktable(kt, nflags); 1826 } 1827 1828 int 1829 pfr_validate_table(struct pfr_table *tbl, int allowedflags, int no_reserved) 1830 { 1831 int i; 1832 1833 if (!tbl->pfrt_name[0]) 1834 return (-1); 1835 if (no_reserved && !strcmp(tbl->pfrt_anchor, PF_RESERVED_ANCHOR)) 1836 return (-1); 1837 if (tbl->pfrt_name[PF_TABLE_NAME_SIZE-1]) 1838 return (-1); 1839 for (i = strlen(tbl->pfrt_name); i < PF_TABLE_NAME_SIZE; i++) 1840 if (tbl->pfrt_name[i]) 1841 return (-1); 1842 if (pfr_fix_anchor(tbl->pfrt_anchor)) 1843 return (-1); 1844 if (tbl->pfrt_flags & ~allowedflags) 1845 return (-1); 1846 return (0); 1847 } 1848 1849 /* 1850 * Rewrite anchors referenced by tables to remove slashes 1851 * and check for validity. 1852 */ 1853 int 1854 pfr_fix_anchor(char *anchor) 1855 { 1856 size_t siz = MAXPATHLEN; 1857 int i; 1858 1859 if (anchor[0] == '/') { 1860 char *path; 1861 int off; 1862 1863 path = anchor; 1864 off = 1; 1865 while (*++path == '/') 1866 off++; 1867 bcopy(path, anchor, siz - off); 1868 memset(anchor + siz - off, 0, off); 1869 } 1870 if (anchor[siz - 1]) 1871 return (-1); 1872 for (i = strlen(anchor); i < siz; i++) 1873 if (anchor[i]) 1874 return (-1); 1875 return (0); 1876 } 1877 1878 int 1879 pfr_table_count(struct pfr_table *filter, int flags) 1880 { 1881 struct pf_ruleset *rs; 1882 1883 if (flags & PFR_FLAG_ALLRSETS) 1884 return (pfr_ktable_cnt); 1885 if (filter->pfrt_anchor[0]) { 1886 rs = pf_find_ruleset(filter->pfrt_anchor); 1887 return ((rs != NULL) ? rs->tables : -1); 1888 } 1889 return (pf_main_ruleset.tables); 1890 } 1891 1892 int 1893 pfr_skip_table(struct pfr_table *filter, struct pfr_ktable *kt, int flags) 1894 { 1895 if (flags & PFR_FLAG_ALLRSETS) 1896 return (0); 1897 if (strcmp(filter->pfrt_anchor, kt->pfrkt_anchor)) 1898 return (1); 1899 return (0); 1900 } 1901 1902 void 1903 pfr_insert_ktables(struct pfr_ktableworkq *workq) 1904 { 1905 struct pfr_ktable *p; 1906 1907 SLIST_FOREACH(p, workq, pfrkt_workq) 1908 pfr_insert_ktable(p); 1909 } 1910 1911 void 1912 pfr_insert_ktable(struct pfr_ktable *kt) 1913 { 1914 RB_INSERT(pfr_ktablehead, &pfr_ktables, kt); 1915 pfr_ktable_cnt++; 1916 if (kt->pfrkt_root != NULL) 1917 if (!kt->pfrkt_root->pfrkt_refcnt[PFR_REFCNT_ANCHOR]++) 1918 pfr_setflags_ktable(kt->pfrkt_root, 1919 kt->pfrkt_root->pfrkt_flags|PFR_TFLAG_REFDANCHOR); 1920 } 1921 1922 void 1923 pfr_setflags_ktables(struct pfr_ktableworkq *workq) 1924 { 1925 struct pfr_ktable *p, *q; 1926 1927 for (p = SLIST_FIRST(workq); p; p = q) { 1928 q = SLIST_NEXT(p, pfrkt_workq); 1929 pfr_setflags_ktable(p, p->pfrkt_nflags); 1930 } 1931 } 1932 1933 void 1934 pfr_setflags_ktable(struct pfr_ktable *kt, int newf) 1935 { 1936 struct pfr_kentryworkq addrq; 1937 1938 if (!(newf & PFR_TFLAG_REFERENCED) && 1939 !(newf & PFR_TFLAG_REFDANCHOR) && 1940 !(newf & PFR_TFLAG_PERSIST)) 1941 newf &= ~PFR_TFLAG_ACTIVE; 1942 if (!(newf & PFR_TFLAG_ACTIVE)) 1943 newf &= ~PFR_TFLAG_USRMASK; 1944 if (!(newf & PFR_TFLAG_SETMASK)) { 1945 RB_REMOVE(pfr_ktablehead, &pfr_ktables, kt); 1946 if (kt->pfrkt_root != NULL) 1947 if (!--kt->pfrkt_root->pfrkt_refcnt[PFR_REFCNT_ANCHOR]) 1948 pfr_setflags_ktable(kt->pfrkt_root, 1949 kt->pfrkt_root->pfrkt_flags & 1950 ~PFR_TFLAG_REFDANCHOR); 1951 pfr_destroy_ktable(kt, 1); 1952 pfr_ktable_cnt--; 1953 return; 1954 } 1955 if (!(newf & PFR_TFLAG_ACTIVE) && kt->pfrkt_cnt) { 1956 pfr_enqueue_addrs(kt, &addrq, NULL, 0); 1957 pfr_remove_kentries(kt, &addrq); 1958 } 1959 if (!(newf & PFR_TFLAG_INACTIVE) && kt->pfrkt_shadow != NULL) { 1960 pfr_destroy_ktable(kt->pfrkt_shadow, 1); 1961 kt->pfrkt_shadow = NULL; 1962 } 1963 kt->pfrkt_flags = newf; 1964 } 1965 1966 void 1967 pfr_clstats_ktables(struct pfr_ktableworkq *workq, time_t tzero, int recurse) 1968 { 1969 struct pfr_ktable *p; 1970 1971 SLIST_FOREACH(p, workq, pfrkt_workq) 1972 pfr_clstats_ktable(p, tzero, recurse); 1973 } 1974 1975 void 1976 pfr_clstats_ktable(struct pfr_ktable *kt, time_t tzero, int recurse) 1977 { 1978 struct pfr_kentryworkq addrq; 1979 1980 if (recurse) { 1981 pfr_enqueue_addrs(kt, &addrq, NULL, 0); 1982 pfr_clstats_kentries(&addrq, tzero, 0); 1983 } 1984 bzero(kt->pfrkt_packets, sizeof(kt->pfrkt_packets)); 1985 bzero(kt->pfrkt_bytes, sizeof(kt->pfrkt_bytes)); 1986 kt->pfrkt_match = kt->pfrkt_nomatch = 0; 1987 kt->pfrkt_tzero = tzero; 1988 } 1989 1990 struct pfr_ktable * 1991 pfr_create_ktable(struct pfr_table *tbl, time_t tzero, int attachruleset, 1992 int intr) 1993 { 1994 struct pfr_ktable *kt; 1995 struct pf_ruleset *rs; 1996 1997 if (intr) 1998 kt = pool_get(&pfr_ktable_pl, PR_NOWAIT|PR_ZERO|PR_LIMITFAIL); 1999 else 2000 kt = pool_get(&pfr_ktable_pl, PR_WAITOK|PR_ZERO|PR_LIMITFAIL); 2001 if (kt == NULL) 2002 return (NULL); 2003 kt->pfrkt_t = *tbl; 2004 2005 if (attachruleset) { 2006 rs = pf_find_or_create_ruleset(tbl->pfrt_anchor); 2007 if (!rs) { 2008 pfr_destroy_ktable(kt, 0); 2009 return (NULL); 2010 } 2011 kt->pfrkt_rs = rs; 2012 rs->tables++; 2013 } 2014 2015 if (!rn_inithead((void **)&kt->pfrkt_ip4, 2016 offsetof(struct sockaddr_in, sin_addr)) || 2017 !rn_inithead((void **)&kt->pfrkt_ip6, 2018 offsetof(struct sockaddr_in6, sin6_addr))) { 2019 pfr_destroy_ktable(kt, 0); 2020 return (NULL); 2021 } 2022 kt->pfrkt_tzero = tzero; 2023 kt->pfrkt_refcntcost = 0; 2024 kt->pfrkt_gcdweight = 0; 2025 kt->pfrkt_maxweight = 1; 2026 2027 return (kt); 2028 } 2029 2030 void 2031 pfr_destroy_ktables(struct pfr_ktableworkq *workq, int flushaddr) 2032 { 2033 struct pfr_ktable *p, *q; 2034 2035 for (p = SLIST_FIRST(workq); p; p = q) { 2036 q = SLIST_NEXT(p, pfrkt_workq); 2037 pfr_destroy_ktable(p, flushaddr); 2038 } 2039 } 2040 2041 void 2042 pfr_destroy_ktable(struct pfr_ktable *kt, int flushaddr) 2043 { 2044 struct pfr_kentryworkq addrq; 2045 2046 if (flushaddr) { 2047 pfr_enqueue_addrs(kt, &addrq, NULL, 0); 2048 pfr_clean_node_mask(kt, &addrq); 2049 pfr_destroy_kentries(&addrq); 2050 } 2051 if (kt->pfrkt_ip4 != NULL) 2052 free((caddr_t)kt->pfrkt_ip4, M_RTABLE, 0); 2053 if (kt->pfrkt_ip6 != NULL) 2054 free((caddr_t)kt->pfrkt_ip6, M_RTABLE, 0); 2055 if (kt->pfrkt_shadow != NULL) 2056 pfr_destroy_ktable(kt->pfrkt_shadow, flushaddr); 2057 if (kt->pfrkt_rs != NULL) { 2058 kt->pfrkt_rs->tables--; 2059 pf_remove_if_empty_ruleset(kt->pfrkt_rs); 2060 } 2061 pool_put(&pfr_ktable_pl, kt); 2062 } 2063 2064 int 2065 pfr_ktable_compare(struct pfr_ktable *p, struct pfr_ktable *q) 2066 { 2067 int d; 2068 2069 if ((d = strncmp(p->pfrkt_name, q->pfrkt_name, PF_TABLE_NAME_SIZE))) 2070 return (d); 2071 return (strcmp(p->pfrkt_anchor, q->pfrkt_anchor)); 2072 } 2073 2074 struct pfr_ktable * 2075 pfr_lookup_table(struct pfr_table *tbl) 2076 { 2077 /* struct pfr_ktable start like a struct pfr_table */ 2078 return (RB_FIND(pfr_ktablehead, &pfr_ktables, 2079 (struct pfr_ktable *)tbl)); 2080 } 2081 2082 int 2083 pfr_match_addr(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af) 2084 { 2085 struct pfr_kentry *ke = NULL; 2086 struct sockaddr_in tmp4; 2087 #ifdef INET6 2088 struct sockaddr_in6 tmp6; 2089 #endif /* INET6 */ 2090 int match; 2091 2092 if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && kt->pfrkt_root != NULL) 2093 kt = kt->pfrkt_root; 2094 if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) 2095 return (0); 2096 2097 switch (af) { 2098 case AF_INET: 2099 bzero(&tmp4, sizeof(tmp4)); 2100 tmp4.sin_len = sizeof(tmp4); 2101 tmp4.sin_family = AF_INET; 2102 tmp4.sin_addr.s_addr = a->addr32[0]; 2103 ke = (struct pfr_kentry *)rn_match(&tmp4, kt->pfrkt_ip4); 2104 break; 2105 #ifdef INET6 2106 case AF_INET6: 2107 bzero(&tmp6, sizeof(tmp6)); 2108 tmp6.sin6_len = sizeof(tmp6); 2109 tmp6.sin6_family = AF_INET6; 2110 bcopy(a, &tmp6.sin6_addr, sizeof(tmp6.sin6_addr)); 2111 ke = (struct pfr_kentry *)rn_match(&tmp6, kt->pfrkt_ip6); 2112 break; 2113 #endif /* INET6 */ 2114 default: 2115 unhandled_af(af); 2116 } 2117 match = (ke && !(ke->pfrke_flags & PFRKE_FLAG_NOT)); 2118 if (match) 2119 kt->pfrkt_match++; 2120 else 2121 kt->pfrkt_nomatch++; 2122 return (match); 2123 } 2124 2125 void 2126 pfr_update_stats(struct pfr_ktable *kt, struct pf_addr *a, struct pf_pdesc *pd, 2127 int op, int notrule) 2128 { 2129 struct pfr_kentry *ke = NULL; 2130 struct sockaddr_in tmp4; 2131 #ifdef INET6 2132 struct sockaddr_in6 tmp6; 2133 #endif /* INET6 */ 2134 sa_family_t af = pd->af; 2135 u_int64_t len = pd->tot_len; 2136 int dir_idx = (pd->dir == PF_OUT); 2137 int op_idx; 2138 2139 if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && kt->pfrkt_root != NULL) 2140 kt = kt->pfrkt_root; 2141 if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) 2142 return; 2143 2144 switch (af) { 2145 case AF_INET: 2146 bzero(&tmp4, sizeof(tmp4)); 2147 tmp4.sin_len = sizeof(tmp4); 2148 tmp4.sin_family = AF_INET; 2149 tmp4.sin_addr.s_addr = a->addr32[0]; 2150 ke = (struct pfr_kentry *)rn_match(&tmp4, kt->pfrkt_ip4); 2151 break; 2152 #ifdef INET6 2153 case AF_INET6: 2154 bzero(&tmp6, sizeof(tmp6)); 2155 tmp6.sin6_len = sizeof(tmp6); 2156 tmp6.sin6_family = AF_INET6; 2157 bcopy(a, &tmp6.sin6_addr, sizeof(tmp6.sin6_addr)); 2158 ke = (struct pfr_kentry *)rn_match(&tmp6, 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 struct sockaddr_in tmp4; 2264 #ifdef INET6 2265 struct sockaddr_in6 tmp6; 2266 #endif 2267 int startidx, idx = -1, loop = 0, use_counter = 0; 2268 2269 switch (af) { 2270 case AF_INET: 2271 bzero(&tmp4, sizeof(tmp4)); 2272 tmp4.sin_len = sizeof(tmp4); 2273 tmp4.sin_family = AF_INET; 2274 addr = (struct pf_addr *)&tmp4.sin_addr; 2275 break; 2276 #ifdef INET6 2277 case AF_INET6: 2278 bzero(&tmp6, sizeof(tmp6)); 2279 tmp6.sin6_len = sizeof(tmp6); 2280 tmp6.sin6_family = AF_INET6; 2281 addr = (struct pf_addr *)&tmp6.sin6_addr; 2282 break; 2283 #endif /* INET6 */ 2284 default: 2285 unhandled_af(af); 2286 } 2287 2288 if (rpool->addr.type == PF_ADDR_TABLE) 2289 kt = rpool->addr.p.tbl; 2290 else if (rpool->addr.type == PF_ADDR_DYNIFTL) 2291 kt = rpool->addr.p.dyn->pfid_kt; 2292 else 2293 return (-1); 2294 if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && kt->pfrkt_root != NULL) 2295 kt = kt->pfrkt_root; 2296 if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) 2297 return (-1); 2298 2299 counter = &rpool->counter; 2300 idx = rpool->tblidx; 2301 if (idx < 0 || idx >= kt->pfrkt_cnt) 2302 idx = 0; 2303 else 2304 use_counter = 1; 2305 startidx = idx; 2306 2307 _next_block: 2308 if (loop && startidx == idx) { 2309 kt->pfrkt_nomatch++; 2310 return (1); 2311 } 2312 2313 ke = pfr_kentry_byidx(kt, idx, af); 2314 if (ke == NULL) { 2315 /* we don't have this idx, try looping */ 2316 if (loop || (ke = pfr_kentry_byidx(kt, 0, af)) == NULL) { 2317 kt->pfrkt_nomatch++; 2318 return (1); 2319 } 2320 idx = 0; 2321 loop++; 2322 } 2323 2324 /* Get current weight for weighted round-robin */ 2325 if (idx == 0 && use_counter == 1 && kt->pfrkt_refcntcost > 0) { 2326 rpool->curweight = rpool->curweight - kt->pfrkt_gcdweight; 2327 2328 if (rpool->curweight < 1) 2329 rpool->curweight = kt->pfrkt_maxweight; 2330 } 2331 2332 pfr_prepare_network(&pfr_mask, af, ke->pfrke_net); 2333 *raddr = SUNION2PF(&ke->pfrke_sa, af); 2334 *rmask = SUNION2PF(&pfr_mask, af); 2335 2336 if (use_counter && !PF_AZERO(counter, af)) { 2337 /* is supplied address within block? */ 2338 if (!PF_MATCHA(0, *raddr, *rmask, counter, af)) { 2339 /* no, go to next block in table */ 2340 idx++; 2341 use_counter = 0; 2342 goto _next_block; 2343 } 2344 PF_ACPY(addr, counter, af); 2345 } else { 2346 /* use first address of block */ 2347 PF_ACPY(addr, *raddr, af); 2348 } 2349 2350 if (!KENTRY_NETWORK(ke)) { 2351 /* this is a single IP address - no possible nested block */ 2352 if (rpool->addr.type == PF_ADDR_DYNIFTL && 2353 pfr_islinklocal(af, addr)) { 2354 idx++; 2355 goto _next_block; 2356 } 2357 PF_ACPY(counter, addr, af); 2358 rpool->tblidx = idx; 2359 kt->pfrkt_match++; 2360 rpool->states = 0; 2361 if (ke->pfrke_counters != NULL) 2362 rpool->states = ke->pfrke_counters->states; 2363 switch (ke->pfrke_type) { 2364 case PFRKE_COST: 2365 rpool->weight = ((struct pfr_kentry_cost *)ke)->weight; 2366 /* FALLTHROUGH */ 2367 case PFRKE_ROUTE: 2368 rpool->kif = ((struct pfr_kentry_route *)ke)->kif; 2369 break; 2370 default: 2371 rpool->weight = 1; 2372 break; 2373 } 2374 return (0); 2375 } 2376 for (;;) { 2377 /* we don't want to use a nested block */ 2378 switch (af) { 2379 case AF_INET: 2380 ke2 = (struct pfr_kentry *)rn_match(&tmp4, 2381 kt->pfrkt_ip4); 2382 break; 2383 #ifdef INET6 2384 case AF_INET6: 2385 ke2 = (struct pfr_kentry *)rn_match(&tmp6, 2386 kt->pfrkt_ip6); 2387 break; 2388 #endif /* INET6 */ 2389 default: 2390 unhandled_af(af); 2391 } 2392 if (ke2 == ke) { 2393 /* lookup return the same block - perfect */ 2394 if (rpool->addr.type == PF_ADDR_DYNIFTL && 2395 pfr_islinklocal(af, addr)) 2396 goto _next_entry; 2397 PF_ACPY(counter, addr, af); 2398 rpool->tblidx = idx; 2399 kt->pfrkt_match++; 2400 rpool->states = 0; 2401 if (ke->pfrke_counters != NULL) 2402 rpool->states = ke->pfrke_counters->states; 2403 switch (ke->pfrke_type) { 2404 case PFRKE_COST: 2405 rpool->weight = 2406 ((struct pfr_kentry_cost *)ke)->weight; 2407 /* FALLTHROUGH */ 2408 case PFRKE_ROUTE: 2409 rpool->kif = ((struct pfr_kentry_route *)ke)->kif; 2410 break; 2411 default: 2412 rpool->weight = 1; 2413 break; 2414 } 2415 return (0); 2416 } 2417 _next_entry: 2418 /* we need to increase the counter past the nested block */ 2419 pfr_prepare_network(&mask, AF_INET, ke2->pfrke_net); 2420 PF_POOLMASK(addr, addr, SUNION2PF(&mask, af), &pfr_ffaddr, af); 2421 PF_AINC(addr, af); 2422 if (!PF_MATCHA(0, *raddr, *rmask, addr, af)) { 2423 /* ok, we reached the end of our main block */ 2424 /* go to next block in table */ 2425 idx++; 2426 use_counter = 0; 2427 goto _next_block; 2428 } 2429 } 2430 } 2431 2432 struct pfr_kentry * 2433 pfr_kentry_byidx(struct pfr_ktable *kt, int idx, int af) 2434 { 2435 struct pfr_walktree w; 2436 2437 bzero(&w, sizeof(w)); 2438 w.pfrw_op = PFRW_POOL_GET; 2439 w.pfrw_cnt = idx; 2440 2441 switch (af) { 2442 case AF_INET: 2443 rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w); 2444 return (w.pfrw_kentry); 2445 #ifdef INET6 2446 case AF_INET6: 2447 rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w); 2448 return (w.pfrw_kentry); 2449 #endif /* INET6 */ 2450 default: 2451 return (NULL); 2452 } 2453 } 2454 2455 /* Added for load balancing state counter use. */ 2456 int 2457 pfr_states_increase(struct pfr_ktable *kt, struct pf_addr *addr, int af) 2458 { 2459 struct pfr_kentry *ke; 2460 2461 ke = pfr_kentry_byaddr(kt, addr, af, 1); 2462 if (ke == NULL) 2463 return (-1); 2464 2465 if (ke->pfrke_counters == NULL) 2466 ke->pfrke_counters = pool_get(&pfr_kcounters_pl, 2467 PR_NOWAIT | PR_ZERO); 2468 if (ke->pfrke_counters == NULL) 2469 return (-1); 2470 2471 ke->pfrke_counters->states++; 2472 return ke->pfrke_counters->states; 2473 } 2474 2475 /* Added for load balancing state counter use. */ 2476 int 2477 pfr_states_decrease(struct pfr_ktable *kt, struct pf_addr *addr, int af) 2478 { 2479 struct pfr_kentry *ke; 2480 2481 ke = pfr_kentry_byaddr(kt, addr, af, 1); 2482 if (ke == NULL) 2483 return (-1); 2484 2485 if (ke->pfrke_counters == NULL) 2486 ke->pfrke_counters = pool_get(&pfr_kcounters_pl, 2487 PR_NOWAIT | PR_ZERO); 2488 if (ke->pfrke_counters == NULL) 2489 return (-1); 2490 2491 if (ke->pfrke_counters->states > 0) 2492 ke->pfrke_counters->states--; 2493 else 2494 DPFPRINTF(LOG_DEBUG, 2495 "pfr_states_decrease: states-- when states <= 0"); 2496 2497 return ke->pfrke_counters->states; 2498 } 2499 2500 /* 2501 * Added for load balancing to find a kentry outside of the table. 2502 * We need to create a custom pfr_addr struct. 2503 */ 2504 struct pfr_kentry * 2505 pfr_kentry_byaddr(struct pfr_ktable *kt, struct pf_addr *addr, sa_family_t af, 2506 int exact) 2507 { 2508 struct pfr_kentry *ke; 2509 struct pfr_addr p; 2510 2511 bzero(&p, sizeof(p)); 2512 p.pfra_af = af; 2513 switch (af) { 2514 case AF_INET: 2515 p.pfra_net = 32; 2516 p.pfra_ip4addr = addr->v4; 2517 break; 2518 #ifdef INET6 2519 case AF_INET6: 2520 p.pfra_net = 128; 2521 p.pfra_ip6addr = addr->v6; 2522 break; 2523 #endif /* INET6 */ 2524 default: 2525 unhandled_af(af); 2526 } 2527 2528 ke = pfr_lookup_addr(kt, &p, exact); 2529 2530 return ke; 2531 } 2532 2533 void 2534 pfr_dynaddr_update(struct pfr_ktable *kt, struct pfi_dynaddr *dyn) 2535 { 2536 struct pfr_walktree w; 2537 2538 bzero(&w, sizeof(w)); 2539 w.pfrw_op = PFRW_DYNADDR_UPDATE; 2540 w.pfrw_dyn = dyn; 2541 2542 dyn->pfid_acnt4 = 0; 2543 dyn->pfid_acnt6 = 0; 2544 switch (dyn->pfid_af) { 2545 case AF_UNSPEC: /* look up all both addresses IPv4 + IPv6 */ 2546 rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w); 2547 rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w); 2548 break; 2549 case AF_INET: 2550 rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w); 2551 break; 2552 #ifdef INET6 2553 case AF_INET6: 2554 rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w); 2555 break; 2556 #endif /* INET6 */ 2557 default: 2558 unhandled_af(dyn->pfid_af); 2559 } 2560 } 2561 2562 void 2563 pfr_ktable_winfo_update(struct pfr_ktable *kt, struct pfr_kentry *p) { 2564 /* 2565 * If cost flag is set, 2566 * gcdweight is needed for round-robin. 2567 */ 2568 if (kt->pfrkt_refcntcost > 0) { 2569 u_int16_t weight; 2570 2571 weight = (p->pfrke_type == PFRKE_COST) ? 2572 ((struct pfr_kentry_cost *)p)->weight : 1; 2573 2574 if (kt->pfrkt_gcdweight == 0) 2575 kt->pfrkt_gcdweight = weight; 2576 2577 kt->pfrkt_gcdweight = 2578 pfr_gcd(weight, kt->pfrkt_gcdweight); 2579 2580 if (kt->pfrkt_maxweight < weight) 2581 kt->pfrkt_maxweight = weight; 2582 } 2583 } 2584