[PATCH NM 0.6.4] use iwlib scan parsing, fix 32<->64 bit issues



	Hi,

	Johannes Berg has discovered some issues with scanning when
using 32 bit userspace on 64 bit kernels. I've implemented a fix for
this in iwlib, and I've just have report that this fix is working.

	The same issue is also present in NetworkManager. Rather than
bloat further the code of NetworkManager, I've made a patch to make it
use the iwlib scanning routines. This should both fix this issue, and
simplify the code and the maintainance of NetworkManager.
	Unfortunately, due to some distro compatibility issues, I had
to work with version 0.6.4. The patch was tested with iwlib v29,
however iwlib v28 has exactly the same API (but without the fix).

	Have fun...

	Jean

-----------------------------------------------------------

diff -u -p NetworkManager-0.6.4/src/nm-device-802-11-wireless.j1.c NetworkManager-0.6.4/src/nm-device-802-11-wireless.c
--- NetworkManager-0.6.4/src/nm-device-802-11-wireless.j1.c	2007-03-22 15:28:11.000000000 -0700
+++ NetworkManager-0.6.4/src/nm-device-802-11-wireless.c	2007-03-22 16:04:54.000000000 -0700
@@ -3229,48 +3229,32 @@ process_scan_results (NMDevice80211Wirel
                       const guint8 *res_buf,
                       guint32 res_buf_len)
 {
-	char *pos, *end, *custom, *genie, *gpos, *gend;
+	char *genie, *gpos, *gend, *custom;
 	NMAccessPoint *ap = NULL;
 	size_t clen;
-	struct iw_param iwp;
 	int maxrate;
 	struct iw_event iwe_buf, *iwe = &iwe_buf;
+	struct stream_descr	stream;
+	struct wireless_scan *	wscan = NULL;
+	int			ret;
 
 	g_return_val_if_fail (dev != NULL, FALSE);
 	g_return_val_if_fail (res_buf != NULL, FALSE);
 	g_return_val_if_fail (res_buf_len > 0, FALSE);
 
-	pos = (char *) res_buf;
-	end = (char *) res_buf + res_buf_len;
+	/* Init stream descriptor */
+	iw_init_event_stream(&stream, (char *) res_buf, res_buf_len);
 
-	while (pos + IW_EV_LCP_LEN <= end)
+	while (1)
 	{
 		int ssid_len;
 
-		/* Event data may be unaligned, so make a local, aligned copy
-		 * before processing. */
-		memcpy (&iwe_buf, pos, IW_EV_LCP_LEN);
-		if (iwe->len <= IW_EV_LCP_LEN)
+		/* Extract an event */
+		ret = iw_extract_event_stream(&stream, &iwe_buf, dev->priv->we_version);
+		if(ret <= 0)
 			break;
 
-		custom = pos + IW_EV_POINT_LEN;
-		if (dev->priv->we_version > 18 &&
-		    (iwe->cmd == SIOCGIWESSID ||
-		     iwe->cmd == SIOCGIWENCODE ||
-		     iwe->cmd == IWEVGENIE ||
-		     iwe->cmd == IWEVCUSTOM))
-		{
-			/* WE-19 removed the pointer from struct iw_point */
-			char *dpos = (char *) &iwe_buf.u.data.length;
-			int dlen = dpos - (char *) &iwe_buf;
-			memcpy (dpos, pos + IW_EV_LCP_LEN, sizeof (struct iw_event) - dlen);
-		}
-		else
-		{
-			memcpy (&iwe_buf, pos, sizeof (struct iw_event));
-			custom += IW_EV_POINT_OFF;
-		}
-
+		iwe = &iwe_buf;		/* Prevent gcc unstrict-aliasing */
 		switch (iwe->cmd)
 		{
 			case SIOCGIWAP:
@@ -3287,6 +3271,7 @@ process_scan_results (NMDevice80211Wirel
 				/* New AP with some defaults */
 				ap = nm_ap_new ();
 				nm_ap_set_address (ap, (const struct ether_addr *)(iwe->u.ap_addr.sa_data));
+				maxrate = 0;
 				break;
 			case SIOCGIWMODE:
 				switch (iwe->u.mode)
@@ -3304,13 +3289,13 @@ process_scan_results (NMDevice80211Wirel
 				break;
 			case SIOCGIWESSID:
 				ssid_len = iwe->u.essid.length;
-				if (custom + ssid_len > end)
+				if (!iwe->u.essid.pointer)
 					break;
 				if (iwe->u.essid.flags && (ssid_len > 0) && (ssid_len <= IW_ESSID_MAX_SIZE))
 				{
 					gboolean set = TRUE;
 					char *essid = g_malloc (IW_ESSID_MAX_SIZE + 1);
-					memcpy (essid, custom, ssid_len);
+					memcpy (essid, iwe->u.essid.pointer, ssid_len);
 					essid[ssid_len] = '\0';
 					if (!strlen(essid))
 						set = FALSE;
@@ -3340,25 +3325,17 @@ process_scan_results (NMDevice80211Wirel
 				}
 				break;
 			case SIOCGIWRATE:
-				clen = iwe->len;
-				if (custom + clen > end)
-					break;
-				maxrate = 0;
-				while (((ssize_t) clen) >= sizeof(struct iw_param))
+				if(iwe->u.bitrate.value > maxrate)
 				{
-					/* the payload may be unaligned, so we align it */
-					memcpy(&iwp, custom, sizeof (struct iw_param));
-					if (iwp.value > maxrate)
-						maxrate = iwp.value;
-					clen -= sizeof (struct iw_param);
-					custom += sizeof (struct iw_param);
+					maxrate = iwe->u.bitrate.value;
+					nm_ap_set_rate (ap, maxrate);
+					nm_warning ("get_scan_results(): SIOCGIWRATE new max %d.", maxrate);
 				}
-				nm_ap_set_rate (ap, maxrate);
 				break;
 			case IWEVGENIE:
-				gpos = genie = custom;
+				gpos = genie = iwe->u.data.pointer;
 				gend = genie + iwe->u.data.length;
-				if (gend > end)
+				if (!iwe->u.data.pointer)
 				{
 					nm_warning ("get_scan_results(): IWEVGENIE overflow.");
 					break;
@@ -3386,8 +3363,9 @@ process_scan_results (NMDevice80211Wirel
 				}
 				break;
 			case IWEVCUSTOM:
+				custom = iwe->u.data.pointer;
 				clen = iwe->u.data.length;
-				if (custom + clen > end)
+				if (!iwe->u.data.pointer)
 					break;
 				if (clen > 7 && ((strncmp (custom, "wpa_ie=", 7) == 0) || (strncmp (custom, "rsn_ie=", 7) == 0)))
 				{
@@ -3418,7 +3396,6 @@ process_scan_results (NMDevice80211Wirel
 				break;
 		}
 
-		pos += iwe->len;
 	}
 
 	if (ap)



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]