summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--iptables-save.c2
-rw-r--r--iptables.8.in10
-rw-r--r--iptables.c24
3 files changed, 33 insertions, 3 deletions
diff --git a/iptables-save.c b/iptables-save.c
index 6c7267e2..4f6f156d 100644
--- a/iptables-save.c
+++ b/iptables-save.c
@@ -197,7 +197,7 @@ static void print_rule(const struct ipt_entry *e,
/* Print target name */
target_name = iptc_get_target(e, h);
if (target_name && (*target_name != '\0'))
- printf("-j %s ", target_name);
+ printf("-%c %s ", e->ip.flags & IPT_F_GOTO ? 'g' : 'j', target_name);
/* Print targinfo part */
t = ipt_get_target((struct ipt_entry *)e);
diff --git a/iptables.8.in b/iptables.8.in
index 118c50ca..0288c173 100644
--- a/iptables.8.in
+++ b/iptables.8.in
@@ -296,10 +296,18 @@ one this rule is in), one of the special builtin targets which decide
the fate of the packet immediately, or an extension (see
.B EXTENSIONS
below). If this
-option is omitted in a rule, then matching the rule will have no
+option is omitted in a rule (and
+.B -g
+is not used), then matching the rule will have no
effect on the packet's fate, but the counters on the rule will be
incremented.
.TP
+.BI "-g, --goto " "chain"
+This specifies that the processing should continue in a user
+specified chain. Unlike the --jump option return will not continue
+processing in this chain but instead in the chain that called us via
+--jump.
+.TP
.BR "-i, --in-interface " "[!] \fIname\fP"
Name of an interface via which a packet was received (only for
packets entering the
diff --git a/iptables.c b/iptables.c
index aec96137..cc47e980 100644
--- a/iptables.c
+++ b/iptables.c
@@ -135,6 +135,7 @@ static struct option original_opts[] = {
{ "line-numbers", 0, 0, '0' },
{ "modprobe", 1, 0, 'M' },
{ "set-counters", 1, 0, 'c' },
+ { "goto", 1, 0, 'g' },
{ 0 }
};
@@ -402,6 +403,10 @@ exit_printhelp(struct iptables_rule_match *matches)
" network interface name ([+] for wildcard)\n"
" --jump -j target\n"
" target for rule (may load target extension)\n"
+#ifdef IPT_F_GOTO
+" --goto -g chain\n"
+" jump to chain with no return\n"
+#endif
" --match -m match\n"
" extended match (may load extension)\n"
" --numeric -n numeric output of addresses and ports\n"
@@ -1410,6 +1415,9 @@ print_firewall(const struct ipt_entry *fw,
if (format & FMT_NOTABLE)
fputs(" ", stdout);
+ if(fw->ip.flags & IPT_F_GOTO)
+ printf("[goto] ");
+
IPT_MATCH_ITERATE(fw, print_match, &fw->ip, format & FMT_NUMERIC);
if (target) {
@@ -1867,7 +1875,7 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle)
opterr = 0;
while ((c = getopt_long(argc, argv,
- "-A:D:R:I:L::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:fbvnt:m:xc:",
+ "-A:D:R:I:L::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:fbvnt:m:xc:g:",
opts, NULL)) != -1) {
switch (c) {
/*
@@ -2035,6 +2043,15 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle)
dhostnetworkmask = argv[optind-1];
break;
+#ifdef IPT_F_GOTO
+ case 'g':
+ set_option(&options, OPT_JUMP, &fw.ip.invflags,
+ invert);
+ fw.ip.flags |= IPT_F_GOTO;
+ jumpto = parse_target(optarg);
+ break;
+#endif
+
case 'j':
set_option(&options, OPT_JUMP, &fw.ip.invflags,
invert);
@@ -2387,6 +2404,11 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle)
* We cannot know if the plugin is corrupt, non
* existant OR if the user just misspelled a
* chain. */
+#ifdef IPT_F_GOTO
+ if (fw.ip.flags & IPT_F_GOTO)
+ exit_error(PARAMETER_PROBLEM,
+ "goto '%s' is not a chain\n", jumpto);
+#endif
find_target(jumpto, LOAD_MUST_SUCCEED);
} else {
e = generate_entry(&fw, matches, target->t);