Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 225496
b: refs/heads/master
c: bfe3850
h: refs/heads/master
v: v3
  • Loading branch information
Jussi Kivilinna authored and John W. Linville committed Dec 22, 2010
1 parent e946f6d commit 2d72d71
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 19 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: ab72efdf107e5b0e0a05efb8f24cc6c598ae31ea
refs/heads/master: bfe3850b0cfca6ba64395e2705d9a51cd044f374
80 changes: 62 additions & 18 deletions trunk/drivers/net/wireless/rndis_wlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -1967,8 +1967,8 @@ static struct cfg80211_bss *rndis_bss_info_update(struct usbnet *usbdev,
int ie_len, bssid_len;
u8 *ie;

netdev_dbg(usbdev->net, " found bssid: '%.32s' [%pM]\n",
bssid->ssid.essid, bssid->mac);
netdev_dbg(usbdev->net, " found bssid: '%.32s' [%pM], len: %d\n",
bssid->ssid.essid, bssid->mac, le32_to_cpu(bssid->length));

/* parse bssid structure */
bssid_len = le32_to_cpu(bssid->length);
Expand Down Expand Up @@ -2002,54 +2002,98 @@ static struct cfg80211_bss *rndis_bss_info_update(struct usbnet *usbdev,
GFP_KERNEL);
}

static struct ndis_80211_bssid_ex *next_bssid_list_item(
struct ndis_80211_bssid_ex *bssid,
int *bssid_len, void *buf, int len)
{
void *buf_end, *bssid_end;

buf_end = (char *)buf + len;
bssid_end = (char *)bssid + *bssid_len;

if ((int)(buf_end - bssid_end) < sizeof(bssid->length)) {
*bssid_len = 0;
return NULL;
} else {
bssid = (void *)((char *)bssid + *bssid_len);
*bssid_len = le32_to_cpu(bssid->length);
return bssid;
}
}

static bool check_bssid_list_item(struct ndis_80211_bssid_ex *bssid,
int bssid_len, void *buf, int len)
{
void *buf_end, *bssid_end;

if (!bssid || bssid_len <= 0 || bssid_len > len)
return false;

buf_end = (char *)buf + len;
bssid_end = (char *)bssid + bssid_len;

return (int)(buf_end - bssid_end) >= 0 && (int)(bssid_end - buf) >= 0;
}

static int rndis_check_bssid_list(struct usbnet *usbdev, u8 *match_bssid,
bool *matched)
{
void *buf = NULL;
struct ndis_80211_bssid_list_ex *bssid_list;
struct ndis_80211_bssid_ex *bssid;
int ret = -EINVAL, len, count, bssid_len;
bool resized = false;
int ret = -EINVAL, len, count, bssid_len, real_count, new_len;

netdev_dbg(usbdev->net, "check_bssid_list\n");
netdev_dbg(usbdev->net, "%s()\n", __func__);

len = CONTROL_BUFFER_SIZE;
resize_buf:
buf = kmalloc(len, GFP_KERNEL);
buf = kzalloc(len, GFP_KERNEL);
if (!buf) {
ret = -ENOMEM;
goto out;
}

ret = rndis_query_oid(usbdev, OID_802_11_BSSID_LIST, buf, &len);
if (ret != 0)
/* BSSID-list might have got bigger last time we checked, keep
* resizing until it won't get any bigger.
*/
new_len = len;
ret = rndis_query_oid(usbdev, OID_802_11_BSSID_LIST, buf, &new_len);
if (ret != 0 || new_len < sizeof(struct ndis_80211_bssid_list_ex))
goto out;

if (!resized && len > CONTROL_BUFFER_SIZE) {
resized = true;
if (new_len > len) {
len = new_len;
kfree(buf);
goto resize_buf;
}

len = new_len;

bssid_list = buf;
bssid = bssid_list->bssid;
bssid_len = le32_to_cpu(bssid->length);
count = le32_to_cpu(bssid_list->num_items);
netdev_dbg(usbdev->net, "check_bssid_list: %d BSSIDs found (buflen: %d)\n",
count, len);
real_count = 0;
netdev_dbg(usbdev->net, "%s(): buflen: %d\n", __func__, len);

bssid_len = 0;
bssid = next_bssid_list_item(bssid_list->bssid, &bssid_len, buf, len);

while (count && ((void *)bssid + bssid_len) <= (buf + len)) {
/* Device returns incorrect 'num_items'. Workaround by ignoring the
* received 'num_items' and walking through full bssid buffer instead.
*/
while (check_bssid_list_item(bssid, bssid_len, buf, len)) {
if (rndis_bss_info_update(usbdev, bssid) && match_bssid &&
matched) {
if (compare_ether_addr(bssid->mac, match_bssid))
*matched = true;
}

bssid = (void *)bssid + bssid_len;
bssid_len = le32_to_cpu(bssid->length);
count--;
real_count++;
bssid = next_bssid_list_item(bssid, &bssid_len, buf, len);
}

netdev_dbg(usbdev->net, "%s(): num_items from device: %d, really found:"
" %d\n", __func__, count, real_count);

out:
kfree(buf);
return ret;
Expand Down

0 comments on commit 2d72d71

Please sign in to comment.