From nobody@FreeBSD.org  Tue Jun 14 05:50:27 2011
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 068B3106566C
	for <freebsd-gnats-submit@FreeBSD.org>; Tue, 14 Jun 2011 05:50:27 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from red.freebsd.org (red.freebsd.org [IPv6:2001:4f8:fff6::22])
	by mx1.freebsd.org (Postfix) with ESMTP id EA27E8FC15
	for <freebsd-gnats-submit@FreeBSD.org>; Tue, 14 Jun 2011 05:50:26 +0000 (UTC)
Received: from red.freebsd.org (localhost [127.0.0.1])
	by red.freebsd.org (8.14.4/8.14.4) with ESMTP id p5E5oQkx019660
	for <freebsd-gnats-submit@FreeBSD.org>; Tue, 14 Jun 2011 05:50:26 GMT
	(envelope-from nobody@red.freebsd.org)
Received: (from nobody@localhost)
	by red.freebsd.org (8.14.4/8.14.4/Submit) id p5E5oQ5j019659;
	Tue, 14 Jun 2011 05:50:26 GMT
	(envelope-from nobody)
Message-Id: <201106140550.p5E5oQ5j019659@red.freebsd.org>
Date: Tue, 14 Jun 2011 05:50:26 GMT
From: "Alexander V. Chernikov" <melifaro@ipfw.ru>
To: freebsd-gnats-submit@FreeBSD.org
Subject: [patch][ipfw] natd globalport support for ipfw nat
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         157867
>Category:       kern
>Synopsis:       [patch][ipfw] natd globalport support for ipfw nat
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-ipfw
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Tue Jun 14 06:00:19 UTC 2011
>Closed-Date:    Thu Jul 28 10:17:27 UTC 2011
>Last-Modified:  Thu Jul 28 10:20:08 UTC 2011
>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     root@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:
Responsible-Changed-From-To: freebsd-bugs->freebsd-ipfw 
Responsible-Changed-By: ae 
Responsible-Changed-When: Tue Jun 14 06:36:57 UTC 2011 
Responsible-Changed-Why:  
Over to maintainer(s). 


http://www.freebsd.org/cgi/query-pr.cgi?pr=157867 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/157867: commit references a PR
Date: Tue, 14 Jun 2011 13:35:34 +0000 (UTC)

 Author: ae
 Date: Tue Jun 14 13:35:24 2011
 New Revision: 223080
 URL: http://svn.freebsd.org/changeset/base/223080
 
 Log:
   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)
   Tested by:	Eugene Grosbein
 
 Modified:
   head/sbin/ipfw/ipfw.8
   head/sbin/ipfw/ipfw2.c
   head/sbin/ipfw/ipfw2.h
   head/sbin/ipfw/nat.c
   head/sys/netinet/ipfw/ip_fw2.c
   head/sys/netinet/ipfw/ip_fw_nat.c
   head/sys/netinet/libalias/alias.h
 
 Modified: head/sbin/ipfw/ipfw.8
 ==============================================================================
 --- head/sbin/ipfw/ipfw.8	Tue Jun 14 13:02:26 2011	(r223079)
 +++ head/sbin/ipfw/ipfw.8	Tue Jun 14 13:35:24 2011	(r223080)
 @@ -1,7 +1,7 @@
  .\"
  .\" $FreeBSD$
  .\"
 -.Dd May 30, 2011
 +.Dd June 14, 2011
  .Dt IPFW 8
  .Os
  .Sh NAME
 @@ -2435,6 +2435,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: head/sbin/ipfw/ipfw2.c
 ==============================================================================
 --- head/sbin/ipfw/ipfw2.c	Tue Jun 14 13:02:26 2011	(r223079)
 +++ head/sbin/ipfw/ipfw2.c	Tue Jun 14 13:35:24 2011	(r223080)
 @@ -1121,8 +1121,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);
 @@ -2738,9 +2741,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: head/sbin/ipfw/ipfw2.h
 ==============================================================================
 --- head/sbin/ipfw/ipfw2.h	Tue Jun 14 13:02:26 2011	(r223079)
 +++ head/sbin/ipfw/ipfw2.h	Tue Jun 14 13:35:24 2011	(r223080)
 @@ -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: head/sbin/ipfw/nat.c
 ==============================================================================
 --- head/sbin/ipfw/nat.c	Tue Jun 14 13:02:26 2011	(r223079)
 +++ head/sbin/ipfw/nat.c	Tue Jun 14 13:35:24 2011	(r223080)
 @@ -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 },
 @@ -628,6 +629,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;
 @@ -746,10 +750,11 @@ ipfw_config_nat(int ac, char **av)
  		case TOK_IP:
  		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:
 @@ -821,6 +826,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: head/sys/netinet/ipfw/ip_fw2.c
 ==============================================================================
 --- head/sys/netinet/ipfw/ip_fw2.c	Tue Jun 14 13:02:26 2011	(r223079)
 +++ head/sys/netinet/ipfw/ip_fw2.c	Tue Jun 14 13:35:24 2011	(r223080)
 @@ -2194,6 +2194,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: head/sys/netinet/ipfw/ip_fw_nat.c
 ==============================================================================
 --- head/sys/netinet/ipfw/ip_fw_nat.c	Tue Jun 14 13:02:26 2011	(r223079)
 +++ head/sys/netinet/ipfw/ip_fw_nat.c	Tue Jun 14 13:35:24 2011	(r223080)
 @@ -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: head/sys/netinet/libalias/alias.h
 ==============================================================================
 --- head/sys/netinet/libalias/alias.h	Tue Jun 14 13:02:26 2011	(r223079)
 +++ head/sys/netinet/libalias/alias.h	Tue Jun 14 13:35:24 2011	(r223080)
 @@ -220,6 +220,12 @@ struct mbuf    *m_megapullup(struct mbuf
  #define	PKT_ALIAS_PUNCH_FW		0x100
  #endif
  
 +/*
 + * 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
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: open->patched 
State-Changed-By: ae 
State-Changed-When: Tue Jun 14 14:55:08 UTC 2011 
State-Changed-Why:  
Patched in head/. Thanks! 

http://www.freebsd.org/cgi/query-pr.cgi?pr=157867 
State-Changed-From-To: patched->closed 
State-Changed-By: ae 
State-Changed-When: Thu Jul 28 10:17:04 UTC 2011 
State-Changed-Why:  
Merged to stable/8. Thanks! 

http://www.freebsd.org/cgi/query-pr.cgi?pr=157867 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/157867: commit references a PR
Date: Thu, 28 Jul 2011 10:10:49 +0000 (UTC)

 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
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
>Unformatted:
