|
Packit |
7b22a4 |
/* Code to restore the iptables state, from file by iptables-save.
|
|
Packit |
7b22a4 |
* (C) 2000-2002 by Harald Welte <laforge@gnumonks.org>
|
|
Packit |
7b22a4 |
* based on previous code from Rusty Russell <rusty@linuxcare.com.au>
|
|
Packit |
7b22a4 |
*
|
|
Packit |
7b22a4 |
* This code is distributed under the terms of GNU GPL v2
|
|
Packit |
7b22a4 |
*/
|
|
Packit |
7b22a4 |
#include "config.h"
|
|
Packit |
7b22a4 |
#include <getopt.h>
|
|
Packit |
7b22a4 |
#include <errno.h>
|
|
Packit |
7b22a4 |
#include <libgen.h>
|
|
Packit |
7b22a4 |
#include <stdbool.h>
|
|
Packit |
7b22a4 |
#include <string.h>
|
|
Packit |
7b22a4 |
#include <stdio.h>
|
|
Packit |
7b22a4 |
#include <stdlib.h>
|
|
Packit |
7b22a4 |
#include "iptables.h"
|
|
Packit |
7b22a4 |
#include "xtables.h"
|
|
Packit |
7b22a4 |
#include "libiptc/libiptc.h"
|
|
Packit |
7b22a4 |
#include "xtables-multi.h"
|
|
Packit |
7b22a4 |
#include "nft.h"
|
|
Packit |
7b22a4 |
#include "nft-bridge.h"
|
|
Packit |
7b22a4 |
#include "nft-cache.h"
|
|
Packit |
7b22a4 |
#include <libnftnl/chain.h>
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static int counters, verbose;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
/* Keeping track of external matches and targets. */
|
|
Packit |
7b22a4 |
static const struct option options[] = {
|
|
Packit |
7b22a4 |
{.name = "counters", .has_arg = false, .val = 'c'},
|
|
Packit |
7b22a4 |
{.name = "verbose", .has_arg = false, .val = 'v'},
|
|
Packit |
7b22a4 |
{.name = "version", .has_arg = 0, .val = 'V'},
|
|
Packit |
7b22a4 |
{.name = "test", .has_arg = false, .val = 't'},
|
|
Packit |
7b22a4 |
{.name = "help", .has_arg = false, .val = 'h'},
|
|
Packit |
7b22a4 |
{.name = "noflush", .has_arg = false, .val = 'n'},
|
|
Packit |
7b22a4 |
{.name = "modprobe", .has_arg = true, .val = 'M'},
|
|
Packit |
7b22a4 |
{.name = "table", .has_arg = true, .val = 'T'},
|
|
Packit |
7b22a4 |
{.name = "ipv4", .has_arg = false, .val = '4'},
|
|
Packit |
7b22a4 |
{.name = "ipv6", .has_arg = false, .val = '6'},
|
|
Packit |
7b22a4 |
{.name = "wait", .has_arg = 2, .val = 'w'},
|
|
Packit |
7b22a4 |
{.name = "wait-interval", .has_arg = 2, .val = 'W'},
|
|
Packit |
7b22a4 |
{NULL},
|
|
Packit |
7b22a4 |
};
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
#define prog_name xtables_globals.program_name
|
|
Packit |
7b22a4 |
#define prog_vers xtables_globals.program_version
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static void print_usage(const char *name, const char *version)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
fprintf(stderr, "Usage: %s [-c] [-v] [-V] [-t] [-h] [-n] [-T table] [-M command] [-4] [-6] [file]\n"
|
|
Packit |
7b22a4 |
" [ --counters ]\n"
|
|
Packit |
7b22a4 |
" [ --verbose ]\n"
|
|
Packit |
7b22a4 |
" [ --version]\n"
|
|
Packit |
7b22a4 |
" [ --test ]\n"
|
|
Packit |
7b22a4 |
" [ --help ]\n"
|
|
Packit |
7b22a4 |
" [ --noflush ]\n"
|
|
Packit |
7b22a4 |
" [ --table= ]\n"
|
|
Packit |
7b22a4 |
" [ --modprobe=<command> ]\n"
|
|
Packit |
7b22a4 |
" [ --ipv4 ]\n"
|
|
Packit |
7b22a4 |
" [ --ipv6 ]\n", name);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static const struct nft_xt_restore_cb restore_cb = {
|
|
Packit |
7b22a4 |
.commit = nft_commit,
|
|
Packit |
7b22a4 |
.abort = nft_abort,
|
|
Packit |
7b22a4 |
.table_new = nft_table_new,
|
|
Packit |
7b22a4 |
.table_flush = nft_table_flush,
|
|
Packit |
7b22a4 |
.do_command = do_commandx,
|
|
Packit |
7b22a4 |
.chain_set = nft_chain_set,
|
|
Packit |
7b22a4 |
.chain_restore = nft_chain_restore,
|
|
Packit |
7b22a4 |
};
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
struct nft_xt_restore_state {
|
|
Packit |
7b22a4 |
const struct builtin_table *curtable;
|
|
Packit |
7b22a4 |
struct argv_store av_store;
|
|
Packit |
7b22a4 |
bool in_table;
|
|
Packit |
7b22a4 |
};
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static void xtables_restore_parse_line(struct nft_handle *h,
|
|
Packit |
7b22a4 |
const struct nft_xt_restore_parse *p,
|
|
Packit |
7b22a4 |
struct nft_xt_restore_state *state,
|
|
Packit |
7b22a4 |
char *buffer)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
const struct nft_xt_restore_cb *cb = p->cb;
|
|
Packit |
7b22a4 |
int ret = 0;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (buffer[0] == '\n')
|
|
Packit |
7b22a4 |
return;
|
|
Packit |
7b22a4 |
else if (buffer[0] == '#') {
|
|
Packit |
7b22a4 |
if (verbose)
|
|
Packit |
7b22a4 |
fputs(buffer, stdout);
|
|
Packit |
7b22a4 |
return;
|
|
Packit |
7b22a4 |
} else if (state->in_table &&
|
|
Packit |
7b22a4 |
(strncmp(buffer, "COMMIT", 6) == 0) &&
|
|
Packit |
7b22a4 |
(buffer[6] == '\0' || buffer[6] == '\n')) {
|
|
Packit |
7b22a4 |
if (!p->testing) {
|
|
Packit |
7b22a4 |
/* Commit per table, although we support
|
|
Packit |
7b22a4 |
* global commit at once, stick by now to
|
|
Packit |
7b22a4 |
* the existing behaviour.
|
|
Packit |
7b22a4 |
*/
|
|
Packit |
7b22a4 |
DEBUGP("Calling commit\n");
|
|
Packit |
7b22a4 |
if (cb->commit)
|
|
Packit |
7b22a4 |
ret = cb->commit(h);
|
|
Packit |
7b22a4 |
} else {
|
|
Packit |
7b22a4 |
DEBUGP("Not calling commit, testing\n");
|
|
Packit |
7b22a4 |
if (cb->abort)
|
|
Packit |
7b22a4 |
ret = cb->abort(h);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
state->in_table = false;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
} else if ((buffer[0] == '*') && (!state->in_table || !p->commit)) {
|
|
Packit |
7b22a4 |
/* New table */
|
|
Packit |
7b22a4 |
char *table;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
table = strtok(buffer+1, " \t\n");
|
|
Packit |
7b22a4 |
DEBUGP("line %u, table '%s'\n", line, table);
|
|
Packit |
7b22a4 |
if (!table)
|
|
Packit |
7b22a4 |
xtables_error(PARAMETER_PROBLEM,
|
|
Packit |
7b22a4 |
"%s: line %u table name invalid\n",
|
|
Packit |
7b22a4 |
xt_params->program_name, line);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
state->curtable = nft_table_builtin_find(h, table);
|
|
Packit |
7b22a4 |
if (!state->curtable)
|
|
Packit |
7b22a4 |
xtables_error(PARAMETER_PROBLEM,
|
|
Packit |
7b22a4 |
"%s: line %u table name '%s' invalid\n",
|
|
Packit |
7b22a4 |
xt_params->program_name, line, table);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (p->tablename && (strcmp(p->tablename, table) != 0))
|
|
Packit |
7b22a4 |
return;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (h->noflush == 0) {
|
|
Packit |
7b22a4 |
DEBUGP("Cleaning all chains of table '%s'\n", table);
|
|
Packit |
7b22a4 |
if (cb->table_flush)
|
|
Packit |
7b22a4 |
cb->table_flush(h, table);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
ret = 1;
|
|
Packit |
7b22a4 |
state->in_table = true;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (cb->table_new)
|
|
Packit |
7b22a4 |
cb->table_new(h, table);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
} else if ((buffer[0] == ':') && state->in_table) {
|
|
Packit |
7b22a4 |
/* New chain. */
|
|
Packit |
7b22a4 |
char *policy, *chain = NULL;
|
|
Packit |
7b22a4 |
struct xt_counters count = {};
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
chain = strtok(buffer+1, " \t\n");
|
|
Packit |
7b22a4 |
DEBUGP("line %u, chain '%s'\n", line, chain);
|
|
Packit |
7b22a4 |
if (!chain)
|
|
Packit |
7b22a4 |
xtables_error(PARAMETER_PROBLEM,
|
|
Packit |
7b22a4 |
"%s: line %u chain name invalid\n",
|
|
Packit |
7b22a4 |
xt_params->program_name, line);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (strlen(chain) >= XT_EXTENSION_MAXNAMELEN)
|
|
Packit |
7b22a4 |
xtables_error(PARAMETER_PROBLEM,
|
|
Packit |
7b22a4 |
"Invalid chain name `%s' (%u chars max)",
|
|
Packit |
7b22a4 |
chain, XT_EXTENSION_MAXNAMELEN - 1);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
policy = strtok(NULL, " \t\n");
|
|
Packit |
7b22a4 |
DEBUGP("line %u, policy '%s'\n", line, policy);
|
|
Packit |
7b22a4 |
if (!policy)
|
|
Packit |
7b22a4 |
xtables_error(PARAMETER_PROBLEM,
|
|
Packit |
7b22a4 |
"%s: line %u policy invalid\n",
|
|
Packit |
7b22a4 |
xt_params->program_name, line);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (nft_chain_builtin_find(state->curtable, chain)) {
|
|
Packit |
7b22a4 |
if (counters) {
|
|
Packit |
7b22a4 |
char *ctrs;
|
|
Packit |
7b22a4 |
ctrs = strtok(NULL, " \t\n");
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (!ctrs || !parse_counters(ctrs, &count))
|
|
Packit |
7b22a4 |
xtables_error(PARAMETER_PROBLEM,
|
|
Packit |
7b22a4 |
"invalid policy counters for chain '%s'\n",
|
|
Packit |
7b22a4 |
chain);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
if (cb->chain_set &&
|
|
Packit |
7b22a4 |
cb->chain_set(h, state->curtable->name,
|
|
Packit |
7b22a4 |
chain, policy, &count) < 0) {
|
|
Packit |
7b22a4 |
xtables_error(OTHER_PROBLEM,
|
|
Packit |
7b22a4 |
"Can't set policy `%s' on `%s' line %u: %s\n",
|
|
Packit |
7b22a4 |
policy, chain, line,
|
|
Packit |
7b22a4 |
strerror(errno));
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
DEBUGP("Setting policy of chain %s to %s\n",
|
|
Packit |
7b22a4 |
chain, policy);
|
|
Packit |
7b22a4 |
} else if (cb->chain_restore(h, chain, state->curtable->name) < 0 &&
|
|
Packit |
7b22a4 |
errno != EEXIST) {
|
|
Packit |
7b22a4 |
xtables_error(PARAMETER_PROBLEM,
|
|
Packit |
7b22a4 |
"cannot create chain '%s' (%s)\n",
|
|
Packit |
7b22a4 |
chain, strerror(errno));
|
|
Packit |
7b22a4 |
} else if (h->family == NFPROTO_BRIDGE &&
|
|
Packit |
7b22a4 |
!ebt_set_user_chain_policy(h, state->curtable->name,
|
|
Packit |
7b22a4 |
chain, policy)) {
|
|
Packit |
7b22a4 |
xtables_error(OTHER_PROBLEM,
|
|
Packit |
7b22a4 |
"Can't set policy `%s' on `%s' line %u: %s\n",
|
|
Packit |
7b22a4 |
policy, chain, line,
|
|
Packit |
7b22a4 |
strerror(errno));
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
ret = 1;
|
|
Packit |
7b22a4 |
} else if (state->in_table) {
|
|
Packit |
7b22a4 |
char *pcnt = NULL;
|
|
Packit |
7b22a4 |
char *bcnt = NULL;
|
|
Packit |
7b22a4 |
char *parsestart = buffer;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
add_argv(&state->av_store, xt_params->program_name, 0);
|
|
Packit |
7b22a4 |
add_argv(&state->av_store, "-t", 0);
|
|
Packit |
7b22a4 |
add_argv(&state->av_store, state->curtable->name, 0);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
tokenize_rule_counters(&parsestart, &pcnt, &bcnt, line);
|
|
Packit |
7b22a4 |
if (counters && pcnt && bcnt) {
|
|
Packit |
7b22a4 |
add_argv(&state->av_store, "--set-counters", 0);
|
|
Packit |
7b22a4 |
add_argv(&state->av_store, pcnt, 0);
|
|
Packit |
7b22a4 |
add_argv(&state->av_store, bcnt, 0);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
add_param_to_argv(&state->av_store, parsestart, line);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
DEBUGP("calling do_command4(%u, argv, &%s, handle):\n",
|
|
Packit |
7b22a4 |
state->av_store.argc, state->curtable->name);
|
|
Packit |
7b22a4 |
debug_print_argv(&state->av_store);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
ret = cb->do_command(h, state->av_store.argc,
|
|
Packit |
7b22a4 |
state->av_store.argv,
|
|
Packit |
7b22a4 |
&state->av_store.argv[2], true);
|
|
Packit |
7b22a4 |
if (ret < 0) {
|
|
Packit |
7b22a4 |
if (cb->abort)
|
|
Packit |
7b22a4 |
ret = cb->abort(h);
|
|
Packit |
7b22a4 |
else
|
|
Packit |
7b22a4 |
ret = 0;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (ret < 0) {
|
|
Packit |
7b22a4 |
fprintf(stderr,
|
|
Packit |
7b22a4 |
"failed to abort commit operation\n");
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
exit(1);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
free_argv(&state->av_store);
|
|
Packit |
7b22a4 |
fflush(stdout);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
if (p->tablename && state->curtable &&
|
|
Packit |
7b22a4 |
(strcmp(p->tablename, state->curtable->name) != 0))
|
|
Packit |
7b22a4 |
return;
|
|
Packit |
7b22a4 |
if (!ret) {
|
|
Packit |
7b22a4 |
fprintf(stderr, "%s: line %u failed\n",
|
|
Packit |
7b22a4 |
xt_params->program_name, line);
|
|
Packit |
7b22a4 |
exit(1);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
/* Return true if given iptables-restore line will require a full cache.
|
|
Packit |
7b22a4 |
* Typically these are commands referring to an existing rule
|
|
Packit |
7b22a4 |
* (either by number or content) or commands listing the ruleset. */
|
|
Packit |
7b22a4 |
static bool cmd_needs_full_cache(char *cmd)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
char c, chain[32];
|
|
Packit |
7b22a4 |
int rulenum, mcount;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
mcount = sscanf(cmd, "-%c %31s %d", &c, chain, &rulenum);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (mcount == 3)
|
|
Packit |
7b22a4 |
return true;
|
|
Packit |
7b22a4 |
if (mcount < 1)
|
|
Packit |
7b22a4 |
return false;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
switch (c) {
|
|
Packit |
7b22a4 |
case 'D':
|
|
Packit |
7b22a4 |
case 'C':
|
|
Packit |
7b22a4 |
case 'S':
|
|
Packit |
7b22a4 |
case 'L':
|
|
Packit |
7b22a4 |
case 'Z':
|
|
Packit |
7b22a4 |
return true;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
return false;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
#define PREBUFSIZ 65536
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
void xtables_restore_parse(struct nft_handle *h,
|
|
Packit |
7b22a4 |
const struct nft_xt_restore_parse *p)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
struct nft_xt_restore_state state = {};
|
|
Packit Service |
aaf71a |
char preload_buffer[PREBUFSIZ] = {}, buffer[10240] = {}, *ptr;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (!h->noflush) {
|
|
Packit |
7b22a4 |
nft_fake_cache(h);
|
|
Packit |
7b22a4 |
} else {
|
|
Packit |
7b22a4 |
ssize_t pblen = sizeof(preload_buffer);
|
|
Packit |
7b22a4 |
bool do_cache = false;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
ptr = preload_buffer;
|
|
Packit |
7b22a4 |
while (fgets(buffer, sizeof(buffer), p->in)) {
|
|
Packit |
7b22a4 |
size_t blen = strlen(buffer);
|
|
Packit |
7b22a4 |
|
|
Packit Service |
635b90 |
/* drop trailing newline; xtables_restore_parse_line()
|
|
Packit |
7b22a4 |
* uses strtok() which replaces them by nul-characters,
|
|
Packit |
7b22a4 |
* causing unpredictable string delimiting in
|
|
Packit Service |
635b90 |
* preload_buffer */
|
|
Packit Service |
635b90 |
if (buffer[blen - 1] == '\n')
|
|
Packit |
7b22a4 |
buffer[blen - 1] = '\0';
|
|
Packit |
7b22a4 |
else
|
|
Packit |
7b22a4 |
blen++;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
pblen -= blen;
|
|
Packit |
7b22a4 |
if (pblen <= 0) {
|
|
Packit |
7b22a4 |
/* buffer exhausted */
|
|
Packit |
7b22a4 |
do_cache = true;
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (cmd_needs_full_cache(buffer)) {
|
|
Packit |
7b22a4 |
do_cache = true;
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
/* copy string including terminating nul-char */
|
|
Packit |
7b22a4 |
memcpy(ptr, buffer, blen);
|
|
Packit |
7b22a4 |
ptr += blen;
|
|
Packit |
7b22a4 |
buffer[0] = '\0';
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (do_cache)
|
|
Packit |
7b22a4 |
nft_build_cache(h, NULL);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
line = 0;
|
|
Packit |
7b22a4 |
ptr = preload_buffer;
|
|
Packit |
7b22a4 |
while (*ptr) {
|
|
Packit Service |
f17ea7 |
size_t len = strlen(ptr);
|
|
Packit Service |
f17ea7 |
|
|
Packit |
7b22a4 |
h->error.lineno = ++line;
|
|
Packit |
7b22a4 |
DEBUGP("%s: buffered line %d: '%s'\n", __func__, line, ptr);
|
|
Packit |
7b22a4 |
xtables_restore_parse_line(h, p, &state, ptr);
|
|
Packit Service |
f17ea7 |
ptr += len + 1;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
if (*buffer) {
|
|
Packit |
7b22a4 |
h->error.lineno = ++line;
|
|
Packit |
7b22a4 |
DEBUGP("%s: overrun line %d: '%s'\n", __func__, line, buffer);
|
|
Packit |
7b22a4 |
xtables_restore_parse_line(h, p, &state, buffer);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
while (fgets(buffer, sizeof(buffer), p->in)) {
|
|
Packit |
7b22a4 |
h->error.lineno = ++line;
|
|
Packit |
7b22a4 |
DEBUGP("%s: input line %d: '%s'\n", __func__, line, buffer);
|
|
Packit |
7b22a4 |
xtables_restore_parse_line(h, p, &state, buffer);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
if (state.in_table && p->commit) {
|
|
Packit |
7b22a4 |
fprintf(stderr, "%s: COMMIT expected at line %u\n",
|
|
Packit |
7b22a4 |
xt_params->program_name, line + 1);
|
|
Packit |
7b22a4 |
exit(1);
|
|
Packit |
7b22a4 |
} else if (state.in_table && p->cb->commit && !p->cb->commit(h)) {
|
|
Packit |
7b22a4 |
xtables_error(OTHER_PROBLEM, "%s: final implicit COMMIT failed",
|
|
Packit |
7b22a4 |
xt_params->program_name);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static int
|
|
Packit |
7b22a4 |
xtables_restore_main(int family, const char *progname, int argc, char *argv[])
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
const struct builtin_table *tables;
|
|
Packit Service |
635b90 |
struct nft_handle h = {
|
|
Packit Service |
635b90 |
.family = family,
|
|
Packit Service |
635b90 |
.restore = true,
|
|
Packit Service |
635b90 |
};
|
|
Packit Service |
635b90 |
int c;
|
|
Packit |
7b22a4 |
struct nft_xt_restore_parse p = {
|
|
Packit |
7b22a4 |
.commit = true,
|
|
Packit |
7b22a4 |
.cb = &restore_cb,
|
|
Packit |
7b22a4 |
};
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
line = 0;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
xtables_globals.program_name = progname;
|
|
Packit |
7b22a4 |
c = xtables_init_all(&xtables_globals, family);
|
|
Packit |
7b22a4 |
if (c < 0) {
|
|
Packit |
7b22a4 |
fprintf(stderr, "%s/%s Failed to initialize xtables\n",
|
|
Packit |
7b22a4 |
xtables_globals.program_name,
|
|
Packit |
7b22a4 |
xtables_globals.program_version);
|
|
Packit |
7b22a4 |
exit(1);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit Service |
635b90 |
while ((c = getopt_long(argc, argv, "bcvVthnM:T:46wW", options, NULL)) != -1) {
|
|
Packit |
7b22a4 |
switch (c) {
|
|
Packit |
7b22a4 |
case 'b':
|
|
Packit |
7b22a4 |
fprintf(stderr, "-b/--binary option is not implemented\n");
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case 'c':
|
|
Packit |
7b22a4 |
counters = 1;
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case 'v':
|
|
Packit |
7b22a4 |
verbose = 1;
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case 'V':
|
|
Packit |
7b22a4 |
printf("%s v%s (nf_tables)\n", prog_name, prog_vers);
|
|
Packit |
7b22a4 |
exit(0);
|
|
Packit |
7b22a4 |
case 't':
|
|
Packit |
7b22a4 |
p.testing = 1;
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case 'h':
|
|
Packit |
7b22a4 |
print_usage(prog_name, PACKAGE_VERSION);
|
|
Packit |
7b22a4 |
exit(0);
|
|
Packit |
7b22a4 |
case 'n':
|
|
Packit Service |
635b90 |
h.noflush = 1;
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case 'M':
|
|
Packit |
7b22a4 |
xtables_modprobe_program = optarg;
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case 'T':
|
|
Packit |
7b22a4 |
p.tablename = optarg;
|
|
Packit |
7b22a4 |
break;
|
|
Packit Service |
635b90 |
case '4':
|
|
Packit Service |
635b90 |
h.family = AF_INET;
|
|
Packit Service |
635b90 |
break;
|
|
Packit Service |
635b90 |
case '6':
|
|
Packit Service |
635b90 |
h.family = AF_INET6;
|
|
Packit Service |
635b90 |
xtables_set_nfproto(AF_INET6);
|
|
Packit Service |
635b90 |
break;
|
|
Packit |
7b22a4 |
case 'w': /* fallthrough. Ignored by xt-restore */
|
|
Packit |
7b22a4 |
case 'W':
|
|
Packit |
7b22a4 |
if (!optarg && xs_has_arg(argc, argv))
|
|
Packit |
7b22a4 |
optind++;
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
default:
|
|
Packit |
7b22a4 |
fprintf(stderr,
|
|
Packit |
7b22a4 |
"Try `%s -h' for more information.\n",
|
|
Packit |
7b22a4 |
prog_name);
|
|
Packit |
7b22a4 |
exit(1);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (optind == argc - 1) {
|
|
Packit |
7b22a4 |
p.in = fopen(argv[optind], "re");
|
|
Packit |
7b22a4 |
if (!p.in) {
|
|
Packit |
7b22a4 |
fprintf(stderr, "Can't open %s: %s\n", argv[optind],
|
|
Packit |
7b22a4 |
strerror(errno));
|
|
Packit |
7b22a4 |
exit(1);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
} else if (optind < argc) {
|
|
Packit |
7b22a4 |
fprintf(stderr, "Unknown arguments found on commandline\n");
|
|
Packit |
7b22a4 |
exit(1);
|
|
Packit |
7b22a4 |
} else {
|
|
Packit |
7b22a4 |
p.in = stdin;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
switch (family) {
|
|
Packit |
7b22a4 |
case NFPROTO_IPV4:
|
|
Packit |
7b22a4 |
case NFPROTO_IPV6: /* fallthough, same table */
|
|
Packit |
7b22a4 |
tables = xtables_ipv4;
|
|
Packit |
7b22a4 |
#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS)
|
|
Packit |
7b22a4 |
init_extensions();
|
|
Packit |
7b22a4 |
init_extensions4();
|
|
Packit |
7b22a4 |
#endif
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case NFPROTO_ARP:
|
|
Packit |
7b22a4 |
tables = xtables_arp;
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case NFPROTO_BRIDGE:
|
|
Packit |
7b22a4 |
tables = xtables_bridge;
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
default:
|
|
Packit |
7b22a4 |
fprintf(stderr, "Unknown family %d\n", family);
|
|
Packit |
7b22a4 |
return 1;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit Service |
635b90 |
if (nft_init(&h, tables) < 0) {
|
|
Packit |
7b22a4 |
fprintf(stderr, "%s/%s Failed to initialize nft: %s\n",
|
|
Packit |
7b22a4 |
xtables_globals.program_name,
|
|
Packit |
7b22a4 |
xtables_globals.program_version,
|
|
Packit |
7b22a4 |
strerror(errno));
|
|
Packit |
7b22a4 |
exit(EXIT_FAILURE);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
xtables_restore_parse(&h, &p);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
nft_fini(&h);
|
|
Packit |
7b22a4 |
fclose(p.in);
|
|
Packit |
7b22a4 |
return 0;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
int xtables_ip4_restore_main(int argc, char *argv[])
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
return xtables_restore_main(NFPROTO_IPV4, basename(*argv),
|
|
Packit |
7b22a4 |
argc, argv);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
int xtables_ip6_restore_main(int argc, char *argv[])
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
return xtables_restore_main(NFPROTO_IPV6, basename(*argv),
|
|
Packit |
7b22a4 |
argc, argv);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static int ebt_table_flush(struct nft_handle *h, const char *table)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
/* drop any pending policy rule add/removal jobs */
|
|
Packit |
7b22a4 |
nft_abort_policy_rule(h, table);
|
|
Packit |
7b22a4 |
return nft_table_flush(h, table);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static const struct nft_xt_restore_cb ebt_restore_cb = {
|
|
Packit |
7b22a4 |
.commit = nft_bridge_commit,
|
|
Packit |
7b22a4 |
.table_new = nft_table_new,
|
|
Packit |
7b22a4 |
.table_flush = ebt_table_flush,
|
|
Packit |
7b22a4 |
.do_command = do_commandeb,
|
|
Packit |
7b22a4 |
.chain_set = nft_chain_set,
|
|
Packit |
7b22a4 |
.chain_restore = nft_chain_restore,
|
|
Packit |
7b22a4 |
};
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static const struct option ebt_restore_options[] = {
|
|
Packit |
7b22a4 |
{.name = "noflush", .has_arg = 0, .val = 'n'},
|
|
Packit |
7b22a4 |
{ 0 }
|
|
Packit |
7b22a4 |
};
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
int xtables_eb_restore_main(int argc, char *argv[])
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
struct nft_xt_restore_parse p = {
|
|
Packit |
7b22a4 |
.in = stdin,
|
|
Packit |
7b22a4 |
.cb = &ebt_restore_cb,
|
|
Packit |
7b22a4 |
};
|
|
Packit |
7b22a4 |
bool noflush = false;
|
|
Packit |
7b22a4 |
struct nft_handle h;
|
|
Packit |
7b22a4 |
int c;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
while ((c = getopt_long(argc, argv, "n",
|
|
Packit |
7b22a4 |
ebt_restore_options, NULL)) != -1) {
|
|
Packit |
7b22a4 |
switch(c) {
|
|
Packit |
7b22a4 |
case 'n':
|
|
Packit |
7b22a4 |
noflush = 1;
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
default:
|
|
Packit |
7b22a4 |
fprintf(stderr,
|
|
Packit |
7b22a4 |
"Usage: ebtables-restore [ --noflush ]\n");
|
|
Packit |
7b22a4 |
exit(1);
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
nft_init_eb(&h, "ebtables-restore");
|
|
Packit |
7b22a4 |
h.noflush = noflush;
|
|
Packit |
7b22a4 |
xtables_restore_parse(&h, &p);
|
|
Packit |
7b22a4 |
nft_fini(&h);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
return 0;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static const struct nft_xt_restore_cb arp_restore_cb = {
|
|
Packit |
7b22a4 |
.commit = nft_commit,
|
|
Packit |
7b22a4 |
.table_new = nft_table_new,
|
|
Packit |
7b22a4 |
.table_flush = nft_table_flush,
|
|
Packit |
7b22a4 |
.do_command = do_commandarp,
|
|
Packit |
7b22a4 |
.chain_set = nft_chain_set,
|
|
Packit |
7b22a4 |
.chain_restore = nft_chain_restore,
|
|
Packit |
7b22a4 |
};
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
int xtables_arp_restore_main(int argc, char *argv[])
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
struct nft_xt_restore_parse p = {
|
|
Packit |
7b22a4 |
.in = stdin,
|
|
Packit |
7b22a4 |
.cb = &arp_restore_cb,
|
|
Packit |
7b22a4 |
};
|
|
Packit |
7b22a4 |
struct nft_handle h;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
nft_init_arp(&h, "arptables-restore");
|
|
Packit |
7b22a4 |
xtables_restore_parse(&h, &p);
|
|
Packit |
7b22a4 |
nft_fini(&h);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
return 0;
|
|
Packit |
7b22a4 |
}
|