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

New upstream version 1.8.4

parent 89c92f0c
......@@ -15,5 +15,9 @@ given user. You may also specify a numerical UID, or an UID range.
Matches if the packet socket's file structure is owned by the given group.
You may also specify a numerical GID, or a GID range.
.TP
\fB\-\-suppl\-groups\fP
Causes group(s) specified with \fB\-\-gid-owner\fP to be also checked in the
supplementary groups of a process.
.TP
[\fB!\fP] \fB\-\-socket\-exists\fP
Matches if the packet is associated with a socket.
......@@ -8,5 +8,9 @@
-m owner --uid-owner 0-10 --gid-owner 0-10;=;OK
-m owner ! --uid-owner root;-m owner ! --uid-owner 0;OK
-m owner --socket-exists;=;OK
-m owner --gid-owner 0-10 --suppl-groups;=;OK
-m owner --suppl-groups --gid-owner 0-10;;FAIL
-m owner --gid-owner 0-10 ! --suppl-groups;;FAIL
-m owner --suppl-groups;;FAIL
:INPUT
-m owner --uid-owner root;;FAIL
......@@ -92,10 +92,10 @@ host_triplet = @host@
@ENABLE_LIBIPQ_TRUE@am__append_1 = libipq/libipq.h
subdir = include
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_linker_flags.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__include_HEADERS_DIST) \
......@@ -208,9 +208,6 @@ INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LEX = @LEX@
LEXLIB = @LEXLIB@
LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
......@@ -244,8 +241,6 @@ SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
YACC = @YACC@
YFLAGS = @YFLAGS@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
......@@ -290,7 +285,6 @@ kinclude_CPPFLAGS = @kinclude_CPPFLAGS@
ksourcedir = @ksourcedir@
libdir = @libdir@
libexecdir = @libexecdir@
libiptc_LDFLAGS2 = @libiptc_LDFLAGS2@
libmnl_CFLAGS = @libmnl_CFLAGS@
libmnl_LIBS = @libmnl_LIBS@
libnetfilter_conntrack_CFLAGS = @libnetfilter_conntrack_CFLAGS@
......
#ifndef IPTABLES_INTERNAL_H
#define IPTABLES_INTERNAL_H 1
#define IPTABLES_VERSION "@PACKAGE_VERSION@"
/**
* Program's own name and version.
*/
......
......@@ -14,4 +14,9 @@ struct xt_nfacct_match_info {
struct nf_acct *nfacct;
};
struct xt_nfacct_match_info_v1 {
char name[NFACCT_NAME_MAX];
struct nf_acct *nfacct __attribute__((aligned(8)));
};
#endif /* _XT_NFACCT_MATCH_H */
......@@ -4,9 +4,10 @@
#include <linux/types.h>
enum {
XT_OWNER_UID = 1 << 0,
XT_OWNER_GID = 1 << 1,
XT_OWNER_SOCKET = 1 << 2,
XT_OWNER_UID = 1 << 0,
XT_OWNER_GID = 1 << 1,
XT_OWNER_SOCKET = 1 << 2,
XT_OWNER_SUPPL_GROUPS = 1 << 3,
};
struct xt_owner_match_info {
......
#!/usr/bin/python
#!/usr/bin/env python
#
# (C) 2012-2013 by Pablo Neira Ayuso <pablo@netfilter.org>
#
......@@ -10,6 +10,7 @@
# This software has been sponsored by Sophos Astaro <http://www.sophos.com>
#
from __future__ import print_function
import sys
import os
import subprocess
......@@ -45,7 +46,7 @@ def print_error(reason, filename=None, lineno=None):
'''
Prints an error with nice colors, indicating file and line number.
'''
print (filename + ": " + Colors.RED + "ERROR" +
print(filename + ": " + Colors.RED + "ERROR" +
Colors.ENDC + ": line %d (%s)" % (lineno, reason))
......@@ -140,7 +141,7 @@ def run_test(iptables, rule, rule_save, res, filename, lineno, netns):
return -1
# find the rule
matching = out.find(rule_save)
matching = out.find(rule_save.encode('utf-8'))
if matching < 0:
reason = "cannot find: " + iptables + " -I " + rule
print_error(reason, filename, lineno)
......@@ -166,7 +167,7 @@ def execute_cmd(cmd, filename, lineno):
if cmd.startswith('iptables ') or cmd.startswith('ip6tables ') or cmd.startswith('ebtables ') or cmd.startswith('arptables '):
cmd = os.path.abspath(os.path.curdir) + "/iptables/" + EXECUTEABLE + " " + cmd
print >> log_file, "command: %s" % cmd
print("command: {}".format(cmd), file=log_file)
ret = subprocess.call(cmd, shell=True, universal_newlines=True,
stderr=subprocess.STDOUT, stdout=log_file)
log_file.flush()
......@@ -249,7 +250,7 @@ def run_test_file(filename, netns):
continue
if len(chain_array) == 0:
print "broken test, missing chain, leaving"
print("broken test, missing chain, leaving")
sys.exit()
test_passed = True
......@@ -282,7 +283,7 @@ def run_test_file(filename, netns):
if netns:
execute_cmd("ip netns del ____iptables-container-test", filename, 0)
if total_test_passed:
print filename + ": " + Colors.GREEN + "OK" + Colors.ENDC
print(filename + ": " + Colors.GREEN + "OK" + Colors.ENDC)
f.close()
return tests, passed
......@@ -302,7 +303,7 @@ def show_missing():
missing = [test_name(i) for i in libfiles
if not test_name(i) in testfiles]
print '\n'.join(missing)
print('\n'.join(missing))
#
......@@ -313,6 +314,8 @@ def main():
parser.add_argument('filename', nargs='?',
metavar='path/to/file.t',
help='Run only this test')
parser.add_argument('-H', '--host', action='store_true',
help='Run tests against installed binaries')
parser.add_argument('-l', '--legacy', action='store_true',
help='Test iptables-legacy')
parser.add_argument('-m', '--missing', action='store_true',
......@@ -336,11 +339,13 @@ def main():
EXECUTEABLE = "xtables-nft-multi"
if os.getuid() != 0:
print "You need to be root to run this, sorry"
print("You need to be root to run this, sorry")
return
os.putenv("XTABLES_LIBDIR", os.path.abspath(EXTENSIONS_PATH))
os.putenv("PATH", "%s/iptables:%s" % (os.path.abspath(os.path.curdir), os.getenv("PATH")))
if not args.host:
os.putenv("XTABLES_LIBDIR", os.path.abspath(EXTENSIONS_PATH))
os.putenv("PATH", "%s/iptables:%s" % (os.path.abspath(os.path.curdir),
os.getenv("PATH")))
test_files = 0
tests = 0
......@@ -351,13 +356,17 @@ def main():
try:
log_file = open(LOGFILE, 'w')
except IOError:
print "Couldn't open log file %s" % LOGFILE
print("Couldn't open log file %s" % LOGFILE)
return
file_list = [os.path.join(EXTENSIONS_PATH, i)
for i in os.listdir(EXTENSIONS_PATH)]
if args.filename:
file_list = [args.filename]
else:
file_list = [os.path.join(EXTENSIONS_PATH, i)
for i in os.listdir(EXTENSIONS_PATH)
if i.endswith('.t')]
file_list.sort()
for filename in file_list:
file_tests, file_passed = run_test_file(filename, args.netns)
if file_tests:
......@@ -365,8 +374,7 @@ def main():
passed += file_passed
test_files += 1
print ("%d test files, %d unit tests, %d passed" %
(test_files, tests, passed))
print("%d test files, %d unit tests, %d passed" % (test_files, tests, passed))
if __name__ == '__main__':
......
......@@ -3,6 +3,7 @@
/ip6tables-restore
/ip6tables-static
/ip6tables-translate.8
/ip6tables-restore-translate.8
/iptables
/iptables.8
/iptables-extensions.8
......@@ -13,14 +14,12 @@
/iptables-restore.8
/iptables-static
/iptables-translate.8
/iptables-restore-translate.8
/iptables-xml
/iptables-xml.1
/xtables-multi
/xtables-legacy-multi
/xtables-nft-multi
/xtables-config-parser.c
/xtables-config-parser.h
/xtables-config-syntax.c
/xtables-monitor.8
/xtables.pc
......@@ -2,7 +2,6 @@
AM_CFLAGS = ${regular_CFLAGS}
AM_CPPFLAGS = ${regular_CPPFLAGS} -I${top_builddir}/include -I${top_srcdir}/include -I${top_srcdir} ${kinclude_CPPFLAGS} ${libmnl_CFLAGS} ${libnftnl_CFLAGS} ${libnetfilter_conntrack_CFLAGS}
AM_YFLAGS = -d
BUILT_SOURCES =
......@@ -27,7 +26,6 @@ xtables_legacy_multi_LDADD += ../libxtables/libxtables.la -lm
# iptables using nf_tables api
if ENABLE_NFTABLES
BUILT_SOURCES += xtables-config-parser.h
xtables_nft_multi_SOURCES = xtables-nft-multi.c iptables-xml.c
xtables_nft_multi_CFLAGS = ${AM_CFLAGS}
xtables_nft_multi_LDADD = ../extensions/libext.a ../extensions/libext_ebt.a
......@@ -35,19 +33,16 @@ if ENABLE_STATIC
xtables_nft_multi_CFLAGS += -DALL_INCLUSIVE
endif
xtables_nft_multi_CFLAGS += -DENABLE_NFTABLES -DENABLE_IPV4 -DENABLE_IPV6
xtables_nft_multi_SOURCES += xtables-config-parser.y xtables-config-syntax.l
xtables_nft_multi_SOURCES += xtables-save.c xtables-restore.c \
xtables-standalone.c xtables.c nft.c \
nft-shared.c nft-ipv4.c nft-ipv6.c nft-arp.c \
xtables-monitor.c \
xtables-monitor.c nft-cache.c \
xtables-arp-standalone.c xtables-arp.c \
nft-bridge.c \
xtables-eb-standalone.c xtables-eb.c \
xtables-eb-translate.c \
xtables-translate.c
xtables_nft_multi_LDADD += ${libmnl_LIBS} ${libnftnl_LIBS} ${libnetfilter_conntrack_LIBS} ../extensions/libext4.a ../extensions/libext6.a ../extensions/libext_ebt.a ../extensions/libext_arpt.a
# yacc and lex generate dirty code
xtables_nft_multi-xtables-config-parser.o xtables_nft_multi-xtables-config-syntax.o: AM_CFLAGS += -Wno-missing-prototypes -Wno-missing-declarations -Wno-implicit-function-declaration -Wno-nested-externs -Wno-undef -Wno-redundant-decls
xtables_nft_multi_SOURCES += xshared.c
xtables_nft_multi_LDADD += ../libxtables/libxtables.la -lm
endif
......@@ -58,17 +53,17 @@ sbin_PROGRAMS += xtables-nft-multi
endif
man_MANS = iptables.8 iptables-restore.8 iptables-save.8 \
iptables-xml.1 ip6tables.8 ip6tables-restore.8 \
ip6tables-save.8 iptables-extensions.8 \
xtables-nft.8 xtables-translate.8 xtables-legacy.8 \
iptables-translate.8 ip6tables-translate.8 \
xtables-monitor.8
ip6tables-save.8 iptables-extensions.8
if ENABLE_NFTABLES
man_MANS += arptables-nft.8 arptables-nft-restore.8 arptables-nft-save.8 \
ebtables-nft.8
man_MANS += xtables-nft.8 xtables-translate.8 xtables-legacy.8 \
iptables-translate.8 ip6tables-translate.8 \
iptables-restore-translate.8 ip6tables-restore-translate.8 \
xtables-monitor.8 \
arptables-nft.8 arptables-nft-restore.8 arptables-nft-save.8 \
ebtables-nft.8
endif
CLEANFILES = iptables.8 xtables-monitor.8 \
iptables-translate.8 ip6tables-translate.8 \
xtables-config-parser.c xtables-config-syntax.c
iptables-translate.8 ip6tables-translate.8
vx_bin_links = iptables-xml
if ENABLE_IPV4
......@@ -98,7 +93,7 @@ iptables-extensions.8: iptables-extensions.8.tmpl ../extensions/matches.man ../e
-e '/@MATCH@/ r ../extensions/matches.man' \
-e '/@TARGET@/ r ../extensions/targets.man' $< >$@;
iptables-translate.8 ip6tables-translate.8:
iptables-translate.8 ip6tables-translate.8 iptables-restore-translate.8 ip6tables-restore-translate.8:
${AM_VERBOSE_GEN} echo '.so man8/xtables-translate.8' >$@
pkgconfig_DATA = xtables.pc
......
This diff is collapsed.
......@@ -522,35 +522,39 @@ If the 802.3 DSAP and SSAP values are 0xaa then the SNAP type field must
be consulted to determine the payload protocol. This is a two byte
(hexadecimal) argument. Only 802.3 frames with DSAP/SSAP 0xaa are
checked for type.
.\" .SS among
.\" Match a MAC address or MAC/IP address pair versus a list of MAC addresses
.\" and MAC/IP address pairs.
.\" A list entry has the following format:
.\" .IR xx:xx:xx:xx:xx:xx[=ip.ip.ip.ip][,] ". Multiple"
.\" list entries are separated by a comma, specifying an IP address corresponding to
.\" the MAC address is optional. Multiple MAC/IP address pairs with the same MAC address
.\" but different IP address (and vice versa) can be specified. If the MAC address doesn't
.\" match any entry from the list, the frame doesn't match the rule (unless "!" was used).
.\" .TP
.\" .BR "--among-dst " "[!] \fIlist\fP"
.\" Compare the MAC destination to the given list. If the Ethernet frame has type
.\" .IR IPv4 " or " ARP ,
.\" then comparison with MAC/IP destination address pairs from the
.\" list is possible.
.\" .TP
.\" .BR "--among-src " "[!] \fIlist\fP"
.\" Compare the MAC source to the given list. If the Ethernet frame has type
.\" .IR IPv4 " or " ARP ,
.\" then comparison with MAC/IP source address pairs from the list
.\" is possible.
.\" .TP
.\" .BR "--among-dst-file " "[!] \fIfile\fP"
.\" Same as
.\" .BR --among-dst " but the list is read in from the specified file."
.\" .TP
.\" .BR "--among-src-file " "[!] \fIfile\fP"
.\" Same as
.\" .BR --among-src " but the list is read in from the specified file."
.SS among
Match a MAC address or MAC/IP address pair versus a list of MAC addresses
and MAC/IP address pairs.
A list entry has the following format:
.IR xx:xx:xx:xx:xx:xx[=ip.ip.ip.ip][,] ". Multiple"
list entries are separated by a comma, specifying an IP address corresponding to
the MAC address is optional. Multiple MAC/IP address pairs with the same MAC address
but different IP address (and vice versa) can be specified. If the MAC address doesn't
match any entry from the list, the frame doesn't match the rule (unless "!" was used).
.TP
.BR "--among-dst " "[!] \fIlist\fP"
Compare the MAC destination to the given list. If the Ethernet frame has type
.IR IPv4 " or " ARP ,
then comparison with MAC/IP destination address pairs from the
list is possible.
.TP
.BR "--among-src " "[!] \fIlist\fP"
Compare the MAC source to the given list. If the Ethernet frame has type
.IR IPv4 " or " ARP ,
then comparison with MAC/IP source address pairs from the list
is possible.
.TP
.BR "--among-dst-file " "[!] \fIfile\fP"
Same as
.BR --among-dst " but the list is read in from the specified file."
.TP
.BR "--among-src-file " "[!] \fIfile\fP"
Same as
.BR --among-src " but the list is read in from the specified file."
.PP
Note that in this implementation of ebtables, among lists uses must be
internally homogeneous regarding whether IP addresses are present or not. Mixed
use of MAC addresses and MAC/IP address pairs is not supported yet.
.SS arp
Specify (R)ARP fields. The protocol must be specified as
.IR ARP " or " RARP .
......@@ -1108,8 +1112,8 @@ arp message and the hardware address length in the arp header is 6 bytes.
The version of ebtables this man page ships with does not support the
.B broute
table. Also there is no support for
.BR among " and " string
matches. And finally, this list is probably not complete.
.B string
match. And finally, this list is probably not complete.
.SH SEE ALSO
.BR xtables-nft "(8), " iptables "(8), " ip (8)
.PP
......
......@@ -24,7 +24,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "config.h"
#include <getopt.h>
#include <string.h>
#include <netdb.h>
......@@ -45,33 +45,6 @@
#include "ip6tables-multi.h"
#include "xshared.h"
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#define CMD_NONE 0x0000U
#define CMD_INSERT 0x0001U
#define CMD_DELETE 0x0002U
#define CMD_DELETE_NUM 0x0004U
#define CMD_REPLACE 0x0008U
#define CMD_APPEND 0x0010U
#define CMD_LIST 0x0020U
#define CMD_FLUSH 0x0040U
#define CMD_ZERO 0x0080U
#define CMD_NEW_CHAIN 0x0100U
#define CMD_DELETE_CHAIN 0x0200U
#define CMD_SET_POLICY 0x0400U
#define CMD_RENAME_CHAIN 0x0800U
#define CMD_LIST_RULES 0x1000U
#define CMD_ZERO_NUM 0x2000U
#define CMD_CHECK 0x4000U
#define NUMBER_OF_CMD 16
static const char cmdflags[] = { 'I', 'D', 'D', 'R', 'A', 'L', 'F', 'Z',
'N', 'X', 'P', 'E', 'S', 'Z', 'C' };
#define NUMBER_OF_OPT ARRAY_SIZE(optflags)
static const char optflags[]
= { 'n', 's', 'd', 'p', 'j', 'v', 'x', 'i', 'o', '0', 'c'};
......@@ -121,7 +94,7 @@ static struct option original_opts[] = {
void ip6tables_exit_error(enum xtables_exittype status, const char *msg, ...) __attribute__((noreturn, format(printf,2,3)));
struct xtables_globals ip6tables_globals = {
.option_offset = 0,
.program_version = IPTABLES_VERSION,
.program_version = PACKAGE_VERSION,
.orig_opts = original_opts,
.exit_err = ip6tables_exit_error,
.compat_rev = xtables_compatible_revision,
......@@ -175,12 +148,6 @@ static const unsigned int inverse_for_options[NUMBER_OF_OPT] =
#define opts ip6tables_globals.opts
#define prog_name ip6tables_globals.program_name
#define prog_vers ip6tables_globals.program_version
/* A few hardcoded protocols for 'all' and in case the user has no
/etc/protocols */
struct pprot {
const char *name;
uint8_t num;
};
static void __attribute__((noreturn))
exit_tryhelp(int status)
......@@ -342,27 +309,6 @@ opt2char(int option)
return *ptr;
}
static char
cmd2char(int option)
{
const char *ptr;
for (ptr = cmdflags; option > 1; option >>= 1, ptr++);
return *ptr;
}
static void
add_command(unsigned int *cmd, const int newcmd, const int othercmds,
int invert)
{
if (invert)
xtables_error(PARAMETER_PROBLEM, "unexpected '!' flag");
if (*cmd & (~othercmds))
xtables_error(PARAMETER_PROBLEM, "Cannot use -%c with -%c\n",
cmd2char(newcmd), cmd2char(*cmd & (~othercmds)));
*cmd |= newcmd;
}
/*
* All functions starting with "parse" should succeed, otherwise
* the program fails.
......@@ -381,19 +327,6 @@ static int is_exthdr(uint16_t proto)
proto == IPPROTO_DSTOPTS);
}
/* Can't be zero. */
static int
parse_rulenumber(const char *rule)
{
unsigned int rulenum;
if (!xtables_strtoui(rule, NULL, &rulenum, 1, INT_MAX))
xtables_error(PARAMETER_PROBLEM,
"Invalid rule number `%s'", rule);
return rulenum;
}
static void
parse_chain(const char *chainname)
{
......@@ -1228,6 +1161,7 @@ int do_command6(int argc, char *argv[], char **table,
struct xtables_rule_match *matchp;
struct xtables_target *t;
unsigned long long cnt;
bool table_set = false;
/* re-set optind to 0 in case do_command6 gets called
* a second time */
......@@ -1508,7 +1442,12 @@ int do_command6(int argc, char *argv[], char **table,
if (cs.invert)
xtables_error(PARAMETER_PROBLEM,
"unexpected ! flag before --table");
if (restore && table_set)
xtables_error(PARAMETER_PROBLEM,
"The -t option (seen in line %u) cannot be used in %s.\n",
line, xt_params->program_name);
*table = optarg;
table_set = true;
break;
case 'x':
......@@ -1578,7 +1517,7 @@ int do_command6(int argc, char *argv[], char **table,
xtables_error(PARAMETER_PROBLEM,
"multiple consecutive ! not"
" allowed");
cs.invert = TRUE;
cs.invert = true;
optarg[0] = '\0';
continue;
}
......@@ -1590,12 +1529,12 @@ int do_command6(int argc, char *argv[], char **table,
/*
* If new options were loaded, we must retry
* getopt immediately and not allow
* cs.invert=FALSE to be executed.
* cs.invert=false to be executed.
*/
continue;
break;
}
cs.invert = FALSE;
cs.invert = false;
}
if (!wait && wait_interval_set)
......
......@@ -4,7 +4,7 @@
*
* This code is distributed under the terms of GNU GPL v2
*/
#include "config.h"
#include <getopt.h>
#include <errno.h>
#include <stdbool.h>
......@@ -43,7 +43,7 @@ static const struct option options[] = {
static void print_usage(const char *name, const char *version)
{
fprintf(stderr, "Usage: %s [-c] [-v] [-V] [-t] [-h] [-n] [-w secs] [-W usecs] [-T table] [-M command]\n"
fprintf(stderr, "Usage: %s [-c] [-v] [-V] [-t] [-h] [-n] [-w secs] [-W usecs] [-T table] [-M command] [file]\n"
" [ --counters ]\n"
" [ --verbose ]\n"
" [ --version]\n"
......@@ -70,7 +70,7 @@ struct iptables_restore_cb {
};
static struct xtc_handle *
create_handle(struct iptables_restore_cb *cb, const char *tablename)
create_handle(const struct iptables_restore_cb *cb, const char *tablename)
{
struct xtc_handle *handle;
......@@ -82,18 +82,19 @@ create_handle(struct iptables_restore_cb *cb, const char *tablename)
handle = cb->ops->init(tablename);
}
if (!handle) {
if (!handle)
xtables_error(PARAMETER_PROBLEM, "%s: unable to initialize "
"table '%s'\n", xt_params->program_name, tablename);
exit(1);
}
return handle;
}
static int
ip46tables_restore_main(struct iptables_restore_cb *cb, int argc, char *argv[])
ip46tables_restore_main(const struct iptables_restore_cb *cb,
int argc, char *argv[])
{
struct xtc_handle *handle = NULL;
struct argv_store av_store = {};
char buffer[10240];
int c, lock;
char curtable[XT_TABLE_MAXNAMELEN + 1] = {};
......@@ -125,7 +126,7 @@ ip46tables_restore_main(struct iptables_restore_cb *cb, int argc, char *argv[])
break;
case 'h':
print_usage(xt_params->program_name,
IPTABLES_VERSION);
PACKAGE_VERSION);
exit(0);
case 'n':
noflush = 1;
......@@ -207,12 +208,11 @@ ip46tables_restore_main(struct iptables_restore_cb *cb, int argc, char *argv[])
table = strtok(buffer+1, " \t\n");
DEBUGP("line %u, table '%s'\n", line, table);
if (!table) {
if (!table)
xtables_error(PARAMETER_PROBLEM,
"%s: line %u table name invalid\n",
xt_params->program_name, line);
exit(1);
}
strncpy(curtable, table, XT_TABLE_MAXNAMELEN);
curtable[XT_TABLE_MAXNAMELEN] = '\0';
......@@ -248,12 +248,10 @@ ip46tables_restore_main(struct iptables_restore_cb *cb, int argc, char *argv[])
chain = strtok(buffer+1, " \t\n");
DEBUGP("line %u, chain '%s'\n", line, chain);
if (!chain) {
if (!chain)
xtables_error(PARAMETER_PROBLEM,
"%s: line %u chain name invalid\n",
xt_params->program_name, line);
exit(1);
}
if (strlen(chain) >= XT_EXTENSION_MAXNAMELEN)
xtables_error(PARAMETER_PROBLEM,
......@@ -281,12 +279,10 @@ ip46tables_restore_main(struct iptables_restore_cb *cb, int argc, char *argv[])
policy = strtok(NULL, " \t\n");
DEBUGP("line %u, policy '%s'\n", line, policy);
if (!policy) {
if (!policy)
xtables_error(PARAMETER_PROBLEM,
"%s: line %u policy invalid\n",
xt_params->program_name, line);
exit(1);
}
if (strcmp(policy, "-") != 0) {
struct xt_counters count = {};
......@@ -316,61 +312,31 @@ ip46tables_restore_main(struct iptables_restore_cb *cb, int argc, char *argv[])
ret = 1;
} else if (in_table) {
int a;
char *pcnt = NULL;
char *bcnt = NULL;
char *parsestart;
if (buffer[0] == '[') {
/* we have counters in our input */
char *ptr = strchr(buffer, ']');
if (!ptr)
xtables_error(PARAMETER_PROBLEM,
"Bad line %u: need ]\n",
line);
pcnt = strtok(buffer+1, ":");
if (!pcnt)
xtables_error(PARAMETER_PROBLEM,
"Bad line %u: need :\n",
line);
bcnt = strtok(NULL, "]");
if (!bcnt)
xtables_error(PARAMETER_PROBLEM,
"Bad line %u: need ]\n",
line);
/* start command parsing after counter */
parsestart = ptr + 1;
} else {
/* start command parsing at start of line */
parsestart = buffer;
}
char *parsestart = buffer;
add_argv(argv[0], 0);
add_argv("-t", 0);
add_argv(curtable, 0);
add_argv(&av_store, argv[0], 0);
add_argv(&av_store, "-t", 0);
add_argv(&av_store, curtable, 0);
tokenize_rule_counters(&parsestart, &pcnt, &bcnt, line);
if (counters && pcnt && bcnt) {
add_argv("--set-counters", 0);
add_argv((char *) pcnt, 0);
add_argv((char *) bcnt, 0);
add_argv(&av_store, "--set-counters", 0);
add_argv(&av_store, pcnt, 0);
add_argv(&av_store, bcnt, 0);
}
add_param_to_argv(parsestart, line);
add_param_to_argv(&av_store, parsestart, line);
DEBUGP("calling do_command(%u, argv, &%s, handle):\n",
newargc, curtable);
for (a = 0; a < newargc; a++)
DEBUGP("argv[%u]: %s\n", a, newargv[a]);
av_store.argc, curtable);
debug_print_argv(&av_store);
ret = cb->do_command(newargc, newargv,
&newargv[2], &handle, true);
ret = cb->do_command(av_store.argc, av_store.argv,
&av_store.argv[2], &handle, true);
free_argv();
free_argv(&av_store);
fflush(stdout);
}
if (tablename && strcmp(tablename, curtable) != 0)
......@@ -393,7 +359,7 @@ ip46tables_restore_main(struct iptables_restore_cb *cb, int argc, char *argv[])
#if defined ENABLE_IPV4
struct iptables_restore_cb ipt_restore_cb = {
static const struct iptables_restore_cb ipt_restore_cb = {
.ops = &iptc_ops,
.for_each_chain = for_each_chain4,
.flush_entries = flush_entries4,
......@@ -424,7 +390,7 @@ iptables_restore_main(int argc, char *argv[])
#endif
#if defined ENABLE_IPV6
struct iptables_restore_cb ip6t_restore_cb = {
static const struct iptables_restore_cb ip6t_restore_cb = {
.ops = &ip6tc_ops,
.for_each_chain = for_each_chain6,
.flush_entries = flush_entries6,
......
......@@ -5,6 +5,7 @@
* This code is distributed under the terms of GNU GPL v2
*
*/
#include "config.h"
#include <getopt.h>
#include <errno.h>
#include <stdio.h>
......@@ -90,7 +91,7 @@ static int do_output(struct iptables_save_cb *cb, const char *tablename)
time_t now = time(NULL);
printf("# Generated by %s v%s on %s",
xt_params->program_name, IPTABLES_VERSION, ctime(&now));
xt_params->program_name, PACKAGE_VERSION, ctime(&now));
printf("*%s\n", tablename);
/* Dump out chain names first,
......
......@@ -5,7 +5,7 @@
*
* This code is distributed under the terms of GNU GPL v2
*/
#include "config.h"
#include <getopt.h>
#include <errno.h>
#include <string.h>
......@@ -20,7 +20,7 @@
struct xtables_globals iptables_xml_globals = {
.option_offset = 0,
.program_version = IPTABLES_VERSION,
.program_version = PACKAGE_VERSION,
.program_name = "iptables-xml",
};
#define prog_name iptables_xml_globals.program_name
......@@ -208,12 +208,11 @@ needChain(char *chain)
static void
saveChain(char *chain, char *policy, struct xt_counters *ctr)
{
if (nextChain >= maxChains) {
if (nextChain >= maxChains)
xtables_error(PARAMETER_PROBLEM,
"%s: line %u chain name invalid\n",
prog_name, line);
exit(1);
};
chains[nextChain].chain = strdup(chain);
chains[nextChain].policy = strdup(policy);
chains[nextChain].count = *ctr;
......@@ -441,7 +440,7 @@ do_rule_part(char *leveltag1, char *leveltag2, int part, int argc,
}
static int
compareRules(void)
compareRules(int newargc, char *newargv[], int oldargc, char *oldargv[])
{
/* Compare arguments up to -j or -g for match.
* NOTE: We don't want to combine actions if there were no criteria
......@@ -490,11 +489,13 @@ compareRules(void)
/* has a nice parsed rule starting with -A */
static void
do_rule(char *pcnt, char *bcnt, int argc, char *argv[], int argvattr[])
do_rule(char *pcnt, char *bcnt, int argc, char *argv[], int argvattr[],
int oldargc, char *oldargv[])
{
/* are these conditions the same as the previous rule?
* If so, skip arg straight to -j or -g */
if (combine && argc > 2 && !isTarget(argv[2]) && compareRules()) {
if (combine && argc > 2 && !isTarget(argv[2]) &&
compareRules(argc, argv, oldargc, oldargv)) {
xmlComment("Combine action from next rule");
} else {
......@@ -540,6 +541,7 @@ do_rule(char *pcnt, char *bcnt, int argc, char *argv[], int argvattr[])
int
iptables_xml_main(int argc, char *argv[])
{
struct argv_store last_rule = {}, cur_rule = {};
char buffer[10240];
int c;
FILE *in;
......@@ -557,7 +559,7 @@ iptables_xml_main(int argc, char *argv[])
verbose = 1;
break;
case 'h':
print_usage("iptables-xml", IPTABLES_VERSION);
print_usage("iptables-xml", PACKAGE_VERSION);
break;
}
}
......@@ -606,12 +608,11 @@ iptables_xml_main(int argc, char *argv[])
table = strtok(buffer + 1, " \t\n");
DEBUGP("line %u, table '%s'\n", line, table);
if (!table) {
if (!table)
xtables_error(PARAMETER_PROBLEM,
"%s: line %u table name invalid\n",
prog_name, line);
exit(1);
}
openTable(table);
ret = 1;
......@@ -623,23 +624,19 @@ iptables_xml_main(int argc, char *argv[])
chain = strtok(buffer + 1, " \t\n");
DEBUGP("line %u, chain '%s'\n", line, chain);
if (!chain) {
if (!chain)
xtables_error(PARAMETER_PROBLEM,
"%s: line %u chain name invalid\n",
prog_name, line);
exit(1);
}
DEBUGP("Creating new chain '%s'\n", chain);
policy = strtok(NULL, " \t\n");
DEBUGP("line %u, policy '%s'\n", line, policy);
if (!policy) {
if (!policy)
xtables_error(PARAMETER_PROBLEM,
"%s: line %u policy invalid\n",
prog_name, line);
exit(1);
}
ctrs = strtok(NULL, " \t\n");
parse_counters(ctrs, &count);
......@@ -650,126 +647,32 @@ iptables_xml_main(int argc, char *argv[])
unsigned int a;
char *pcnt = NULL;
char *bcnt = NULL;
char *parsestart;
char *parsestart = buffer;
char *chain = NULL;
/* the parser */
char *param_start, *curchar;
int quote_open, quoted;
char param_buffer[1024];
if (buffer[0] == '[') {
/* we have counters in our input */
char *ptr = strchr(buffer, ']');
if (!ptr)
xtables_error(PARAMETER_PROBLEM,
"Bad line %u: need ]\n",
line);
pcnt = strtok(buffer + 1, ":");
if (!pcnt)
xtables_error(PARAMETER_PROBLEM,
"Bad line %u: need :\n",
line);
bcnt = strtok(NULL, "]");
if (!bcnt)
xtables_error(PARAMETER_PROBLEM,
"Bad line %u: need ]\n",
line);
/* start command parsing after counter */
parsestart = ptr + 1;
} else {
/* start command parsing at start of line */
parsestart = buffer;
}
/* This is a 'real' parser crafted in artist mode
* not hacker mode. If the author can live with that
* then so can everyone else */
quote_open = 0;
/* We need to know which args were quoted so we
can preserve quote */
quoted = 0;
param_start = parsestart;
for (curchar = parsestart; *curchar; curchar++) {
if (*curchar == '"') {
/* quote_open cannot be true if there
* was no previous character. Thus,
* curchar-1 has to be within bounds */
if (quote_open &&
*(curchar - 1) != '\\') {
quote_open = 0;
*curchar = ' ';
} else {
quote_open = 1;
quoted = 1;
param_start++;
}
}
if (*curchar == ' '
|| *curchar == '\t' || *curchar == '\n') {
int param_len = curchar - param_start;
if (quote_open)
continue;
if (!param_len) {
/* two spaces? */
param_start++;
continue;
}
/* end of one parameter */
strncpy(param_buffer, param_start,
param_len);
*(param_buffer + param_len) = '\0';
/* check if table name specified */
if ((param_buffer[0] == '-' &&
param_buffer[1] != '-' &&
strchr(param_buffer, 't')) ||
(!strncmp(param_buffer, "--t", 3) &&
!strncmp(param_buffer, "--table", strlen(param_buffer)))) {
xtables_error(PARAMETER_PROBLEM,
"Line %u seems to have a "
"-t table option.\n",
line);
exit(1);
}
add_argv(param_buffer, quoted);
if (newargc >= 2
&& 0 ==
strcmp(newargv[newargc - 2], "-A"))
chain = newargv[newargc - 1];
quoted = 0;
param_start += param_len + 1;
} else {
/* regular character, skip */
}
}
tokenize_rule_counters(&parsestart, &pcnt, &bcnt, line);
add_param_to_argv(&cur_rule, parsestart, line);
DEBUGP("calling do_command4(%u, argv, &%s, handle):\n",
newargc, curTable);
for (a = 0; a < newargc; a++)
DEBUGP("argv[%u]: %s\n", a, newargv[a]);
cur_rule.argc, curTable);
debug_print_argv(&cur_rule);
for (a = 1; a < cur_rule.argc; a++) {
if (strcmp(cur_rule.argv[a - 1], "-A"))
continue;
chain = cur_rule.argv[a];
break;
}
if (!chain) {
fprintf(stderr, "%s: line %u failed - no chain found\n",
prog_name, line);
exit(1);
}
needChain(chain);// Should we explicitly look for -A
do_rule(pcnt, bcnt, newargc, newargv, newargvattr);
do_rule(pcnt, bcnt, cur_rule.argc, cur_rule.argv,
cur_rule.argvattr, last_rule.argc, last_rule.argv);
save_argv();
save_argv(&last_rule, &cur_rule);
ret = 1;
}
if (!ret) {
......@@ -786,7 +689,7 @@ iptables_xml_main(int argc, char *argv[])
fclose(in);
printf("</iptables-rules>\n");
free_argv();
free_argv(&last_rule);
return 0;
}
......@@ -24,7 +24,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "config.h"
#include <getopt.h>
#include <string.h>
#include <netdb.h>
......@@ -41,33 +41,6 @@
#include <fcntl.h>
#include "xshared.h"
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#define CMD_NONE 0x0000U
#define CMD_INSERT 0x0001U
#define CMD_DELETE 0x0002U
#define CMD_DELETE_NUM 0x0004U
#define CMD_REPLACE 0x0008U
#define CMD_APPEND 0x0010U
#define CMD_LIST 0x0020U
#define CMD_FLUSH 0x0040U
#define CMD_ZERO 0x0080U
#define CMD_NEW_CHAIN 0x0100U
#define CMD_DELETE_CHAIN 0x0200U
#define CMD_SET_POLICY 0x0400U
#define CMD_RENAME_CHAIN 0x0800U
#define CMD_LIST_RULES 0x1000U
#define CMD_ZERO_NUM 0x2000U
#define CMD_CHECK 0x4000U
#define NUMBER_OF_CMD 16
static const char cmdflags[] = { 'I', 'D', 'D', 'R', 'A', 'L', 'F', 'Z',
'N', 'X', 'P', 'E', 'S', 'Z', 'C' };
#define OPT_FRAGMENT 0x00800U
#define NUMBER_OF_OPT ARRAY_SIZE(optflags)
static const char optflags[]
......@@ -120,7 +93,7 @@ void iptables_exit_error(enum xtables_exittype status, const char *msg, ...) __a
struct xtables_globals iptables_globals = {
.option_offset = 0,
.program_version = IPTABLES_VERSION,
.program_version = PACKAGE_VERSION,
.orig_opts = original_opts,
.exit_err = iptables_exit_error,
.compat_rev = xtables_compatible_revision,
......@@ -335,27 +308,6 @@ opt2char(int option)
return *ptr;
}
static char
cmd2char(int option)
{
const char *ptr;
for (ptr = cmdflags; option > 1; option >>= 1, ptr++);
return *ptr;
}
static void
add_command(unsigned int *cmd, const int newcmd, const int othercmds,
int invert)
{
if (invert)
xtables_error(PARAMETER_PROBLEM, "unexpected ! flag");
if (*cmd & (~othercmds))
xtables_error(PARAMETER_PROBLEM, "Cannot use -%c with -%c\n",
cmd2char(newcmd), cmd2char(*cmd & (~othercmds)));
*cmd |= newcmd;
}
/*
* All functions starting with "parse" should succeed, otherwise
* the program fails.
......@@ -366,18 +318,6 @@ add_command(unsigned int *cmd, const int newcmd, const int othercmds,
*/
/* Christophe Burki wants `-p 6' to imply `-m tcp'. */
/* Can't be zero. */
static int
parse_rulenumber(const char *rule)
{
unsigned int rulenum;
if (!xtables_strtoui(rule, NULL, &rulenum, 1, INT_MAX))
xtables_error(PARAMETER_PROBLEM,
"Invalid rule number `%s'", rule);
return rulenum;
}
static void
parse_chain(const char *chainname)
......@@ -1217,6 +1157,7 @@ int do_command4(int argc, char *argv[], char **table,
struct xtables_rule_match *matchp;
struct xtables_target *t;
unsigned long long cnt;
bool table_set = false;
/* re-set optind to 0 in case do_command4 gets called
* a second time */
......@@ -1494,7 +1435,12 @@ int do_command4(int argc, char *argv[], char **table,
if (cs.invert)
xtables_error(PARAMETER_PROBLEM,
"unexpected ! flag before --table");
if (restore && table_set)
xtables_error(PARAMETER_PROBLEM,
"The -t option (seen in line %u) cannot be used in %s.\n",
line, xt_params->program_name);
*table = optarg;
table_set = true;
break;
case 'x':
......@@ -1564,7 +1510,7 @@ int do_command4(int argc, char *argv[], char **table,
xtables_error(PARAMETER_PROBLEM,
"multiple consecutive ! not"
" allowed");
cs.invert = TRUE;
cs.invert = true;
optarg[0] = '\0';
continue;
}
......@@ -1577,7 +1523,7 @@ int do_command4(int argc, char *argv[], char **table,
continue;
break;
}
cs.invert = FALSE;
cs.invert = false;
}
if (!wait && wait_interval_set)
......
......@@ -114,29 +114,6 @@ mask_to_dotted(const struct in_addr *mask)
return buf;
}
static void print_mac(const unsigned char *mac, int l)
{
int j;
for (j = 0; j < l; j++)
printf("%02x%s", mac[j],
(j==l-1) ? "" : ":");
}
static void print_mac_and_mask(const unsigned char *mac, const unsigned char *mask, int l)
{
int i;
print_mac(mac, l);
for (i = 0; i < l ; i++)
if (mask[i] != 255)
break;
if (i == l)
return;
printf("/");
print_mac(mask, l);
}
static bool need_devaddr(struct arpt_devaddr_info *info)
{
int i;
......@@ -149,7 +126,7 @@ static bool need_devaddr(struct arpt_devaddr_info *info)
return false;
}
static int nft_arp_add(struct nftnl_rule *r, void *data)
static int nft_arp_add(struct nft_handle *h, struct nftnl_rule *r, void *data)
{
struct iptables_command_state *cs = data;
struct arpt_entry *fw = &cs->arp;
......@@ -506,8 +483,8 @@ static void nft_arp_print_rule_details(const struct iptables_command_state *cs,
printf("%s%s", sep, fw->arp.invflags & ARPT_INV_SRCDEVADDR
? "! " : "");
printf("--src-mac ");
print_mac_and_mask((unsigned char *)fw->arp.src_devaddr.addr,
(unsigned char *)fw->arp.src_devaddr.mask, ETH_ALEN);
xtables_print_mac_and_mask((unsigned char *)fw->arp.src_devaddr.addr,
(unsigned char *)fw->arp.src_devaddr.mask);
sep = " ";
after_devsrc:
......@@ -532,8 +509,8 @@ after_devsrc:
printf("%s%s", sep, fw->arp.invflags & ARPT_INV_TGTDEVADDR
? "! " : "");
printf("--dst-mac ");
print_mac_and_mask((unsigned char *)fw->arp.tgt_devaddr.addr,
(unsigned char *)fw->arp.tgt_devaddr.mask, ETH_ALEN);
xtables_print_mac_and_mask((unsigned char *)fw->arp.tgt_devaddr.addr,
(unsigned char *)fw->arp.tgt_devaddr.mask);
sep = " ";
after_devdst:
......@@ -605,14 +582,15 @@ nft_arp_save_rule(const void *data, unsigned int format)
}
static void
nft_arp_print_rule(struct nftnl_rule *r, unsigned int num, unsigned int format)
nft_arp_print_rule(struct nft_handle *h, struct nftnl_rule *r,
unsigned int num, unsigned int format)
{
struct iptables_command_state cs = {};
if (format & FMT_LINENUMBERS)
printf("%u ", num);
nft_rule_to_iptables_command_state(r, &cs);
nft_rule_to_iptables_command_state(h, r, &cs);
nft_arp_print_rule_details(&cs, format);
print_matches_and_target(&cs, format);
......@@ -655,7 +633,7 @@ static bool nft_arp_is_same(const void *data_a,
(unsigned char *)b->arp.outiface_mask);
}
static bool nft_arp_rule_find(struct nft_family_ops *ops, struct nftnl_rule *r,
static bool nft_arp_rule_find(struct nft_handle *h, struct nftnl_rule *r,
void *data)
{
const struct iptables_command_state *cs = data;
......@@ -663,7 +641,7 @@ static bool nft_arp_rule_find(struct nft_family_ops *ops, struct nftnl_rule *r,
bool ret = false;
/* Delete by matching rule case */
nft_rule_to_iptables_command_state(r, &this);
nft_rule_to_iptables_command_state(h, r, &this);
if (!nft_arp_is_same(&cs->arp, &this.arp))
goto out;
......@@ -676,7 +654,7 @@ static bool nft_arp_rule_find(struct nft_family_ops *ops, struct nftnl_rule *r,
ret = true;
out:
ops->clear_cs(&this);
h->ops->clear_cs(&this);
return ret;
}
......
......@@ -17,12 +17,13 @@
#include <libiptc/libxtc.h>
#include <linux/netfilter/nf_tables.h>
#include <libnftnl/set.h>
#include "nft-shared.h"
#include "nft-bridge.h"
#include "nft-cache.h"
#include "nft.h"
static bool ebt_legacy_counter_fmt;
void ebt_cs_clean(struct iptables_command_state *cs)
{
struct ebt_match *m, *nm;
......@@ -128,7 +129,8 @@ static int _add_action(struct nftnl_rule *r, struct iptables_command_state *cs)
return add_action(r, cs, false);
}
static int nft_bridge_add(struct nftnl_rule *r, void *data)
static int nft_bridge_add(struct nft_handle *h,
struct nftnl_rule *r, void *data)
{
struct iptables_command_state *cs = data;
struct ebt_match *iter;
......@@ -184,7 +186,7 @@ static int nft_bridge_add(struct nftnl_rule *r, void *data)
for (iter = cs->match_list; iter; iter = iter->next) {
if (iter->ismatch) {
if (add_match(r, iter->u.match->m))
if (add_match(h, r, iter->u.match->m))
break;
} else {
if (add_target(r, iter->u.watcher->t))
......@@ -292,6 +294,212 @@ static void nft_bridge_parse_immediate(const char *jumpto, bool nft_goto,
cs->jumpto = jumpto;
}
/* return 0 if saddr, 1 if daddr, -1 on error */
static int
lookup_check_ether_payload(uint32_t base, uint32_t offset, uint32_t len)
{
if (base != 0 || len != ETH_ALEN)
return -1;
switch (offset) {
case offsetof(struct ether_header, ether_dhost):
return 1;
case offsetof(struct ether_header, ether_shost):
return 0;
default:
return -1;
}
}
/* return 0 if saddr, 1 if daddr, -1 on error */
static int
lookup_check_iphdr_payload(uint32_t base, uint32_t offset, uint32_t len)
{
if (base != 1 || len != 4)
return -1;
switch (offset) {
case offsetof(struct iphdr, daddr):
return 1;
case offsetof(struct iphdr, saddr):
return 0;
default:
return -1;
}
}
/* Make sure previous payload expression(s) is/are consistent and extract if
* matching on source or destination address and if matching on MAC and IP or
* only MAC address. */
static int lookup_analyze_payloads(const struct nft_xt_ctx *ctx,
bool *dst, bool *ip)
{
int val, val2 = -1;
if (ctx->flags & NFT_XT_CTX_PREV_PAYLOAD) {
val = lookup_check_ether_payload(ctx->prev_payload.base,
ctx->prev_payload.offset,
ctx->prev_payload.len);
if (val < 0) {
DEBUGP("unknown payload base/offset/len %d/%d/%d\n",
ctx->prev_payload.base, ctx->prev_payload.offset,
ctx->prev_payload.len);
return -1;
}
if (!(ctx->flags & NFT_XT_CTX_PAYLOAD)) {
DEBUGP("Previous but no current payload?\n");
return -1;
}
val2 = lookup_check_iphdr_payload(ctx->payload.base,
ctx->payload.offset,
ctx->payload.len);
if (val2 < 0) {
DEBUGP("unknown payload base/offset/len %d/%d/%d\n",
ctx->payload.base, ctx->payload.offset,
ctx->payload.len);
return -1;
} else if (val != val2) {
DEBUGP("mismatching payload match offsets\n");
return -1;
}
} else if (ctx->flags & NFT_XT_CTX_PAYLOAD) {
val = lookup_check_ether_payload(ctx->payload.base,
ctx->payload.offset,
ctx->payload.len);
if (val < 0) {
DEBUGP("unknown payload base/offset/len %d/%d/%d\n",
ctx->payload.base, ctx->payload.offset,
ctx->payload.len);
return -1;
}
} else {
DEBUGP("unknown LHS of lookup expression\n");
return -1;
}
if (dst)
*dst = (val == 1);
if (ip)
*ip = (val2 != -1);
return 0;
}
static int set_elems_to_among_pairs(struct nft_among_pair *pairs,
const struct nftnl_set *s, int cnt)
{
struct nftnl_set_elems_iter *iter = nftnl_set_elems_iter_create(s);
struct nftnl_set_elem *elem;
size_t tmpcnt = 0;
const void *data;
uint32_t datalen;
int ret = -1;
if (!iter) {
fprintf(stderr, "BUG: set elems iter allocation failed\n");
return ret;
}
while ((elem = nftnl_set_elems_iter_next(iter))) {
data = nftnl_set_elem_get(elem, NFTNL_SET_ELEM_KEY, &datalen);
if (!data) {
fprintf(stderr, "BUG: set elem without key\n");
goto err;
}
if (datalen > sizeof(*pairs)) {
fprintf(stderr, "BUG: overlong set elem\n");
goto err;
}
nft_among_insert_pair(pairs, &tmpcnt, data);
}
ret = 0;
err:
nftnl_set_elems_iter_destroy(iter);
return ret;
}
static struct nftnl_set *set_from_lookup_expr(struct nft_xt_ctx *ctx,
const struct nftnl_expr *e)
{
const char *set_name = nftnl_expr_get_str(e, NFTNL_EXPR_LOOKUP_SET);
struct nftnl_set_list *slist;
slist = nft_set_list_get(ctx->h, ctx->table, set_name);
if (slist)
return nftnl_set_list_lookup_byname(slist, set_name);
return NULL;
}
static void nft_bridge_parse_lookup(struct nft_xt_ctx *ctx,
struct nftnl_expr *e, void *data)
{
struct xtables_match *match = NULL;
struct nft_among_data *among_data;
bool is_dst, have_ip, inv;
struct ebt_match *ematch;
struct nftnl_set *s;
size_t poff, size;
uint32_t cnt;
if (lookup_analyze_payloads(ctx, &is_dst, &have_ip))
return;
s = set_from_lookup_expr(ctx, e);
if (!s)
xtables_error(OTHER_PROBLEM,
"BUG: lookup expression references unknown set");
cnt = nftnl_set_get_u32(s, NFTNL_SET_DESC_SIZE);
for (ematch = ctx->cs->match_list; ematch; ematch = ematch->next) {
if (!ematch->ismatch || strcmp(ematch->u.match->name, "among"))
continue;
match = ematch->u.match;
among_data = (struct nft_among_data *)match->m->data;
size = cnt + among_data->src.cnt + among_data->dst.cnt;
size *= sizeof(struct nft_among_pair);
size += XT_ALIGN(sizeof(struct xt_entry_match)) +
sizeof(struct nft_among_data);
match->m = xtables_realloc(match->m, size);
break;
}
if (!match) {
match = xtables_find_match("among", XTF_TRY_LOAD,
&ctx->cs->matches);
size = cnt * sizeof(struct nft_among_pair);
size += XT_ALIGN(sizeof(struct xt_entry_match)) +
sizeof(struct nft_among_data);
match->m = xtables_calloc(1, size);
strcpy(match->m->u.user.name, match->name);
match->m->u.user.revision = match->revision;
xs_init_match(match);
if (ctx->h->ops->parse_match != NULL)
ctx->h->ops->parse_match(match, ctx->cs);
}
if (!match)
return;
match->m->u.match_size = size;
inv = !!(nftnl_expr_get_u32(e, NFTNL_EXPR_LOOKUP_FLAGS) &
NFT_LOOKUP_F_INV);
among_data = (struct nft_among_data *)match->m->data;
poff = nft_among_prepare_data(among_data, is_dst, cnt, inv, have_ip);
if (set_elems_to_among_pairs(among_data->pairs + poff, s, cnt))
xtables_error(OTHER_PROBLEM,
"ebtables among pair parsing failed");
ctx->flags &= ~(NFT_XT_CTX_PAYLOAD | NFT_XT_CTX_PREV_PAYLOAD);
}
static void parse_watcher(void *object, struct ebt_match **match_list,
bool ismatch)
{
......@@ -334,11 +542,12 @@ static void nft_bridge_parse_target(struct xtables_target *t, void *data)
cs->target = t;
}
static void nft_rule_to_ebtables_command_state(const struct nftnl_rule *r,
static void nft_rule_to_ebtables_command_state(struct nft_handle *h,
const struct nftnl_rule *r,
struct iptables_command_state *cs)
{
cs->eb.bitmask = EBT_NOPROTO;
nft_rule_to_iptables_command_state(r, cs);
nft_rule_to_iptables_command_state(h, r, cs);
}
static void print_iface(const char *option, const char *name, bool invert)
......@@ -422,22 +631,6 @@ static void print_protocol(uint16_t ethproto, bool invert, unsigned int bitmask)
printf("%s ", ent->e_name);
}
static void nft_bridge_save_counters(const void *data)
{
const char *ctr;
if (ebt_legacy_counter_fmt)
return;
ctr = getenv("EBTABLES_SAVE_COUNTER");
if (ctr) {
ebt_legacy_counter_fmt = true;
return;
}
save_counters(data);
}
static void nft_bridge_save_rule(const void *data, unsigned int format)
{
const struct iptables_command_state *cs = data;
......@@ -474,29 +667,30 @@ static void nft_bridge_save_rule(const void *data, unsigned int format)
cs->target->print(&cs->fw, cs->target->t, format & FMT_NUMERIC);
}
if (format & FMT_EBT_SAVE)
printf(" -c %"PRIu64" %"PRIu64"",
(uint64_t)cs->counters.pcnt,
(uint64_t)cs->counters.bcnt);
if (!(format & FMT_NOCOUNTS))
printf(" , pcnt = %"PRIu64" -- bcnt = %"PRIu64"",
(uint64_t)cs->counters.pcnt,
(uint64_t)cs->counters.bcnt);
if ((format & (FMT_NOCOUNTS | FMT_C_COUNTS)) == FMT_C_COUNTS) {
if (format & FMT_EBT_SAVE)
printf(" -c %"PRIu64" %"PRIu64"",
(uint64_t)cs->counters.pcnt,
(uint64_t)cs->counters.bcnt);
else
printf(" , pcnt = %"PRIu64" -- bcnt = %"PRIu64"",
(uint64_t)cs->counters.pcnt,
(uint64_t)cs->counters.bcnt);
}
if (!(format & FMT_NONEWLINE))
fputc('\n', stdout);
}
static void nft_bridge_print_rule(struct nftnl_rule *r, unsigned int num,
unsigned int format)
static void nft_bridge_print_rule(struct nft_handle *h, struct nftnl_rule *r,
unsigned int num, unsigned int format)
{
struct iptables_command_state cs = {};
if (format & FMT_LINENUMBERS)
printf("%d ", num);
nft_rule_to_ebtables_command_state(r, &cs);
nft_rule_to_ebtables_command_state(h, r, &cs);
nft_bridge_save_rule(&cs, format);
ebt_cs_clean(&cs);
}
......@@ -553,14 +747,14 @@ static bool nft_bridge_is_same(const void *data_a, const void *data_b)
return strcmp(a->in, b->in) == 0 && strcmp(a->out, b->out) == 0;
}
static bool nft_bridge_rule_find(struct nft_family_ops *ops, struct nftnl_rule *r,
static bool nft_bridge_rule_find(struct nft_handle *h, struct nftnl_rule *r,
void *data)
{
struct iptables_command_state *cs = data;
struct iptables_command_state this = {};
bool ret = false;
nft_rule_to_ebtables_command_state(r, &this);
nft_rule_to_ebtables_command_state(h, r, &this);
DEBUGP("comparing with... ");
......@@ -584,7 +778,7 @@ static bool nft_bridge_rule_find(struct nft_family_ops *ops, struct nftnl_rule *
ret = true;
out:
ops->clear_cs(&this);
h->ops->clear_cs(&this);
return ret;
}
......@@ -757,13 +951,14 @@ struct nft_family_ops nft_family_ops_bridge = {
.parse_meta = nft_bridge_parse_meta,
.parse_payload = nft_bridge_parse_payload,
.parse_immediate = nft_bridge_parse_immediate,
.parse_lookup = nft_bridge_parse_lookup,
.parse_match = nft_bridge_parse_match,
.parse_target = nft_bridge_parse_target,
.print_table_header = nft_bridge_print_table_header,
.print_header = nft_bridge_print_header,
.print_rule = nft_bridge_print_rule,
.save_rule = nft_bridge_save_rule,
.save_counters = nft_bridge_save_counters,
.save_counters = save_counters,
.save_chain = nft_bridge_save_chain,
.post_parse = NULL,
.rule_to_cs = nft_rule_to_ebtables_command_state,
......
......@@ -122,4 +122,60 @@ void ebt_add_watcher(struct xtables_target *watcher,
struct iptables_command_state *cs);
int ebt_command_default(struct iptables_command_state *cs);
struct nft_among_pair {
struct ether_addr ether;
struct in_addr in __attribute__((aligned (4)));
};
struct nft_among_data {
struct {
size_t cnt;
bool inv;
bool ip;
} src, dst;
/* first source, then dest pairs */
struct nft_among_pair pairs[0];
};
/* initialize fields, return offset into pairs array to write pairs to */
static inline size_t
nft_among_prepare_data(struct nft_among_data *data, bool dst,
size_t cnt, bool inv, bool ip)
{
size_t poff;
if (dst) {
data->dst.cnt = cnt;
data->dst.inv = inv;
data->dst.ip = ip;
poff = data->src.cnt;
} else {
data->src.cnt = cnt;
data->src.inv = inv;
data->src.ip = ip;
poff = 0;
memmove(data->pairs + cnt, data->pairs,
data->dst.cnt * sizeof(*data->pairs));
}
return poff;
}
static inline void
nft_among_insert_pair(struct nft_among_pair *pairs,
size_t *pcount, const struct nft_among_pair *new)
{
int i;
/* nftables automatically sorts set elements from smallest to largest,
* insert sorted so extension comparison works */
for (i = 0; i < *pcount; i++) {
if (memcmp(new, &pairs[i], sizeof(*new)) < 0)
break;
}
memmove(&pairs[i + 1], &pairs[i], sizeof(*pairs) * (*pcount - i));
memcpy(&pairs[i], new, sizeof(*new));
(*pcount)++;
}
#endif
/*
* (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This code has been sponsored by Sophos Astaro <http://www.sophos.com>
*/
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <xtables.h>
#include <linux/netfilter/nf_tables.h>
#include <libmnl/libmnl.h>
#include <libnftnl/gen.h>
#include <libnftnl/set.h>
#include <libnftnl/table.h>
#include "nft.h"
#include "nft-cache.h"
static int genid_cb(const struct nlmsghdr *nlh, void *data)
{
uint32_t *genid = data;
struct nftnl_gen *gen;
gen = nftnl_gen_alloc();
if (!gen)
return MNL_CB_ERROR;
if (nftnl_gen_nlmsg_parse(nlh, gen) < 0)
goto out;
*genid = nftnl_gen_get_u32(gen, NFTNL_GEN_ID);
nftnl_gen_free(gen);
return MNL_CB_STOP;
out:
nftnl_gen_free(gen);
return MNL_CB_ERROR;
}
static void mnl_genid_get(struct nft_handle *h, uint32_t *genid)
{
char buf[MNL_SOCKET_BUFFER_SIZE];
struct nlmsghdr *nlh;
int ret;
nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETGEN, 0, 0, h->seq);
ret = mnl_talk(h, nlh, genid_cb, genid);
if (ret == 0)
return;
xtables_error(RESOURCE_PROBLEM,
"Could not fetch rule set generation id: %s\n", nft_strerror(errno));
}
static int nftnl_table_list_cb(const struct nlmsghdr *nlh, void *data)
{
struct nftnl_table *t;
struct nftnl_table_list *list = data;
t = nftnl_table_alloc();
if (t == NULL)
goto err;
if (nftnl_table_nlmsg_parse(nlh, t) < 0)
goto out;
nftnl_table_list_add_tail(t, list);
return MNL_CB_OK;
out:
nftnl_table_free(t);
err:
return MNL_CB_OK;
}
static int fetch_table_cache(struct nft_handle *h)
{
char buf[16536];
struct nlmsghdr *nlh;
struct nftnl_table_list *list;
int ret;
if (h->cache->tables)
return 0;
list = nftnl_table_list_alloc();
if (list == NULL)
return 0;
nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, h->family,
NLM_F_DUMP, h->seq);
ret = mnl_talk(h, nlh, nftnl_table_list_cb, list);
if (ret < 0 && errno == EINTR)
assert(nft_restart(h) >= 0);
h->cache->tables = list;
return 1;
}
struct nftnl_chain_list_cb_data {
struct nft_handle *h;
const struct builtin_table *t;
};
static int nftnl_chain_list_cb(const struct nlmsghdr *nlh, void *data)
{
struct nftnl_chain_list_cb_data *d = data;
const struct builtin_table *t = d->t;
struct nftnl_chain_list *list;
struct nft_handle *h = d->h;
const char *tname, *cname;
struct nftnl_chain *c;
c = nftnl_chain_alloc();
if (c == NULL)
goto err;
if (nftnl_chain_nlmsg_parse(nlh, c) < 0)
goto out;
tname = nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
if (!t) {
t = nft_table_builtin_find(h, tname);
if (!t)
goto out;
} else if (strcmp(t->name, tname)) {
goto out;
}
list = h->cache->table[t->type].chains;
cname = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
if (nftnl_chain_list_lookup_byname(list, cname))
goto out;
nftnl_chain_list_add_tail(c, list);
return MNL_CB_OK;
out:
nftnl_chain_free(c);
err:
return MNL_CB_OK;
}
struct nftnl_set_list_cb_data {
struct nft_handle *h;
const struct builtin_table *t;
};
static int nftnl_set_list_cb(const struct nlmsghdr *nlh, void *data)
{
struct nftnl_set_list_cb_data *d = data;
const struct builtin_table *t = d->t;
struct nftnl_set_list *list;
struct nft_handle *h = d->h;
const char *tname, *sname;
struct nftnl_set *s;
s = nftnl_set_alloc();
if (s == NULL)
return MNL_CB_OK;
if (nftnl_set_nlmsg_parse(nlh, s) < 0)
goto out_free;
tname = nftnl_set_get_str(s, NFTNL_SET_TABLE);
if (!t)
t = nft_table_builtin_find(h, tname);
else if (strcmp(t->name, tname))
goto out_free;
if (!t)
goto out_free;
list = h->cache->table[t->type].sets;
sname = nftnl_set_get_str(s, NFTNL_SET_NAME);
if (nftnl_set_list_lookup_byname(list, sname))
goto out_free;
nftnl_set_list_add_tail(s, list);
return MNL_CB_OK;
out_free:
nftnl_set_free(s);
return MNL_CB_OK;
}
static int set_elem_cb(const struct nlmsghdr *nlh, void *data)
{
return nftnl_set_elems_nlmsg_parse(nlh, data) ? -1 : MNL_CB_OK;
}
static bool set_has_elements(struct nftnl_set *s)
{
struct nftnl_set_elems_iter *iter;
bool ret = false;
iter = nftnl_set_elems_iter_create(s);
if (iter) {
ret = !!nftnl_set_elems_iter_cur(iter);
nftnl_set_elems_iter_destroy(iter);
}
return ret;
}
static int set_fetch_elem_cb(struct nftnl_set *s, void *data)
{
char buf[MNL_SOCKET_BUFFER_SIZE];
struct nft_handle *h = data;
struct nlmsghdr *nlh;
if (set_has_elements(s))
return 0;
nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETSETELEM, h->family,
NLM_F_DUMP, h->seq);
nftnl_set_elems_nlmsg_build_payload(nlh, s);
return mnl_talk(h, nlh, set_elem_cb, s);
}
static int fetch_set_cache(struct nft_handle *h,
const struct builtin_table *t, const char *set)
{
struct nftnl_set_list_cb_data d = {
.h = h,
.t = t,
};
struct nlmsghdr *nlh;
char buf[16536];
int i, ret;
if (!t) {
for (i = 0; i < NFT_TABLE_MAX; i++) {
enum nft_table_type type = h->tables[i].type;
if (!h->tables[i].name)
continue;
h->cache->table[type].sets = nftnl_set_list_alloc();
if (!h->cache->table[type].sets)
return -1;
}
} else if (!h->cache->table[t->type].sets) {
h->cache->table[t->type].sets = nftnl_set_list_alloc();
}
if (t && set) {
struct nftnl_set *s = nftnl_set_alloc();
if (!s)
return -1;
nlh = nftnl_set_nlmsg_build_hdr(buf, NFT_MSG_GETSET, h->family,
NLM_F_ACK, h->seq);
nftnl_set_set_str(s, NFTNL_SET_TABLE, t->name);
nftnl_set_set_str(s, NFTNL_SET_NAME, set);
nftnl_set_nlmsg_build_payload(nlh, s);
nftnl_set_free(s);
} else {
nlh = nftnl_set_nlmsg_build_hdr(buf, NFT_MSG_GETSET, h->family,
NLM_F_DUMP, h->seq);
}
ret = mnl_talk(h, nlh, nftnl_set_list_cb, &d);
if (ret < 0 && errno == EINTR) {
assert(nft_restart(h) >= 0);
return ret;
}
if (t && set) {
struct nftnl_set *s;
s = nftnl_set_list_lookup_byname(h->cache->table[t->type].sets,
set);
set_fetch_elem_cb(s, h);
} else if (t) {
nftnl_set_list_foreach(h->cache->table[t->type].sets,
set_fetch_elem_cb, h);
} else {
for (i = 0; i < NFT_TABLE_MAX; i++) {
enum nft_table_type type = h->tables[i].type;
if (!h->tables[i].name)
continue;
nftnl_set_list_foreach(h->cache->table[type].sets,
set_fetch_elem_cb, h);
}
}
return ret;
}
static int fetch_chain_cache(struct nft_handle *h,
const struct builtin_table *t,
const char *chain)
{
struct nftnl_chain_list_cb_data d = {
.h = h,
.t = t,
};
char buf[16536];
struct nlmsghdr *nlh;
int i, ret;
if (!t) {
for (i = 0; i < NFT_TABLE_MAX; i++) {
enum nft_table_type type = h->tables[i].type;
if (!h->tables[i].name)
continue;
if (h->cache->table[type].chains)
continue;
h->cache->table[type].chains = nftnl_chain_list_alloc();
if (!h->cache->table[type].chains)
return -1;
}
} else if (!h->cache->table[t->type].chains) {
h->cache->table[t->type].chains = nftnl_chain_list_alloc();
if (!h->cache->table[t->type].chains)
return -1;
}
if (t && chain) {
struct nftnl_chain *c = nftnl_chain_alloc();
if (!c)
return -1;
nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN,
h->family, NLM_F_ACK,
h->seq);
nftnl_chain_set_str(c, NFTNL_CHAIN_TABLE, t->name);
nftnl_chain_set_str(c, NFTNL_CHAIN_NAME, chain);
nftnl_chain_nlmsg_build_payload(nlh, c);
nftnl_chain_free(c);
} else {
nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN,
h->family, NLM_F_DUMP,
h->seq);
}
ret = mnl_talk(h, nlh, nftnl_chain_list_cb, &d);
if (ret < 0 && errno == EINTR)
assert(nft_restart(h) >= 0);
return ret;
}
static int nftnl_rule_list_cb(const struct nlmsghdr *nlh, void *data)
{
struct nftnl_chain *c = data;
struct nftnl_rule *r;
r = nftnl_rule_alloc();
if (r == NULL)
return MNL_CB_OK;
if (nftnl_rule_nlmsg_parse(nlh, r) < 0) {
nftnl_rule_free(r);
return MNL_CB_OK;
}
nftnl_chain_rule_add_tail(r, c);
return MNL_CB_OK;
}
static int nft_rule_list_update(struct nftnl_chain *c, void *data)
{
struct nft_handle *h = data;
char buf[16536];
struct nlmsghdr *nlh;
struct nftnl_rule *rule;
int ret;
if (nftnl_rule_lookup_byindex(c, 0))
return 0;
rule = nftnl_rule_alloc();
if (!rule)
return -1;
nftnl_rule_set_str(rule, NFTNL_RULE_TABLE,
nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE));
nftnl_rule_set_str(rule, NFTNL_RULE_CHAIN,
nftnl_chain_get_str(c, NFTNL_CHAIN_NAME));
nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_GETRULE, h->family,
NLM_F_DUMP, h->seq);
nftnl_rule_nlmsg_build_payload(nlh, rule);
ret = mnl_talk(h, nlh, nftnl_rule_list_cb, c);
if (ret < 0 && errno == EINTR)
assert(nft_restart(h) >= 0);
nftnl_rule_free(rule);
if (h->family == NFPROTO_BRIDGE)
nft_bridge_chain_postprocess(h, c);
return 0;
}
static int fetch_rule_cache(struct nft_handle *h,
const struct builtin_table *t, const char *chain)
{
int i;
if (t) {
struct nftnl_chain_list *list;
struct nftnl_chain *c;
list = h->cache->table[t->type].chains;
if (chain) {
c = nftnl_chain_list_lookup_byname(list, chain);
return nft_rule_list_update(c, h);
}
return nftnl_chain_list_foreach(list, nft_rule_list_update, h);
}
for (i = 0; i < NFT_TABLE_MAX; i++) {
enum nft_table_type type = h->tables[i].type;
if (!h->tables[i].name)
continue;
if (nftnl_chain_list_foreach(h->cache->table[type].chains,
nft_rule_list_update, h))
return -1;
}
return 0;
}
static void
__nft_build_cache(struct nft_handle *h, enum nft_cache_level level,
const struct builtin_table *t, const char *set,
const char *chain)
{
uint32_t genid_start, genid_stop;
if (level <= h->cache_level)
return;
retry:
mnl_genid_get(h, &genid_start);
if (h->cache_level && genid_start != h->nft_genid)
flush_chain_cache(h, NULL);
switch (h->cache_level) {
case NFT_CL_NONE:
fetch_table_cache(h);
if (level == NFT_CL_TABLES)
break;
/* fall through */
case NFT_CL_TABLES:
fetch_chain_cache(h, t, chain);
if (level == NFT_CL_CHAINS)
break;
/* fall through */
case NFT_CL_CHAINS:
fetch_set_cache(h, t, set);
if (level == NFT_CL_SETS)
break;
/* fall through */
case NFT_CL_SETS:
fetch_rule_cache(h, t, chain);
if (level == NFT_CL_RULES)
break;
/* fall through */
case NFT_CL_RULES:
break;
}
mnl_genid_get(h, &genid_stop);
if (genid_start != genid_stop) {
flush_chain_cache(h, NULL);
goto retry;
}
if (!t && !chain)
h->cache_level = level;
else if (h->cache_level < NFT_CL_TABLES)
h->cache_level = NFT_CL_TABLES;
h->nft_genid = genid_start;
}
void nft_build_cache(struct nft_handle *h, struct nftnl_chain *c)
{
const struct builtin_table *t;
const char *table, *chain;
if (!c)
return __nft_build_cache(h, NFT_CL_RULES, NULL, NULL, NULL);
table = nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
chain = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
t = nft_table_builtin_find(h, table);
__nft_build_cache(h, NFT_CL_RULES, t, NULL, chain);
}
void nft_fake_cache(struct nft_handle *h)
{
int i;
fetch_table_cache(h);
for (i = 0; i < NFT_TABLE_MAX; i++) {
enum nft_table_type type = h->tables[i].type;
if (!h->tables[i].name)
continue;
h->cache->table[type].chains = nftnl_chain_list_alloc();
}
h->cache_level = NFT_CL_RULES;
mnl_genid_get(h, &h->nft_genid);
}
static void __nft_flush_cache(struct nft_handle *h)
{
if (!h->cache_index) {
h->cache_index++;
h->cache = &h->__cache[h->cache_index];
} else {
flush_chain_cache(h, NULL);
}
}
static int ____flush_rule_cache(struct nftnl_rule *r, void *data)
{
nftnl_rule_list_del(r);
nftnl_rule_free(r);
return 0;
}
static int __flush_rule_cache(struct nftnl_chain *c, void *data)
{
return nftnl_rule_foreach(c, ____flush_rule_cache, NULL);
}
int flush_rule_cache(struct nft_handle *h, const char *table,
struct nftnl_chain *c)
{
const struct builtin_table *t;
if (c)
return __flush_rule_cache(c, NULL);
t = nft_table_builtin_find(h, table);
if (!t || !h->cache->table[t->type].chains)
return 0;
return nftnl_chain_list_foreach(h->cache->table[t->type].chains,
__flush_rule_cache, NULL);
}
static int __flush_chain_cache(struct nftnl_chain *c, void *data)
{
nftnl_chain_list_del(c);
nftnl_chain_free(c);
return 0;
}
static int __flush_set_cache(struct nftnl_set *s, void *data)
{
nftnl_set_list_del(s);
nftnl_set_free(s);
return 0;
}
static int flush_cache(struct nft_handle *h, struct nft_cache *c,
const char *tablename)
{
const struct builtin_table *table;
int i;
if (tablename) {
table = nft_table_builtin_find(h, tablename);
if (!table)
return 0;
if (c->table[table->type].chains)
nftnl_chain_list_foreach(c->table[table->type].chains,
__flush_chain_cache, NULL);
if (c->table[table->type].sets)
nftnl_set_list_foreach(c->table[table->type].sets,
__flush_set_cache, NULL);
return 0;
}
for (i = 0; i < NFT_TABLE_MAX; i++) {
if (h->tables[i].name == NULL)
continue;
if (!c->table[i].chains)
continue;
nftnl_chain_list_free(c->table[i].chains);
c->table[i].chains = NULL;
if (c->table[i].sets)
nftnl_set_list_free(c->table[i].sets);
c->table[i].sets = NULL;
}
nftnl_table_list_free(c->tables);
c->tables = NULL;
return 1;
}
void flush_chain_cache(struct nft_handle *h, const char *tablename)
{
if (!h->cache_level)
return;
if (flush_cache(h, h->cache, tablename))
h->cache_level = NFT_CL_NONE;
}
void nft_rebuild_cache(struct nft_handle *h)
{
enum nft_cache_level level = h->cache_level;
if (h->cache_level)
__nft_flush_cache(h);
h->cache_level = NFT_CL_NONE;
__nft_build_cache(h, level, NULL, NULL, NULL);
}
void nft_release_cache(struct nft_handle *h)
{
if (h->cache_index)
flush_cache(h, &h->__cache[0], NULL);
}
struct nftnl_table_list *nftnl_table_list_get(struct nft_handle *h)
{
__nft_build_cache(h, NFT_CL_TABLES, NULL, NULL, NULL);
return h->cache->tables;
}
struct nftnl_set_list *
nft_set_list_get(struct nft_handle *h, const char *table, const char *set)
{
const struct builtin_table *t;
t = nft_table_builtin_find(h, table);
if (!t)
return NULL;
__nft_build_cache(h, NFT_CL_RULES, t, set, NULL);
return h->cache->table[t->type].sets;
}
struct nftnl_chain_list *
nft_chain_list_get(struct nft_handle *h, const char *table, const char *chain)
{
const struct builtin_table *t;
t = nft_table_builtin_find(h, table);
if (!t)
return NULL;
__nft_build_cache(h, NFT_CL_CHAINS, t, NULL, chain);
return h->cache->table[t->type].chains;
}
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