Re: [xtables-arptables PATCH] xtables: Bootstrap xtables-arptables compatible tool for nftables

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Giuseppe,

Some issues. You should take into account your previous refactoring patches.
See:

xtables: Bootstrap xtables-arptables compatible tool for nftables

Signed-off-by: Giuseppe Longo <giuseppelng@xxxxxxxxx>
---
  iptables/Makefile.am                    |    4
  iptables/nft-arptables.c                |  214 ++++
  iptables/nft-arptables.h                |   95 ++
  iptables/xtables-arptables-standalone.c |   58 +
  iptables/xtables-arptables.c            | 1632 +++++++++++++++++++++++++++++++
  iptables/xtables-multi.c                |    1
  iptables/xtables-multi.h                |    1
  7 files changed, 2004 insertions(+), 1 deletions(-)
  create mode 100644 iptables/nft-arptables.c
  create mode 100644 iptables/nft-arptables.h
  create mode 100644 iptables/xtables-arptables-standalone.c
  create mode 100644 iptables/xtables-arptables.c

diff --git a/iptables/Makefile.am b/iptables/Makefile.am
index fb26a32..ac9edf6 100644
--- a/iptables/Makefile.am
+++ b/iptables/Makefile.am
@@ -31,7 +31,9 @@ xtables_multi_SOURCES += xtables-config-parser.y xtables-config-syntax.l
  xtables_multi_SOURCES += xtables-save.c xtables-restore.c \
  			 xtables-standalone.c xtables.c nft.c \
  			 nft-shared.c nft-ipv4.c nft-ipv6.c \
-			 xtables-config.c xtables-events.c
+			 xtables-config.c xtables-events.c \
+			 nft-arptables.c xtables-arptables.c \
+			 xtables-arptables-standalone.c			
  xtables_multi_LDADD   += -lmnl -lnftables ${libmnl_LIBS} ${libnftables_LIBS}
  xtables_multi_CFLAGS  += -DENABLE_NFTABLES
  # yacc and lex generate dirty code
diff --git a/iptables/nft-arptables.c b/iptables/nft-arptables.c
new file mode 100644
index 0000000..ef9dfdd
--- /dev/null
+++ b/iptables/nft-arptables.c
@@ -0,0 +1,214 @@
+/*
+ * (C) 2013 by Giuseppe Longo <giuseppelng@xxxxxxxxx>
+ *
+ * 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.
+ */
+
+#include <errno.h>
+
+#include <linux/netlink.h>
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nf_tables.h>
+#include <linux/netfilter/nf_tables_compat.h>
+
+#include <libiptc/libxtc.h>
+#include <libiptc/xtcshared.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <netinet/ip6.h>
+
+#include <libmnl/libmnl.h>
+#include <libnftables/table.h>
+#include <libnftables/chain.h>
+#include <libnftables/rule.h>
+#include <libnftables/expr.h>
+
+#include "nft-arptables.h"
+#include "xshared.h" /* proto_to_name */
+#include "nft-shared.h"
+#include "xtables-config-parser.h"
+
+extern struct builtin_table arp_tables[TABLES_MAX] = {

No need of extern keyword here.

+	[FILTER] = {
+		.name	= "filter",
+		.chains = {
+			{
+				.name	= "INPUT",
+				.type	= "filter",
+				.prio	= 0,	/* NF_IP_PRI_FILTER */
+				.hook	= NF_INET_LOCAL_IN,
+			},
+			{
+				.name	= "FORWARD",
+				.type	= "filter",
+				.prio	= 0,	/* NF_IP_PRI_FILTER */
+				.hook	= NF_INET_FORWARD,
+			},
+			{
+				.name	= "OUTPUT",
+				.type	= "filter",
+				.prio	= 0,	/* NF_IP_PRI_FILTER */
+				.hook	= NF_INET_LOCAL_OUT,
+			},
+		},
+	},
+};
+
+static int
+nft_arp_chain_user_add(struct nft_handle *h, const char *chain,

No need of that function. You can use nft_chain_user_add() from nft.c, just make it public. Now that from your previous patches, nft_handle is owning the builtin_table pointer.

+		       const char *table)
+{
+	char buf[MNL_SOCKET_BUFFER_SIZE];
+	struct nlmsghdr *nlh;
+	struct nft_chain *c;
+	int ret;
+
+	/* If built-in chains don't exist for this table, create them */
+	if (nft_xtables_config_load(h, ARPTABLES_CONFIG_DEFAULT, 0) < 0)
+		nft_chain_builtin_init(h, table, NULL, NF_ACCEPT);
+
+	nft_chain_builtin_init(h, table, NULL, NF_ACCEPT);
+
+	c = nft_chain_alloc();
+	if (c == NULL) {
+		DEBUGP("cannot allocate chain\n");
+		return -1;
+	}
+
+	nft_chain_attr_set(c, NFT_CHAIN_ATTR_TABLE, (char *)table);
+	nft_chain_attr_set(c, NFT_CHAIN_ATTR_NAME, (char *)chain);
+
+	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family,
+                                       NLM_F_ACK|NLM_F_EXCL, h->seq);
+	nft_chain_nlmsg_build_payload(nlh, c);
+	nft_chain_free(c);
+
+	ret = mnl_talk(h, nlh, NULL, NULL);
+	if (ret < 0) {
+		if (errno != EEXIST)
+			perror("mnl_talk:nft_chain_add");
+	}
+
+	/* the core expects 1 for success and 0 for error */
+	return ret == 0 ? 1 : 0;
+}
+
+static const char *policy_name[NF_ACCEPT+1] = {
+	[NF_DROP] = "DROP",
+	[NF_ACCEPT] = "ACCEPT",
+};
+
+static void
+print_header(unsigned int format, const char *chain, const char *pol,
+            const struct xt_counters *counters, bool basechain, uint32_t refs)
+{
+	printf("Chain %s", chain);
+	if (basechain) {
+		printf(" (policy %s", pol);
+		if (!(format & FMT_NOCOUNTS)) {
+			fputc(' ', stdout);
+			print_num(counters->pcnt, (format|FMT_NOTABLE));
+			fputs("packets, ", stdout);
+			print_num(counters->bcnt, (format|FMT_NOTABLE));
+			fputs("bytes", stdout);
+		}
+		printf(")\n");
+	} else {
+		printf(" (%u references)\n", refs);
+	}
+
+	if (format & FMT_LINENUMBERS)
+		printf(FMT("%-4s ", "%s "), "num");
+	if (!(format & FMT_NOCOUNTS)) {
+		if (format & FMT_KILOMEGAGIGA) {
+			printf(FMT("%5s ","%s "), "pkts");
+			printf(FMT("%5s ","%s "), "bytes");
+		} else {
+			printf(FMT("%8s ","%s "), "pkts");
+			printf(FMT("%10s ","%s "), "bytes");
+		}
+	}
+	if (!(format & FMT_NOTARGET))
+		printf(FMT("%-9s ","%s "), "target");
+	fputs(" prot ", stdout);
+	if (format & FMT_OPTIONS)
+		fputs("opt", stdout);
+	if (format & FMT_VIA) {
+		printf(FMT(" %-6s ","%s "), "in");
+		printf(FMT("%-6s ","%s "), "out");
+	}
+	printf(FMT(" %-19s ","%s "), "source");
+	printf(FMT(" %-19s "," %s "), "destination");
+	printf("\n");
+}
+
+static int
+nft_arp_rule_list(struct nft_handle *h, const char *chain, const char *table,

Ok here you need it, since nft_rule_list from nft.c is using internal print_headers, which is proper to xtables.c (Though we could think of refactoring to make a generic function, let's say nft_rule_list_full() which would take in 2 more parameters: the print_headers function pointer, and the callback pointer given to __nft_rule_list() inside).

+		  int rulenum, unsigned int format)
+{
+	struct nft_chain_list *list;
+	struct nft_chain_list_iter *iter;
+	struct nft_chain *c;
+	bool found = false;
+
+	/* If built-in chains don't exist for this table, create them */
+	if (nft_xtables_config_load(h, ARPTABLES_CONFIG_DEFAULT, 0) < 0)
+		nft_chain_builtin_init(h, table, NULL, NF_ACCEPT);

And this is now useless since it's called once in nft_init() with your previous patches.

+
+	list = nft_chain_dump(h);
+
+	iter = nft_chain_list_iter_create(list);
+	if (iter == NULL) {
+		DEBUGP("cannot allocate rule list iterator\n");
+		return 0;
+	}
+
+	c = nft_chain_list_iter_next(iter);
+	while (c != NULL) {
+		const char *chain_table =
+			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
+		const char *chain_name =
+			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
+		uint32_t policy =
+			nft_chain_attr_get_u32(c, NFT_CHAIN_ATTR_POLICY);
+		uint32_t refs =
+			nft_chain_attr_get_u32(c, NFT_CHAIN_ATTR_USE);
+		struct xt_counters ctrs = {
+			.pcnt = nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_PACKETS),
+			.bcnt = nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_BYTES),
+		};
+		bool basechain = false;
+
+		if (nft_chain_attr_get(c, NFT_CHAIN_ATTR_HOOKNUM))
+			basechain = true;
+
+		if (strcmp(table, chain_table) != 0)
+			goto next;
+		if (chain && strcmp(chain, chain_name) != 0)
+			goto next;
+
+		if (found) printf("\n");
+
+		print_header(format, chain_name, policy_name[policy], &ctrs,
+				basechain, refs);
+
+		//__nft_rule_list(h, c, table, rulenum, format, print_firewall);
+
+		found = true;
+
+next:
+		c = nft_chain_list_iter_next(iter);
+	}
+
+	nft_chain_list_free(list);
+
+	return 1;
+}
diff --git a/iptables/nft-arptables.h b/iptables/nft-arptables.h
new file mode 100644
index 0000000..e573324
--- /dev/null
+++ b/iptables/nft-arptables.h
@@ -0,0 +1,95 @@
+/*
+ * (C) 2013 by Giuseppe Longo <giuseppelng@xxxxxxxxx>
+ *
+ * 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.
+ */
+#ifndef _NFT_ARPTABLES_H_
+#define _NFT_ARPTABLES_H_
+
+#include "nft.h"
+
+typedef char arpt_chainlabel[32];
+
+enum exittype {
+	OTHER_PROBLEM = 1,
+	PARAMETER_PROBLEM,
+	VERSION_PROBLEM
+};
+
+/*******************************/
+/* REMOVE LATER, PUT IN KERNEL */
+/*******************************/
+struct arpt_entry_match
+{
+	int iets;
+};
+
+/*******************************/
+/* END OF KERNEL REPLACEMENTS  */
+/*******************************/
+
+/* Include file for additions: new matches and targets. */
+
+struct arptables_match
+{
+	struct arptables_match *next;
+
+	arpt_chainlabel name;
+
+	const char *version;
+
+	/* Size of match data. */
+	size_t size;
+
+	/* Size of match data relevent for userspace comparison purposes */
+	size_t userspacesize;
+
+	/* Function which prints out usage message. */
+	void (*help)(void);
+
+	/* Initialize the match. */
+	void (*init)(struct arpt_entry_match *m, unsigned int *nfcache);
+
+	/* Function which parses command options; returns true if it
+		ate an option */
+	int (*parse)(int c, char **argv, int invert, unsigned int *flags,
+			const struct arpt_entry *entry,
+			unsigned int *nfcache,
+			struct arpt_entry_match **match);
+
+	/* Final check; exit if not ok. */
+	void (*final_check)(unsigned int flags);
+
+	/* Prints out the match iff non-NULL: put space at end */
+	void (*print)(const struct arpt_arp *ip,
+			const struct arpt_entry_match *match, int numeric);
+
+	/* Saves the match info in parsable form to stdout. */
+	void (*save)(const struct arpt_arp *ip,
+			const struct arpt_entry_match *match);
+
+	/* Pointer to list of extra command-line options */
+	const struct option *extra_opts;
+
+	/* Ignore these men behind the curtain: */
+	unsigned int option_offset;
+	struct arpt_entry_match *m;
+	unsigned int mflags;
+	unsigned int used;
+	unsigned int loaded; /* simulate loading so options are merged properly */
+};
+
+const char *program_name, *program_version;
+
+/* For nft_arptables.c */
+int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table);
+
+/*
+ * Parse config for tables and chain helper functions
+ */
+#define ARPTABLES_CONFIG_DEFAULT  "/etc/arptables.conf"
+
+#endif
diff --git a/iptables/xtables-arptables-standalone.c b/iptables/xtables-arptables-standalone.c
new file mode 100644
index 0000000..a98ceea
--- /dev/null
+++ b/iptables/xtables-arptables-standalone.c
@@ -0,0 +1,58 @@
+/*
+ * Author: Paul.Russell@xxxxxxxxxxxxxxx and mneuling@xxxxxxxxxxxxxxx
+ *
+ * Based on the ipchains code by Paul Russell and Michael Neuling
+ *
+ * (C) 2000-2002 by the netfilter coreteam <coreteam@xxxxxxxxxxxxx>:
+ * 		    Paul 'Rusty' Russell <rusty@xxxxxxxxxxxxxxx>
+ * 		    Marc Boucher <marc+nf@xxxxxxx>
+ * 		    James Morris <jmorris@xxxxxxxxxxxxxxxx>
+ * 		    Harald Welte <laforge@xxxxxxxxxxxx>
+ * 		    Jozsef Kadlecsik <kadlec@xxxxxxxxxxxxxxxxx>
+ *
+ *	arptables -- IP firewall administration for kernels with
+ *	firewall table (aimed for the 2.3 kernels)
+ *
+ *	See the accompanying manual page arptables(8) for information
+ *	about proper usage of this program.
+ *
+ *	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 program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program; if not, write to the Free Software
+ *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include "nft-arptables.h"
+
+int
+xtables_arptables_main(int argc, char *argv[])
+{
+	int ret;
+	char *table = "filter";
+	extern struct builtin_table arp_tables[TABLES_MAX];

No, global variable should be put as global. And anyway here you don't need it (put it in xtables-arptables.c)

+        struct nft_handle h = {
+                .family = NFPROTO_ARP,
+        };
+
+	program_name = "xtables-arptables";
+
+	nft_init(&h, arp_tables, ARPTABLES_CONFIG_DEFAULT);

Don't call nft_init() here. Let do_commandarp() do this (we initialize NFT if only the command is properly parsed).

+
+	ret = do_commandarp(&h, argc, argv, &table);
+
+	exit(!ret);
+}
+
diff --git a/iptables/xtables-arptables.c b/iptables/xtables-arptables.c
new file mode 100644
index 0000000..fc3c2ff
--- /dev/null
+++ b/iptables/xtables-arptables.c
@@ -0,0 +1,1632 @@
+/* Code to take an arptables-style command line and do it. */
+

(...)

+		default:
+			break;
+			/* FIXME: This scheme doesn't allow two of the same
+				matches --RR */
+			/*if (!target
+				|| !(target->parse(c - target->option_offset,
+						argv, invert,
+						&target->tflags,
+						&fw, &target->t))) {*/
+	/*
+				for (m = arptables_matches; m; m = m->next) {
+					if (!m->used)
+						continue;
+
+					if (m->parse(c - m->option_offset,
+							argv, invert,
+							&m->mflags,
+							&fw,
+							&fw.nfcache,
+							&m->m))
+						break;
+				}
+*/
+
+				/* If you listen carefully, you can
+					actually hear this code suck. */
+
+				/* some explanations (after four different bugs
+				* in 3 different releases): If we encountere a
+				* parameter, that has not been parsed yet,
+				* it's not an option of an explicitly loaded
+				* match or a target.  However, we support
+				* implicit loading of the protocol match
+				* extension.  '-p tcp' means 'l4 proto 6' and
+				* at the same time 'load tcp protocol match on
+				* demand if we specify --dport'.
+				*
+				* To make this work, we need to make sure:
+				* - the parameter has not been parsed by
+				*   a match (m above)
+				* - a protocol has been specified
+				* - the protocol extension has not been
+				*   loaded yet, or is loaded and unused
+				*   [think of arptables-restore!]
+				* - the protocol extension can be successively
+				*   loaded
+				*/
+/*
+				if (m == NULL
+					&& protocol
+					&& (!find_proto(protocol, DONT_LOAD,
+							options&OPT_NUMERIC)
+					|| (find_proto(protocol, DONT_LOAD,
+							options&OPT_NUMERIC)
+						&& (proto_used == 0))
+					)
+					&& (m = find_proto(protocol, TRY_LOAD,
+							options&OPT_NUMERIC))) {
+					Try loading protocol */
+/*
+					size_t size;
+
+					proto_used = 1;
+
+					size = ARPT_ALIGN(sizeof(struct arpt_entry_match))
+							+ m->size;
+
+					m->m = fw_calloc(1, size);
+					m->m->u.match_size = size;
+					strcpy(m->m->u.user.name, m->name);
+					m->init(m->m, &fw.nfcache);
+
+					opts = merge_options(opts,
+						m->extra_opts, &m->option_offset);
+
+					optind--;
+					continue;
+				}
+				if (!m)
+					exit_error(PARAMETER_PROBLEM,
+							"Unknown arg `%s'",
+							argv[optind-1]);
+*/
+                       //}
+		}
+		invert = FALSE;
+	}

You need to call nft_init() here, as in xtables.c

Cheers,

Tomasz
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux