>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"

Reply via email to