Blame iptables/xtables-restore.c

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 6e8e02
	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 53d824
			/* 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 53d824
			 * preload_buffer.
Packit Service 53d824
			 * Unless this is an empty line which would fold into a
Packit Service 53d824
			 * spurious EoB indicator (double nul-char). */
Packit Service 53d824
			if (buffer[blen - 1] == '\n' && blen > 1)
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 7e5334
		size_t len = strlen(ptr);
Packit Service 7e5334
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 7e5334
		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 7b22a4
	struct nft_xt_restore_parse p = {
Packit 7b22a4
		.commit = true,
Packit 7b22a4
		.cb = &restore_cb,
Packit 7b22a4
	};
Packit Service 10e551
	bool noflush = false;
Packit Service 10e551
	struct nft_handle h;
Packit Service 10e551
	int c;
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 43dd26
	while ((c = getopt_long(argc, argv, "bcvVthnM:T:wW", 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 10e551
				noflush = true;
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 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 10e551
	if (nft_init(&h, family, 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 Service 10e551
	h.noflush = noflush;
Packit Service 10e551
	h.restore = true;
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
}