|
@@ -531,24 +531,78 @@ static int cmp_bss(struct cfg80211_bss *a,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static bool cfg80211_bss_type_match(u16 capability,
|
|
|
+ enum ieee80211_band band,
|
|
|
+ enum ieee80211_bss_type bss_type)
|
|
|
+{
|
|
|
+ bool ret = true;
|
|
|
+ u16 mask, val;
|
|
|
+
|
|
|
+ if (bss_type == IEEE80211_BSS_TYPE_ANY)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ if (band == IEEE80211_BAND_60GHZ) {
|
|
|
+ mask = WLAN_CAPABILITY_DMG_TYPE_MASK;
|
|
|
+ switch (bss_type) {
|
|
|
+ case IEEE80211_BSS_TYPE_ESS:
|
|
|
+ val = WLAN_CAPABILITY_DMG_TYPE_AP;
|
|
|
+ break;
|
|
|
+ case IEEE80211_BSS_TYPE_PBSS:
|
|
|
+ val = WLAN_CAPABILITY_DMG_TYPE_PBSS;
|
|
|
+ break;
|
|
|
+ case IEEE80211_BSS_TYPE_IBSS:
|
|
|
+ val = WLAN_CAPABILITY_DMG_TYPE_IBSS;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ mask = WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS;
|
|
|
+ switch (bss_type) {
|
|
|
+ case IEEE80211_BSS_TYPE_ESS:
|
|
|
+ val = WLAN_CAPABILITY_ESS;
|
|
|
+ break;
|
|
|
+ case IEEE80211_BSS_TYPE_IBSS:
|
|
|
+ val = WLAN_CAPABILITY_IBSS;
|
|
|
+ break;
|
|
|
+ case IEEE80211_BSS_TYPE_MBSS:
|
|
|
+ val = 0;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = ((capability & mask) == val);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
/* Returned bss is reference counted and must be cleaned up appropriately. */
|
|
|
struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy,
|
|
|
struct ieee80211_channel *channel,
|
|
|
const u8 *bssid,
|
|
|
const u8 *ssid, size_t ssid_len,
|
|
|
- u16 capa_mask, u16 capa_val)
|
|
|
+ enum ieee80211_bss_type bss_type,
|
|
|
+ enum ieee80211_privacy privacy)
|
|
|
{
|
|
|
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
|
|
struct cfg80211_internal_bss *bss, *res = NULL;
|
|
|
unsigned long now = jiffies;
|
|
|
+ int bss_privacy;
|
|
|
|
|
|
- trace_cfg80211_get_bss(wiphy, channel, bssid, ssid, ssid_len, capa_mask,
|
|
|
- capa_val);
|
|
|
+ trace_cfg80211_get_bss(wiphy, channel, bssid, ssid, ssid_len, bss_type,
|
|
|
+ privacy);
|
|
|
|
|
|
spin_lock_bh(&rdev->bss_lock);
|
|
|
|
|
|
list_for_each_entry(bss, &rdev->bss_list, list) {
|
|
|
- if ((bss->pub.capability & capa_mask) != capa_val)
|
|
|
+ if (!cfg80211_bss_type_match(bss->pub.capability,
|
|
|
+ bss->pub.channel->band, bss_type))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ bss_privacy = (bss->pub.capability & WLAN_CAPABILITY_PRIVACY);
|
|
|
+ if ((privacy == IEEE80211_PRIVACY_ON && !bss_privacy) ||
|
|
|
+ (privacy == IEEE80211_PRIVACY_OFF && bss_privacy))
|
|
|
continue;
|
|
|
if (channel && bss->pub.channel != channel)
|
|
|
continue;
|
|
@@ -896,6 +950,7 @@ cfg80211_inform_bss_width(struct wiphy *wiphy,
|
|
|
struct cfg80211_bss_ies *ies;
|
|
|
struct ieee80211_channel *channel;
|
|
|
struct cfg80211_internal_bss tmp = {}, *res;
|
|
|
+ int bss_type;
|
|
|
bool signal_valid;
|
|
|
|
|
|
if (WARN_ON(!wiphy))
|
|
@@ -950,8 +1005,15 @@ cfg80211_inform_bss_width(struct wiphy *wiphy,
|
|
|
if (!res)
|
|
|
return NULL;
|
|
|
|
|
|
- if (res->pub.capability & WLAN_CAPABILITY_ESS)
|
|
|
- regulatory_hint_found_beacon(wiphy, channel, gfp);
|
|
|
+ if (channel->band == IEEE80211_BAND_60GHZ) {
|
|
|
+ bss_type = res->pub.capability & WLAN_CAPABILITY_DMG_TYPE_MASK;
|
|
|
+ if (bss_type == WLAN_CAPABILITY_DMG_TYPE_AP ||
|
|
|
+ bss_type == WLAN_CAPABILITY_DMG_TYPE_PBSS)
|
|
|
+ regulatory_hint_found_beacon(wiphy, channel, gfp);
|
|
|
+ } else {
|
|
|
+ if (res->pub.capability & WLAN_CAPABILITY_ESS)
|
|
|
+ regulatory_hint_found_beacon(wiphy, channel, gfp);
|
|
|
+ }
|
|
|
|
|
|
trace_cfg80211_return_bss(&res->pub);
|
|
|
/* cfg80211_bss_update gives us a referenced result */
|
|
@@ -973,6 +1035,7 @@ cfg80211_inform_bss_width_frame(struct wiphy *wiphy,
|
|
|
bool signal_valid;
|
|
|
size_t ielen = len - offsetof(struct ieee80211_mgmt,
|
|
|
u.probe_resp.variable);
|
|
|
+ int bss_type;
|
|
|
|
|
|
BUILD_BUG_ON(offsetof(struct ieee80211_mgmt, u.probe_resp.variable) !=
|
|
|
offsetof(struct ieee80211_mgmt, u.beacon.variable));
|
|
@@ -1025,8 +1088,15 @@ cfg80211_inform_bss_width_frame(struct wiphy *wiphy,
|
|
|
if (!res)
|
|
|
return NULL;
|
|
|
|
|
|
- if (res->pub.capability & WLAN_CAPABILITY_ESS)
|
|
|
- regulatory_hint_found_beacon(wiphy, channel, gfp);
|
|
|
+ if (channel->band == IEEE80211_BAND_60GHZ) {
|
|
|
+ bss_type = res->pub.capability & WLAN_CAPABILITY_DMG_TYPE_MASK;
|
|
|
+ if (bss_type == WLAN_CAPABILITY_DMG_TYPE_AP ||
|
|
|
+ bss_type == WLAN_CAPABILITY_DMG_TYPE_PBSS)
|
|
|
+ regulatory_hint_found_beacon(wiphy, channel, gfp);
|
|
|
+ } else {
|
|
|
+ if (res->pub.capability & WLAN_CAPABILITY_ESS)
|
|
|
+ regulatory_hint_found_beacon(wiphy, channel, gfp);
|
|
|
+ }
|
|
|
|
|
|
trace_cfg80211_return_bss(&res->pub);
|
|
|
/* cfg80211_bss_update gives us a referenced result */
|
|
@@ -1237,17 +1307,17 @@ int cfg80211_wext_siwscan(struct net_device *dev,
|
|
|
kfree(creq);
|
|
|
return err;
|
|
|
}
|
|
|
-EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan);
|
|
|
+EXPORT_WEXT_HANDLER(cfg80211_wext_siwscan);
|
|
|
|
|
|
-static void ieee80211_scan_add_ies(struct iw_request_info *info,
|
|
|
- const struct cfg80211_bss_ies *ies,
|
|
|
- char **current_ev, char *end_buf)
|
|
|
+static char *ieee80211_scan_add_ies(struct iw_request_info *info,
|
|
|
+ const struct cfg80211_bss_ies *ies,
|
|
|
+ char *current_ev, char *end_buf)
|
|
|
{
|
|
|
const u8 *pos, *end, *next;
|
|
|
struct iw_event iwe;
|
|
|
|
|
|
if (!ies)
|
|
|
- return;
|
|
|
+ return current_ev;
|
|
|
|
|
|
/*
|
|
|
* If needed, fragment the IEs buffer (at IE boundaries) into short
|
|
@@ -1264,10 +1334,11 @@ static void ieee80211_scan_add_ies(struct iw_request_info *info,
|
|
|
memset(&iwe, 0, sizeof(iwe));
|
|
|
iwe.cmd = IWEVGENIE;
|
|
|
iwe.u.data.length = next - pos;
|
|
|
- *current_ev = iwe_stream_add_point(info, *current_ev,
|
|
|
- end_buf, &iwe,
|
|
|
- (void *)pos);
|
|
|
-
|
|
|
+ current_ev = iwe_stream_add_point_check(info, current_ev,
|
|
|
+ end_buf, &iwe,
|
|
|
+ (void *)pos);
|
|
|
+ if (IS_ERR(current_ev))
|
|
|
+ return current_ev;
|
|
|
pos = next;
|
|
|
}
|
|
|
|
|
@@ -1275,10 +1346,14 @@ static void ieee80211_scan_add_ies(struct iw_request_info *info,
|
|
|
memset(&iwe, 0, sizeof(iwe));
|
|
|
iwe.cmd = IWEVGENIE;
|
|
|
iwe.u.data.length = end - pos;
|
|
|
- *current_ev = iwe_stream_add_point(info, *current_ev,
|
|
|
- end_buf, &iwe,
|
|
|
- (void *)pos);
|
|
|
+ current_ev = iwe_stream_add_point_check(info, current_ev,
|
|
|
+ end_buf, &iwe,
|
|
|
+ (void *)pos);
|
|
|
+ if (IS_ERR(current_ev))
|
|
|
+ return current_ev;
|
|
|
}
|
|
|
+
|
|
|
+ return current_ev;
|
|
|
}
|
|
|
|
|
|
static char *
|
|
@@ -1289,7 +1364,8 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,
|
|
|
const struct cfg80211_bss_ies *ies;
|
|
|
struct iw_event iwe;
|
|
|
const u8 *ie;
|
|
|
- u8 *buf, *cfg, *p;
|
|
|
+ u8 buf[50];
|
|
|
+ u8 *cfg, *p, *tmp;
|
|
|
int rem, i, sig;
|
|
|
bool ismesh = false;
|
|
|
|
|
@@ -1297,22 +1373,28 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,
|
|
|
iwe.cmd = SIOCGIWAP;
|
|
|
iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
|
|
|
memcpy(iwe.u.ap_addr.sa_data, bss->pub.bssid, ETH_ALEN);
|
|
|
- current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe,
|
|
|
- IW_EV_ADDR_LEN);
|
|
|
+ current_ev = iwe_stream_add_event_check(info, current_ev, end_buf, &iwe,
|
|
|
+ IW_EV_ADDR_LEN);
|
|
|
+ if (IS_ERR(current_ev))
|
|
|
+ return current_ev;
|
|
|
|
|
|
memset(&iwe, 0, sizeof(iwe));
|
|
|
iwe.cmd = SIOCGIWFREQ;
|
|
|
iwe.u.freq.m = ieee80211_frequency_to_channel(bss->pub.channel->center_freq);
|
|
|
iwe.u.freq.e = 0;
|
|
|
- current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe,
|
|
|
- IW_EV_FREQ_LEN);
|
|
|
+ current_ev = iwe_stream_add_event_check(info, current_ev, end_buf, &iwe,
|
|
|
+ IW_EV_FREQ_LEN);
|
|
|
+ if (IS_ERR(current_ev))
|
|
|
+ return current_ev;
|
|
|
|
|
|
memset(&iwe, 0, sizeof(iwe));
|
|
|
iwe.cmd = SIOCGIWFREQ;
|
|
|
iwe.u.freq.m = bss->pub.channel->center_freq;
|
|
|
iwe.u.freq.e = 6;
|
|
|
- current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe,
|
|
|
- IW_EV_FREQ_LEN);
|
|
|
+ current_ev = iwe_stream_add_event_check(info, current_ev, end_buf, &iwe,
|
|
|
+ IW_EV_FREQ_LEN);
|
|
|
+ if (IS_ERR(current_ev))
|
|
|
+ return current_ev;
|
|
|
|
|
|
if (wiphy->signal_type != CFG80211_SIGNAL_TYPE_NONE) {
|
|
|
memset(&iwe, 0, sizeof(iwe));
|
|
@@ -1341,8 +1423,11 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,
|
|
|
/* not reached */
|
|
|
break;
|
|
|
}
|
|
|
- current_ev = iwe_stream_add_event(info, current_ev, end_buf,
|
|
|
- &iwe, IW_EV_QUAL_LEN);
|
|
|
+ current_ev = iwe_stream_add_event_check(info, current_ev,
|
|
|
+ end_buf, &iwe,
|
|
|
+ IW_EV_QUAL_LEN);
|
|
|
+ if (IS_ERR(current_ev))
|
|
|
+ return current_ev;
|
|
|
}
|
|
|
|
|
|
memset(&iwe, 0, sizeof(iwe));
|
|
@@ -1352,8 +1437,10 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,
|
|
|
else
|
|
|
iwe.u.data.flags = IW_ENCODE_DISABLED;
|
|
|
iwe.u.data.length = 0;
|
|
|
- current_ev = iwe_stream_add_point(info, current_ev, end_buf,
|
|
|
- &iwe, "");
|
|
|
+ current_ev = iwe_stream_add_point_check(info, current_ev, end_buf,
|
|
|
+ &iwe, "");
|
|
|
+ if (IS_ERR(current_ev))
|
|
|
+ return current_ev;
|
|
|
|
|
|
rcu_read_lock();
|
|
|
ies = rcu_dereference(bss->pub.ies);
|
|
@@ -1371,66 +1458,91 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,
|
|
|
iwe.cmd = SIOCGIWESSID;
|
|
|
iwe.u.data.length = ie[1];
|
|
|
iwe.u.data.flags = 1;
|
|
|
- current_ev = iwe_stream_add_point(info, current_ev, end_buf,
|
|
|
- &iwe, (u8 *)ie + 2);
|
|
|
+ current_ev = iwe_stream_add_point_check(info,
|
|
|
+ current_ev,
|
|
|
+ end_buf, &iwe,
|
|
|
+ (u8 *)ie + 2);
|
|
|
+ if (IS_ERR(current_ev))
|
|
|
+ goto unlock;
|
|
|
break;
|
|
|
case WLAN_EID_MESH_ID:
|
|
|
memset(&iwe, 0, sizeof(iwe));
|
|
|
iwe.cmd = SIOCGIWESSID;
|
|
|
iwe.u.data.length = ie[1];
|
|
|
iwe.u.data.flags = 1;
|
|
|
- current_ev = iwe_stream_add_point(info, current_ev, end_buf,
|
|
|
- &iwe, (u8 *)ie + 2);
|
|
|
+ current_ev = iwe_stream_add_point_check(info,
|
|
|
+ current_ev,
|
|
|
+ end_buf, &iwe,
|
|
|
+ (u8 *)ie + 2);
|
|
|
+ if (IS_ERR(current_ev))
|
|
|
+ goto unlock;
|
|
|
break;
|
|
|
case WLAN_EID_MESH_CONFIG:
|
|
|
ismesh = true;
|
|
|
if (ie[1] != sizeof(struct ieee80211_meshconf_ie))
|
|
|
break;
|
|
|
- buf = kmalloc(50, GFP_ATOMIC);
|
|
|
- if (!buf)
|
|
|
- break;
|
|
|
cfg = (u8 *)ie + 2;
|
|
|
memset(&iwe, 0, sizeof(iwe));
|
|
|
iwe.cmd = IWEVCUSTOM;
|
|
|
sprintf(buf, "Mesh Network Path Selection Protocol ID: "
|
|
|
"0x%02X", cfg[0]);
|
|
|
iwe.u.data.length = strlen(buf);
|
|
|
- current_ev = iwe_stream_add_point(info, current_ev,
|
|
|
- end_buf,
|
|
|
- &iwe, buf);
|
|
|
+ current_ev = iwe_stream_add_point_check(info,
|
|
|
+ current_ev,
|
|
|
+ end_buf,
|
|
|
+ &iwe, buf);
|
|
|
+ if (IS_ERR(current_ev))
|
|
|
+ goto unlock;
|
|
|
sprintf(buf, "Path Selection Metric ID: 0x%02X",
|
|
|
cfg[1]);
|
|
|
iwe.u.data.length = strlen(buf);
|
|
|
- current_ev = iwe_stream_add_point(info, current_ev,
|
|
|
- end_buf,
|
|
|
- &iwe, buf);
|
|
|
+ current_ev = iwe_stream_add_point_check(info,
|
|
|
+ current_ev,
|
|
|
+ end_buf,
|
|
|
+ &iwe, buf);
|
|
|
+ if (IS_ERR(current_ev))
|
|
|
+ goto unlock;
|
|
|
sprintf(buf, "Congestion Control Mode ID: 0x%02X",
|
|
|
cfg[2]);
|
|
|
iwe.u.data.length = strlen(buf);
|
|
|
- current_ev = iwe_stream_add_point(info, current_ev,
|
|
|
- end_buf,
|
|
|
- &iwe, buf);
|
|
|
+ current_ev = iwe_stream_add_point_check(info,
|
|
|
+ current_ev,
|
|
|
+ end_buf,
|
|
|
+ &iwe, buf);
|
|
|
+ if (IS_ERR(current_ev))
|
|
|
+ goto unlock;
|
|
|
sprintf(buf, "Synchronization ID: 0x%02X", cfg[3]);
|
|
|
iwe.u.data.length = strlen(buf);
|
|
|
- current_ev = iwe_stream_add_point(info, current_ev,
|
|
|
- end_buf,
|
|
|
- &iwe, buf);
|
|
|
+ current_ev = iwe_stream_add_point_check(info,
|
|
|
+ current_ev,
|
|
|
+ end_buf,
|
|
|
+ &iwe, buf);
|
|
|
+ if (IS_ERR(current_ev))
|
|
|
+ goto unlock;
|
|
|
sprintf(buf, "Authentication ID: 0x%02X", cfg[4]);
|
|
|
iwe.u.data.length = strlen(buf);
|
|
|
- current_ev = iwe_stream_add_point(info, current_ev,
|
|
|
- end_buf,
|
|
|
- &iwe, buf);
|
|
|
+ current_ev = iwe_stream_add_point_check(info,
|
|
|
+ current_ev,
|
|
|
+ end_buf,
|
|
|
+ &iwe, buf);
|
|
|
+ if (IS_ERR(current_ev))
|
|
|
+ goto unlock;
|
|
|
sprintf(buf, "Formation Info: 0x%02X", cfg[5]);
|
|
|
iwe.u.data.length = strlen(buf);
|
|
|
- current_ev = iwe_stream_add_point(info, current_ev,
|
|
|
- end_buf,
|
|
|
- &iwe, buf);
|
|
|
+ current_ev = iwe_stream_add_point_check(info,
|
|
|
+ current_ev,
|
|
|
+ end_buf,
|
|
|
+ &iwe, buf);
|
|
|
+ if (IS_ERR(current_ev))
|
|
|
+ goto unlock;
|
|
|
sprintf(buf, "Capabilities: 0x%02X", cfg[6]);
|
|
|
iwe.u.data.length = strlen(buf);
|
|
|
- current_ev = iwe_stream_add_point(info, current_ev,
|
|
|
- end_buf,
|
|
|
- &iwe, buf);
|
|
|
- kfree(buf);
|
|
|
+ current_ev = iwe_stream_add_point_check(info,
|
|
|
+ current_ev,
|
|
|
+ end_buf,
|
|
|
+ &iwe, buf);
|
|
|
+ if (IS_ERR(current_ev))
|
|
|
+ goto unlock;
|
|
|
break;
|
|
|
case WLAN_EID_SUPP_RATES:
|
|
|
case WLAN_EID_EXT_SUPP_RATES:
|
|
@@ -1445,8 +1557,14 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,
|
|
|
for (i = 0; i < ie[1]; i++) {
|
|
|
iwe.u.bitrate.value =
|
|
|
((ie[i + 2] & 0x7f) * 500000);
|
|
|
+ tmp = p;
|
|
|
p = iwe_stream_add_value(info, current_ev, p,
|
|
|
- end_buf, &iwe, IW_EV_PARAM_LEN);
|
|
|
+ end_buf, &iwe,
|
|
|
+ IW_EV_PARAM_LEN);
|
|
|
+ if (p == tmp) {
|
|
|
+ current_ev = ERR_PTR(-E2BIG);
|
|
|
+ goto unlock;
|
|
|
+ }
|
|
|
}
|
|
|
current_ev = p;
|
|
|
break;
|
|
@@ -1465,31 +1583,35 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,
|
|
|
iwe.u.mode = IW_MODE_MASTER;
|
|
|
else
|
|
|
iwe.u.mode = IW_MODE_ADHOC;
|
|
|
- current_ev = iwe_stream_add_event(info, current_ev, end_buf,
|
|
|
- &iwe, IW_EV_UINT_LEN);
|
|
|
- }
|
|
|
-
|
|
|
- buf = kmalloc(31, GFP_ATOMIC);
|
|
|
- if (buf) {
|
|
|
- memset(&iwe, 0, sizeof(iwe));
|
|
|
- iwe.cmd = IWEVCUSTOM;
|
|
|
- sprintf(buf, "tsf=%016llx", (unsigned long long)(ies->tsf));
|
|
|
- iwe.u.data.length = strlen(buf);
|
|
|
- current_ev = iwe_stream_add_point(info, current_ev, end_buf,
|
|
|
- &iwe, buf);
|
|
|
- memset(&iwe, 0, sizeof(iwe));
|
|
|
- iwe.cmd = IWEVCUSTOM;
|
|
|
- sprintf(buf, " Last beacon: %ums ago",
|
|
|
- elapsed_jiffies_msecs(bss->ts));
|
|
|
- iwe.u.data.length = strlen(buf);
|
|
|
- current_ev = iwe_stream_add_point(info, current_ev,
|
|
|
- end_buf, &iwe, buf);
|
|
|
- kfree(buf);
|
|
|
+ current_ev = iwe_stream_add_event_check(info, current_ev,
|
|
|
+ end_buf, &iwe,
|
|
|
+ IW_EV_UINT_LEN);
|
|
|
+ if (IS_ERR(current_ev))
|
|
|
+ goto unlock;
|
|
|
}
|
|
|
|
|
|
- ieee80211_scan_add_ies(info, ies, ¤t_ev, end_buf);
|
|
|
+ memset(&iwe, 0, sizeof(iwe));
|
|
|
+ iwe.cmd = IWEVCUSTOM;
|
|
|
+ sprintf(buf, "tsf=%016llx", (unsigned long long)(ies->tsf));
|
|
|
+ iwe.u.data.length = strlen(buf);
|
|
|
+ current_ev = iwe_stream_add_point_check(info, current_ev, end_buf,
|
|
|
+ &iwe, buf);
|
|
|
+ if (IS_ERR(current_ev))
|
|
|
+ goto unlock;
|
|
|
+ memset(&iwe, 0, sizeof(iwe));
|
|
|
+ iwe.cmd = IWEVCUSTOM;
|
|
|
+ sprintf(buf, " Last beacon: %ums ago",
|
|
|
+ elapsed_jiffies_msecs(bss->ts));
|
|
|
+ iwe.u.data.length = strlen(buf);
|
|
|
+ current_ev = iwe_stream_add_point_check(info, current_ev,
|
|
|
+ end_buf, &iwe, buf);
|
|
|
+ if (IS_ERR(current_ev))
|
|
|
+ goto unlock;
|
|
|
+
|
|
|
+ current_ev = ieee80211_scan_add_ies(info, ies, current_ev, end_buf);
|
|
|
+
|
|
|
+ unlock:
|
|
|
rcu_read_unlock();
|
|
|
-
|
|
|
return current_ev;
|
|
|
}
|
|
|
|
|
@@ -1501,19 +1623,27 @@ static int ieee80211_scan_results(struct cfg80211_registered_device *rdev,
|
|
|
char *current_ev = buf;
|
|
|
char *end_buf = buf + len;
|
|
|
struct cfg80211_internal_bss *bss;
|
|
|
+ int err = 0;
|
|
|
|
|
|
spin_lock_bh(&rdev->bss_lock);
|
|
|
cfg80211_bss_expire(rdev);
|
|
|
|
|
|
list_for_each_entry(bss, &rdev->bss_list, list) {
|
|
|
if (buf + len - current_ev <= IW_EV_ADDR_LEN) {
|
|
|
- spin_unlock_bh(&rdev->bss_lock);
|
|
|
- return -E2BIG;
|
|
|
+ err = -E2BIG;
|
|
|
+ break;
|
|
|
}
|
|
|
current_ev = ieee80211_bss(&rdev->wiphy, info, bss,
|
|
|
current_ev, end_buf);
|
|
|
+ if (IS_ERR(current_ev)) {
|
|
|
+ err = PTR_ERR(current_ev);
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
spin_unlock_bh(&rdev->bss_lock);
|
|
|
+
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
return current_ev - buf;
|
|
|
}
|
|
|
|
|
@@ -1545,5 +1675,5 @@ int cfg80211_wext_giwscan(struct net_device *dev,
|
|
|
|
|
|
return res;
|
|
|
}
|
|
|
-EXPORT_SYMBOL_GPL(cfg80211_wext_giwscan);
|
|
|
+EXPORT_WEXT_HANDLER(cfg80211_wext_giwscan);
|
|
|
#endif
|