@@ -2,6 +2,7 @@ pkginclude_HEADERS = batch.h \
table.h \
trace.h \
chain.h \
+ device.h \
object.h \
rule.h \
expr.h \
new file mode 100644
@@ -0,0 +1,39 @@
+#ifndef _LIBNFTNL_DEVICE_H_
+#define _LIBNFTNL_DEVICE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct nftnl_device;
+
+struct nftnl_device *nftnl_device_alloc(void);
+void nftnl_device_free(const struct nftnl_device *);
+
+enum nftnl_device_attr {
+ NFTNL_DEVICE_NAME = 0,
+ NFTNL_DEVICE_TABLE,
+ NFTNL_DEVICE_FLOWTABLE,
+ NFTNL_DEVICE_CHAIN,
+ NFTNL_DEVICE_SPEC,
+ NFTNL_DEVICE_FAMILY,
+ __NFTNL_DEVICE_MAX,
+};
+#define NFTNL_DEVICE_MAX (__NFTNL_DEVICE_MAX - 1)
+
+bool nftnl_device_is_set(const struct nftnl_device *d, uint16_t attr);
+
+const void *nftnl_device_get_data(const struct nftnl_device *d,
+ uint16_t attr, uint32_t *data_len);
+const char *nftnl_device_get_str(const struct nftnl_device *d, uint16_t attr);
+int32_t nftnl_device_get_s32(const struct nftnl_device *d, uint16_t attr);
+
+struct nlmsghdr;
+
+int nftnl_device_nlmsg_parse(const struct nlmsghdr *nlh, struct nftnl_device *d);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* _LIBNFTNL_DEVICE_H_ */
@@ -1740,10 +1740,18 @@ enum nft_synproxy_attributes {
* enum nft_device_attributes - nf_tables device netlink attributes
*
* @NFTA_DEVICE_NAME: name of this device (NLA_STRING)
+ * @NFTA_DEVICE_TABLE: table containing the flowtable or chain hooking into the device (NLA_STRING)
+ * @NFTA_DEVICE_FLOWTABLE: flowtable hooking into the device (NLA_STRING)
+ * @NFTA_DEVICE_CHAIN: chain hooking into the device (NLA_STRING)
+ * @NFTA_DEVICE_SPEC: hook spec matching the device (NLA_STRING)
*/
enum nft_devices_attributes {
NFTA_DEVICE_UNSPEC,
NFTA_DEVICE_NAME,
+ NFTA_DEVICE_TABLE,
+ NFTA_DEVICE_FLOWTABLE,
+ NFTA_DEVICE_CHAIN,
+ NFTA_DEVICE_SPEC,
__NFTA_DEVICE_MAX
};
#define NFTA_DEVICE_MAX (__NFTA_DEVICE_MAX - 1)
@@ -13,6 +13,7 @@ libnftnl_la_SOURCES = utils.c \
table.c \
trace.c \
chain.c \
+ device.c \
object.c \
rule.c \
set.c \
new file mode 100644
@@ -0,0 +1,153 @@
+/*
+ * (C) 2024 Red Hat GmbH
+ * Author: Phil Sutter <phil@nwl.cc>
+ *
+ * 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.
+ */
+#include "internal.h"
+
+#include <linux/netfilter/nfnetlink.h>
+
+#include <libnftnl/device.h>
+
+struct nftnl_device {
+ const char *name;
+ const char *table;
+ const char *flowtable;
+ const char *chain;
+ const char *spec;
+ int32_t family;
+ uint32_t flags;
+};
+
+EXPORT_SYMBOL(nftnl_device_alloc);
+struct nftnl_device *nftnl_device_alloc(void)
+{
+ return calloc(1, sizeof(struct nftnl_device));
+}
+
+EXPORT_SYMBOL(nftnl_device_free);
+void nftnl_device_free(const struct nftnl_device *d)
+{
+ if (d->flags & (1 << NFTNL_DEVICE_NAME))
+ xfree(d->name);
+ if (d->flags & (1 << NFTNL_DEVICE_TABLE))
+ xfree(d->table);
+ if (d->flags & (1 << NFTNL_DEVICE_FLOWTABLE))
+ xfree(d->flowtable);
+ if (d->flags & (1 << NFTNL_DEVICE_CHAIN))
+ xfree(d->chain);
+ if (d->flags & (1 << NFTNL_DEVICE_SPEC))
+ xfree(d->spec);
+ xfree(d);
+}
+
+EXPORT_SYMBOL(nftnl_device_is_set);
+bool nftnl_device_is_set(const struct nftnl_device *d, uint16_t attr)
+{
+ return d->flags & (1 << attr);
+}
+
+EXPORT_SYMBOL(nftnl_device_get_data);
+const void *nftnl_device_get_data(const struct nftnl_device *d,
+ uint16_t attr, uint32_t *data_len)
+{
+ if (!(d->flags & (1 << attr)))
+ return NULL;
+
+ switch (attr) {
+ case NFTNL_DEVICE_NAME:
+ *data_len = strlen(d->name) + 1;
+ return d->name;
+ case NFTNL_DEVICE_TABLE:
+ *data_len = strlen(d->table) + 1;
+ return d->table;
+ case NFTNL_DEVICE_FLOWTABLE:
+ *data_len = strlen(d->flowtable) + 1;
+ return d->flowtable;
+ case NFTNL_DEVICE_CHAIN:
+ *data_len = strlen(d->chain) + 1;
+ return d->chain;
+ case NFTNL_DEVICE_SPEC:
+ *data_len = strlen(d->spec) + 1;
+ return d->spec;
+ case NFTNL_DEVICE_FAMILY:
+ *data_len = sizeof(int32_t);
+ return &d->family;
+ }
+ return NULL;
+}
+
+EXPORT_SYMBOL(nftnl_device_get_str);
+const char *nftnl_device_get_str(const struct nftnl_device *d, uint16_t attr)
+{
+ uint32_t data_len;
+
+ return nftnl_device_get_data(d, attr, &data_len);
+}
+
+EXPORT_SYMBOL(nftnl_device_get_s32);
+int32_t nftnl_device_get_s32(const struct nftnl_device *d, uint16_t attr)
+{
+ uint32_t data_len = 0;
+ const int32_t *val = nftnl_device_get_data(d, attr, &data_len);
+
+ nftnl_assert(val, attr, data_len == sizeof(int32_t));
+
+ return val ? *val : 0;
+}
+
+static int nftnl_device_parse_attr_cb(const struct nlattr *attr, void *data)
+{
+ const struct nlattr **tb = data;
+ int type = mnl_attr_get_type(attr);
+
+ if (mnl_attr_type_valid(attr, NFTA_DEVICE_MAX) < 0)
+ return MNL_CB_OK;
+
+ /* all attributes are of string type */
+ if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
+ abi_breakage();
+
+ tb[type] = attr;
+ return MNL_CB_OK;
+}
+
+EXPORT_SYMBOL(nftnl_device_nlmsg_parse);
+int nftnl_device_nlmsg_parse(const struct nlmsghdr *nlh, struct nftnl_device *d)
+{
+ struct nlattr *tb[NFTA_DEVICE_MAX + 1] = {};
+ struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
+ int ret = 0;
+
+ if (mnl_attr_parse(nlh, sizeof(*nfg), nftnl_device_parse_attr_cb, tb) < 0)
+ return -1;
+
+ if (nftnl_parse_str_attr(tb[NFTA_DEVICE_NAME], NFTNL_DEVICE_NAME,
+ &d->name, &d->flags) < 0)
+ return -1;
+ if (nftnl_parse_str_attr(tb[NFTA_DEVICE_TABLE], NFTNL_DEVICE_TABLE,
+ &d->table, &d->flags) < 0)
+ return -1;
+ if (nftnl_parse_str_attr(tb[NFTA_DEVICE_FLOWTABLE],
+ NFTNL_DEVICE_FLOWTABLE,
+ &d->flowtable, &d->flags) < 0)
+ return -1;
+ if (nftnl_parse_str_attr(tb[NFTA_DEVICE_CHAIN], NFTNL_DEVICE_CHAIN,
+ &d->chain, &d->flags) < 0)
+ return -1;
+ if (tb[NFTA_DEVICE_SPEC]) {
+ d->spec = strdup(mnl_attr_get_ifname(tb[NFTA_DEVICE_SPEC]));
+ if (!d->spec)
+ return -1;
+ d->flags |= (1 << NFTNL_DEVICE_SPEC);
+ }
+
+ d->family = nfg->nfgen_family;
+ d->flags |= (1 << NFTNL_DEVICE_FAMILY);
+
+ return ret;
+}
@@ -383,3 +383,13 @@ LIBNFTNL_16 {
LIBNFTNL_17 {
nftnl_set_elem_nlmsg_build;
} LIBNFTNL_16;
+
+LIBNFTNL_18 {
+ nftnl_device_alloc;
+ nftnl_device_free;
+ nftnl_device_is_set;
+ nftnl_device_get_data;
+ nftnl_device_get_str;
+ nftnl_device_get_s32;
+ nftnl_device_nlmsg_parse;
+} LIBNFTNL_17;
A data structure used to parse NFT_MSG_(NEW|DEL)DEV messages into. Since the kernel does not support these message types in requests yet, implement a parser and getters only. Signed-off-by: Phil Sutter <phil@nwl.cc> --- include/libnftnl/Makefile.am | 1 + include/libnftnl/device.h | 39 +++++++ include/linux/netfilter/nf_tables.h | 8 ++ src/Makefile.am | 1 + src/device.c | 153 ++++++++++++++++++++++++++++ src/libnftnl.map | 10 ++ 6 files changed, 212 insertions(+) create mode 100644 include/libnftnl/device.h create mode 100644 src/device.c