1 /*- 2 * Copyright (c) 2001 Daniel Hartmeier 3 * Copyright (c) 2002 - 2008 Henning Brauer 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * - Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * - Redistributions in binary form must reproduce the above 13 * copyright notice, this list of conditions and the following 14 * disclaimer in the documentation and/or other materials provided 15 * with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 21 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 * 30 * Effort sponsored in part by the Defense Advanced Research Projects 31 * Agency (DARPA) and Air Force Research Laboratory, Air Force 32 * Materiel Command, USAF, under agreement number F30602-01-2-0537. 33 * 34 * $OpenBSD: pf_lb.c,v 1.2 2009/02/12 02:13:15 sthen Exp $ 35 */ 36 37 #include <sys/cdefs.h> 38 __FBSDID("$FreeBSD$"); 39 40 #include "opt_pf.h" 41 #include "opt_inet.h" 42 #include "opt_inet6.h" 43 44 #include <sys/param.h> 45 #include <sys/socket.h> 46 #include <sys/sysctl.h> 47 48 #include <net/if.h> 49 #include <net/pfvar.h> 50 #include <net/if_pflog.h> 51 #include <net/pf_mtag.h> 52 53 #define DPFPRINTF(n, x) if (V_pf_status.debug >= (n)) printf x 54 55 static void pf_hash(struct pf_addr *, struct pf_addr *, 56 struct pf_poolhashkey *, sa_family_t); 57 static struct pf_rule *pf_match_translation(struct pf_pdesc *, struct mbuf *, 58 int, int, struct pfi_kif *, 59 struct pf_addr *, u_int16_t, struct pf_addr *, 60 uint16_t, int, struct pf_anchor_stackframe *); 61 static int pf_get_sport(sa_family_t, u_int8_t, struct pf_rule *, 62 struct pf_addr *, struct pf_addr *, u_int16_t, 63 struct pf_addr *, u_int16_t*, u_int16_t, u_int16_t, 64 struct pf_src_node **); 65 66 #define mix(a,b,c) \ 67 do { \ 68 a -= b; a -= c; a ^= (c >> 13); \ 69 b -= c; b -= a; b ^= (a << 8); \ 70 c -= a; c -= b; c ^= (b >> 13); \ 71 a -= b; a -= c; a ^= (c >> 12); \ 72 b -= c; b -= a; b ^= (a << 16); \ 73 c -= a; c -= b; c ^= (b >> 5); \ 74 a -= b; a -= c; a ^= (c >> 3); \ 75 b -= c; b -= a; b ^= (a << 10); \ 76 c -= a; c -= b; c ^= (b >> 15); \ 77 } while (0) 78 79 /* 80 * hash function based on bridge_hash in if_bridge.c 81 */ 82 static void 83 pf_hash(struct pf_addr *inaddr, struct pf_addr *hash, 84 struct pf_poolhashkey *key, sa_family_t af) 85 { 86 u_int32_t a = 0x9e3779b9, b = 0x9e3779b9, c = key->key32[0]; 87 88 switch (af) { 89 #ifdef INET 90 case AF_INET: 91 a += inaddr->addr32[0]; 92 b += key->key32[1]; 93 mix(a, b, c); 94 hash->addr32[0] = c + key->key32[2]; 95 break; 96 #endif /* INET */ 97 #ifdef INET6 98 case AF_INET6: 99 a += inaddr->addr32[0]; 100 b += inaddr->addr32[2]; 101 mix(a, b, c); 102 hash->addr32[0] = c; 103 a += inaddr->addr32[1]; 104 b += inaddr->addr32[3]; 105 c += key->key32[1]; 106 mix(a, b, c); 107 hash->addr32[1] = c; 108 a += inaddr->addr32[2]; 109 b += inaddr->addr32[1]; 110 c += key->key32[2]; 111 mix(a, b, c); 112 hash->addr32[2] = c; 113 a += inaddr->addr32[3]; 114 b += inaddr->addr32[0]; 115 c += key->key32[3]; 116 mix(a, b, c); 117 hash->addr32[3] = c; 118 break; 119 #endif /* INET6 */ 120 } 121 } 122 123 static struct pf_rule * 124 pf_match_translation(struct pf_pdesc *pd, struct mbuf *m, int off, 125 int direction, struct pfi_kif *kif, struct pf_addr *saddr, u_int16_t sport, 126 struct pf_addr *daddr, uint16_t dport, int rs_num, 127 struct pf_anchor_stackframe *anchor_stack) 128 { 129 struct pf_rule *r, *rm = NULL; 130 struct pf_ruleset *ruleset = NULL; 131 int tag = -1; 132 int rtableid = -1; 133 int asd = 0; 134 135 r = TAILQ_FIRST(pf_main_ruleset.rules[rs_num].active.ptr); 136 while (r && rm == NULL) { 137 struct pf_rule_addr *src = NULL, *dst = NULL; 138 struct pf_addr_wrap *xdst = NULL; 139 140 if (r->action == PF_BINAT && direction == PF_IN) { 141 src = &r->dst; 142 if (r->rpool.cur != NULL) 143 xdst = &r->rpool.cur->addr; 144 } else { 145 src = &r->src; 146 dst = &r->dst; 147 } 148 149 r->evaluations++; 150 if (pfi_kif_match(r->kif, kif) == r->ifnot) 151 r = r->skip[PF_SKIP_IFP].ptr; 152 else if (r->direction && r->direction != direction) 153 r = r->skip[PF_SKIP_DIR].ptr; 154 else if (r->af && r->af != pd->af) 155 r = r->skip[PF_SKIP_AF].ptr; 156 else if (r->proto && r->proto != pd->proto) 157 r = r->skip[PF_SKIP_PROTO].ptr; 158 else if (PF_MISMATCHAW(&src->addr, saddr, pd->af, 159 src->neg, kif, M_GETFIB(m))) 160 r = r->skip[src == &r->src ? PF_SKIP_SRC_ADDR : 161 PF_SKIP_DST_ADDR].ptr; 162 else if (src->port_op && !pf_match_port(src->port_op, 163 src->port[0], src->port[1], sport)) 164 r = r->skip[src == &r->src ? PF_SKIP_SRC_PORT : 165 PF_SKIP_DST_PORT].ptr; 166 else if (dst != NULL && 167 PF_MISMATCHAW(&dst->addr, daddr, pd->af, dst->neg, NULL, 168 M_GETFIB(m))) 169 r = r->skip[PF_SKIP_DST_ADDR].ptr; 170 else if (xdst != NULL && PF_MISMATCHAW(xdst, daddr, pd->af, 171 0, NULL, M_GETFIB(m))) 172 r = TAILQ_NEXT(r, entries); 173 else if (dst != NULL && dst->port_op && 174 !pf_match_port(dst->port_op, dst->port[0], 175 dst->port[1], dport)) 176 r = r->skip[PF_SKIP_DST_PORT].ptr; 177 else if (r->match_tag && !pf_match_tag(m, r, &tag, 178 pd->pf_mtag ? pd->pf_mtag->tag : 0)) 179 r = TAILQ_NEXT(r, entries); 180 else if (r->os_fingerprint != PF_OSFP_ANY && (pd->proto != 181 IPPROTO_TCP || !pf_osfp_match(pf_osfp_fingerprint(pd, m, 182 off, pd->hdr.tcp), r->os_fingerprint))) 183 r = TAILQ_NEXT(r, entries); 184 else { 185 if (r->tag) 186 tag = r->tag; 187 if (r->rtableid >= 0) 188 rtableid = r->rtableid; 189 if (r->anchor == NULL) { 190 rm = r; 191 } else 192 pf_step_into_anchor(anchor_stack, &asd, 193 &ruleset, rs_num, &r, NULL, NULL); 194 } 195 if (r == NULL) 196 pf_step_out_of_anchor(anchor_stack, &asd, &ruleset, 197 rs_num, &r, NULL, NULL); 198 } 199 200 if (tag > 0 && pf_tag_packet(m, pd, tag)) 201 return (NULL); 202 if (rtableid >= 0) 203 M_SETFIB(m, rtableid); 204 205 if (rm != NULL && (rm->action == PF_NONAT || 206 rm->action == PF_NORDR || rm->action == PF_NOBINAT)) 207 return (NULL); 208 return (rm); 209 } 210 211 static int 212 pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r, 213 struct pf_addr *saddr, struct pf_addr *daddr, u_int16_t dport, 214 struct pf_addr *naddr, u_int16_t *nport, u_int16_t low, u_int16_t high, 215 struct pf_src_node **sn) 216 { 217 struct pf_state_key_cmp key; 218 struct pf_addr init_addr; 219 u_int16_t cut; 220 221 bzero(&init_addr, sizeof(init_addr)); 222 if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn)) 223 return (1); 224 225 if (proto == IPPROTO_ICMP) { 226 low = 1; 227 high = 65535; 228 } 229 230 do { 231 key.af = af; 232 key.proto = proto; 233 PF_ACPY(&key.addr[1], daddr, key.af); 234 PF_ACPY(&key.addr[0], naddr, key.af); 235 key.port[1] = dport; 236 237 /* 238 * port search; start random, step; 239 * similar 2 portloop in in_pcbbind 240 */ 241 if (!(proto == IPPROTO_TCP || proto == IPPROTO_UDP || 242 proto == IPPROTO_ICMP)) { 243 key.port[0] = dport; 244 if (pf_find_state_all(&key, PF_IN, NULL) == NULL) 245 return (0); 246 } else if (low == 0 && high == 0) { 247 key.port[0] = *nport; 248 if (pf_find_state_all(&key, PF_IN, NULL) == NULL) 249 return (0); 250 } else if (low == high) { 251 key.port[0] = htons(low); 252 if (pf_find_state_all(&key, PF_IN, NULL) == NULL) { 253 *nport = htons(low); 254 return (0); 255 } 256 } else { 257 u_int16_t tmp; 258 259 if (low > high) { 260 tmp = low; 261 low = high; 262 high = tmp; 263 } 264 /* low < high */ 265 cut = htonl(arc4random()) % (1 + high - low) + low; 266 /* low <= cut <= high */ 267 for (tmp = cut; tmp <= high; ++(tmp)) { 268 key.port[0] = htons(tmp); 269 if (pf_find_state_all(&key, PF_IN, NULL) == 270 NULL) { 271 *nport = htons(tmp); 272 return (0); 273 } 274 } 275 for (tmp = cut - 1; tmp >= low; --(tmp)) { 276 key.port[0] = htons(tmp); 277 if (pf_find_state_all(&key, PF_IN, NULL) == 278 NULL) { 279 *nport = htons(tmp); 280 return (0); 281 } 282 } 283 } 284 285 switch (r->rpool.opts & PF_POOL_TYPEMASK) { 286 case PF_POOL_RANDOM: 287 case PF_POOL_ROUNDROBIN: 288 if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn)) 289 return (1); 290 break; 291 case PF_POOL_NONE: 292 case PF_POOL_SRCHASH: 293 case PF_POOL_BITMASK: 294 default: 295 return (1); 296 } 297 } while (! PF_AEQ(&init_addr, naddr, af) ); 298 return (1); /* none available */ 299 } 300 301 int 302 pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr, 303 struct pf_addr *naddr, struct pf_addr *init_addr, struct pf_src_node **sn) 304 { 305 struct pf_pool *rpool = &r->rpool; 306 struct pf_addr *raddr = NULL, *rmask = NULL; 307 308 if (*sn == NULL && r->rpool.opts & PF_POOL_STICKYADDR && 309 (r->rpool.opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) { 310 *sn = pf_find_src_node(saddr, r, af, 0); 311 if (*sn != NULL && !PF_AZERO(&(*sn)->raddr, af)) { 312 PF_ACPY(naddr, &(*sn)->raddr, af); 313 if (V_pf_status.debug >= PF_DEBUG_MISC) { 314 printf("pf_map_addr: src tracking maps "); 315 pf_print_host(saddr, 0, af); 316 printf(" to "); 317 pf_print_host(naddr, 0, af); 318 printf("\n"); 319 } 320 return (0); 321 } 322 } 323 324 if (rpool->cur->addr.type == PF_ADDR_NOROUTE) 325 return (1); 326 if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) { 327 switch (af) { 328 #ifdef INET 329 case AF_INET: 330 if (rpool->cur->addr.p.dyn->pfid_acnt4 < 1 && 331 (rpool->opts & PF_POOL_TYPEMASK) != 332 PF_POOL_ROUNDROBIN) 333 return (1); 334 raddr = &rpool->cur->addr.p.dyn->pfid_addr4; 335 rmask = &rpool->cur->addr.p.dyn->pfid_mask4; 336 break; 337 #endif /* INET */ 338 #ifdef INET6 339 case AF_INET6: 340 if (rpool->cur->addr.p.dyn->pfid_acnt6 < 1 && 341 (rpool->opts & PF_POOL_TYPEMASK) != 342 PF_POOL_ROUNDROBIN) 343 return (1); 344 raddr = &rpool->cur->addr.p.dyn->pfid_addr6; 345 rmask = &rpool->cur->addr.p.dyn->pfid_mask6; 346 break; 347 #endif /* INET6 */ 348 } 349 } else if (rpool->cur->addr.type == PF_ADDR_TABLE) { 350 if ((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN) 351 return (1); /* unsupported */ 352 } else { 353 raddr = &rpool->cur->addr.v.a.addr; 354 rmask = &rpool->cur->addr.v.a.mask; 355 } 356 357 switch (rpool->opts & PF_POOL_TYPEMASK) { 358 case PF_POOL_NONE: 359 PF_ACPY(naddr, raddr, af); 360 break; 361 case PF_POOL_BITMASK: 362 PF_POOLMASK(naddr, raddr, rmask, saddr, af); 363 break; 364 case PF_POOL_RANDOM: 365 if (init_addr != NULL && PF_AZERO(init_addr, af)) { 366 switch (af) { 367 #ifdef INET 368 case AF_INET: 369 rpool->counter.addr32[0] = htonl(arc4random()); 370 break; 371 #endif /* INET */ 372 #ifdef INET6 373 case AF_INET6: 374 if (rmask->addr32[3] != 0xffffffff) 375 rpool->counter.addr32[3] = 376 htonl(arc4random()); 377 else 378 break; 379 if (rmask->addr32[2] != 0xffffffff) 380 rpool->counter.addr32[2] = 381 htonl(arc4random()); 382 else 383 break; 384 if (rmask->addr32[1] != 0xffffffff) 385 rpool->counter.addr32[1] = 386 htonl(arc4random()); 387 else 388 break; 389 if (rmask->addr32[0] != 0xffffffff) 390 rpool->counter.addr32[0] = 391 htonl(arc4random()); 392 break; 393 #endif /* INET6 */ 394 } 395 PF_POOLMASK(naddr, raddr, rmask, &rpool->counter, af); 396 PF_ACPY(init_addr, naddr, af); 397 398 } else { 399 PF_AINC(&rpool->counter, af); 400 PF_POOLMASK(naddr, raddr, rmask, &rpool->counter, af); 401 } 402 break; 403 case PF_POOL_SRCHASH: 404 { 405 unsigned char hash[16]; 406 407 pf_hash(saddr, (struct pf_addr *)&hash, &rpool->key, af); 408 PF_POOLMASK(naddr, raddr, rmask, (struct pf_addr *)&hash, af); 409 break; 410 } 411 case PF_POOL_ROUNDROBIN: 412 { 413 struct pf_pooladdr *acur = rpool->cur; 414 415 /* 416 * XXXGL: in the round-robin case we need to store 417 * the round-robin machine state in the rule, thus 418 * forwarding thread needs to modify rule. 419 * 420 * This is done w/o locking, because performance is assumed 421 * more important than round-robin precision. 422 * 423 * In the simpliest case we just update the "rpool->cur" 424 * pointer. However, if pool contains tables or dynamic 425 * addresses, then "tblidx" is also used to store machine 426 * state. Since "tblidx" is int, concurrent access to it can't 427 * lead to inconsistence, only to lost of precision. 428 * 429 * Things get worse, if table contains not hosts, but 430 * prefixes. In this case counter also stores machine state, 431 * and for IPv6 address, counter can't be updated atomically. 432 * Probably, using round-robin on a table containing IPv6 433 * prefixes (or even IPv4) would cause a panic. 434 */ 435 436 if (rpool->cur->addr.type == PF_ADDR_TABLE) { 437 if (!pfr_pool_get(rpool->cur->addr.p.tbl, 438 &rpool->tblidx, &rpool->counter, af)) 439 goto get_addr; 440 } else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) { 441 if (!pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt, 442 &rpool->tblidx, &rpool->counter, af)) 443 goto get_addr; 444 } else if (pf_match_addr(0, raddr, rmask, &rpool->counter, af)) 445 goto get_addr; 446 447 try_next: 448 if (TAILQ_NEXT(rpool->cur, entries) == NULL) 449 rpool->cur = TAILQ_FIRST(&rpool->list); 450 else 451 rpool->cur = TAILQ_NEXT(rpool->cur, entries); 452 if (rpool->cur->addr.type == PF_ADDR_TABLE) { 453 rpool->tblidx = -1; 454 if (pfr_pool_get(rpool->cur->addr.p.tbl, 455 &rpool->tblidx, &rpool->counter, af)) { 456 /* table contains no address of type 'af' */ 457 if (rpool->cur != acur) 458 goto try_next; 459 return (1); 460 } 461 } else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) { 462 rpool->tblidx = -1; 463 if (pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt, 464 &rpool->tblidx, &rpool->counter, af)) { 465 /* table contains no address of type 'af' */ 466 if (rpool->cur != acur) 467 goto try_next; 468 return (1); 469 } 470 } else { 471 raddr = &rpool->cur->addr.v.a.addr; 472 rmask = &rpool->cur->addr.v.a.mask; 473 PF_ACPY(&rpool->counter, raddr, af); 474 } 475 476 get_addr: 477 PF_ACPY(naddr, &rpool->counter, af); 478 if (init_addr != NULL && PF_AZERO(init_addr, af)) 479 PF_ACPY(init_addr, naddr, af); 480 PF_AINC(&rpool->counter, af); 481 break; 482 } 483 } 484 if (*sn != NULL) 485 PF_ACPY(&(*sn)->raddr, naddr, af); 486 487 if (V_pf_status.debug >= PF_DEBUG_MISC && 488 (rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) { 489 printf("pf_map_addr: selected address "); 490 pf_print_host(naddr, 0, af); 491 printf("\n"); 492 } 493 494 return (0); 495 } 496 497 struct pf_rule * 498 pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction, 499 struct pfi_kif *kif, struct pf_src_node **sn, 500 struct pf_state_key **skp, struct pf_state_key **nkp, 501 struct pf_addr *saddr, struct pf_addr *daddr, 502 uint16_t sport, uint16_t dport, struct pf_anchor_stackframe *anchor_stack) 503 { 504 struct pf_rule *r = NULL; 505 struct pf_addr *naddr; 506 uint16_t *nport; 507 508 PF_RULES_RASSERT(); 509 KASSERT(*skp == NULL, ("*skp not NULL")); 510 KASSERT(*nkp == NULL, ("*nkp not NULL")); 511 512 if (direction == PF_OUT) { 513 r = pf_match_translation(pd, m, off, direction, kif, saddr, 514 sport, daddr, dport, PF_RULESET_BINAT, anchor_stack); 515 if (r == NULL) 516 r = pf_match_translation(pd, m, off, direction, kif, 517 saddr, sport, daddr, dport, PF_RULESET_NAT, 518 anchor_stack); 519 } else { 520 r = pf_match_translation(pd, m, off, direction, kif, saddr, 521 sport, daddr, dport, PF_RULESET_RDR, anchor_stack); 522 if (r == NULL) 523 r = pf_match_translation(pd, m, off, direction, kif, 524 saddr, sport, daddr, dport, PF_RULESET_BINAT, 525 anchor_stack); 526 } 527 528 if (r == NULL) 529 return (NULL); 530 531 switch (r->action) { 532 case PF_NONAT: 533 case PF_NOBINAT: 534 case PF_NORDR: 535 return (NULL); 536 } 537 538 *skp = pf_state_key_setup(pd, saddr, daddr, sport, dport); 539 if (*skp == NULL) 540 return (NULL); 541 *nkp = pf_state_key_clone(*skp); 542 if (*nkp == NULL) { 543 uma_zfree(V_pf_state_key_z, skp); 544 *skp = NULL; 545 return (NULL); 546 } 547 548 /* XXX We only modify one side for now. */ 549 naddr = &(*nkp)->addr[1]; 550 nport = &(*nkp)->port[1]; 551 552 switch (r->action) { 553 case PF_NAT: 554 if (pf_get_sport(pd->af, pd->proto, r, saddr, daddr, dport, 555 naddr, nport, r->rpool.proxy_port[0], 556 r->rpool.proxy_port[1], sn)) { 557 DPFPRINTF(PF_DEBUG_MISC, 558 ("pf: NAT proxy port allocation (%u-%u) failed\n", 559 r->rpool.proxy_port[0], r->rpool.proxy_port[1])); 560 goto notrans; 561 } 562 break; 563 case PF_BINAT: 564 switch (direction) { 565 case PF_OUT: 566 if (r->rpool.cur->addr.type == PF_ADDR_DYNIFTL){ 567 switch (pd->af) { 568 #ifdef INET 569 case AF_INET: 570 if (r->rpool.cur->addr.p.dyn-> 571 pfid_acnt4 < 1) 572 goto notrans; 573 PF_POOLMASK(naddr, 574 &r->rpool.cur->addr.p.dyn-> 575 pfid_addr4, 576 &r->rpool.cur->addr.p.dyn-> 577 pfid_mask4, saddr, AF_INET); 578 break; 579 #endif /* INET */ 580 #ifdef INET6 581 case AF_INET6: 582 if (r->rpool.cur->addr.p.dyn-> 583 pfid_acnt6 < 1) 584 goto notrans; 585 PF_POOLMASK(naddr, 586 &r->rpool.cur->addr.p.dyn-> 587 pfid_addr6, 588 &r->rpool.cur->addr.p.dyn-> 589 pfid_mask6, saddr, AF_INET6); 590 break; 591 #endif /* INET6 */ 592 } 593 } else 594 PF_POOLMASK(naddr, 595 &r->rpool.cur->addr.v.a.addr, 596 &r->rpool.cur->addr.v.a.mask, saddr, 597 pd->af); 598 break; 599 case PF_IN: 600 if (r->src.addr.type == PF_ADDR_DYNIFTL) { 601 switch (pd->af) { 602 #ifdef INET 603 case AF_INET: 604 if (r->src.addr.p.dyn-> pfid_acnt4 < 1) 605 goto notrans; 606 PF_POOLMASK(naddr, 607 &r->src.addr.p.dyn->pfid_addr4, 608 &r->src.addr.p.dyn->pfid_mask4, 609 daddr, AF_INET); 610 break; 611 #endif /* INET */ 612 #ifdef INET6 613 case AF_INET6: 614 if (r->src.addr.p.dyn->pfid_acnt6 < 1) 615 goto notrans; 616 PF_POOLMASK(naddr, 617 &r->src.addr.p.dyn->pfid_addr6, 618 &r->src.addr.p.dyn->pfid_mask6, 619 daddr, AF_INET6); 620 break; 621 #endif /* INET6 */ 622 } 623 } else 624 PF_POOLMASK(naddr, &r->src.addr.v.a.addr, 625 &r->src.addr.v.a.mask, daddr, pd->af); 626 break; 627 } 628 break; 629 case PF_RDR: { 630 if (pf_map_addr(pd->af, r, saddr, naddr, NULL, sn)) 631 goto notrans; 632 if ((r->rpool.opts & PF_POOL_TYPEMASK) == PF_POOL_BITMASK) 633 PF_POOLMASK(naddr, naddr, &r->rpool.cur->addr.v.a.mask, 634 daddr, pd->af); 635 636 if (r->rpool.proxy_port[1]) { 637 uint32_t tmp_nport; 638 639 tmp_nport = ((ntohs(dport) - ntohs(r->dst.port[0])) % 640 (r->rpool.proxy_port[1] - r->rpool.proxy_port[0] + 641 1)) + r->rpool.proxy_port[0]; 642 643 /* Wrap around if necessary. */ 644 if (tmp_nport > 65535) 645 tmp_nport -= 65535; 646 *nport = htons((uint16_t)tmp_nport); 647 } else if (r->rpool.proxy_port[0]) 648 *nport = htons(r->rpool.proxy_port[0]); 649 break; 650 } 651 default: 652 panic("%s: unknown action %u", __func__, r->action); 653 } 654 655 /* Return success only if translation really happened. */ 656 if (bcmp(*skp, *nkp, sizeof(struct pf_state_key_cmp))) 657 return (r); 658 659 notrans: 660 uma_zfree(V_pf_state_key_z, *nkp); 661 uma_zfree(V_pf_state_key_z, *skp); 662 *skp = *nkp = NULL; 663 664 return (NULL); 665 } 666