1 /* $NetBSD: npf_nat.c,v 1.23 2013/12/06 01:33:37 rmind Exp $ */ 2 3 /*- 4 * Copyright (c) 2010-2013 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This material is based upon work partially supported by The 8 * NetBSD Foundation under a contract with Mindaugas Rasiukevicius. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * NPF network address port translation (NAPT) and other forms of NAT. 34 * Described in RFC 2663, RFC 3022, etc. 35 * 36 * Overview 37 * 38 * There are few mechanisms: NAT policy, port map and translation. 39 * NAT module has a separate ruleset, where rules contain associated 40 * NAT policy, thus flexible filter criteria can be used. 41 * 42 * Translation types 43 * 44 * There are two types of translation: outbound (NPF_NATOUT) and 45 * inbound (NPF_NATIN). It should not be confused with connection 46 * direction. See npf_nat_which() for the description of how the 47 * addresses are rewritten. 48 * 49 * It should be noted that bi-directional NAT is a combined outbound 50 * and inbound translation, therefore constructed as two policies. 51 * 52 * NAT policies and port maps 53 * 54 * NAT (translation) policy is applied when a packet matches the rule. 55 * Apart from filter criteria, NAT policy has a translation IP address 56 * and associated port map. Port map is a bitmap used to reserve and 57 * use unique TCP/UDP ports for translation. Port maps are unique to 58 * the IP addresses, therefore multiple NAT policies with the same IP 59 * will share the same port map. 60 * 61 * Sessions, translation entries and their life-cycle 62 * 63 * NAT module relies on session management module. Each translated 64 * session has an associated translation entry (npf_nat_t), which 65 * contains information used for backwards stream translation, i.e. 66 * original IP address with port and translation port, allocated from 67 * the port map. Each NAT entry is associated with the policy, which 68 * contains translation IP address. Allocated port is returned to the 69 * port map and NAT entry is destroyed when session expires. 70 */ 71 72 #include <sys/cdefs.h> 73 __KERNEL_RCSID(0, "$NetBSD: npf_nat.c,v 1.23 2013/12/06 01:33:37 rmind Exp $"); 74 75 #include <sys/param.h> 76 #include <sys/types.h> 77 78 #include <sys/atomic.h> 79 #include <sys/bitops.h> 80 #include <sys/condvar.h> 81 #include <sys/kmem.h> 82 #include <sys/mutex.h> 83 #include <sys/pool.h> 84 #include <sys/proc.h> 85 #include <sys/cprng.h> 86 87 #include <net/pfil.h> 88 #include <netinet/in.h> 89 90 #include "npf_impl.h" 91 92 /* 93 * NPF portmap structure. 94 */ 95 typedef struct { 96 u_int p_refcnt; 97 uint32_t p_bitmap[0]; 98 } npf_portmap_t; 99 100 /* Portmap range: [ 1024 .. 65535 ] */ 101 #define PORTMAP_FIRST (1024) 102 #define PORTMAP_SIZE ((65536 - PORTMAP_FIRST) / 32) 103 #define PORTMAP_FILLED ((uint32_t)~0) 104 #define PORTMAP_MASK (31) 105 #define PORTMAP_SHIFT (5) 106 107 #define PORTMAP_MEM_SIZE \ 108 (sizeof(npf_portmap_t) + (PORTMAP_SIZE * sizeof(uint32_t))) 109 110 /* 111 * NAT policy structure. 112 */ 113 struct npf_natpolicy { 114 LIST_HEAD(, npf_nat) n_nat_list; 115 volatile u_int n_refcnt; 116 kmutex_t n_lock; 117 kcondvar_t n_cv; 118 npf_portmap_t * n_portmap; 119 /* NPF_NP_CMP_START */ 120 int n_type; 121 u_int n_flags; 122 size_t n_addr_sz; 123 npf_addr_t n_taddr; 124 in_port_t n_tport; 125 }; 126 127 #define NPF_NP_CMP_START offsetof(npf_natpolicy_t, n_type) 128 #define NPF_NP_CMP_SIZE (sizeof(npf_natpolicy_t) - NPF_NP_CMP_START) 129 130 /* 131 * NAT translation entry for a session. 132 */ 133 struct npf_nat { 134 /* Association (list entry and a link pointer) with NAT policy. */ 135 LIST_ENTRY(npf_nat) nt_entry; 136 npf_natpolicy_t * nt_natpolicy; 137 npf_session_t * nt_session; 138 /* Original address and port (for backwards translation). */ 139 npf_addr_t nt_oaddr; 140 in_port_t nt_oport; 141 /* Translation port (for redirects). */ 142 in_port_t nt_tport; 143 /* ALG (if any) associated with this NAT entry. */ 144 npf_alg_t * nt_alg; 145 uintptr_t nt_alg_arg; 146 }; 147 148 static pool_cache_t nat_cache __read_mostly; 149 150 /* 151 * npf_nat_sys{init,fini}: initialise/destroy NAT subsystem structures. 152 */ 153 154 void 155 npf_nat_sysinit(void) 156 { 157 nat_cache = pool_cache_init(sizeof(npf_nat_t), coherency_unit, 158 0, 0, "npfnatpl", NULL, IPL_NET, NULL, NULL, NULL); 159 KASSERT(nat_cache != NULL); 160 } 161 162 void 163 npf_nat_sysfini(void) 164 { 165 /* All NAT policies should already be destroyed. */ 166 pool_cache_destroy(nat_cache); 167 } 168 169 /* 170 * npf_nat_newpolicy: create a new NAT policy. 171 * 172 * => Shares portmap if policy is on existing translation address. 173 */ 174 npf_natpolicy_t * 175 npf_nat_newpolicy(prop_dictionary_t natdict, npf_ruleset_t *nrlset) 176 { 177 npf_natpolicy_t *np; 178 prop_object_t obj; 179 npf_portmap_t *pm; 180 181 np = kmem_zalloc(sizeof(npf_natpolicy_t), KM_SLEEP); 182 183 /* Translation type and flags. */ 184 prop_dictionary_get_int32(natdict, "type", &np->n_type); 185 prop_dictionary_get_uint32(natdict, "flags", &np->n_flags); 186 187 /* Should be exclusively either inbound or outbound NAT. */ 188 if (((np->n_type == NPF_NATIN) ^ (np->n_type == NPF_NATOUT)) == 0) { 189 kmem_free(np, sizeof(npf_natpolicy_t)); 190 return NULL; 191 } 192 mutex_init(&np->n_lock, MUTEX_DEFAULT, IPL_SOFTNET); 193 cv_init(&np->n_cv, "npfnatcv"); 194 LIST_INIT(&np->n_nat_list); 195 196 /* Translation IP. */ 197 obj = prop_dictionary_get(natdict, "translation-ip"); 198 np->n_addr_sz = prop_data_size(obj); 199 KASSERT(np->n_addr_sz > 0 && np->n_addr_sz <= sizeof(npf_addr_t)); 200 memcpy(&np->n_taddr, prop_data_data_nocopy(obj), np->n_addr_sz); 201 202 /* Translation port (for redirect case). */ 203 prop_dictionary_get_uint16(natdict, "translation-port", &np->n_tport); 204 205 /* Determine if port map is needed. */ 206 np->n_portmap = NULL; 207 if ((np->n_flags & NPF_NAT_PORTMAP) == 0) { 208 /* No port map. */ 209 return np; 210 } 211 212 /* 213 * Inspect NAT policies in the ruleset for port map sharing. 214 * Note that npf_ruleset_sharepm() will increase the reference count. 215 */ 216 if (!npf_ruleset_sharepm(nrlset, np)) { 217 /* Allocate a new port map for the NAT policy. */ 218 pm = kmem_zalloc(PORTMAP_MEM_SIZE, KM_SLEEP); 219 pm->p_refcnt = 1; 220 KASSERT((uintptr_t)pm->p_bitmap == (uintptr_t)pm + sizeof(*pm)); 221 np->n_portmap = pm; 222 } else { 223 KASSERT(np->n_portmap != NULL); 224 } 225 return np; 226 } 227 228 /* 229 * npf_nat_freepolicy: free NAT policy and, on last reference, free portmap. 230 * 231 * => Called from npf_rule_free() during the reload via npf_ruleset_destroy(). 232 */ 233 void 234 npf_nat_freepolicy(npf_natpolicy_t *np) 235 { 236 npf_portmap_t *pm = np->n_portmap; 237 npf_session_t *se; 238 npf_nat_t *nt; 239 240 /* 241 * Disassociate all entries from the policy. At this point, 242 * new entries can no longer be created for this policy. 243 */ 244 mutex_enter(&np->n_lock); 245 LIST_FOREACH(nt, &np->n_nat_list, nt_entry) { 246 se = nt->nt_session; 247 KASSERT(se != NULL); 248 npf_session_expire(se); 249 } 250 while (!LIST_EMPTY(&np->n_nat_list)) { 251 cv_wait(&np->n_cv, &np->n_lock); 252 } 253 mutex_exit(&np->n_lock); 254 255 /* Kick the worker - all references should be going away. */ 256 npf_worker_signal(); 257 while (np->n_refcnt) { 258 kpause("npfgcnat", false, 1, NULL); 259 } 260 KASSERT(LIST_EMPTY(&np->n_nat_list)); 261 262 /* Destroy the port map, on last reference. */ 263 if (pm && --pm->p_refcnt == 0) { 264 KASSERT((np->n_flags & NPF_NAT_PORTMAP) != 0); 265 kmem_free(pm, PORTMAP_MEM_SIZE); 266 } 267 cv_destroy(&np->n_cv); 268 mutex_destroy(&np->n_lock); 269 kmem_free(np, sizeof(npf_natpolicy_t)); 270 } 271 272 void 273 npf_nat_freealg(npf_natpolicy_t *np, npf_alg_t *alg) 274 { 275 npf_nat_t *nt; 276 277 mutex_enter(&np->n_lock); 278 LIST_FOREACH(nt, &np->n_nat_list, nt_entry) { 279 if (nt->nt_alg != alg) { 280 continue; 281 } 282 nt->nt_alg = NULL; 283 } 284 mutex_exit(&np->n_lock); 285 } 286 287 /* 288 * npf_nat_matchpolicy: compare two NAT policies. 289 * 290 * => Return 0 on match, and non-zero otherwise. 291 */ 292 bool 293 npf_nat_matchpolicy(npf_natpolicy_t *np, npf_natpolicy_t *mnp) 294 { 295 void *np_raw, *mnp_raw; 296 /* 297 * Compare the relevant NAT policy information (in raw form), 298 * which is enough for matching criterion. 299 */ 300 KASSERT(np && mnp && np != mnp); 301 np_raw = (uint8_t *)np + NPF_NP_CMP_START; 302 mnp_raw = (uint8_t *)mnp + NPF_NP_CMP_START; 303 return (memcmp(np_raw, mnp_raw, NPF_NP_CMP_SIZE) == 0); 304 } 305 306 bool 307 npf_nat_sharepm(npf_natpolicy_t *np, npf_natpolicy_t *mnp) 308 { 309 npf_portmap_t *pm, *mpm; 310 311 KASSERT(np && mnp && np != mnp); 312 313 /* Using port map and having equal translation address? */ 314 if ((np->n_flags & mnp->n_flags & NPF_NAT_PORTMAP) == 0) { 315 return false; 316 } 317 if (np->n_addr_sz != mnp->n_addr_sz) { 318 return false; 319 } 320 if (memcmp(&np->n_taddr, &mnp->n_taddr, np->n_addr_sz) != 0) { 321 return false; 322 } 323 /* If NAT policy has an old port map - drop the reference. */ 324 mpm = mnp->n_portmap; 325 if (mpm) { 326 /* Note: at this point we cannot hold a last reference. */ 327 KASSERT(mpm->p_refcnt > 1); 328 mpm->p_refcnt--; 329 } 330 /* Share the port map. */ 331 pm = np->n_portmap; 332 mnp->n_portmap = pm; 333 pm->p_refcnt++; 334 return true; 335 } 336 337 /* 338 * npf_nat_getport: allocate and return a port in the NAT policy portmap. 339 * 340 * => Returns in network byte-order. 341 * => Zero indicates failure. 342 */ 343 static in_port_t 344 npf_nat_getport(npf_natpolicy_t *np) 345 { 346 npf_portmap_t *pm = np->n_portmap; 347 u_int n = PORTMAP_SIZE, idx, bit; 348 uint32_t map, nmap; 349 350 idx = cprng_fast32() % PORTMAP_SIZE; 351 for (;;) { 352 KASSERT(idx < PORTMAP_SIZE); 353 map = pm->p_bitmap[idx]; 354 if (__predict_false(map == PORTMAP_FILLED)) { 355 if (n-- == 0) { 356 /* No space. */ 357 return 0; 358 } 359 /* This bitmap is filled, next. */ 360 idx = (idx ? idx : PORTMAP_SIZE) - 1; 361 continue; 362 } 363 bit = ffs32(~map) - 1; 364 nmap = map | (1 << bit); 365 if (atomic_cas_32(&pm->p_bitmap[idx], map, nmap) == map) { 366 /* Success. */ 367 break; 368 } 369 } 370 return htons(PORTMAP_FIRST + (idx << PORTMAP_SHIFT) + bit); 371 } 372 373 /* 374 * npf_nat_takeport: allocate specific port in the NAT policy portmap. 375 */ 376 static bool 377 npf_nat_takeport(npf_natpolicy_t *np, in_port_t port) 378 { 379 npf_portmap_t *pm = np->n_portmap; 380 uint32_t map, nmap; 381 u_int idx, bit; 382 383 port = ntohs(port) - PORTMAP_FIRST; 384 idx = port >> PORTMAP_SHIFT; 385 bit = port & PORTMAP_MASK; 386 map = pm->p_bitmap[idx]; 387 nmap = map | (1 << bit); 388 if (map == nmap) { 389 /* Already taken. */ 390 return false; 391 } 392 return atomic_cas_32(&pm->p_bitmap[idx], map, nmap) == map; 393 } 394 395 /* 396 * npf_nat_putport: return port as available in the NAT policy portmap. 397 * 398 * => Port should be in network byte-order. 399 */ 400 static void 401 npf_nat_putport(npf_natpolicy_t *np, in_port_t port) 402 { 403 npf_portmap_t *pm = np->n_portmap; 404 uint32_t map, nmap; 405 u_int idx, bit; 406 407 port = ntohs(port) - PORTMAP_FIRST; 408 idx = port >> PORTMAP_SHIFT; 409 bit = port & PORTMAP_MASK; 410 do { 411 map = pm->p_bitmap[idx]; 412 KASSERT(map | (1 << bit)); 413 nmap = map & ~(1 << bit); 414 } while (atomic_cas_32(&pm->p_bitmap[idx], map, nmap) != map); 415 } 416 417 /* 418 * npf_nat_which: tell which address (source or destination) should be 419 * rewritten given the combination of the NAT type and flow direction. 420 */ 421 static inline u_int 422 npf_nat_which(const int type, bool forw) 423 { 424 /* 425 * Outbound NAT rewrites: 426 * - Source on "forwards" stream. 427 * - Destination on "backwards" stream. 428 * Inbound NAT is other way round. 429 */ 430 if (type == NPF_NATOUT) { 431 forw = !forw; 432 } else { 433 KASSERT(type == NPF_NATIN); 434 } 435 CTASSERT(NPF_SRC == 0 && NPF_DST == 1); 436 KASSERT(forw == 0 || forw == 1); 437 return (u_int)forw; 438 } 439 440 /* 441 * npf_nat_inspect: inspect packet against NAT ruleset and return a policy. 442 * 443 * => Acquire a reference on the policy, if found. 444 */ 445 static npf_natpolicy_t * 446 npf_nat_inspect(npf_cache_t *npc, nbuf_t *nbuf, const int di) 447 { 448 int slock = npf_config_read_enter(); 449 npf_ruleset_t *rlset = npf_config_natset(); 450 npf_natpolicy_t *np; 451 npf_rule_t *rl; 452 453 rl = npf_ruleset_inspect(npc, nbuf, rlset, di, NPF_LAYER_3); 454 if (rl == NULL) { 455 npf_config_read_exit(slock); 456 return NULL; 457 } 458 np = npf_rule_getnat(rl); 459 atomic_inc_uint(&np->n_refcnt); 460 npf_config_read_exit(slock); 461 return np; 462 } 463 464 /* 465 * npf_nat_create: create a new NAT translation entry. 466 */ 467 static npf_nat_t * 468 npf_nat_create(npf_cache_t *npc, npf_natpolicy_t *np, npf_session_t *se) 469 { 470 const int proto = npc->npc_proto; 471 npf_nat_t *nt; 472 473 KASSERT(npf_iscached(npc, NPC_IP46)); 474 KASSERT(npf_iscached(npc, NPC_LAYER4)); 475 476 /* Construct a new NAT entry and associate it with the session. */ 477 nt = pool_cache_get(nat_cache, PR_NOWAIT); 478 if (nt == NULL){ 479 return NULL; 480 } 481 npf_stats_inc(NPF_STAT_NAT_CREATE); 482 nt->nt_natpolicy = np; 483 nt->nt_session = se; 484 nt->nt_alg = NULL; 485 486 /* Save the original address which may be rewritten. */ 487 if (np->n_type == NPF_NATOUT) { 488 /* Outbound NAT: source (think internal) address. */ 489 memcpy(&nt->nt_oaddr, npc->npc_ips[NPF_SRC], npc->npc_alen); 490 } else { 491 /* Inbound NAT: destination (think external) address. */ 492 KASSERT(np->n_type == NPF_NATIN); 493 memcpy(&nt->nt_oaddr, npc->npc_ips[NPF_DST], npc->npc_alen); 494 } 495 496 /* 497 * Port translation, if required, and if it is TCP/UDP. 498 */ 499 if ((np->n_flags & NPF_NAT_PORTS) == 0 || 500 (proto != IPPROTO_TCP && proto != IPPROTO_UDP)) { 501 nt->nt_oport = 0; 502 nt->nt_tport = 0; 503 goto out; 504 } 505 506 /* Save the relevant TCP/UDP port. */ 507 if (proto == IPPROTO_TCP) { 508 const struct tcphdr *th = npc->npc_l4.tcp; 509 nt->nt_oport = (np->n_type == NPF_NATOUT) ? 510 th->th_sport : th->th_dport; 511 } else { 512 const struct udphdr *uh = npc->npc_l4.udp; 513 nt->nt_oport = (np->n_type == NPF_NATOUT) ? 514 uh->uh_sport : uh->uh_dport; 515 } 516 517 /* Get a new port for translation. */ 518 if ((np->n_flags & NPF_NAT_PORTMAP) != 0) { 519 nt->nt_tport = npf_nat_getport(np); 520 } else { 521 nt->nt_tport = np->n_tport; 522 } 523 out: 524 mutex_enter(&np->n_lock); 525 LIST_INSERT_HEAD(&np->n_nat_list, nt, nt_entry); 526 mutex_exit(&np->n_lock); 527 return nt; 528 } 529 530 /* 531 * npf_nat_translate: perform address and/or port translation. 532 */ 533 int 534 npf_nat_translate(npf_cache_t *npc, nbuf_t *nbuf, npf_nat_t *nt, bool forw) 535 { 536 const int proto = npc->npc_proto; 537 const npf_natpolicy_t *np = nt->nt_natpolicy; 538 const u_int which = npf_nat_which(np->n_type, forw); 539 const npf_addr_t *addr; 540 in_port_t port; 541 542 KASSERT(npf_iscached(npc, NPC_IP46)); 543 KASSERT(npf_iscached(npc, NPC_LAYER4)); 544 KASSERT(!nbuf_flag_p(nbuf, NBUF_DATAREF_RESET)); 545 546 if (forw) { 547 /* "Forwards" stream: use translation address/port. */ 548 addr = &np->n_taddr; 549 port = nt->nt_tport; 550 } else { 551 /* "Backwards" stream: use original address/port. */ 552 addr = &nt->nt_oaddr; 553 port = nt->nt_oport; 554 } 555 KASSERT((np->n_flags & NPF_NAT_PORTS) != 0 || port == 0); 556 557 /* Execute ALG hook first. */ 558 if ((npc->npc_info & NPC_ALG_EXEC) == 0) { 559 npc->npc_info |= NPC_ALG_EXEC; 560 npf_alg_exec(npc, nbuf, nt, forw); 561 } 562 563 /* 564 * Rewrite IP and/or TCP/UDP checksums first, since we need the 565 * current (old) address/port for the calculations. Then perform 566 * the address translation i.e. rewrite source or destination. 567 */ 568 if (!npf_rwrcksum(npc, which, addr, port)) { 569 return EINVAL; 570 } 571 if (!npf_rwrip(npc, which, addr)) { 572 return EINVAL; 573 } 574 575 if ((np->n_flags & NPF_NAT_PORTS) == 0) { 576 /* Done. */ 577 return 0; 578 } 579 580 switch (proto) { 581 case IPPROTO_TCP: 582 case IPPROTO_UDP: 583 /* Rewrite source/destination port. */ 584 if (!npf_rwrport(npc, which, port)) { 585 return EINVAL; 586 } 587 break; 588 case IPPROTO_ICMP: 589 KASSERT(npf_iscached(npc, NPC_ICMP)); 590 /* Nothing. */ 591 break; 592 default: 593 return ENOTSUP; 594 } 595 return 0; 596 } 597 598 /* 599 * npf_do_nat: 600 * - Inspect packet for a NAT policy, unless a session with a NAT 601 * association already exists. In such case, determine whether it 602 * is a "forwards" or "backwards" stream. 603 * - Perform translation: rewrite source or destination fields, 604 * depending on translation type and direction. 605 * - Associate a NAT policy with a session (may establish a new). 606 */ 607 int 608 npf_do_nat(npf_cache_t *npc, npf_session_t *se, nbuf_t *nbuf, const int di) 609 { 610 npf_session_t *nse = NULL; 611 npf_natpolicy_t *np; 612 npf_nat_t *nt; 613 int error; 614 bool forw; 615 616 /* All relevant IPv4 data should be already cached. */ 617 if (!npf_iscached(npc, NPC_IP46) || !npf_iscached(npc, NPC_LAYER4)) { 618 return 0; 619 } 620 KASSERT(!nbuf_flag_p(nbuf, NBUF_DATAREF_RESET)); 621 622 /* 623 * Return the NAT entry associated with the session, if any. 624 * Determines whether the stream is "forwards" or "backwards". 625 * Note: no need to lock, since reference on session is held. 626 */ 627 if (se && (nt = npf_session_retnat(se, di, &forw)) != NULL) { 628 np = nt->nt_natpolicy; 629 goto translate; 630 } 631 632 /* 633 * Inspect the packet for a NAT policy, if there is no session. 634 * Note: acquires a reference if found. 635 */ 636 np = npf_nat_inspect(npc, nbuf, di); 637 if (np == NULL) { 638 /* If packet does not match - done. */ 639 return 0; 640 } 641 forw = true; 642 643 /* 644 * If there is no local session (no "stateful" rule - unusual, but 645 * possible configuration), establish one before translation. Note 646 * that it is not a "pass" session, therefore passing of "backwards" 647 * stream depends on other, stateless filtering rules. 648 */ 649 if (se == NULL) { 650 nse = npf_session_establish(npc, nbuf, di); 651 if (nse == NULL) { 652 atomic_dec_uint(&np->n_refcnt); 653 return ENOMEM; 654 } 655 se = nse; 656 } 657 658 /* 659 * Create a new NAT entry and associate with the session. 660 * We will consume the reference on success (release on error). 661 */ 662 nt = npf_nat_create(npc, np, se); 663 if (nt == NULL) { 664 atomic_dec_uint(&np->n_refcnt); 665 error = ENOMEM; 666 goto out; 667 } 668 669 /* Associate the NAT translation entry with the session. */ 670 error = npf_session_setnat(se, nt, np->n_type); 671 if (error) { 672 /* Will release the reference. */ 673 npf_nat_destroy(nt); 674 goto out; 675 } 676 677 /* Determine whether any ALG matches. */ 678 if (npf_alg_match(npc, nbuf, nt, di)) { 679 KASSERT(nt->nt_alg != NULL); 680 } 681 682 translate: 683 /* May need to process the delayed checksums first (XXX: NetBSD). */ 684 if (nbuf_cksum_barrier(nbuf, di)) { 685 npf_recache(npc, nbuf); 686 } 687 688 /* Perform the translation. */ 689 error = npf_nat_translate(npc, nbuf, nt, forw); 690 out: 691 if (error && nse) { 692 /* It created for NAT - just expire. */ 693 npf_session_expire(nse); 694 } 695 if (nse) { 696 npf_session_release(nse); 697 } 698 return error; 699 } 700 701 /* 702 * npf_nat_gettrans: return translation IP address and port. 703 */ 704 void 705 npf_nat_gettrans(npf_nat_t *nt, npf_addr_t **addr, in_port_t *port) 706 { 707 npf_natpolicy_t *np = nt->nt_natpolicy; 708 709 *addr = &np->n_taddr; 710 *port = nt->nt_tport; 711 } 712 713 /* 714 * npf_nat_getorig: return original IP address and port from translation entry. 715 */ 716 void 717 npf_nat_getorig(npf_nat_t *nt, npf_addr_t **addr, in_port_t *port) 718 { 719 *addr = &nt->nt_oaddr; 720 *port = nt->nt_oport; 721 } 722 723 /* 724 * npf_nat_setalg: associate an ALG with the NAT entry. 725 */ 726 void 727 npf_nat_setalg(npf_nat_t *nt, npf_alg_t *alg, uintptr_t arg) 728 { 729 nt->nt_alg = alg; 730 nt->nt_alg_arg = arg; 731 } 732 733 /* 734 * npf_nat_destroy: destroy NAT structure (performed on session expiration). 735 */ 736 void 737 npf_nat_destroy(npf_nat_t *nt) 738 { 739 npf_natpolicy_t *np = nt->nt_natpolicy; 740 741 /* Return any taken port to the portmap. */ 742 if ((np->n_flags & NPF_NAT_PORTMAP) != 0 && nt->nt_tport) { 743 npf_nat_putport(np, nt->nt_tport); 744 } 745 746 mutex_enter(&np->n_lock); 747 LIST_REMOVE(nt, nt_entry); 748 if (LIST_EMPTY(&np->n_nat_list)) { 749 /* Notify any waiters if empty. */ 750 cv_broadcast(&np->n_cv); 751 } 752 atomic_dec_uint(&np->n_refcnt); 753 mutex_exit(&np->n_lock); 754 755 pool_cache_put(nat_cache, nt); 756 npf_stats_inc(NPF_STAT_NAT_DESTROY); 757 } 758 759 /* 760 * npf_nat_save: construct NAT entry and reference to the NAT policy. 761 */ 762 int 763 npf_nat_save(prop_dictionary_t sedict, prop_array_t natlist, npf_nat_t *nt) 764 { 765 npf_natpolicy_t *np = nt->nt_natpolicy; 766 prop_object_iterator_t it; 767 prop_dictionary_t npdict; 768 prop_data_t nd, npd; 769 uint64_t itnp; 770 771 /* Set NAT entry data. */ 772 nd = prop_data_create_data(nt, sizeof(npf_nat_t)); 773 prop_dictionary_set(sedict, "nat-data", nd); 774 prop_object_release(nd); 775 776 /* Find or create a NAT policy. */ 777 it = prop_array_iterator(natlist); 778 while ((npdict = prop_object_iterator_next(it)) != NULL) { 779 CTASSERT(sizeof(uintptr_t) <= sizeof(uint64_t)); 780 prop_dictionary_get_uint64(npdict, "id-ptr", &itnp); 781 if ((uintptr_t)itnp == (uintptr_t)np) { 782 break; 783 } 784 } 785 if (npdict == NULL) { 786 /* Create NAT policy dictionary and copy the data. */ 787 npdict = prop_dictionary_create(); 788 npd = prop_data_create_data(np, sizeof(npf_natpolicy_t)); 789 prop_dictionary_set(npdict, "nat-policy-data", npd); 790 prop_object_release(npd); 791 792 CTASSERT(sizeof(uintptr_t) <= sizeof(uint64_t)); 793 prop_dictionary_set_uint64(npdict, "id-ptr", (uintptr_t)np); 794 prop_array_add(natlist, npdict); 795 prop_object_release(npdict); 796 } 797 prop_dictionary_set(sedict, "nat-policy", npdict); 798 prop_object_release(npdict); 799 return 0; 800 } 801 802 /* 803 * npf_nat_restore: find a matching NAT policy and restore NAT entry. 804 * 805 * => Caller should lock the active NAT ruleset. 806 */ 807 npf_nat_t * 808 npf_nat_restore(prop_dictionary_t sedict, npf_session_t *se) 809 { 810 const npf_natpolicy_t *onp; 811 const npf_nat_t *ntraw; 812 prop_object_t obj; 813 npf_natpolicy_t *np; 814 npf_rule_t *rl; 815 npf_nat_t *nt; 816 817 /* Get raw NAT entry. */ 818 obj = prop_dictionary_get(sedict, "nat-data"); 819 ntraw = prop_data_data_nocopy(obj); 820 if (ntraw == NULL || prop_data_size(obj) != sizeof(npf_nat_t)) { 821 return NULL; 822 } 823 824 /* Find a stored NAT policy information. */ 825 obj = prop_dictionary_get( 826 prop_dictionary_get(sedict, "nat-policy"), "nat-policy-data"); 827 onp = prop_data_data_nocopy(obj); 828 if (onp == NULL || prop_data_size(obj) != sizeof(npf_natpolicy_t)) { 829 return NULL; 830 } 831 832 /* 833 * Match if there is an existing NAT policy. Will acquire the 834 * reference on it if further operations are successful. 835 */ 836 KASSERT(npf_config_locked_p()); 837 rl = npf_ruleset_matchnat(npf_config_natset(), __UNCONST(onp)); 838 if (rl == NULL) { 839 return NULL; 840 } 841 np = npf_rule_getnat(rl); 842 KASSERT(np != NULL); 843 844 /* Take a specific port from port-map. */ 845 if (!npf_nat_takeport(np, ntraw->nt_tport)) { 846 return NULL; 847 } 848 atomic_inc_uint(&np->n_refcnt); 849 850 /* Create and return NAT entry for association. */ 851 nt = pool_cache_get(nat_cache, PR_WAITOK); 852 memcpy(nt, ntraw, sizeof(npf_nat_t)); 853 LIST_INSERT_HEAD(&np->n_nat_list, nt, nt_entry); 854 nt->nt_natpolicy = np; 855 nt->nt_session = se; 856 nt->nt_alg = NULL; 857 return nt; 858 } 859 860 #if defined(DDB) || defined(_NPF_TESTING) 861 862 void 863 npf_nat_dump(const npf_nat_t *nt) 864 { 865 const npf_natpolicy_t *np; 866 struct in_addr ip; 867 868 np = nt->nt_natpolicy; 869 memcpy(&ip, &np->n_taddr, sizeof(ip)); 870 printf("\tNATP(%p): type %d flags 0x%x taddr %s tport %d\n", 871 np, np->n_type, np->n_flags, inet_ntoa(ip), np->n_tport); 872 memcpy(&ip, &nt->nt_oaddr, sizeof(ip)); 873 printf("\tNAT: original address %s oport %d tport %d\n", 874 inet_ntoa(ip), ntohs(nt->nt_oport), ntohs(nt->nt_tport)); 875 if (nt->nt_alg) { 876 printf("\tNAT ALG = %p, ARG = %p\n", 877 nt->nt_alg, (void *)nt->nt_alg_arg); 878 } 879 } 880 881 #endif 882