[PATCH] wext: handle mode switches correctly for mac80211

Dan Williams dcbw at redhat.com
Tue Jun 3 21:30:56 EDT 2008


Since mac80211 requires that the device be !IFF_UP to change the mode
(and I think the old prism54 fullmac driver does too), do that.  This
shouldn't harm fullmac devices since they can handle mode switches on
the fly and usually don't care about up/down that much.


diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c
index efa88a8..8c4bac2 100644
--- a/src/drivers/driver_wext.c
+++ b/src/drivers/driver_wext.c
@@ -2152,17 +2152,37 @@ int wpa_driver_wext_set_mode(void *priv, int mode)
 {
 	struct wpa_driver_wext_data *drv = priv;
 	struct iwreq iwr;
-	int ret = 0;
+	int ret = 0, bring_up = 0, flags;
+	int new_mode = mode ? IW_MODE_ADHOC : IW_MODE_INFRA;
 
 	os_memset(&iwr, 0, sizeof(iwr));
 	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
-	iwr.u.mode = mode ? IW_MODE_ADHOC : IW_MODE_INFRA;
 
+	/* mac80211 doesn't allow mode changes while the device is up, so if
+	 * the device isn't in the mode we're about to change to, take device
+	 * down, set the the mode, and bring it back up.
+	 */
+	if (ioctl(drv->ioctl_sock, SIOCGIWMODE, &iwr) == 0) {
+		if (iwr.u.mode != new_mode) {
+			if (wpa_driver_wext_get_ifflags(drv, &flags) == 0) {
+				(void) wpa_driver_wext_set_ifflags(drv,
+						flags & ~IFF_UP);
+				bring_up = 1;
+			}
+		}
+	}
+
+	iwr.u.mode = new_mode;
 	if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0) {
 		perror("ioctl[SIOCSIWMODE]");
 		ret = -1;
 	}
 
+	if (bring_up) {
+		if (wpa_driver_wext_get_ifflags(drv, &flags) == 0)
+			(void) wpa_driver_wext_set_ifflags(drv, flags | IFF_UP);
+	}
+
 	return ret;
 }
 



More information about the HostAP mailing list