>Number: 157867 >Category: kern >Synopsis: [patch][ipfw] natd globalport support for ipfw nat >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Tue Jun 14 06:00:19 UTC 2011 >Closed-Date: >Last-Modified: >Originator: Alexander V. Chernikov >Release: 9.0-CURRENT >Organization: JSC Meganet >Environment: FreeBSD zfscurr0.home.ipfw.ru 9.0-CURRENT FreeBSD 9.0-CURRENT #7 r222980M: Sat Jun 11 20:25:05 MSD 2011 r...@zfscurr0.home.ipfw.ru:/var/xtmp/usj/obj/usr/src/sys/DEVEL amd64
>Description: Permit ipfw nat to find translation state in multiple nat instances via new 'global' option. This functionality is very close to natd -globalport (please see MULTIPLE ISTANCES in natd(8) for more detailed explanation) >How-To-Repeat: >Fix: Patch attached with submission follows: Index: sbin/ipfw/nat.c =================================================================== --- sbin/ipfw/nat.c (revision 221263) +++ sbin/ipfw/nat.c (working copy) @@ -53,6 +53,7 @@ { "deny_in", TOK_DENY_INC }, { "same_ports", TOK_SAME_PORTS }, { "unreg_only", TOK_UNREG_ONLY }, + { "skip_global", TOK_SKIP_GLOBAL }, { "reset", TOK_RESET_ADDR }, { "reverse", TOK_ALIAS_REV }, { "proxy_only", TOK_PROXY_ONLY }, @@ -675,6 +676,9 @@ } else if (n->mode & PKT_ALIAS_UNREGISTERED_ONLY) { printf(" unreg_only"); n->mode &= ~PKT_ALIAS_UNREGISTERED_ONLY; + } else if (n->mode & PKT_ALIAS_SKIP_GLOBAL) { + printf(" skip_global"); + n->mode &= ~PKT_ALIAS_SKIP_GLOBAL; } else if (n->mode & PKT_ALIAS_RESET_ON_ADDR_CHANGE) { printf(" reset"); n->mode &= ~PKT_ALIAS_RESET_ON_ADDR_CHANGE; @@ -815,6 +819,9 @@ case TOK_UNREG_ONLY: n->mode |= PKT_ALIAS_UNREGISTERED_ONLY; break; + case TOK_SKIP_GLOBAL: + n->mode |= PKT_ALIAS_SKIP_GLOBAL; + break; case TOK_RESET_ADDR: n->mode |= PKT_ALIAS_RESET_ON_ADDR_CHANGE; break; Index: sbin/ipfw/ipfw2.c =================================================================== --- sbin/ipfw/ipfw2.c (revision 221263) +++ sbin/ipfw/ipfw2.c (working copy) @@ -1112,7 +1112,10 @@ break; case O_NAT: - PRINT_UINT_ARG("nat ", cmd->arg1); + if (cmd->arg1 != 0) + PRINT_UINT_ARG("nat ", cmd->arg1); + else + printf("nat global"); break; case O_SETFIB: @@ -2731,7 +2734,12 @@ case TOK_NAT: action->opcode = O_NAT; action->len = F_INSN_SIZE(ipfw_insn_nat); - goto chkarg; + if (_substrcmp(*av, "global") == 0) { + action->arg1 = 0; + av++; + break; + } else + goto chkarg; case TOK_QUEUE: action->opcode = O_QUEUE; Index: sbin/ipfw/ipfw.8 =================================================================== --- sbin/ipfw/ipfw.8 (revision 221263) +++ sbin/ipfw/ipfw.8 (working copy) @@ -2419,8 +2419,28 @@ Reverse the way libalias handles aliasing. .It Cm proxy_only Obey transparent proxy rules only, packet aliasing is not performed. +.It Cm skip_global +Skip instance in case of global state lookup (see below). .El .Pp +Some specials value can be supplied instead of +.Va nat_number: +.Bl -tag -width indent +.It Cm global +Looks up translation state in all configured nat instances. If an entry +is found, packet is aliased according to that entry. If no entry +was found in any of the instances, packet is passed unchanged, and +no new entry will be created. See section +.Sx MULTIPLE INSTANCES +in +.Xr natd 8 +for more information. +.It Cm tablearg +Uses argument supplied in lookup table. See +.Sx LOOKUP TABLES +section below for more information on lookup tables. +.El +.Pp To let the packet continue after being (de)aliased, set the sysctl variable .Va net.inet.ip.fw.one_pass to 0. Index: sbin/ipfw/ipfw2.h =================================================================== --- sbin/ipfw/ipfw2.h (revision 221263) +++ sbin/ipfw/ipfw2.h (working copy) @@ -178,6 +178,7 @@ TOK_DENY_INC, TOK_SAME_PORTS, TOK_UNREG_ONLY, + TOK_SKIP_GLOBAL, TOK_RESET_ADDR, TOK_ALIAS_REV, TOK_PROXY_ONLY, Index: sys/netinet/libalias/alias.h =================================================================== --- sys/netinet/libalias/alias.h (revision 221263) +++ sys/netinet/libalias/alias.h (working copy) @@ -220,6 +220,12 @@ */ #define PKT_ALIAS_REVERSE 0x80 +/* + * If PKT_ALIAS_SKIP_GLOBAL is set, nat instance is not checked for matching states + * in 'nat global' rule. + */ +#define PKT_ALIAS_SKIP_GLOBAL 0x100 + /* Function return codes. */ #define PKT_ALIAS_ERROR -1 #define PKT_ALIAS_OK 1 Index: sys/netinet/ipfw/ip_fw_nat.c =================================================================== --- sys/netinet/ipfw/ip_fw_nat.c (revision 221263) +++ sys/netinet/ipfw/ip_fw_nat.c (working copy) @@ -208,11 +208,13 @@ struct mbuf *mcl; struct ip *ip; /* XXX - libalias duct tape */ - int ldt, retval; + int ldt, retval, found; char *c; + struct ip_fw_chain *chain; ldt = 0; retval = 0; + found = 0; mcl = m_megapullup(m, m->m_pkthdr.len); if (mcl == NULL) { args->m = NULL; @@ -257,12 +259,44 @@ ldt = 1; c = mtod(mcl, char *); - if (args->oif == NULL) - retval = LibAliasIn(t->lib, c, - mcl->m_len + M_TRAILINGSPACE(mcl)); - else - retval = LibAliasOut(t->lib, c, - mcl->m_len + M_TRAILINGSPACE(mcl)); + + /* Check if this is 'global' instance */ + if (t == NULL) { + if (args->oif == NULL) { + /* Wrong direction, skip processing */ + args->m = mcl; + return (IP_FW_NAT); + } + + chain = &V_layer3_chain; + IPFW_RLOCK(chain); + /* Check every nat entry... */ + LIST_FOREACH(t, &chain->nat, _next) { + if ((t->lib->packetAliasMode & PKT_ALIAS_SKIP_GLOBAL) != 0) + continue; + + if ((retval = LibAliasOutTry(t->lib, c, mcl->m_len + M_TRAILINGSPACE(mcl), 0)) == PKT_ALIAS_OK) { + /* Nat instance recognises state */ + found = 1; + break; + } + + } + IPFW_RUNLOCK(chain); + + if (found != 1) { + /* No instance found, return ignore */ + args->m = mcl; + return (IP_FW_NAT); + } + } else { + if (args->oif == NULL) + retval = LibAliasIn(t->lib, c, + mcl->m_len + M_TRAILINGSPACE(mcl)); + else + retval = LibAliasOut(t->lib, c, + mcl->m_len + M_TRAILINGSPACE(mcl)); + } if (retval == PKT_ALIAS_RESPOND) { m->m_flags |= M_SKIP_FIREWALL; retval = PKT_ALIAS_OK; Index: sys/netinet/ipfw/ip_fw2.c =================================================================== --- sys/netinet/ipfw/ip_fw2.c (revision 221263) +++ sys/netinet/ipfw/ip_fw2.c (working copy) @@ -2118,6 +2118,13 @@ int nat_id; set_match(args, f_pos, chain); + /* Check if this is 'global' nat rule */ + if (cmd->arg1 == 0) { + retval = ipfw_nat_ptr(args, NULL, m); + l = 0; + done = 1; + break; + } t = ((ipfw_insn_nat *)cmd)->nat; if (t == NULL) { nat_id = (cmd->arg1 == IP_FW_TABLEARG) ? >Release-Note: >Audit-Trail: >Unformatted: _______________________________________________ freebsd-bugs@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-bugs To unsubscribe, send any mail to "freebsd-bugs-unsubscr...@freebsd.org"