From: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
To: Giuseppe Longo <giuseppelng@gmail.com>
Cc: netfilter-devel@vger.kernel.org
Subject: Re: [xtables-arptables PATCH] xtables: Bootstrap xtables-arptables compatible tool for nftables
Date: Wed, 24 Jul 2013 11:21:09 +0300 [thread overview]
Message-ID: <51EF8E75.1080302@linux.intel.com> (raw)
In-Reply-To: <20130724075808.4219.71684.stgit@localhost>
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@gmail.com>
> ---
> 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@gmail.com>
> + *
> + * 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@gmail.com>
> + *
> + * 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@rustcorp.com.au and mneuling@radlogic.com.au
> + *
> + * Based on the ipchains code by Paul Russell and Michael Neuling
> + *
> + * (C) 2000-2002 by the netfilter coreteam <coreteam@netfilter.org>:
> + * Paul 'Rusty' Russell <rusty@rustcorp.com.au>
> + * Marc Boucher <marc+nf@mbsi.ca>
> + * James Morris <jmorris@intercode.com.au>
> + * Harald Welte <laforge@gnumonks.org>
> + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
> + *
> + * 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
prev parent reply other threads:[~2013-07-24 8:21 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-07-24 7:58 [xtables-arptables PATCH] xtables: Bootstrap xtables-arptables compatible tool for nftables Giuseppe Longo
2013-07-24 8:21 ` Tomasz Bursztyka [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=51EF8E75.1080302@linux.intel.com \
--to=tomasz.bursztyka@linux.intel.com \
--cc=giuseppelng@gmail.com \
--cc=netfilter-devel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).