diff options
Diffstat (limited to 'lib/nl80211.c')
-rw-r--r-- | lib/nl80211.c | 109 |
1 files changed, 57 insertions, 52 deletions
diff --git a/lib/nl80211.c b/lib/nl80211.c index d7c94b8..f43a33d 100644 --- a/lib/nl80211.c +++ b/lib/nl80211.c @@ -169,6 +169,7 @@ enum { DF_OFFSET1 = (1 << 4), DF_ARRAY = (1 << 5), DF_BINARY = (1 << 6), + DF_RELATED = (1 << 7), }; typedef struct uc_nl_attr_spec { @@ -187,6 +188,7 @@ typedef struct uc_nl_nested_spec { #define SIZE(type) (void *)(uintptr_t)sizeof(struct type) #define MEMBER(type, field) (void *)(uintptr_t)offsetof(struct type, field) +#define ATTRID(id) (void *)(uintptr_t)(id) static const uc_nl_nested_spec_t nl80211_cqm_nla = { .headsize = 0, @@ -565,7 +567,7 @@ static const uc_nl_nested_spec_t nl80211_wiphy_bands_iftype_data_nla = { { NL80211_BAND_IFTYPE_ATTR_IFTYPES, "iftypes", DT_NESTED, 0, &nl80211_ifcomb_limit_types_nla }, { NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC, "he_cap_mac", DT_U8, DF_ARRAY, NULL }, { NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY, "he_cap_phy", DT_U8, DF_ARRAY, NULL }, - { NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET, "he_cap_mcs_set", DT_HE_MCS, 0, NULL }, + { NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET, "he_cap_mcs_set", DT_HE_MCS, DF_RELATED, ATTRID(NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY) }, { NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE, "he_cap_ppe", DT_U8, DF_ARRAY, NULL }, { NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA, "he_6ghz_capa", DT_U16, 0, NULL }, { NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS, "vendor_elems", DT_STRING, DF_BINARY, NULL }, @@ -1030,12 +1032,12 @@ 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); static uc_value_t * -uc_nl_convert_attr(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, char *base, struct nlattr **tb, uc_vm_t *vm); +uc_nl_convert_attr(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, char *base, struct nlattr *attr, struct nlattr *attr2, uc_vm_t *vm); static bool uc_nl_convert_attrs(struct nl_msg *msg, void *buf, size_t buflen, size_t headsize, const uc_nl_attr_spec_t *attrs, size_t nattrs, uc_vm_t *vm, uc_value_t *obj) { - struct nlattr **tb, *nla, *nla_nest; + struct nlattr **tb, *nla, *nla2, *nla_nest; size_t i, type, maxattr = 0; uc_value_t *v, *arr; int rem; @@ -1071,9 +1073,7 @@ uc_nl_convert_attrs(struct nl_msg *msg, void *buf, size_t buflen, size_t headsiz attrs[i].auxdata && nla_type(nla) != (intptr_t)attrs[i].auxdata) continue; - tb[attrs[i].attr] = nla; - - v = uc_nl_convert_attr(&attrs[i], msg, (char *)buf, tb, vm); + v = uc_nl_convert_attr(&attrs[i], msg, (char *)buf, nla, NULL, vm); if (!v) continue; @@ -1093,7 +1093,12 @@ uc_nl_convert_attrs(struct nl_msg *msg, void *buf, size_t buflen, size_t headsiz v = arr; } else { - v = uc_nl_convert_attr(&attrs[i], msg, (char *)buf, tb, vm); + if (attrs[i].flags & DF_RELATED) + nla2 = tb[(uintptr_t)attrs[i].auxdata]; + else + nla2 = NULL; + + v = uc_nl_convert_attr(&attrs[i], msg, (char *)buf, tb[attrs[i].attr], nla2, vm); if (!v) continue; @@ -1183,7 +1188,7 @@ uc_nl_parse_rta_nested(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, char * } static uc_value_t * -uc_nl_convert_rta_nested(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr **tb, uc_vm_t *vm) +uc_nl_convert_rta_nested(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr *attr, uc_vm_t *vm) { const uc_nl_nested_spec_t *nest = spec->auxdata; uc_value_t *nested_obj; @@ -1192,13 +1197,13 @@ uc_nl_convert_rta_nested(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, stru if (!nest) return NULL; - if (!nla_check_len(tb[spec->attr], nest->headsize)) + if (!nla_check_len(attr, nest->headsize)) return NULL; nested_obj = ucv_object_new(vm); rv = uc_nl_convert_attrs(msg, - nla_data(tb[spec->attr]), nla_len(tb[spec->attr]), nest->headsize, + nla_data(attr), nla_len(attr), nest->headsize, nest->attrs, nest->nattrs, vm, nested_obj); @@ -1212,17 +1217,17 @@ uc_nl_convert_rta_nested(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, stru } static uc_value_t * -uc_nl_convert_rta_ht_mcs(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr **tb, uc_vm_t *vm) +uc_nl_convert_rta_ht_mcs(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr *attr, uc_vm_t *vm) { uc_value_t *mcs_obj, *mcs_idx; uint16_t max_rate = 0; uint8_t *mcs; size_t i; - if (!nla_check_len(tb[spec->attr], 16)) + if (!nla_check_len(attr, 16)) return NULL; - mcs = nla_data(tb[spec->attr]); + mcs = nla_data(attr); mcs_obj = ucv_object_new(vm); max_rate = (mcs[10] | ((mcs[11] & 0x3) << 8)); @@ -1247,16 +1252,16 @@ uc_nl_convert_rta_ht_mcs(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, stru } static uc_value_t * -uc_nl_convert_rta_ht_cap(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr **tb, uc_vm_t *vm) +uc_nl_convert_rta_ht_cap(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr *attr, uc_vm_t *vm) { uc_value_t *cap_obj, *mcs_obj, *rx_mask; struct ieee80211_ht_cap *cap; size_t i; - if (!nla_check_len(tb[spec->attr], sizeof(*cap))) + if (!nla_check_len(attr, sizeof(*cap))) return NULL; - cap = nla_data(tb[spec->attr]); + cap = nla_data(attr); cap_obj = ucv_object_new(vm); ucv_object_add(cap_obj, "cap_info", ucv_uint64_new(le16toh(cap->cap_info))); @@ -1281,17 +1286,17 @@ uc_nl_convert_rta_ht_cap(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, stru } static uc_value_t * -uc_nl_convert_rta_vht_mcs(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr **tb, uc_vm_t *vm) +uc_nl_convert_rta_vht_mcs(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr *attr, uc_vm_t *vm) { uc_value_t *mcs_obj, *mcs_set, *mcs_entry, *mcs_idx; size_t i, j, max_idx; uint16_t u16; uint8_t *mcs; - if (!nla_check_len(tb[spec->attr], 8)) + if (!nla_check_len(attr, 8)) return NULL; - mcs = nla_data(tb[spec->attr]); + mcs = nla_data(attr); mcs_obj = ucv_object_new(vm); u16 = mcs[0] | (mcs[1] << 8); @@ -1352,7 +1357,7 @@ uc_nl_convert_rta_vht_mcs(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, str } static uc_value_t * -uc_nl_convert_rta_he_mcs(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr **tb, uc_vm_t *vm) +uc_nl_convert_rta_he_mcs(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr *attr, struct nlattr *phy_attr, uc_vm_t *vm) { uint8_t bw_support_mask[] = { (1 << 1) | (1 << 2), (1 << 3), (1 << 4) }; uc_value_t *mcs_set, *mcs_bw, *mcs_dir, *mcs_entry, *mcs_idx; @@ -1360,13 +1365,13 @@ uc_nl_convert_rta_he_mcs(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, stru uint16_t u16, phy_cap_0 = 0; size_t i, j, k, l, max_idx; - if (!nla_check_len(tb[spec->attr], sizeof(mcs))) + if (!nla_check_len(attr, sizeof(mcs))) return NULL; - if (nla_check_len(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY], sizeof(phy_cap_0))) - phy_cap_0 = nla_get_u16(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]); + if (nla_check_len(phy_attr, sizeof(phy_cap_0))) + phy_cap_0 = nla_get_u16(phy_attr); - memcpy(mcs, nla_data(tb[spec->attr]), sizeof(mcs)); + memcpy(mcs, nla_data(attr), sizeof(mcs)); mcs_set = ucv_array_new_length(vm, 3); @@ -1423,14 +1428,14 @@ uc_nl_convert_rta_he_mcs(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, stru } static uc_value_t * -uc_nl_convert_rta_ie(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr **tb, uc_vm_t *vm) +uc_nl_convert_rta_ie(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, struct nlattr *attr, uc_vm_t *vm) { uc_value_t *ie_arr, *ie_obj; uint8_t *ie; size_t len; - len = nla_len(tb[spec->attr]); - ie = nla_data(tb[spec->attr]); + len = nla_len(attr); + ie = nla_data(attr); if (len < 2) return NULL; @@ -1699,7 +1704,7 @@ uc_nl_convert_numval(const uc_nl_attr_spec_t *spec, char *base) } static uc_value_t * -uc_nl_convert_attr(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, char *base, struct nlattr **tb, uc_vm_t *vm) +uc_nl_convert_attr(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, char *base, struct nlattr *attr, struct nlattr *attr2, uc_vm_t *vm) { union { uint8_t u8; uint16_t u16; uint32_t u32; uint64_t u64; size_t sz; } t = { 0 }; char buf[sizeof("FF:FF:FF:FF:FF:FF")]; @@ -1716,17 +1721,17 @@ uc_nl_convert_attr(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, char *base case DT_U64: if (spec->flags & DF_ARRAY) { assert(spec->attr != 0); - assert((nla_len(tb[spec->attr]) % dt_sizes[spec->type]) == 0); + assert((nla_len(attr) % dt_sizes[spec->type]) == 0); - v = ucv_array_new_length(vm, nla_len(tb[spec->attr]) / dt_sizes[spec->type]); + v = ucv_array_new_length(vm, nla_len(attr) / dt_sizes[spec->type]); - for (i = 0; i < nla_len(tb[spec->attr]); i += dt_sizes[spec->type]) - ucv_array_push(v, uc_nl_convert_numval(spec, nla_data(tb[spec->attr]) + i)); + for (i = 0; i < nla_len(attr); i += dt_sizes[spec->type]) + ucv_array_push(v, uc_nl_convert_numval(spec, nla_data(attr) + i)); return v; } - else if (nla_check_len(tb[spec->attr], dt_sizes[spec->type])) { - return uc_nl_convert_numval(spec, nla_data(tb[spec->attr])); + else if (nla_check_len(attr, dt_sizes[spec->type])) { + return uc_nl_convert_numval(spec, nla_data(attr)); } return NULL; @@ -1734,15 +1739,15 @@ uc_nl_convert_attr(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, char *base case DT_BOOL: if (spec->attr == 0) t.u8 = uc_nl_get_struct_member_u8(base, spec->auxdata); - else if (nla_check_len(tb[spec->attr], sizeof(t.u8))) - t.u8 = nla_get_u8(tb[spec->attr]); + else if (nla_check_len(attr, sizeof(t.u8))) + t.u8 = nla_get_u8(attr); return ucv_boolean_new(t.u8 != 0); case DT_FLAG: if (spec->attr == 0) t.u8 = uc_nl_get_struct_member_u8(base, spec->auxdata); - else if (tb[spec->attr] != NULL) + else if (attr != NULL) t.u8 = 1; return ucv_boolean_new(t.u8 != 0); @@ -1750,21 +1755,21 @@ uc_nl_convert_attr(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, char *base case DT_STRING: assert(spec->attr != 0); - if (!nla_check_len(tb[spec->attr], 1)) + if (!nla_check_len(attr, 1)) return NULL; - t.sz = nla_len(tb[spec->attr]); + t.sz = nla_len(attr); if (!(spec->flags & DF_BINARY)) t.sz -= 1; - return ucv_string_new_length(nla_data(tb[spec->attr]), t.sz); + return ucv_string_new_length(nla_data(attr), t.sz); case DT_NETDEV: if (spec->attr == 0) t.u32 = uc_nl_get_struct_member_u32(base, spec->auxdata); - else if (nla_check_len(tb[spec->attr], sizeof(t.u32))) - t.u32 = nla_get_u32(tb[spec->attr]); + else if (nla_check_len(attr, sizeof(t.u32))) + t.u32 = nla_get_u32(attr); if (if_indextoname(t.u32, buf)) return ucv_string_new(buf); @@ -1774,10 +1779,10 @@ uc_nl_convert_attr(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, char *base case DT_LLADDR: assert(spec->attr != 0); - if (!nla_check_len(tb[spec->attr], sizeof(*ea))) + if (!nla_check_len(attr, sizeof(*ea))) return NULL; - ea = nla_data(tb[spec->attr]); + ea = nla_data(attr); snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x", ea->ether_addr_octet[0], ea->ether_addr_octet[1], @@ -1789,29 +1794,29 @@ uc_nl_convert_attr(const uc_nl_attr_spec_t *spec, struct nl_msg *msg, char *base case DT_INADDR: assert(spec->attr != 0); - if (!nla_check_len(tb[spec->attr], sizeof(struct in_addr)) || - !inet_ntop(AF_INET, nla_data(tb[spec->attr]), buf, sizeof(buf))) + if (!nla_check_len(attr, sizeof(struct in_addr)) || + !inet_ntop(AF_INET, nla_data(attr), buf, sizeof(buf))) return NULL; return ucv_string_new(buf); case DT_NESTED: - return uc_nl_convert_rta_nested(spec, msg, tb, vm); + return uc_nl_convert_rta_nested(spec, msg, attr, vm); case DT_HT_MCS: - return uc_nl_convert_rta_ht_mcs(spec, msg, tb, vm); + return uc_nl_convert_rta_ht_mcs(spec, msg, attr, vm); case DT_HT_CAP: - return uc_nl_convert_rta_ht_cap(spec, msg, tb, vm); + return uc_nl_convert_rta_ht_cap(spec, msg, attr, vm); case DT_VHT_MCS: - return uc_nl_convert_rta_vht_mcs(spec, msg, tb, vm); + return uc_nl_convert_rta_vht_mcs(spec, msg, attr, vm); case DT_HE_MCS: - return uc_nl_convert_rta_he_mcs(spec, msg, tb, vm); + return uc_nl_convert_rta_he_mcs(spec, msg, attr, attr2, vm); case DT_IE: - return uc_nl_convert_rta_ie(spec, msg, tb, vm); + return uc_nl_convert_rta_ie(spec, msg, attr, vm); default: assert(0); |