1 /* $OpenBSD: pf_lb.c,v 1.4 2009/03/05 03:09:37 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 55 #include <crypto/md5.h> 56 57 #include <net/if.h> 58 #include <net/if_types.h> 59 #include <net/bpf.h> 60 #include <net/route.h> 61 #include <net/radix_mpath.h> 62 63 #include <netinet/in.h> 64 #include <netinet/in_var.h> 65 #include <netinet/in_systm.h> 66 #include <netinet/ip.h> 67 #include <netinet/ip_var.h> 68 #include <netinet/tcp.h> 69 #include <netinet/tcp_seq.h> 70 #include <netinet/udp.h> 71 #include <netinet/ip_icmp.h> 72 #include <netinet/in_pcb.h> 73 #include <netinet/tcp_timer.h> 74 #include <netinet/tcp_var.h> 75 #include <netinet/udp_var.h> 76 #include <netinet/icmp_var.h> 77 #include <netinet/if_ether.h> 78 79 #include <dev/rndvar.h> 80 #include <net/pfvar.h> 81 #include <net/if_pflog.h> 82 #include <net/if_pflow.h> 83 84 #if NPFSYNC > 0 85 #include <net/if_pfsync.h> 86 #endif /* NPFSYNC > 0 */ 87 88 #ifdef INET6 89 #include <netinet/ip6.h> 90 #include <netinet/in_pcb.h> 91 #include <netinet/icmp6.h> 92 #include <netinet6/nd6.h> 93 #endif /* INET6 */ 94 95 96 #define DPFPRINTF(n, x) if (pf_status.debug >= (n)) printf x 97 98 /* 99 * Global variables 100 */ 101 102 void pf_hash(struct pf_addr *, struct pf_addr *, 103 struct pf_poolhashkey *, sa_family_t); 104 struct pf_rule *pf_match_translation(struct pf_pdesc *, struct mbuf *, 105 int, int, struct pfi_kif *, 106 struct pf_addr *, u_int16_t, struct pf_addr *, 107 u_int16_t, int); 108 int pf_get_sport(sa_family_t, u_int8_t, struct pf_rule *, 109 struct pf_addr *, struct pf_addr *, u_int16_t, 110 struct pf_addr *, u_int16_t*, u_int16_t, u_int16_t, 111 struct pf_src_node **); 112 113 #define mix(a,b,c) \ 114 do { \ 115 a -= b; a -= c; a ^= (c >> 13); \ 116 b -= c; b -= a; b ^= (a << 8); \ 117 c -= a; c -= b; c ^= (b >> 13); \ 118 a -= b; a -= c; a ^= (c >> 12); \ 119 b -= c; b -= a; b ^= (a << 16); \ 120 c -= a; c -= b; c ^= (b >> 5); \ 121 a -= b; a -= c; a ^= (c >> 3); \ 122 b -= c; b -= a; b ^= (a << 10); \ 123 c -= a; c -= b; c ^= (b >> 15); \ 124 } while (0) 125 126 /* 127 * hash function based on bridge_hash in if_bridge.c 128 */ 129 void 130 pf_hash(struct pf_addr *inaddr, struct pf_addr *hash, 131 struct pf_poolhashkey *key, sa_family_t af) 132 { 133 u_int32_t a = 0x9e3779b9, b = 0x9e3779b9, c = key->key32[0]; 134 135 switch (af) { 136 #ifdef INET 137 case AF_INET: 138 a += inaddr->addr32[0]; 139 b += key->key32[1]; 140 mix(a, b, c); 141 hash->addr32[0] = c + key->key32[2]; 142 break; 143 #endif /* INET */ 144 #ifdef INET6 145 case AF_INET6: 146 a += inaddr->addr32[0]; 147 b += inaddr->addr32[2]; 148 mix(a, b, c); 149 hash->addr32[0] = c; 150 a += inaddr->addr32[1]; 151 b += inaddr->addr32[3]; 152 c += key->key32[1]; 153 mix(a, b, c); 154 hash->addr32[1] = c; 155 a += inaddr->addr32[2]; 156 b += inaddr->addr32[1]; 157 c += key->key32[2]; 158 mix(a, b, c); 159 hash->addr32[2] = c; 160 a += inaddr->addr32[3]; 161 b += inaddr->addr32[0]; 162 c += key->key32[3]; 163 mix(a, b, c); 164 hash->addr32[3] = c; 165 break; 166 #endif /* INET6 */ 167 } 168 } 169 170 struct pf_rule * 171 pf_match_translation(struct pf_pdesc *pd, struct mbuf *m, int off, 172 int direction, struct pfi_kif *kif, struct pf_addr *saddr, u_int16_t sport, 173 struct pf_addr *daddr, u_int16_t dport, int rs_num) 174 { 175 struct pf_rule *r, *rm = NULL; 176 struct pf_ruleset *ruleset = NULL; 177 int tag = -1; 178 int rtableid = -1; 179 int asd = 0; 180 181 r = TAILQ_FIRST(pf_main_ruleset.rules[rs_num].active.ptr); 182 while (r && rm == NULL) { 183 struct pf_rule_addr *src = NULL, *dst = NULL; 184 struct pf_addr_wrap *xdst = NULL; 185 186 if (r->action == PF_BINAT && direction == PF_IN) { 187 src = &r->dst; 188 if (r->rpool.cur != NULL) 189 xdst = &r->rpool.cur->addr; 190 } else { 191 src = &r->src; 192 dst = &r->dst; 193 } 194 195 r->evaluations++; 196 if (pfi_kif_match(r->kif, kif) == r->ifnot) 197 r = r->skip[PF_SKIP_IFP].ptr; 198 else if (r->direction && r->direction != direction) 199 r = r->skip[PF_SKIP_DIR].ptr; 200 else if (r->af && r->af != pd->af) 201 r = r->skip[PF_SKIP_AF].ptr; 202 else if (r->proto && r->proto != pd->proto) 203 r = r->skip[PF_SKIP_PROTO].ptr; 204 else if (PF_MISMATCHAW(&src->addr, saddr, pd->af, 205 src->neg, kif)) 206 r = r->skip[src == &r->src ? PF_SKIP_SRC_ADDR : 207 PF_SKIP_DST_ADDR].ptr; 208 else if (src->port_op && !pf_match_port(src->port_op, 209 src->port[0], src->port[1], sport)) 210 r = r->skip[src == &r->src ? PF_SKIP_SRC_PORT : 211 PF_SKIP_DST_PORT].ptr; 212 else if (dst != NULL && 213 PF_MISMATCHAW(&dst->addr, daddr, pd->af, dst->neg, NULL)) 214 r = r->skip[PF_SKIP_DST_ADDR].ptr; 215 else if (xdst != NULL && PF_MISMATCHAW(xdst, daddr, pd->af, 216 0, NULL)) 217 r = TAILQ_NEXT(r, entries); 218 else if (dst != NULL && dst->port_op && 219 !pf_match_port(dst->port_op, dst->port[0], 220 dst->port[1], dport)) 221 r = r->skip[PF_SKIP_DST_PORT].ptr; 222 else if (r->match_tag && !pf_match_tag(m, r, &tag)) 223 r = TAILQ_NEXT(r, entries); 224 else if (r->os_fingerprint != PF_OSFP_ANY && (pd->proto != 225 IPPROTO_TCP || !pf_osfp_match(pf_osfp_fingerprint(pd, m, 226 off, pd->hdr.tcp), r->os_fingerprint))) 227 r = TAILQ_NEXT(r, entries); 228 else { 229 if (r->tag) 230 tag = r->tag; 231 if (r->rtableid >= 0) 232 rtableid = r->rtableid; 233 if (r->anchor == NULL) { 234 rm = r; 235 } else 236 pf_step_into_anchor(&asd, &ruleset, rs_num, 237 &r, NULL, NULL); 238 } 239 if (r == NULL) 240 pf_step_out_of_anchor(&asd, &ruleset, rs_num, &r, 241 NULL, NULL); 242 } 243 if (pf_tag_packet(m, tag, rtableid)) 244 return (NULL); 245 if (rm != NULL && (rm->action == PF_NONAT || 246 rm->action == PF_NORDR || rm->action == PF_NOBINAT)) 247 return (NULL); 248 return (rm); 249 } 250 251 int 252 pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r, 253 struct pf_addr *saddr, struct pf_addr *daddr, u_int16_t dport, 254 struct pf_addr *naddr, u_int16_t *nport, u_int16_t low, u_int16_t high, 255 struct pf_src_node **sn) 256 { 257 struct pf_state_key_cmp key; 258 struct pf_addr init_addr; 259 u_int16_t cut; 260 261 bzero(&init_addr, sizeof(init_addr)); 262 if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn)) 263 return (1); 264 265 if (proto == IPPROTO_ICMP || proto == IPPROTO_ICMPV6) { 266 if (dport == ICMP6_ECHO_REQUEST || dport == ICMP_ECHO) { 267 low = 1; 268 high = 65535; 269 } else 270 return (0); /* Don't try to modify non-echo ICMP */ 271 } 272 273 do { 274 key.af = af; 275 key.proto = proto; 276 PF_ACPY(&key.addr[1], daddr, key.af); 277 PF_ACPY(&key.addr[0], naddr, key.af); 278 key.port[1] = dport; 279 280 /* 281 * port search; start random, step; 282 * similar 2 portloop in in_pcbbind 283 */ 284 if (!(proto == IPPROTO_TCP || proto == IPPROTO_UDP || 285 proto == IPPROTO_ICMP)) { 286 key.port[0] = dport; 287 if (pf_find_state_all(&key, PF_IN, NULL) == NULL) 288 return (0); 289 } else if (low == 0 && high == 0) { 290 key.port[0] = *nport; 291 if (pf_find_state_all(&key, PF_IN, NULL) == NULL) 292 return (0); 293 } else if (low == high) { 294 key.port[0] = htons(low); 295 if (pf_find_state_all(&key, PF_IN, NULL) == NULL) { 296 *nport = htons(low); 297 return (0); 298 } 299 } else { 300 u_int16_t tmp; 301 302 if (low > high) { 303 tmp = low; 304 low = high; 305 high = tmp; 306 } 307 /* low < high */ 308 cut = arc4random_uniform(1 + high - low) + low; 309 /* low <= cut <= high */ 310 for (tmp = cut; tmp <= high; ++(tmp)) { 311 key.port[0] = htons(tmp); 312 if (pf_find_state_all(&key, PF_IN, NULL) == 313 NULL && !in_baddynamic(tmp, proto)) { 314 *nport = htons(tmp); 315 return (0); 316 } 317 } 318 for (tmp = cut - 1; tmp >= low; --(tmp)) { 319 key.port[0] = htons(tmp); 320 if (pf_find_state_all(&key, PF_IN, NULL) == 321 NULL && !in_baddynamic(tmp, proto)) { 322 *nport = htons(tmp); 323 return (0); 324 } 325 } 326 } 327 328 switch (r->rpool.opts & PF_POOL_TYPEMASK) { 329 case PF_POOL_RANDOM: 330 case PF_POOL_ROUNDROBIN: 331 if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn)) 332 return (1); 333 break; 334 case PF_POOL_NONE: 335 case PF_POOL_SRCHASH: 336 case PF_POOL_BITMASK: 337 default: 338 return (1); 339 } 340 } while (! PF_AEQ(&init_addr, naddr, af) ); 341 return (1); /* none available */ 342 } 343 344 int 345 pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr, 346 struct pf_addr *naddr, struct pf_addr *init_addr, struct pf_src_node **sn) 347 { 348 unsigned char hash[16]; 349 struct pf_pool *rpool = &r->rpool; 350 struct pf_addr *raddr = &rpool->cur->addr.v.a.addr; 351 struct pf_addr *rmask = &rpool->cur->addr.v.a.mask; 352 struct pf_pooladdr *acur = rpool->cur; 353 struct pf_src_node k; 354 355 if (*sn == NULL && r->rpool.opts & PF_POOL_STICKYADDR && 356 (r->rpool.opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) { 357 k.af = af; 358 PF_ACPY(&k.addr, saddr, af); 359 if (r->rule_flag & PFRULE_RULESRCTRACK || 360 r->rpool.opts & PF_POOL_STICKYADDR) 361 k.rule.ptr = r; 362 else 363 k.rule.ptr = NULL; 364 pf_status.scounters[SCNT_SRC_NODE_SEARCH]++; 365 *sn = RB_FIND(pf_src_tree, &tree_src_tracking, &k); 366 if (*sn != NULL && !PF_AZERO(&(*sn)->raddr, af)) { 367 PF_ACPY(naddr, &(*sn)->raddr, af); 368 if (pf_status.debug >= PF_DEBUG_MISC) { 369 printf("pf_map_addr: src tracking maps "); 370 pf_print_host(&k.addr, 0, af); 371 printf(" to "); 372 pf_print_host(naddr, 0, af); 373 printf("\n"); 374 } 375 return (0); 376 } 377 } 378 379 if (rpool->cur->addr.type == PF_ADDR_NOROUTE) 380 return (1); 381 if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) { 382 switch (af) { 383 #ifdef INET 384 case AF_INET: 385 if (rpool->cur->addr.p.dyn->pfid_acnt4 < 1 && 386 (rpool->opts & PF_POOL_TYPEMASK) != 387 PF_POOL_ROUNDROBIN) 388 return (1); 389 raddr = &rpool->cur->addr.p.dyn->pfid_addr4; 390 rmask = &rpool->cur->addr.p.dyn->pfid_mask4; 391 break; 392 #endif /* INET */ 393 #ifdef INET6 394 case AF_INET6: 395 if (rpool->cur->addr.p.dyn->pfid_acnt6 < 1 && 396 (rpool->opts & PF_POOL_TYPEMASK) != 397 PF_POOL_ROUNDROBIN) 398 return (1); 399 raddr = &rpool->cur->addr.p.dyn->pfid_addr6; 400 rmask = &rpool->cur->addr.p.dyn->pfid_mask6; 401 break; 402 #endif /* INET6 */ 403 } 404 } else if (rpool->cur->addr.type == PF_ADDR_TABLE) { 405 if ((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN) 406 return (1); /* unsupported */ 407 } else { 408 raddr = &rpool->cur->addr.v.a.addr; 409 rmask = &rpool->cur->addr.v.a.mask; 410 } 411 412 switch (rpool->opts & PF_POOL_TYPEMASK) { 413 case PF_POOL_NONE: 414 PF_ACPY(naddr, raddr, af); 415 break; 416 case PF_POOL_BITMASK: 417 PF_POOLMASK(naddr, raddr, rmask, saddr, af); 418 break; 419 case PF_POOL_RANDOM: 420 if (init_addr != NULL && PF_AZERO(init_addr, af)) { 421 switch (af) { 422 #ifdef INET 423 case AF_INET: 424 rpool->counter.addr32[0] = htonl(arc4random()); 425 break; 426 #endif /* INET */ 427 #ifdef INET6 428 case AF_INET6: 429 if (rmask->addr32[3] != 0xffffffff) 430 rpool->counter.addr32[3] = 431 htonl(arc4random()); 432 else 433 break; 434 if (rmask->addr32[2] != 0xffffffff) 435 rpool->counter.addr32[2] = 436 htonl(arc4random()); 437 else 438 break; 439 if (rmask->addr32[1] != 0xffffffff) 440 rpool->counter.addr32[1] = 441 htonl(arc4random()); 442 else 443 break; 444 if (rmask->addr32[0] != 0xffffffff) 445 rpool->counter.addr32[0] = 446 htonl(arc4random()); 447 break; 448 #endif /* INET6 */ 449 } 450 PF_POOLMASK(naddr, raddr, rmask, &rpool->counter, af); 451 PF_ACPY(init_addr, naddr, af); 452 453 } else { 454 PF_AINC(&rpool->counter, af); 455 PF_POOLMASK(naddr, raddr, rmask, &rpool->counter, af); 456 } 457 break; 458 case PF_POOL_SRCHASH: 459 pf_hash(saddr, (struct pf_addr *)&hash, &rpool->key, af); 460 PF_POOLMASK(naddr, raddr, rmask, (struct pf_addr *)&hash, af); 461 break; 462 case PF_POOL_ROUNDROBIN: 463 if (rpool->cur->addr.type == PF_ADDR_TABLE) { 464 if (!pfr_pool_get(rpool->cur->addr.p.tbl, 465 &rpool->tblidx, &rpool->counter, 466 &raddr, &rmask, af)) 467 goto get_addr; 468 } else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) { 469 if (!pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt, 470 &rpool->tblidx, &rpool->counter, 471 &raddr, &rmask, af)) 472 goto get_addr; 473 } else if (pf_match_addr(0, raddr, rmask, &rpool->counter, af)) 474 goto get_addr; 475 476 try_next: 477 if ((rpool->cur = TAILQ_NEXT(rpool->cur, entries)) == NULL) 478 rpool->cur = TAILQ_FIRST(&rpool->list); 479 if (rpool->cur->addr.type == PF_ADDR_TABLE) { 480 rpool->tblidx = -1; 481 if (pfr_pool_get(rpool->cur->addr.p.tbl, 482 &rpool->tblidx, &rpool->counter, 483 &raddr, &rmask, af)) { 484 /* table contains no address of type 'af' */ 485 if (rpool->cur != acur) 486 goto try_next; 487 return (1); 488 } 489 } else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) { 490 rpool->tblidx = -1; 491 if (pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt, 492 &rpool->tblidx, &rpool->counter, 493 &raddr, &rmask, af)) { 494 /* table contains no address of type 'af' */ 495 if (rpool->cur != acur) 496 goto try_next; 497 return (1); 498 } 499 } else { 500 raddr = &rpool->cur->addr.v.a.addr; 501 rmask = &rpool->cur->addr.v.a.mask; 502 PF_ACPY(&rpool->counter, raddr, af); 503 } 504 505 get_addr: 506 PF_ACPY(naddr, &rpool->counter, af); 507 if (init_addr != NULL && PF_AZERO(init_addr, af)) 508 PF_ACPY(init_addr, naddr, af); 509 PF_AINC(&rpool->counter, af); 510 break; 511 } 512 if (*sn != NULL) 513 PF_ACPY(&(*sn)->raddr, naddr, af); 514 515 if (pf_status.debug >= PF_DEBUG_MISC && 516 (rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) { 517 printf("pf_map_addr: selected address "); 518 pf_print_host(naddr, 0, af); 519 printf("\n"); 520 } 521 522 return (0); 523 } 524 525 struct pf_rule * 526 pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction, 527 struct pfi_kif *kif, struct pf_src_node **sn, 528 struct pf_state_key **skw, struct pf_state_key **sks, 529 struct pf_state_key **skp, struct pf_state_key **nkp, 530 struct pf_addr *saddr, struct pf_addr *daddr, 531 u_int16_t sport, u_int16_t dport) 532 { 533 struct pf_rule *r = NULL; 534 535 536 if (direction == PF_OUT) { 537 r = pf_match_translation(pd, m, off, direction, kif, saddr, 538 sport, daddr, dport, PF_RULESET_BINAT); 539 if (r == NULL) 540 r = pf_match_translation(pd, m, off, direction, kif, 541 saddr, sport, daddr, dport, PF_RULESET_NAT); 542 } else { 543 r = pf_match_translation(pd, m, off, direction, kif, saddr, 544 sport, daddr, dport, PF_RULESET_RDR); 545 if (r == NULL) 546 r = pf_match_translation(pd, m, off, direction, kif, 547 saddr, sport, daddr, dport, PF_RULESET_BINAT); 548 } 549 550 if (r != NULL) { 551 struct pf_addr *naddr; 552 u_int16_t *nport; 553 554 if (pf_state_key_setup(pd, r, skw, sks, skp, nkp, 555 saddr, daddr, sport, dport)) 556 return r; 557 558 /* XXX We only modify one side for now. */ 559 naddr = &(*nkp)->addr[1]; 560 nport = &(*nkp)->port[1]; 561 562 switch (r->action) { 563 case PF_NONAT: 564 case PF_NOBINAT: 565 case PF_NORDR: 566 return (NULL); 567 case PF_NAT: 568 if (pf_get_sport(pd->af, pd->proto, r, saddr, 569 daddr, dport, naddr, nport, r->rpool.proxy_port[0], 570 r->rpool.proxy_port[1], sn)) { 571 DPFPRINTF(PF_DEBUG_MISC, 572 ("pf: NAT proxy port allocation " 573 "(%u-%u) failed\n", 574 r->rpool.proxy_port[0], 575 r->rpool.proxy_port[1])); 576 return (NULL); 577 } 578 break; 579 case PF_BINAT: 580 switch (direction) { 581 case PF_OUT: 582 if (r->rpool.cur->addr.type == PF_ADDR_DYNIFTL){ 583 switch (pd->af) { 584 #ifdef INET 585 case AF_INET: 586 if (r->rpool.cur->addr.p.dyn-> 587 pfid_acnt4 < 1) 588 return (NULL); 589 PF_POOLMASK(naddr, 590 &r->rpool.cur->addr.p.dyn-> 591 pfid_addr4, 592 &r->rpool.cur->addr.p.dyn-> 593 pfid_mask4, 594 saddr, AF_INET); 595 break; 596 #endif /* INET */ 597 #ifdef INET6 598 case AF_INET6: 599 if (r->rpool.cur->addr.p.dyn-> 600 pfid_acnt6 < 1) 601 return (NULL); 602 PF_POOLMASK(naddr, 603 &r->rpool.cur->addr.p.dyn-> 604 pfid_addr6, 605 &r->rpool.cur->addr.p.dyn-> 606 pfid_mask6, 607 saddr, AF_INET6); 608 break; 609 #endif /* INET6 */ 610 } 611 } else 612 PF_POOLMASK(naddr, 613 &r->rpool.cur->addr.v.a.addr, 614 &r->rpool.cur->addr.v.a.mask, 615 saddr, pd->af); 616 break; 617 case PF_IN: 618 if (r->src.addr.type == PF_ADDR_DYNIFTL) { 619 switch (pd->af) { 620 #ifdef INET 621 case AF_INET: 622 if (r->src.addr.p.dyn-> 623 pfid_acnt4 < 1) 624 return (NULL); 625 PF_POOLMASK(naddr, 626 &r->src.addr.p.dyn-> 627 pfid_addr4, 628 &r->src.addr.p.dyn-> 629 pfid_mask4, 630 daddr, AF_INET); 631 break; 632 #endif /* INET */ 633 #ifdef INET6 634 case AF_INET6: 635 if (r->src.addr.p.dyn-> 636 pfid_acnt6 < 1) 637 return (NULL); 638 PF_POOLMASK(naddr, 639 &r->src.addr.p.dyn-> 640 pfid_addr6, 641 &r->src.addr.p.dyn-> 642 pfid_mask6, 643 daddr, AF_INET6); 644 break; 645 #endif /* INET6 */ 646 } 647 } else 648 PF_POOLMASK(naddr, 649 &r->src.addr.v.a.addr, 650 &r->src.addr.v.a.mask, daddr, 651 pd->af); 652 break; 653 } 654 break; 655 case PF_RDR: { 656 if (pf_map_addr(pd->af, r, saddr, naddr, NULL, sn)) 657 return (NULL); 658 if ((r->rpool.opts & PF_POOL_TYPEMASK) == 659 PF_POOL_BITMASK) 660 PF_POOLMASK(naddr, naddr, 661 &r->rpool.cur->addr.v.a.mask, daddr, 662 pd->af); 663 664 if (r->rpool.proxy_port[1]) { 665 u_int32_t tmp_nport; 666 667 tmp_nport = ((ntohs(dport) - 668 ntohs(r->dst.port[0])) % 669 (r->rpool.proxy_port[1] - 670 r->rpool.proxy_port[0] + 1)) + 671 r->rpool.proxy_port[0]; 672 673 /* wrap around if necessary */ 674 if (tmp_nport > 65535) 675 tmp_nport -= 65535; 676 *nport = htons((u_int16_t)tmp_nport); 677 } else if (r->rpool.proxy_port[0]) 678 *nport = htons(r->rpool.proxy_port[0]); 679 break; 680 } 681 default: 682 return (NULL); 683 } 684 /* 685 * Translation was a NOP. 686 * Pretend there was no match. 687 */ 688 if (!bcmp(*skp, *nkp, sizeof(struct pf_state_key_cmp))) { 689 pool_put(&pf_state_key_pl, *nkp); 690 pool_put(&pf_state_key_pl, *skp); 691 *skw = *sks = *nkp = *skp = NULL; 692 return (NULL); 693 } 694 } 695 696 return (r); 697 } 698 699