Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 1 Dec 2007 08:40:06 GMT
From:      Weongyo Jeong <weongyo.jeong@gmail.com>
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   kern/118370: [PATCH] if_ndis - fix a scanning problem of Marvell 88W8335 chipset.
Message-ID:  <200712010840.lB18e6nk063489@www.freebsd.org>
Resent-Message-ID: <200712010850.lB18o18w029206@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>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:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200712010840.lB18e6nk063489>