Skip to content

Commit 49a68e0

Browse files
committed
cfg80211: add various struct element finding helpers
We currently have a number of helpers to find elements that just return a u8 *, change those to return a struct element and add inlines to deal with the u8 * compatibility. Note that the match behaviour is changed to start the natch at the data, so conversion from _ie_match to _elem_match need to be done carefully. Signed-off-by: Johannes Berg <[email protected]>
1 parent c17e28d commit 49a68e0

File tree

3 files changed

+148
-32
lines changed

3 files changed

+148
-32
lines changed

include/net/cfg80211.h

Lines changed: 128 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2062,16 +2062,30 @@ struct cfg80211_bss {
20622062
u8 priv[0] __aligned(sizeof(void *));
20632063
};
20642064

2065+
/**
2066+
* ieee80211_bss_get_elem - find element with given ID
2067+
* @bss: the bss to search
2068+
* @id: the element ID
2069+
*
2070+
* Note that the return value is an RCU-protected pointer, so
2071+
* rcu_read_lock() must be held when calling this function.
2072+
* Return: %NULL if not found.
2073+
*/
2074+
const struct element *ieee80211_bss_get_elem(struct cfg80211_bss *bss, u8 id);
2075+
20652076
/**
20662077
* ieee80211_bss_get_ie - find IE with given ID
20672078
* @bss: the bss to search
2068-
* @ie: the IE ID
2079+
* @id: the element ID
20692080
*
20702081
* Note that the return value is an RCU-protected pointer, so
20712082
* rcu_read_lock() must be held when calling this function.
20722083
* Return: %NULL if not found.
20732084
*/
2074-
const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie);
2085+
static inline const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 id)
2086+
{
2087+
return (void *)ieee80211_bss_get_elem(bss, id);
2088+
}
20752089

20762090

20772091
/**
@@ -4999,6 +5013,33 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
49995013
unsigned int cfg80211_classify8021d(struct sk_buff *skb,
50005014
struct cfg80211_qos_map *qos_map);
50015015

5016+
/**
5017+
* cfg80211_find_elem_match - match information element and byte array in data
5018+
*
5019+
* @eid: element ID
5020+
* @ies: data consisting of IEs
5021+
* @len: length of data
5022+
* @match: byte array to match
5023+
* @match_len: number of bytes in the match array
5024+
* @match_offset: offset in the IE data where the byte array should match.
5025+
* Note the difference to cfg80211_find_ie_match() which considers
5026+
* the offset to start from the element ID byte, but here we take
5027+
* the data portion instead.
5028+
*
5029+
* Return: %NULL if the element ID could not be found or if
5030+
* the element is invalid (claims to be longer than the given
5031+
* data) or if the byte array doesn't match; otherwise return the
5032+
* requested element struct.
5033+
*
5034+
* Note: There are no checks on the element length other than
5035+
* having to fit into the given data and being large enough for the
5036+
* byte array to match.
5037+
*/
5038+
const struct element *
5039+
cfg80211_find_elem_match(u8 eid, const u8 *ies, unsigned int len,
5040+
const u8 *match, unsigned int match_len,
5041+
unsigned int match_offset);
5042+
50025043
/**
50035044
* cfg80211_find_ie_match - match information element and byte array in data
50045045
*
@@ -5023,9 +5064,44 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb,
50235064
* having to fit into the given data and being large enough for the
50245065
* byte array to match.
50255066
*/
5026-
const u8 *cfg80211_find_ie_match(u8 eid, const u8 *ies, int len,
5027-
const u8 *match, int match_len,
5028-
int match_offset);
5067+
static inline const u8 *
5068+
cfg80211_find_ie_match(u8 eid, const u8 *ies, unsigned int len,
5069+
const u8 *match, unsigned int match_len,
5070+
unsigned int match_offset)
5071+
{
5072+
/* match_offset can't be smaller than 2, unless match_len is
5073+
* zero, in which case match_offset must be zero as well.
5074+
*/
5075+
if (WARN_ON((match_len && match_offset < 2) ||
5076+
(!match_len && match_offset)))
5077+
return NULL;
5078+
5079+
return (void *)cfg80211_find_elem_match(eid, ies, len,
5080+
match, match_len,
5081+
match_offset ?
5082+
match_offset - 2 : 0);
5083+
}
5084+
5085+
/**
5086+
* cfg80211_find_elem - find information element in data
5087+
*
5088+
* @eid: element ID
5089+
* @ies: data consisting of IEs
5090+
* @len: length of data
5091+
*
5092+
* Return: %NULL if the element ID could not be found or if
5093+
* the element is invalid (claims to be longer than the given
5094+
* data) or if the byte array doesn't match; otherwise return the
5095+
* requested element struct.
5096+
*
5097+
* Note: There are no checks on the element length other than
5098+
* having to fit into the given data.
5099+
*/
5100+
static inline const struct element *
5101+
cfg80211_find_elem(u8 eid, const u8 *ies, int len)
5102+
{
5103+
return cfg80211_find_elem_match(eid, ies, len, NULL, 0, 0);
5104+
}
50295105

50305106
/**
50315107
* cfg80211_find_ie - find information element in data
@@ -5047,6 +5123,28 @@ static inline const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len)
50475123
return cfg80211_find_ie_match(eid, ies, len, NULL, 0, 0);
50485124
}
50495125

5126+
/**
5127+
* cfg80211_find_ext_elem - find information element with EID Extension in data
5128+
*
5129+
* @ext_eid: element ID Extension
5130+
* @ies: data consisting of IEs
5131+
* @len: length of data
5132+
*
5133+
* Return: %NULL if the etended element could not be found or if
5134+
* the element is invalid (claims to be longer than the given
5135+
* data) or if the byte array doesn't match; otherwise return the
5136+
* requested element struct.
5137+
*
5138+
* Note: There are no checks on the element length other than
5139+
* having to fit into the given data.
5140+
*/
5141+
static inline const struct element *
5142+
cfg80211_find_ext_elem(u8 ext_eid, const u8 *ies, int len)
5143+
{
5144+
return cfg80211_find_elem_match(WLAN_EID_EXTENSION, ies, len,
5145+
&ext_eid, 1, 0);
5146+
}
5147+
50505148
/**
50515149
* cfg80211_find_ext_ie - find information element with EID Extension in data
50525150
*
@@ -5068,6 +5166,25 @@ static inline const u8 *cfg80211_find_ext_ie(u8 ext_eid, const u8 *ies, int len)
50685166
&ext_eid, 1, 2);
50695167
}
50705168

5169+
/**
5170+
* cfg80211_find_vendor_elem - find vendor specific information element in data
5171+
*
5172+
* @oui: vendor OUI
5173+
* @oui_type: vendor-specific OUI type (must be < 0xff), negative means any
5174+
* @ies: data consisting of IEs
5175+
* @len: length of data
5176+
*
5177+
* Return: %NULL if the vendor specific element ID could not be found or if the
5178+
* element is invalid (claims to be longer than the given data); otherwise
5179+
* return the element structure for the requested element.
5180+
*
5181+
* Note: There are no checks on the element length other than having to fit into
5182+
* the given data.
5183+
*/
5184+
const struct element *cfg80211_find_vendor_elem(unsigned int oui, int oui_type,
5185+
const u8 *ies,
5186+
unsigned int len);
5187+
50715188
/**
50725189
* cfg80211_find_vendor_ie - find vendor specific information element in data
50735190
*
@@ -5084,8 +5201,12 @@ static inline const u8 *cfg80211_find_ext_ie(u8 ext_eid, const u8 *ies, int len)
50845201
* Note: There are no checks on the element length other than having to fit into
50855202
* the given data.
50865203
*/
5087-
const u8 *cfg80211_find_vendor_ie(unsigned int oui, int oui_type,
5088-
const u8 *ies, int len);
5204+
static inline const u8 *
5205+
cfg80211_find_vendor_ie(unsigned int oui, int oui_type,
5206+
const u8 *ies, unsigned int len)
5207+
{
5208+
return (void *)cfg80211_find_vendor_elem(oui, oui_type, ies, len);
5209+
}
50895210

50905211
/**
50915212
* cfg80211_send_layer2_update - send layer 2 update frame

net/wireless/scan.c

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -480,48 +480,43 @@ void cfg80211_bss_expire(struct cfg80211_registered_device *rdev)
480480
__cfg80211_bss_expire(rdev, jiffies - IEEE80211_SCAN_RESULT_EXPIRE);
481481
}
482482

483-
const u8 *cfg80211_find_ie_match(u8 eid, const u8 *ies, int len,
484-
const u8 *match, int match_len,
485-
int match_offset)
483+
const struct element *
484+
cfg80211_find_elem_match(u8 eid, const u8 *ies, unsigned int len,
485+
const u8 *match, unsigned int match_len,
486+
unsigned int match_offset)
486487
{
487488
const struct element *elem;
488489

489-
/* match_offset can't be smaller than 2, unless match_len is
490-
* zero, in which case match_offset must be zero as well.
491-
*/
492-
if (WARN_ON((match_len && match_offset < 2) ||
493-
(!match_len && match_offset)))
494-
return NULL;
495-
496490
for_each_element_id(elem, eid, ies, len) {
497-
if (elem->datalen >= match_offset - 2 + match_len &&
498-
!memcmp(elem->data + match_offset - 2, match, match_len))
499-
return (void *)elem;
491+
if (elem->datalen >= match_offset + match_len &&
492+
!memcmp(elem->data + match_offset, match, match_len))
493+
return elem;
500494
}
501495

502496
return NULL;
503497
}
504-
EXPORT_SYMBOL(cfg80211_find_ie_match);
498+
EXPORT_SYMBOL(cfg80211_find_elem_match);
505499

506-
const u8 *cfg80211_find_vendor_ie(unsigned int oui, int oui_type,
507-
const u8 *ies, int len)
500+
const struct element *cfg80211_find_vendor_elem(unsigned int oui, int oui_type,
501+
const u8 *ies,
502+
unsigned int len)
508503
{
509-
const u8 *ie;
504+
const struct element *elem;
510505
u8 match[] = { oui >> 16, oui >> 8, oui, oui_type };
511506
int match_len = (oui_type < 0) ? 3 : sizeof(match);
512507

513508
if (WARN_ON(oui_type > 0xff))
514509
return NULL;
515510

516-
ie = cfg80211_find_ie_match(WLAN_EID_VENDOR_SPECIFIC, ies, len,
517-
match, match_len, 2);
511+
elem = cfg80211_find_elem_match(WLAN_EID_VENDOR_SPECIFIC, ies, len,
512+
match, match_len, 0);
518513

519-
if (ie && (ie[1] < 4))
514+
if (!elem || elem->datalen < 4)
520515
return NULL;
521516

522-
return ie;
517+
return elem;
523518
}
524-
EXPORT_SYMBOL(cfg80211_find_vendor_ie);
519+
EXPORT_SYMBOL(cfg80211_find_vendor_elem);
525520

526521
static bool is_bss(struct cfg80211_bss *a, const u8 *bssid,
527522
const u8 *ssid, size_t ssid_len)

net/wireless/util.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -776,17 +776,17 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb,
776776
}
777777
EXPORT_SYMBOL(cfg80211_classify8021d);
778778

779-
const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie)
779+
const struct element *ieee80211_bss_get_elem(struct cfg80211_bss *bss, u8 id)
780780
{
781781
const struct cfg80211_bss_ies *ies;
782782

783783
ies = rcu_dereference(bss->ies);
784784
if (!ies)
785785
return NULL;
786786

787-
return cfg80211_find_ie(ie, ies->data, ies->len);
787+
return cfg80211_find_elem(id, ies->data, ies->len);
788788
}
789-
EXPORT_SYMBOL(ieee80211_bss_get_ie);
789+
EXPORT_SYMBOL(ieee80211_bss_get_elem);
790790

791791
void cfg80211_upload_connect_keys(struct wireless_dev *wdev)
792792
{

0 commit comments

Comments
 (0)