When building NFTA_FLOWTABLE_HOOK_DEVS, NFTA_HOOK_DEV or NFTA_HOOK_DEVS attributes, detect trailing asterisks in interface names and reduce attribute length accordingly. Kernel will use strncmp(), effectively performing a prefix search this way. Deserialization (i.e., appending asterisk to interface names which don't include a trailing nul-char) happens in libnftnl. Signed-off-by: Phil Sutter <phil@xxxxxx> --- Changes since v2: - Introduce mnl_attr_put_ifname() to perform the conditional mnl_attr_put() parameter adjustment - Sanity-check array index in above function to avoid out-of-bounds access --- src/mnl.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/mnl.c b/src/mnl.c index 43229f2498e55..8ec4ef40d2761 100644 --- a/src/mnl.c +++ b/src/mnl.c @@ -795,6 +795,17 @@ static void nft_dev_array_free(const struct nft_dev *dev_array) free_const(dev_array); } +static void mnl_attr_put_ifname(struct nlmsghdr *nlh, + int attr, const char *ifname) +{ + int len = strlen(ifname) + 1; + + if (len >= 2 && ifname[len - 2] == '*') + len -= 2; + + mnl_attr_put(nlh, attr, len, ifname); +} + static void mnl_nft_chain_devs_build(struct nlmsghdr *nlh, struct cmd *cmd) { const struct expr *dev_expr = cmd->chain->dev_expr; @@ -805,12 +816,13 @@ static void mnl_nft_chain_devs_build(struct nlmsghdr *nlh, struct cmd *cmd) dev_array = nft_dev_array(dev_expr, &num_devs); if (num_devs == 1) { cmd_add_loc(cmd, nlh, dev_array[0].location); - mnl_attr_put_strz(nlh, NFTA_HOOK_DEV, dev_array[0].ifname); + mnl_attr_put_ifname(nlh, NFTA_HOOK_DEV, dev_array[0].ifname); } else { nest_dev = mnl_attr_nest_start(nlh, NFTA_HOOK_DEVS); for (i = 0; i < num_devs; i++) { cmd_add_loc(cmd, nlh, dev_array[i].location); - mnl_attr_put_strz(nlh, NFTA_DEVICE_NAME, dev_array[i].ifname); + mnl_attr_put_ifname(nlh, NFTA_DEVICE_NAME, + dev_array[i].ifname); } mnl_attr_nest_end(nlh, nest_dev); } @@ -2085,13 +2097,13 @@ static void mnl_nft_ft_devs_build(struct nlmsghdr *nlh, struct cmd *cmd) const struct expr *dev_expr = cmd->flowtable->dev_expr; const struct nft_dev *dev_array; struct nlattr *nest_dev; - int i, num_devs= 0; + int i, num_devs = 0; dev_array = nft_dev_array(dev_expr, &num_devs); nest_dev = mnl_attr_nest_start(nlh, NFTA_FLOWTABLE_HOOK_DEVS); for (i = 0; i < num_devs; i++) { cmd_add_loc(cmd, nlh, dev_array[i].location); - mnl_attr_put_strz(nlh, NFTA_DEVICE_NAME, dev_array[i].ifname); + mnl_attr_put_ifname(nlh, NFTA_DEVICE_NAME, dev_array[i].ifname); } mnl_attr_nest_end(nlh, nest_dev); -- 2.49.0