* [libnftnl PATCH v4] utils: Add helpers for interface name wildcards
@ 2025-07-31 22:17 Phil Sutter
2025-09-30 21:06 ` Phil Sutter
0 siblings, 1 reply; 2+ messages in thread
From: Phil Sutter @ 2025-07-31 22:17 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: netfilter-devel
Support simple (suffix) wildcards in NFTNL_{CHAIN,FLOWTABLE}_DEVICES
identified by NFTA_DEVICE_PREFIX attribute. Add helpers converting to
and from the human-readable asterisk-suffix notation.
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
Changes since v4:
- Adjust code to NFTA_DEVICE_PREFIX attribute
Changes since v3:
- Use uint16_t for 'attr' parameter and size_t for internal 'len'
variable
- nftnl_attr_get_ifname to return allocated buffer, 'attr' parameter may
be const
Changes since v2:
- Use 'nftnl' prefix for introduced helpers
- Forward-declare struct nlattr to avoid extra include in utils.h
- Sanity-check array indexes to avoid out-of-bounds access
---
include/linux/netfilter/nf_tables.h | 2 ++
include/utils.h | 5 ++++
src/chain.c | 4 ++-
src/flowtable.c | 2 +-
src/str_array.c | 10 +++++---
src/utils.c | 39 +++++++++++++++++++++++++++++
6 files changed, 57 insertions(+), 5 deletions(-)
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
index 2beb30be2c5f8..8e0eb832bc01e 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -1784,10 +1784,12 @@ enum nft_synproxy_attributes {
* enum nft_device_attributes - nf_tables device netlink attributes
*
* @NFTA_DEVICE_NAME: name of this device (NLA_STRING)
+ * @NFTA_DEVICE_PREFIX: device name prefix, a simple wildcard (NLA_STRING)
*/
enum nft_devices_attributes {
NFTA_DEVICE_UNSPEC,
NFTA_DEVICE_NAME,
+ NFTA_DEVICE_PREFIX,
__NFTA_DEVICE_MAX
};
#define NFTA_DEVICE_MAX (__NFTA_DEVICE_MAX - 1)
diff --git a/include/utils.h b/include/utils.h
index 247d99d19dd7f..5a3379fb501e1 100644
--- a/include/utils.h
+++ b/include/utils.h
@@ -83,4 +83,9 @@ int nftnl_fprintf(FILE *fpconst, const void *obj, uint32_t cmd, uint32_t type,
int nftnl_set_str_attr(const char **dptr, uint32_t *flags,
uint16_t attr, const void *data, uint32_t data_len);
+struct nlattr;
+
+void nftnl_attr_put_ifname(struct nlmsghdr *nlh, const char *ifname);
+char *nftnl_attr_get_ifname(const struct nlattr *attr);
+
#endif
diff --git a/src/chain.c b/src/chain.c
index 895108cddad51..8396114439ff7 100644
--- a/src/chain.c
+++ b/src/chain.c
@@ -464,7 +464,7 @@ void nftnl_chain_nlmsg_build_payload(struct nlmsghdr *nlh, const struct nftnl_ch
nest_dev = mnl_attr_nest_start(nlh, NFTA_HOOK_DEVS);
nftnl_str_array_foreach(dev, &c->dev_array, i)
- mnl_attr_put_strz(nlh, NFTA_DEVICE_NAME, dev);
+ nftnl_attr_put_ifname(nlh, dev);
mnl_attr_nest_end(nlh, nest_dev);
}
@@ -648,6 +648,8 @@ static int nftnl_chain_parse_hook(struct nlattr *attr, struct nftnl_chain *c)
c->flags |= (1 << NFTNL_CHAIN_PRIO);
}
if (tb[NFTA_HOOK_DEV]) {
+ if (c->flags & (1 << NFTNL_CHAIN_DEV))
+ xfree(c->dev);
c->dev = strdup(mnl_attr_get_str(tb[NFTA_HOOK_DEV]));
if (!c->dev)
return -1;
diff --git a/src/flowtable.c b/src/flowtable.c
index fbbe0a866368d..59991d694f602 100644
--- a/src/flowtable.c
+++ b/src/flowtable.c
@@ -299,7 +299,7 @@ void nftnl_flowtable_nlmsg_build_payload(struct nlmsghdr *nlh,
nest_dev = mnl_attr_nest_start(nlh, NFTA_FLOWTABLE_HOOK_DEVS);
nftnl_str_array_foreach(dev, &c->dev_array, i)
- mnl_attr_put_strz(nlh, NFTA_DEVICE_NAME, dev);
+ nftnl_attr_put_ifname(nlh, dev);
mnl_attr_nest_end(nlh, nest_dev);
}
diff --git a/src/str_array.c b/src/str_array.c
index 5669c6154d394..4292c98a9debd 100644
--- a/src/str_array.c
+++ b/src/str_array.c
@@ -45,9 +45,13 @@ int nftnl_parse_devs(struct nftnl_str_array *sa, const struct nlattr *nest)
int len = 0;
mnl_attr_for_each_nested(attr, nest) {
- if (mnl_attr_get_type(attr) != NFTA_DEVICE_NAME)
+ switch(mnl_attr_get_type(attr)) {
+ default:
return -1;
- len++;
+ case NFTA_DEVICE_NAME:
+ case NFTA_DEVICE_PREFIX:
+ len++;
+ }
}
nftnl_str_array_clear(sa);
@@ -56,7 +60,7 @@ int nftnl_parse_devs(struct nftnl_str_array *sa, const struct nlattr *nest)
return -1;
mnl_attr_for_each_nested(attr, nest) {
- sa->array[sa->len] = strdup(mnl_attr_get_str(attr));
+ sa->array[sa->len] = nftnl_attr_get_ifname(attr);
if (!sa->array[sa->len]) {
nftnl_str_array_clear(sa);
return -1;
diff --git a/src/utils.c b/src/utils.c
index 5f2c5bff7c650..c4bbd4f7ed171 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -13,8 +13,11 @@
#include <errno.h>
#include <inttypes.h>
+#include <libmnl/libmnl.h>
+
#include <libnftnl/common.h>
+#include <linux/if.h>
#include <linux/netfilter.h>
#include <linux/netfilter/nf_tables.h>
@@ -146,3 +149,39 @@ int nftnl_set_str_attr(const char **dptr, uint32_t *flags,
*flags |= (1 << attr);
return 0;
}
+
+static bool is_wildcard_str(const char *str)
+{
+ size_t len = strlen(str);
+
+ if (len < 1 || str[len - 1] != '*')
+ return false;
+ if (len < 2 || str[len - 2] != '\\')
+ return true;
+ /* XXX: ignore backslash escaping for now */
+ return false;
+}
+
+void nftnl_attr_put_ifname(struct nlmsghdr *nlh, const char *ifname)
+{
+ uint16_t attr = is_wildcard_str(ifname) ?
+ NFTA_DEVICE_PREFIX : NFTA_DEVICE_NAME;
+
+ mnl_attr_put_strz(nlh, attr, ifname);
+}
+
+char *nftnl_attr_get_ifname(const struct nlattr *attr)
+{
+ const char *dev = mnl_attr_get_str(attr);
+ char buf[IFNAMSIZ];
+
+ switch (mnl_attr_get_type(attr)) {
+ case NFTA_DEVICE_NAME:
+ return strdup(dev);
+ case NFTA_DEVICE_PREFIX:
+ snprintf(buf, IFNAMSIZ, "%s*", dev);
+ return strdup(buf);
+ default:
+ return NULL;
+ }
+}
--
2.49.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2025-09-30 21:06 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-31 22:17 [libnftnl PATCH v4] utils: Add helpers for interface name wildcards Phil Sutter
2025-09-30 21:06 ` Phil Sutter
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).