svn commit: r224473 - in stable/8: sbin/ipfw sys/netinet/ipfw sys/netinet/libalias

Andrey V. Elsukov ae at FreeBSD.org
Thu Jul 28 10:10:40 UTC 2011


Author: ae
Date: Thu Jul 28 10:10:39 2011
New Revision: 224473
URL: http://svn.freebsd.org/changeset/base/224473

Log:
  MFC r223080:
    Implement "global" mode for ipfw nat. It is similar to natd(8)
    "globalport" option for multiple NAT instances.
  
    If ipfw rule contains "global" keyword instead of nat_number, then
    for each outgoing packet ipfw_nat looks up translation state in all
    configured nat instances. If an entry is found, packet aliased
    according to that entry, otherwise packet is passed unchanged.
  
    User can specify "skip_global" option in NAT configuration to exclude
    an instance from the lookup in global mode.
  
    PR:		kern/157867
    Submitted by:	Alexander V. Chernikov (previous version)

Modified:
  stable/8/sbin/ipfw/ipfw.8
  stable/8/sbin/ipfw/ipfw2.c
  stable/8/sbin/ipfw/ipfw2.h
  stable/8/sbin/ipfw/nat.c
  stable/8/sys/netinet/ipfw/ip_fw2.c
  stable/8/sys/netinet/ipfw/ip_fw_nat.c
  stable/8/sys/netinet/libalias/alias.h
Directory Properties:
  stable/8/sbin/ipfw/   (props changed)
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/geom/label/   (props changed)

Modified: stable/8/sbin/ipfw/ipfw.8
==============================================================================
--- stable/8/sbin/ipfw/ipfw.8	Thu Jul 28 09:27:01 2011	(r224472)
+++ stable/8/sbin/ipfw/ipfw.8	Thu Jul 28 10:10:39 2011	(r224473)
@@ -1,7 +1,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd May 30, 2011
+.Dd June 14, 2011
 .Dt IPFW 8
 .Os
 .Sh NAME
@@ -2422,6 +2422,27 @@ Reset table of the packet aliasing engin
 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

Modified: stable/8/sbin/ipfw/ipfw2.c
==============================================================================
--- stable/8/sbin/ipfw/ipfw2.c	Thu Jul 28 09:27:01 2011	(r224472)
+++ stable/8/sbin/ipfw/ipfw2.c	Thu Jul 28 10:10:39 2011	(r224473)
@@ -1112,8 +1112,11 @@ show_ipfw(struct ip_fw *rule, int pcwidt
 			break;
 
 		case O_NAT:
-			PRINT_UINT_ARG("nat ", cmd->arg1);
- 			break;
+			if (cmd->arg1 != 0)
+				PRINT_UINT_ARG("nat ", cmd->arg1);
+			else
+				printf("nat global");
+			break;
 
 		case O_SETFIB:
 			PRINT_UINT_ARG("setfib ", cmd->arg1);
@@ -2728,9 +2731,14 @@ ipfw_add(char *av[])
 		break;
 
 	case TOK_NAT:
- 		action->opcode = O_NAT;
- 		action->len = F_INSN_SIZE(ipfw_insn_nat);
-		goto chkarg;
+		action->opcode = O_NAT;
+		action->len = F_INSN_SIZE(ipfw_insn_nat);
+		if (_substrcmp(*av, "global") == 0) {
+			action->arg1 = 0;
+			av++;
+			break;
+		} else
+			goto chkarg;
 
 	case TOK_QUEUE:
 		action->opcode = O_QUEUE;

Modified: stable/8/sbin/ipfw/ipfw2.h
==============================================================================
--- stable/8/sbin/ipfw/ipfw2.h	Thu Jul 28 09:27:01 2011	(r224472)
+++ stable/8/sbin/ipfw/ipfw2.h	Thu Jul 28 10:10:39 2011	(r224473)
@@ -178,6 +178,7 @@ enum tokens {
  	TOK_DENY_INC,
  	TOK_SAME_PORTS,
  	TOK_UNREG_ONLY,
+	TOK_SKIP_GLOBAL,
  	TOK_RESET_ADDR,
  	TOK_ALIAS_REV,
  	TOK_PROXY_ONLY,

Modified: stable/8/sbin/ipfw/nat.c
==============================================================================
--- stable/8/sbin/ipfw/nat.c	Thu Jul 28 09:27:01 2011	(r224472)
+++ stable/8/sbin/ipfw/nat.c	Thu Jul 28 10:10:39 2011	(r224473)
@@ -53,6 +53,7 @@ static struct _s_x nat_params[] = {
  	{ "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 },
@@ -638,6 +639,9 @@ print_nat_config(unsigned char *buf)
 		} else if (n->mode & PKT_ALIAS_SAME_PORTS) {
 			printf(" same_ports");
 			n->mode &= ~PKT_ALIAS_SAME_PORTS;
+		} else if (n->mode & PKT_ALIAS_SKIP_GLOBAL) {
+			printf(" skip_global");
+			n->mode &= ~PKT_ALIAS_SKIP_GLOBAL;
 		} else if (n->mode & PKT_ALIAS_UNREGISTERED_ONLY) {
 			printf(" unreg_only");
 			n->mode &= ~PKT_ALIAS_UNREGISTERED_ONLY;
@@ -760,10 +764,11 @@ ipfw_config_nat(int ac, char **av)
 		case TOK_IF:
 			ac1--;
 			av1++;
-			break;	    
+			break;
 		case TOK_ALOG:
 		case TOK_DENY_INC:
 		case TOK_SAME_PORTS:
+		case TOK_SKIP_GLOBAL:
 		case TOK_UNREG_ONLY:
 		case TOK_RESET_ADDR:
 		case TOK_ALIAS_REV:
@@ -856,6 +861,9 @@ ipfw_config_nat(int ac, char **av)
 		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;

Modified: stable/8/sys/netinet/ipfw/ip_fw2.c
==============================================================================
--- stable/8/sys/netinet/ipfw/ip_fw2.c	Thu Jul 28 09:27:01 2011	(r224472)
+++ stable/8/sys/netinet/ipfw/ip_fw2.c	Thu Jul 28 10:10:39 2011	(r224473)
@@ -2128,6 +2128,13 @@ do {								\
 				    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) ?

Modified: stable/8/sys/netinet/ipfw/ip_fw_nat.c
==============================================================================
--- stable/8/sys/netinet/ipfw/ip_fw_nat.c	Thu Jul 28 09:27:01 2011	(r224472)
+++ stable/8/sys/netinet/ipfw/ip_fw_nat.c	Thu Jul 28 10:10:39 2011	(r224473)
@@ -207,7 +207,8 @@ ipfw_nat(struct ip_fw_args *args, struct
 	struct mbuf *mcl;
 	struct ip *ip;
 	/* XXX - libalias duct tape */
-	int ldt, retval;
+	int ldt, retval, found;
+	struct ip_fw_chain *chain;
 	char *c;
 
 	ldt = 0;
@@ -256,12 +257,44 @@ ipfw_nat(struct ip_fw_args *args, struct
 		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);
+		}
+
+		found = 0;
+		chain = &V_layer3_chain;
+		IPFW_RLOCK(chain);
+		/* Check every nat entry... */
+		LIST_FOREACH(t, &chain->nat, _next) {
+			if ((t->mode & PKT_ALIAS_SKIP_GLOBAL) != 0)
+				continue;
+			retval = LibAliasOutTry(t->lib, c,
+			    mcl->m_len + M_TRAILINGSPACE(mcl), 0);
+			if (retval == 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));
+	}
 
 	/*
 	 * We drop packet when:
@@ -274,7 +307,7 @@ ipfw_nat(struct ip_fw_args *args, struct
 	if (retval == PKT_ALIAS_ERROR ||
 	    (args->oif == NULL && (retval == PKT_ALIAS_UNRESOLVED_FRAGMENT ||
 	    (retval == PKT_ALIAS_IGNORED &&
-	    (t->lib->packetAliasMode & PKT_ALIAS_DENY_INCOMING) != 0)))) {
+	    (t->mode & PKT_ALIAS_DENY_INCOMING) != 0)))) {
 		/* XXX - should i add some logging? */
 		m_free(mcl);
 		args->m = NULL;

Modified: stable/8/sys/netinet/libalias/alias.h
==============================================================================
--- stable/8/sys/netinet/libalias/alias.h	Thu Jul 28 09:27:01 2011	(r224472)
+++ stable/8/sys/netinet/libalias/alias.h	Thu Jul 28 10:10:39 2011	(r224473)
@@ -220,6 +220,12 @@ struct mbuf    *m_megapullup(struct mbuf
  */
 #define	PKT_ALIAS_REVERSE		0x80
 
+/*
+ * If PKT_ALIAS_SKIP_GLOBAL is set, nat instance is not checked for matching
+ * states in 'ipfw nat global' rule.
+ */
+#define	PKT_ALIAS_SKIP_GLOBAL		0x200
+
 /* Function return codes. */
 #define	PKT_ALIAS_ERROR			-1
 #define	PKT_ALIAS_OK			1


More information about the svn-src-all mailing list