[RFC 2/2] driver_nl80211: use nl80211 p2p interface types

Eliad Peller eliad at wizery.com
Mon Jan 17 04:29:08 EST 2011


Create NL80211_IFTYPE_P2P_CLIENT/GO interfaces for p2p, rather
than NL80211_IFTYPE_STATION/AP.

After doing it, we need to start considering these interfaces
as well (for example, when doing scan while being ap).
For that, add the is_sta_interface() and is_ap_interface()
functions that take into account the p2p equivalents of
NL80211_IFTYPE_STATION and NL80211_IFTYPE_AP.

When doing "ap_scan_as_station" we now need to save the
actual ap interface type (normal/p2p) in order to restore
it properly. for that, change ap_scan_as_station type from
int to nl80211_iftype, and set it NL80211_IFTYPE_UNSPECIFED
when not used.

Signed-off-by: Eliad Peller <eliad at wizery.com>
---
 src/drivers/driver_nl80211.c |  107 ++++++++++++++++++++++-------------------
 1 files changed, 57 insertions(+), 50 deletions(-)

diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index e8ec38e..b8d2249 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -150,7 +150,7 @@ struct wpa_driver_nl80211_data {
 	u8 ssid[32];
 	size_t ssid_len;
 	int nlmode;
-	int ap_scan_as_station;
+	enum nl80211_iftype ap_scan_as_station;
 	unsigned int assoc_freq;
 
 	int monitor_sock;
@@ -186,7 +186,8 @@ struct wpa_driver_nl80211_data {
 
 static void wpa_driver_nl80211_scan_timeout(void *eloop_ctx,
 					    void *timeout_ctx);
-static int wpa_driver_nl80211_set_mode(void *priv, int mode);
+static int wpa_driver_nl80211_set_mode(void *priv,
+				       enum nl80211_iftype nlmode);
 static int
 wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv);
 static int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
@@ -1111,6 +1112,17 @@ static int get_link_signal(struct nl_msg *msg, void *arg)
 	return NL_SKIP;
 }
 
+static int is_ap_interface(enum nl80211_iftype nlmode)
+{
+	return (nlmode == NL80211_IFTYPE_AP ||
+		nlmode == NL80211_IFTYPE_P2P_GO);
+}
+
+static int is_sta_interface(enum nl80211_iftype nlmode)
+{
+	return (nlmode == NL80211_IFTYPE_STATION ||
+		nlmode == NL80211_IFTYPE_P2P_CLIENT);
+}
 
 static int nl80211_get_link_signal(struct wpa_driver_nl80211_data *drv,
 				   struct signal_change *sig)
@@ -1309,12 +1321,12 @@ static int process_event(struct nl_msg *msg, void *arg)
 		}
 	}
 
-	if (drv->ap_scan_as_station &&
+	if ((drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED) &&
 	    (gnlh->cmd == NL80211_CMD_NEW_SCAN_RESULTS ||
 	     gnlh->cmd == NL80211_CMD_SCAN_ABORTED)) {
 		wpa_driver_nl80211_set_mode(&drv->first_bss,
-					    IEEE80211_MODE_AP);
-		drv->ap_scan_as_station = 0;
+					    drv->ap_scan_as_station);
+		drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
 	}
 
 	switch (gnlh->cmd) {
@@ -1804,6 +1816,7 @@ static void * wpa_driver_nl80211_init(void *ctx, const char *ifname,
 	drv->monitor_ifidx = -1;
 	drv->monitor_sock = -1;
 	drv->ioctl_sock = -1;
+	drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
 
 	if (wpa_driver_nl80211_init_nl(drv)) {
 		os_free(drv);
@@ -1968,7 +1981,7 @@ wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv)
 	drv->first_bss.ifindex = drv->ifindex;
 
 #ifndef HOSTAPD
-	if (wpa_driver_nl80211_set_mode(bss, IEEE80211_MODE_INFRA) < 0) {
+	if (wpa_driver_nl80211_set_mode(bss, NL80211_IFTYPE_STATION) < 0) {
 		wpa_printf(MSG_DEBUG, "nl80211: Could not configure driver to "
 			   "use managed mode");
 	}
@@ -2064,7 +2077,7 @@ static void wpa_driver_nl80211_deinit(void *priv)
 
 	nl80211_remove_monitor_interface(drv);
 
-	if (drv->nlmode == NL80211_IFTYPE_AP)
+	if (is_ap_interface(drv->nlmode))
 		wpa_driver_nl80211_del_beacon(drv);
 
 #ifdef HOSTAPD
@@ -2095,7 +2108,7 @@ static void wpa_driver_nl80211_deinit(void *priv)
 	eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
 
 	(void) linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 0);
-	wpa_driver_nl80211_set_mode(bss, IEEE80211_MODE_INFRA);
+	wpa_driver_nl80211_set_mode(bss, NL80211_IFTYPE_STATION);
 
 	if (drv->ioctl_sock >= 0)
 		close(drv->ioctl_sock);
@@ -2128,10 +2141,10 @@ static void wpa_driver_nl80211_deinit(void *priv)
 static void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx)
 {
 	struct wpa_driver_nl80211_data *drv = eloop_ctx;
-	if (drv->ap_scan_as_station) {
+	if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED) {
 		wpa_driver_nl80211_set_mode(&drv->first_bss,
-					    IEEE80211_MODE_AP);
-		drv->ap_scan_as_station = 0;
+					    drv->ap_scan_as_station);
+		drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
 	}
 	wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
 	wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
@@ -2205,23 +2218,23 @@ static int wpa_driver_nl80211_scan(void *priv,
 		wpa_printf(MSG_DEBUG, "nl80211: Scan trigger failed: ret=%d "
 			   "(%s)", ret, strerror(-ret));
 #ifdef HOSTAPD
-		if (drv->nlmode == NL80211_IFTYPE_AP) {
+		if (is_ap_interface(drv->nlmode)) {
 			/*
 			 * mac80211 does not allow scan requests in AP mode, so
 			 * try to do this in station mode.
 			 */
 			if (wpa_driver_nl80211_set_mode(bss,
-							IEEE80211_MODE_INFRA))
+							NL80211_IFTYPE_STATION))
 				goto nla_put_failure;
 
 			if (wpa_driver_nl80211_scan(drv, params)) {
 				wpa_driver_nl80211_set_mode(bss,
-							    IEEE80211_MODE_AP);
+							    drv->nlmode);
 				goto nla_put_failure;
 			}
 
 			/* Restore AP mode when processing scan results */
-			drv->ap_scan_as_station = 1;
+			drv->ap_scan_as_station = drv->nlmode;
 			ret = 0;
 		} else
 			goto nla_put_failure;
@@ -2447,7 +2460,7 @@ static void wpa_driver_nl80211_check_bss_status(
 				   "indicates BSS status with " MACSTR
 				   " as authenticated",
 				   MAC2STR(r->bssid));
-			if (drv->nlmode == NL80211_IFTYPE_STATION &&
+			if (is_sta_interface(drv->nlmode) &&
 			    os_memcmp(r->bssid, drv->bssid, ETH_ALEN) != 0 &&
 			    os_memcmp(r->bssid, drv->auth_bssid, ETH_ALEN) !=
 			    0) {
@@ -2465,13 +2478,13 @@ static void wpa_driver_nl80211_check_bss_status(
 				   "indicate BSS status with " MACSTR
 				   " as associated",
 				   MAC2STR(r->bssid));
-			if (drv->nlmode == NL80211_IFTYPE_STATION &&
+			if (is_sta_interface(drv->nlmode) &&
 			    !drv->associated) {
 				wpa_printf(MSG_DEBUG, "nl80211: Local state "
 					   "(not associated) does not match "
 					   "with BSS state");
 				clear_state_mismatch(drv, r->bssid);
-			} else if (drv->nlmode == NL80211_IFTYPE_STATION &&
+			} else if (is_sta_interface(drv->nlmode) &&
 				   os_memcmp(drv->bssid, r->bssid, ETH_ALEN) !=
 				   0) {
 				wpa_printf(MSG_DEBUG, "nl80211: Local state "
@@ -2679,7 +2692,7 @@ static int wpa_driver_nl80211_set_key(const char *ifname, void *priv,
 	 */
 	if (ret || !set_tx || alg == WPA_ALG_NONE)
 		return ret;
-	if (drv->nlmode == NL80211_IFTYPE_AP && addr &&
+	if (is_ap_interface(drv->nlmode) && addr &&
 	    !is_broadcast_ether_addr(addr))
 		return ret;
 
@@ -2935,8 +2948,8 @@ static int wpa_driver_nl80211_authenticate(
 	drv->associated = 0;
 	os_memset(drv->auth_bssid, 0, ETH_ALEN);
 	/* FIX: IBSS mode */
-	if (drv->nlmode != NL80211_IFTYPE_STATION)
-		if (wpa_driver_nl80211_set_mode(priv, IEEE80211_MODE_INFRA) < 0)
+	if (!is_sta_interface(drv->nlmode))
+		if (wpa_driver_nl80211_set_mode(priv, NL80211_IFTYPE_STATION) < 0)
 			return -1;
 
 retry:
@@ -3524,7 +3537,7 @@ static int wpa_driver_nl80211_send_mlme(void *priv, const u8 *data,
 	mgmt = (struct ieee80211_mgmt *) data;
 	fc = le_to_host16(mgmt->frame_control);
 
-	if (drv->nlmode == NL80211_IFTYPE_STATION &&
+	if (is_sta_interface(drv->nlmode) &&
 	    WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
 	    WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_RESP) {
 		/*
@@ -4341,7 +4354,9 @@ static int wpa_driver_nl80211_ap(struct wpa_driver_nl80211_data *drv,
 	if (params->p2p)
 		wpa_printf(MSG_DEBUG, "nl80211: Setup AP operations for P2P "
 			   "group (GO)");
-	if (wpa_driver_nl80211_set_mode(&drv->first_bss, params->mode) ||
+	enum nl80211_iftype nlmode = params->p2p ?
+		NL80211_IFTYPE_P2P_GO : NL80211_IFTYPE_AP;
+	if (wpa_driver_nl80211_set_mode(&drv->first_bss, nlmode) ||
 	    wpa_driver_nl80211_set_freq(drv, params->freq, 0, 0)) {
 		nl80211_remove_monitor_interface(drv);
 		return -1;
@@ -4392,7 +4407,8 @@ static int wpa_driver_nl80211_ibss(struct wpa_driver_nl80211_data *drv,
 
 	wpa_printf(MSG_DEBUG, "nl80211: Join IBSS (ifindex=%d)", drv->ifindex);
 
-	if (wpa_driver_nl80211_set_mode(&drv->first_bss, params->mode)) {
+	if (wpa_driver_nl80211_set_mode(&drv->first_bss,
+					NL80211_IFTYPE_ADHOC)) {
 		wpa_printf(MSG_INFO, "nl80211: Failed to set interface into "
 			   "IBSS mode");
 		return -1;
@@ -4618,7 +4634,10 @@ static int wpa_driver_nl80211_associate(
 		return wpa_driver_nl80211_ibss(drv, params);
 
 	if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) {
-		if (wpa_driver_nl80211_set_mode(priv, params->mode) < 0)
+		enum nl80211_iftype nlmode = params->p2p ?
+			NL80211_IFTYPE_P2P_CLIENT : NL80211_IFTYPE_STATION;
+
+		if (wpa_driver_nl80211_set_mode(priv, nlmode) < 0)
 			return -1;
 		return wpa_driver_nl80211_connect(drv, params);
 	}
@@ -4765,28 +4784,14 @@ nla_put_failure:
 }
 
 
-static int wpa_driver_nl80211_set_mode(void *priv, int mode)
+static int wpa_driver_nl80211_set_mode(void *priv,
+				       enum nl80211_iftype nlmode)
 {
 	struct i802_bss *bss = priv;
 	struct wpa_driver_nl80211_data *drv = bss->drv;
 	int ret = -1;
-	int nlmode;
 	int i;
 
-	switch (mode) {
-	case 0:
-		nlmode = NL80211_IFTYPE_STATION;
-		break;
-	case 1:
-		nlmode = NL80211_IFTYPE_ADHOC;
-		break;
-	case 2:
-		nlmode = NL80211_IFTYPE_AP;
-		break;
-	default:
-		return -1;
-	}
-
 	if (nl80211_set_mode(drv, drv->ifindex, nlmode) == 0) {
 		drv->nlmode = nlmode;
 		ret = 0;
@@ -4830,12 +4835,12 @@ static int wpa_driver_nl80211_set_mode(void *priv, int mode)
 	}
 
 done:
-	if (!ret && nlmode == NL80211_IFTYPE_AP) {
+	if (!ret && is_ap_interface(nlmode)) {
 		/* Setup additional AP mode functionality if needed */
 		if (drv->monitor_ifidx < 0 &&
 		    nl80211_create_monitor_interface(drv))
 			return -1;
-	} else if (!ret && nlmode != NL80211_IFTYPE_AP) {
+	} else if (!ret && !is_ap_interface(nlmode)) {
 		/* Remove additional AP mode functionality */
 		nl80211_remove_monitor_interface(drv);
 		bss->beacon_set = 0;
@@ -5585,7 +5590,7 @@ static void *i802_init(struct hostapd_data *hapd,
 			goto failed;
 	}
 
-	if (wpa_driver_nl80211_set_mode(bss, IEEE80211_MODE_AP)) {
+	if (wpa_driver_nl80211_set_mode(bss, drv->nlmode)) {
 		wpa_printf(MSG_ERROR, "nl80211: Failed to set interface %s "
 			   "into AP mode", bss->ifname);
 		goto failed;
@@ -5646,14 +5651,16 @@ static enum nl80211_iftype wpa_driver_nl80211_if_type(
 {
 	switch (type) {
 	case WPA_IF_STATION:
-	case WPA_IF_P2P_CLIENT:
 	case WPA_IF_P2P_GROUP:
 		return NL80211_IFTYPE_STATION;
 	case WPA_IF_AP_VLAN:
 		return NL80211_IFTYPE_AP_VLAN;
 	case WPA_IF_AP_BSS:
-	case WPA_IF_P2P_GO:
 		return NL80211_IFTYPE_AP;
+	case WPA_IF_P2P_CLIENT:
+		return NL80211_IFTYPE_P2P_CLIENT;
+	case WPA_IF_P2P_GO:
+		return NL80211_IFTYPE_P2P_GO;
 	}
 	return -1;
 }
@@ -5908,7 +5915,7 @@ static int wpa_driver_nl80211_send_action(void *priv, unsigned int freq,
 	os_memcpy(hdr->addr2, src, ETH_ALEN);
 	os_memcpy(hdr->addr3, bssid, ETH_ALEN);
 
-	if (drv->nlmode == NL80211_IFTYPE_AP)
+	if (is_ap_interface(drv->nlmode))
 		ret = wpa_driver_nl80211_send_mlme(priv, buf, 24 + data_len);
 	else
 		ret = nl80211_send_frame_cmd(drv, freq, wait_time, buf,
@@ -6027,7 +6034,7 @@ static int wpa_driver_nl80211_probe_req_report(void *priv, int report)
 	struct i802_bss *bss = priv;
 	struct wpa_driver_nl80211_data *drv = bss->drv;
 
-	if (drv->nlmode != NL80211_IFTYPE_STATION) {
+	if (!is_sta_interface(drv->nlmode)) {
 		wpa_printf(MSG_DEBUG, "nl80211: probe_req_report control only "
 			   "allowed in station mode (iftype=%d)",
 			   drv->nlmode);
@@ -6165,10 +6172,10 @@ static int wpa_driver_nl80211_deinit_ap(void *priv)
 {
 	struct i802_bss *bss = priv;
 	struct wpa_driver_nl80211_data *drv = bss->drv;
-	if (drv->nlmode != NL80211_IFTYPE_AP)
+	if (!is_ap_interface(drv->nlmode))
 		return -1;
 	wpa_driver_nl80211_del_beacon(drv);
-	return wpa_driver_nl80211_set_mode(priv, IEEE80211_MODE_INFRA);
+	return wpa_driver_nl80211_set_mode(priv, NL80211_IFTYPE_STATION);
 }
 
 
-- 
1.7.0.4



More information about the HostAP mailing list