diff options
author | Johannes Berg <johannes.berg@intel.com> | 2019-02-08 16:57:48 (GMT) |
---|---|---|
committer | Jouni Malinen <j@w1.fi> | 2019-02-11 11:37:22 (GMT) |
commit | 0e0c31bdc57a124c2b62e6659ef9e20b8368c8de (patch) | |
tree | 8e7efc7309739915d6ff00bdd44846da487ea027 | |
parent | 51c83edfca481ca789e49e4af4c7938733e24635 (diff) | |
download | hostap-0e0c31bdc57a124c2b62e6659ef9e20b8368c8de.zip hostap-0e0c31bdc57a124c2b62e6659ef9e20b8368c8de.tar.gz hostap-0e0c31bdc57a124c2b62e6659ef9e20b8368c8de.tar.bz2 |
common: Add strongly typed element iteration macros
Rather than always iterating elements from frames with pure
u8 pointers, add a type "struct element" that encapsulates
the id/datalen/data format of them.
Then, add the element iteration macros
* for_each_element
* for_each_element_id
* for_each_element_extid
which take, as their first 'argument', such a structure and
iterate through a given u8 array interpreting it as elements.
While at it also add
* for_each_subelement
* for_each_subelement_id
* for_each_subelement_extid
which instead of taking data/length just take an outer element
and use its data/datalen.
Also add for_each_element_completed() to determine if any of
the loops above completed, i.e., it was able to parse all of
the elements successfully and no data remained.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r-- | src/common/ieee802_11_common.h | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h index ce3bb8b..4e35b79 100644 --- a/src/common/ieee802_11_common.h +++ b/src/common/ieee802_11_common.h @@ -12,6 +12,12 @@ #include "defs.h" #include "ieee802_11_defs.h" +struct element { + u8 id; + u8 datalen; + u8 data[]; +} STRUCT_PACKED; + struct hostapd_hw_modes; #define MAX_NOF_MB_IES_SUPPORTED 5 @@ -214,4 +220,51 @@ int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep, int ieee802_11_ext_capab(const u8 *ie, unsigned int capab); +/* element iteration helpers */ +#define for_each_element(_elem, _data, _datalen) \ + for (_elem = (const struct element *) (_data); \ + (const u8 *) (_data) + (_datalen) - (const u8 *) _elem >= \ + (int) sizeof(*_elem) && \ + (const u8 *) (_data) + (_datalen) - (const u8 *) _elem >= \ + (int) sizeof(*_elem) + _elem->datalen; \ + _elem = (const struct element *) (_elem->data + _elem->datalen)) + +#define for_each_element_id(element, _id, data, datalen) \ + for_each_element(element, data, datalen) \ + if (element->id == (_id)) + +#define for_each_element_extid(element, extid, _data, _datalen) \ + for_each_element(element, _data, _datalen) \ + if (element->id == WLAN_EID_EXTENSION && \ + element->datalen > 0 && \ + element->data[0] == (extid)) + +#define for_each_subelement(sub, element) \ + for_each_element(sub, (element)->data, (element)->datalen) + +#define for_each_subelement_id(sub, id, element) \ + for_each_element_id(sub, id, (element)->data, (element)->datalen) + +#define for_each_subelement_extid(sub, extid, element) \ + for_each_element_extid(sub, extid, (element)->data, (element)->datalen) + +/** + * for_each_element_completed - Determine if element parsing consumed all data + * @element: Element pointer after for_each_element() or friends + * @data: Same data pointer as passed to for_each_element() or friends + * @datalen: Same data length as passed to for_each_element() or friends + * + * This function returns 1 if all the data was parsed or considered + * while walking the elements. Only use this if your for_each_element() + * loop cannot be broken out of, otherwise it always returns 0. + * + * If some data was malformed, this returns %false since the last parsed + * element will not fill the whole remaining data. + */ +static inline int for_each_element_completed(const struct element *element, + const void *data, size_t datalen) +{ + return (const u8 *) element == (const u8 *) data + datalen; +} + #endif /* IEEE802_11_COMMON_H */ |