summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2011-12-28 20:16:46 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2011-12-29 15:40:36 +0100
commit3388d7df304f26617c4487418c05734ae4fce5b8 (patch)
treec4fe8bb3cd31a8d85a908485e0b79e1817fefdad
parenta69ac90ec039509ef6ec2684bda156ed6d41fc83 (diff)
src: major API redesign
This patch reworks the initial API. Now it provides functions to: - allocate/release accounting objects. - set/unset/get attributes of accounting objects. - build one netlink message from one accounting object. - parse one netlink message to one accounting object. - print one accounting object into a buffer. Binary layout of nfacct objects are opaque. This is good for extensibility without breaking backward compatibility. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--examples/nfacct-add.c22
-rw-r--r--examples/nfacct-del.c67
-rw-r--r--examples/nfacct-get.c34
-rw-r--r--include/libnetfilter_acct/libnetfilter_acct.h36
-rw-r--r--src/libnetfilter_acct.c257
-rw-r--r--src/libnetfilter_acct.map19
6 files changed, 333 insertions, 102 deletions
diff --git a/examples/nfacct-add.c b/examples/nfacct-add.c
index 64f94d1..40e0e31 100644
--- a/examples/nfacct-add.c
+++ b/examples/nfacct-add.c
@@ -10,18 +10,28 @@ int main(int argc, char *argv[])
char buf[MNL_SOCKET_BUFFER_SIZE];
struct nlmsghdr *nlh;
uint32_t portid, seq;
- struct nfacct nfacct = {};
+ struct nfacct *nfacct;
int ret;
if (argc != 2) {
fprintf(stderr, "Usage: %s [name]\n", argv[0]);
exit(EXIT_FAILURE);
}
- strncpy(nfacct.name, argv[1], NFACCT_NAME_MAX);
- nfacct.name[NFACCT_NAME_MAX-1] = '\0';
- nlh = nfacct_add(buf, &nfacct);
- seq = nlh->nlmsg_seq = time(NULL);
+ nfacct = nfacct_alloc();
+ if (nfacct == NULL) {
+ perror("OOM");
+ exit(EXIT_FAILURE);
+ }
+
+ nfacct_attr_set(nfacct, NFACCT_ATTR_NAME, argv[1]);
+
+ seq = time(NULL);
+ nlh = nfacct_nlmsg_build_hdr(buf, NFNL_MSG_ACCT_NEW,
+ NLM_F_CREATE | NLM_F_ACK, seq);
+ nfacct_nlmsg_build_payload(nlh, nfacct);
+
+ nfacct_free(nfacct);
nl = mnl_socket_open(NETLINK_NETFILTER);
if (nl == NULL) {
@@ -42,7 +52,7 @@ int main(int argc, char *argv[])
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
while (ret > 0) {
- ret = mnl_cb_run(buf, ret, seq, portid, nfacct_list_cb, NULL);
+ ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
if (ret <= 0)
break;
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
diff --git a/examples/nfacct-del.c b/examples/nfacct-del.c
new file mode 100644
index 0000000..7a1190c
--- /dev/null
+++ b/examples/nfacct-del.c
@@ -0,0 +1,67 @@
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <libmnl/libmnl.h>
+#include <libnetfilter_acct/libnetfilter_acct.h>
+
+int main(int argc, char *argv[])
+{
+ struct mnl_socket *nl;
+ char buf[MNL_SOCKET_BUFFER_SIZE];
+ struct nlmsghdr *nlh;
+ uint32_t portid, seq;
+ struct nfacct *nfacct;
+ int ret;
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s [name]\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ nfacct = nfacct_alloc();
+ if (nfacct == NULL) {
+ perror("OOM");
+ exit(EXIT_FAILURE);
+ }
+
+ nfacct_attr_set(nfacct, NFACCT_ATTR_NAME, argv[1]);
+
+ seq = time(NULL);
+ nlh = nfacct_nlmsg_build_hdr(buf, NFNL_MSG_ACCT_DEL,
+ NLM_F_ACK, seq);
+ nfacct_nlmsg_build_payload(nlh, nfacct);
+
+ nfacct_free(nfacct);
+
+ 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, seq, portid, NULL, 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;
+}
diff --git a/examples/nfacct-get.c b/examples/nfacct-get.c
index 7b22352..fffa3ec 100644
--- a/examples/nfacct-get.c
+++ b/examples/nfacct-get.c
@@ -4,6 +4,31 @@
#include <libmnl/libmnl.h>
#include <libnetfilter_acct/libnetfilter_acct.h>
+static int nfacct_cb(const struct nlmsghdr *nlh, void *data)
+{
+ struct nfacct *nfacct;
+ char buf[4096];
+
+ nfacct = nfacct_alloc();
+ if (nfacct == NULL) {
+ perror("OOM");
+ goto err;
+ }
+
+ if (nfacct_nlmsg_parse_payload(nlh, nfacct) < 0) {
+ perror("nfacct_parse_nl_msg");
+ goto err_free;
+ }
+
+ nfacct_snprintf(buf, sizeof(buf), nfacct, NFACCT_SNPRINTF_F_FULL);
+ printf("%s\n", buf);
+
+err_free:
+ nfacct_free(nfacct);
+err:
+ return MNL_CB_OK;
+}
+
int main(int argc, char *argv[])
{
struct mnl_socket *nl;
@@ -21,8 +46,11 @@ int main(int argc, char *argv[])
if (argc == 2 && strncmp(argv[1], "-z", strlen("-z")) == 0)
zeroctr = true;
- nlh = nfacct_list(buf, zeroctr);
- seq = nlh->nlmsg_seq = time(NULL);
+ seq = time(NULL);
+ nlh = nfacct_nlmsg_build_hdr(buf, zeroctr ?
+ NFNL_MSG_ACCT_GET_CTRZERO :
+ NFNL_MSG_ACCT_GET,
+ NLM_F_DUMP, seq);
nl = mnl_socket_open(NETLINK_NETFILTER);
if (nl == NULL) {
@@ -43,7 +71,7 @@ int main(int argc, char *argv[])
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
while (ret > 0) {
- ret = mnl_cb_run(buf, ret, seq, portid, nfacct_list_cb, &full);
+ ret = mnl_cb_run(buf, ret, seq, portid, nfacct_cb, &full);
if (ret <= 0)
break;
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
diff --git a/include/libnetfilter_acct/libnetfilter_acct.h b/include/libnetfilter_acct/libnetfilter_acct.h
index f5b0040..d877407 100644
--- a/include/libnetfilter_acct/libnetfilter_acct.h
+++ b/include/libnetfilter_acct/libnetfilter_acct.h
@@ -4,16 +4,34 @@
#include <sys/types.h>
#include <linux/netfilter/nfnetlink_acct.h>
-struct nfacct {
- char name[NFACCT_NAME_MAX];
- uint64_t pkts;
- uint64_t bytes;
+struct nfacct;
+
+enum nfacct_attr_type {
+ NFACCT_ATTR_NAME = 0,
+ NFACCT_ATTR_PKTS,
+ NFACCT_ATTR_BYTES,
};
-struct nlmsghdr *nfacct_add(char *buf, struct nfacct *nfacct);
-struct nlmsghdr *nfacct_list(char *buf, bool ctrzero);
-int nfacct_list_cb(const struct nlmsghdr *nlh, void *data);
-struct nlmsghdr *nfacct_flush(char *buf);
-struct nlmsghdr *nfacct_delete(char *buf, const char *filter_name);
+struct nfacct *nfacct_alloc(void);
+void nfacct_free(struct nfacct *nfacct);
+
+void nfacct_attr_set(struct nfacct *nfacct, enum nfacct_attr_type type, const void *data);
+void nfacct_attr_set_str(struct nfacct *nfacct, enum nfacct_attr_type type, const char *name);
+void nfacct_attr_set_u64(struct nfacct *nfacct, enum nfacct_attr_type type, uint64_t value);
+void nfacct_attr_unset(struct nfacct *nfacct, enum nfacct_attr_type type);
+
+const void *nfacct_attr_get(struct nfacct *nfacct, enum nfacct_attr_type type);
+const char *nfacct_attr_get_str(struct nfacct *nfacct, enum nfacct_attr_type type);
+uint64_t nfacct_attr_get_u64(struct nfacct *nfacct, enum nfacct_attr_type type);
+
+struct nlmsghdr;
+
+struct nlmsghdr *nfacct_nlmsg_build_hdr(char *buf, uint8_t cmd, uint16_t flags, uint32_t seq);
+void nfacct_nlmsg_build_payload(struct nlmsghdr *nlh, struct nfacct *nfacct);
+int nfacct_nlmsg_parse_payload(const struct nlmsghdr *nlh, struct nfacct *nfacct);
+
+#define NFACCT_SNPRINTF_F_FULL (1 << 0)
+
+int nfacct_snprintf(char *buf, size_t size, struct nfacct *nfacct, unsigned int flags);
#endif
diff --git a/src/libnetfilter_acct.c b/src/libnetfilter_acct.c
index 777c960..86d7b96 100644
--- a/src/libnetfilter_acct.c
+++ b/src/libnetfilter_acct.c
@@ -11,48 +11,159 @@
#include <time.h>
#include <endian.h>
+#include <stdlib.h>
+#include <string.h>
+
#include <libmnl/libmnl.h>
#include <linux/netfilter/nfnetlink.h>
#include <linux/netfilter/nfnetlink_acct.h>
#include <libnetfilter_acct/libnetfilter_acct.h>
-struct nlmsghdr *nfacct_add(char *buf, struct nfacct *nfacct)
+struct nfacct {
+ char name[NFACCT_NAME_MAX];
+ uint64_t pkts;
+ uint64_t bytes;
+ uint32_t bitset;
+};
+
+struct nfacct *nfacct_alloc(void)
{
- struct nlmsghdr *nlh;
- struct nfgenmsg *nfh;
+ return calloc(1, sizeof(struct nfacct));
+}
+EXPORT_SYMBOL(nfacct_alloc);
- nlh = mnl_nlmsg_put_header(buf);
- nlh->nlmsg_type = (NFNL_SUBSYS_ACCT << 8) | NFNL_MSG_ACCT_NEW;
- nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK;
- nlh->nlmsg_seq = time(NULL);
+void nfacct_free(struct nfacct *nfacct)
+{
+ free(nfacct);
+}
+EXPORT_SYMBOL(nfacct_free);
- nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg));
- nfh->nfgen_family = AF_UNSPEC;
- nfh->version = NFNETLINK_V0;
- nfh->res_id = 0;
+void
+nfacct_attr_set(struct nfacct *nfacct, enum nfacct_attr_type type,
+ const void *data)
+{
+ switch(type) {
+ case NFACCT_ATTR_NAME:
+ strncpy(nfacct->name, data, NFACCT_NAME_MAX);
+ nfacct->name[NFACCT_NAME_MAX-1] = '\0';
+ nfacct->bitset |= (1 << NFACCT_ATTR_NAME);
+ break;
+ case NFACCT_ATTR_PKTS:
+ nfacct->bytes = *((uint64_t *) data);
+ nfacct->bitset |= (1 << NFACCT_ATTR_PKTS);
+ break;
+ case NFACCT_ATTR_BYTES:
+ nfacct->pkts = *((uint64_t *) data);
+ nfacct->bitset |= (1 << NFACCT_ATTR_BYTES);
+ break;
+ }
+}
+EXPORT_SYMBOL(nfacct_attr_set);
- mnl_attr_put_strz(nlh, NFACCT_NAME, nfacct->name);
- mnl_attr_put_u64(nlh, NFACCT_PKTS, htobe64(nfacct->pkts));
- mnl_attr_put_u64(nlh, NFACCT_PKTS, htobe64(nfacct->bytes));
+void
+nfacct_attr_set_str(struct nfacct *nfacct, enum nfacct_attr_type type,
+ const char *name)
+{
+ nfacct_attr_set(nfacct, type, name);
+}
+EXPORT_SYMBOL(nfacct_attr_set_str);
- return nlh;
+void
+nfacct_attr_set_u64(struct nfacct *nfacct, enum nfacct_attr_type type,
+ uint64_t value)
+{
+ nfacct_attr_set(nfacct, type, &value);
}
-EXPORT_SYMBOL(nfacct_add);
+EXPORT_SYMBOL(nfacct_attr_set_u64);
-struct nlmsghdr *nfacct_list(char *buf, bool ctrzero)
+void
+nfacct_attr_unset(struct nfacct *nfacct, enum nfacct_attr_type type)
+{
+ switch(type) {
+ case NFACCT_ATTR_NAME:
+ nfacct->bitset &= ~(1 << NFACCT_ATTR_NAME);
+ break;
+ case NFACCT_ATTR_PKTS:
+ nfacct->bitset &= ~(1 << NFACCT_ATTR_PKTS);
+ break;
+ case NFACCT_ATTR_BYTES:
+ nfacct->bitset &= ~(1 << NFACCT_ATTR_BYTES);
+ break;
+ }
+}
+EXPORT_SYMBOL(nfacct_attr_unset);
+
+const void *nfacct_attr_get(struct nfacct *nfacct, enum nfacct_attr_type type)
+{
+ const void *ret = NULL;
+
+ switch(type) {
+ case NFACCT_ATTR_NAME:
+ ret = nfacct->name;
+ break;
+ case NFACCT_ATTR_PKTS:
+ ret = &nfacct->pkts;
+ break;
+ case NFACCT_ATTR_BYTES:
+ ret = &nfacct->bytes;
+ break;
+ }
+ return ret;
+}
+EXPORT_SYMBOL(nfacct_attr_get);
+
+const char *
+nfacct_attr_get_str(struct nfacct *nfacct, enum nfacct_attr_type type)
+{
+ return (char *)nfacct_attr_get(nfacct, type);
+}
+EXPORT_SYMBOL(nfacct_attr_get_str);
+
+uint64_t nfacct_attr_get_u64(struct nfacct *nfacct, enum nfacct_attr_type type)
+{
+ return *((uint64_t *)nfacct_attr_get(nfacct, type));
+}
+EXPORT_SYMBOL(nfacct_attr_get_u64);
+
+/**
+ * nfacct_nlmsg_build_hdr - build netlink message header for nfacct subsystem
+ * @buf: buffer where this function outputs the netlink message.
+ * @cmd: nfacct nfnetlink command.
+ * @flags: netlink flags.
+ * @seq: sequence number for this message.
+ *
+ * Possible commands:
+ * - NFNL_MSG_ACCT_NEW: new accounting object.
+ * - NFNL_MSG_ACCT_GET: get accounting object.
+ * - NFNL_MSG_ACCT_GET_CTRZERO: get accounting object and atomically reset.
+ *
+ * Examples:
+ * - Command NFNL_MSG_ACCT_NEW + flags NLM_F_CREATE | NLM_F_ACK, to create
+ * one new accounting object (if it does not already exists). You receive
+ * one acknoledgment in any case with the result of the operation.
+ *
+ * - Command NFNL_MSG_ACCT_GET + flags NLM_F_DUMP, to obtain all the
+ * existing accounting objects.
+ *
+ * - Command NFNL_MSG_ACCT_GET_CTRZERO + flags NLM_F_DUMP, to atomically
+ * obtain all the existing accounting objects and reset them.
+ *
+ * - Command NFNL_MSG_ACCT_DEL, to delete all existing unused objects.
+ *
+ * - Command NFNL_MSG_ACCT_DEL, to delete one specific nfacct object (if
+ * unused, otherwise you hit EBUSY).
+ */
+struct nlmsghdr *
+nfacct_nlmsg_build_hdr(char *buf, uint8_t cmd, uint16_t flags, uint32_t seq)
{
struct nlmsghdr *nlh;
struct nfgenmsg *nfh;
- uint32_t msg_type = NFNL_MSG_ACCT_GET;
-
- if (ctrzero)
- msg_type = NFNL_MSG_ACCT_GET_CTRZERO;
nlh = mnl_nlmsg_put_header(buf);
- nlh->nlmsg_type = (NFNL_SUBSYS_ACCT << 8) | msg_type;
- nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
- nlh->nlmsg_seq = time(NULL);
+ nlh->nlmsg_type = (NFNL_SUBSYS_ACCT << 8) | cmd;
+ nlh->nlmsg_flags = NLM_F_REQUEST | flags;
+ nlh->nlmsg_seq = seq;
nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg));
nfh->nfgen_family = AF_UNSPEC;
@@ -61,9 +172,22 @@ struct nlmsghdr *nfacct_list(char *buf, bool ctrzero)
return nlh;
}
-EXPORT_SYMBOL(nfacct_list);
+EXPORT_SYMBOL(nfacct_nlmsg_build_hdr);
+
+void nfacct_nlmsg_build_payload(struct nlmsghdr *nlh, struct nfacct *nfacct)
+{
+ if (nfacct->name)
+ mnl_attr_put_strz(nlh, NFACCT_NAME, nfacct->name);
+
+ if (nfacct->pkts)
+ mnl_attr_put_u64(nlh, NFACCT_PKTS, htobe64(nfacct->pkts));
+
+ if (nfacct->bytes)
+ mnl_attr_put_u64(nlh, NFACCT_PKTS, htobe64(nfacct->bytes));
+}
+EXPORT_SYMBOL(nfacct_nlmsg_build_payload);
-static int nfacct_list_attr_cb(const struct nlattr *attr, void *data)
+static int nfacct_nlmsg_parse_attr_cb(const struct nlattr *attr, void *data)
{
const struct nlattr **tb = data;
int type = mnl_attr_get_type(attr);
@@ -95,67 +219,44 @@ static int nfacct_list_attr_cb(const struct nlattr *attr, void *data)
return MNL_CB_OK;
}
-int nfacct_list_cb(const struct nlmsghdr *nlh, void *data)
+int
+nfacct_nlmsg_parse_payload(const struct nlmsghdr *nlh, struct nfacct *nfacct)
{
struct nlattr *tb[NFACCT_MAX+1] = {};
struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
- bool *full = data;
- mnl_attr_parse(nlh, sizeof(*nfg), nfacct_list_attr_cb, tb);
+ mnl_attr_parse(nlh, sizeof(*nfg), nfacct_nlmsg_parse_attr_cb, tb);
if (!tb[NFACCT_NAME] && !tb[NFACCT_PKTS] && !tb[NFACCT_BYTES])
- return MNL_CB_OK;
+ return -1;
- if (full) {
- printf("%s = { pkts = %.12llu,\tbytes = %.12llu }; \n",
- mnl_attr_get_str(tb[NFACCT_NAME]),
- (unsigned long long)
- be64toh(mnl_attr_get_u64(tb[NFACCT_PKTS])),
- (unsigned long long)
- be64toh(mnl_attr_get_u64(tb[NFACCT_BYTES])));
- } else {
- printf("%s\n", mnl_attr_get_str(tb[NFACCT_NAME]));
- }
+ nfacct_attr_set_str(nfacct, NFACCT_ATTR_NAME,
+ mnl_attr_get_str(tb[NFACCT_NAME]));
+ nfacct_attr_set_u64(nfacct, NFACCT_ATTR_PKTS,
+ be64toh(mnl_attr_get_u64(tb[NFACCT_PKTS])));
+ nfacct_attr_set_u64(nfacct, NFACCT_ATTR_BYTES,
+ be64toh(mnl_attr_get_u64(tb[NFACCT_BYTES])));
- return MNL_CB_OK;
+ return 0;
}
-EXPORT_SYMBOL(nfacct_list_cb);
+EXPORT_SYMBOL(nfacct_nlmsg_parse_payload);
-struct nlmsghdr *nfacct_flush(char *buf)
+int nfacct_snprintf(char *buf, size_t size, struct nfacct *nfacct,
+ unsigned int flags)
{
- struct nlmsghdr *nlh;
- struct nfgenmsg *nfh;
-
- nlh = mnl_nlmsg_put_header(buf);
- nlh->nlmsg_type = (NFNL_SUBSYS_ACCT << 8) | NFNL_MSG_ACCT_DEL;
- nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK;
- nlh->nlmsg_seq = time(NULL);
+ int ret;
- nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg));
- nfh->nfgen_family = AF_UNSPEC;
- nfh->version = NFNETLINK_V0;
- nfh->res_id = 0;
-
- return nlh;
-}
-EXPORT_SYMBOL(nfacct_flush);
-
-struct nlmsghdr *nfacct_delete(char *buf, const char *filter_name)
-{
- struct nlmsghdr *nlh;
- struct nfgenmsg *nfh;
-
- nlh = mnl_nlmsg_put_header(buf);
- nlh->nlmsg_type = (NFNL_SUBSYS_ACCT << 8) | NFNL_MSG_ACCT_DEL;
- nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
- nlh->nlmsg_seq = time(NULL);
-
- nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg));
- nfh->nfgen_family = AF_UNSPEC;
- nfh->version = NFNETLINK_V0;
- nfh->res_id = 0;
-
- mnl_attr_put_strz(nlh, NFACCT_NAME, filter_name);
-
- return nlh;
+ if (flags & NFACCT_SNPRINTF_F_FULL) {
+ ret = snprintf(buf, size,
+ "%s = { pkts = %.12llu,\tbytes = %.12llu };",
+ nfacct_attr_get_str(nfacct, NFACCT_ATTR_NAME),
+ (unsigned long long)
+ nfacct_attr_get_u64(nfacct, NFACCT_ATTR_BYTES),
+ (unsigned long long)
+ nfacct_attr_get_u64(nfacct, NFACCT_ATTR_PKTS));
+ } else {
+ ret = snprintf(buf, size, "%s\n",
+ nfacct_attr_get_str(nfacct, NFACCT_ATTR_NAME));
+ }
+ return ret;
}
-EXPORT_SYMBOL(nfacct_delete);
+EXPORT_SYMBOL(nfacct_snprintf);
diff --git a/src/libnetfilter_acct.map b/src/libnetfilter_acct.map
index f5c3172..2a56eba 100644
--- a/src/libnetfilter_acct.map
+++ b/src/libnetfilter_acct.map
@@ -1,11 +1,18 @@
LIBNETFILTER_ACCT_1.0 {
global:
- nfacct_add;
- nfacct_list;
- nfacct_list_cb;
- nfacct_flush;
- nfacct_delete;
- nfacct_list;
+ nfacct_alloc;
+ nfacct_free;
+ nfacct_attr_set;
+ nfacct_attr_set_str;
+ nfacct_attr_set_u64;
+ nfacct_attr_unset;
+ nfacct_attr_get;
+ nfacct_attr_get_str;
+ nfacct_attr_get_u64;
+ nfacct_nlmsg_build_hdr;
+ nfacct_nlmsg_build_payload;
+ nfacct_nlmsg_parse_payload;
+ nfacct_snprintf;
local: *;
};