[PATCH 6/6] driver_nl80211: use p2p interface types

Johannes Berg johannes at sipsolutions.net
Thu Sep 16 09:03:16 EDT 2010


From: Johannes Berg <johannes.berg at intel.com>

This modifies the nl80211 driver to no longer
use interface modes but rather use interface
types throughout, and then also use the new
p2p interface types. Additionally, the ability
to use p2p is now discovered based on the
supported interface types.

Signed-off-by: Johannes Berg <johannes.berg at intel.com>
---
 src/drivers/driver_nl80211.c |  167 ++++++++++++++++++++++++------------------
 1 files changed, 95 insertions(+), 72 deletions(-)

diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 819cb7a..8608dd5 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -136,8 +136,8 @@ struct wpa_driver_nl80211_data {
 	int associated;
 	u8 ssid[32];
 	size_t ssid_len;
-	int nlmode;
-	int ap_scan_as_station;
+	enum nl80211_iftype iftype;
+	enum nl80211_iftype ap_scan_as_station_iftype;
 	unsigned int assoc_freq;
 
 	int monitor_sock;
@@ -173,7 +173,7 @@ 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_iftype(void *priv, enum nl80211_iftype);
 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,
@@ -1122,12 +1122,12 @@ static int process_event(struct nl_msg *msg, void *arg)
 		}
 	}
 
-	if (drv->ap_scan_as_station &&
+	if (drv->ap_scan_as_station_iftype != 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;
+		wpa_driver_nl80211_set_iftype(&drv->first_bss,
+					      drv->ap_scan_as_station_iftype);
+		drv->ap_scan_as_station_iftype = NL80211_IFTYPE_UNSPECIFIED;
 	}
 
 	switch (gnlh->cmd) {
@@ -1272,6 +1272,7 @@ struct wiphy_info_data {
 	int ap_supported;
 	int auth_supported;
 	int connect_supported;
+	int p2p_supported;
 };
 
 
@@ -1291,13 +1292,22 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
 	if (tb[NL80211_ATTR_SUPPORTED_IFTYPES]) {
 		struct nlattr *nl_mode;
 		int i;
+		int p2p = 0;
 		nla_for_each_nested(nl_mode,
 				    tb[NL80211_ATTR_SUPPORTED_IFTYPES], i) {
-			if (nl_mode->nla_type == NL80211_IFTYPE_AP) {
+			switch (nl_mode->nla_type) {
+			case NL80211_IFTYPE_AP:
 				info->ap_supported = 1;
 				break;
+			case NL80211_IFTYPE_P2P_CLIENT:
+				p2p |= 1;
+				break;
+			case NL80211_IFTYPE_P2P_GO:
+				p2p |= 2;
+				break;
 			}
 		}
+		info->p2p_supported = p2p == 3;
 	}
 
 	if (tb[NL80211_ATTR_SUPPORTED_COMMANDS]) {
@@ -1374,7 +1384,8 @@ static int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
 	}
 
 	drv->capa.flags |= WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE;
-	drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CAPABLE;
+	if (info.p2p_supported)
+		drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CAPABLE;
 	drv->capa.max_remain_on_chan = 5000;
 
 	return 0;
@@ -1697,7 +1708,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_iftype(bss, NL80211_IFTYPE_STATION) < 0) {
 		wpa_printf(MSG_DEBUG, "nl80211: Could not configure driver to "
 			   "use managed mode");
 	}
@@ -1788,7 +1799,8 @@ static void wpa_driver_nl80211_deinit(void *priv)
 
 	nl80211_remove_monitor_interface(drv);
 
-	if (drv->nlmode == NL80211_IFTYPE_AP)
+	if (drv->iftype == NL80211_IFTYPE_AP ||
+	    drv->iftype == NL80211_IFTYPE_P2P_GO)
 		wpa_driver_nl80211_del_beacon(drv);
 
 #ifdef HOSTAPD
@@ -1819,7 +1831,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_iftype(bss, NL80211_IFTYPE_STATION);
 
 	if (drv->ioctl_sock >= 0)
 		close(drv->ioctl_sock);
@@ -1849,10 +1861,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) {
-		wpa_driver_nl80211_set_mode(&drv->first_bss,
-					    IEEE80211_MODE_AP);
-		drv->ap_scan_as_station = 0;
+	if (drv->ap_scan_as_station_iftype != NL80211_IFTYPE_UNSPECIFIED) {
+		wpa_driver_nl80211_set_iftype(&drv->first_bss,
+					      drv->ap_scan_as_station_iftype);
+		drv->ap_scan_as_station_iftype = NL80211_IFTYPE_UNSPECIFIED;
 	}
 	wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
 	wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
@@ -1926,23 +1938,24 @@ 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 (drv->iftype == NL80211_IFTYPE_AP ||
+		    drv->iftype == NL80211_IFTYPE_P2P_GO) {
+			enum nl80211_iftype cur_iftype = drv->iftype;
 			/*
 			 * 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))
+			if (wpa_driver_nl80211_set_iftype(bss,
+						NL80211_IFTYPE_STATION))
 				goto nla_put_failure;
 
 			if (wpa_driver_nl80211_scan(drv, params)) {
-				wpa_driver_nl80211_set_mode(bss,
-							    IEEE80211_MODE_AP);
+				wpa_driver_nl80211_set_iftype(bss, cur_iftype);
 				goto nla_put_failure;
 			}
 
 			/* Restore AP mode when processing scan results */
-			drv->ap_scan_as_station = 1;
+			drv->ap_scan_as_station_iftype = cur_iftype;
 			ret = 0;
 		} else
 			goto nla_put_failure;
@@ -2168,7 +2181,8 @@ 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 ((drv->iftype == NL80211_IFTYPE_STATION ||
+			     drv->iftype == NL80211_IFTYPE_P2P_CLIENT) &&
 			    os_memcmp(r->bssid, drv->bssid, ETH_ALEN) != 0 &&
 			    os_memcmp(r->bssid, drv->auth_bssid, ETH_ALEN) !=
 			    0) {
@@ -2186,13 +2200,15 @@ 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 ((drv->iftype == NL80211_IFTYPE_STATION ||
+			     drv->iftype == NL80211_IFTYPE_P2P_CLIENT) &&
 			    !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 ((drv->iftype == NL80211_IFTYPE_STATION ||
+				    drv->iftype == NL80211_IFTYPE_P2P_CLIENT) &&
 				   os_memcmp(drv->bssid, r->bssid, ETH_ALEN) !=
 				   0) {
 				wpa_printf(MSG_DEBUG, "nl80211: Local state "
@@ -2386,7 +2402,8 @@ static int wpa_driver_nl80211_set_key(const char *ifname, void *priv,
 	if (addr)
 		return ret;
 #else /* HOSTAPD */
-	if (drv->nlmode == NL80211_IFTYPE_AP && addr)
+	if ((drv->iftype == NL80211_IFTYPE_AP ||
+	     drv->iftype == NL80211_IFTYPE_P2P_GO) && addr)
 		return ret;
 #endif /* HOSTAPD */
 
@@ -2607,14 +2624,19 @@ static int wpa_driver_nl80211_authenticate(
 	struct nl_msg *msg;
 	enum nl80211_auth_type type;
 	int count = 0;
+	enum nl80211_iftype wanted_iftype = NL80211_IFTYPE_STATION;
 
 	drv->associated = 0;
 	os_memset(drv->auth_bssid, 0, ETH_ALEN);
+
 	/* FIX: IBSS mode */
-	if (drv->nlmode != NL80211_IFTYPE_STATION)
-		wpa_driver_nl80211_set_mode(priv, IEEE80211_MODE_INFRA);
+	if (drv->iftype == NL80211_IFTYPE_P2P_CLIENT)
+		wanted_iftype = NL80211_IFTYPE_P2P_CLIENT;
 
-	if (wpa_driver_nl80211_set_mode(priv, IEEE80211_MODE_INFRA) < 0)
+	if (drv->iftype != wanted_iftype)
+		wpa_driver_nl80211_set_iftype(priv, wanted_iftype);
+
+	if (wpa_driver_nl80211_set_iftype(priv, wanted_iftype) < 0)
 		return -1;
 
 retry:
@@ -3046,7 +3068,8 @@ 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 ((drv->iftype == NL80211_IFTYPE_STATION ||
+	     drv->iftype == NL80211_IFTYPE_P2P_CLIENT) &&
 	    WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
 	    WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_RESP) {
 		/*
@@ -3853,10 +3876,14 @@ static int wpa_driver_nl80211_sta_set_flags(void *priv, const u8 *addr,
 static int wpa_driver_nl80211_ap(struct wpa_driver_nl80211_data *drv,
 				 struct wpa_driver_associate_params *params)
 {
-	if (params->p2p)
+	enum nl80211_iftype wanted_iftype = NL80211_IFTYPE_AP;
+
+	if (params->p2p) {
+		wanted_iftype = NL80211_IFTYPE_P2P_GO;
 		wpa_printf(MSG_DEBUG, "nl80211: Setup AP operations for P2P "
 			   "group (GO)");
-	if (wpa_driver_nl80211_set_mode(&drv->first_bss, params->mode) ||
+	}
+	if (wpa_driver_nl80211_set_iftype(&drv->first_bss, wanted_iftype) ||
 	    wpa_driver_nl80211_set_freq(drv, params->freq, 0, 0)) {
 		nl80211_remove_monitor_interface(drv);
 		return -1;
@@ -3907,7 +3934,7 @@ 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_iftype(&drv->first_bss, NL80211_IFTYPE_ADHOC)) {
 		wpa_printf(MSG_INFO, "nl80211: Failed to set interface into "
 			   "IBSS mode");
 		return -1;
@@ -4125,6 +4152,7 @@ static int wpa_driver_nl80211_associate(
 	struct wpa_driver_nl80211_data *drv = bss->drv;
 	int ret = -1;
 	struct nl_msg *msg;
+	enum nl80211_iftype wanted_iftype = NL80211_IFTYPE_STATION;
 
 	if (params->mode == IEEE80211_MODE_AP)
 		return wpa_driver_nl80211_ap(drv, params);
@@ -4132,8 +4160,11 @@ static int wpa_driver_nl80211_associate(
 	if (params->mode == IEEE80211_MODE_IBSS)
 		return wpa_driver_nl80211_ibss(drv, params);
 
+	if (params->p2p)
+		wanted_iftype = NL80211_IFTYPE_P2P_CLIENT;
+
 	if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) {
-		if (wpa_driver_nl80211_set_mode(priv, params->mode) < 0)
+		if (wpa_driver_nl80211_set_iftype(priv, wanted_iftype) < 0)
 			return -1;
 		return wpa_driver_nl80211_connect(drv, params);
 	}
@@ -4211,8 +4242,8 @@ nla_put_failure:
 }
 
 
-static int nl80211_set_mode(struct wpa_driver_nl80211_data *drv,
-			    int ifindex, int mode)
+static int nl80211_set_iftype(struct wpa_driver_nl80211_data *drv,
+			      int ifindex, enum nl80211_iftype iftype)
 {
 	struct nl_msg *msg;
 	int ret = -ENOBUFS;
@@ -4224,47 +4255,32 @@ static int nl80211_set_mode(struct wpa_driver_nl80211_data *drv,
 	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
 		    0, NL80211_CMD_SET_INTERFACE, 0);
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
-	NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, mode);
+	NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, iftype);
 
 	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
 	if (!ret)
 		return 0;
 nla_put_failure:
-	wpa_printf(MSG_DEBUG, "nl80211: Failed to set interface %d to mode %d:"
-		   " %d (%s)", ifindex, mode, ret, strerror(-ret));
+	wpa_printf(MSG_DEBUG, "nl80211: Failed to set interface %d to type %d:"
+		   " %d (%s)", ifindex, iftype, ret, strerror(-ret));
 	return ret;
 }
 
 
-static int wpa_driver_nl80211_set_mode(void *priv, int mode)
+static int wpa_driver_nl80211_set_iftype(void *priv, enum nl80211_iftype iftype)
 {
 	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;
+	if (nl80211_set_iftype(drv, drv->ifindex, iftype) == 0) {
+		drv->iftype = iftype;
 		ret = 0;
 		goto done;
 	}
 
-	if (nlmode == drv->nlmode) {
+	if (iftype == drv->iftype) {
 		wpa_printf(MSG_DEBUG, "nl80211: Interface already in "
 			   "requested mode - ignore error");
 		ret = 0;
@@ -4282,7 +4298,7 @@ static int wpa_driver_nl80211_set_mode(void *priv, int mode)
 		    0) {
 			/* Try to set the mode again while the interface is
 			 * down */
-			ret = nl80211_set_mode(drv, drv->ifindex, nlmode);
+			ret = nl80211_set_iftype(drv, drv->ifindex, iftype);
 			if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname,
 						  1))
 				ret = -1;
@@ -4297,24 +4313,26 @@ static int wpa_driver_nl80211_set_mode(void *priv, int mode)
 	if (!ret) {
 		wpa_printf(MSG_DEBUG, "nl80211: Mode change succeeded while "
 			   "interface is down");
-		drv->nlmode = nlmode;
+		drv->iftype = iftype;
 	}
 
 done:
-	if (!ret && nlmode == NL80211_IFTYPE_AP) {
+	if (!ret && (iftype == NL80211_IFTYPE_AP ||
+		     iftype == NL80211_IFTYPE_P2P_GO)) {
 		/* 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 && iftype != NL80211_IFTYPE_AP &&
+			   iftype != NL80211_IFTYPE_P2P_GO) {
 		/* Remove additional AP mode functionality */
 		nl80211_remove_monitor_interface(drv);
 		bss->beacon_set = 0;
 	}
 
 	if (ret)
-		wpa_printf(MSG_DEBUG, "nl80211: Interface mode change to %d "
-			   "from %d failed", nlmode, drv->nlmode);
+		wpa_printf(MSG_DEBUG, "nl80211: Interface type change to %d "
+			   "from %d failed", iftype, drv->iftype);
 
 	return ret;
 }
@@ -5034,7 +5052,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_iftype(bss, NL80211_IFTYPE_AP)) {
 		wpa_printf(MSG_ERROR, "nl80211: Failed to set interface %s "
 			   "into AP mode", bss->ifname);
 		goto failed;
@@ -5092,14 +5110,16 @@ static enum nl80211_iftype wpa_driver_nl80211_if_type(
 {
 	switch (type) {
 	case WPA_IF_STATION:
+		return NL80211_IFTYPE_STATION;
 	case WPA_IF_P2P_CLIENT:
 	case WPA_IF_P2P_GROUP:
-		return NL80211_IFTYPE_STATION;
+		return NL80211_IFTYPE_P2P_CLIENT;
 	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_GO:
+		return NL80211_IFTYPE_P2P_GO;
 	}
 	return -1;
 }
@@ -5272,7 +5292,8 @@ 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 (drv->iftype == NL80211_IFTYPE_AP ||
+	    drv->iftype == NL80211_IFTYPE_P2P_GO) {
 		ret = wpa_driver_nl80211_send_mlme(priv, buf, 24 + data_len);
 		os_free(buf);
 		return ret;
@@ -5365,10 +5386,11 @@ 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 (drv->iftype != NL80211_IFTYPE_STATION &&
+	    drv->iftype != NL80211_IFTYPE_P2P_CLIENT) {
 		wpa_printf(MSG_DEBUG, "nl80211: probe_req_report control only "
 			   "allowed in station mode (iftype=%d)",
-			   drv->nlmode);
+			   drv->iftype);
 		return -1;
 	}
 
@@ -5501,10 +5523,11 @@ 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 (drv->iftype != NL80211_IFTYPE_AP &&
+	    drv->iftype != NL80211_IFTYPE_P2P_GO)
 		return -1;
 	wpa_driver_nl80211_del_beacon(drv);
-	return wpa_driver_nl80211_set_mode(priv, IEEE80211_MODE_INFRA);
+	return wpa_driver_nl80211_set_iftype(priv, NL80211_IFTYPE_STATION);
 }
 
 
-- 
1.7.1



More information about the HostAP mailing list