1 /* $OpenBSD: pf_lb.c,v 1.17 2011/07/29 10:48:35 mcbride Exp $ */ 2 3 /* 4 * Copyright (c) 2001 Daniel Hartmeier 5 * Copyright (c) 2002 - 2008 Henning Brauer 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * - Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * - Redistributions in binary form must reproduce the above 15 * copyright notice, this list of conditions and the following 16 * disclaimer in the documentation and/or other materials provided 17 * with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 25 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 29 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 * 32 * Effort sponsored in part by the Defense Advanced Research Projects 33 * Agency (DARPA) and Air Force Research Laboratory, Air Force 34 * Materiel Command, USAF, under agreement number F30602-01-2-0537. 35 * 36 */ 37 38 #include "bpfilter.h" 39 #include "pflog.h" 40 #include "pfsync.h" 41 #include "pflow.h" 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/mbuf.h> 46 #include <sys/filio.h> 47 #include <sys/socket.h> 48 #include <sys/socketvar.h> 49 #include <sys/kernel.h> 50 #include <sys/time.h> 51 #include <sys/pool.h> 52 #include <sys/proc.h> 53 #include <sys/rwlock.h> 54 #include <sys/syslog.h> 55 56 #include <crypto/md5.h> 57 58 #include <net/if.h> 59 #include <net/if_types.h> 60 #include <net/bpf.h> 61 #include <net/route.h> 62 #include <net/radix_mpath.h> 63 64 #include <netinet/in.h> 65 #include <netinet/in_var.h> 66 #include <netinet/in_systm.h> 67 #include <netinet/ip.h> 68 #include <netinet/ip_var.h> 69 #include <netinet/tcp.h> 70 #include <netinet/tcp_seq.h> 71 #include <netinet/udp.h> 72 #include <netinet/ip_icmp.h> 73 #include <netinet/in_pcb.h> 74 #include <netinet/tcp_timer.h> 75 #include <netinet/tcp_var.h> 76 #include <netinet/udp_var.h> 77 #include <netinet/icmp_var.h> 78 #include <netinet/if_ether.h> 79 80 #include <dev/rndvar.h> 81 #include <net/pfvar.h> 82 #include <net/if_pflog.h> 83 #include <net/if_pflow.h> 84 85 #if NPFSYNC > 0 86 #include <net/if_pfsync.h> 87 #endif /* NPFSYNC > 0 */ 88 89 #ifdef INET6 90 #include <netinet/ip6.h> 91 #include <netinet/in_pcb.h> 92 #include <netinet/icmp6.h> 93 #include <netinet6/nd6.h> 94 #endif /* INET6 */ 95 96 97 /* 98 * Global variables 99 */ 100 101 void pf_hash(struct pf_addr *, struct pf_addr *, 102 struct pf_poolhashkey *, sa_family_t); 103 int pf_get_sport(struct pf_pdesc *, struct pf_rule *, 104 struct pf_addr *, u_int16_t *, u_int16_t, 105 u_int16_t, struct pf_src_node **); 106 int pf_islinklocal(sa_family_t, struct pf_addr *); 107 108 #define mix(a,b,c) \ 109 do { \ 110 a -= b; a -= c; a ^= (c >> 13); \ 111 b -= c; b -= a; b ^= (a << 8); \ 112 c -= a; c -= b; c ^= (b >> 13); \ 113 a -= b; a -= c; a ^= (c >> 12); \ 114 b -= c; b -= a; b ^= (a << 16); \ 115 c -= a; c -= b; c ^= (b >> 5); \ 116 a -= b; a -= c; a ^= (c >> 3); \ 117 b -= c; b -= a; b ^= (a << 10); \ 118 c -= a; c -= b; c ^= (b >> 15); \ 119 } while (0) 120 121 /* 122 * hash function based on bridge_hash in if_bridge.c 123 */ 124 void 125 pf_hash(struct pf_addr *inaddr, struct pf_addr *hash, 126 struct pf_poolhashkey *key, sa_family_t af) 127 { 128 u_int32_t a = 0x9e3779b9, b = 0x9e3779b9, c = key->key32[0]; 129 130 switch (af) { 131 #ifdef INET 132 case AF_INET: 133 a += inaddr->addr32[0]; 134 b += key->key32[1]; 135 mix(a, b, c); 136 hash->addr32[0] = c + key->key32[2]; 137 break; 138 #endif /* INET */ 139 #ifdef INET6 140 case AF_INET6: 141 a += inaddr->addr32[0]; 142 b += inaddr->addr32[2]; 143 mix(a, b, c); 144 hash->addr32[0] = c; 145 a += inaddr->addr32[1]; 146 b += inaddr->addr32[3]; 147 c += key->key32[1]; 148 mix(a, b, c); 149 hash->addr32[1] = c; 150 a += inaddr->addr32[2]; 151 b += inaddr->addr32[1]; 152 c += key->key32[2]; 153 mix(a, b, c); 154 hash->addr32[2] = c; 155 a += inaddr->addr32[3]; 156 b += inaddr->addr32[0]; 157 c += key->key32[3]; 158 mix(a, b, c); 159 hash->addr32[3] = c; 160 break; 161 #endif /* INET6 */ 162 } 163 } 164 165 int 166 pf_get_sport(struct pf_pdesc *pd, struct pf_rule *r, 167 struct pf_addr *naddr, u_int16_t *nport, u_int16_t low, u_int16_t high, 168 struct pf_src_node **sn) 169 { 170 struct pf_state_key_cmp key; 171 struct pf_addr init_addr; 172 u_int16_t cut; 173 174 bzero(&init_addr, sizeof(init_addr)); 175 if (pf_map_addr(pd->af, r, &pd->nsaddr, naddr, &init_addr, sn, &r->nat, 176 PF_SN_NAT)) 177 return (1); 178 179 if (pd->proto == IPPROTO_ICMP || pd->proto == IPPROTO_ICMPV6) { 180 if (pd->ndport == htons(ICMP6_ECHO_REQUEST) || 181 pd->ndport == htons(ICMP_ECHO)) { 182 low = 1; 183 high = 65535; 184 } else 185 return (0); /* Don't try to modify non-echo ICMP */ 186 } 187 188 do { 189 key.af = pd->af; 190 key.proto = pd->proto; 191 key.rdomain = pd->rdomain; 192 PF_ACPY(&key.addr[0], &pd->ndaddr, key.af); 193 PF_ACPY(&key.addr[1], naddr, key.af); 194 key.port[0] = pd->ndport; 195 196 /* 197 * port search; start random, step; 198 * similar 2 portloop in in_pcbbind 199 */ 200 if (!(pd->proto == IPPROTO_TCP || pd->proto == IPPROTO_UDP || 201 pd->proto == IPPROTO_ICMP)) { 202 /* XXX bug: icmp states dont use the id on both 203 * XXX sides (traceroute -I through nat) */ 204 key.port[1] = pd->nsport; 205 if (pf_find_state_all(&key, PF_IN, NULL) == NULL) { 206 *nport = pd->nsport; 207 return (0); 208 } 209 } else if (low == 0 && high == 0) { 210 key.port[1] = pd->nsport; 211 if (pf_find_state_all(&key, PF_IN, NULL) == NULL) { 212 *nport = pd->nsport; 213 return (0); 214 } 215 } else if (low == high) { 216 key.port[1] = htons(low); 217 if (pf_find_state_all(&key, PF_IN, NULL) == NULL) { 218 *nport = htons(low); 219 return (0); 220 } 221 } else { 222 u_int16_t tmp; 223 224 if (low > high) { 225 tmp = low; 226 low = high; 227 high = tmp; 228 } 229 /* low < high */ 230 cut = arc4random_uniform(1 + high - low) + low; 231 /* low <= cut <= high */ 232 for (tmp = cut; tmp <= high; ++(tmp)) { 233 key.port[1] = htons(tmp); 234 if (pf_find_state_all(&key, PF_IN, NULL) == 235 NULL && !in_baddynamic(tmp, pd->proto)) { 236 *nport = htons(tmp); 237 return (0); 238 } 239 } 240 for (tmp = cut - 1; tmp >= low; --(tmp)) { 241 key.port[1] = htons(tmp); 242 if (pf_find_state_all(&key, PF_IN, NULL) == 243 NULL && !in_baddynamic(tmp, pd->proto)) { 244 *nport = htons(tmp); 245 return (0); 246 } 247 } 248 } 249 250 switch (r->nat.opts & PF_POOL_TYPEMASK) { 251 case PF_POOL_RANDOM: 252 case PF_POOL_ROUNDROBIN: 253 case PF_POOL_LEASTSTATES: 254 if (pf_map_addr(pd->af, r, &pd->nsaddr, naddr, 255 &init_addr, sn, &r->nat, PF_SN_NAT)) 256 return (1); 257 break; 258 case PF_POOL_NONE: 259 case PF_POOL_SRCHASH: 260 case PF_POOL_BITMASK: 261 default: 262 return (1); 263 } 264 } while (! PF_AEQ(&init_addr, naddr, pd->af) ); 265 return (1); /* none available */ 266 } 267 268 int 269 pf_islinklocal(sa_family_t af, struct pf_addr *addr) 270 { 271 if (af == AF_INET6 && IN6_IS_ADDR_LINKLOCAL(&addr->v6)) 272 return (1); 273 return (0); 274 } 275 276 int 277 pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr, 278 struct pf_addr *naddr, struct pf_addr *init_addr, struct pf_src_node **sns, 279 struct pf_pool *rpool, enum pf_sn_types type) 280 { 281 unsigned char hash[16]; 282 struct pf_addr faddr; 283 struct pf_addr *raddr = &rpool->addr.v.a.addr; 284 struct pf_addr *rmask = &rpool->addr.v.a.mask; 285 struct pf_src_node k; 286 u_int64_t states; 287 u_int16_t weight; 288 289 if (sns[type] == NULL && rpool->opts & PF_POOL_STICKYADDR && 290 (rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) { 291 k.af = af; 292 k.type = type; 293 PF_ACPY(&k.addr, saddr, af); 294 k.rule.ptr = r; 295 pf_status.scounters[SCNT_SRC_NODE_SEARCH]++; 296 sns[type] = RB_FIND(pf_src_tree, &tree_src_tracking, &k); 297 if (sns[type] != NULL) { 298 if (!PF_AZERO(&(sns[type])->raddr, af)) 299 PF_ACPY(naddr, &(sns[type])->raddr, af); 300 if (pf_status.debug >= LOG_DEBUG) { 301 log(LOG_DEBUG, "pf: pf_map_addr: " 302 "src tracking (%u) maps ", type); 303 pf_print_host(&k.addr, 0, af); 304 addlog(" to "); 305 pf_print_host(naddr, 0, af); 306 addlog("\n"); 307 } 308 return (0); 309 } 310 } 311 312 if (rpool->addr.type == PF_ADDR_NOROUTE) 313 return (1); 314 if (rpool->addr.type == PF_ADDR_DYNIFTL) { 315 switch (af) { 316 #ifdef INET 317 case AF_INET: 318 if (rpool->addr.p.dyn->pfid_acnt4 < 1 && 319 ((rpool->opts & PF_POOL_TYPEMASK) != 320 PF_POOL_ROUNDROBIN) && 321 ((rpool->opts & PF_POOL_TYPEMASK) != 322 PF_POOL_LEASTSTATES)) 323 return (1); 324 raddr = &rpool->addr.p.dyn->pfid_addr4; 325 rmask = &rpool->addr.p.dyn->pfid_mask4; 326 break; 327 #endif /* INET */ 328 #ifdef INET6 329 case AF_INET6: 330 if (rpool->addr.p.dyn->pfid_acnt6 < 1 && 331 ((rpool->opts & PF_POOL_TYPEMASK) != 332 PF_POOL_ROUNDROBIN) && 333 ((rpool->opts & PF_POOL_TYPEMASK) != 334 PF_POOL_LEASTSTATES)) 335 return (1); 336 raddr = &rpool->addr.p.dyn->pfid_addr6; 337 rmask = &rpool->addr.p.dyn->pfid_mask6; 338 break; 339 #endif /* INET6 */ 340 } 341 } else if (rpool->addr.type == PF_ADDR_TABLE) { 342 if (((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN) && 343 ((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_LEASTSTATES)) 344 return (1); /* unsupported */ 345 } else { 346 raddr = &rpool->addr.v.a.addr; 347 rmask = &rpool->addr.v.a.mask; 348 } 349 350 switch (rpool->opts & PF_POOL_TYPEMASK) { 351 case PF_POOL_NONE: 352 PF_ACPY(naddr, raddr, af); 353 break; 354 case PF_POOL_BITMASK: 355 PF_POOLMASK(naddr, raddr, rmask, saddr, af); 356 break; 357 case PF_POOL_RANDOM: 358 if (init_addr != NULL && PF_AZERO(init_addr, af)) { 359 switch (af) { 360 #ifdef INET 361 case AF_INET: 362 rpool->counter.addr32[0] = htonl(arc4random()); 363 break; 364 #endif /* INET */ 365 #ifdef INET6 366 case AF_INET6: 367 if (rmask->addr32[3] != 0xffffffff) 368 rpool->counter.addr32[3] = 369 htonl(arc4random()); 370 else 371 break; 372 if (rmask->addr32[2] != 0xffffffff) 373 rpool->counter.addr32[2] = 374 htonl(arc4random()); 375 else 376 break; 377 if (rmask->addr32[1] != 0xffffffff) 378 rpool->counter.addr32[1] = 379 htonl(arc4random()); 380 else 381 break; 382 if (rmask->addr32[0] != 0xffffffff) 383 rpool->counter.addr32[0] = 384 htonl(arc4random()); 385 break; 386 #endif /* INET6 */ 387 } 388 PF_POOLMASK(naddr, raddr, rmask, &rpool->counter, af); 389 PF_ACPY(init_addr, naddr, af); 390 391 } else { 392 PF_AINC(&rpool->counter, af); 393 PF_POOLMASK(naddr, raddr, rmask, &rpool->counter, af); 394 } 395 break; 396 case PF_POOL_SRCHASH: 397 pf_hash(saddr, (struct pf_addr *)&hash, &rpool->key, af); 398 PF_POOLMASK(naddr, raddr, rmask, (struct pf_addr *)&hash, af); 399 break; 400 case PF_POOL_ROUNDROBIN: 401 if (rpool->addr.type == PF_ADDR_TABLE) { 402 if (pfr_pool_get(rpool->addr.p.tbl, 403 &rpool->tblidx, &rpool->counter, 404 &raddr, &rmask, &rpool->kif, 405 &rpool->states, &rpool->weight, 406 &rpool->curweight, af, NULL)) 407 return (1); 408 } else if (rpool->addr.type == PF_ADDR_DYNIFTL) { 409 if (pfr_pool_get(rpool->addr.p.dyn->pfid_kt, 410 &rpool->tblidx, &rpool->counter, 411 &raddr, &rmask, &rpool->kif, 412 &rpool->states, &rpool->weight, 413 &rpool->curweight, af, pf_islinklocal)) 414 return (1); 415 } else if (pf_match_addr(0, raddr, rmask, &rpool->counter, af)) 416 return (1); 417 418 /* iterate over table if it contains entries which are weighted */ 419 if ((rpool->addr.type == PF_ADDR_TABLE && 420 rpool->addr.p.tbl->pfrkt_refcntcost > 0) || 421 (rpool->addr.type == PF_ADDR_DYNIFTL && 422 rpool->addr.p.dyn->pfid_kt->pfrkt_refcntcost > 0)) { 423 do { 424 if (rpool->addr.type == PF_ADDR_TABLE) { 425 if (pfr_pool_get(rpool->addr.p.tbl, 426 &rpool->tblidx, &rpool->counter, 427 &raddr, &rmask, &rpool->kif, 428 &rpool->states, &rpool->weight, 429 &rpool->curweight, af, NULL)) 430 return (1); 431 } else if (rpool->addr.type == PF_ADDR_DYNIFTL) { 432 if (pfr_pool_get( 433 rpool->addr.p.dyn->pfid_kt, 434 &rpool->tblidx, &rpool->counter, 435 &raddr, &rmask, &rpool->kif, 436 &rpool->states, &rpool->weight, 437 &rpool->curweight, af, 438 pf_islinklocal)) 439 return (1); 440 } else { 441 log(LOG_ERR, "pf: pf_map_addr: " 442 "weighted RR failure"); 443 return (1); 444 } 445 if (rpool->weight >= rpool->curweight) 446 break; 447 PF_AINC(&rpool->counter, af); 448 } while (1); 449 450 weight = rpool->weight; 451 } 452 453 PF_ACPY(naddr, &rpool->counter, af); 454 if (init_addr != NULL && PF_AZERO(init_addr, af)) 455 PF_ACPY(init_addr, naddr, af); 456 PF_AINC(&rpool->counter, af); 457 break; 458 case PF_POOL_LEASTSTATES: 459 /* retrieve an address first */ 460 if (rpool->addr.type == PF_ADDR_TABLE) { 461 if (pfr_pool_get(rpool->addr.p.tbl, 462 &rpool->tblidx, &rpool->counter, 463 &raddr, &rmask, &rpool->kif, 464 &rpool->states, &rpool->weight, 465 &rpool->curweight, af, NULL)) 466 return (1); 467 } else if (rpool->addr.type == PF_ADDR_DYNIFTL) { 468 if (pfr_pool_get(rpool->addr.p.dyn->pfid_kt, 469 &rpool->tblidx, &rpool->counter, 470 &raddr, &rmask, &rpool->kif, 471 &rpool->states, &rpool->weight, 472 &rpool->curweight, af, pf_islinklocal)) 473 return (1); 474 } else if (pf_match_addr(0, raddr, rmask, &rpool->counter, af)) 475 return (1); 476 477 states = rpool->states; 478 479 PF_ACPY(&faddr, &rpool->counter, af); 480 481 PF_ACPY(naddr, &rpool->counter, af); 482 if (init_addr != NULL && PF_AZERO(init_addr, af)) 483 PF_ACPY(init_addr, naddr, af); 484 485 /* 486 * iterate *once* over whole table and find destination with 487 * least connection 488 */ 489 do { 490 PF_AINC(&rpool->counter, af); 491 if (rpool->addr.type == PF_ADDR_TABLE) { 492 if (pfr_pool_get(rpool->addr.p.tbl, 493 &rpool->tblidx, &rpool->counter, 494 &raddr, &rmask, &rpool->kif, 495 &rpool->states, &rpool->weight, 496 &rpool->curweight, af, NULL)) 497 return (1); 498 } else if (rpool->addr.type == PF_ADDR_DYNIFTL) { 499 if (pfr_pool_get(rpool->addr.p.dyn->pfid_kt, 500 &rpool->tblidx, &rpool->counter, 501 &raddr, &rmask, &rpool->kif, 502 &rpool->states, &rpool->weight, 503 &rpool->curweight, af, pf_islinklocal)) 504 return (1); 505 } else if (pf_match_addr(0, raddr, rmask, 506 &rpool->counter, af)) 507 return (1); 508 509 /* find lc minimum */ 510 if (states > rpool->states) { 511 states = rpool->states; 512 513 PF_ACPY(naddr, &rpool->counter, af); 514 if (init_addr != NULL && 515 PF_AZERO(init_addr, af)) 516 PF_ACPY(init_addr, naddr, af); 517 } 518 } while (pf_match_addr(1, &faddr, rmask, &rpool->counter, af) && 519 (states > 0)); 520 521 if (rpool->addr.type == PF_ADDR_TABLE) { 522 if (pfr_states_increase(rpool->addr.p.tbl, 523 naddr, af) == -1) { 524 if (pf_status.debug >= LOG_DEBUG) { 525 log(LOG_DEBUG,"pf: pf_map_addr: " 526 "selected address "); 527 pf_print_host(naddr, 0, af); 528 addlog(". Failed to increase count!\n"); 529 } 530 return (1); 531 } 532 } else if (rpool->addr.type == PF_ADDR_DYNIFTL) { 533 if (pfr_states_increase(rpool->addr.p.dyn->pfid_kt, 534 naddr, af) == -1) { 535 if (pf_status.debug >= LOG_DEBUG) { 536 log(LOG_DEBUG, "pf: pf_map_addr: " 537 "selected address "); 538 pf_print_host(naddr, 0, af); 539 addlog(". Failed to increase count!\n"); 540 } 541 return (1); 542 } 543 } 544 break; 545 } 546 547 if (rpool->opts & PF_POOL_STICKYADDR) { 548 if (sns[type] != NULL) { 549 pf_remove_src_node(sns[type]); 550 sns[type] = NULL; 551 } 552 if (pf_insert_src_node(&sns[type], r, type, af, saddr, naddr, 553 0)) 554 return (1); 555 } 556 557 if (pf_status.debug >= LOG_NOTICE && 558 (rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) { 559 log(LOG_NOTICE, "pf: pf_map_addr: selected address "); 560 pf_print_host(naddr, 0, af); 561 if ((rpool->opts & PF_POOL_TYPEMASK) == 562 PF_POOL_LEASTSTATES) 563 addlog(" with state count %d", states); 564 if (((rpool->addr.type == PF_ADDR_TABLE && 565 rpool->addr.p.tbl->pfrkt_refcntcost > 0) || 566 (rpool->addr.type == PF_ADDR_DYNIFTL && 567 rpool->addr.p.dyn->pfid_kt->pfrkt_refcntcost > 0)) && 568 ((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_LEASTSTATES)) 569 addlog(" with weight %u", weight); 570 addlog("\n"); 571 } 572 573 return (0); 574 } 575 576 int 577 pf_get_transaddr(struct pf_rule *r, struct pf_pdesc *pd, 578 struct pf_src_node **sns, struct pf_rule **nr) 579 { 580 struct pf_addr naddr; 581 u_int16_t nport = 0; 582 583 if (r->nat.addr.type != PF_ADDR_NONE) { 584 /* XXX is this right? what if rtable is changed at the same 585 * XXX time? where do I need to figure out the sport? */ 586 if (pf_get_sport(pd, r, &naddr, &nport, 587 r->nat.proxy_port[0], r->nat.proxy_port[1], sns)) { 588 DPFPRINTF(LOG_NOTICE, 589 "pf: NAT proxy port allocation (%u-%u) failed", 590 r->nat.proxy_port[0], 591 r->nat.proxy_port[1]); 592 return (-1); 593 } 594 *nr = r; 595 PF_ACPY(&pd->nsaddr, &naddr, pd->af); 596 pd->nsport = nport; 597 } 598 if (r->rdr.addr.type != PF_ADDR_NONE) { 599 if (pf_map_addr(pd->af, r, &pd->nsaddr, &naddr, NULL, sns, 600 &r->rdr, PF_SN_RDR)) 601 return (-1); 602 if ((r->rdr.opts & PF_POOL_TYPEMASK) == PF_POOL_BITMASK) 603 PF_POOLMASK(&naddr, &naddr, &r->rdr.addr.v.a.mask, 604 &pd->ndaddr, pd->af); 605 606 if (r->rdr.proxy_port[1]) { 607 u_int32_t tmp_nport; 608 609 tmp_nport = ((ntohs(pd->ndport) - 610 ntohs(r->dst.port[0])) % 611 (r->rdr.proxy_port[1] - 612 r->rdr.proxy_port[0] + 1)) + 613 r->rdr.proxy_port[0]; 614 615 /* wrap around if necessary */ 616 if (tmp_nport > 65535) 617 tmp_nport -= 65535; 618 nport = htons((u_int16_t)tmp_nport); 619 } else if (r->rdr.proxy_port[0]) 620 nport = htons(r->rdr.proxy_port[0]); 621 *nr = r; 622 PF_ACPY(&pd->ndaddr, &naddr, pd->af); 623 if (nport) 624 pd->ndport = nport; 625 } 626 627 return (0); 628 } 629 630 int 631 pf_postprocess_addr(struct pf_state *cur) { 632 struct pf_rule *nr; 633 634 nr = cur->natrule.ptr; 635 636 /* decrease counter */ 637 if (nr != NULL) { 638 int slbcount; 639 struct pf_pool rpool; 640 struct pf_addr lookup_addr; 641 struct pf_state_key *sks; 642 643 sks = cur ? cur->key[PF_SK_STACK] : NULL; 644 645 /* check for outgoing or ingoing balancing */ 646 if (nr->rt == PF_ROUTETO) 647 lookup_addr = cur->rt_addr; 648 else if (sks != NULL) 649 lookup_addr = sks->addr[1]; 650 else { 651 if (pf_status.debug >= LOG_DEBUG) { 652 log(LOG_DEBUG, "pf: pf_unlink_state: " 653 "unable to optain address"); 654 } 655 return (1); 656 } 657 658 /* check for appropriate pool */ 659 if (nr->rdr.addr.type != PF_ADDR_NONE) 660 rpool = nr->rdr; 661 else if (nr->nat.addr.type != PF_ADDR_NONE) 662 rpool = nr->nat; 663 else if (nr->route.addr.type != PF_ADDR_NONE) 664 rpool = nr->route; 665 666 if (((rpool.opts & PF_POOL_TYPEMASK) != PF_POOL_LEASTSTATES)) 667 return (0); 668 669 if (rpool.addr.type == PF_ADDR_TABLE) { 670 if ((slbcount = pfr_states_decrease( 671 rpool.addr.p.tbl, 672 &lookup_addr, sks->af)) == -1) { 673 if (pf_status.debug >= LOG_DEBUG) { 674 log(LOG_DEBUG, "pf: pf_unlink_state: " 675 "selected address "); 676 pf_print_host(&lookup_addr, 677 sks->port[0], sks->af); 678 addlog(". Failed to " 679 "decrease count!\n"); 680 } 681 return (1); 682 } 683 } else if (rpool.addr.type == PF_ADDR_DYNIFTL) { 684 if ((slbcount = pfr_states_decrease( 685 rpool.addr.p.dyn->pfid_kt, 686 &lookup_addr, sks->af)) == -1) { 687 if (pf_status.debug >= LOG_DEBUG) { 688 log(LOG_DEBUG, 689 "pf: pf_unlink_state: " 690 "selected address "); 691 pf_print_host(&lookup_addr, 692 sks->port[0], sks->af); 693 addlog(". Failed to " 694 "decrease count!\n"); 695 } 696 return (1); 697 } 698 } 699 if (slbcount > -1) { 700 if (pf_status.debug >= LOG_NOTICE) { 701 log(LOG_NOTICE, 702 "pf: pf_unlink_state: selected address "); 703 pf_print_host(&lookup_addr, sks->port[0], 704 sks->af); 705 addlog(" decreased state count to %u\n", 706 slbcount); 707 } 708 } 709 } 710 711 return (0); 712 } 713