diff options
Diffstat (limited to 'net/wireless/scan.c')
-rw-r--r-- | net/wireless/scan.c | 58 |
1 files changed, 27 insertions, 31 deletions
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 0358e12be54b..b5bd58d0f731 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -352,52 +352,48 @@ void cfg80211_bss_expire(struct cfg80211_registered_device *rdev) | |||
352 | __cfg80211_bss_expire(rdev, jiffies - IEEE80211_SCAN_RESULT_EXPIRE); | 352 | __cfg80211_bss_expire(rdev, jiffies - IEEE80211_SCAN_RESULT_EXPIRE); |
353 | } | 353 | } |
354 | 354 | ||
355 | const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len) | 355 | const u8 *cfg80211_find_ie_match(u8 eid, const u8 *ies, int len, |
356 | const u8 *match, int match_len, | ||
357 | int match_offset) | ||
356 | { | 358 | { |
357 | while (len > 2 && ies[0] != eid) { | 359 | /* match_offset can't be smaller than 2, unless match_len is |
360 | * zero, in which case match_offset must be zero as well. | ||
361 | */ | ||
362 | if (WARN_ON((match_len && match_offset < 2) || | ||
363 | (!match_len && match_offset))) | ||
364 | return NULL; | ||
365 | |||
366 | while (len >= 2 && len >= ies[1] + 2) { | ||
367 | if ((ies[0] == eid) && | ||
368 | (ies[1] + 2 >= match_offset + match_len) && | ||
369 | !memcmp(ies + match_offset, match, match_len)) | ||
370 | return ies; | ||
371 | |||
358 | len -= ies[1] + 2; | 372 | len -= ies[1] + 2; |
359 | ies += ies[1] + 2; | 373 | ies += ies[1] + 2; |
360 | } | 374 | } |
361 | if (len < 2) | 375 | |
362 | return NULL; | 376 | return NULL; |
363 | if (len < 2 + ies[1]) | ||
364 | return NULL; | ||
365 | return ies; | ||
366 | } | 377 | } |
367 | EXPORT_SYMBOL(cfg80211_find_ie); | 378 | EXPORT_SYMBOL(cfg80211_find_ie_match); |
368 | 379 | ||
369 | const u8 *cfg80211_find_vendor_ie(unsigned int oui, int oui_type, | 380 | const u8 *cfg80211_find_vendor_ie(unsigned int oui, int oui_type, |
370 | const u8 *ies, int len) | 381 | const u8 *ies, int len) |
371 | { | 382 | { |
372 | struct ieee80211_vendor_ie *ie; | 383 | const u8 *ie; |
373 | const u8 *pos = ies, *end = ies + len; | 384 | u8 match[] = { oui >> 16, oui >> 8, oui, oui_type }; |
374 | int ie_oui; | 385 | int match_len = (oui_type < 0) ? 3 : sizeof(match); |
375 | 386 | ||
376 | if (WARN_ON(oui_type > 0xff)) | 387 | if (WARN_ON(oui_type > 0xff)) |
377 | return NULL; | 388 | return NULL; |
378 | 389 | ||
379 | while (pos < end) { | 390 | ie = cfg80211_find_ie_match(WLAN_EID_VENDOR_SPECIFIC, ies, len, |
380 | pos = cfg80211_find_ie(WLAN_EID_VENDOR_SPECIFIC, pos, | 391 | match, match_len, 2); |
381 | end - pos); | ||
382 | if (!pos) | ||
383 | return NULL; | ||
384 | |||
385 | ie = (struct ieee80211_vendor_ie *)pos; | ||
386 | |||
387 | /* make sure we can access ie->len */ | ||
388 | BUILD_BUG_ON(offsetof(struct ieee80211_vendor_ie, len) != 1); | ||
389 | 392 | ||
390 | if (ie->len < sizeof(*ie)) | 393 | if (ie && (ie[1] < 4)) |
391 | goto cont; | 394 | return NULL; |
392 | 395 | ||
393 | ie_oui = ie->oui[0] << 16 | ie->oui[1] << 8 | ie->oui[2]; | 396 | return ie; |
394 | if (ie_oui == oui && | ||
395 | (oui_type < 0 || ie->oui_type == oui_type)) | ||
396 | return pos; | ||
397 | cont: | ||
398 | pos += 2 + ie->len; | ||
399 | } | ||
400 | return NULL; | ||
401 | } | 397 | } |
402 | EXPORT_SYMBOL(cfg80211_find_vendor_ie); | 398 | EXPORT_SYMBOL(cfg80211_find_vendor_ie); |
403 | 399 | ||