This is a partial revert of commit 7462e4aa757dc28e74b4a731b3ee13079b04ef23
("iptables-compat: Keep xtables-config and xtables-events out from tree")
and re-adds xtables-events under a new name, with a few enhancements,
this is --trace mode, which replaces printk-based tracing, and an
imroved event mode which will now also display pid/name and new generation id
at the end of a batch.

Example output of xtables-monitor --event --trace

PACKET: 10 fa6b77e1 IN=wlan0 MACSRC=51:14:31:51:XX:XX MACDST=1c:b6:b0:ac:XX:XX 
MACPROTO=86dd SRC=2a00:3a0:2::1 DST=2b00:bf0:c001::1 LEN=1440 TC=18 HOPLIMIT=61 
FLOWLBL=1921 SPORT=22 DPORT=13024 ACK PSH
 TRACE: 10 fa6b77e1 raw:PREROUTING:return:
 TRACE: 10 fa6b77e1 raw:PREROUTING:policy:DROP
 TRACE: 10 fa6b77e1 filter:INPUT:return:
 TRACE: 10 fa6b77e1 filter:INPUT:policy:DROP
 EVENT: -6 -t mangle -A PREROUTING -j DNPT --src-pfx dead::/64 --dst-pfx 
1c3::/64
NEWGEN: GENID=6581 PID=15601 NAME=xtables-multi

Signed-off-by: Florian Westphal <[email protected]>
---
 Changes since v1:
  - allow filtering for ip(6)tables, but also allow listing both
  ipv4/ipv6 events
  - add fallback for nft-style events for base chains (hook prios etc)
  - change to -N/-X for user defined chain/add/del

 iptables/Makefile.am            |   3 +-
 iptables/xtables-compat-multi.c |   1 +
 iptables/xtables-monitor.c      | 647 ++++++++++++++++++++++++++++++++
 iptables/xtables-multi.c        |   1 -
 iptables/xtables-multi.h        |   2 +-
 5 files changed, 651 insertions(+), 3 deletions(-)
 create mode 100644 iptables/xtables-monitor.c

diff --git a/iptables/Makefile.am b/iptables/Makefile.am
index 2de142083c81..008d811045d5 100644
--- a/iptables/Makefile.am
+++ b/iptables/Makefile.am
@@ -41,6 +41,7 @@ xtables_compat_multi_SOURCES += xtables-config-parser.y 
xtables-config-syntax.l
 xtables_compat_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-arp-standalone.c xtables-arp.c \
                                getethertype.c nft-bridge.c \
                                xtables-eb-standalone.c xtables-eb.c \
@@ -76,7 +77,7 @@ x_sbin_links  = iptables-compat iptables-compat-restore 
iptables-compat-save \
                ip6tables-compat ip6tables-compat-restore ip6tables-compat-save 
\
                iptables-translate ip6tables-translate \
                iptables-restore-translate ip6tables-restore-translate \
-               arptables-compat ebtables-compat
+               arptables-compat ebtables-compat xtables-monitor
 endif
 
 iptables-extensions.8: iptables-extensions.8.tmpl ../extensions/matches.man 
../extensions/targets.man
diff --git a/iptables/xtables-compat-multi.c b/iptables/xtables-compat-multi.c
index 0b05eaded617..014e5a4e3c8f 100644
--- a/iptables/xtables-compat-multi.c
+++ b/iptables/xtables-compat-multi.c
@@ -35,6 +35,7 @@ static const struct subcommand multi_subcommands[] = {
        {"ebtables-compat",             xtables_eb_main},
        {"ebtables-translate",          xtables_eb_xlate_main},
        {"ebtables",                    xtables_eb_main},
+       {"xtables-monitor",             xtables_monitor_main},
        {NULL},
 };
 
diff --git a/iptables/xtables-monitor.c b/iptables/xtables-monitor.c
new file mode 100644
index 000000000000..09f9fb2ede34
--- /dev/null
+++ b/iptables/xtables-monitor.c
@@ -0,0 +1,647 @@
+/*
+ * (C) 2012-2013 by Pablo Neira Ayuso <[email protected]>
+ *
+ * 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 software has been sponsored by Sophos Astaro <http://www.sophos.com>
+ */
+
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <netinet/ether.h>
+#include <netinet/in.h>
+#include <netinet/ip6.h>
+#include <net/if_arp.h>
+#include <getopt.h>
+
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nf_tables.h>
+
+#include <libmnl/libmnl.h>
+#include <libnftnl/table.h>
+#include <libnftnl/trace.h>
+#include <libnftnl/chain.h>
+#include <libnftnl/rule.h>
+
+#include <include/xtables.h>
+#include "iptables.h" /* for xtables_globals */
+#include "xtables-multi.h"
+#include "nft.h"
+#include "nft-arp.h"
+
+struct cb_arg {
+       uint32_t nfproto;
+
+};
+
+static int table_cb(const struct nlmsghdr *nlh, void *data)
+{
+       uint32_t type = nlh->nlmsg_type & 0xFF;
+       const struct cb_arg *arg = data;
+       struct nftnl_table *t;
+       char buf[4096];
+
+       t = nftnl_table_alloc();
+       if (t == NULL)
+               goto err;
+
+       if (nftnl_table_nlmsg_parse(nlh, t) < 0)
+               goto err_free;
+
+       if (arg->nfproto && arg->nfproto != nftnl_table_get_u32(t, 
NFTNL_TABLE_FAMILY))
+               goto err_free;
+       nftnl_table_snprintf(buf, sizeof(buf), t, NFTNL_OUTPUT_DEFAULT, 0);
+       printf(" EVENT: ");
+       printf("nft: %s table: %s\n", type == NFT_MSG_NEWTABLE ? "NEW" : "DEL", 
buf);
+
+err_free:
+       nftnl_table_free(t);
+err:
+       return MNL_CB_OK;
+}
+
+static bool counters;
+static bool trace;
+static bool events;
+
+static int rule_cb(const struct nlmsghdr *nlh, void *data)
+{
+       struct arptables_command_state cs_arp = {};
+       struct iptables_command_state cs = {};
+       uint32_t type = nlh->nlmsg_type & 0xFF;
+       const struct cb_arg *arg = data;
+       struct nftnl_rule *r;
+       void *fw = NULL;
+       uint8_t family;
+
+       r = nftnl_rule_alloc();
+       if (r == NULL)
+               goto err;
+
+       if (nftnl_rule_nlmsg_parse(nlh, r) < 0)
+               goto err_free;
+
+       family = nftnl_rule_get_u32(r, NFTNL_RULE_FAMILY);
+       if (arg->nfproto && arg->nfproto != family)
+               goto err_free;
+
+       printf(" EVENT: ");
+       switch (family) {
+       case AF_INET:
+       case AF_INET6:
+               printf("-%c ", family == AF_INET ? '4' : '6');
+               nft_rule_to_iptables_command_state(r, &cs);
+               fw = &cs;
+               break;
+       case NFPROTO_ARP:
+               printf("-0 ");
+               nft_rule_to_arptables_command_state(r, &cs_arp);
+               fw = &cs_arp;
+               break;
+       default:
+               goto err_free;
+       }
+
+       printf("-t %s ", nftnl_rule_get_str(r, NFTNL_RULE_TABLE));
+       nft_rule_print_save(fw, r,
+                           type == NFT_MSG_NEWRULE ? NFT_RULE_APPEND :
+                                                          NFT_RULE_DEL,
+                           counters ? 0 : FMT_NOCOUNTS);
+err_free:
+       nftnl_rule_free(r);
+err:
+       return MNL_CB_OK;
+}
+
+static int chain_cb(const struct nlmsghdr *nlh, void *data)
+{
+       uint32_t type = nlh->nlmsg_type & 0xFF;
+       const struct cb_arg *arg = data;
+       struct nftnl_chain *c;
+       char buf[4096];
+       int family;
+
+       c = nftnl_chain_alloc();
+       if (c == NULL)
+               goto err;
+
+       if (nftnl_chain_nlmsg_parse(nlh, c) < 0)
+               goto err_free;
+
+       family = nftnl_chain_get_u32(c, NFTNL_CHAIN_FAMILY);
+       if (arg->nfproto && arg->nfproto != family)
+               goto err_free;
+
+       if (nftnl_chain_is_set(c, NFTNL_CHAIN_PRIO))
+               family = -1;
+
+       printf(" EVENT: ");
+       switch (family) {
+       case NFPROTO_IPV4:
+               family = 4;
+               break;
+       case NFPROTO_IPV6:
+               family = 6;
+               break;
+       default:
+               nftnl_chain_snprintf(buf, sizeof(buf), c, NFTNL_OUTPUT_DEFAULT, 
0);
+               printf("# nft: %s\n", buf);
+               goto err_free;
+       }
+
+       printf("-%d -t %s -%c %s\n",
+                       family,
+                       nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE),
+                       type == NFT_MSG_NEWCHAIN ? 'N' : 'X',
+                       nftnl_chain_get_str(c, NFTNL_CHAIN_NAME));
+err_free:
+       nftnl_chain_free(c);
+err:
+       return MNL_CB_OK;
+}
+
+static int newgen_cb(const struct nlmsghdr *nlh, void *data)
+{
+       uint32_t genid = 0, pid = 0;
+       const struct nlattr *attr;
+       const char *name = NULL;
+
+       mnl_attr_for_each(attr, nlh, sizeof(struct nfgenmsg)) {
+               switch (mnl_attr_get_type(attr)) {
+               case NFTA_GEN_ID:
+                       if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
+                               break;
+                       genid = ntohl(mnl_attr_get_u32(attr));
+                       break;
+               case NFTA_GEN_PROC_NAME:
+                       if (mnl_attr_validate(attr, MNL_TYPE_NUL_STRING) < 0)
+                               break;
+                       name = mnl_attr_get_str(attr);
+                       break;
+               case NFTA_GEN_PROC_PID:
+                       if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
+                               break;
+                       pid = ntohl(mnl_attr_get_u32(attr));
+                       break;
+               }
+       }
+
+       if (name)
+               printf("NEWGEN: GENID=%u PID=%u NAME=%s\n", genid, pid, name);
+
+       return MNL_CB_OK;
+}
+
+static void trace_print_return(const struct nftnl_trace *nlt)
+{
+       const char *chain = NULL;
+
+       if (nftnl_trace_is_set(nlt, NFTNL_TRACE_JUMP_TARGET)) {
+               chain = nftnl_trace_get_str(nlt, NFTNL_TRACE_JUMP_TARGET);
+               printf("%s", chain);
+       }
+}
+
+static void trace_print_rule(const struct nftnl_trace *nlt, struct cb_arg 
*args)
+{
+       uint64_t handle = nftnl_trace_get_u64(nlt, NFTNL_TRACE_RULE_HANDLE);
+       uint32_t family = nftnl_trace_get_u32(nlt, NFTNL_TRACE_FAMILY);
+       const char *table = nftnl_trace_get_str(nlt, NFTNL_TRACE_TABLE);
+       const char *chain = nftnl_trace_get_str(nlt, NFTNL_TRACE_CHAIN);
+        struct nftnl_rule *r;
+       struct mnl_socket *nl;
+       struct nlmsghdr *nlh;
+       uint32_t portid;
+       char buf[16536];
+       int ret;
+
+        r = nftnl_rule_alloc();
+       if (r == NULL) {
+               perror("OOM");
+               exit(EXIT_FAILURE);
+       }
+
+       nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_GETRULE, family, 
NLM_F_DUMP, 0);
+
+        nftnl_rule_set_u32(r, NFTNL_RULE_FAMILY, family);
+       nftnl_rule_set_str(r, NFTNL_RULE_CHAIN, chain);
+       nftnl_rule_set_str(r, NFTNL_RULE_TABLE, table);
+       nftnl_rule_set_u64(r, NFTNL_RULE_POSITION, handle);
+       nftnl_rule_nlmsg_build_payload(nlh, r);
+       nftnl_rule_free(r);
+
+       nl = mnl_socket_open(NETLINK_NETFILTER);
+       if (nl == NULL) {
+               perror("mnl_socket_open");
+               exit(EXIT_FAILURE);
+       }
+
+       if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
+               perror("mnl_socket_bind");
+               exit(EXIT_FAILURE);
+       }
+
+       portid = mnl_socket_get_portid(nl);
+        if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
+                perror("mnl_socket_send");
+                exit(EXIT_FAILURE);
+        }
+
+       ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
+        while (ret > 0) {
+                ret = mnl_cb_run(buf, ret, 0, portid, rule_cb, args);
+                if (ret <= 0)
+                        break;
+                ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
+        }
+        if (ret == -1) {
+                perror("error");
+                exit(EXIT_FAILURE);
+        }
+        mnl_socket_close(nl);
+}
+
+static void trace_print_packet(const struct nftnl_trace *nlt, struct cb_arg 
*args)
+{
+       struct list_head stmts = LIST_HEAD_INIT(stmts);
+       uint32_t nfproto, family;
+       uint16_t l4proto = 0;
+       uint32_t mark;
+       char name[IFNAMSIZ];
+
+       printf("PACKET: %d %08x ", args->nfproto, nftnl_trace_get_u32(nlt, 
NFTNL_TRACE_ID));
+
+       if (nftnl_trace_is_set(nlt, NFTNL_TRACE_IIF))
+               printf("IN=%s ", if_indextoname(nftnl_trace_get_u32(nlt, 
NFTNL_TRACE_IIF), name));
+       if (nftnl_trace_is_set(nlt, NFTNL_TRACE_OIF))
+               printf("OUT=%s ", if_indextoname(nftnl_trace_get_u32(nlt, 
NFTNL_TRACE_OIF), name));
+
+       family = nftnl_trace_get_u32(nlt, NFTNL_TRACE_FAMILY);
+       nfproto = family;
+       if (nftnl_trace_is_set(nlt, NFTNL_TRACE_NFPROTO)) {
+               nfproto = nftnl_trace_get_u32(nlt, NFTNL_TRACE_NFPROTO);
+
+               if (family != nfproto)
+                       printf("NFPROTO=%d ", nfproto);
+       }
+
+       if (nftnl_trace_is_set(nlt, NFTNL_TRACE_LL_HEADER)) {
+               const struct ethhdr *eh;
+               const char *linklayer;
+               uint32_t i, len;
+               uint16_t type = nftnl_trace_get_u16(nlt, NFTNL_TRACE_IIFTYPE);
+
+               linklayer = nftnl_trace_get_data(nlt, NFTNL_TRACE_LL_HEADER, 
&len);
+               switch (type) {
+               case ARPHRD_ETHER:
+                       if (len < sizeof(*eh))
+                              break;
+                       eh = (const void *)linklayer;
+                       printf("MACSRC=%s ", ether_ntoa((const void 
*)eh->h_source));
+                       printf("MACDST=%s ", ether_ntoa((const void 
*)eh->h_dest));
+                       printf("MACPROTO=%04x ", ntohs(eh->h_proto));
+                       break;
+               default:
+                       printf("LL=0x%x ", type);
+                       for (i = 0 ; i < len; i++)
+                               printf("%02x", linklayer[i]);
+                       printf(" ");
+                       break;
+               }
+       }
+
+       if (nftnl_trace_is_set(nlt, NFTNL_TRACE_NETWORK_HEADER)) {
+               const struct ip6_hdr *ip6h;
+               const struct iphdr *iph;
+               uint32_t i, len;
+               const char *nh;
+
+               ip6h = nftnl_trace_get_data(nlt, NFTNL_TRACE_NETWORK_HEADER, 
&len);
+
+               switch (nfproto) {
+               case NFPROTO_IPV4: {
+                       char addrbuf[INET_ADDRSTRLEN];
+
+                       if (len < sizeof(*iph))
+                               break;
+                       iph = (const void *)ip6h;
+
+
+                       inet_ntop(AF_INET, &iph->saddr, addrbuf, 
sizeof(addrbuf));
+                       printf("SRC=%s ", addrbuf);
+                       inet_ntop(AF_INET, &iph->daddr, addrbuf, 
sizeof(addrbuf));
+                       printf("DST=%s ", addrbuf);
+
+                       printf("LEN=%d TOS=0x%x TTL=%d ID=%d", 
ntohs(iph->tot_len), iph->tos, iph->ttl, ntohs(iph->id));
+                       if (iph->frag_off & htons(0x8000))
+                               printf("CE ");
+                       if (iph->frag_off & htons(IP_DF))
+                               printf("DF ");
+                       if (iph->frag_off & htons(IP_MF))
+                               printf("MF ");
+
+                       if (ntohs(iph->frag_off) & 0x1fff)
+                               printf("FRAG:%u ", ntohs(iph->frag_off) & 
0x1fff);
+
+                       // TRACE: raw:OUTPUT:rule:1 IN= OUT=wlp58s0 
SRC=217.197.81.41 DST=146.0.238.67 LEN=88 TOS=0x12 PREC=0x00 TTL=64 ID=34694 DF 
PROTO=TCP SPT=52432 DPT=22 SEQ=2308055971 ACK=3782479795 WINDOW=1444 RES=0x00 
ACK PSH URGP=0 OPT (0101080A8D509CFA47870333) UID=1000 GID=1000
+                       l4proto = iph->protocol;
+                       if (iph->ihl * 4 > sizeof(*iph)) {
+                               unsigned int optsize;
+                               const char *op;
+
+                               optsize = iph->ihl * 4 - sizeof(*iph);
+                               op = (const char *)iph;
+                               op += sizeof(*iph);
+
+                               printf("OPT (");
+                               for (i = 0; i < optsize; i++)
+                                       printf("%02X", op[i]);
+                               printf(")");
+                       }
+                       break;
+               }
+               case NFPROTO_IPV6: {
+                       uint32_t flowlabel = ntohl(*(uint32_t *)ip6h);
+                       char addrbuf[INET6_ADDRSTRLEN];
+
+                       if (len < sizeof(*ip6h))
+                               break;
+
+                       inet_ntop(AF_INET6, &ip6h->ip6_src, addrbuf, 
sizeof(addrbuf));
+                       printf("SRC=%s ", addrbuf);
+                       inet_ntop(AF_INET6, &ip6h->ip6_dst, addrbuf, 
sizeof(addrbuf));
+                       printf("DST=%s ", addrbuf);
+
+                       printf("LEN=%zu TC=%u HOPLIMIT=%u FLOWLBL=%u ",
+                               ntohs(ip6h->ip6_plen) + sizeof(*iph),
+                               (flowlabel & 0x0ff00000) >> 20,
+                               ip6h->ip6_hops,
+                               flowlabel & 0x000fffff);
+
+                       l4proto = ip6h->ip6_nxt;
+                       break;
+               }
+               default:
+                       nh = (const char *)ip6h;
+                       printf("NH=");
+                       for (i = 0 ; i < len; i++)
+                               printf("%02x", nh[i]);
+                       printf(" ");
+               }
+       }
+
+       if (nftnl_trace_is_set(nlt, NFTNL_TRACE_TRANSPORT_HEADER)) {
+               const struct tcphdr *tcph;
+               uint32_t len;
+
+               tcph = nftnl_trace_get_data(nlt, NFTNL_TRACE_TRANSPORT_HEADER, 
&len);
+
+               switch (l4proto) {
+               case IPPROTO_DCCP:
+               case IPPROTO_SCTP:
+               case IPPROTO_UDPLITE:
+               case IPPROTO_UDP:
+                       if (len < 4)
+                               break;
+                       printf("SPORT=%d DPORT=%d ", ntohs(tcph->th_sport), 
ntohs(tcph->th_dport));
+                       break;
+               case IPPROTO_TCP:
+                       if (len < sizeof(*tcph))
+                               break;
+                       printf("SPORT=%d DPORT=%d ", ntohs(tcph->th_sport), 
ntohs(tcph->th_dport));
+                       if (tcph->th_flags & 
(TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG)) {
+                               if (tcph->th_flags & TH_SYN)
+                                       printf("SYN ");
+                               if (tcph->th_flags & TH_ACK)
+                                       printf("ACK ");
+                               if (tcph->th_flags & TH_FIN)
+                                       printf("FIN ");
+                               if (tcph->th_flags & TH_RST)
+                                       printf("RST ");
+                               if (tcph->th_flags & TH_PUSH)
+                                       printf("PSH ");
+                               if (tcph->th_flags & TH_URG)
+                                       printf("URG ");
+                       }
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       mark = nftnl_trace_get_u32(nlt, NFTNL_TRACE_MARK);
+       if (mark)
+               printf("MARK=0x%x ", mark);
+}
+
+static int trace_cb(const struct nlmsghdr *nlh, struct cb_arg *arg)
+{
+       struct nftnl_trace *nlt;
+
+       nlt = nftnl_trace_alloc();
+       if (nlt == NULL)
+               goto err;
+
+       if (nftnl_trace_nlmsg_parse(nlh, nlt) < 0)
+               goto err_free;
+
+       if (arg->nfproto &&
+           arg->nfproto != nftnl_trace_get_u32(nlt, NFTNL_TABLE_FAMILY))
+               goto err_free;
+
+       printf(" TRACE: %d %08x %s:%s", nftnl_trace_get_u32(nlt, 
NFTNL_TABLE_FAMILY),
+                                       nftnl_trace_get_u32(nlt, 
NFTNL_TRACE_ID),
+                                       nftnl_trace_get_str(nlt, 
NFTNL_TRACE_TABLE),
+                                       nftnl_trace_get_str(nlt, 
NFTNL_TRACE_CHAIN));
+
+       switch (nftnl_trace_get_u32(nlt, NFTNL_TRACE_TYPE)) {
+       case NFT_TRACETYPE_RULE:
+               printf(":rule:0x%llx ", (unsigned long 
long)nftnl_trace_get_u64(nlt, NFTNL_TRACE_RULE_HANDLE));
+
+               if (nftnl_trace_is_set(nlt, NFTNL_TRACE_RULE_HANDLE))
+                       trace_print_rule(nlt, arg);
+               if (nftnl_trace_is_set(nlt, NFTNL_TRACE_LL_HEADER) ||
+                   nftnl_trace_is_set(nlt, NFTNL_TRACE_NETWORK_HEADER))
+                       trace_print_packet(nlt, arg);
+               break;
+       case NFT_TRACETYPE_POLICY: {
+               uint32_t verdict;
+
+               printf(":policy:");
+               verdict = nftnl_trace_get_u32(nlt, NFTNL_TRACE_VERDICT);
+
+               switch(verdict) {
+               case NF_ACCEPT:
+                       printf("ACCEPT");
+                       break;
+                break;
+               case NF_DROP:
+                       printf("DROP");
+                       break;
+               default: /* Would be a kernel bug - policy must be ACCEPT or 
DROP */
+                       printf("%d", verdict);
+                       break;
+               }
+       }
+               break;
+       case NFT_TRACETYPE_RETURN:
+               printf(":return:");
+               trace_print_return(nlt);
+               break;
+       }
+       puts("");
+err_free:
+       nftnl_trace_free(nlt);
+err:
+       return MNL_CB_OK;
+}
+
+static int monitor_cb(const struct nlmsghdr *nlh, void *data)
+{
+       uint32_t type = nlh->nlmsg_type & 0xFF;
+       int ret = MNL_CB_OK;
+
+       switch(type) {
+       case NFT_MSG_NEWTABLE:
+       case NFT_MSG_DELTABLE:
+               ret = table_cb(nlh, data);
+               break;
+       case NFT_MSG_NEWCHAIN:
+       case NFT_MSG_DELCHAIN:
+               ret = chain_cb(nlh, data);
+               break;
+       case NFT_MSG_NEWRULE:
+       case NFT_MSG_DELRULE:
+               ret = rule_cb(nlh, data);
+               break;
+       case NFT_MSG_NEWGEN:
+               ret = newgen_cb(nlh, data);
+               break;
+       case NFT_MSG_TRACE:
+               ret = trace_cb(nlh, data);
+               break;
+       }
+
+       return ret;
+}
+
+static const struct option options[] = {
+       {.name = "counters", .has_arg = false, .val = 'c'},
+       {.name = "trace", .has_arg = false, .val = 't'},
+       {.name = "monitor", .has_arg = false, .val = 'm'},
+       {.name = "ipv4", .has_arg = false, .val = '4'},
+       {.name = "ipv6", .has_arg = false, .val = '6'},
+       {NULL},
+};
+
+static void print_usage(void)
+{
+       printf("%s %s\n", xtables_globals.program_name,
+                         xtables_globals.program_version);
+       printf("Usage: %s [ -t | -e ]\n"
+              "        --trace    -t    trace ruleset traversal of packets 
tagged via -j TRACE rule\n"
+              "        --event    -e    show events  taht modify the ruleset\n"
+              "Optional arguments:\n"
+              "        --ipv4     -4    only monitor ipv4\n"
+              "        --ipv6     -6    only monitor ipv6\n"
+              "        --counters -c    show counters in rules\n"
+
+              , xtables_globals.program_name);
+       exit(EXIT_FAILURE);
+}
+
+int xtables_monitor_main(int argc, char *argv[])
+{
+       struct mnl_socket *nl;
+       char buf[MNL_SOCKET_BUFFER_SIZE];
+       uint32_t nfgroup = 0;
+       struct cb_arg cb_arg;
+       int ret, c;
+
+       xtables_globals.program_name = "xtables-monitor";
+       /* XXX xtables_init_all does several things we don't want */
+       c = xtables_init_all(&xtables_globals, NFPROTO_IPV4);
+       if (c < 0) {
+               fprintf(stderr, "%s/%s Failed to initialize xtables\n",
+                               xtables_globals.program_name,
+                               xtables_globals.program_version);
+               exit(1);
+       }
+#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS)
+       init_extensions();
+       init_extensions4();
+#endif
+
+       memset(&cb_arg, 0, sizeof(cb_arg));
+       opterr = 0;
+       while ((c = getopt_long(argc, argv, "ceht46", options, NULL)) != -1) {
+               switch (c) {
+               case 'c':
+                       counters = true;
+                       break;
+               case 't':
+                       trace = true;
+                       break;
+               case 'e':
+                       events = true;
+                       break;
+               case 'h':
+                       print_usage();
+                       exit(0);
+               case '4':
+                       cb_arg.nfproto = NFPROTO_IPV4;
+                       break;
+               case '6':
+                       cb_arg.nfproto = NFPROTO_IPV6;
+                       break;
+               default:
+                       fprintf(stderr, "xtables-monitor %s: Bad argument.\n", 
XTABLES_VERSION);
+                       fprintf(stderr, "Try `xtables-monitor -h' for more 
information.");
+                       exit(PARAMETER_PROBLEM);
+               }
+       }
+
+       if (trace)
+               nfgroup |= 1 << (NFNLGRP_NFTRACE - 1);
+       if (events)
+               nfgroup |= 1 << (NFNLGRP_NFTABLES - 1);
+
+       if (nfgroup == 0) {
+               print_usage();
+               exit(EXIT_FAILURE);
+       }
+
+       nl = mnl_socket_open(NETLINK_NETFILTER);
+       if (nl == NULL) {
+               perror("cannot open nfnetlink socket");
+               exit(EXIT_FAILURE);
+       }
+
+       if (mnl_socket_bind(nl, nfgroup, MNL_SOCKET_AUTOPID) < 0) {
+               perror("cannot bind to nfnetlink socket");
+               exit(EXIT_FAILURE);
+       }
+
+       ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
+       while (ret > 0) {
+               ret = mnl_cb_run(buf, ret, 0, 0, monitor_cb, &cb_arg);
+               if (ret <= 0)
+                       break;
+               ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
+       }
+       if (ret == -1) {
+               perror("cannot receive from nfnetlink socket");
+               exit(EXIT_FAILURE);
+       }
+       mnl_socket_close(nl);
+
+       return EXIT_SUCCESS;
+}
+
diff --git a/iptables/xtables-multi.c b/iptables/xtables-multi.c
index 30391e7fec7f..e90885ddb0fd 100644
--- a/iptables/xtables-multi.c
+++ b/iptables/xtables-multi.c
@@ -41,7 +41,6 @@ static const struct subcommand multi_subcommands[] = {
        {"xtables-save",        xtables_save_main},
        {"xtables-restore",     xtables_restore_main},
        {"xtables-config",      xtables_config_main},
-       {"xtables-events",      xtables_events_main},
        {"xtables-arp",         xtables_arp_main},
        {"xtables-ebtables",    xtables_eb_main},
 #endif
diff --git a/iptables/xtables-multi.h b/iptables/xtables-multi.h
index f0c14ea42ed4..82ee9c9dbcab 100644
--- a/iptables/xtables-multi.h
+++ b/iptables/xtables-multi.h
@@ -17,7 +17,7 @@ extern int xtables_ip6_xlate_restore_main(int, char **);
 extern int xtables_arp_main(int, char **);
 extern int xtables_eb_main(int, char **);
 extern int xtables_config_main(int, char **);
-extern int xtables_events_main(int, char **);
+extern int xtables_monitor_main(int, char **);
 #endif
 
 #endif /* _XTABLES_MULTI_H */
-- 
2.17.1

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

Reply via email to