Commit 290749d4 authored by Arturo Borrero Gonzalez's avatar Arturo Borrero Gonzalez
Browse files

New upstream version 1.8.4

parent 89c92f0c
#!/bin/bash
# Make sure iptables-restore without --noflush does not flush tables other than
# those contained in the dump it's reading from
set -e
$XT_MULTI iptables-restore <<EOF
*nat
-A POSTROUTING -j ACCEPT
COMMIT
EOF
EXPECT="*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -j ACCEPT
COMMIT"
diff -u -Z <(echo -e "$EXPECT" | sort) <($XT_MULTI iptables-save | grep -v '^#' | sort)
$XT_MULTI iptables-restore <<EOF
*filter
-A FORWARD -j ACCEPT
COMMIT
EOF
EXPECT="*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A FORWARD -j ACCEPT
COMMIT
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -j ACCEPT
COMMIT"
diff -u -Z <(echo -e "$EXPECT" | sort) <($XT_MULTI iptables-save | grep -v '^#' | sort)
#!/bin/bash
set -e
DUMP="*filter
:foo - [23:42]
[13:37] -A foo -j ACCEPT
COMMIT
"
EXPECT=":foo - [0:0]
[0:0] -A foo -j ACCEPT"
$XT_MULTI iptables-restore <<< "$DUMP"
diff -u -Z <(echo -e "$EXPECT") <($XT_MULTI iptables-save --counters | grep foo)
# iptables-*-restore ignores custom chain counters :(
EXPECT=":foo - [0:0]
[13:37] -A foo -j ACCEPT"
$XT_MULTI iptables-restore --counters <<< "$DUMP"
diff -u -Z <(echo -e "$EXPECT") <($XT_MULTI iptables-save --counters | grep foo)
#!/bin/bash
# when restoring a ruleset, *tables-restore prefixes each rule with
# '-t <tablename>' so standard rule parsing routines may be used. This means
# that it has to detect and reject rules which already contain a table option.
families="ip ip6"
[[ $(basename $XT_MULTI) == xtables-nft-multi ]] && families+=" eb"
for fam in $families; do
$XT_MULTI ${fam}tables-restore <<EOF
*filter
-t nat -A FORWARD -j ACCEPT
COMMIT
EOF
[[ $? != 0 ]] || {
echo "${fam}tables-restore did not fail when it should have"
exit 1
}
$XT_MULTI ${fam}tables-restore <<EOF
*filter
-A FORWARD -j ACCEPT
COMMIT
EOF
[[ $? == 0 ]] || {
echo "${fam}tables-restore failed when it should not have"
exit 1
}
done
#!/bin/bash
case "$(basename $XT_MULTI)" in
xtables-legacy-multi)
;;
*)
echo "skip $XT_MULTI"
exit 0
;;
esac
dump=$(dirname $0)/dumps/fedora27-iptables
diff -u -Z <(cat ${dump}.xml) <($XT_MULTI iptables-xml <$dump)
<iptables-rules version="1.0">
<!-- # Completed on Sat Feb 17 10:50:33 2018 -->
<!-- # Generated by iptables*-save v1.6.1 on Sat Feb 17 10:50:33 2018 -->
<table name="mangle" >
<chain name="PREROUTING" policy="ACCEPT" packet-count="0" byte-count="0" >
<rule packet-count="1" byte-count="2" >
<actions>
<call >
<PREROUTING_direct />
</call>
</actions>
</rule>
<rule packet-count="3" byte-count="4" >
<actions>
<call >
<PREROUTING_ZONES_SOURCE />
</call>
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<actions>
<call >
<PREROUTING_ZONES />
</call>
</actions>
</rule>
</chain>
<chain name="INPUT" policy="ACCEPT" packet-count="0" byte-count="0" >
<rule packet-count="0" byte-count="0" >
<actions>
<call >
<INPUT_direct />
</call>
</actions>
</rule>
</chain>
<chain name="FORWARD" policy="ACCEPT" packet-count="0" byte-count="0" >
<rule packet-count="0" byte-count="0" >
<actions>
<call >
<FORWARD_direct />
</call>
</actions>
</rule>
</chain>
<chain name="OUTPUT" policy="ACCEPT" packet-count="0" byte-count="0" >
<rule packet-count="0" byte-count="0" >
<actions>
<call >
<OUTPUT_direct />
</call>
</actions>
</rule>
</chain>
<chain name="POSTROUTING" policy="ACCEPT" packet-count="0" byte-count="0" >
<rule packet-count="0" byte-count="0" >
<conditions>
<match >
<o >virbr0</o>
<p >udp</p>
</match>
<udp >
<dport >68</dport>
</udp>
</conditions>
<actions>
<CHECKSUM >
<checksum-fill />
</CHECKSUM>
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<actions>
<call >
<POSTROUTING_direct />
</call>
</actions>
</rule>
</chain>
<chain name="PREROUTING_ZONES" packet-count="0" byte-count="0" >
<rule packet-count="0" byte-count="0" >
<conditions>
<match >
<i >wlp58s0</i>
</match>
</conditions>
<actions>
<goto >
<PRE_FedoraWorkstation />
</goto>
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<actions>
<goto >
<PRE_FedoraWorkstation />
</goto>
</actions>
</rule>
</chain>
<chain name="PRE_FedoraWorkstation" packet-count="0" byte-count="0" >
<rule packet-count="0" byte-count="0" >
<actions>
<call >
<PRE_FedoraWorkstation_log />
</call>
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<actions>
<call >
<PRE_FedoraWorkstation_deny />
</call>
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<actions>
<call >
<PRE_FedoraWorkstation_allow />
</call>
</actions>
</rule>
</chain>
<chain name="FORWARD_direct" packet-count="0" byte-count="0" />
<chain name="INPUT_direct" packet-count="0" byte-count="0" />
<chain name="OUTPUT_direct" packet-count="0" byte-count="0" />
<chain name="POSTROUTING_direct" packet-count="0" byte-count="0" />
<chain name="PREROUTING_ZONES_SOURCE" packet-count="0" byte-count="0" />
<chain name="PREROUTING_direct" packet-count="0" byte-count="0" />
<chain name="PRE_FedoraWorkstation_allow" packet-count="0" byte-count="0" />
<chain name="PRE_FedoraWorkstation_deny" packet-count="0" byte-count="0" />
<chain name="PRE_FedoraWorkstation_log" packet-count="0" byte-count="0" />
</table>
<!-- # Completed on Sat Feb 17 10:50:33 2018 -->
<!-- # Generated by iptables*-save v1.6.1 on Sat Feb 17 10:50:33 2018 -->
<table name="raw" >
<chain name="PREROUTING" policy="ACCEPT" packet-count="1681" byte-count="2620433" >
<rule packet-count="0" byte-count="0" >
<actions>
<call >
<PREROUTING_direct />
</call>
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<actions>
<call >
<PREROUTING_ZONES_SOURCE />
</call>
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<actions>
<call >
<PREROUTING_ZONES />
</call>
</actions>
</rule>
</chain>
<chain name="OUTPUT" policy="ACCEPT" packet-count="1619" byte-count="171281" >
<rule packet-count="0" byte-count="0" >
<actions>
<call >
<OUTPUT_direct />
</call>
</actions>
</rule>
</chain>
<chain name="PREROUTING_ZONES" packet-count="0" byte-count="0" >
<rule packet-count="0" byte-count="0" >
<conditions>
<match >
<i >wlp58s0</i>
</match>
</conditions>
<actions>
<goto >
<PRE_FedoraWorkstation />
</goto>
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<actions>
<goto >
<PRE_FedoraWorkstation />
</goto>
</actions>
</rule>
</chain>
<chain name="PRE_FedoraWorkstation" packet-count="0" byte-count="0" >
<rule packet-count="0" byte-count="0" >
<actions>
<call >
<PRE_FedoraWorkstation_log />
</call>
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<actions>
<call >
<PRE_FedoraWorkstation_deny />
</call>
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<actions>
<call >
<PRE_FedoraWorkstation_allow />
</call>
</actions>
</rule>
</chain>
<chain name="PRE_FedoraWorkstation_allow" packet-count="0" byte-count="0" >
<rule packet-count="0" byte-count="0" >
<conditions>
<match >
<p >udp</p>
</match>
<udp >
<dport >137</dport>
</udp>
</conditions>
<actions>
<CT >
<helper >netbios-ns</helper>
</CT>
</actions>
</rule>
</chain>
<chain name="OUTPUT_direct" packet-count="0" byte-count="0" />
<chain name="PREROUTING_ZONES_SOURCE" packet-count="0" byte-count="0" />
<chain name="PREROUTING_direct" packet-count="0" byte-count="0" />
<chain name="PRE_FedoraWorkstation_deny" packet-count="0" byte-count="0" />
<chain name="PRE_FedoraWorkstation_log" packet-count="0" byte-count="0" />
</table>
<!-- # Completed on Sat Feb 17 10:50:33 2018 -->
<!-- # Generated by iptables*-save v1.6.1 on Sat Feb 17 10:50:33 2018 -->
<table name="filter" >
<chain name="INPUT" policy="ACCEPT" packet-count="0" byte-count="0" >
<rule packet-count="5" byte-count="6" >
<conditions>
<match >
<i >virbr0</i>
<p >udp</p>
</match>
<udp >
<dport >53</dport>
</udp>
</conditions>
<actions>
<ACCEPT />
</actions>
</rule>
<rule packet-count="0" byte-count="123456789" >
<conditions>
<match >
<i >virbr0</i>
<p >tcp</p>
</match>
<tcp >
<dport >53</dport>
</tcp>
</conditions>
<actions>
<ACCEPT />
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<conditions>
<match >
<i >virbr0</i>
<p >udp</p>
</match>
<udp >
<dport >67</dport>
</udp>
</conditions>
<actions>
<ACCEPT />
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<conditions>
<match >
<i >virbr0</i>
<p >tcp</p>
</match>
<tcp >
<dport >67</dport>
</tcp>
</conditions>
<actions>
<ACCEPT />
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<conditions>
<conntrack >
<ctstate >RELATED,ESTABLISHED</ctstate>
</conntrack>
</conditions>
<actions>
<ACCEPT />
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<conditions>
<match >
<i >lo</i>
</match>
</conditions>
<actions>
<ACCEPT />
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<actions>
<call >
<INPUT_direct />
</call>
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<actions>
<call >
<INPUT_ZONES_SOURCE />
</call>
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<actions>
<call >
<INPUT_ZONES />
</call>
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<conditions>
<conntrack >
<ctstate >INVALID</ctstate>
</conntrack>
</conditions>
<actions>
<DROP />
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<actions>
<REJECT >
<reject-with >icmp-host-prohibited</reject-with>
</REJECT>
</actions>
</rule>
</chain>
<chain name="FORWARD" policy="ACCEPT" packet-count="0" byte-count="0" >
<rule packet-count="0" byte-count="0" >
<conditions>
<match >
<d >192.168.122.0/24</d>
<o >virbr0</o>
</match>
<conntrack >
<ctstate >RELATED,ESTABLISHED</ctstate>
</conntrack>
</conditions>
<actions>
<ACCEPT />
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<conditions>
<match >
<s >192.168.122.0/24</s>
<i >virbr0</i>
</match>
</conditions>
<actions>
<ACCEPT />
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<conditions>
<match >
<i >virbr0</i>
<o >virbr0</o>
</match>
</conditions>
<actions>
<ACCEPT />
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<conditions>
<match >
<o >virbr0</o>
</match>
</conditions>
<actions>
<REJECT >
<reject-with >icmp-port-unreachable</reject-with>
</REJECT>
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<conditions>
<match >
<i >virbr0</i>
</match>
</conditions>
<actions>
<REJECT >
<reject-with >icmp-port-unreachable</reject-with>
</REJECT>
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<conditions>
<conntrack >
<ctstate >RELATED,ESTABLISHED</ctstate>
</conntrack>
</conditions>
<actions>
<ACCEPT />
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<conditions>
<match >
<i >lo</i>
</match>
</conditions>
<actions>
<ACCEPT />
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<actions>
<call >
<FORWARD_direct />
</call>
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<actions>
<call >
<FORWARD_IN_ZONES_SOURCE />
</call>
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<actions>
<call >
<FORWARD_IN_ZONES />
</call>
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<actions>
<call >
<FORWARD_OUT_ZONES_SOURCE />
</call>
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<actions>
<call >
<FORWARD_OUT_ZONES />
</call>
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<conditions>
<conntrack >
<ctstate >INVALID</ctstate>
</conntrack>
</conditions>
<actions>
<DROP />
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<actions>
<REJECT >
<reject-with >icmp-host-prohibited</reject-with>
</REJECT>
</actions>
</rule>
</chain>
<chain name="OUTPUT" policy="ACCEPT" packet-count="1619" byte-count="171281" >
<rule packet-count="0" byte-count="0" >
<conditions>
<match >
<o >virbr0</o>
<p >udp</p>
</match>
<udp >
<dport >68</dport>
</udp>
</conditions>
<actions>
<ACCEPT />
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<actions>
<call >
<OUTPUT_direct />
</call>
</actions>
</rule>
</chain>
<chain name="FORWARD_IN_ZONES" packet-count="0" byte-count="0" >
<rule packet-count="0" byte-count="0" >
<conditions>
<match >
<i >wlp58s0</i>
</match>
</conditions>
<actions>
<goto >
<FWDI_FedoraWorkstation />
</goto>
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<actions>
<goto >
<FWDI_FedoraWorkstation />
</goto>
</actions>
</rule>
</chain>
<chain name="FORWARD_OUT_ZONES" packet-count="0" byte-count="0" >
<rule packet-count="0" byte-count="0" >
<conditions>
<match >
<o >wlp58s0</o>
</match>
</conditions>
<actions>
<goto >
<FWDO_FedoraWorkstation />
</goto>
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<actions>
<goto >
<FWDO_FedoraWorkstation />
</goto>
</actions>
</rule>
</chain>
<chain name="FWDI_FedoraWorkstation" packet-count="0" byte-count="0" >
<rule packet-count="0" byte-count="0" >
<actions>
<call >
<FWDI_FedoraWorkstation_log />
</call>
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<actions>
<call >
<FWDI_FedoraWorkstation_deny />
</call>
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<actions>
<call >
<FWDI_FedoraWorkstation_allow />
</call>
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<conditions>
<match >
<p >icmp</p>
</match>
</conditions>
<actions>
<ACCEPT />
</actions>
</rule>
</chain>
<chain name="FWDO_FedoraWorkstation" packet-count="0" byte-count="0" >
<rule packet-count="0" byte-count="0" >
<actions>
<call >
<FWDO_FedoraWorkstation_log />
</call>
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<actions>
<call >
<FWDO_FedoraWorkstation_deny />
</call>
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<actions>
<call >
<FWDO_FedoraWorkstation_allow />
</call>
</actions>
</rule>
</chain>
<chain name="INPUT_ZONES" packet-count="0" byte-count="0" >
<rule packet-count="0" byte-count="0" >
<conditions>
<match >
<i >wlp58s0</i>
</match>
</conditions>
<actions>
<goto >
<IN_FedoraWorkstation />
</goto>
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<actions>
<goto >
<IN_FedoraWorkstation />
</goto>
</actions>
</rule>
</chain>
<chain name="IN_FedoraWorkstation" packet-count="0" byte-count="0" >
<rule packet-count="0" byte-count="0" >
<actions>
<call >
<IN_FedoraWorkstation_log />
</call>
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<actions>
<call >
<IN_FedoraWorkstation_deny />
</call>
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<actions>
<call >
<IN_FedoraWorkstation_allow />
</call>
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<conditions>
<match >
<p >icmp</p>
</match>
</conditions>
<actions>
<ACCEPT />
</actions>
</rule>
</chain>
<chain name="IN_FedoraWorkstation_allow" packet-count="0" byte-count="0" >
<rule packet-count="0" byte-count="0" >
<conditions>
<match >
<p >udp</p>
</match>
<udp >
<dport >137</dport>
</udp>
<conntrack >
<ctstate >NEW</ctstate>
</conntrack>
</conditions>
<actions>
<ACCEPT />
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<conditions>
<match >
<p >udp</p>
</match>
<udp >
<dport >138</dport>
</udp>
<conntrack >
<ctstate >NEW</ctstate>
</conntrack>
</conditions>
<actions>
<ACCEPT />
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<conditions>
<match >
<p >tcp</p>
</match>
<tcp >
<dport >22</dport>
</tcp>
<conntrack >
<ctstate >NEW</ctstate>
</conntrack>
</conditions>
<actions>
<ACCEPT />
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<conditions>
<match >
<d >224.0.0.251/32</d>
<p >udp</p>
</match>
<udp >
<dport >5353</dport>
</udp>
<conntrack >
<ctstate >NEW</ctstate>
</conntrack>
</conditions>
<actions>
<ACCEPT />
</actions>
</rule>
<rule packet-count="0" byte-count="0" >
<conditions>
<match >
<p >udp</p>
</match>
<udp >
<dport >1025:65535</dport>
</udp>
<conntrack >
<ctstate >NEW</ctstate>
</conntrack>
</conditions>
<actions>
<ACCEPT />
</actions>
</rule>
<rule packet-count="7" byte-count="8" >
<conditions>
<match >
<p >tcp</p>
</match>
<tcp >
<dport >1025:65535</dport>
</tcp>
<conntrack >
<ctstate >NEW</ctstate>
</conntrack>
</conditions>
<actions>
<ACCEPT />
</actions>
</rule>
</chain>
<chain name="FORWARD_IN_ZONES_SOURCE" packet-count="0" byte-count="0" />
<chain name="FORWARD_OUT_ZONES_SOURCE" packet-count="0" byte-count="0" />
<chain name="FORWARD_direct" packet-count="0" byte-count="0" />
<chain name="FWDI_FedoraWorkstation_allow" packet-count="0" byte-count="0" />
<chain name="FWDI_FedoraWorkstation_deny" packet-count="0" byte-count="0" />
<chain name="FWDI_FedoraWorkstation_log" packet-count="0" byte-count="0" />
<chain name="FWDO_FedoraWorkstation_allow" packet-count="0" byte-count="0" />
<chain name="FWDO_FedoraWorkstation_deny" packet-count="0" byte-count="0" />
<chain name="FWDO_FedoraWorkstation_log" packet-count="0" byte-count="0" />
<chain name="INPUT_ZONES_SOURCE" packet-count="0" byte-count="0" />
<chain name="INPUT_direct" packet-count="0" byte-count="0" />
<chain name="IN_FedoraWorkstation_deny" packet-count="0" byte-count="0" />
<chain name="IN_FedoraWorkstation_log" packet-count="0" byte-count="0" />
<chain name="OUTPUT_direct" packet-count="0" byte-count="0" />
</table>
<!-- # Completed on Sat Feb 17 10:50:33 2018 -->
</iptables-rules>
......@@ -181,7 +181,6 @@ int command_default(struct iptables_command_state *cs,
xtables_error(PARAMETER_PROBLEM, "unknown option "
"\"%s\"", cs->argv[optind-1]);
xtables_error(PARAMETER_PROBLEM, "Unknown arg \"%s\"", optarg);
return 0;
}
static mainfunc_t subcmd_get(const char *cmd, const struct subcommand *cb)
......@@ -374,6 +373,43 @@ int parse_counters(const char *string, struct xt_counters *ctr)
return ret == 2;
}
/* Tokenize counters argument of typical iptables-restore format rule.
*
* If *bufferp contains counters, update *pcntp and *bcntp to point at them,
* change bytes after counters in *bufferp to nul-bytes, update *bufferp to
* point to after the counters and return true.
* If *bufferp does not contain counters, return false.
* If syntax is wrong in *bufferp, call xtables_error() and hence exit().
* */
bool tokenize_rule_counters(char **bufferp, char **pcntp, char **bcntp, int line)
{
char *ptr, *buffer = *bufferp, *pcnt, *bcnt;
if (buffer[0] != '[')
return false;
/* we have counters in our input */
ptr = strchr(buffer, ']');
if (!ptr)
xtables_error(PARAMETER_PROBLEM, "Bad line %u: need ]\n", line);
pcnt = strtok(buffer+1, ":");
if (!pcnt)
xtables_error(PARAMETER_PROBLEM, "Bad line %u: need :\n", line);
bcnt = strtok(NULL, "]");
if (!bcnt)
xtables_error(PARAMETER_PROBLEM, "Bad line %u: need ]\n", line);
*pcntp = pcnt;
*bcntp = bcnt;
/* start command parsing after counter */
*bufferp = ptr + 1;
return true;
}
inline bool xs_has_arg(int argc, char *argv[])
{
return optind < argc &&
......@@ -381,56 +417,48 @@ inline bool xs_has_arg(int argc, char *argv[])
argv[optind][0] != '!';
}
/* global new argv and argc */
char *newargv[255];
int newargc = 0;
/* saved newargv and newargc from save_argv() */
char *oldargv[255];
int oldargc = 0;
/* arg meta data, were they quoted, frinstance */
int newargvattr[255];
/* function adding one argument to newargv, updating newargc
* returns true if argument added, false otherwise */
int add_argv(const char *what, int quoted)
/* function adding one argument to store, updating argc
* returns if argument added, does not return otherwise */
void add_argv(struct argv_store *store, const char *what, int quoted)
{
DEBUGP("add_argv: %s\n", what);
if (what && newargc + 1 < ARRAY_SIZE(newargv)) {
newargv[newargc] = strdup(what);
newargvattr[newargc] = quoted;
newargv[++newargc] = NULL;
return 1;
} else {
if (store->argc + 1 >= MAX_ARGC)
xtables_error(PARAMETER_PROBLEM,
"Parser cannot handle more arguments\n");
}
if (!what)
xtables_error(PARAMETER_PROBLEM,
"Trying to store NULL argument\n");
store->argv[store->argc] = strdup(what);
store->argvattr[store->argc] = quoted;
store->argv[++store->argc] = NULL;
}
void free_argv(void)
void free_argv(struct argv_store *store)
{
while (newargc)
free(newargv[--newargc]);
while (oldargc)
free(oldargv[--oldargc]);
while (store->argc) {
store->argc--;
free(store->argv[store->argc]);
store->argvattr[store->argc] = 0;
}
}
/* Save parsed rule for comparison with next rule to perform action aggregation
* on duplicate conditions.
*/
void save_argv(void)
void save_argv(struct argv_store *dst, struct argv_store *src)
{
unsigned int i;
while (oldargc)
free(oldargv[--oldargc]);
int i;
oldargc = newargc;
newargc = 0;
for (i = 0; i < oldargc; i++) {
oldargv[i] = newargv[i];
free_argv(dst);
for (i = 0; i < src->argc; i++) {
dst->argvattr[i] = src->argvattr[i];
dst->argv[i] = src->argv[i];
src->argv[i] = NULL;
}
dst->argc = src->argc;
src->argc = 0;
}
struct xt_param_buf {
......@@ -446,9 +474,9 @@ static void add_param(struct xt_param_buf *param, const char *curchar)
"Parameter too long!");
}
void add_param_to_argv(char *parsestart, int line)
void add_param_to_argv(struct argv_store *store, char *parsestart, int line)
{
int quote_open = 0, escaped = 0;
int quote_open = 0, escaped = 0, quoted = 0;
struct xt_param_buf param = {};
char *curchar;
......@@ -475,6 +503,7 @@ void add_param_to_argv(char *parsestart, int line)
} else {
if (*curchar == '"') {
quote_open = 1;
quoted = 1;
continue;
}
}
......@@ -497,23 +526,26 @@ void add_param_to_argv(char *parsestart, int line)
}
param.buffer[param.len] = '\0';
/* check if table name specified */
if ((param.buffer[0] == '-' &&
param.buffer[1] != '-' &&
strchr(param.buffer, 't')) ||
(!strncmp(param.buffer, "--t", 3) &&
!strncmp(param.buffer, "--table", strlen(param.buffer)))) {
xtables_error(PARAMETER_PROBLEM,
"The -t option (seen in line %u) cannot be used in %s.\n",
line, xt_params->program_name);
}
add_argv(param.buffer, 0);
add_argv(store, param.buffer, quoted);
param.len = 0;
quoted = 0;
}
if (param.len) {
param.buffer[param.len] = '\0';
add_argv(store, param.buffer, 0);
}
}
#ifdef DEBUG
void debug_print_argv(struct argv_store *store)
{
int i;
for (i = 0; i < store->argc; i++)
fprintf(stderr, "argv[%d]: %s\n", i, store->argv[i]);
}
#endif
static const char *ipv4_addr_to_string(const struct in_addr *addr,
const struct in_addr *mask,
unsigned int format)
......@@ -704,3 +736,42 @@ void command_jump(struct iptables_command_state *cs, const char *jumpto)
xtables_error(OTHER_PROBLEM, "can't alloc memory!");
xt_params->opts = opts;
}
char cmd2char(int option)
{
/* cmdflags index corresponds with position of bit in CMD_* values */
static const char cmdflags[] = { 'I', 'D', 'D', 'R', 'A', 'L', 'F', 'Z',
'N', 'X', 'P', 'E', 'S', 'Z', 'C' };
int i;
for (i = 0; option > 1; option >>= 1, i++)
;
if (i >= ARRAY_SIZE(cmdflags))
xtables_error(OTHER_PROBLEM,
"cmd2char(): Invalid command number %u.\n",
1 << i);
return cmdflags[i];
}
void add_command(unsigned int *cmd, const int newcmd,
const int othercmds, int invert)
{
if (invert)
xtables_error(PARAMETER_PROBLEM, "unexpected '!' flag");
if (*cmd & (~othercmds))
xtables_error(PARAMETER_PROBLEM, "Cannot use -%c with -%c\n",
cmd2char(newcmd), cmd2char(*cmd & (~othercmds)));
*cmd |= newcmd;
}
/* Can't be zero. */
int parse_rulenumber(const char *rule)
{
unsigned int rulenum;
if (!xtables_strtoui(rule, NULL, &rulenum, 1, INT_MAX))
xtables_error(PARAMETER_PROBLEM,
"Invalid rule number `%s'", rule);
return rulenum;
}
......@@ -11,7 +11,7 @@
#include <linux/netfilter_ipv6/ip6_tables.h>
#ifdef DEBUG
#define DEBUGP(x, args...) fprintf(stdout, x, ## args)
#define DEBUGP(x, args...) fprintf(stderr, x, ## args)
#else
#define DEBUGP(x, args...)
#endif
......@@ -29,8 +29,35 @@ enum {
OPT_VIANAMEOUT = 1 << 8,
OPT_LINENUMBERS = 1 << 9,
OPT_COUNTERS = 1 << 10,
/* below are for arptables only */
OPT_S_MAC = 1 << 11,
OPT_D_MAC = 1 << 12,
OPT_H_LENGTH = 1 << 13,
OPT_OPCODE = 1 << 14,
OPT_H_TYPE = 1 << 15,
OPT_P_TYPE = 1 << 16,
};
enum {
CMD_NONE = 0,
CMD_INSERT = 1 << 0,
CMD_DELETE = 1 << 1,
CMD_DELETE_NUM = 1 << 2,
CMD_REPLACE = 1 << 3,
CMD_APPEND = 1 << 4,
CMD_LIST = 1 << 5,
CMD_FLUSH = 1 << 6,
CMD_ZERO = 1 << 7,
CMD_NEW_CHAIN = 1 << 8,
CMD_DELETE_CHAIN = 1 << 9,
CMD_SET_POLICY = 1 << 10,
CMD_RENAME_CHAIN = 1 << 11,
CMD_LIST_RULES = 1 << 12,
CMD_ZERO_NUM = 1 << 13,
CMD_CHECK = 1 << 14,
};
#define NUMBER_OF_CMD 16
struct xtables_globals;
struct xtables_rule_match;
struct xtables_target;
......@@ -151,22 +178,27 @@ extern int xtables_lock_or_exit(int wait, struct timeval *tv);
int parse_wait_time(int argc, char *argv[]);
void parse_wait_interval(int argc, char *argv[], struct timeval *wait_interval);
int parse_counters(const char *string, struct xt_counters *ctr);
bool tokenize_rule_counters(char **bufferp, char **pcnt, char **bcnt, int line);
bool xs_has_arg(int argc, char *argv[]);
extern const struct xtables_afinfo *afinfo;
extern char *newargv[];
extern int newargc;
extern char *oldargv[];
extern int oldargc;
extern int newargvattr[];
#define MAX_ARGC 255
struct argv_store {
int argc;
char *argv[MAX_ARGC];
int argvattr[MAX_ARGC];
};
int add_argv(const char *what, int quoted);
void free_argv(void);
void save_argv(void);
void add_param_to_argv(char *parsestart, int line);
void add_argv(struct argv_store *store, const char *what, int quoted);
void free_argv(struct argv_store *store);
void save_argv(struct argv_store *dst, struct argv_store *src);
void add_param_to_argv(struct argv_store *store, char *parsestart, int line);
#ifdef DEBUG
void debug_print_argv(struct argv_store *store);
#else
# define debug_print_argv(...) /* nothing */
#endif
void print_ipv4_addresses(const struct ipt_entry *fw, unsigned int format);
void print_ipv6_addresses(const struct ip6t_entry *fw6, unsigned int format);
......@@ -178,4 +210,9 @@ void command_match(struct iptables_command_state *cs);
const char *xt_parse_target(const char *targetname);
void command_jump(struct iptables_command_state *cs, const char *jumpto);
char cmd2char(int option);
void add_command(unsigned int *cmd, const int newcmd,
const int othercmds, int invert);
int parse_rulenumber(const char *rule);
#endif /* IPTABLES_XSHARED_H */
......@@ -27,7 +27,7 @@
This tool is not luser-proof: you can specify an Ethernet source address
and set hardware length to something different than 6, f.e.
*/
#include "config.h"
#include <getopt.h>
#include <string.h>
#include <netdb.h>
......@@ -53,56 +53,6 @@
#include "nft-arp.h"
#include <linux/netfilter_arp/arp_tables.h>
typedef char arpt_chainlabel[32];
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
/* XXX: command defined by nft-shared.h do not overlap with these two */
#undef CMD_CHECK
#undef CMD_RENAME_CHAIN
#define CMD_NONE 0x0000U
#define CMD_INSERT 0x0001U
#define CMD_DELETE 0x0002U
#define CMD_DELETE_NUM 0x0004U
#define CMD_REPLACE 0x0008U
#define CMD_APPEND 0x0010U
#define CMD_LIST 0x0020U
#define CMD_FLUSH 0x0040U
#define CMD_ZERO 0x0080U
#define CMD_NEW_CHAIN 0x0100U
#define CMD_DELETE_CHAIN 0x0200U
#define CMD_SET_POLICY 0x0400U
#define CMD_CHECK 0x0800U
#define CMD_RENAME_CHAIN 0x1000U
#define NUMBER_OF_CMD 13
static const char cmdflags[] = { 'I', 'D', 'D', 'R', 'A', 'L', 'F', 'Z',
'N', 'X', 'P', 'E' };
#define OPTION_OFFSET 256
#define OPT_NONE 0x00000U
#define OPT_NUMERIC 0x00001U
#define OPT_S_IP 0x00002U
#define OPT_D_IP 0x00004U
#define OPT_S_MAC 0x00008U
#define OPT_D_MAC 0x00010U
#define OPT_H_LENGTH 0x00020U
#define OPT_P_LENGTH 0x00040U
#define OPT_OPCODE 0x00080U
#define OPT_H_TYPE 0x00100U
#define OPT_P_TYPE 0x00200U
#define OPT_JUMP 0x00400U
#define OPT_VERBOSE 0x00800U
#define OPT_VIANAMEIN 0x01000U
#define OPT_VIANAMEOUT 0x02000U
#define OPT_LINENUMBERS 0x04000U
#define OPT_COUNTERS 0x08000U
#define NUMBER_OF_OPT 16
static const char optflags[NUMBER_OF_OPT]
= { 'n', 's', 'd', 2, 3, 7, 8, 4, 5, 6, 'j', 'v', 'i', 'o', '0', 'c'};
......@@ -148,85 +98,39 @@ static struct option original_opts[] = {
{ 0 }
};
int RUNTIME_NF_ARP_NUMHOOKS = 3;
#define opts xt_params->opts
extern void xtables_exit_error(enum xtables_exittype status, const char *msg, ...) __attribute__((noreturn, format(printf,2,3)));
struct xtables_globals arptables_globals = {
.option_offset = 0,
.program_version = IPTABLES_VERSION,
.program_version = PACKAGE_VERSION,
.orig_opts = original_opts,
.exit_err = xtables_exit_error,
.compat_rev = nft_compatible_revision,
};
/* Table of legal combinations of commands and options. If any of the
* given commands make an option legal, that option is legal (applies to
* CMD_LIST and CMD_ZERO only).
* Key:
* + compulsory
* x illegal
* optional
*/
static char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] =
/* Well, it's better than "Re: Linux vs FreeBSD" */
{
/* -n -s -d -p -j -v -x -i -o -f --line */
/*INSERT*/ {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '},
/*DELETE*/ {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '},
/*DELETE_NUM*/{' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '},
/*REPLACE*/ {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '},
/*APPEND*/ {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '},
/*LIST*/ {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '},
/*FLUSH*/ {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '},
/*ZERO*/ {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '},
/*NEW_CHAIN*/ {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '},
/*DEL_CHAIN*/ {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '},
/*SET_POLICY*/{' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '},
/*CHECK*/ {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '},
/*RENAME*/ {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}
};
static int inverse_for_options[NUMBER_OF_OPT] =
/* index relates to bit of each OPT_* value */
static int inverse_for_options[] =
{
/* -n */ 0,
/* -s */ ARPT_INV_SRCIP,
/* -d */ ARPT_INV_TGTIP,
/* 2 */ ARPT_INV_SRCDEVADDR,
/* 3 */ ARPT_INV_TGTDEVADDR,
/* -l */ ARPT_INV_ARPHLN,
/* 8 */ 0,
/* 4 */ ARPT_INV_ARPOP,
/* 5 */ ARPT_INV_ARPHRD,
/* 6 */ ARPT_INV_ARPPRO,
/* -p */ 0,
/* -j */ 0,
/* -v */ 0,
/* -x */ 0,
/* -i */ ARPT_INV_VIA_IN,
/* -o */ ARPT_INV_VIA_OUT,
/*--line*/ 0,
/* -c */ 0,
/* 2 */ ARPT_INV_SRCDEVADDR,
/* 3 */ ARPT_INV_TGTDEVADDR,
/* -l */ ARPT_INV_ARPHLN,
/* 4 */ ARPT_INV_ARPOP,
/* 5 */ ARPT_INV_ARPHRD,
/* 6 */ ARPT_INV_ARPPRO,
};
/* A few hardcoded protocols for 'all' and in case the user has no
/etc/protocols */
struct pprot {
char *name;
u_int8_t num;
};
/* Primitive headers... */
/* defined in netinet/in.h */
#if 0
#ifndef IPPROTO_ESP
#define IPPROTO_ESP 50
#endif
#ifndef IPPROTO_AH
#define IPPROTO_AH 51
#endif
#endif
/***********************************************/
/* ARPTABLES SPECIFIC NEW FUNCTIONS ADDED HERE */
/***********************************************/
......@@ -317,89 +221,10 @@ static int get16_and_mask(char *from, uint16_t *to, uint16_t *mask, int base)
return 0;
}
static int
string_to_number(const char *s, unsigned int min, unsigned int max,
unsigned int *ret)
{
long number;
char *end;
/* Handle hex, octal, etc. */
errno = 0;
number = strtol(s, &end, 0);
if (*end == '\0' && end != s) {
/* we parsed a number, let's see if we want this */
if (errno != ERANGE && min <= number && number <= max) {
*ret = number;
return 0;
}
}
return -1;
}
/*********************************************/
/* ARPTABLES SPECIFIC NEW FUNCTIONS END HERE */
/*********************************************/
static struct in_addr *
dotted_to_addr(const char *dotted)
{
static struct in_addr addr;
unsigned char *addrp;
char *p, *q;
unsigned int onebyte;
int i;
char buf[20];
/* copy dotted string, because we need to modify it */
strncpy(buf, dotted, sizeof(buf) - 1);
addrp = (unsigned char *) &(addr.s_addr);
p = buf;
for (i = 0; i < 3; i++) {
if ((q = strchr(p, '.')) == NULL)
return (struct in_addr *) NULL;
*q = '\0';
if (string_to_number(p, 0, 255, &onebyte) == -1)
return (struct in_addr *) NULL;
addrp[i] = (unsigned char) onebyte;
p = q + 1;
}
/* we've checked 3 bytes, now we check the last one */
if (string_to_number(p, 0, 255, &onebyte) == -1)
return (struct in_addr *) NULL;
addrp[3] = (unsigned char) onebyte;
return &addr;
}
static struct in_addr *
network_to_addr(const char *name)
{
struct netent *net;
static struct in_addr addr;
if ((net = getnetbyname(name)) != NULL) {
if (net->n_addrtype != AF_INET)
return (struct in_addr *) NULL;
addr.s_addr = htonl((unsigned long) net->n_net);
return &addr;
}
return (struct in_addr *) NULL;
}
static void
inaddrcpy(struct in_addr *dst, struct in_addr *src)
{
/* memcpy(dst, src, sizeof(struct in_addr)); */
dst->s_addr = src->s_addr;
}
static void
exit_tryhelp(int status)
{
......@@ -503,42 +328,6 @@ exit_printhelp(void)
exit(0);
}
static void
generic_opt_check(int command, int options)
{
int i, j, legal = 0;
/* Check that commands are valid with options. Complicated by the
* fact that if an option is legal with *any* command given, it is
* legal overall (ie. -z and -l).
*/
for (i = 0; i < NUMBER_OF_OPT; i++) {
legal = 0; /* -1 => illegal, 1 => legal, 0 => undecided. */
for (j = 0; j < NUMBER_OF_CMD; j++) {
if (!(command & (1<<j)))
continue;
if (!(options & (1<<i))) {
if (commands_v_options[j][i] == '+')
xtables_error(PARAMETER_PROBLEM,
"You need to supply the `-%c' "
"option for this command\n",
optflags[i]);
} else {
if (commands_v_options[j][i] != 'x')
legal = 1;
else if (legal == 0)
legal = -1;
}
}
if (legal == -1)
xtables_error(PARAMETER_PROBLEM,
"Illegal option `-%c' with this command\n",
optflags[i]);
}
}
static char
opt2char(int option)
{
......@@ -548,26 +337,6 @@ opt2char(int option)
return *ptr;
}
static char
cmd2char(int option)
{
const char *ptr;
for (ptr = cmdflags; option > 1; option >>= 1, ptr++);
return *ptr;
}
static void
add_command(unsigned int *cmd, const int newcmd, const unsigned int othercmds, int invert)
{
if (invert)
xtables_error(PARAMETER_PROBLEM, "unexpected ! flag");
if (*cmd & (~othercmds))
xtables_error(PARAMETER_PROBLEM, "Can't use -%c with -%c\n",
cmd2char(newcmd), cmd2char(*cmd & (~othercmds)));
*cmd |= newcmd;
}
static int
check_inverse(const char option[], int *invert, int *optidx, int argc)
{
......@@ -575,7 +344,7 @@ check_inverse(const char option[], int *invert, int *optidx, int argc)
if (*invert)
xtables_error(PARAMETER_PROBLEM,
"Multiple `!' flags not allowed");
*invert = TRUE;
*invert = true;
if (optidx) {
*optidx = *optidx+1;
if (argc && *optidx > argc)
......@@ -583,181 +352,9 @@ check_inverse(const char option[], int *invert, int *optidx, int argc)
"no argument following `!'");
}
return TRUE;
return true;
}
return FALSE;
}
static struct in_addr *
host_to_addr(const char *name, unsigned int *naddr)
{
struct in_addr *addr;
struct addrinfo hints = {
.ai_flags = AI_CANONNAME,
.ai_family = AF_INET,
.ai_socktype = SOCK_RAW,
};;
struct addrinfo *res, *p;
int err;
unsigned int i;
*naddr = 0;
err = getaddrinfo(name, NULL, &hints, &res);
if (err != 0)
return NULL;
else {
for (p = res; p != NULL; p = p->ai_next)
(*naddr)++;
addr = xtables_calloc(*naddr, sizeof(struct in_addr));
for (i = 0, p = res; p != NULL; p = p->ai_next)
memcpy(&addr[i++],
&((const struct sockaddr_in *)p->ai_addr)->sin_addr,
sizeof(struct in_addr));
freeaddrinfo(res);
return addr;
}
return (struct in_addr *) NULL;
}
/*
* All functions starting with "parse" should succeed, otherwise
* the program fails.
* Most routines return pointers to static data that may change
* between calls to the same or other routines with a few exceptions:
* "host_to_addr", "parse_hostnetwork", and "parse_hostnetworkmask"
* return global static data.
*/
static struct in_addr *
parse_hostnetwork(const char *name, unsigned int *naddrs)
{
struct in_addr *addrp, *addrptmp;
if ((addrptmp = dotted_to_addr(name)) != NULL ||
(addrptmp = network_to_addr(name)) != NULL) {
addrp = xtables_malloc(sizeof(struct in_addr));
inaddrcpy(addrp, addrptmp);
*naddrs = 1;
return addrp;
}
if ((addrp = host_to_addr(name, naddrs)) != NULL)
return addrp;
xtables_error(PARAMETER_PROBLEM, "host/network `%s' not found", name);
}
static struct in_addr *
parse_mask(char *mask)
{
static struct in_addr maskaddr;
struct in_addr *addrp;
unsigned int bits;
if (mask == NULL) {
/* no mask at all defaults to 32 bits */
maskaddr.s_addr = 0xFFFFFFFF;
return &maskaddr;
}
if ((addrp = dotted_to_addr(mask)) != NULL)
/* dotted_to_addr already returns a network byte order addr */
return addrp;
if (string_to_number(mask, 0, 32, &bits) == -1)
xtables_error(PARAMETER_PROBLEM,
"invalid mask `%s' specified", mask);
if (bits != 0) {
maskaddr.s_addr = htonl(0xFFFFFFFF << (32 - bits));
return &maskaddr;
}
maskaddr.s_addr = 0L;
return &maskaddr;
}
static void
parse_hostnetworkmask(const char *name, struct in_addr **addrpp,
struct in_addr *maskp, unsigned int *naddrs)
{
struct in_addr *addrp;
char buf[256];
char *p;
int i, j, k, n;
strncpy(buf, name, sizeof(buf) - 1);
if ((p = strrchr(buf, '/')) != NULL) {
*p = '\0';
addrp = parse_mask(p + 1);
} else
addrp = parse_mask(NULL);
inaddrcpy(maskp, addrp);
/* if a null mask is given, the name is ignored, like in "any/0" */
if (maskp->s_addr == 0L)
strcpy(buf, "0.0.0.0");
addrp = *addrpp = parse_hostnetwork(buf, naddrs);
n = *naddrs;
for (i = 0, j = 0; i < n; i++) {
addrp[j++].s_addr &= maskp->s_addr;
for (k = 0; k < j - 1; k++) {
if (addrp[k].s_addr == addrp[j - 1].s_addr) {
(*naddrs)--;
j--;
break;
}
}
}
}
static void
parse_interface(const char *arg, char *vianame, unsigned char *mask)
{
int vialen = strlen(arg);
unsigned int i;
memset(mask, 0, IFNAMSIZ);
memset(vianame, 0, IFNAMSIZ);
if (vialen + 1 > IFNAMSIZ)
xtables_error(PARAMETER_PROBLEM,
"interface name `%s' must be shorter than IFNAMSIZ"
" (%i)", arg, IFNAMSIZ-1);
strcpy(vianame, arg);
if (vialen == 0)
memset(mask, 0, IFNAMSIZ);
else if (vianame[vialen - 1] == '+') {
memset(mask, 0xFF, vialen - 1);
memset(mask + vialen - 1, 0, IFNAMSIZ - vialen + 1);
/* Don't remove `+' here! -HW */
} else {
/* Include nul-terminator in match */
memset(mask, 0xFF, vialen + 1);
memset(mask + vialen + 1, 0, IFNAMSIZ - vialen - 1);
for (i = 0; vianame[i]; i++) {
if (!isalnum(vianame[i])
&& vianame[i] != '_'
&& vianame[i] != '.') {
printf("Warning: weird character in interface"
" `%s' (No aliases, :, ! or *).\n",
vianame);
break;
}
}
}
}
/* Can't be zero. */
static int
parse_rulenumber(const char *rule)
{
unsigned int rulenum;
if (!xtables_strtoui(rule, NULL, &rulenum, 1, INT_MAX))
xtables_error(PARAMETER_PROBLEM,
"Invalid rule number `%s'", rule);
return rulenum;
return false;
}
static void
......@@ -814,8 +411,10 @@ append_entry(struct nft_handle *h,
int rulenum,
unsigned int nsaddrs,
const struct in_addr saddrs[],
const struct in_addr smasks[],
unsigned int ndaddrs,
const struct in_addr daddrs[],
const struct in_addr dmasks[],
bool verbose, bool append)
{
unsigned int i, j;
......@@ -823,8 +422,10 @@ append_entry(struct nft_handle *h,
for (i = 0; i < nsaddrs; i++) {
cs->arp.arp.src.s_addr = saddrs[i].s_addr;
cs->arp.arp.smsk.s_addr = smasks[i].s_addr;
for (j = 0; j < ndaddrs; j++) {
cs->arp.arp.tgt.s_addr = daddrs[j].s_addr;
cs->arp.arp.tmsk.s_addr = dmasks[j].s_addr;
if (append) {
ret = nft_rule_append(h, chain, table, cs, NULL,
verbose);
......@@ -844,11 +445,15 @@ replace_entry(const char *chain,
struct iptables_command_state *cs,
unsigned int rulenum,
const struct in_addr *saddr,
const struct in_addr *smask,
const struct in_addr *daddr,
const struct in_addr *dmask,
bool verbose, struct nft_handle *h)
{
cs->arp.arp.src.s_addr = saddr->s_addr;
cs->arp.arp.tgt.s_addr = daddr->s_addr;
cs->arp.arp.smsk.s_addr = smask->s_addr;
cs->arp.arp.tmsk.s_addr = dmask->s_addr;
return nft_rule_replace(h, chain, table, cs, rulenum, verbose);
}
......@@ -859,8 +464,10 @@ delete_entry(const char *chain,
struct iptables_command_state *cs,
unsigned int nsaddrs,
const struct in_addr saddrs[],
const struct in_addr smasks[],
unsigned int ndaddrs,
const struct in_addr daddrs[],
const struct in_addr dmasks[],
bool verbose, struct nft_handle *h)
{
unsigned int i, j;
......@@ -868,8 +475,10 @@ delete_entry(const char *chain,
for (i = 0; i < nsaddrs; i++) {
cs->arp.arp.src.s_addr = saddrs[i].s_addr;
cs->arp.arp.smsk.s_addr = smasks[i].s_addr;
for (j = 0; j < ndaddrs; j++) {
cs->arp.arp.tgt.s_addr = daddrs[j].s_addr;
cs->arp.arp.tmsk.s_addr = dmasks[j].s_addr;
ret = nft_rule_delete(h, chain, table, cs, verbose);
}
}
......@@ -919,7 +528,8 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table,
};
int invert = 0;
unsigned int nsaddrs = 0, ndaddrs = 0;
struct in_addr *saddrs = NULL, *daddrs = NULL;
struct in_addr *saddrs = NULL, *smasks = NULL;
struct in_addr *daddrs = NULL, *dmasks = NULL;
int c, verbose = 0;
const char *chain = NULL;
......@@ -1067,14 +677,14 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table,
break;
case 's':
check_inverse(optarg, &invert, &optind, argc);
set_option(&options, OPT_S_IP, &cs.arp.arp.invflags,
set_option(&options, OPT_SOURCE, &cs.arp.arp.invflags,
invert);
shostnetworkmask = argv[optind-1];
break;
case 'd':
check_inverse(optarg, &invert, &optind, argc);
set_option(&options, OPT_D_IP, &cs.arp.arp.invflags,
set_option(&options, OPT_DESTINATION, &cs.arp.arp.invflags,
invert);
dhostnetworkmask = argv[optind-1];
break;
......@@ -1168,18 +778,18 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table,
check_inverse(optarg, &invert, &optind, argc);
set_option(&options, OPT_VIANAMEIN, &cs.arp.arp.invflags,
invert);
parse_interface(argv[optind-1],
cs.arp.arp.iniface,
cs.arp.arp.iniface_mask);
xtables_parse_interface(argv[optind-1],
cs.arp.arp.iniface,
cs.arp.arp.iniface_mask);
break;
case 'o':
check_inverse(optarg, &invert, &optind, argc);
set_option(&options, OPT_VIANAMEOUT, &cs.arp.arp.invflags,
invert);
parse_interface(argv[optind-1],
cs.arp.arp.outiface,
cs.arp.arp.outiface_mask);
xtables_parse_interface(argv[optind-1],
cs.arp.arp.outiface,
cs.arp.arp.outiface_mask);
break;
case 'v':
......@@ -1255,7 +865,7 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table,
xtables_error(PARAMETER_PROBLEM,
"multiple consecutive ! not"
" allowed");
invert = TRUE;
invert = true;
optarg[0] = '\0';
continue;
}
......@@ -1269,7 +879,7 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table,
}
break;
}
invert = FALSE;
invert = false;
}
if (cs.target)
......@@ -1285,19 +895,19 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table,
"nothing appropriate following !");
if (command & (CMD_REPLACE | CMD_INSERT | CMD_DELETE | CMD_APPEND)) {
if (!(options & OPT_D_IP))
if (!(options & OPT_DESTINATION))
dhostnetworkmask = "0.0.0.0/0";
if (!(options & OPT_S_IP))
if (!(options & OPT_SOURCE))
shostnetworkmask = "0.0.0.0/0";
}
if (shostnetworkmask)
parse_hostnetworkmask(shostnetworkmask, &saddrs,
&(cs.arp.arp.smsk), &nsaddrs);
xtables_ipparse_multiple(shostnetworkmask, &saddrs,
&smasks, &nsaddrs);
if (dhostnetworkmask)
parse_hostnetworkmask(dhostnetworkmask, &daddrs,
&(cs.arp.arp.tmsk), &ndaddrs);
xtables_ipparse_multiple(dhostnetworkmask, &daddrs,
&dmasks, &ndaddrs);
if ((nsaddrs > 1 || ndaddrs > 1) &&
(cs.arp.arp.invflags & (ARPT_INV_SRCIP | ARPT_INV_TGTIP)))
......@@ -1308,8 +918,6 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table,
xtables_error(PARAMETER_PROBLEM, "Replacement rule does not "
"specify a unique address");
generic_opt_check(command, options);
if (chain && strlen(chain) > ARPT_FUNCTION_MAXNAMELEN)
xtables_error(PARAMETER_PROBLEM,
"chain name `%s' too long (must be under %i chars)",
......@@ -1343,12 +951,14 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table,
switch (command) {
case CMD_APPEND:
ret = append_entry(h, chain, *table, &cs, 0,
nsaddrs, saddrs, ndaddrs, daddrs,
nsaddrs, saddrs, smasks,
ndaddrs, daddrs, dmasks,
options&OPT_VERBOSE, true);
break;
case CMD_DELETE:
ret = delete_entry(chain, *table, &cs,
nsaddrs, saddrs, ndaddrs, daddrs,
nsaddrs, saddrs, smasks,
ndaddrs, daddrs, dmasks,
options&OPT_VERBOSE, h);
break;
case CMD_DELETE_NUM:
......@@ -1356,11 +966,13 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table,
break;
case CMD_REPLACE:
ret = replace_entry(chain, *table, &cs, rulenum - 1,
saddrs, daddrs, options&OPT_VERBOSE, h);
saddrs, smasks, daddrs, dmasks,
options&OPT_VERBOSE, h);
break;
case CMD_INSERT:
ret = append_entry(h, chain, *table, &cs, rulenum - 1,
nsaddrs, saddrs, ndaddrs, daddrs,
nsaddrs, saddrs, smasks,
ndaddrs, daddrs, dmasks,
options&OPT_VERBOSE, false);
break;
case CMD_LIST:
......@@ -1409,10 +1021,10 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table,
exit_tryhelp(2);
}
if (nsaddrs)
free(saddrs);
if (ndaddrs)
free(daddrs);
free(saddrs);
free(smasks);
free(daddrs);
free(dmasks);
if (cs.target)
free(cs.target->t);
......
%{
/*
* (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software has been sponsored by Sophos Astaro <http://www.sophos.com>
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <stdarg.h>
#include <libiptc/linux_list.h>
#include <libnftnl/table.h>
#include <libnftnl/chain.h>
#include <netinet/in.h>
#include <linux/netfilter.h>
extern char *yytext;
extern int yylineno;
static LIST_HEAD(xtables_stack);
struct stack_elem {
struct list_head head;
int token;
size_t size;
char data[];
};
static void *stack_push(int token, size_t size)
{
struct stack_elem *e;
e = calloc(1, sizeof(struct stack_elem) + size);
e->token = token;
e->size = size;
list_add(&e->head, &xtables_stack);
return e->data;
}
static struct stack_elem *stack_pop(void)
{
struct stack_elem *e;
e = list_entry(xtables_stack.next, struct stack_elem, head);
if (&e->head == &xtables_stack)
return NULL;
list_del(&e->head);
return e;
}
static inline void stack_put_i32(void *data, int value)
{
memcpy(data, &value, sizeof(int));
}
static inline void stack_put_str(void *data, const char *str)
{
memcpy(data, str, strlen(str));
}
static void stack_free(struct stack_elem *e)
{
free(e);
}
%}
%union {
int val;
char *string;
}
%token T_FAMILY
%token T_TABLE
%token T_CHAIN
%token T_HOOK
%token T_PRIO
%token <string> T_STRING
%token <val> T_INTEGER
%%
configfile :
| lines
;
lines : line
| lines line
;
line : family
;
family : T_FAMILY T_STRING '{' tables '}'
{
void *data = stack_push(T_FAMILY, strlen($2)+1);
stack_put_str(data, $2);
}
;
tables : table
| tables table
;
table : T_TABLE T_STRING '{' chains '}'
{
/* added in reverse order to pop it in order */
void *data = stack_push(T_TABLE, strlen($2)+1);
stack_put_str(data, $2);
}
;
chains : chain
| chains chain
;
chain : T_CHAIN T_STRING T_HOOK T_STRING T_PRIO T_INTEGER
{
/* added in reverse order to pop it in order */
void *data = stack_push(T_PRIO, sizeof(int32_t));
stack_put_i32(data, $6);
data = stack_push(T_HOOK, strlen($4)+1);
stack_put_str(data, $4);
data = stack_push(T_CHAIN, strlen($2)+1);
stack_put_str(data, $2);
}
;
%%
int __attribute__((noreturn))
yyerror(char *msg)
{
fprintf(stderr, "parsing config file in line (%d), symbol '%s': %s\n",
yylineno, yytext, msg);
exit(EXIT_FAILURE);
}
static int hooknametonum(const char *hookname)
{
if (strcmp(hookname, "NF_INET_LOCAL_IN") == 0)
return NF_INET_LOCAL_IN;
else if (strcmp(hookname, "NF_INET_FORWARD") == 0)
return NF_INET_FORWARD;
else if (strcmp(hookname, "NF_INET_LOCAL_OUT") == 0)
return NF_INET_LOCAL_OUT;
else if (strcmp(hookname, "NF_INET_PRE_ROUTING") == 0)
return NF_INET_PRE_ROUTING;
else if (strcmp(hookname, "NF_INET_POST_ROUTING") == 0)
return NF_INET_POST_ROUTING;
return -1;
}
static int32_t familytonumber(const char *family)
{
if (strcmp(family, "ipv4") == 0)
return AF_INET;
else if (strcmp(family, "ipv6") == 0)
return AF_INET6;
return -1;
}
int xtables_config_parse(char *filename, struct nftnl_table_list *table_list,
struct nftnl_chain_list *chain_list)
{
FILE *fp;
struct stack_elem *e;
struct nftnl_table *table = NULL;
struct nftnl_chain *chain = NULL;
int prio = 0;
int32_t family = 0;
fp = fopen(filename, "r");
if (!fp)
return -1;
yyrestart(fp);
yyparse();
fclose(fp);
for (e = stack_pop(); e != NULL; e = stack_pop()) {
switch(e->token) {
case T_FAMILY:
family = familytonumber(e->data);
if (family == -1)
return -1;
break;
case T_TABLE:
table = nftnl_table_alloc();
if (table == NULL)
return -1;
nftnl_table_set_u32(table, NFTNL_TABLE_FAMILY, family);
nftnl_table_set(table, NFTNL_TABLE_NAME, e->data);
/* This is intentionally prepending, instead of
* appending, since the elements in the stack are in
* the reverse order that chains appear in the
* configuration file.
*/
nftnl_table_list_add(table, table_list);
break;
case T_PRIO:
memcpy(&prio, e->data, sizeof(int32_t));
break;
case T_CHAIN:
chain = nftnl_chain_alloc();
if (chain == NULL)
return -1;
nftnl_chain_set(chain, NFTNL_CHAIN_TABLE,
(char *)nftnl_table_get(table, NFTNL_TABLE_NAME));
nftnl_chain_set_u32(chain, NFTNL_CHAIN_FAMILY,
nftnl_table_get_u32(table, NFTNL_TABLE_FAMILY));
nftnl_chain_set_s32(chain, NFTNL_CHAIN_PRIO, prio);
nftnl_chain_set(chain, NFTNL_CHAIN_NAME, e->data);
/* Intentionally prepending, instead of appending */
nftnl_chain_list_add(chain, chain_list);
break;
case T_HOOK:
nftnl_chain_set_u32(chain, NFTNL_CHAIN_HOOKNUM,
hooknametonum(e->data));
break;
default:
printf("unknown token type %d\n", e->token);
break;
}
stack_free(e);
}
return 0;
}
%{
/*
* (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software has been sponsored by Sophos Astaro <http://www.sophos.com>
*/
#include <string.h>
#include "xtables-config-parser.h"
%}
%option yylineno
%option noinput
%option nounput
ws [ \t]+
comment #.*$
nl [\n\r]
is_on [o|O][n|N]
is_off [o|O][f|F][f|F]
integer [\-\+]?[0-9]+
string [a-zA-Z][a-zA-Z0-9\.\-\_]*
%%
"family" { return T_FAMILY; }
"table" { return T_TABLE; }
"chain" { return T_CHAIN; }
"hook" { return T_HOOK; }
"prio" { return T_PRIO; }
{integer} { yylval.val = atoi(yytext); return T_INTEGER; }
{string} { yylval.string = strdup(yytext); return T_STRING; }
{comment} ;
{ws} ;
{nl} ;
<<EOF>> { yyterminate(); }
. { return yytext[0]; }
%%
int
yywrap()
{
return 1;
}
......@@ -51,7 +51,7 @@ int xtables_eb_main(int argc, char *argv[])
ret = do_commandeb(&h, argc, argv, &table, false);
if (ret)
ret = nft_commit(&h);
ret = nft_bridge_commit(&h);
if (!ret)
fprintf(stderr, "ebtables: %s\n", nft_strerror(errno));
......
......@@ -20,7 +20,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "config.h"
#include <ctype.h>
#include <errno.h>
#include <getopt.h>
......@@ -197,7 +197,8 @@ int ebt_get_current_chain(const char *chain)
else if (strcmp(chain, "POSTROUTING") == 0)
return NF_BR_POST_ROUTING;
return -1;
/* placeholder for user defined chain */
return NF_BR_NUMHOOKS;
}
/*
......@@ -273,7 +274,7 @@ struct option ebt_original_options[] =
extern void xtables_exit_error(enum xtables_exittype status, const char *msg, ...) __attribute__((noreturn, format(printf,2,3)));
struct xtables_globals ebtables_globals = {
.option_offset = 0,
.program_version = IPTABLES_VERSION,
.program_version = PACKAGE_VERSION,
.orig_opts = ebt_original_options,
.exit_err = xtables_exit_error,
.compat_rev = nft_compatible_revision,
......@@ -410,7 +411,7 @@ static int list_rules(struct nft_handle *h, const char *chain, const char *table
{
unsigned int format;
format = FMT_OPTIONS;
format = FMT_OPTIONS | FMT_C_COUNTS;
if (verbose)
format |= FMT_VIA;
......@@ -593,6 +594,7 @@ void ebt_load_match_extensions(void)
ebt_load_match("pkttype");
ebt_load_match("vlan");
ebt_load_match("stp");
ebt_load_match("among");
ebt_load_watcher("log");
ebt_load_watcher("nflog");
......@@ -779,6 +781,7 @@ int do_commandeb(struct nft_handle *h, int argc, char *argv[], char **table,
int selected_chain = -1;
struct xtables_rule_match *xtrm_i;
struct ebt_match *match;
bool table_set = false;
/* prevent getopt to spoil our error reporting */
optind = 0;
......@@ -946,11 +949,16 @@ print_zero:
break;
case 't': /* Table */
ebt_check_option2(&flags, OPT_TABLE);
if (restore && table_set)
xtables_error(PARAMETER_PROBLEM,
"The -t option (seen in line %u) cannot be used in %s.\n",
line, xt_params->program_name);
if (strlen(optarg) > EBT_TABLE_MAXNAMELEN - 1)
xtables_error(PARAMETER_PROBLEM,
"Table name length cannot exceed %d characters",
EBT_TABLE_MAXNAMELEN - 1);
*table = optarg;
table_set = true;
break;
case 'i': /* Input interface */
case 2 : /* Logical input interface */
......@@ -1180,7 +1188,7 @@ print_zero:
if (ebt_command_default(&cs))
xtables_error(PARAMETER_PROBLEM,
"Unknown argument: '%s'",
argv[optind - 1]);
argv[optind]);
if (command != 'A' && command != 'I' &&
command != 'D' && command != 'C')
......@@ -1223,7 +1231,7 @@ print_zero:
cs.eb.ethproto = htons(cs.eb.ethproto);
if (command == 'P') {
if (selected_chain < 0) {
if (selected_chain >= NF_BR_NUMHOOKS) {
ret = ebt_set_user_chain_policy(h, *table, chain, policy);
} else {
if (strcmp(policy, "RETURN") == 0) {
......
......@@ -10,6 +10,8 @@
*/
#define _GNU_SOURCE
#include "config.h"
#include <errno.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
......@@ -40,6 +42,7 @@
struct cb_arg {
uint32_t nfproto;
bool is_event;
struct nft_handle *h;
};
static int table_cb(const struct nlmsghdr *nlh, void *data)
......@@ -105,7 +108,7 @@ static int rule_cb(const struct nlmsghdr *nlh, void *data)
}
printf("-t %s ", nftnl_rule_get_str(r, NFTNL_RULE_TABLE));
nft_rule_print_save(r, type == NFT_MSG_NEWRULE ? NFT_RULE_APPEND :
nft_rule_print_save(arg->h, r, type == NFT_MSG_NEWRULE ? NFT_RULE_APPEND :
NFT_RULE_DEL,
counters ? 0 : FMT_NOCOUNTS);
err_free:
......@@ -592,7 +595,10 @@ int xtables_monitor_main(int argc, char *argv[])
struct mnl_socket *nl;
char buf[MNL_SOCKET_BUFFER_SIZE];
uint32_t nfgroup = 0;
struct cb_arg cb_arg = {};
struct nft_handle h = {};
struct cb_arg cb_arg = {
.h = &h,
};
int ret, c;
xtables_globals.program_name = "xtables-monitor";
......@@ -609,6 +615,14 @@ int xtables_monitor_main(int argc, char *argv[])
init_extensions4();
#endif
if (nft_init(&h, xtables_ipv4)) {
fprintf(stderr, "%s/%s Failed to initialize nft: %s\n",
xtables_globals.program_name,
xtables_globals.program_version,
strerror(errno));
exit(EXIT_FAILURE);
}
opterr = 0;
while ((c = getopt_long(argc, argv, "ceht46V", options, NULL)) != -1) {
switch (c) {
......@@ -631,10 +645,10 @@ int xtables_monitor_main(int argc, char *argv[])
cb_arg.nfproto = NFPROTO_IPV6;
break;
case 'V':
printf("xtables-monitor %s\n", IPTABLES_VERSION);
printf("xtables-monitor %s\n", PACKAGE_VERSION);
exit(0);
default:
fprintf(stderr, "xtables-monitor %s: Bad argument.\n", IPTABLES_VERSION);
fprintf(stderr, "xtables-monitor %s: Bad argument.\n", PACKAGE_VERSION);
fprintf(stderr, "Try `xtables-monitor -h' for more information.\n");
exit(PARAMETER_PROBLEM);
}
......
......@@ -4,9 +4,10 @@
*
* This code is distributed under the terms of GNU GPL v2
*/
#include "config.h"
#include <getopt.h>
#include <errno.h>
#include <libgen.h>
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
......@@ -17,6 +18,7 @@
#include "xtables-multi.h"
#include "nft.h"
#include "nft-bridge.h"
#include "nft-cache.h"
#include <libnftnl/chain.h>
static int counters, verbose;
......@@ -43,7 +45,7 @@ static const struct option options[] = {
static void print_usage(const char *name, const char *version)
{
fprintf(stderr, "Usage: %s [-c] [-v] [-V] [-t] [-h] [-n] [-T table] [-M command] [-4] [-6]\n"
fprintf(stderr, "Usage: %s [-c] [-v] [-V] [-t] [-h] [-n] [-T table] [-M command] [-4] [-6] [file]\n"
" [ --counters ]\n"
" [ --verbose ]\n"
" [ --version]\n"
......@@ -51,25 +53,12 @@ static void print_usage(const char *name, const char *version)
" [ --help ]\n"
" [ --noflush ]\n"
" [ --table=<TABLE> ]\n"
" [ --modprobe=<command> ]\n"
" [ --modprobe=<command> ]\n"
" [ --ipv4 ]\n"
" [ --ipv6 ]\n", name);
}
static struct nftnl_chain_list *get_chain_list(struct nft_handle *h,
const char *table)
{
struct nftnl_chain_list *chain_list;
chain_list = nft_chain_list_get(h, table);
if (chain_list == NULL)
xtables_error(OTHER_PROBLEM, "cannot retrieve chain list\n");
return chain_list;
}
struct nft_xt_restore_cb restore_cb = {
.chain_list = get_chain_list,
static const struct nft_xt_restore_cb restore_cb = {
.commit = nft_commit,
.abort = nft_abort,
.table_new = nft_table_new,
......@@ -79,241 +68,285 @@ struct nft_xt_restore_cb restore_cb = {
.chain_restore = nft_chain_restore,
};
static const struct xtc_ops xtc_ops = {
.strerror = nft_strerror,
struct nft_xt_restore_state {
const struct builtin_table *curtable;
struct argv_store av_store;
bool in_table;
};
void xtables_restore_parse(struct nft_handle *h,
struct nft_xt_restore_parse *p,
struct nft_xt_restore_cb *cb,
int argc, char *argv[])
static void xtables_restore_parse_line(struct nft_handle *h,
const struct nft_xt_restore_parse *p,
struct nft_xt_restore_state *state,
char *buffer)
{
const struct builtin_table *curtable = NULL;
char buffer[10240];
int in_table = 0;
const struct xtc_ops *ops = &xtc_ops;
const struct nft_xt_restore_cb *cb = p->cb;
int ret = 0;
if (buffer[0] == '\n')
return;
else if (buffer[0] == '#') {
if (verbose)
fputs(buffer, stdout);
return;
} else if (state->in_table &&
(strncmp(buffer, "COMMIT", 6) == 0) &&
(buffer[6] == '\0' || buffer[6] == '\n')) {
if (!p->testing) {
/* Commit per table, although we support
* global commit at once, stick by now to
* the existing behaviour.
*/
DEBUGP("Calling commit\n");
if (cb->commit)
ret = cb->commit(h);
} else {
DEBUGP("Not calling commit, testing\n");
if (cb->abort)
ret = cb->abort(h);
}
state->in_table = false;
} else if ((buffer[0] == '*') && (!state->in_table || !p->commit)) {
/* New table */
char *table;
table = strtok(buffer+1, " \t\n");
DEBUGP("line %u, table '%s'\n", line, table);
if (!table)
xtables_error(PARAMETER_PROBLEM,
"%s: line %u table name invalid\n",
xt_params->program_name, line);
state->curtable = nft_table_builtin_find(h, table);
if (!state->curtable)
xtables_error(PARAMETER_PROBLEM,
"%s: line %u table name '%s' invalid\n",
xt_params->program_name, line, table);
if (p->tablename && (strcmp(p->tablename, table) != 0))
return;
if (h->noflush == 0) {
DEBUGP("Cleaning all chains of table '%s'\n", table);
if (cb->table_flush)
cb->table_flush(h, table);
}
line = 0;
ret = 1;
state->in_table = true;
if (cb->table_new)
cb->table_new(h, table);
} else if ((buffer[0] == ':') && state->in_table) {
/* New chain. */
char *policy, *chain = NULL;
struct xt_counters count = {};
chain = strtok(buffer+1, " \t\n");
DEBUGP("line %u, chain '%s'\n", line, chain);
if (!chain)
xtables_error(PARAMETER_PROBLEM,
"%s: line %u chain name invalid\n",
xt_params->program_name, line);
if (strlen(chain) >= XT_EXTENSION_MAXNAMELEN)
xtables_error(PARAMETER_PROBLEM,
"Invalid chain name `%s' (%u chars max)",
chain, XT_EXTENSION_MAXNAMELEN - 1);
policy = strtok(NULL, " \t\n");
DEBUGP("line %u, policy '%s'\n", line, policy);
if (!policy)
xtables_error(PARAMETER_PROBLEM,
"%s: line %u policy invalid\n",
xt_params->program_name, line);
if (nft_chain_builtin_find(state->curtable, chain)) {
if (counters) {
char *ctrs;
ctrs = strtok(NULL, " \t\n");
if (!ctrs || !parse_counters(ctrs, &count))
xtables_error(PARAMETER_PROBLEM,
"invalid policy counters for chain '%s'\n",
chain);
/* Grab standard input. */
while (fgets(buffer, sizeof(buffer), p->in)) {
int ret = 0;
line++;
h->error.lineno = line;
if (buffer[0] == '\n')
continue;
else if (buffer[0] == '#') {
if (verbose)
fputs(buffer, stdout);
continue;
} else if ((strcmp(buffer, "COMMIT\n") == 0) && (in_table)) {
if (!p->testing) {
/* Commit per table, although we support
* global commit at once, stick by now to
* the existing behaviour.
*/
DEBUGP("Calling commit\n");
if (cb->commit)
ret = cb->commit(h);
} else {
DEBUGP("Not calling commit, testing\n");
if (cb->abort)
ret = cb->abort(h);
}
in_table = 0;
} else if ((buffer[0] == '*') && (!in_table || !p->commit)) {
/* New table */
char *table;
table = strtok(buffer+1, " \t\n");
DEBUGP("line %u, table '%s'\n", line, table);
if (!table) {
xtables_error(PARAMETER_PROBLEM,
"%s: line %u table name invalid\n",
xt_params->program_name, line);
exit(1);
}
curtable = nft_table_builtin_find(h, table);
if (!curtable)
xtables_error(PARAMETER_PROBLEM,
"%s: line %u table name '%s' invalid\n",
xt_params->program_name, line, table);
if (p->tablename && (strcmp(p->tablename, table) != 0))
continue;
nft_build_cache(h);
if (h->noflush == 0) {
DEBUGP("Cleaning all chains of table '%s'\n",
table);
if (cb->table_flush)
cb->table_flush(h, table);
if (cb->chain_set &&
cb->chain_set(h, state->curtable->name,
chain, policy, &count) < 0) {
xtables_error(OTHER_PROBLEM,
"Can't set policy `%s' on `%s' line %u: %s\n",
policy, chain, line,
strerror(errno));
}
DEBUGP("Setting policy of chain %s to %s\n",
chain, policy);
} else if (cb->chain_restore(h, chain, state->curtable->name) < 0 &&
errno != EEXIST) {
xtables_error(PARAMETER_PROBLEM,
"cannot create chain '%s' (%s)\n",
chain, strerror(errno));
} else if (h->family == NFPROTO_BRIDGE &&
!ebt_set_user_chain_policy(h, state->curtable->name,
chain, policy)) {
xtables_error(OTHER_PROBLEM,
"Can't set policy `%s' on `%s' line %u: %s\n",
policy, chain, line,
strerror(errno));
}
ret = 1;
} else if (state->in_table) {
char *pcnt = NULL;
char *bcnt = NULL;
char *parsestart = buffer;
add_argv(&state->av_store, xt_params->program_name, 0);
add_argv(&state->av_store, "-t", 0);
add_argv(&state->av_store, state->curtable->name, 0);
tokenize_rule_counters(&parsestart, &pcnt, &bcnt, line);
if (counters && pcnt && bcnt) {
add_argv(&state->av_store, "--set-counters", 0);
add_argv(&state->av_store, pcnt, 0);
add_argv(&state->av_store, bcnt, 0);
}
ret = 1;
in_table = 1;
if (cb->table_new)
cb->table_new(h, table);
add_param_to_argv(&state->av_store, parsestart, line);
} else if ((buffer[0] == ':') && (in_table)) {
/* New chain. */
char *policy, *chain = NULL;
struct xt_counters count = {};
DEBUGP("calling do_command4(%u, argv, &%s, handle):\n",
state->av_store.argc, state->curtable->name);
debug_print_argv(&state->av_store);
chain = strtok(buffer+1, " \t\n");
DEBUGP("line %u, chain '%s'\n", line, chain);
if (!chain) {
xtables_error(PARAMETER_PROBLEM,
"%s: line %u chain name invalid\n",
xt_params->program_name, line);
exit(1);
}
ret = cb->do_command(h, state->av_store.argc,
state->av_store.argv,
&state->av_store.argv[2], true);
if (ret < 0) {
if (cb->abort)
ret = cb->abort(h);
else
ret = 0;
if (strlen(chain) >= XT_EXTENSION_MAXNAMELEN)
xtables_error(PARAMETER_PROBLEM,
"Invalid chain name `%s' "
"(%u chars max)",
chain, XT_EXTENSION_MAXNAMELEN - 1);
policy = strtok(NULL, " \t\n");
DEBUGP("line %u, policy '%s'\n", line, policy);
if (!policy) {
xtables_error(PARAMETER_PROBLEM,
"%s: line %u policy invalid\n",
xt_params->program_name, line);
exit(1);
if (ret < 0) {
fprintf(stderr,
"failed to abort commit operation\n");
}
exit(1);
}
if (nft_chain_builtin_find(curtable, chain)) {
if (counters) {
char *ctrs;
ctrs = strtok(NULL, " \t\n");
if (!ctrs || !parse_counters(ctrs, &count))
xtables_error(PARAMETER_PROBLEM,
"invalid policy counters "
"for chain '%s'\n", chain);
}
if (cb->chain_set &&
cb->chain_set(h, curtable->name,
chain, policy, &count) < 0) {
xtables_error(OTHER_PROBLEM,
"Can't set policy `%s'"
" on `%s' line %u: %s\n",
policy, chain, line,
ops->strerror(errno));
}
DEBUGP("Setting policy of chain %s to %s\n",
chain, policy);
} else if (cb->chain_restore(h, chain, curtable->name) < 0 &&
errno != EEXIST) {
xtables_error(PARAMETER_PROBLEM,
"cannot create chain "
"'%s' (%s)\n", chain,
strerror(errno));
} else if (h->family == NFPROTO_BRIDGE &&
!ebt_set_user_chain_policy(h, curtable->name,
chain, policy)) {
xtables_error(OTHER_PROBLEM,
"Can't set policy `%s'"
" on `%s' line %u: %s\n",
policy, chain, line,
ops->strerror(errno));
}
ret = 1;
} else if (in_table) {
int a;
char *pcnt = NULL;
char *bcnt = NULL;
char *parsestart;
free_argv(&state->av_store);
fflush(stdout);
}
if (p->tablename && state->curtable &&
(strcmp(p->tablename, state->curtable->name) != 0))
return;
if (!ret) {
fprintf(stderr, "%s: line %u failed\n",
xt_params->program_name, line);
exit(1);
}
}
/* reset the newargv */
newargc = 0;
/* Return true if given iptables-restore line will require a full cache.
* Typically these are commands referring to an existing rule
* (either by number or content) or commands listing the ruleset. */
static bool cmd_needs_full_cache(char *cmd)
{
char c, chain[32];
int rulenum, mcount;
mcount = sscanf(cmd, "-%c %31s %d", &c, chain, &rulenum);
if (mcount == 3)
return true;
if (mcount < 1)
return false;
switch (c) {
case 'D':
case 'C':
case 'S':
case 'L':
case 'Z':
return true;
}
if (buffer[0] == '[') {
/* we have counters in our input */
char *ptr = strchr(buffer, ']');
return false;
}
if (!ptr)
xtables_error(PARAMETER_PROBLEM,
"Bad line %u: need ]\n",
line);
#define PREBUFSIZ 65536
pcnt = strtok(buffer+1, ":");
if (!pcnt)
xtables_error(PARAMETER_PROBLEM,
"Bad line %u: need :\n",
line);
void xtables_restore_parse(struct nft_handle *h,
const struct nft_xt_restore_parse *p)
{
struct nft_xt_restore_state state = {};
char preload_buffer[PREBUFSIZ] = {}, buffer[10240], *ptr;
bcnt = strtok(NULL, "]");
if (!bcnt)
xtables_error(PARAMETER_PROBLEM,
"Bad line %u: need ]\n",
line);
/* start command parsing after counter */
parsestart = ptr + 1;
} else {
/* start command parsing at start of line */
parsestart = buffer;
if (!h->noflush) {
nft_fake_cache(h);
} else {
ssize_t pblen = sizeof(preload_buffer);
bool do_cache = false;
ptr = preload_buffer;
while (fgets(buffer, sizeof(buffer), p->in)) {
size_t blen = strlen(buffer);
/* drop trailing newline; xtables_restore_parse_line()
* uses strtok() which replaces them by nul-characters,
* causing unpredictable string delimiting in
* preload_buffer */
if (buffer[blen - 1] == '\n')
buffer[blen - 1] = '\0';
else
blen++;
pblen -= blen;
if (pblen <= 0) {
/* buffer exhausted */
do_cache = true;
break;
}
add_argv(argv[0], 0);
add_argv("-t", 0);
add_argv(curtable->name, 0);
if (counters && pcnt && bcnt) {
add_argv("--set-counters", 0);
add_argv((char *) pcnt, 0);
add_argv((char *) bcnt, 0);
if (cmd_needs_full_cache(buffer)) {
do_cache = true;
break;
}
add_param_to_argv(parsestart, line);
DEBUGP("calling do_command4(%u, argv, &%s, handle):\n",
newargc, curtable->name);
for (a = 0; a < newargc; a++)
DEBUGP("argv[%u]: %s\n", a, newargv[a]);
/* copy string including terminating nul-char */
memcpy(ptr, buffer, blen);
ptr += blen;
buffer[0] = '\0';
}
ret = cb->do_command(h, newargc, newargv,
&newargv[2], true);
if (ret < 0) {
if (cb->abort)
ret = cb->abort(h);
else
ret = 0;
if (ret < 0) {
fprintf(stderr, "failed to abort "
"commit operation\n");
}
exit(1);
}
if (do_cache)
nft_build_cache(h, NULL);
}
free_argv();
fflush(stdout);
}
if (p->tablename && curtable &&
(strcmp(p->tablename, curtable->name) != 0))
continue;
if (!ret) {
fprintf(stderr, "%s: line %u failed\n",
xt_params->program_name, line);
exit(1);
}
line = 0;
ptr = preload_buffer;
while (*ptr) {
h->error.lineno = ++line;
DEBUGP("%s: buffered line %d: '%s'\n", __func__, line, ptr);
xtables_restore_parse_line(h, p, &state, ptr);
ptr += strlen(ptr) + 1;
}
if (*buffer) {
h->error.lineno = ++line;
DEBUGP("%s: overrun line %d: '%s'\n", __func__, line, buffer);
xtables_restore_parse_line(h, p, &state, buffer);
}
if (in_table && p->commit) {
while (fgets(buffer, sizeof(buffer), p->in)) {
h->error.lineno = ++line;
DEBUGP("%s: input line %d: '%s'\n", __func__, line, buffer);
xtables_restore_parse_line(h, p, &state, buffer);
}
if (state.in_table && p->commit) {
fprintf(stderr, "%s: COMMIT expected at line %u\n",
xt_params->program_name, line + 1);
exit(1);
} else if (in_table && cb->commit && !cb->commit(h)) {
} else if (state.in_table && p->cb->commit && !p->cb->commit(h)) {
xtables_error(OTHER_PROBLEM, "%s: final implicit COMMIT failed",
xt_params->program_name);
}
......@@ -330,6 +363,7 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[])
int c;
struct nft_xt_restore_parse p = {
.commit = true,
.cb = &restore_cb,
};
line = 0;
......@@ -361,8 +395,7 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[])
p.testing = 1;
break;
case 'h':
print_usage("xtables-restore",
IPTABLES_VERSION);
print_usage(prog_name, PACKAGE_VERSION);
exit(0);
case 'n':
h.noflush = 1;
......@@ -387,7 +420,8 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[])
break;
default:
fprintf(stderr,
"Try `xtables-restore -h' for more information.\n");
"Try `%s -h' for more information.\n",
prog_name);
exit(1);
}
}
......@@ -434,7 +468,7 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[])
exit(EXIT_FAILURE);
}
xtables_restore_parse(&h, &p, &restore_cb, argc, argv);
xtables_restore_parse(&h, &p);
nft_fini(&h);
fclose(p.in);
......@@ -443,13 +477,13 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[])
int xtables_ip4_restore_main(int argc, char *argv[])
{
return xtables_restore_main(NFPROTO_IPV4, "iptables-restore",
return xtables_restore_main(NFPROTO_IPV4, basename(*argv),
argc, argv);
}
int xtables_ip6_restore_main(int argc, char *argv[])
{
return xtables_restore_main(NFPROTO_IPV6, "ip6tables-restore",
return xtables_restore_main(NFPROTO_IPV6, basename(*argv),
argc, argv);
}
......@@ -460,9 +494,8 @@ static int ebt_table_flush(struct nft_handle *h, const char *table)
return nft_table_flush(h, table);
}
struct nft_xt_restore_cb ebt_restore_cb = {
.chain_list = get_chain_list,
.commit = nft_commit,
static const struct nft_xt_restore_cb ebt_restore_cb = {
.commit = nft_bridge_commit,
.table_new = nft_table_new,
.table_flush = ebt_table_flush,
.do_command = do_commandeb,
......@@ -479,6 +512,7 @@ int xtables_eb_restore_main(int argc, char *argv[])
{
struct nft_xt_restore_parse p = {
.in = stdin,
.cb = &ebt_restore_cb,
};
bool noflush = false;
struct nft_handle h;
......@@ -500,14 +534,13 @@ int xtables_eb_restore_main(int argc, char *argv[])
nft_init_eb(&h, "ebtables-restore");
h.noflush = noflush;
xtables_restore_parse(&h, &p, &ebt_restore_cb, argc, argv);
xtables_restore_parse(&h, &p);
nft_fini(&h);
return 0;
}
struct nft_xt_restore_cb arp_restore_cb = {
.chain_list = get_chain_list,
static const struct nft_xt_restore_cb arp_restore_cb = {
.commit = nft_commit,
.table_new = nft_table_new,
.table_flush = nft_table_flush,
......@@ -520,11 +553,12 @@ int xtables_arp_restore_main(int argc, char *argv[])
{
struct nft_xt_restore_parse p = {
.in = stdin,
.cb = &arp_restore_cb,
};
struct nft_handle h;
nft_init_arp(&h, "arptables-restore");
xtables_restore_parse(&h, &p, &arp_restore_cb, argc, argv);
xtables_restore_parse(&h, &p);
nft_fini(&h);
return 0;
......
......@@ -6,8 +6,10 @@
* This code is distributed under the terms of GNU GPL v2
*
*/
#include "config.h"
#include <getopt.h>
#include <errno.h>
#include <libgen.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
......@@ -19,6 +21,7 @@
#include "iptables.h"
#include "xtables-multi.h"
#include "nft.h"
#include "nft-cache.h"
#include <libnftnl/chain.h>
......@@ -29,9 +32,8 @@
#define prog_name xtables_globals.program_name
#define prog_vers xtables_globals.program_version
static bool show_counters = false;
static const struct option options[] = {
static const char *ipt_save_optstring = "bcdt:M:f:46V";
static const struct option ipt_save_options[] = {
{.name = "counters", .has_arg = false, .val = 'c'},
{.name = "version", .has_arg = false, .val = 'V'},
{.name = "dump", .has_arg = false, .val = 'd'},
......@@ -43,6 +45,7 @@ static const struct option options[] = {
{NULL},
};
static const char *arp_save_optstring = "cM:V";
static const struct option arp_save_options[] = {
{.name = "counters", .has_arg = false, .val = 'c'},
{.name = "version", .has_arg = false, .val = 'V'},
......@@ -50,6 +53,7 @@ static const struct option arp_save_options[] = {
{NULL},
};
static const char *ebt_save_optstring = "ct:M:V";
static const struct option ebt_save_options[] = {
{.name = "counters", .has_arg = false, .val = 'c'},
{.name = "version", .has_arg = false, .val = 'V'},
......@@ -58,49 +62,55 @@ static const struct option ebt_save_options[] = {
{NULL},
};
static bool ebt_legacy_counter_format;
struct do_output_data {
unsigned int format;
bool commit;
};
static int
__do_output(struct nft_handle *h, const char *tablename, bool counters)
__do_output(struct nft_handle *h, const char *tablename, void *data)
{
struct nftnl_chain_list *chain_list;
struct do_output_data *d = data;
time_t now;
if (!nft_table_builtin_find(h, tablename))
return 0;
if (!nft_is_table_compatible(h, tablename)) {
if (!nft_table_builtin_find(h, tablename))
printf("# Table `%s' is incompatible, use 'nft' tool.\n",
tablename);
if (!nft_is_table_compatible(h, tablename, NULL)) {
printf("# Table `%s' is incompatible, use 'nft' tool.\n",
tablename);
return 0;
}
chain_list = nft_chain_list_get(h, tablename);
chain_list = nft_chain_list_get(h, tablename, NULL);
if (!chain_list)
return 0;
time_t now = time(NULL);
now = time(NULL);
printf("# Generated by %s v%s on %s", prog_name,
prog_vers, ctime(&now));
printf("# Generated by xtables-save v%s on %s",
IPTABLES_VERSION, ctime(&now));
printf("*%s\n", tablename);
/* Dump out chain names first,
* thereby preventing dependency conflicts */
nft_chain_save(h, chain_list);
nft_rule_save(h, tablename, counters ? 0 : FMT_NOCOUNTS);
nft_rule_save(h, tablename, d->format);
if (d->commit)
printf("COMMIT\n");
now = time(NULL);
printf("COMMIT\n");
printf("# Completed on %s", ctime(&now));
return 0;
}
static int
do_output(struct nft_handle *h, const char *tablename, bool counters)
do_output(struct nft_handle *h, const char *tablename, struct do_output_data *d)
{
int ret;
if (!tablename) {
ret = nft_for_each_table(h, __do_output, counters);
ret = nft_for_each_table(h, __do_output, d);
nft_check_xt_legacy(h->family, true);
return !!ret;
}
......@@ -111,7 +121,7 @@ do_output(struct nft_handle *h, const char *tablename, bool counters)
return 1;
}
ret = __do_output(h, tablename, counters);
ret = __do_output(h, tablename, d);
nft_check_xt_legacy(h->family, true);
return ret;
}
......@@ -121,10 +131,14 @@ do_output(struct nft_handle *h, const char *tablename, bool counters)
* rule
*/
static int
xtables_save_main(int family, const char *progname, int argc, char *argv[])
xtables_save_main(int family, int argc, char *argv[],
const char *optstring, const struct option *longopts)
{
const struct builtin_table *tables;
const char *tablename = NULL;
struct do_output_data d = {
.format = FMT_NOCOUNTS,
};
bool dump = false;
struct nft_handle h = {
.family = family,
......@@ -132,7 +146,7 @@ xtables_save_main(int family, const char *progname, int argc, char *argv[])
FILE *file = NULL;
int ret, c;
xtables_globals.program_name = progname;
xtables_globals.program_name = basename(*argv);;
c = xtables_init_all(&xtables_globals, family);
if (c < 0) {
fprintf(stderr, "%s/%s Failed to initialize xtables\n",
......@@ -141,13 +155,13 @@ xtables_save_main(int family, const char *progname, int argc, char *argv[])
exit(1);
}
while ((c = getopt_long(argc, argv, "bcdt:M:f:46V", options, NULL)) != -1) {
while ((c = getopt_long(argc, argv, optstring, longopts, NULL)) != -1) {
switch (c) {
case 'b':
fprintf(stderr, "-b/--binary option is not implemented\n");
break;
case 'c':
show_counters = true;
d.format &= ~FMT_NOCOUNTS;
break;
case 't':
......@@ -206,13 +220,23 @@ xtables_save_main(int family, const char *progname, int argc, char *argv[])
init_extensions4();
#endif
tables = xtables_ipv4;
d.commit = true;
break;
case NFPROTO_ARP:
tables = xtables_arp;
break;
case NFPROTO_BRIDGE:
case NFPROTO_BRIDGE: {
const char *ctr = getenv("EBTABLES_SAVE_COUNTER");
if (!(d.format & FMT_NOCOUNTS)) {
d.format |= FMT_EBT_SAVE;
} else if (ctr && !strcmp(ctr, "yes")) {
d.format &= ~FMT_NOCOUNTS;
d.format |= FMT_C_COUNTS | FMT_EBT_SAVE;
}
tables = xtables_bridge;
break;
}
default:
fprintf(stderr, "Unknown family %d\n", family);
return 1;
......@@ -225,8 +249,11 @@ xtables_save_main(int family, const char *progname, int argc, char *argv[])
strerror(errno));
exit(EXIT_FAILURE);
}
h.ops = nft_family_ops_lookup(h.family);
if (!h.ops)
xtables_error(PARAMETER_PROBLEM, "Unknown family");
ret = do_output(&h, tablename, show_counters);
ret = do_output(&h, tablename, &d);
nft_fini(&h);
if (dump)
exit(0);
......@@ -236,178 +263,24 @@ xtables_save_main(int family, const char *progname, int argc, char *argv[])
int xtables_ip4_save_main(int argc, char *argv[])
{
return xtables_save_main(NFPROTO_IPV4, "iptables-save", argc, argv);
return xtables_save_main(NFPROTO_IPV4, argc, argv,
ipt_save_optstring, ipt_save_options);
}
int xtables_ip6_save_main(int argc, char *argv[])
{
return xtables_save_main(NFPROTO_IPV6, "ip6tables-save", argc, argv);
}
static int __ebt_save(struct nft_handle *h, const char *tablename, bool counters)
{
struct nftnl_chain_list *chain_list;
unsigned int format = FMT_NOCOUNTS;
static bool first = true;
time_t now;
if (!nft_table_find(h, tablename)) {
printf("Table `%s' does not exist\n", tablename);
return 1;
}
if (!nft_is_table_compatible(h, tablename)) {
printf("# Table `%s' is incompatible, use 'nft' tool.\n", tablename);
return 0;
}
chain_list = nft_chain_list_get(h, tablename);
if (first) {
now = time(NULL);
printf("# Generated by ebtables-save v%s on %s",
IPTABLES_VERSION, ctime(&now));
first = false;
}
printf("*%s\n", tablename);
if (counters)
format = ebt_legacy_counter_format ? FMT_EBT_SAVE : 0;
/* Dump out chain names first,
* thereby preventing dependency conflicts */
nft_chain_save(h, chain_list);
nft_rule_save(h, tablename, format);
printf("\n");
return 0;
return xtables_save_main(NFPROTO_IPV6, argc, argv,
ipt_save_optstring, ipt_save_options);
}
static int ebt_save(struct nft_handle *h, const char *tablename, bool counters)
int xtables_eb_save_main(int argc, char *argv[])
{
if (!tablename)
return nft_for_each_table(h, __ebt_save, counters);
return __ebt_save(h, tablename, counters);
return xtables_save_main(NFPROTO_BRIDGE, argc, argv,
ebt_save_optstring, ebt_save_options);
}
int xtables_eb_save_main(int argc_, char *argv_[])
int xtables_arp_save_main(int argc, char *argv[])
{
const char *ctr = getenv("EBTABLES_SAVE_COUNTER");
const char *tablename = NULL;
struct nft_handle h = {
.family = NFPROTO_BRIDGE,
};
int c;
if (ctr) {
if (strcmp(ctr, "yes") == 0) {
ebt_legacy_counter_format = true;
show_counters = true;
}
}
xtables_globals.program_name = "ebtables-save";
c = xtables_init_all(&xtables_globals, h.family);
if (c < 0) {
fprintf(stderr, "%s/%s Failed to initialize xtables\n",
xtables_globals.program_name,
xtables_globals.program_version);
exit(1);
}
while ((c = getopt_long(argc_, argv_, "ct:M:V", ebt_save_options, NULL)) != -1) {
switch (c) {
case 'c':
unsetenv("EBTABLES_SAVE_COUNTER");
show_counters = true;
ebt_legacy_counter_format = false;
break;
case 't':
/* Select specific table. */
tablename = optarg;
break;
case 'M':
xtables_modprobe_program = optarg;
break;
case 'V':
printf("%s v%s (nf_tables)\n", prog_name, prog_vers);
exit(0);
default:
fprintf(stderr,
"Look at manual page `%s.8' for more information.\n",
prog_name);
exit(1);
}
}
if (nft_init(&h, xtables_bridge) < 0) {
fprintf(stderr, "%s/%s Failed to initialize nft: %s\n",
xtables_globals.program_name,
xtables_globals.program_version,
strerror(errno));
exit(EXIT_FAILURE);
}
ebt_save(&h, tablename, show_counters);
nft_fini(&h);
return 0;
}
int xtables_arp_save_main(int argc, char **argv)
{
struct nft_handle h = {
.family = NFPROTO_ARP,
};
int c;
xtables_globals.program_name = "arptables-save";
c = xtables_init_all(&xtables_globals, h.family);
if (c < 0) {
fprintf(stderr, "%s/%s Failed to initialize xtables\n",
xtables_globals.program_name,
xtables_globals.program_version);
exit(1);
}
while ((c = getopt_long(argc, argv, "cM:V", arp_save_options, NULL)) != -1) {
switch (c) {
case 'c':
show_counters = true;
break;
case 'M':
xtables_modprobe_program = optarg;
break;
case 'V':
printf("%s v%s (nf_tables)\n", prog_name, prog_vers);
exit(0);
default:
fprintf(stderr,
"Look at manual page `%s.8' for more information.\n",
prog_name);
exit(1);
}
}
if (nft_init(&h, xtables_arp) < 0) {
fprintf(stderr, "%s/%s Failed to initialize nft: %s\n",
xtables_globals.program_name,
xtables_globals.program_version,
strerror(errno));
exit(EXIT_FAILURE);
}
if (!nft_table_find(&h, "filter"))
return 0;
if (!nft_is_table_compatible(&h, "filter")) {
printf("# Table `filter' is incompatible, use 'nft' tool.\n");
return 0;
}
printf("*filter\n");
nft_chain_save(&h, nft_chain_list_get(&h, "filter"));
nft_rule_save(&h, "filter", show_counters ? 0 : FMT_NOCOUNTS);
printf("\n");
nft_fini(&h);
return 0;
return xtables_save_main(NFPROTO_ARP, argc, argv,
arp_save_optstring, arp_save_options);
}
......@@ -6,7 +6,7 @@
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include "config.h"
#include <time.h>
#include "xtables-multi.h"
#include "nft.h"
......@@ -413,7 +413,7 @@ static int dummy_compat_rev(const char *name, uint8_t rev, int opt)
return 1;
}
static struct nft_xt_restore_cb cb_xlate = {
static const struct nft_xt_restore_cb cb_xlate = {
.table_new = xlate_table_new,
.chain_set = xlate_chain_set,
.chain_restore = xlate_chain_user_restore,
......@@ -498,7 +498,9 @@ static int xtables_restore_xlate_main(int family, const char *progname,
.family = family,
};
const char *file = NULL;
struct nft_xt_restore_parse p = {};
struct nft_xt_restore_parse p = {
.cb = &cb_xlate,
};
time_t now = time(NULL);
int c;
......@@ -510,20 +512,20 @@ static int xtables_restore_xlate_main(int family, const char *progname,
while ((c = getopt_long(argc, argv, "hf:V", options, NULL)) != -1) {
switch (c) {
case 'h':
print_usage(argv[0], IPTABLES_VERSION);
print_usage(argv[0], PACKAGE_VERSION);
exit(0);
case 'f':
file = optarg;
break;
case 'V':
printf("%s v%s\n", argv[0], IPTABLES_VERSION);
printf("%s v%s\n", argv[0], PACKAGE_VERSION);
exit(0);
}
}
if (file == NULL) {
fprintf(stderr, "ERROR: missing file name\n");
print_usage(argv[0], IPTABLES_VERSION);
print_usage(argv[0], PACKAGE_VERSION);
exit(0);
}
......@@ -534,8 +536,8 @@ static int xtables_restore_xlate_main(int family, const char *progname,
}
printf("# Translated by %s v%s on %s",
argv[0], IPTABLES_VERSION, ctime(&now));
xtables_restore_parse(&h, &p, &cb_xlate, argc, argv);
argv[0], PACKAGE_VERSION, ctime(&now));
xtables_restore_parse(&h, &p);
printf("# Completed on %s", ctime(&now));
nft_fini(&h);
......
......@@ -24,7 +24,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "config.h"
#include <getopt.h>
#include <string.h>
#include <netdb.h>
......@@ -43,17 +43,6 @@
#include "nft-shared.h"
#include "nft.h"
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#define NUMBER_OF_CMD 16
static const char cmdflags[] = { 'I', 'D', 'D', 'R', 'A', 'L', 'F', 'Z',
'N', 'X', 'P', 'E', 'S', 'Z', 'C' };
#define OPT_FRAGMENT 0x00800U
#define NUMBER_OF_OPT ARRAY_SIZE(optflags)
static const char optflags[]
......@@ -104,7 +93,7 @@ void xtables_exit_error(enum xtables_exittype status, const char *msg, ...) __at
struct xtables_globals xtables_globals = {
.option_offset = 0,
.program_version = IPTABLES_VERSION,
.program_version = PACKAGE_VERSION,
.orig_opts = original_opts,
.exit_err = xtables_exit_error,
.compat_rev = nft_compatible_revision,
......@@ -319,27 +308,6 @@ opt2char(int option)
return *ptr;
}
static char
cmd2char(int option)
{
const char *ptr;
for (ptr = cmdflags; option > 1; option >>= 1, ptr++);
return *ptr;
}
static void
add_command(unsigned int *cmd, const int newcmd, const int othercmds,
int invert)
{
if (invert)
xtables_error(PARAMETER_PROBLEM, "unexpected ! flag");
if (*cmd & (~othercmds))
xtables_error(PARAMETER_PROBLEM, "Cannot use -%c with -%c\n",
cmd2char(newcmd), cmd2char(*cmd & (~othercmds)));
*cmd |= newcmd;
}
/*
* All functions starting with "parse" should succeed, otherwise
* the program fails.
......@@ -350,18 +318,6 @@ add_command(unsigned int *cmd, const int newcmd, const int othercmds,
*/
/* Christophe Burki wants `-p 6' to imply `-m tcp'. */
/* Can't be zero. */
static int
parse_rulenumber(const char *rule)
{
unsigned int rulenum;
if (!xtables_strtoui(rule, NULL, &rulenum, 1, INT_MAX))
xtables_error(PARAMETER_PROBLEM,
"Invalid rule number `%s'", rule);
return rulenum;
}
static void
set_option(unsigned int *options, unsigned int option, uint8_t *invflg,
......@@ -590,6 +546,7 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
bool wait_interval_set = false;
struct timeval wait_interval;
struct xtables_target *t;
bool table_set = false;
int wait = 0;
memset(cs, 0, sizeof(*cs));
......@@ -879,11 +836,16 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
if (cs->invert)
xtables_error(PARAMETER_PROBLEM,
"unexpected ! flag before --table");
if (p->restore && table_set)
xtables_error(PARAMETER_PROBLEM,
"The -t option (seen in line %u) cannot be used in %s.\n",
line, xt_params->program_name);
if (!nft_table_builtin_find(h, optarg))
xtables_error(VERSION_PROBLEM,
"table '%s' does not exist",
optarg);
p->table = optarg;
table_set = true;
break;
case 'x':
......@@ -955,6 +917,9 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
break;
case '4':
if (p->restore && args->family == AF_INET6)
return;
if (args->family != AF_INET)
exit_tryhelp(2);
......@@ -962,6 +927,9 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
break;
case '6':
if (p->restore && args->family == AF_INET)
return;
args->family = AF_INET6;
xtables_set_nfproto(AF_INET6);
......@@ -977,7 +945,7 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
xtables_error(PARAMETER_PROBLEM,
"multiple consecutive ! not"
" allowed");
cs->invert = TRUE;
cs->invert = true;
optarg[0] = '\0';
continue;
}
......@@ -990,7 +958,7 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
continue;
break;
}
cs->invert = FALSE;
cs->invert = false;
}
if (strcmp(p->table, "nat") == 0 &&
......@@ -1174,6 +1142,9 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table,
case CMD_SET_POLICY:
ret = nft_chain_set(h, p.table, p.chain, p.policy, NULL);
break;
case CMD_NONE:
/* do_parse ignored the line (eg: -4 with ip6tables-restore) */
break;
default:
/* We should never reach this... */
exit_tryhelp(2);
......
......@@ -92,10 +92,10 @@ build_triplet = @build@
host_triplet = @host@
subdir = libipq
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_linker_flags.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
......@@ -241,9 +241,6 @@ INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LEX = @LEX@
LEXLIB = @LEXLIB@
LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
......@@ -277,8 +274,6 @@ SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
YACC = @YACC@
YFLAGS = @YFLAGS@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
......@@ -323,7 +318,6 @@ kinclude_CPPFLAGS = @kinclude_CPPFLAGS@
ksourcedir = @ksourcedir@
libdir = @libdir@
libexecdir = @libexecdir@
libiptc_LDFLAGS2 = @libiptc_LDFLAGS2@
libmnl_CFLAGS = @libmnl_CFLAGS@
libmnl_LIBS = @libmnl_LIBS@
libnetfilter_conntrack_CFLAGS = @libnetfilter_conntrack_CFLAGS@
......
......@@ -5,11 +5,8 @@ AM_CPPFLAGS = ${regular_CPPFLAGS} -I${top_builddir}/include -I${top_srcdir}
pkgconfig_DATA = libiptc.pc libip4tc.pc libip6tc.pc
lib_LTLIBRARIES = libip4tc.la libip6tc.la libiptc.la
libiptc_la_SOURCES =
libiptc_la_LIBADD = libip4tc.la libip6tc.la
libiptc_la_LDFLAGS = -version-info 0:0:0 ${libiptc_LDFLAGS2}
lib_LTLIBRARIES = libip4tc.la libip6tc.la
libip4tc_la_SOURCES = libip4tc.c
libip4tc_la_LDFLAGS = -version-info 2:0:0
libip6tc_la_SOURCES = libip6tc.c
libip6tc_la_LDFLAGS = -version-info 2:0:0 ${libiptc_LDFLAGS2}
libip6tc_la_LDFLAGS = -version-info 2:0:0
......@@ -92,10 +92,10 @@ build_triplet = @build@
host_triplet = @host@
subdir = libiptc
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_linker_flags.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
......@@ -148,12 +148,6 @@ libip6tc_la_OBJECTS = $(am_libip6tc_la_OBJECTS)
libip6tc_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libip6tc_la_LDFLAGS) $(LDFLAGS) -o $@
libiptc_la_DEPENDENCIES = libip4tc.la libip6tc.la
am_libiptc_la_OBJECTS =
libiptc_la_OBJECTS = $(am_libiptc_la_OBJECTS)
libiptc_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libiptc_la_LDFLAGS) $(LDFLAGS) -o $@
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
......@@ -188,10 +182,8 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
SOURCES = $(libip4tc_la_SOURCES) $(libip6tc_la_SOURCES) \
$(libiptc_la_SOURCES)
DIST_SOURCES = $(libip4tc_la_SOURCES) $(libip6tc_la_SOURCES) \
$(libiptc_la_SOURCES)
SOURCES = $(libip4tc_la_SOURCES) $(libip6tc_la_SOURCES)
DIST_SOURCES = $(libip4tc_la_SOURCES) $(libip6tc_la_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
......@@ -255,9 +247,6 @@ INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LEX = @LEX@
LEXLIB = @LEXLIB@
LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
......@@ -291,8 +280,6 @@ SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
YACC = @YACC@
YFLAGS = @YFLAGS@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
......@@ -337,7 +324,6 @@ kinclude_CPPFLAGS = @kinclude_CPPFLAGS@
ksourcedir = @ksourcedir@
libdir = @libdir@
libexecdir = @libexecdir@
libiptc_LDFLAGS2 = @libiptc_LDFLAGS2@
libmnl_CFLAGS = @libmnl_CFLAGS@
libmnl_LIBS = @libmnl_LIBS@
libnetfilter_conntrack_CFLAGS = @libnetfilter_conntrack_CFLAGS@
......@@ -375,14 +361,11 @@ xtlibdir = @xtlibdir@
AM_CFLAGS = ${regular_CFLAGS}
AM_CPPFLAGS = ${regular_CPPFLAGS} -I${top_builddir}/include -I${top_srcdir}/include ${kinclude_CPPFLAGS}
pkgconfig_DATA = libiptc.pc libip4tc.pc libip6tc.pc
lib_LTLIBRARIES = libip4tc.la libip6tc.la libiptc.la
libiptc_la_SOURCES =
libiptc_la_LIBADD = libip4tc.la libip6tc.la
libiptc_la_LDFLAGS = -version-info 0:0:0 ${libiptc_LDFLAGS2}
lib_LTLIBRARIES = libip4tc.la libip6tc.la
libip4tc_la_SOURCES = libip4tc.c
libip4tc_la_LDFLAGS = -version-info 2:0:0
libip6tc_la_SOURCES = libip6tc.c
libip6tc_la_LDFLAGS = -version-info 2:0:0 ${libiptc_LDFLAGS2}
libip6tc_la_LDFLAGS = -version-info 2:0:0
all: all-am
.SUFFIXES:
......@@ -464,9 +447,6 @@ libip4tc.la: $(libip4tc_la_OBJECTS) $(libip4tc_la_DEPENDENCIES) $(EXTRA_libip4tc
libip6tc.la: $(libip6tc_la_OBJECTS) $(libip6tc_la_DEPENDENCIES) $(EXTRA_libip6tc_la_DEPENDENCIES)
$(AM_V_CCLD)$(libip6tc_la_LINK) -rpath $(libdir) $(libip6tc_la_OBJECTS) $(libip6tc_la_LIBADD) $(LIBS)
libiptc.la: $(libiptc_la_OBJECTS) $(libiptc_la_DEPENDENCIES) $(EXTRA_libiptc_la_DEPENDENCIES)
$(AM_V_CCLD)$(libiptc_la_LINK) -rpath $(libdir) $(libiptc_la_OBJECTS) $(libiptc_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment