Commit dab1e98e authored by Arturo Borrero Gonzalez's avatar Arturo Borrero Gonzalez
Browse files

New upstream version 1.8.1

parent f1f129da
.\"
.\" (C) Copyright 2016-2017, Arturo Borrero Gonzalez <arturo@netfilter.org>
.\"
.\" %%%LICENSE_START(GPLv2+_DOC_FULL)
.\" This is free documentation; 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.
.\"
.\" The GNU General Public License's references to "object code"
.\" and "executables" are to be interpreted as the output of any
.\" document formatting or typesetting system, including
.\" intermediate and printed output.
.\"
.\" This manual is distributed in the hope that it will be useful,
.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
.\" GNU General Public License for more details.
.\"
.\" You should have received a copy of the GNU General Public
.\" License along with this manual; if not, see
.\" <http://www.gnu.org/licenses/>.
.\" %%%LICENSE_END
.\"
.TH XTABLES-NFT 8 "June 2018"
.SH NAME
xtables-nft \(em iptables using nftables kernel api
.SH DESCRIPTION
\fBxtables-nft\fP are versions of iptables that use the nftables API.
This is a set of tools to help the system administrator migrate the
ruleset from \fBiptables(8)\fP, \fBip6tables(8)\fP, \fBarptables(8)\fP, and
\fBebtables(8)\fP to \fBnftables(8)\fP.
The \fBxtables-nft\fP set is composed of several commands:
.IP \[bu] 2
iptables\-nft
.IP \[bu]
iptables\-nft\-save
.IP \[bu]
iptables\-nft\-restore
.IP \[bu]
ip6tables\-nft
.IP \[bu]
ip6tables\-nft\-save
.IP \[bu]
ip6tables\-nft\-restore
.IP \[bu]
arptables\-nft
.IP \[bu]
ebtables\-nft
These tools use the libxtables framework extensions and hook to the nf_tables
kernel subsystem using the \fBnft_compat\fP module.
.SH USAGE
The xtables-nft tools allow you to manage the nf_tables backend using the
native syntax of \fBiptables(8)\fP, \fBip6tables(8)\fP, \fBarptables(8)\fP, and
\fBebtables(8)\fP.
You should use the xtables-nft tools exactly the same way as you would use the
corresponding original tools.
Adding a rule will result in that rule being added to the nf_tables kernel
subsystem instead.
Listing the ruleset will use the nf_tables backend as well.
When these tools were designed, the main idea was to replace each legacy binary
with a symlink to the xtables-nft program, for example:
.nf
/sbin/iptables -> /usr/sbin/iptables\-nft\-multi
/sbin/ip6tables -> /usr/sbin/ip6tables\-nft\-multi
/sbin/arptables -> /usr/sbin/arptables\-nft\-multi
/sbin/ebtables -> /usr/sbin/ebtables\-nft\-multi
.fi
The iptables version string will indicate whether the legacy API (get/setsockopt) or
the new nf_tables api is used:
.nf
iptables \-V
iptables v1.7 (nf_tables)
.fi
.SH DIFFERENCES TO LEGACY IPTABLES
Because the xtables-nft tools use the nf_tables kernel API, rule additions
and deletions are always atomic. Unlike iptables-legacy, iptables-nft \-A ..
will NOT need to retrieve the current ruleset from the kernel, change it, and
re-load the altered ruleset. Instead, iptables-nft will tell the kernel to add
one rule. For this reason, the iptables-legacy \-\-wait option is a no-op in
iptables-nft.
Use of the xtables-nft tools allow monitoring ruleset changes using the
.B xtables\-monitor(8)
command.
When using \-j TRACE to debug packet traversal to the ruleset, note that you will need to use
.B xtables\-monitor(8)
in \-\-trace mode to obtain monitoring trace events.
.SH EXAMPLES
One basic example is creating the skeleton ruleset in nf_tables from the
xtables-nft tools, in a fresh machine:
.nf
root@machine:~# iptables\-nft \-L
[...]
root@machine:~# ip6tables\-nft \-L
[...]
root@machine:~# arptables\-nft \-L
[...]
root@machine:~# ebtables\-nft \-L
[...]
root@machine:~# nft list ruleset
table ip filter {
chain INPUT {
type filter hook input priority 0; policy accept;
}
chain FORWARD {
type filter hook forward priority 0; policy accept;
}
chain OUTPUT {
type filter hook output priority 0; policy accept;
}
}
table ip6 filter {
chain INPUT {
type filter hook input priority 0; policy accept;
}
chain FORWARD {
type filter hook forward priority 0; policy accept;
}
chain OUTPUT {
type filter hook output priority 0; policy accept;
}
}
table bridge filter {
chain INPUT {
type filter hook input priority \-200; policy accept;
}
chain FORWARD {
type filter hook forward priority \-200; policy accept;
}
chain OUTPUT {
type filter hook output priority \-200; policy accept;
}
}
table arp filter {
chain INPUT {
type filter hook input priority 0; policy accept;
}
chain FORWARD {
type filter hook forward priority 0; policy accept;
}
chain OUTPUT {
type filter hook output priority 0; policy accept;
}
}
.fi
(please note that in fresh machines, listing the ruleset for the first time
results in all tables an chain being created).
To migrate your complete filter ruleset, in the case of \fBiptables(8)\fP,
you would use:
.nf
root@machine:~# iptables\-legacy\-save > myruleset # reads from x_tables
root@machine:~# iptables\-nft\-restore myruleset # writes to nf_tables
.fi
or
.nf
root@machine:~# iptables\-legacy\-save | iptables-translate-restore | less
.fi
to see how rules would look like in the nft
\fBnft(8)\fP
syntax.
.SH LIMITATIONS
You should use \fBLinux kernel >= 4.17\fP.
The CLUSTERIP target is not supported.
To get up-to-date information about this, please head to
\fBhttp://wiki.nftables.org/\fP.
.SH SEE ALSO
\fBnft(8)\fP, \fBxtables\-translate(8)\fP, \fBxtables\-monitor(8)\fP
.SH AUTHORS
The nftables framework is written by the Netfilter project
(https://www.netfilter.org).
This manual page was written by Arturo Borrero Gonzalez
<arturo@debian.org> for the Debian project, but may be used by others.
This documentation is free/libre under the terms of the GPLv2+.
......@@ -16,20 +16,16 @@
#include "libiptc/libiptc.h"
#include "xtables-multi.h"
#include "nft.h"
#include "nft-bridge.h"
#include <libnftnl/chain.h>
#ifdef DEBUG
#define DEBUGP(x, args...) fprintf(stderr, x, ## args)
#else
#define DEBUGP(x, args...)
#endif
static int counters = 0, verbose = 0, noflush = 0;
static int counters, verbose, noflush;
/* Keeping track of external matches and targets. */
static const struct option options[] = {
{.name = "counters", .has_arg = false, .val = 'c'},
{.name = "verbose", .has_arg = false, .val = 'v'},
{.name = "version", .has_arg = 0, .val = 'V'},
{.name = "test", .has_arg = false, .val = 't'},
{.name = "help", .has_arg = false, .val = 'h'},
{.name = "noflush", .has_arg = false, .val = 'n'},
......@@ -37,18 +33,20 @@ static const struct option options[] = {
{.name = "table", .has_arg = true, .val = 'T'},
{.name = "ipv4", .has_arg = false, .val = '4'},
{.name = "ipv6", .has_arg = false, .val = '6'},
{.name = "wait", .has_arg = 2, .val = 'w'},
{.name = "wait-interval", .has_arg = 2, .val = 'W'},
{NULL},
};
static void print_usage(const char *name, const char *version) __attribute__((noreturn));
#define prog_name xtables_globals.program_name
#define prog_vers xtables_globals.program_version
static void print_usage(const char *name, const char *version)
{
fprintf(stderr, "Usage: %s [-c] [-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]\n"
" [ --counters ]\n"
" [ --verbose ]\n"
" [ --version]\n"
" [ --test ]\n"
" [ --help ]\n"
" [ --noflush ]\n"
......@@ -56,109 +54,6 @@ static void print_usage(const char *name, const char *version)
" [ --modprobe=<command> ]\n"
" [ --ipv4 ]\n"
" [ --ipv6 ]\n", name);
exit(1);
}
static int parse_counters(char *string, struct xt_counters *ctr)
{
unsigned long long pcnt, bcnt;
int ret;
ret = sscanf(string, "[%llu:%llu]", &pcnt, &bcnt);
ctr->pcnt = pcnt;
ctr->bcnt = bcnt;
return ret == 2;
}
/* global new argv and argc */
static char *newargv[255];
static int newargc;
/* function adding one argument to newargv, updating newargc
* returns true if argument added, false otherwise */
static int add_argv(char *what) {
DEBUGP("add_argv: %s\n", what);
if (what && newargc + 1 < ARRAY_SIZE(newargv)) {
newargv[newargc] = strdup(what);
newargv[++newargc] = NULL;
return 1;
} else {
xtables_error(PARAMETER_PROBLEM,
"Parser cannot handle more arguments\n");
return 0;
}
}
static void free_argv(void) {
int i;
for (i = 0; i < newargc; i++)
free(newargv[i]);
}
static void add_param_to_argv(char *parsestart)
{
int quote_open = 0, escaped = 0, param_len = 0;
char param_buffer[1024], *curchar;
/* After fighting with strtok enough, here's now
* a 'real' parser. According to Rusty I'm now no
* longer a real hacker, but I can live with that */
for (curchar = parsestart; *curchar; curchar++) {
if (quote_open) {
if (escaped) {
param_buffer[param_len++] = *curchar;
escaped = 0;
continue;
} else if (*curchar == '\\') {
escaped = 1;
continue;
} else if (*curchar == '"') {
quote_open = 0;
*curchar = ' ';
} else {
param_buffer[param_len++] = *curchar;
continue;
}
} else {
if (*curchar == '"') {
quote_open = 1;
continue;
}
}
if (*curchar == ' '
|| *curchar == '\t'
|| * curchar == '\n') {
if (!param_len) {
/* two spaces? */
continue;
}
param_buffer[param_len] = '\0';
/* check if table name specified */
if (!strncmp(param_buffer, "-t", 2)
|| !strncmp(param_buffer, "--table", 8)) {
xtables_error(PARAMETER_PROBLEM,
"The -t option (seen in line %u) cannot be "
"used in xtables-restore.\n", line);
exit(1);
}
add_argv(param_buffer);
param_len = 0;
} else {
/* regular character, copy to buffer */
param_buffer[param_len++] = *curchar;
if (param_len >= sizeof(param_buffer))
xtables_error(PARAMETER_PROBLEM,
"Parameter too long!");
}
}
}
static struct nftnl_chain_list *get_chain_list(struct nft_handle *h)
......@@ -181,16 +76,19 @@ static void chain_delete(struct nftnl_chain_list *clist, const char *curtable,
/* This chain has been found, delete from list. Later
* on, unvisited chains will be purged out.
*/
if (chain_obj != NULL)
if (chain_obj != NULL) {
nftnl_chain_list_del(chain_obj);
nftnl_chain_free(chain_obj);
}
}
struct nft_xt_restore_cb restore_cb = {
.chain_list = get_chain_list,
.commit = nft_commit,
.abort = nft_abort,
.chains_purge = nft_table_purge_chains,
.rule_flush = nft_rule_flush,
.table_new = nft_table_new,
.table_flush = nft_table_flush,
.chain_user_flush = nft_chain_user_flush,
.chain_del = chain_delete,
.do_command = do_commandx,
.chain_set = nft_chain_set,
......@@ -208,7 +106,7 @@ void xtables_restore_parse(struct nft_handle *h,
{
char buffer[10240];
int in_table = 0;
char curtable[XT_TABLE_MAXNAMELEN + 1];
struct builtin_table *curtable = NULL;
const struct xtc_ops *ops = &xtc_ops;
struct nftnl_chain_list *chain_list = NULL;
......@@ -222,6 +120,8 @@ void xtables_restore_parse(struct nft_handle *h,
int ret = 0;
line++;
h->error.lineno = line;
if (buffer[0] == '\n')
continue;
else if (buffer[0] == '#') {
......@@ -244,11 +144,7 @@ void xtables_restore_parse(struct nft_handle *h,
}
in_table = 0;
/* Purge out unused chains in this table */
if (!p->testing && cb->chains_purge)
cb->chains_purge(h, curtable, chain_list);
} else if ((buffer[0] == '*') && (!in_table)) {
} else if ((buffer[0] == '*') && (!in_table || !p->commit)) {
/* New table */
char *table;
......@@ -260,8 +156,11 @@ void xtables_restore_parse(struct nft_handle *h,
xt_params->program_name, line);
exit(1);
}
strncpy(curtable, table, XT_TABLE_MAXNAMELEN);
curtable[XT_TABLE_MAXNAMELEN] = '\0';
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;
......@@ -269,8 +168,8 @@ void xtables_restore_parse(struct nft_handle *h,
if (noflush == 0) {
DEBUGP("Cleaning all chains of table '%s'\n",
table);
if (cb->rule_flush)
cb->rule_flush(h, NULL, table);
if (cb->table_flush)
cb->table_flush(h, table);
}
ret = 1;
......@@ -283,6 +182,7 @@ void xtables_restore_parse(struct nft_handle *h,
/* New chain. */
char *policy, *chain = NULL;
struct xt_counters count = {};
bool chain_exists = false;
chain = strtok(buffer+1, " \t\n");
DEBUGP("line %u, chain '%s'\n", line, chain);
......@@ -293,8 +193,21 @@ void xtables_restore_parse(struct nft_handle *h,
exit(1);
}
if (noflush == 0) {
if (cb->chain_del)
cb->chain_del(chain_list, curtable, chain);
cb->chain_del(chain_list, curtable->name,
chain);
} else if (nft_chain_list_find(chain_list,
curtable->name, chain)) {
chain_exists = true;
/* Apparently -n still flushes existing user
* defined chains that are redefined. Otherwise,
* leave them as is.
*/
if (cb->chain_user_flush)
cb->chain_user_flush(h, chain_list,
curtable->name, chain);
}
if (strlen(chain) >= XT_EXTENSION_MAXNAMELEN)
xtables_error(PARAMETER_PROBLEM,
......@@ -311,7 +224,7 @@ void xtables_restore_parse(struct nft_handle *h,
exit(1);
}
if (strcmp(policy, "-") != 0) {
if (nft_chain_builtin_find(curtable, chain)) {
if (counters) {
char *ctrs;
ctrs = strtok(NULL, " \t\n");
......@@ -323,7 +236,8 @@ void xtables_restore_parse(struct nft_handle *h,
}
if (cb->chain_set &&
cb->chain_set(h, curtable, chain, policy, &count) < 0) {
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",
......@@ -335,8 +249,10 @@ void xtables_restore_parse(struct nft_handle *h,
ret = 1;
} else {
if (cb->chain_user_add &&
cb->chain_user_add(h, chain, curtable) < 0) {
if (!chain_exists &&
cb->chain_user_add &&
cb->chain_user_add(h, chain,
curtable->name) < 0) {
if (errno == EEXIST)
continue;
......@@ -350,7 +266,6 @@ void xtables_restore_parse(struct nft_handle *h,
} else if (in_table) {
int a;
char *ptr = buffer;
char *pcnt = NULL;
char *bcnt = NULL;
char *parsestart;
......@@ -360,7 +275,8 @@ void xtables_restore_parse(struct nft_handle *h,
if (buffer[0] == '[') {
/* we have counters in our input */
ptr = strchr(buffer, ']');
char *ptr = strchr(buffer, ']');
if (!ptr)
xtables_error(PARAMETER_PROBLEM,
"Bad line %u: need ]\n",
......@@ -385,20 +301,20 @@ void xtables_restore_parse(struct nft_handle *h,
parsestart = buffer;
}
add_argv(argv[0]);
add_argv("-t");
add_argv(curtable);
add_argv(argv[0], 0);
add_argv("-t", 0);
add_argv(curtable->name, 0);
if (counters && pcnt && bcnt) {
add_argv("--set-counters");
add_argv((char *) pcnt);
add_argv((char *) bcnt);
add_argv("--set-counters", 0);
add_argv((char *) pcnt, 0);
add_argv((char *) bcnt, 0);
}
add_param_to_argv(parsestart);
add_param_to_argv(parsestart, line);
DEBUGP("calling do_command4(%u, argv, &%s, handle):\n",
newargc, curtable);
newargc, curtable->name);
for (a = 0; a < newargc; a++)
DEBUGP("argv[%u]: %s\n", a, newargv[a]);
......@@ -421,7 +337,8 @@ void xtables_restore_parse(struct nft_handle *h,
free_argv();
fflush(stdout);
}
if (p->tablename && (strcmp(p->tablename, curtable) != 0))
if (p->tablename && curtable &&
(strcmp(p->tablename, curtable->name) != 0))
continue;
if (!ret) {
fprintf(stderr, "%s: line %u failed\n",
......@@ -429,22 +346,28 @@ void xtables_restore_parse(struct nft_handle *h,
exit(1);
}
}
if (in_table) {
if (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)) {
xtables_error(OTHER_PROBLEM, "%s: final implicit COMMIT failed",
xt_params->program_name);
}
}
static int
xtables_restore_main(int family, const char *progname, int argc, char *argv[])
{
struct builtin_table *tables;
struct nft_handle h = {
.family = family,
.restore = true,
};
int c;
struct nft_xt_restore_parse p = {};
struct nft_xt_restore_parse p = {
.commit = true,
};
line = 0;
......@@ -456,20 +379,8 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[])
xtables_globals.program_version);
exit(1);
}
#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS)
init_extensions();
init_extensions4();
#endif
if (nft_init(&h, xtables_ipv4) < 0) {
fprintf(stderr, "%s/%s Failed to initialize nft: %s\n",
xtables_globals.program_name,
xtables_globals.program_version,
strerror(errno));
exit(EXIT_FAILURE);
}
while ((c = getopt_long(argc, argv, "bcvthnM:T:46", options, NULL)) != -1) {
while ((c = getopt_long(argc, argv, "bcvVthnM:T:46wW", options, NULL)) != -1) {
switch (c) {
case 'b':
fprintf(stderr, "-b/--binary option is not implemented\n");
......@@ -480,13 +391,16 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[])
case 'v':
verbose = 1;
break;
case 'V':
printf("%s v%s (nf_tables)\n", prog_name, prog_vers);
exit(0);
case 't':
p.testing = 1;
break;
case 'h':
print_usage("xtables-restore",
IPTABLES_VERSION);
break;
exit(0);
case 'n':
noflush = 1;
break;
......@@ -503,6 +417,15 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[])
h.family = AF_INET6;
xtables_set_nfproto(AF_INET6);
break;
case 'w': /* fallthrough. Ignored by xt-restore */
case 'W':
if (!optarg && xs_has_arg(argc, argv))
optind++;
break;
default:
fprintf(stderr,
"Try `xtables-restore -h' for more information.\n");
exit(1);
}
}
......@@ -520,8 +443,37 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[])
p.in = stdin;
}
switch (family) {
case NFPROTO_IPV4:
case NFPROTO_IPV6: /* fallthough, same table */
tables = xtables_ipv4;
#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS)
init_extensions();
init_extensions4();
#endif
break;
case NFPROTO_ARP:
tables = xtables_arp;
break;
case NFPROTO_BRIDGE:
tables = xtables_bridge;
break;
default:
fprintf(stderr, "Unknown family %d\n", family);
return 1;
}
if (nft_init(&h, tables) < 0) {
fprintf(stderr, "%s/%s Failed to initialize nft: %s\n",
xtables_globals.program_name,
xtables_globals.program_version,
strerror(errno));
exit(EXIT_FAILURE);
}
xtables_restore_parse(&h, &p, &restore_cb, argc, argv);
nft_fini(&h);
fclose(p.in);
return 0;
}
......@@ -537,3 +489,75 @@ int xtables_ip6_restore_main(int argc, char *argv[])
return xtables_restore_main(NFPROTO_IPV6, "ip6tables-restore",
argc, argv);
}
struct nft_xt_restore_cb ebt_restore_cb = {
.chain_list = get_chain_list,
.commit = nft_commit,
.table_new = nft_table_new,
.table_flush = nft_table_flush,
.chain_user_flush = nft_chain_user_flush,
.chain_del = chain_delete,
.do_command = do_commandeb,
.chain_set = nft_chain_set,
.chain_user_add = nft_chain_user_add,
};
static const struct option ebt_restore_options[] = {
{.name = "noflush", .has_arg = 0, .val = 'n'},
{ 0 }
};
int xtables_eb_restore_main(int argc, char *argv[])
{
struct nft_xt_restore_parse p = {
.in = stdin,
};
struct nft_handle h;
int c;
while ((c = getopt_long(argc, argv, "n",
ebt_restore_options, NULL)) != -1) {
switch(c) {
case 'n':
noflush = 1;
break;
default:
fprintf(stderr,
"Usage: ebtables-restore [ --noflush ]\n");
exit(1);
break;
}
}
nft_init_eb(&h, "ebtables-restore");
xtables_restore_parse(&h, &p, &ebt_restore_cb, argc, argv);
nft_fini(&h);
return 0;
}
struct nft_xt_restore_cb arp_restore_cb = {
.chain_list = get_chain_list,
.commit = nft_commit,
.table_new = nft_table_new,
.table_flush = nft_table_flush,
.chain_user_flush = nft_chain_user_flush,
.chain_del = chain_delete,
.do_command = do_commandarp,
.chain_set = nft_chain_set,
.chain_user_add = nft_chain_user_add,
};
int xtables_arp_restore_main(int argc, char *argv[])
{
struct nft_xt_restore_parse p = {
.in = stdin,
};
struct nft_handle h;
nft_init_arp(&h, "arptables-restore");
xtables_restore_parse(&h, &p, &arp_restore_cb, argc, argv);
nft_fini(&h);
return 0;
}
......@@ -14,6 +14,7 @@
#include <string.h>
#include <time.h>
#include <netdb.h>
#include <unistd.h>
#include "libiptc/libiptc.h"
#include "iptables.h"
#include "xtables-multi.h"
......@@ -25,28 +26,33 @@
#include <dlfcn.h>
#endif
#define prog_name xtables_globals.program_name
#define prog_vers xtables_globals.program_version
static bool show_counters = false;
static const struct option options[] = {
{.name = "counters", .has_arg = false, .val = 'c'},
{.name = "version", .has_arg = false, .val = 'V'},
{.name = "dump", .has_arg = false, .val = 'd'},
{.name = "table", .has_arg = true, .val = 't'},
{.name = "modprobe", .has_arg = true, .val = 'M'},
{.name = "file", .has_arg = true, .val = 'f'},
{.name = "ipv4", .has_arg = false, .val = '4'},
{.name = "ipv6", .has_arg = false, .val = '6'},
{NULL},
};
static int
do_output(struct nft_handle *h, const char *tablename, bool counters)
__do_output(struct nft_handle *h, const char *tablename, bool counters)
{
struct nftnl_chain_list *chain_list;
if (!tablename)
return nft_for_each_table(h, do_output, counters);
if (!nft_table_find(h, tablename)) {
printf("Table `%s' does not exist\n", tablename);
if (!nft_is_table_compatible(h, tablename)) {
if (!nft_table_builtin_find(h, tablename))
printf("# Table `%s' is incompatible, use 'nft' tool.\n",
tablename);
return 0;
}
......@@ -61,13 +67,33 @@ do_output(struct nft_handle *h, const char *tablename, bool counters)
/* Dump out chain names first,
* thereby preventing dependency conflicts */
nft_chain_save(h, chain_list, tablename);
nft_rule_save(h, tablename, counters);
nft_rule_save(h, tablename, counters ? 0 : FMT_NOCOUNTS);
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)
{
int ret;
if (!tablename) {
ret = nft_for_each_table(h, __do_output, counters);
nft_check_xt_legacy(h->family, true);
return !!ret;
}
if (!nft_table_find(h, tablename)) {
printf("Table `%s' does not exist\n", tablename);
return 1;
}
ret = __do_output(h, tablename, counters);
nft_check_xt_legacy(h->family, true);
return ret;
}
/* Format:
......@@ -77,12 +103,14 @@ do_output(struct nft_handle *h, const char *tablename, bool counters)
static int
xtables_save_main(int family, const char *progname, int argc, char *argv[])
{
struct builtin_table *tables;
const char *tablename = NULL;
bool dump = false;
struct nft_handle h = {
.family = family,
};
int c;
FILE *file = NULL;
int ret, c;
xtables_globals.program_name = progname;
c = xtables_init_all(&xtables_globals, family);
......@@ -92,19 +120,8 @@ xtables_save_main(int family, const char *progname, int argc, char *argv[])
xtables_globals.program_version);
exit(1);
}
#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS)
init_extensions();
init_extensions4();
#endif
if (nft_init(&h, xtables_ipv4) < 0) {
fprintf(stderr, "%s/%s Failed to initialize nft: %s\n",
xtables_globals.program_name,
xtables_globals.program_version,
strerror(errno));
exit(EXIT_FAILURE);
}
while ((c = getopt_long(argc, argv, "bcdt:M:46", options, NULL)) != -1) {
while ((c = getopt_long(argc, argv, "bcdt:M:f:46V", options, NULL)) != -1) {
switch (c) {
case 'b':
fprintf(stderr, "-b/--binary option is not implemented\n");
......@@ -120,6 +137,21 @@ xtables_save_main(int family, const char *progname, int argc, char *argv[])
case 'M':
xtables_modprobe_program = optarg;
break;
case 'f':
file = fopen(optarg, "w");
if (file == NULL) {
fprintf(stderr, "Failed to open file, error: %s\n",
strerror(errno));
exit(1);
}
ret = dup2(fileno(file), STDOUT_FILENO);
if (ret == -1) {
fprintf(stderr, "Failed to redirect stdout, error: %s\n",
strerror(errno));
exit(1);
}
fclose(file);
break;
case 'd':
dump = true;
break;
......@@ -130,6 +162,13 @@ xtables_save_main(int family, const char *progname, int argc, char *argv[])
h.family = AF_INET6;
xtables_set_nfproto(AF_INET6);
break;
case 'V':
printf("%s v%s (nf_tables)\n", prog_name, prog_vers);
exit(0);
default:
fprintf(stderr,
"Look at manual page `xtables-save.8' for more information.\n");
exit(1);
}
}
......@@ -138,17 +177,40 @@ xtables_save_main(int family, const char *progname, int argc, char *argv[])
exit(1);
}
if (nft_is_ruleset_compatible(&h) == 1) {
printf("ERROR: You're using nft features that cannot be mapped to iptables, please keep using nft.\n");
switch (family) {
case NFPROTO_IPV4:
case NFPROTO_IPV6: /* fallthough, same table */
#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS)
init_extensions();
init_extensions4();
#endif
tables = xtables_ipv4;
break;
case NFPROTO_ARP:
tables = xtables_arp;
break;
case NFPROTO_BRIDGE:
tables = xtables_bridge;
break;
default:
fprintf(stderr, "Unknown family %d\n", family);
return 1;
}
if (nft_init(&h, tables) < 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 (dump) {
do_output(&h, tablename, show_counters);
ret = do_output(&h, tablename, show_counters);
nft_fini(&h);
if (dump)
exit(0);
}
return !do_output(&h, tablename, show_counters);
return ret;
}
int xtables_ip4_save_main(int argc, char *argv[])
......@@ -160,3 +222,111 @@ 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;
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_dump(h);
if (first) {
now = time(NULL);
printf("# Generated by ebtables-save v%s on %s",
IPTABLES_VERSION, ctime(&now));
first = false;
}
printf("*%s\n", tablename);
/* Dump out chain names first,
* thereby preventing dependency conflicts */
nft_chain_save(h, chain_list, tablename);
nft_rule_save(h, tablename,
FMT_EBT_SAVE | (counters ? 0 : FMT_NOCOUNTS));
printf("\n");
return 0;
}
int xtables_eb_save_main(int argc_, char *argv_[])
{
const char *ctr = getenv("EBTABLES_SAVE_COUNTER");
struct nft_handle h = {
.family = NFPROTO_BRIDGE,
};
int c;
if (ctr && strcmp(ctr, "yes"))
ctr = NULL;
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);
}
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);
}
nft_for_each_table(&h, __ebt_save, !!ctr);
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);
}
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_dump(&h), "filter");
nft_rule_save(&h, "filter", FMT_NOCOUNTS);
printf("\n");
nft_fini(&h);
return 0;
}
......@@ -66,7 +66,6 @@ xtables_main(int family, const char *progname, int argc, char *argv[])
xtables_globals.program_name,
xtables_globals.program_version,
strerror(errno));
nft_fini(&h);
exit(EXIT_FAILURE);
}
......@@ -85,10 +84,9 @@ xtables_main(int family, const char *progname, int argc, char *argv[])
fprintf(stderr, "iptables: %s.\n",
nft_strerror(errno));
}
if (errno == EAGAIN) {
if (errno == EAGAIN)
exit(RESOURCE_PROBLEM);
}
}
exit(!ret);
}
......
.\"
.\" (C) Copyright 2018, Arturo Borrero Gonzalez <arturo@netfilter.org>
.\"
.\" %%%LICENSE_START(GPLv2+_DOC_FULL)
.\" This is free documentation; 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.
.\"
.\" The GNU General Public License's references to "object code"
.\" and "executables" are to be interpreted as the output of any
.\" document formatting or typesetting system, including
.\" intermediate and printed output.
.\"
.\" This manual is distributed in the hope that it will be useful,
.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
.\" GNU General Public License for more details.
.\"
.\" You should have received a copy of the GNU General Public
.\" License along with this manual; if not, see
.\" <http://www.gnu.org/licenses/>.
.\" %%%LICENSE_END
.\"
.TH XTABLES-TRANSLATE 8 "Mar 16, 2018"
.SH NAME
xtables-translate \- translation tools to migrate from iptables to nftables
.SH DESCRIPTION
There is a set of tools to help the system administrator translate a given
ruleset from \fBiptables(8)\fP and \fBip6tables(8)\fP to \fBnftables(8)\fP.
The available commands are:
.IP \[bu] 2
iptables-translate
.IP \[bu]
iptables-restore-translate
.IP \[bu] 2
ip6tables-translate
.IP \[bu]
ip6tables-restore-translate
.SH USAGE
They take as input the original \fBiptables(8)\fP/\fBip6tables(8)\fP syntax and
output the native \fBnftables(8)\fP syntax.
The \fBiptables-restore-translate\fP tool reads a ruleset in the syntax
produced by \fBiptables-save(8)\fP. Likewise, the
\fBip6tables-restore-translate\fP tool reads one produced by
\fBip6tables-save(8)\fP. No ruleset modifications occur, these tools are
text converters only.
The \fBiptables-translate\fP reads a command line as if it was entered to
\fBiptables(8)\fP, and \fBip6tables-translate\fP reads a command like as if it
was entered to \fBip6tables(8)\fP.
.SH EXAMPLES
Basic operation examples.
Single command translation:
.nf
root@machine:~# iptables-translate -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
nft add rule ip filter INPUT tcp dport 22 ct state new counter accept
root@machine:~# ip6tables-translate -A FORWARD -i eth0 -o eth3 -p udp -m multiport --dports 111,222 -j ACCEPT
nft add rule ip6 filter FORWARD iifname eth0 oifname eth3 meta l4proto udp udp dport { 111,222} counter accept
.fi
Whole ruleset translation:
.nf
root@machine:~# iptables-save > save.txt
root@machine:~# cat save.txt
# Generated by iptables-save v1.6.0 on Sat Dec 24 14:26:40 2016
*filter
:INPUT ACCEPT [5166:1752111]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [5058:628693]
-A FORWARD -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
COMMIT
# Completed on Sat Dec 24 14:26:40 2016
root@machine:~# iptables-restore-translate -f save.txt
# Translated by iptables-restore-translate v1.6.0 on Sat Dec 24 14:26:59 2016
add table ip filter
add chain ip filter INPUT { type filter hook input priority 0; }
add chain ip filter FORWARD { type filter hook forward priority 0; }
add chain ip filter OUTPUT { type filter hook output priority 0; }
add rule ip filter FORWARD tcp dport 22 ct state new counter accept
root@machine:~# iptables-restore-translate -f save.txt > ruleset.nft
root@machine:~# nft -f ruleset.nft
root@machine:~# nft list ruleset
table ip filter {
chain INPUT {
type filter hook input priority 0; policy accept;
}
chain FORWARD {
type filter hook forward priority 0; policy accept;
tcp dport ssh ct state new counter packets 0 bytes 0 accept
}
chain OUTPUT {
type filter hook output priority 0; policy accept;
}
}
.fi
.SH LIMITATIONS
Some (few) extensions may be not supported (or fully-supported) for whatever
reason (for example, they were considered obsolete, or we didn't have the time
to work on them).
There are no translations available for \fBebtables(8)\fP and
\fBarptables(8)\fP.
To get up-to-date information about this, please head to
\fBhttps://wiki.nftables.org/\fP.
.SH SEE ALSO
\fBnft(8)\fP, \fBxtables-compat(8)\fP
.SH AUTHORS
The nftables framework is written by the Netfilter project
(https://www.netfilter.org).
This manual page was written by Arturo Borrero Gonzalez
<arturo@netfilter.org>.
This documentation is free/libre under the terms of the GPLv2+.
......@@ -7,11 +7,6 @@
* (at your option) any later version.
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <iptables.h>
#include <time.h>
#include "xtables-multi.h"
#include "nft.h"
......@@ -48,7 +43,7 @@ void xlate_ifname(struct xt_xlate *xl, const char *nftmeta, const char *ifname,
if (iface[ifaclen - 1] == '+')
iface[ifaclen - 1] = '*';
xt_xlate_add(xl, "%s %s%s ", nftmeta, invert ? "!= " : "", iface);
xt_xlate_add(xl, "%s %s\"%s\" ", nftmeta, invert ? "!= " : "", iface);
}
int xlate_action(const struct iptables_command_state *cs, bool goto_set,
......@@ -60,12 +55,13 @@ int xlate_action(const struct iptables_command_state *cs, bool goto_set,
if (cs->target != NULL) {
/* Standard target? */
if (strcmp(cs->jumpto, XTC_LABEL_ACCEPT) == 0)
xt_xlate_add(xl, "accept");
xt_xlate_add(xl, " accept");
else if (strcmp(cs->jumpto, XTC_LABEL_DROP) == 0)
xt_xlate_add(xl, "drop");
xt_xlate_add(xl, " drop");
else if (strcmp(cs->jumpto, XTC_LABEL_RETURN) == 0)
xt_xlate_add(xl, "return");
xt_xlate_add(xl, " return");
else if (cs->target->xlate) {
xt_xlate_add(xl, " ");
struct xt_xlate_tg_params params = {
.ip = (const void *)&cs->fw,
.target = cs->target->t,
......@@ -79,9 +75,9 @@ int xlate_action(const struct iptables_command_state *cs, bool goto_set,
} else if (strlen(cs->jumpto) > 0) {
/* Not standard, then it's a go / jump to chain */
if (goto_set)
xt_xlate_add(xl, "goto %s", cs->jumpto);
xt_xlate_add(xl, " goto %s", cs->jumpto);
else
xt_xlate_add(xl, "jump %s", cs->jumpto);
xt_xlate_add(xl, " jump %s", cs->jumpto);
}
return ret;
......@@ -195,6 +191,8 @@ static int xlate(struct nft_handle *h, struct nft_xt_cmd_parse *p,
}
break;
}
if (!cs->restore && i < args->s.naddrs - 1)
printf("nft ");
}
return ret;
......@@ -234,9 +232,8 @@ static int do_command_xlate(struct nft_handle *h, int argc, char *argv[],
switch (p.command) {
case CMD_APPEND:
ret = 1;
if (!xlate(h, &p, &cs, &args, true, nft_rule_xlate_add)) {
if (!xlate(h, &p, &cs, &args, true, nft_rule_xlate_add))
print_ipt_cmd(argc, argv);
}
break;
case CMD_DELETE:
break;
......@@ -248,9 +245,8 @@ static int do_command_xlate(struct nft_handle *h, int argc, char *argv[],
break;
case CMD_INSERT:
ret = 1;
if (!xlate(h, &p, &cs, &args, false, nft_rule_xlate_add)) {
if (!xlate(h, &p, &cs, &args, false, nft_rule_xlate_add))
print_ipt_cmd(argc, argv);
}
break;
case CMD_FLUSH:
if (p.chain) {
......@@ -328,6 +324,7 @@ static void print_usage(const char *name, const char *version)
static const struct option options[] = {
{ .name = "help", .has_arg = false, .val = 'h' },
{ .name = "file", .has_arg = true, .val = 'f' },
{ .name = "version", .has_arg = false, .val = 'V' },
{ NULL },
};
......@@ -348,27 +345,55 @@ static void xlate_table_new(struct nft_handle *h, const char *table)
printf("add table %s %s\n", family2str[h->family], table);
}
static int get_hook_prio(const char *table, const char *chain)
{
int prio = 0;
if (strcmp("nat", table) == 0) {
if (strcmp(chain, "PREROUTING") == 0)
prio = NF_IP_PRI_NAT_DST;
if (strcmp(chain, "INPUT") == 0)
prio = NF_IP_PRI_NAT_SRC;
if (strcmp(chain, "OUTPUT") == 0)
prio = NF_IP_PRI_NAT_DST;
if (strcmp(chain, "POSTROUTING") == 0)
prio = NF_IP_PRI_NAT_SRC;
} else if (strcmp("mangle", table) == 0) {
prio = NF_IP_PRI_MANGLE;
} else if (strcmp("raw", table) == 0) {
prio = NF_IP_PRI_RAW;
} else if (strcmp(chain, "security") == 0) {
prio = NF_IP_PRI_SECURITY;
}
return prio;
}
static int xlate_chain_set(struct nft_handle *h, const char *table,
const char *chain, const char *policy,
const struct xt_counters *counters)
{
const char *type = "filter";
int prio;
if (strcmp(table, "nat") == 0)
type = "nat";
else if (strcmp(table, "mangle") == 0 && strcmp(chain, "OUTPUT") == 0)
type = "route";
printf("add chain %s %s %s { type %s ",
family2str[h->family], table, chain, type);
prio = get_hook_prio(table, chain);
if (strcmp(chain, "PREROUTING") == 0)
printf("hook prerouting priority 0; ");
printf("hook prerouting priority %d; ", prio);
else if (strcmp(chain, "INPUT") == 0)
printf("hook input priority 0; ");
printf("hook input priority %d; ", prio);
else if (strcmp(chain, "FORWARD") == 0)
printf("hook forward priority 0; ");
printf("hook forward priority %d; ", prio);
else if (strcmp(chain, "OUTPUT") == 0)
printf("hook output priority 0; ");
printf("hook output priority %d; ", prio);
else if (strcmp(chain, "POSTROUTING") == 0)
printf("hook postrouting priority 0; ");
printf("hook postrouting priority %d; ", prio);
if (strcmp(policy, "ACCEPT") == 0)
printf("policy accept; ");
......@@ -379,6 +404,14 @@ static int xlate_chain_set(struct nft_handle *h, const char *table,
return 1;
}
static int dummy_compat_rev(const char *name, uint8_t rev, int opt)
{
/* Avoid querying the kernel - it's not needed when just translating
* rules and not even possible when running as unprivileged user.
*/
return 1;
}
static struct nft_xt_restore_cb cb_xlate = {
.table_new = xlate_table_new,
.chain_set = xlate_chain_set,
......@@ -388,37 +421,66 @@ static struct nft_xt_restore_cb cb_xlate = {
.abort = commit,
};
static int xtables_xlate_main(int family, const char *progname, int argc,
char *argv[])
static int xtables_xlate_main_common(struct nft_handle *h,
int family,
const char *progname)
{
struct builtin_table *tables;
int ret;
char *table = "filter";
struct nft_handle h = {
.family = family,
};
xtables_globals.program_name = progname;
xtables_globals.compat_rev = dummy_compat_rev;
ret = xtables_init_all(&xtables_globals, family);
if (ret < 0) {
fprintf(stderr, "%s/%s Failed to initialize xtables\n",
xtables_globals.program_name,
xtables_globals.program_version);
exit(1);
return 1;
}
switch (family) {
case NFPROTO_IPV4:
case NFPROTO_IPV6: /* fallthrough: same table */
#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS)
init_extensions();
init_extensions4();
#endif
tables = xtables_ipv4;
break;
case NFPROTO_ARP:
tables = xtables_arp;
break;
case NFPROTO_BRIDGE:
tables = xtables_bridge;
break;
default:
fprintf(stderr, "Unknown family %d\n", family);
return 1;
}
if (nft_init(&h, xtables_ipv4) < 0) {
if (nft_init(h, tables) < 0) {
fprintf(stderr, "%s/%s Failed to initialize nft: %s\n",
xtables_globals.program_name,
xtables_globals.program_version,
strerror(errno));
nft_fini(&h);
exit(EXIT_FAILURE);
return 1;
}
return 0;
}
static int xtables_xlate_main(int family, const char *progname, int argc,
char *argv[])
{
int ret;
char *table = "filter";
struct nft_handle h = {
.family = family,
};
ret = xtables_xlate_main_common(&h, family, progname);
if (ret < 0)
exit(EXIT_FAILURE);
ret = do_command_xlate(&h, argc, argv, &table, false);
if (!ret)
fprintf(stderr, "Translation not implemented\n");
......@@ -439,30 +501,12 @@ static int xtables_restore_xlate_main(int family, const char *progname,
time_t now = time(NULL);
int c;
xtables_globals.program_name = progname;
ret = xtables_init_all(&xtables_globals, family);
if (ret < 0) {
fprintf(stderr, "%s/%s Failed to initialize xtables\n",
xtables_globals.program_name,
xtables_globals.program_version);
exit(1);
}
#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS)
init_extensions();
init_extensions4();
#endif
if (nft_init(&h, xtables_ipv4) < 0) {
fprintf(stderr, "%s/%s Failed to initialize nft: %s\n",
xtables_globals.program_name,
xtables_globals.program_version,
strerror(errno));
nft_fini(&h);
ret = xtables_xlate_main_common(&h, family, progname);
if (ret < 0)
exit(EXIT_FAILURE);
}
opterr = 0;
while ((c = getopt_long(argc, argv, "hf:", options, NULL)) != -1) {
while ((c = getopt_long(argc, argv, "hf:V", options, NULL)) != -1) {
switch (c) {
case 'h':
print_usage(argv[0], IPTABLES_VERSION);
......@@ -470,6 +514,9 @@ static int xtables_restore_xlate_main(int family, const char *progname,
case 'f':
file = optarg;
break;
case 'V':
printf("%s v%s\n", argv[0], IPTABLES_VERSION);
exit(0);
}
}
......
......@@ -156,9 +156,9 @@ static const int inverse_for_options[NUMBER_OF_OPT] =
/* -f */ IPT_INV_FRAG,
};
#define opts xtables_globals.opts
#define prog_name xtables_globals.program_name
#define prog_vers xtables_globals.program_version
#define opts xt_params->opts
#define prog_name xt_params->program_name
#define prog_vers xt_params->program_version
static void __attribute__((noreturn))
exit_tryhelp(int status)
......@@ -260,7 +260,7 @@ xtables_exit_error(enum xtables_exittype status, const char *msg, ...)
va_list args;
va_start(args, msg);
fprintf(stderr, "%s v%s: ", prog_name, prog_vers);
fprintf(stderr, "%s v%s (nf_tables): ", prog_name, prog_vers);
vfprintf(stderr, msg, args);
va_end(args);
fprintf(stderr, "\n");
......@@ -363,27 +363,6 @@ parse_rulenumber(const char *rule)
return rulenum;
}
static const char *
parse_target(const char *targetname)
{
const char *ptr;
if (strlen(targetname) < 1)
xtables_error(PARAMETER_PROBLEM,
"Invalid target name (too short)");
if (strlen(targetname) >= XT_EXTENSION_MAXNAMELEN)
xtables_error(PARAMETER_PROBLEM,
"Invalid target name `%s' (%u chars max)",
targetname, XT_EXTENSION_MAXNAMELEN - 1);
for (ptr = targetname; *ptr; ptr++)
if (isspace(*ptr))
xtables_error(PARAMETER_PROBLEM,
"Invalid target name `%s'", targetname);
return targetname;
}
static void
set_option(unsigned int *options, unsigned int option, uint8_t *invflg,
int invert)
......@@ -599,88 +578,7 @@ list_rules(struct nft_handle *h, const char *chain, const char *table,
if (counters)
counters = -1; /* iptables -c format */
nft_rule_list_save(h, chain, table, rulenum, counters);
/* iptables does not return error if rule number not found */
return 1;
}
static void command_jump(struct iptables_command_state *cs)
{
size_t size;
set_option(&cs->options, OPT_JUMP, &cs->fw.ip.invflags, cs->invert);
cs->jumpto = parse_target(optarg);
/* TRY_LOAD (may be chain name) */
cs->target = xtables_find_target(cs->jumpto, XTF_TRY_LOAD);
if (cs->target == NULL)
return;
size = XT_ALIGN(sizeof(struct xt_entry_target))
+ cs->target->size;
cs->target->t = xtables_calloc(1, size);
cs->target->t->u.target_size = size;
if (cs->target->real_name == NULL) {
strcpy(cs->target->t->u.user.name, cs->jumpto);
} else {
/* Alias support for userspace side */
strcpy(cs->target->t->u.user.name, cs->target->real_name);
if (!(cs->target->ext_flags & XTABLES_EXT_ALIAS))
fprintf(stderr, "Notice: The %s target is converted into %s target "
"in rule listing and saving.\n",
cs->jumpto, cs->target->real_name);
}
cs->target->t->u.user.revision = cs->target->revision;
xs_init_target(cs->target);
if (cs->target->x6_options != NULL)
opts = xtables_options_xfrm(xtables_globals.orig_opts, opts,
cs->target->x6_options,
&cs->target->option_offset);
else
opts = xtables_merge_options(xtables_globals.orig_opts, opts,
cs->target->extra_opts,
&cs->target->option_offset);
if (opts == NULL)
xtables_error(OTHER_PROBLEM, "can't alloc memory!");
}
static void command_match(struct iptables_command_state *cs)
{
struct xtables_match *m;
size_t size;
if (cs->invert)
xtables_error(PARAMETER_PROBLEM,
"unexpected ! flag before --match");
m = xtables_find_match(optarg, XTF_LOAD_MUST_SUCCEED, &cs->matches);
size = XT_ALIGN(sizeof(struct xt_entry_match)) + m->size;
m->m = xtables_calloc(1, size);
m->m->u.match_size = size;
if (m->real_name == NULL) {
strcpy(m->m->u.user.name, m->name);
} else {
strcpy(m->m->u.user.name, m->real_name);
if (!(m->ext_flags & XTABLES_EXT_ALIAS))
fprintf(stderr, "Notice: the %s match is converted into %s match "
"in rule listing and saving.\n", m->name, m->real_name);
}
m->m->u.user.revision = m->revision;
xs_init_match(m);
if (m == m->next)
return;
/* Merge options for non-cloned matches */
if (m->x6_options != NULL)
opts = xtables_options_xfrm(xtables_globals.orig_opts, opts,
m->x6_options, &m->option_offset);
else if (m->extra_opts != NULL)
opts = xtables_merge_options(xtables_globals.orig_opts, opts,
m->extra_opts, &m->option_offset);
if (opts == NULL)
xtables_error(OTHER_PROBLEM, "can't alloc memory!");
return nft_rule_list_save(h, chain, table, rulenum, counters);
}
void do_parse(struct nft_handle *h, int argc, char *argv[],
......@@ -744,8 +642,7 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
add_command(&p->command, CMD_DELETE, CMD_NONE,
cs->invert);
p->chain = optarg;
if (optind < argc && argv[optind][0] != '-'
&& argv[optind][0] != '!') {
if (xs_has_arg(argc, argv)) {
p->rulenum = parse_rulenumber(argv[optind++]);
p->command = CMD_DELETE_NUM;
}
......@@ -755,8 +652,7 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
add_command(&p->command, CMD_REPLACE, CMD_NONE,
cs->invert);
p->chain = optarg;
if (optind < argc && argv[optind][0] != '-'
&& argv[optind][0] != '!')
if (xs_has_arg(argc, argv))
p->rulenum = parse_rulenumber(argv[optind++]);
else
xtables_error(PARAMETER_PROBLEM,
......@@ -768,8 +664,7 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
add_command(&p->command, CMD_INSERT, CMD_NONE,
cs->invert);
p->chain = optarg;
if (optind < argc && argv[optind][0] != '-'
&& argv[optind][0] != '!')
if (xs_has_arg(argc, argv))
p->rulenum = parse_rulenumber(argv[optind++]);
else
p->rulenum = 1;
......@@ -780,11 +675,9 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
CMD_ZERO | CMD_ZERO_NUM, cs->invert);
if (optarg)
p->chain = optarg;
else if (optind < argc && argv[optind][0] != '-'
&& argv[optind][0] != '!')
else if (xs_has_arg(argc, argv))
p->chain = argv[optind++];
if (optind < argc && argv[optind][0] != '-'
&& argv[optind][0] != '!')
if (xs_has_arg(argc, argv))
p->rulenum = parse_rulenumber(argv[optind++]);
break;
......@@ -793,11 +686,9 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
CMD_ZERO|CMD_ZERO_NUM, cs->invert);
if (optarg)
p->chain = optarg;
else if (optind < argc && argv[optind][0] != '-'
&& argv[optind][0] != '!')
else if (xs_has_arg(argc, argv))
p->chain = argv[optind++];
if (optind < argc && argv[optind][0] != '-'
&& argv[optind][0] != '!')
if (xs_has_arg(argc, argv))
p->rulenum = parse_rulenumber(argv[optind++]);
break;
......@@ -806,8 +697,7 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
cs->invert);
if (optarg)
p->chain = optarg;
else if (optind < argc && argv[optind][0] != '-'
&& argv[optind][0] != '!')
else if (xs_has_arg(argc, argv))
p->chain = argv[optind++];
break;
......@@ -816,11 +706,9 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
CMD_LIST|CMD_LIST_RULES, cs->invert);
if (optarg)
p->chain = optarg;
else if (optind < argc && argv[optind][0] != '-'
&& argv[optind][0] != '!')
else if (xs_has_arg(argc, argv))
p->chain = argv[optind++];
if (optind < argc && argv[optind][0] != '-'
&& argv[optind][0] != '!') {
if (xs_has_arg(argc, argv)) {
p->rulenum = parse_rulenumber(argv[optind++]);
p->command = CMD_ZERO_NUM;
}
......@@ -845,8 +733,7 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
cs->invert);
if (optarg)
p->chain = optarg;
else if (optind < argc && argv[optind][0] != '-'
&& argv[optind][0] != '!')
else if (xs_has_arg(argc, argv))
p->chain = argv[optind++];
break;
......@@ -854,8 +741,7 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
add_command(&p->command, CMD_RENAME_CHAIN, CMD_NONE,
cs->invert);
p->chain = optarg;
if (optind < argc && argv[optind][0] != '-'
&& argv[optind][0] != '!')
if (xs_has_arg(argc, argv))
p->newname = argv[optind++];
else
xtables_error(PARAMETER_PROBLEM,
......@@ -868,8 +754,7 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
add_command(&p->command, CMD_SET_POLICY, CMD_NONE,
cs->invert);
p->chain = optarg;
if (optind < argc && argv[optind][0] != '-'
&& argv[optind][0] != '!')
if (xs_has_arg(argc, argv))
p->policy = argv[optind++];
else
xtables_error(PARAMETER_PROBLEM,
......@@ -928,11 +813,13 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
set_option(&cs->options, OPT_JUMP, &args->invflags,
cs->invert);
args->goto_set = true;
cs->jumpto = parse_target(optarg);
cs->jumpto = xt_parse_target(optarg);
break;
#endif
case 'j':
set_option(&cs->options, OPT_JUMP, &cs->fw.ip.invflags,
cs->invert);
command_jump(cs);
break;
......@@ -992,6 +879,10 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
if (cs->invert)
xtables_error(PARAMETER_PROBLEM,
"unexpected ! flag before --table");
if (!nft_table_builtin_find(h, optarg))
xtables_error(VERSION_PROBLEM,
"table '%s' does not exist",
optarg);
p->table = optarg;
break;
......@@ -1004,7 +895,7 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
if (cs->invert)
printf("Not %s ;-)\n", prog_vers);
else
printf("%s v%s\n",
printf("%s v%s (nf_tables)\n",
prog_name, prog_vers);
exit(0);
......@@ -1014,15 +905,8 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
"You cannot use `-w' from "
"iptables-restore");
}
if (optarg) {
if (sscanf(optarg, "%i", &wait) != 1)
xtables_error(PARAMETER_PROBLEM,
"wait seconds not numeric");
} else if (optind < argc && argv[optind][0] != '-'
&& argv[optind][0] != '!')
if (sscanf(argv[optind++], "%i", &wait) != 1)
xtables_error(PARAMETER_PROBLEM,
"wait seconds not numeric");
wait = parse_wait_time(argc, argv);
break;
case 'W':
......@@ -1031,14 +915,8 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
"You cannot use `-W' from "
"iptables-restore");
}
if (optarg)
parse_wait_interval(optarg, &wait_interval);
else if (optind < argc &&
argv[optind][0] != '-' &&
argv[optind][0] != '!')
parse_wait_interval(argv[optind++],
&wait_interval);
parse_wait_interval(argc, argv, &wait_interval);
wait_interval_set = true;
break;
......@@ -1058,9 +936,7 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
args->bcnt = strchr(args->pcnt + 1, ',');
if (args->bcnt)
args->bcnt++;
if (!args->bcnt && optind < argc &&
argv[optind][0] != '-' &&
argv[optind][0] != '!')
if (!args->bcnt && xs_has_arg(argc, argv))
args->bcnt = argv[optind++];
if (!args->bcnt)
xtables_error(PARAMETER_PROBLEM,
......@@ -1187,12 +1063,18 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
p->chain);
}
/*
* Contrary to what iptables does, we assume that any jumpto
* is a custom chain jumps (if no target is found). Later on,
* nf_table will spot the error if the chain does not exists.
*/
if (!nft_chain_exists(h, p->table, p->chain))
xtables_error(OTHER_PROBLEM,
"Chain '%s' does not exist", cs->jumpto);
if (!cs->target && strlen(cs->jumpto) > 0 &&
!nft_chain_exists(h, p->table, cs->jumpto))
xtables_error(PARAMETER_PROBLEM,
"Chain '%s' does not exist", cs->jumpto);
}
if (p->command == CMD_NEW_CHAIN &&
nft_chain_exists(h, p->table, p->chain))
xtables_error(OTHER_PROBLEM, "Chain already exists");
}
int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table,
......@@ -1241,10 +1123,12 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table,
cs.options&OPT_VERBOSE, h, false);
break;
case CMD_FLUSH:
ret = nft_rule_flush(h, p.chain, p.table);
ret = nft_rule_flush(h, p.chain, p.table,
cs.options & OPT_VERBOSE);
break;
case CMD_ZERO:
ret = nft_chain_zero_counters(h, p.chain, p.table);
ret = nft_chain_zero_counters(h, p.chain, p.table,
cs.options & OPT_VERBOSE);
break;
case CMD_ZERO_NUM:
ret = nft_rule_zero_counters(h, p.chain, p.table,
......@@ -1253,24 +1137,20 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table,
case CMD_LIST:
case CMD_LIST|CMD_ZERO:
case CMD_LIST|CMD_ZERO_NUM:
if (nft_is_ruleset_compatible(h) == 1) {
printf("ERROR: You're using nft features that cannot be mapped to iptables, please keep using nft.\n");
exit(EXIT_FAILURE);
}
ret = list_entries(h, p.chain, p.table, p.rulenum,
cs.options & OPT_VERBOSE,
cs.options & OPT_NUMERIC,
cs.options & OPT_EXPANDED,
cs.options & OPT_LINENUMBERS);
if (ret && (p.command & CMD_ZERO)) {
ret = nft_chain_zero_counters(h, p.chain,
p.table);
ret = nft_chain_zero_counters(h, p.chain, p.table,
cs.options & OPT_VERBOSE);
}
if (ret && (p.command & CMD_ZERO_NUM)) {
ret = nft_rule_zero_counters(h, p.chain, p.table,
p.rulenum - 1);
}
nft_check_xt_legacy(h->family, false);
break;
case CMD_LIST_RULES:
case CMD_LIST_RULES|CMD_ZERO:
......@@ -1278,28 +1158,27 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table,
ret = list_rules(h, p.chain, p.table, p.rulenum,
cs.options & OPT_VERBOSE);
if (ret && (p.command & CMD_ZERO)) {
ret = nft_chain_zero_counters(h, p.chain,
p.table);
ret = nft_chain_zero_counters(h, p.chain, p.table,
cs.options & OPT_VERBOSE);
}
if (ret && (p.command & CMD_ZERO_NUM)) {
ret = nft_rule_zero_counters(h, p.chain, p.table,
p.rulenum - 1);
}
nft_check_xt_legacy(h->family, false);
break;
case CMD_NEW_CHAIN:
ret = nft_chain_user_add(h, p.chain, p.table);
break;
case CMD_DELETE_CHAIN:
ret = nft_chain_user_del(h, p.chain, p.table);
ret = nft_chain_user_del(h, p.chain, p.table,
cs.options & OPT_VERBOSE);
break;
case CMD_RENAME_CHAIN:
ret = nft_chain_user_rename(h, p.chain, p.table, p.newname);
break;
case CMD_SET_POLICY:
ret = nft_chain_set(h, p.table, p.chain, p.policy, NULL);
if (ret < 0)
xtables_error(PARAMETER_PROBLEM, "Wrong policy `%s'\n",
p.policy);
break;
default:
/* We should never reach this... */
......@@ -1309,6 +1188,8 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table,
*table = p.table;
xtables_rule_matches_free(&cs.matches);
if (cs.target)
free(cs.target->t);
if (h->family == AF_INET) {
free(args.s.addr.v4);
......
# Makefile.in generated by automake 1.14.1 from Makefile.am.
# Makefile.in generated by automake 1.15 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
# Copyright (C) 1994-2014 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
......@@ -18,7 +18,17 @@
VPATH = @srcdir@
am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
......@@ -81,8 +91,6 @@ POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = libipq
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(srcdir)/libipq.pc.in $(top_srcdir)/build-aux/depcomp
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 \
......@@ -90,6 +98,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_linker_flags.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)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES = libipq.pc
......@@ -195,6 +204,8 @@ am__define_uniq_tagged_files = \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/libipq.pc.in \
$(top_srcdir)/build-aux/depcomp
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
pkgdatadir = @pkgdatadir@
ACLOCAL = @ACLOCAL@
......@@ -239,6 +250,7 @@ LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
......@@ -336,6 +348,7 @@ program_transform_name = @program_transform_name@
psdir = @psdir@
regular_CFLAGS = @regular_CFLAGS@
regular_CPPFLAGS = @regular_CPPFLAGS@
runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
......@@ -371,7 +384,6 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libipq/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnu libipq/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
......@@ -740,6 +752,8 @@ uninstall-man: uninstall-man3
tags tags-am uninstall uninstall-am uninstall-libLTLIBRARIES \
uninstall-man uninstall-man3 uninstall-pkgconfigDATA
.PRECIOUS: Makefile
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
......
# Makefile.in generated by automake 1.14.1 from Makefile.am.
# Makefile.in generated by automake 1.15 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
# Copyright (C) 1994-2014 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
......@@ -18,7 +18,17 @@
VPATH = @srcdir@
am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
......@@ -81,9 +91,6 @@ POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = libiptc
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(srcdir)/libiptc.pc.in $(srcdir)/libip4tc.pc.in \
$(srcdir)/libip6tc.pc.in $(top_srcdir)/build-aux/depcomp
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 \
......@@ -91,6 +98,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_linker_flags.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)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES = libiptc.pc libip4tc.pc libip6tc.pc
......@@ -209,6 +217,9 @@ am__define_uniq_tagged_files = \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/libip4tc.pc.in \
$(srcdir)/libip6tc.pc.in $(srcdir)/libiptc.pc.in \
$(top_srcdir)/build-aux/depcomp
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
pkgdatadir = @pkgdatadir@
ACLOCAL = @ACLOCAL@
......@@ -253,6 +264,7 @@ LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
......@@ -350,6 +362,7 @@ program_transform_name = @program_transform_name@
psdir = @psdir@
regular_CFLAGS = @regular_CFLAGS@
regular_CPPFLAGS = @regular_CPPFLAGS@
runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
......@@ -386,7 +399,6 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libiptc/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnu libiptc/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
......@@ -719,6 +731,8 @@ uninstall-am: uninstall-libLTLIBRARIES uninstall-pkgconfigDATA
pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \
uninstall-libLTLIBRARIES uninstall-pkgconfigDATA
.PRECIOUS: Makefile
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
......
......@@ -1115,8 +1115,9 @@ static inline int iptcc_compile_rule (struct xtc_handle *h, STRUCT_REPLACE *repl
STRUCT_STANDARD_TARGET *t;
t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry);
/* memset for memcmp convenience on delete/replace */
memset(t->target.u.user.name, 0, FUNCTION_MAXNAMELEN);
memset(t->target.u.user.name, 0, XT_EXTENSION_MAXNAMELEN);
strcpy(t->target.u.user.name, STANDARD_TARGET);
t->target.u.user.revision = 0;
/* Jumps can only happen to builtin chains, so we
* can safely assume that they always have a header */
t->verdict = r->jump->head_offset + IPTCB_CHAIN_START_SIZE;
......@@ -1149,7 +1150,8 @@ static int iptcc_compile_chain(struct xtc_handle *h, STRUCT_REPLACE *repl, struc
strcpy(head->name.target.u.user.name, ERROR_TARGET);
head->name.target.u.target_size =
ALIGN(sizeof(struct xt_error_target));
strcpy(head->name.errorname, c->name);
strncpy(head->name.errorname, c->name, XT_FUNCTION_MAXNAMELEN);
head->name.errorname[XT_FUNCTION_MAXNAMELEN - 1] = '\0';
} else {
repl->hook_entry[c->hooknum-1] = c->head_offset;
repl->underflow[c->hooknum-1] = c->foot_offset;
......@@ -1269,7 +1271,7 @@ static int iptcc_compile_table(struct xtc_handle *h, STRUCT_REPLACE *repl)
/* Allocate handle of given size */
static struct xtc_handle *
alloc_handle(const char *tablename, unsigned int size, unsigned int num_rules)
alloc_handle(STRUCT_GETINFO *infop)
{
struct xtc_handle *h;
......@@ -1280,14 +1282,14 @@ alloc_handle(const char *tablename, unsigned int size, unsigned int num_rules)
}
memset(h, 0, sizeof(*h));
INIT_LIST_HEAD(&h->chains);
strcpy(h->info.name, tablename);
strcpy(h->info.name, infop->name);
h->entries = malloc(sizeof(STRUCT_GET_ENTRIES) + size);
h->entries = malloc(sizeof(STRUCT_GET_ENTRIES) + infop->size);
if (!h->entries)
goto out_free_handle;
strcpy(h->entries->name, tablename);
h->entries->size = size;
strcpy(h->entries->name, infop->name);
h->entries->size = infop->size;
return h;
......@@ -1336,8 +1338,8 @@ retry:
DEBUGP("valid_hooks=0x%08x, num_entries=%u, size=%u\n",
info.valid_hooks, info.num_entries, info.size);
if ((h = alloc_handle(info.name, info.size, info.num_entries))
== NULL) {
h = alloc_handle(&info);
if (h == NULL) {
close(sockfd);
return NULL;
}
......@@ -1675,8 +1677,9 @@ iptcc_standard_map(struct rule_head *r, int verdict)
return 0;
}
/* memset for memcmp convenience on delete/replace */
memset(t->target.u.user.name, 0, FUNCTION_MAXNAMELEN);
memset(t->target.u.user.name, 0, XT_EXTENSION_MAXNAMELEN);
strcpy(t->target.u.user.name, STANDARD_TARGET);
t->target.u.user.revision = 0;
t->verdict = verdict;
r->type = IPTCC_R_STANDARD;
......@@ -1686,7 +1689,8 @@ iptcc_standard_map(struct rule_head *r, int verdict)
static int
iptcc_map_target(struct xtc_handle *const handle,
struct rule_head *r)
struct rule_head *r,
bool dry_run)
{
STRUCT_ENTRY *e = r->entry;
STRUCT_ENTRY_TARGET *t = GET_TARGET(e);
......@@ -1731,6 +1735,7 @@ iptcc_map_target(struct xtc_handle *const handle,
0,
FUNCTION_MAXNAMELEN - 1 - strlen(t->u.user.name));
r->type = IPTCC_R_MODULE;
if (!dry_run)
set_changed(handle);
return 1;
}
......@@ -1781,7 +1786,7 @@ TC_INSERT_ENTRY(const IPT_CHAINLABEL chain,
memcpy(r->entry, e, e->next_offset);
r->counter_map.maptype = COUNTER_MAP_SET;
if (!iptcc_map_target(handle, r)) {
if (!iptcc_map_target(handle, r, false)) {
free(r);
return 0;
}
......@@ -1831,7 +1836,7 @@ TC_REPLACE_ENTRY(const IPT_CHAINLABEL chain,
memcpy(r->entry, e, e->next_offset);
r->counter_map.maptype = COUNTER_MAP_SET;
if (!iptcc_map_target(handle, r)) {
if (!iptcc_map_target(handle, r, false)) {
free(r);
return 0;
}
......@@ -1870,7 +1875,7 @@ TC_APPEND_ENTRY(const IPT_CHAINLABEL chain,
memcpy(r->entry, e, e->next_offset);
r->counter_map.maptype = COUNTER_MAP_SET;
if (!iptcc_map_target(handle, r)) {
if (!iptcc_map_target(handle, r, false)) {
DEBUGP("unable to map target of rule for chain `%s'\n", chain);
free(r);
return 0;
......@@ -1976,7 +1981,7 @@ static int delete_entry(const IPT_CHAINLABEL chain, const STRUCT_ENTRY *origfw,
memcpy(r->entry, origfw, origfw->next_offset);
r->counter_map.maptype = COUNTER_MAP_NOMAP;
if (!iptcc_map_target(handle, r)) {
if (!iptcc_map_target(handle, r, dry_run)) {
DEBUGP("unable to map target of rule for chain `%s'\n", chain);
free(r);
return 0;
......
......@@ -4,7 +4,7 @@ AM_CFLAGS = ${regular_CFLAGS}
AM_CPPFLAGS = ${regular_CPPFLAGS} -I${top_builddir}/include -I${top_srcdir}/include -I${top_srcdir}/iptables ${kinclude_CPPFLAGS}
lib_LTLIBRARIES = libxtables.la
libxtables_la_SOURCES = xtables.c xtoptions.c
libxtables_la_SOURCES = xtables.c xtoptions.c getethertype.c
libxtables_la_LDFLAGS = -version-info ${libxtables_vcurrent}:0:${libxtables_vage}
libxtables_la_LIBADD =
if ENABLE_STATIC
......
# Makefile.in generated by automake 1.14.1 from Makefile.am.
# Makefile.in generated by automake 1.15 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
# Copyright (C) 1994-2014 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
......@@ -17,7 +17,17 @@
# -*- Makefile -*-
VPATH = @srcdir@
am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
......@@ -84,8 +94,6 @@ host_triplet = @host@
@ENABLE_STATIC_TRUE@am__append_1 = -lm ${libnetfilter_conntrack_LIBS}
@ENABLE_SHARED_TRUE@am__append_2 = -ldl
subdir = libxtables
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(top_srcdir)/build-aux/depcomp
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 \
......@@ -93,6 +101,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_linker_flags.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)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
......@@ -131,7 +140,7 @@ am__DEPENDENCIES_1 =
libxtables_la_DEPENDENCIES = $(am__DEPENDENCIES_2) \
$(am__DEPENDENCIES_1)
am_libxtables_la_OBJECTS = libxtables_la-xtables.lo \
libxtables_la-xtoptions.lo
libxtables_la-xtoptions.lo libxtables_la-getethertype.lo
libxtables_la_OBJECTS = $(am_libxtables_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
......@@ -200,6 +209,8 @@ am__define_uniq_tagged_files = \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
am__DIST_COMMON = $(srcdir)/Makefile.in \
$(top_srcdir)/build-aux/depcomp
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
pkgdatadir = @pkgdatadir@
ACLOCAL = @ACLOCAL@
......@@ -244,6 +255,7 @@ LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
......@@ -341,6 +353,7 @@ program_transform_name = @program_transform_name@
psdir = @psdir@
regular_CFLAGS = @regular_CFLAGS@
regular_CPPFLAGS = @regular_CPPFLAGS@
runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
......@@ -353,7 +366,7 @@ xtlibdir = @xtlibdir@
AM_CFLAGS = ${regular_CFLAGS}
AM_CPPFLAGS = ${regular_CPPFLAGS} -I${top_builddir}/include -I${top_srcdir}/include -I${top_srcdir}/iptables ${kinclude_CPPFLAGS}
lib_LTLIBRARIES = libxtables.la
libxtables_la_SOURCES = xtables.c xtoptions.c
libxtables_la_SOURCES = xtables.c xtoptions.c getethertype.c
libxtables_la_LDFLAGS = -version-info ${libxtables_vcurrent}:0:${libxtables_vage}
libxtables_la_LIBADD = $(am__append_1) $(am__append_2)
@ENABLE_SHARED_FALSE@libxtables_la_CFLAGS = ${AM_CFLAGS} -DNO_SHARED_LIBS=1
......@@ -374,7 +387,6 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libxtables/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnu libxtables/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
......@@ -437,6 +449,7 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxtables_la-getethertype.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxtables_la-xtables.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxtables_la-xtoptions.Plo@am__quote@
......@@ -475,6 +488,13 @@ libxtables_la-xtoptions.lo: xtoptions.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libxtables_la_CFLAGS) $(CFLAGS) -c -o libxtables_la-xtoptions.lo `test -f 'xtoptions.c' || echo '$(srcdir)/'`xtoptions.c
libxtables_la-getethertype.lo: getethertype.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libxtables_la_CFLAGS) $(CFLAGS) -MT libxtables_la-getethertype.lo -MD -MP -MF $(DEPDIR)/libxtables_la-getethertype.Tpo -c -o libxtables_la-getethertype.lo `test -f 'getethertype.c' || echo '$(srcdir)/'`getethertype.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libxtables_la-getethertype.Tpo $(DEPDIR)/libxtables_la-getethertype.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='getethertype.c' object='libxtables_la-getethertype.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libxtables_la_CFLAGS) $(CFLAGS) -c -o libxtables_la-getethertype.lo `test -f 'getethertype.c' || echo '$(srcdir)/'`getethertype.c
mostlyclean-libtool:
-rm -f *.lo
......@@ -687,6 +707,8 @@ uninstall-am: uninstall-libLTLIBRARIES
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
tags tags-am uninstall uninstall-am uninstall-libLTLIBRARIES
.PRECIOUS: Makefile
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
......
......@@ -42,27 +42,26 @@
#include <string.h>
#include <netinet/ether.h>
#include <net/ethernet.h>
#include <ebtables/ethernetdb.h>
#include <xtables.h>
#define MAXALIASES 35
static FILE *etherf = NULL;
static char line[BUFSIZ + 1];
static struct ethertypeent et_ent;
static struct xt_ethertypeent et_ent;
static char *ethertype_aliases[MAXALIASES];
static int ethertype_stayopen;
void setethertypeent(int f)
static void setethertypeent(int f)
{
if (etherf == NULL)
etherf = fopen(_PATH_ETHERTYPES, "r");
etherf = fopen(XT_PATH_ETHERTYPES, "r");
else
rewind(etherf);
ethertype_stayopen |= f;
}
void endethertypeent(void)
static void endethertypeent(void)
{
if (etherf) {
fclose(etherf);
......@@ -71,14 +70,15 @@ void endethertypeent(void)
ethertype_stayopen = 0;
}
struct ethertypeent *getethertypeent(void)
static struct xt_ethertypeent *getethertypeent(void)
{
char *e;
char *endptr;
register char *cp, **q;
if (etherf == NULL
&& (etherf = fopen(_PATH_ETHERTYPES, "r")) == NULL) {
&& (etherf = fopen(XT_PATH_ETHERTYPES, "r")) == NULL) {
return (NULL);
}
......@@ -127,10 +127,9 @@ again:
return (&et_ent);
}
struct ethertypeent *getethertypebyname(const char *name)
struct xt_ethertypeent *xtables_getethertypebyname(const char *name)
{
register struct ethertypeent *e;
register struct xt_ethertypeent *e;
register char **cp;
setethertypeent(ethertype_stayopen);
......@@ -147,9 +146,9 @@ found:
return (e);
}
struct ethertypeent *getethertypebynumber(int type)
struct xt_ethertypeent *xtables_getethertypebynumber(int type)
{
register struct ethertypeent *e;
register struct xt_ethertypeent *e;
setethertypeent(ethertype_stayopen);
while ((e = getethertypeent()) != NULL)
......
......@@ -21,6 +21,7 @@
#include <fcntl.h>
#include <inttypes.h>
#include <netdb.h>
#include <spawn.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
......@@ -119,8 +120,10 @@ struct option *xtables_merge_options(struct option *orig_opts,
* Since @oldopts also has @orig_opts already (and does so at the
* start), skip these entries.
*/
if (oldopts != NULL) {
oldopts += num_oold;
num_old -= num_oold;
}
merge = malloc(sizeof(*mp) * (num_oold + num_old + num_new + 1));
if (merge == NULL)
......@@ -139,8 +142,10 @@ struct option *xtables_merge_options(struct option *orig_opts,
mp->val += *option_offset;
/* Third, the old options */
if (oldopts != NULL) {
memcpy(mp, oldopts, sizeof(*mp) * num_old);
mp += num_old;
}
xtables_free_opts(0);
/* Clear trailing entry */
......@@ -198,8 +203,8 @@ struct xtables_match *xtables_matches;
struct xtables_target *xtables_targets;
/* Fully register a match/target which was previously partially registered. */
static void xtables_fully_register_pending_match(struct xtables_match *me);
static void xtables_fully_register_pending_target(struct xtables_target *me);
static bool xtables_fully_register_pending_match(struct xtables_match *me);
static bool xtables_fully_register_pending_target(struct xtables_target *me);
void xtables_init(void)
{
......@@ -358,6 +363,7 @@ int xtables_insmod(const char *modname, const char *modprobe, bool quiet)
char *buf = NULL;
char *argv[4];
int status;
pid_t pid;
/* If they don't explicitly set it, read out of kernel */
if (!modprobe) {
......@@ -378,18 +384,11 @@ int xtables_insmod(const char *modname, const char *modprobe, bool quiet)
*/
fflush(stdout);
switch (vfork()) {
case 0:
execv(argv[0], argv);
/* not usually reached */
_exit(1);
case -1:
if (posix_spawn(&pid, argv[0], NULL, NULL, argv, NULL)) {
free(buf);
return -1;
default: /* parent */
wait(&status);
} else {
waitpid(pid, &status, 0);
}
free(buf);
......@@ -488,7 +487,7 @@ bool xtables_strtoui(const char *s, char **end, unsigned int *value,
bool ret;
ret = xtables_strtoul(s, end, &v, min, max);
if (value != NULL)
if (ret && value != NULL)
*value = v;
return ret;
}
......@@ -538,17 +537,17 @@ void xtables_parse_interface(const char *arg, char *vianame,
} else {
/* Include nul-terminator in match */
memset(mask, 0xFF, vialen + 1);
}
/* Display warning on invalid characters */
for (i = 0; vianame[i]; i++) {
if (vianame[i] == '/' ||
vianame[i] == ' ') {
fprintf(stderr,
"Warning: weird character in interface"
if (vianame[i] == '/' || vianame[i] == ' ') {
fprintf(stderr, "Warning: weird character in interface"
" `%s' ('/' and ' ' are not allowed by the kernel).\n",
vianame);
break;
}
}
}
}
#ifndef NO_SHARED_LIBS
......@@ -638,11 +637,11 @@ xtables_find_match(const char *name, enum xtables_tryload tryload,
if (extension_cmp(name, (*dptr)->name, (*dptr)->family)) {
ptr = *dptr;
*dptr = (*dptr)->next;
ptr->next = NULL;
xtables_fully_register_pending_match(ptr);
} else {
dptr = &((*dptr)->next);
if (xtables_fully_register_pending_match(ptr))
continue;
*dptr = ptr;
}
dptr = &((*dptr)->next);
}
for (ptr = xtables_matches; ptr; ptr = ptr->next) {
......@@ -709,6 +708,27 @@ xtables_find_match(const char *name, enum xtables_tryload tryload,
return ptr;
}
struct xtables_match *
xtables_find_match_revision(const char *name, enum xtables_tryload tryload,
struct xtables_match *match, int revision)
{
if (!match) {
match = xtables_find_match(name, tryload, NULL);
if (!match)
return NULL;
}
while (1) {
if (match->revision == revision)
return match;
match = match->next;
if (!match)
return NULL;
if (!extension_cmp(name, match->name, match->family))
return NULL;
}
}
struct xtables_target *
xtables_find_target(const char *name, enum xtables_tryload tryload)
{
......@@ -728,11 +748,11 @@ xtables_find_target(const char *name, enum xtables_tryload tryload)
if (extension_cmp(name, (*dptr)->name, (*dptr)->family)) {
ptr = *dptr;
*dptr = (*dptr)->next;
ptr->next = NULL;
xtables_fully_register_pending_target(ptr);
} else {
dptr = &((*dptr)->next);
if (xtables_fully_register_pending_target(ptr))
continue;
*dptr = ptr;
}
dptr = &((*dptr)->next);
}
for (ptr = xtables_targets; ptr; ptr = ptr->next) {
......@@ -769,6 +789,27 @@ xtables_find_target(const char *name, enum xtables_tryload tryload)
return ptr;
}
struct xtables_target *
xtables_find_target_revision(const char *name, enum xtables_tryload tryload,
struct xtables_target *target, int revision)
{
if (!target) {
target = xtables_find_target(name, tryload);
if (!target)
return NULL;
}
while (1) {
if (target->revision == revision)
return target;
target = target->next;
if (!target)
return NULL;
if (!extension_cmp(name, target->name, target->family))
return NULL;
}
}
int xtables_compatible_revision(const char *name, uint8_t revision, int opt)
{
struct xt_get_revision rev;
......@@ -846,11 +887,25 @@ static void xtables_check_options(const char *name, const struct option *opt)
void xtables_register_match(struct xtables_match *me)
{
if (me->next) {
fprintf(stderr, "%s: match \"%s\" already registered\n",
xt_params->program_name, me->name);
exit(1);
}
if (me->version == NULL) {
fprintf(stderr, "%s: match %s<%u> is missing a version\n",
xt_params->program_name, me->name, me->revision);
exit(1);
}
if (me->size != XT_ALIGN(me->size)) {
fprintf(stderr, "%s: match \"%s\" has invalid size %u.\n",
xt_params->program_name, me->name,
(unsigned int)me->size);
exit(1);
}
if (strcmp(me->version, XTABLES_VERSION) != 0) {
fprintf(stderr, "%s: match \"%s\" has version \"%s\", "
"but \"%s\" is required.\n",
......@@ -865,6 +920,12 @@ void xtables_register_match(struct xtables_match *me)
exit(1);
}
if (me->real_name && strlen(me->real_name) >= XT_EXTENSION_MAXNAMELEN) {
fprintf(stderr, "%s: match `%s' has invalid real name\n",
xt_params->program_name, me->real_name);
exit(1);
}
if (me->family >= NPROTO) {
fprintf(stderr,
"%s: BUG: match %s has invalid protocol family\n",
......@@ -877,9 +938,6 @@ void xtables_register_match(struct xtables_match *me)
if (me->extra_opts != NULL)
xtables_check_options(me->name, me->extra_opts);
/* ignore not interested match */
if (me->family != afinfo->family && me->family != AF_UNSPEC)
return;
/* place on linked list of matches pending full registration */
me->next = xtables_pending_matches;
......@@ -947,14 +1005,19 @@ static int xtables_target_prefer(const struct xtables_target *a,
b->revision, b->family);
}
static void xtables_fully_register_pending_match(struct xtables_match *me)
static bool xtables_fully_register_pending_match(struct xtables_match *me)
{
struct xtables_match **i, *old;
struct xtables_match **i, *old, *pos = NULL;
const char *rn;
int compare;
/* See if new match can be used. */
rn = (me->real_name != NULL) ? me->real_name : me->name;
if (!compatible_match_revision(rn, me->revision))
return false;
old = xtables_find_match(me->name, XTF_DURING_LOAD, NULL);
if (old) {
while (old) {
compare = xtables_match_prefer(old, me);
if (compare == 0) {
fprintf(stderr,
......@@ -965,34 +1028,47 @@ static void xtables_fully_register_pending_match(struct xtables_match *me)
/* Now we have two (or more) options, check compatibility. */
rn = (old->real_name != NULL) ? old->real_name : old->name;
if (compare > 0 &&
compatible_match_revision(rn, old->revision))
return;
/* See if new match can be used. */
rn = (me->real_name != NULL) ? me->real_name : me->name;
if (!compatible_match_revision(rn, me->revision))
return;
if (compare > 0) {
/* Kernel tells old isn't compatible anymore??? */
if (!compatible_match_revision(rn, old->revision)) {
/* Delete old one. */
for (i = &xtables_matches; *i!=old; i = &(*i)->next);
for (i = &xtables_matches; *i != old;)
i = &(*i)->next;
*i = old->next;
}
pos = old;
old = old->next;
if (!old)
break;
if (!extension_cmp(me->name, old->name, old->family))
break;
continue;
}
if (me->size != XT_ALIGN(me->size)) {
fprintf(stderr, "%s: match `%s' has invalid size %u.\n",
xt_params->program_name, me->name,
(unsigned int)me->size);
exit(1);
/* Found right old */
pos = old;
break;
}
if (!pos) {
/* Append to list. */
for (i = &xtables_matches; *i; i = &(*i)->next);
me->next = NULL;
} else if (compare < 0) {
/* Prepend it */
for (i = &xtables_matches; *i != pos; i = &(*i)->next);
} else if (compare > 0) {
/* Append it */
i = &pos->next;
pos = pos->next;
}
me->next = pos;
*i = me;
me->m = NULL;
me->mflags = 0;
return true;
}
void xtables_register_matches(struct xtables_match *match, unsigned int n)
......@@ -1004,11 +1080,25 @@ void xtables_register_matches(struct xtables_match *match, unsigned int n)
void xtables_register_target(struct xtables_target *me)
{
if (me->next) {
fprintf(stderr, "%s: target \"%s\" already registered\n",
xt_params->program_name, me->name);
exit(1);
}
if (me->version == NULL) {
fprintf(stderr, "%s: target %s<%u> is missing a version\n",
xt_params->program_name, me->name, me->revision);
exit(1);
}
if (me->size != XT_ALIGN(me->size)) {
fprintf(stderr, "%s: target \"%s\" has invalid size %u.\n",
xt_params->program_name, me->name,
(unsigned int)me->size);
exit(1);
}
if (strcmp(me->version, XTABLES_VERSION) != 0) {
fprintf(stderr, "%s: target \"%s\" has version \"%s\", "
"but \"%s\" is required.\n",
......@@ -1023,6 +1113,12 @@ void xtables_register_target(struct xtables_target *me)
exit(1);
}
if (me->real_name && strlen(me->real_name) >= XT_EXTENSION_MAXNAMELEN) {
fprintf(stderr, "%s: target `%s' has invalid real name\n",
xt_params->program_name, me->real_name);
exit(1);
}
if (me->family >= NPROTO) {
fprintf(stderr,
"%s: BUG: target %s has invalid protocol family\n",
......@@ -1044,16 +1140,21 @@ void xtables_register_target(struct xtables_target *me)
xtables_pending_targets = me;
}
static void xtables_fully_register_pending_target(struct xtables_target *me)
static bool xtables_fully_register_pending_target(struct xtables_target *me)
{
struct xtables_target *old;
struct xtables_target **i, *old, *pos = NULL;
const char *rn;
int compare;
old = xtables_find_target(me->name, XTF_DURING_LOAD);
if (old) {
struct xtables_target **i;
if (strcmp(me->name, "standard") != 0) {
/* See if new target can be used. */
rn = (me->real_name != NULL) ? me->real_name : me->name;
if (!compatible_target_revision(rn, me->revision))
return false;
}
old = xtables_find_target(me->name, XTF_DURING_LOAD);
while (old) {
compare = xtables_target_prefer(old, me);
if (compare == 0) {
fprintf(stderr,
......@@ -1064,32 +1165,48 @@ static void xtables_fully_register_pending_target(struct xtables_target *me)
/* Now we have two (or more) options, check compatibility. */
rn = (old->real_name != NULL) ? old->real_name : old->name;
if (compare > 0 &&
compatible_target_revision(rn, old->revision))
return;
/* See if new target can be used. */
rn = (me->real_name != NULL) ? me->real_name : me->name;
if (!compatible_target_revision(rn, me->revision))
return;
if (compare > 0) {
/* Kernel tells old isn't compatible anymore??? */
if (!compatible_target_revision(rn, old->revision)) {
/* Delete old one. */
for (i = &xtables_targets; *i!=old; i = &(*i)->next);
for (i = &xtables_targets; *i != old;)
i = &(*i)->next;
*i = old->next;
}
pos = old;
old = old->next;
if (!old)
break;
if (!extension_cmp(me->name, old->name, old->family))
break;
continue;
}
if (me->size != XT_ALIGN(me->size)) {
fprintf(stderr, "%s: target `%s' has invalid size %u.\n",
xt_params->program_name, me->name,
(unsigned int)me->size);
exit(1);
/* Found right old */
pos = old;
break;
}
if (!pos) {
/* Prepend to list. */
me->next = xtables_targets;
xtables_targets = me;
i = &xtables_targets;
pos = xtables_targets;
} else if (compare < 0) {
/* Prepend it */
for (i = &xtables_targets; *i != pos; i = &(*i)->next);
} else if (compare > 0) {
/* Append it */
i = &pos->next;
pos = pos->next;
}
me->next = pos;
*i = me;
me->t = NULL;
me->tflags = 0;
return true;
}
void xtables_register_targets(struct xtables_target *target, unsigned int n)
......@@ -1367,14 +1484,13 @@ static struct in_addr *host_to_ipaddr(const char *name, unsigned int *naddr)
unsigned int i;
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_CANONNAME;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_RAW;
*naddr = 0;
if ((err = getaddrinfo(name, NULL, &hints, &res)) != 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));
......@@ -1384,9 +1500,6 @@ static struct in_addr *host_to_ipaddr(const char *name, unsigned int *naddr)
sizeof(struct in_addr));
freeaddrinfo(res);
return addr;
}
return NULL;
}
static struct in_addr *
......@@ -1657,14 +1770,13 @@ host_to_ip6addr(const char *name, unsigned int *naddr)
unsigned int i;
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_CANONNAME;
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_RAW;
*naddr = 0;
if ((err = getaddrinfo(name, NULL, &hints, &res)) != 0) {
err = getaddrinfo(name, NULL, &hints, &res);
if (err != 0)
return NULL;
} else {
/* Find length of address chain */
for (p = res; p != NULL; p = p->ai_next)
++*naddr;
......@@ -1676,9 +1788,6 @@ host_to_ip6addr(const char *name, unsigned int *naddr)
sizeof(struct in6_addr));
freeaddrinfo(res);
return addr;
}
return NULL;
}
static struct in6_addr *network_to_ip6addr(const char *name)
......@@ -1968,6 +2077,78 @@ void xtables_print_num(uint64_t number, unsigned int format)
printf(FMT("%4lluT ","%lluT "), (unsigned long long)number);
}
void xtables_parse_val_mask(struct xt_option_call *cb,
unsigned int *val, unsigned int *mask,
const struct xtables_lmap *lmap)
{
char *end;
*mask = ~0U;
if (!xtables_strtoui(cb->arg, &end, val, 0, UINT32_MAX)) {
if (lmap)
goto name2val;
else
goto bad_val;
}
if (*end == '\0')
return;
if (*end != '/') {
if (lmap)
goto name2val;
else
goto garbage;
}
if (!xtables_strtoui(end + 1, &end, mask, 0, UINT32_MAX))
goto bad_val;
if (*end == '\0')
return;
garbage:
xt_params->exit_err(PARAMETER_PROBLEM,
"%s: trailing garbage after value "
"for option \"--%s\".\n",
cb->ext_name, cb->entry->name);
bad_val:
xt_params->exit_err(PARAMETER_PROBLEM,
"%s: bad integer value for option \"--%s\", "
"or out of range.\n",
cb->ext_name, cb->entry->name);
name2val:
*val = xtables_lmap_name2id(lmap, cb->arg);
if ((int)*val == -1)
xt_params->exit_err(PARAMETER_PROBLEM,
"%s: could not map name %s to an integer value "
"for option \"--%s\".\n",
cb->ext_name, cb->arg, cb->entry->name);
}
void xtables_print_val_mask(unsigned int val, unsigned int mask,
const struct xtables_lmap *lmap)
{
if (mask != ~0U) {
printf(" 0x%x/0x%x", val, mask);
return;
}
if (lmap) {
const char *name = xtables_lmap_id2name(lmap, val);
if (name) {
printf(" %s", name);
return;
}
}
printf(" 0x%x", val);
}
int kernel_version;
void get_kernel_version(void)
......
......@@ -91,8 +91,10 @@ xtables_options_xfrm(struct option *orig_opts, struct option *oldopts,
* Since @oldopts also has @orig_opts already (and does so at the
* start), skip these entries.
*/
if (oldopts != NULL) {
oldopts += num_orig;
num_old -= num_orig;
}
merge = malloc(sizeof(*mp) * (num_orig + num_old + num_new + 1));
if (merge == NULL)
......@@ -114,8 +116,10 @@ xtables_options_xfrm(struct option *orig_opts, struct option *oldopts,
}
/* Third, the old options */
if (oldopts != NULL) {
memcpy(mp, oldopts, sizeof(*mp) * num_old);
mp += num_old;
}
xtables_free_opts(0);
/* Clear trailing entry */
......@@ -282,7 +286,7 @@ static void xtopt_mint_value_to_ptr(struct xt_option_call *cb, void **datap,
static void xtopt_parse_mint(struct xt_option_call *cb)
{
const struct xt_option_entry *entry = cb->entry;
const char *arg = cb->arg;
const char *arg;
size_t esize = xtopt_esize_by_type(entry->type);
const uintmax_t lmax = xtopt_max_by_type(entry->type);
void *put = XTOPT_MKPTR(cb);
......@@ -428,27 +432,7 @@ static void xtopt_parse_tosmask(struct xt_option_call *cb)
*/
static void xtopt_parse_markmask(struct xt_option_call *cb)
{
unsigned int mark = 0, mask = ~0U;
char *end;
if (!xtables_strtoui(cb->arg, &end, &mark, 0, UINT32_MAX))
xt_params->exit_err(PARAMETER_PROBLEM,
"%s: bad mark value for option \"--%s\", "
"or out of range.\n",
cb->ext_name, cb->entry->name);
if (*end == '/' &&
!xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX))
xt_params->exit_err(PARAMETER_PROBLEM,
"%s: bad mask value for option \"--%s\", "
"or out of range.\n",
cb->ext_name, cb->entry->name);
if (*end != '\0')
xt_params->exit_err(PARAMETER_PROBLEM,
"%s: trailing garbage after value "
"for option \"--%s\".\n",
cb->ext_name, cb->entry->name);
cb->val.mark = mark;
cb->val.mask = mask;
xtables_parse_mark_mask(cb, &cb->val.mark, &cb->val.mask);
}
static int xtopt_sysloglvl_compare(const void *a, const void *b)
......@@ -864,7 +848,7 @@ void xtables_option_parse(struct xt_option_call *cb)
* a *RC option type.
*/
cb->nvals = 1;
if (entry->type <= ARRAY_SIZE(xtopt_subparse) &&
if (entry->type < ARRAY_SIZE(xtopt_subparse) &&
xtopt_subparse[entry->type] != NULL)
xtopt_subparse[entry->type](cb);
/* Exclusion with other flags tested later in finalize. */
......
This source diff could not be displayed because it is too large. You can view the blob instead.
# Helper functions for option handling. -*- Autoconf -*-
#
# Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation,
# Inc.
# Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software
# Foundation, Inc.
# Written by Gary V. Vaughan, 2004
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# serial 7 ltoptions.m4
# serial 8 ltoptions.m4
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])])
......@@ -29,7 +29,7 @@ m4_define([_LT_SET_OPTION],
[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl
m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]),
_LT_MANGLE_DEFUN([$1], [$2]),
[m4_warning([Unknown $1 option `$2'])])[]dnl
[m4_warning([Unknown $1 option '$2'])])[]dnl
])
......@@ -75,13 +75,15 @@ m4_if([$1],[LT_INIT],[
dnl
dnl If no reference was made to various pairs of opposing options, then
dnl we run the default mode handler for the pair. For example, if neither
dnl `shared' nor `disable-shared' was passed, we enable building of shared
dnl 'shared' nor 'disable-shared' was passed, we enable building of shared
dnl archives by default:
_LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED])
_LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC])
_LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC])
_LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install],
[_LT_ENABLE_FAST_INSTALL])
_LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4],
[_LT_WITH_AIX_SONAME([aix])])
])
])# _LT_SET_OPTIONS
......@@ -112,7 +114,7 @@ AU_DEFUN([AC_LIBTOOL_DLOPEN],
[_LT_SET_OPTION([LT_INIT], [dlopen])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you
put the `dlopen' option into LT_INIT's first parameter.])
put the 'dlopen' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
......@@ -148,7 +150,7 @@ AU_DEFUN([AC_LIBTOOL_WIN32_DLL],
_LT_SET_OPTION([LT_INIT], [win32-dll])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you
put the `win32-dll' option into LT_INIT's first parameter.])
put the 'win32-dll' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
......@@ -157,9 +159,9 @@ dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [])
# _LT_ENABLE_SHARED([DEFAULT])
# ----------------------------
# implement the --enable-shared flag, and supports the `shared' and
# `disable-shared' LT_INIT options.
# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
# implement the --enable-shared flag, and supports the 'shared' and
# 'disable-shared' LT_INIT options.
# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'.
m4_define([_LT_ENABLE_SHARED],
[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl
AC_ARG_ENABLE([shared],
......@@ -172,14 +174,14 @@ AC_ARG_ENABLE([shared],
*)
enable_shared=no
# Look at the argument we got. We use all the common list separators.
lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
for pkg in $enableval; do
IFS="$lt_save_ifs"
IFS=$lt_save_ifs
if test "X$pkg" = "X$p"; then
enable_shared=yes
fi
done
IFS="$lt_save_ifs"
IFS=$lt_save_ifs
;;
esac],
[enable_shared=]_LT_ENABLE_SHARED_DEFAULT)
......@@ -211,9 +213,9 @@ dnl AC_DEFUN([AM_DISABLE_SHARED], [])
# _LT_ENABLE_STATIC([DEFAULT])
# ----------------------------
# implement the --enable-static flag, and support the `static' and
# `disable-static' LT_INIT options.
# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
# implement the --enable-static flag, and support the 'static' and
# 'disable-static' LT_INIT options.
# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'.
m4_define([_LT_ENABLE_STATIC],
[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl
AC_ARG_ENABLE([static],
......@@ -226,14 +228,14 @@ AC_ARG_ENABLE([static],
*)
enable_static=no
# Look at the argument we got. We use all the common list separators.
lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
for pkg in $enableval; do
IFS="$lt_save_ifs"
IFS=$lt_save_ifs
if test "X$pkg" = "X$p"; then
enable_static=yes
fi
done
IFS="$lt_save_ifs"
IFS=$lt_save_ifs
;;
esac],
[enable_static=]_LT_ENABLE_STATIC_DEFAULT)
......@@ -265,9 +267,9 @@ dnl AC_DEFUN([AM_DISABLE_STATIC], [])
# _LT_ENABLE_FAST_INSTALL([DEFAULT])
# ----------------------------------
# implement the --enable-fast-install flag, and support the `fast-install'
# and `disable-fast-install' LT_INIT options.
# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
# implement the --enable-fast-install flag, and support the 'fast-install'
# and 'disable-fast-install' LT_INIT options.
# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'.
m4_define([_LT_ENABLE_FAST_INSTALL],
[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl
AC_ARG_ENABLE([fast-install],
......@@ -280,14 +282,14 @@ AC_ARG_ENABLE([fast-install],
*)
enable_fast_install=no
# Look at the argument we got. We use all the common list separators.
lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
for pkg in $enableval; do
IFS="$lt_save_ifs"
IFS=$lt_save_ifs
if test "X$pkg" = "X$p"; then
enable_fast_install=yes
fi
done
IFS="$lt_save_ifs"
IFS=$lt_save_ifs
;;
esac],
[enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT)
......@@ -304,14 +306,14 @@ AU_DEFUN([AC_ENABLE_FAST_INSTALL],
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you put
the `fast-install' option into LT_INIT's first parameter.])
the 'fast-install' option into LT_INIT's first parameter.])
])
AU_DEFUN([AC_DISABLE_FAST_INSTALL],
[_LT_SET_OPTION([LT_INIT], [disable-fast-install])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you put
the `disable-fast-install' option into LT_INIT's first parameter.])
the 'disable-fast-install' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
......@@ -319,11 +321,64 @@ dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], [])
dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], [])
# _LT_WITH_AIX_SONAME([DEFAULT])
# ----------------------------------
# implement the --with-aix-soname flag, and support the `aix-soname=aix'
# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT
# is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'.
m4_define([_LT_WITH_AIX_SONAME],
[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl
shared_archive_member_spec=
case $host,$enable_shared in
power*-*-aix[[5-9]]*,yes)
AC_MSG_CHECKING([which variant of shared library versioning to provide])
AC_ARG_WITH([aix-soname],
[AS_HELP_STRING([--with-aix-soname=aix|svr4|both],
[shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])],
[case $withval in
aix|svr4|both)
;;
*)
AC_MSG_ERROR([Unknown argument to --with-aix-soname])
;;
esac
lt_cv_with_aix_soname=$with_aix_soname],
[AC_CACHE_VAL([lt_cv_with_aix_soname],
[lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT)
with_aix_soname=$lt_cv_with_aix_soname])
AC_MSG_RESULT([$with_aix_soname])
if test aix != "$with_aix_soname"; then
# For the AIX way of multilib, we name the shared archive member
# based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o',
# and 'shr.imp' or 'shr_64.imp', respectively, for the Import File.
# Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag,
# the AIX toolchain works better with OBJECT_MODE set (default 32).
if test 64 = "${OBJECT_MODE-32}"; then
shared_archive_member_spec=shr_64
else
shared_archive_member_spec=shr
fi
fi
;;
*)
with_aix_soname=aix
;;
esac
_LT_DECL([], [shared_archive_member_spec], [0],
[Shared archive member basename, for filename based shared library versioning on AIX])dnl
])# _LT_WITH_AIX_SONAME
LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])])
LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])])
LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])])
# _LT_WITH_PIC([MODE])
# --------------------
# implement the --with-pic flag, and support the `pic-only' and `no-pic'
# implement the --with-pic flag, and support the 'pic-only' and 'no-pic'
# LT_INIT options.
# MODE is either `yes' or `no'. If omitted, it defaults to `both'.
# MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'.
m4_define([_LT_WITH_PIC],
[AC_ARG_WITH([pic],
[AS_HELP_STRING([--with-pic@<:@=PKGS@:>@],
......@@ -334,19 +389,17 @@ m4_define([_LT_WITH_PIC],
*)
pic_mode=default
# Look at the argument we got. We use all the common list separators.
lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
for lt_pkg in $withval; do
IFS="$lt_save_ifs"
IFS=$lt_save_ifs
if test "X$lt_pkg" = "X$lt_p"; then
pic_mode=yes
fi
done
IFS="$lt_save_ifs"
IFS=$lt_save_ifs
;;
esac],
[pic_mode=default])
test -z "$pic_mode" && pic_mode=m4_default([$1], [default])
[pic_mode=m4_default([$1], [default])])
_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl
])# _LT_WITH_PIC
......@@ -359,7 +412,7 @@ AU_DEFUN([AC_LIBTOOL_PICMODE],
[_LT_SET_OPTION([LT_INIT], [pic-only])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you
put the `pic-only' option into LT_INIT's first parameter.])
put the 'pic-only' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
......
# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*-
#
# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
# Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software
# Foundation, Inc.
# Written by Gary V. Vaughan, 2004
#
# This file is free software; the Free Software Foundation gives
......@@ -33,7 +34,7 @@ m4_define([_lt_join],
# ------------
# Manipulate m4 lists.
# These macros are necessary as long as will still need to support
# Autoconf-2.59 which quotes differently.
# Autoconf-2.59, which quotes differently.
m4_define([lt_car], [[$1]])
m4_define([lt_cdr],
[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
......@@ -44,7 +45,7 @@ m4_define([lt_unquote], $1)
# lt_append(MACRO-NAME, STRING, [SEPARATOR])
# ------------------------------------------
# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'.
# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'.
# Note that neither SEPARATOR nor STRING are expanded; they are appended
# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
# No SEPARATOR is output if MACRO-NAME was previously undefined (different
......
# ltversion.m4 -- version numbers -*- Autoconf -*-
#
# Copyright (C) 2004 Free Software Foundation, Inc.
# Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc.
# Written by Scott James Remnant, 2004
#
# This file is free software; the Free Software Foundation gives
......@@ -9,15 +9,15 @@
# @configure_input@
# serial 3337 ltversion.m4
# serial 4179 ltversion.m4
# This file is part of GNU Libtool
m4_define([LT_PACKAGE_VERSION], [2.4.2])
m4_define([LT_PACKAGE_REVISION], [1.3337])
m4_define([LT_PACKAGE_VERSION], [2.4.6])
m4_define([LT_PACKAGE_REVISION], [2.4.6])
AC_DEFUN([LTVERSION_VERSION],
[macro_version='2.4.2'
macro_revision='1.3337'
[macro_version='2.4.6'
macro_revision='2.4.6'
_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
_LT_DECL(, macro_revision, 0)
])
# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*-
#
# Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc.
# Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software
# Foundation, Inc.
# Written by Scott James Remnant, 2004.
#
# This file is free software; the Free Software Foundation gives
......@@ -11,7 +12,7 @@
# These exist entirely to fool aclocal when bootstrapping libtool.
#
# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN)
# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN),
# which have later been changed to m4_define as they aren't part of the
# exported API, or moved to Autoconf or Automake where they belong.
#
......
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