|
|
@@ -3185,4 +3185,57 @@ static inline bool ieee80211_action_contains_tpc(struct sk_buff *skb)
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+struct element {
|
|
|
+ u8 id;
|
|
|
+ u8 datalen;
|
|
|
+ u8 data[];
|
|
|
+};
|
|
|
+
|
|
|
+/* element iteration helpers */
|
|
|
+#define for_each_element(element, _data, _datalen) \
|
|
|
+ for (element = (void *)(_data); \
|
|
|
+ (u8 *)(_data) + (_datalen) - (u8 *)element >= \
|
|
|
+ sizeof(*element) && \
|
|
|
+ (u8 *)(_data) + (_datalen) - (u8 *)element >= \
|
|
|
+ sizeof(*element) + element->datalen; \
|
|
|
+ element = (void *)(element->data + element->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 %true 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 %false.
|
|
|
+ *
|
|
|
+ * If some data was malformed, this returns %false since the last parsed
|
|
|
+ * element will not fill the whole remaining data.
|
|
|
+ */
|
|
|
+static inline bool for_each_element_completed(const struct element *element,
|
|
|
+ const void *data, size_t datalen)
|
|
|
+{
|
|
|
+ return (u8 *)element == (u8 *)data + datalen;
|
|
|
+}
|
|
|
+
|
|
|
#endif /* LINUX_IEEE80211_H */
|