From 6e3cf83a77a7363d05c2b4c604187004d6eb17ef Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 29 Jun 2024 12:05:29 +0200 Subject: [PATCH] nl80211: add support for multi-attribute arrays For newly added attributes, the kernel prefers to no longer add a nesting container attribute. Instead, an attribute with the element type is simply added multiple times within the outer container. Add support for this array style, which will be used in the pending wiphy multi radio support. Signed-off-by: Felix Fietkau --- lib/nl80211.c | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/lib/nl80211.c b/lib/nl80211.c index f43a33da..3d2f6e24 100644 --- a/lib/nl80211.c +++ b/lib/nl80211.c @@ -170,6 +170,7 @@ enum { DF_ARRAY = (1 << 5), DF_BINARY = (1 << 6), DF_RELATED = (1 << 7), + DF_REPEATED = (1 << 8), }; typedef struct uc_nl_attr_spec { @@ -1008,26 +1009,6 @@ uc_nl_get_struct_member_u32(char *base, const void *offset) return u32; } -static void -uc_nl_nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len) -{ - struct nlattr *nla; - int rem; - - memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1)); - - nla_for_each_attr(nla, head, len, rem) { - int type = nla_type(nla); - - if (type <= maxtype) - tb[type] = nla; - } - - if (rem > 0) - fprintf(stderr, "netlink: %d bytes leftover after parsing attributes.\n", rem); -} - - static bool uc_nl_parse_attr(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, char *base, uc_vm_t *vm, uc_value_t *val, size_t idx); @@ -1051,12 +1032,10 @@ uc_nl_convert_attrs(struct nl_msg *msg, void *buf, size_t buflen, size_t headsiz if (!tb) return false; - uc_nl_nla_parse(tb, maxattr, buf + headsize, buflen - headsize); - nla_for_each_attr(nla, buf + headsize, buflen - headsize, rem) { type = nla_type(nla); - if (type <= maxattr) + if (type <= maxattr && !tb[type]) tb[type] = nla; } @@ -1064,7 +1043,28 @@ uc_nl_convert_attrs(struct nl_msg *msg, void *buf, size_t buflen, size_t headsiz if (attrs[i].attr != 0 && !tb[attrs[i].attr]) continue; - if (attrs[i].flags & DF_MULTIPLE) { + if (attrs[i].flags & DF_REPEATED) { + arr = ucv_array_new(vm); + + nla = tb[attrs[i].attr]; + rem = buflen - ((void *)nla - buf); + for (; nla_ok(nla, rem); nla = nla_next(nla, &rem)) { + if (nla_type(nla) != (int)attrs[i].attr) + break; + v = uc_nl_convert_attr(&attrs[i], msg, (char *)buf, nla, NULL, vm); + if (!v) + continue; + + ucv_array_push(arr, v); + } + if (!ucv_array_length(arr)) { + ucv_put(arr); + continue; + } + + v = arr; + } + else if (attrs[i].flags & DF_MULTIPLE) { arr = ucv_array_new(vm); nla_nest = tb[attrs[i].attr];