// SPDX-License-Identifier: GPL-3.0-or-later
#include "../../libnetdata/libnetdata.h"
#define PLUGIN_NFACCT_NAME "nfacct.plugin"
#define NETDATA_CHART_PRIO_NETFILTER_NEW 8701
#define NETDATA_CHART_PRIO_NETFILTER_CHANGES 8702
#define NETDATA_CHART_PRIO_NETFILTER_EXPECT 8703
#define NETDATA_CHART_PRIO_NETFILTER_ERRORS 8705
#define NETDATA_CHART_PRIO_NETFILTER_SEARCH 8710
#define NETDATA_CHART_PRIO_NETFILTER_PACKETS 8906
#define NETDATA_CHART_PRIO_NETFILTER_BYTES 8907
#ifdef HAVE_LIBMNL
#include <libmnl/libmnl.h>
static inline size_t mnl_buffer_size() {
long s = MNL_SOCKET_BUFFER_SIZE;
if(s <= 0) return 8192;
return (size_t)s;
}
// callback required by fatal()
void netdata_cleanup_and_exit(int ret) {
exit(ret);
}
void send_statistics( const char *action, const char *action_result, const char *action_data) {
(void) action;
(void) action_result;
(void) action_data;
return;
}
// callbacks required by popen()
void signals_block(void) {};
void signals_unblock(void) {};
void signals_reset(void) {};
// callback required by eval()
int health_variable_lookup(const char *variable, uint32_t hash, struct rrdcalc *rc, calculated_number *result) {
(void)variable;
(void)hash;
(void)rc;
(void)result;
return 0;
};
// required by get_system_cpus()
char *netdata_configured_host_prefix = "";
// Variables
static int debug = 0;
static int netdata_update_every = 1;
// ----------------------------------------------------------------------------
// DO_NFSTAT - collect netfilter connection tracker statistics via netlink
// example: https://github.com/formorer/pkg-conntrack-tools/blob/master/src/conntrack.c
#ifdef HAVE_LINUX_NETFILTER_NFNETLINK_CONNTRACK_H
#define DO_NFSTAT 1
#define RRD_TYPE_NET_STAT_NETFILTER "netfilter"
#define RRD_TYPE_NET_STAT_CONNTRACK "netlink"
#include <linux/netfilter/nfnetlink_conntrack.h>
static struct {
int update_every;
char *buf;
size_t buf_size;
struct mnl_socket *mnl;
struct nlmsghdr *nlh;
struct nfgenmsg *nfh;
unsigned int seq;
uint32_t portid;
struct nlattr *tb[CTA_STATS_MAX+1];
const char *attr2name[CTA_STATS_MAX+1];
kernel_uint_t metrics[CTA_STATS_MAX+1];
struct nlattr *tb_exp[CTA_STATS_EXP_MAX+1];
const char *attr2name_exp[CTA_STATS_EXP_MAX+1];
kernel_uint_t metrics_exp[CTA_STATS_EXP_MAX+1];
} nfstat_root = {
.update_every = 1,
.buf = NULL,
.buf_size = 0,
.mnl = NULL,
.nlh = NULL,
.nfh = NULL,
.seq = 0,
.portid = 0,
.tb = {},
.attr2name = {
[CTA_STATS_SEARCHED] = "searched",
[CTA_STATS_FOUND] = "found",
[CTA_STATS_NEW] = "new",
[CTA_STATS_INVALID] = "invalid",
[CTA_STATS_IGNORE] = "ignore",
[CTA_STATS_DELETE] = "delete",
[CTA_STATS_DELETE_LIST] = "delete_list",
[CTA_STATS_INSERT] = "insert",
[CTA_STATS_INSERT_FAILED] = "insert_failed",
[CTA_STATS_DROP] = "drop",
[CTA_STATS_EARLY_DROP] = "early_drop",
[CTA_STATS_ERROR] = "icmp_error",
[CTA_STATS_SEARCH_RESTART] = "search_restart",
},
.metrics = {},
.tb_exp = {},
.attr2name_exp = {
[CTA_STATS_EXP_NEW] = "new",
[CTA_STATS_EXP_CREATE] = "created",
[CTA_STATS_EXP_DELETE] = "deleted",
},
.metrics_exp = {}
};
static int nfstat_init(int update_every) {
nfstat_root.update_every = update_every;
nfstat_root.buf_size = mnl_buffer_size();
nfstat_root.buf = mallocz(nfstat_root.buf_size);
nfstat_root.mnl = mnl_socket_open(NETLINK_NETFILTER);
if(!nfstat_root.mnl) {
error("NFSTAT: mnl_socket_open() failed");
return 1;
}
nfstat_root.seq = (unsigned int)now_realtime_sec() - 1;
if(mnl_socket_bind(nfstat_root.mnl, 0, MNL_SOCKET_AUTOPID) < 0) {
error("NFSTAT: mnl_socket_bind() failed");
return 1;
}
nfstat_root.portid = mnl_socket_get_portid(nfstat_root.mnl);
return 0;
}
static struct