From nobody@FreeBSD.org  Sat Dec  1 08:40:20 2007
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 5ACC816A421
	for <freebsd-gnats-submit@FreeBSD.org>; Sat,  1 Dec 2007 08:40:20 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21])
	by mx1.freebsd.org (Postfix) with ESMTP id 53B8B13C447
	for <freebsd-gnats-submit@FreeBSD.org>; Sat,  1 Dec 2007 08:40:20 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.14.2/8.14.2) with ESMTP id lB18e6F0063490
	for <freebsd-gnats-submit@FreeBSD.org>; Sat, 1 Dec 2007 08:40:06 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.2/8.14.1/Submit) id lB18e6nk063489;
	Sat, 1 Dec 2007 08:40:06 GMT
	(envelope-from nobody)
Message-Id: <200712010840.lB18e6nk063489@www.freebsd.org>
Date: Sat, 1 Dec 2007 08:40:06 GMT
From: Weongyo Jeong <weongyo.jeong@gmail.com>
To: freebsd-gnats-submit@FreeBSD.org
Subject: [PATCH] if_ndis - fix a scanning problem of Marvell 88W8335 chipset.
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         118370
>Category:       kern
>Synopsis:       [ndis] [patch] if_ndis - fix a scanning problem of Marvell 88W8335 chipset.
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    thompsa
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sat Dec 01 08:50:00 UTC 2007
>Closed-Date:    Fri Mar 15 23:34:35 UTC 2013
>Last-Modified:  Fri Mar 15 23:34:35 UTC 2013
>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:
Responsible-Changed-From-To: freebsd-bugs->thompsa 
Responsible-Changed-By: thompsa 
Responsible-Changed-When: Sat Dec 1 10:45:57 UTC 2007 
Responsible-Changed-Why:  
I'll take care of this one. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=118370 

From: Weongyo Jeong <weongyo.jeong@gmail.com>
To: bug-followup@FreeBSD.org
Cc: Andrew Thompson <thompsa@freebsd.org>
Subject: Re: kern/118370: [if_ndis] [patch] if_ndis - fix a scanning problem of Marvell 88W8335 chipset.
Date: Fri, 7 Dec 2007 14:06:21 +0900

 This patch also is known as that fixes BCM4328 Wifi card's scanning
 problem on MacBook.  In addition, it worked after applying this patch.
 
 Please refer to the following link:
 	http://www.nabble.com/ndis(4):-BCM4328-driver-from-Apple---dies-in-pe_translate_addr-t4936133.html
 
 Regards,
 Weongyo Jeong

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/118370: commit references a PR
Date: Fri,  7 Dec 2007 10:37:35 +0000 (UTC)

 thompsa     2007-12-07 10:37:26 UTC
 
   FreeBSD src repository
 
   Modified files:
     sys/dev/if_ndis      if_ndis.c 
   Log:
   Preallocate some space to return the scan results, some drivers do not properly
   pass back the desired buffer length. This fixes scanning with the Marvell
   88W8335 and BCM4328 wireless cards.
   
   PR:             kern/118370
   Submitted by:   Weongyo Jeong
   Tested by:      Ed Schouten
   
   Revision  Changes    Path
   1.129     +25 -9     src/sys/dev/if_ndis/if_ndis.c
 _______________________________________________
 cvs-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/cvs-all
 To unsubscribe, send any mail to "cvs-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: open->patched 
State-Changed-By: thompsa 
State-Changed-When: Fri Dec 7 10:41:20 UTC 2007 
State-Changed-Why:  
Commited to HEAD, thanks for the PR and keep the patches coming! 

http://www.freebsd.org/cgi/query-pr.cgi?pr=118370 
State-Changed-From-To: patched->closed 
State-Changed-By: eadler 
State-Changed-When: Fri Mar 15 23:34:35 UTC 2013 
State-Changed-Why:  
MFCed/fixed by now or it will never be MFCed 

http://www.freebsd.org/cgi/query-pr.cgi?pr=118370 
>Unformatted:
