summaryrefslogtreecommitdiffstats
path: root/src
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 /src
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>
Diffstat (limited to 'src')
-rw-r--r--src/libnetfilter_acct.c257
-rw-r--r--src/libnetfilter_acct.map19
2 files changed, 192 insertions, 84 deletions
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: *;
};