/* * (C) 2012-2013 by Pablo Neira Ayuso * * 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 */ #include #include #include #include #include #include #include #include #include #include #include #include #include "iptables.h" /* for xtables_globals */ #include "xtables-multi.h" #include "nft.h" static int table_cb(const struct nlmsghdr *nlh, int type) { struct nft_table *t; char buf[4096]; t = nft_table_alloc(); if (t == NULL) { perror("OOM"); goto err; } if (nft_table_nlmsg_parse(nlh, t) < 0) { perror("nft_table_nlmsg_parse"); goto err_free; } nft_table_snprintf(buf, sizeof(buf), t, NFT_TABLE_O_DEFAULT, 0); /* FIXME: define syntax to represent table events */ printf("# [table: %s]\t%s\n", type == NFT_MSG_NEWTABLE ? "NEW" : "DEL", buf); err_free: nft_table_free(t); err: return MNL_CB_OK; } static bool counters; static int rule_cb(const struct nlmsghdr *nlh, int type) { struct nft_rule *r; r = nft_rule_alloc(); if (r == NULL) { perror("OOM"); goto err; } if (nft_rule_nlmsg_parse(nlh, r) < 0) { perror("nft_rule_nlmsg_parse"); goto err_free; } switch(nft_rule_attr_get_u8(r, NFT_RULE_ATTR_FAMILY)) { case AF_INET: printf("-4 "); break; case AF_INET6: printf("-6 "); break; default: break; } nft_rule_print_save(r, type == NFT_MSG_NEWRULE ? NFT_RULE_APPEND : NFT_RULE_DEL, counters); err_free: nft_rule_free(r); err: return MNL_CB_OK; } static int chain_cb(const struct nlmsghdr *nlh, int type) { struct nft_chain *t; char buf[4096]; t = nft_chain_alloc(); if (t == NULL) { perror("OOM"); goto err; } if (nft_chain_nlmsg_parse(nlh, t) < 0) { perror("nft_chain_nlmsg_parse"); goto err_free; } nft_chain_snprintf(buf, sizeof(buf), t, NFT_CHAIN_O_DEFAULT, 0); /* FIXME: define syntax to represent chain events */ printf("# [chain: %s]\t%s\n", type == NFT_MSG_NEWCHAIN ? "NEW" : "DEL", buf); err_free: nft_chain_free(t); err: return MNL_CB_OK; } static int events_cb(const struct nlmsghdr *nlh, void *data) { int ret = MNL_CB_OK; int type = nlh->nlmsg_type & 0xFF; switch(type) { case NFT_MSG_NEWTABLE: case NFT_MSG_DELTABLE: ret = table_cb(nlh, type); break; case NFT_MSG_NEWCHAIN: case NFT_MSG_DELCHAIN: ret = chain_cb(nlh, type); break; case NFT_MSG_NEWRULE: case NFT_MSG_DELRULE: ret = rule_cb(nlh, type); break; } return ret; } static const struct option options[] = { {.name = "counters", .has_arg = false, .val = 'c'}, {NULL}, }; static void print_usage(const char *name, const char *version) { fprintf(stderr, "Usage: %s [-c]\n" " [ --counters ]\n", name); exit(EXIT_FAILURE); } int xtables_events_main(int argc, char *argv[]) { struct mnl_socket *nl; char buf[MNL_SOCKET_BUFFER_SIZE]; int ret, c; xtables_globals.program_name = "xtables-events"; /* 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 opterr = 0; while ((c = getopt_long(argc, argv, "c", options, NULL)) != -1) { switch (c) { case 'c': counters = true; break; default: print_usage(argv[0], XTABLES_VERSION); exit(EXIT_FAILURE); } } nl = mnl_socket_open(NETLINK_NETFILTER); if (nl == NULL) { perror("mnl_socket_open"); exit(EXIT_FAILURE); } if (mnl_socket_bind(nl, (1 << (NFNLGRP_NFTABLES-1)), MNL_SOCKET_AUTOPID) < 0) { perror("mnl_socket_bind"); exit(EXIT_FAILURE); } ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); while (ret > 0) { ret = mnl_cb_run(buf, ret, 0, 0, events_cb, NULL); if (ret <= 0) break; ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); } if (ret == -1) { perror("error"); exit(EXIT_FAILURE); } mnl_socket_close(nl); return EXIT_SUCCESS; }