kern/118370: [PATCH] if_ndis - fix a scanning problem of Marvell
88W8335 chipset.
Weongyo Jeong
weongyo.jeong at gmail.com
Sat Dec 1 00:50:01 PST 2007
>Number: 118370
>Category: kern
>Synopsis: [PATCH] if_ndis - fix a scanning problem of Marvell 88W8335 chipset.
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Sat Dec 01 08:50:00 UTC 2007
>Closed-Date:
>Last-Modified:
>Originator: Weongyo Jeong
>Release: FreeBSD-CURRENT
>Organization:
CDNetworks
>Environment:
>Description:
I have a Marvell 88W8335 chipset wireless NIC card and tested it with ndis(4). However, I was succeed to load drivers using ndisgen(8) but can't scan and associate with my APs.
After analyzing, I found a problem of handling OID_802_11_BSSID_LIST in if_ndis.c. The problem was that if we requests NDIS driver using querying OID_802_11_BSSID_LIST with no buffer space to get a necessary buffer size like below:
len = 4;
error = ndis_get_info(sc, OID_802_11_BSSID_LIST, NULL, &len);
The return value was always 4 so I patched that when we query OID_802_11_BSSID_LIST, firstly we allocated a small space to save structures then we request like ndiswrapper of linux did.
Now it works well in my case except some problems.
>How-To-Repeat:
>Fix:
Index: if_ndis.c
===================================================================
RCS file: /data/ndis/if_ndis/if_ndis.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 if_ndis.c
--- if_ndis.c 1 Dec 2007 06:23:58 -0000 1.1.1.1
+++ if_ndis.c 1 Dec 2007 07:34:01 -0000
@@ -2629,13 +2629,20 @@
return(ENOENT);
}
- len = 4;
- error = ndis_get_info(sc, OID_802_11_BSSID_LIST, NULL, &len);
- if (error != ENOSPC)
- len = 65536;
+ len = sizeof(uint32_t) + (sizeof(ndis_wlan_bssid_ex) * 16);
+ bl = malloc(len, M_TEMP, M_NOWAIT | M_ZERO);
+ if (bl == NULL)
+ return (ENOMEM);
- bl = malloc(len, M_TEMP, M_NOWAIT|M_ZERO);
error = ndis_get_info(sc, OID_802_11_BSSID_LIST, bl, &len);
+ if (error == ENOSPC) {
+ free(bl, M_TEMP);
+ bl = malloc(len, M_TEMP, M_NOWAIT | M_ZERO);
+ if (bl == NULL)
+ return (ENOMEM);
+
+ error = ndis_get_info(sc, OID_802_11_BSSID_LIST, bl, &len);
+ }
if (error) {
free(bl, M_TEMP);
device_printf(sc->ndis_dev, "bssid_list failed\n");
@@ -3066,16 +3073,28 @@
NULL, &len);
if (error == 0)
tsleep(&error, PPAUSE|PCATCH, "ssidscan", hz * 2);
- len = 0;
- error = ndis_get_info(sc, OID_802_11_BSSID_LIST, NULL, &len);
- if (error != ENOSPC)
- len = 65536;
- bl = malloc(len, M_DEVBUF, M_NOWAIT|M_ZERO);
+
+ len = sizeof(uint32_t) + (sizeof(ndis_wlan_bssid_ex) * 16);
+ bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (bl == NULL)
+ return (ENOMEM);
+
error = ndis_get_info(sc, OID_802_11_BSSID_LIST, bl, &len);
+ if (error == ENOSPC) {
+ free(bl, M_DEVBUF);
+ bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (bl == NULL)
+ return (ENOMEM);
+
+ error = ndis_get_info(sc, OID_802_11_BSSID_LIST, bl,
+ &len);
+ }
if (error) {
free(bl, M_DEVBUF);
+ device_printf(sc->ndis_dev, "bssid_list failed\n");
break;
}
+
maxaps = (2 * wreq.wi_len - sizeof(int)) / sizeof(*api);
maxaps = MIN(maxaps, bl->nblx_items);
wreq.wi_len = (maxaps * sizeof(*api) + sizeof(int)) / 2;
@@ -3561,13 +3580,22 @@
uint8_t rates[2+IEEE80211_RATE_MAXSIZE];
uint8_t *frm, *efrm;
- len = 0;
noise = -96;
- error = ndis_get_info(sc, OID_802_11_BSSID_LIST, NULL, &len);
- if (error != ENOSPC)
- len = 65536;
+
+ len = sizeof(uint32_t) + (sizeof(ndis_wlan_bssid_ex) * 16);
bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (bl == NULL)
+ return;
+
error = ndis_get_info(sc, OID_802_11_BSSID_LIST, bl, &len);
+ if (error == ENOSPC) {
+ free(bl, M_DEVBUF);
+ bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (bl == NULL)
+ return;
+
+ error = ndis_get_info(sc, OID_802_11_BSSID_LIST, bl, &len);
+ }
if (error) {
DPRINTF(("%s: failed to read\n", __func__));
free(bl, M_DEVBUF);
Patch attached with submission follows:
Index: if_ndis.c
===================================================================
RCS file: /data/ndis/if_ndis/if_ndis.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 if_ndis.c
--- if_ndis.c 1 Dec 2007 06:23:58 -0000 1.1.1.1
+++ if_ndis.c 1 Dec 2007 07:34:01 -0000
@@ -2629,13 +2629,20 @@
return(ENOENT);
}
- len = 4;
- error = ndis_get_info(sc, OID_802_11_BSSID_LIST, NULL, &len);
- if (error != ENOSPC)
- len = 65536;
+ len = sizeof(uint32_t) + (sizeof(ndis_wlan_bssid_ex) * 16);
+ bl = malloc(len, M_TEMP, M_NOWAIT | M_ZERO);
+ if (bl == NULL)
+ return (ENOMEM);
- bl = malloc(len, M_TEMP, M_NOWAIT|M_ZERO);
error = ndis_get_info(sc, OID_802_11_BSSID_LIST, bl, &len);
+ if (error == ENOSPC) {
+ free(bl, M_TEMP);
+ bl = malloc(len, M_TEMP, M_NOWAIT | M_ZERO);
+ if (bl == NULL)
+ return (ENOMEM);
+
+ error = ndis_get_info(sc, OID_802_11_BSSID_LIST, bl, &len);
+ }
if (error) {
free(bl, M_TEMP);
device_printf(sc->ndis_dev, "bssid_list failed\n");
@@ -3066,16 +3073,28 @@
NULL, &len);
if (error == 0)
tsleep(&error, PPAUSE|PCATCH, "ssidscan", hz * 2);
- len = 0;
- error = ndis_get_info(sc, OID_802_11_BSSID_LIST, NULL, &len);
- if (error != ENOSPC)
- len = 65536;
- bl = malloc(len, M_DEVBUF, M_NOWAIT|M_ZERO);
+
+ len = sizeof(uint32_t) + (sizeof(ndis_wlan_bssid_ex) * 16);
+ bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (bl == NULL)
+ return (ENOMEM);
+
error = ndis_get_info(sc, OID_802_11_BSSID_LIST, bl, &len);
+ if (error == ENOSPC) {
+ free(bl, M_DEVBUF);
+ bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (bl == NULL)
+ return (ENOMEM);
+
+ error = ndis_get_info(sc, OID_802_11_BSSID_LIST, bl,
+ &len);
+ }
if (error) {
free(bl, M_DEVBUF);
+ device_printf(sc->ndis_dev, "bssid_list failed\n");
break;
}
+
maxaps = (2 * wreq.wi_len - sizeof(int)) / sizeof(*api);
maxaps = MIN(maxaps, bl->nblx_items);
wreq.wi_len = (maxaps * sizeof(*api) + sizeof(int)) / 2;
@@ -3561,13 +3580,22 @@
uint8_t rates[2+IEEE80211_RATE_MAXSIZE];
uint8_t *frm, *efrm;
- len = 0;
noise = -96;
- error = ndis_get_info(sc, OID_802_11_BSSID_LIST, NULL, &len);
- if (error != ENOSPC)
- len = 65536;
+
+ len = sizeof(uint32_t) + (sizeof(ndis_wlan_bssid_ex) * 16);
bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (bl == NULL)
+ return;
+
error = ndis_get_info(sc, OID_802_11_BSSID_LIST, bl, &len);
+ if (error == ENOSPC) {
+ free(bl, M_DEVBUF);
+ bl = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (bl == NULL)
+ return;
+
+ error = ndis_get_info(sc, OID_802_11_BSSID_LIST, bl, &len);
+ }
if (error) {
DPRINTF(("%s: failed to read\n", __func__));
free(bl, M_DEVBUF);
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list