summaryrefslogtreecommitdiffstats
path: root/sbin
diff options
context:
space:
mode:
authorae <ae@FreeBSD.org>2011-06-29 10:06:58 +0000
committerae <ae@FreeBSD.org>2011-06-29 10:06:58 +0000
commit6b5f802b89475290bd6d581f19f00d0326038be1 (patch)
tree39ec2dc897c198c72a20dac2c11a69066b5cb64f /sbin
parent93c32fd0711f841f49c0349d8c693ccc83913e1d (diff)
downloadFreeBSD-src-6b5f802b89475290bd6d581f19f00d0326038be1.zip
FreeBSD-src-6b5f802b89475290bd6d581f19f00d0326038be1.tar.gz
Add new rule actions "call" and "return" to ipfw. They make
possible to organize subroutines with rules. The "call" action saves the current rule number in the internal stack and rules processing continues from the first rule with specified number (similar to skipto action). If later a rule with "return" action is encountered, the processing returns to the first rule with number of "call" rule saved in the stack plus one or higher. Submitted by: Vadim Goncharov Discussed by: ipfw@, luigi@
Diffstat (limited to 'sbin')
-rw-r--r--sbin/ipfw/ipfw.889
-rw-r--r--sbin/ipfw/ipfw2.c16
-rw-r--r--sbin/ipfw/ipfw2.h2
3 files changed, 106 insertions, 1 deletions
diff --git a/sbin/ipfw/ipfw.8 b/sbin/ipfw/ipfw.8
index 4a22320..6fc12c8 100644
--- a/sbin/ipfw/ipfw.8
+++ b/sbin/ipfw/ipfw.8
@@ -1,7 +1,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd June 14, 2011
+.Dd June 29, 2011
.Dt IPFW 8
.Os
.Sh NAME
@@ -822,6 +822,78 @@ skipto, but care should be used, as no destination caching
is possible in this case so the rules are always walked to find it,
starting from the
.Cm skipto .
+.It Cm call Ar number | tablearg
+The current rule number is saved in the internal stack and
+ruleset processing continues with the first rule numbered
+.Ar number
+or higher.
+If later a rule with the
+.Cm return
+action is encountered, the processing returns to the first rule
+with number of this
+.Cm call
+rule plus one or higher
+(the same behaviour as with packets returning from
+.Xr divert 4
+socket after a
+.Cm divert
+action).
+This could be used to make somewhat like an assembly language
+.Dq subroutine
+calls to rules with common checks for different interfaces, etc.
+.Pp
+Rule with any number could be called, not just forward jumps as with
+.Cm skipto .
+So, to prevent endless loops in case of mistakes, both
+.Cm call
+and
+.Cm return
+actions don't do any jumps and simply go to the next rule if memory
+can't be allocated or stack overflowed/undeflowed.
+.Pp
+Internally stack for rule numbers is implemented using
+.Xr mbuf_tags 9
+facility and currently has size of 16 entries.
+As mbuf tags are lost when packet leaves the kernel,
+.Cm divert
+should not be used in subroutines to avoid endless loops
+and other undesired effects.
+.It Cm return
+Takes rule number saved to internal stack by the last
+.Cm call
+action and returns ruleset processing to the first rule
+with number greater than number of corresponding
+.Cm call
+rule. See description of the
+.Cm call
+action for more details.
+.Pp
+Note that
+.Cm return
+rules usually end a
+.Dq subroutine
+and thus are unconditional, but
+.Nm
+command-line utility currently requires every action except
+.Cm check-state
+to have body.
+While it is sometimes useful to return only on some packets,
+usually you want to print just
+.Dq return
+for readability.
+A workaround for this is to use new syntax and
+.Fl c
+switch:
+.Pp
+.Bd -literal -offset indent
+# Add a rule without actual body
+ipfw add 2999 return via any
+
+# List rules without "from any to any" part
+ipfw -c list
+.Ed
+.Pp
+This cosmetic annoyance may be fixed in future releases.
.It Cm tee Ar port
Send a copy of packets matching this rule to the
.Xr divert 4
@@ -3253,3 +3325,18 @@ for the respective conversations.
To avoid failures of network error detection and path MTU discovery,
ICMP error messages may need to be allowed explicitly through static
rules.
+.Pp
+Rules using
+.Cm call
+and
+.Cm return
+actions may lead to confusing behaviour if ruleset has mistakes,
+and/or interaction with other subsystems (netgraph, dummynet, etc.) is used.
+One possible case for this is packet leaving
+.Nm
+in subroutine on the input pass, while later on output encountering unpaired
+.Cm return
+first.
+As the call stack is kept intact after input pass, packet will suddenly
+return to the rule number used on input pass, not on output one.
+Order of processing should be checked carefully to avoid such mistakes.
diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c
index 64e5eb1..e259f5e 100644
--- a/sbin/ipfw/ipfw2.c
+++ b/sbin/ipfw/ipfw2.c
@@ -214,6 +214,8 @@ static struct _s_x rule_actions[] = {
{ "nat", TOK_NAT },
{ "reass", TOK_REASS },
{ "setfib", TOK_SETFIB },
+ { "call", TOK_CALL },
+ { "return", TOK_RETURN },
{ NULL, 0 } /* terminator */
};
@@ -1136,6 +1138,13 @@ show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth)
printf("reass");
break;
+ case O_CALLRETURN:
+ if (cmd->len & F_NOT)
+ printf("return");
+ else
+ PRINT_UINT_ARG("call ", cmd->arg1);
+ break;
+
default:
printf("** unrecognized action %d len %d ",
cmd->opcode, cmd->len);
@@ -2771,6 +2780,9 @@ ipfw_add(char *av[])
goto chkarg;
case TOK_TEE:
action->opcode = O_TEE;
+ goto chkarg;
+ case TOK_CALL:
+ action->opcode = O_CALLRETURN;
chkarg:
if (!av[0])
errx(EX_USAGE, "missing argument for %s", *(av - 1));
@@ -2863,6 +2875,10 @@ chkarg:
action->opcode = O_REASS;
break;
+ case TOK_RETURN:
+ fill_cmd(action, O_CALLRETURN, F_NOT, 0);
+ break;
+
default:
errx(EX_DATAERR, "invalid action %s\n", av[-1]);
}
diff --git a/sbin/ipfw/ipfw2.h b/sbin/ipfw/ipfw2.h
index 9562f32..bade0dd 100644
--- a/sbin/ipfw/ipfw2.h
+++ b/sbin/ipfw/ipfw2.h
@@ -99,6 +99,8 @@ enum tokens {
TOK_CHECKSTATE,
TOK_NAT,
TOK_REASS,
+ TOK_CALL,
+ TOK_RETURN,
TOK_ALTQ,
TOK_LOG,
OpenPOWER on IntegriCloud