Patchwork [RFC] nl80211: allow Android P2P functionality

login
register
mail settings
Submitter Johannes Berg
Date April 23, 2013, 12:47 p.m.
Message ID <1366721263-5553-1-git-send-email-johannes@sipsolutions.net>
Download mbox | patch
Permalink /patch/238902/
State Accepted
Headers show

Comments

Johannes Berg - April 23, 2013, 12:47 p.m.
From: Johannes Berg <johannes.berg@intel.com>

To support Android the kernel may have a "p2p0" netdev for a
P2P-Device even though this isn't very useful, but Android
requires a netdev. To support this in the supplicant, if the
interface mode is P2P_DEVICE, re-set it to the same instead
of STATION mode.

Note that this is only possible with a kernel that creates a
netdev for the P2P-Device wdev.

Change-Id: Ia558cf847e0753b9c77056deee3acc618a63755f
Signed-hostap: Johannes Berg <johannes.berg@intel.com>
---
 src/drivers/driver_nl80211.c | 50 +++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 45 insertions(+), 5 deletions(-)
Sreenath - April 30, 2013, 1:12 p.m.
Hello Johannes,

Does this patch has to be applied on top of the patches submitted by 
David Spinadel or hostap default git checkout code?

Also whether wpa_supplicant has to be started on dummy 'p2p0' interface 
along with WLAN primary interface. Because with out that, control socket 
won't be created on 'p2p0' and which in turn is needed by Android 
framework for P2P operations.

Regards,
Sreenath

On 04/23/2013 06:17 PM, Johannes Berg wrote:
> From: Johannes Berg <johannes.berg@intel.com>
>
> To support Android the kernel may have a "p2p0" netdev for a
> P2P-Device even though this isn't very useful, but Android
> requires a netdev. To support this in the supplicant, if the
> interface mode is P2P_DEVICE, re-set it to the same instead
> of STATION mode.
>
> Note that this is only possible with a kernel that creates a
> netdev for the P2P-Device wdev.
>
> Change-Id: Ia558cf847e0753b9c77056deee3acc618a63755f
> Signed-hostap: Johannes Berg <johannes.berg@intel.com>
> ---
>   src/drivers/driver_nl80211.c | 50 +++++++++++++++++++++++++++++++++++++++-----
>   1 file changed, 45 insertions(+), 5 deletions(-)
>
> diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
> index 3b0dba4..7b14219 100644
> --- a/src/drivers/driver_nl80211.c
> +++ b/src/drivers/driver_nl80211.c
> @@ -537,6 +537,7 @@ static void * nl80211_cmd(struct wpa_driver_nl80211_data *drv,
>   
>   struct wiphy_idx_data {
>   	int wiphy_idx;
> +	enum nl80211_iftype nlmode;
>   };
>   
>   
> @@ -552,6 +553,9 @@ static int netdev_info_handler(struct nl_msg *msg, void *arg)
>   	if (tb[NL80211_ATTR_WIPHY])
>   		info->wiphy_idx = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
>   
> +	if (tb[NL80211_ATTR_IFTYPE])
> +		info->nlmode = nla_get_u32(tb[NL80211_ATTR_IFTYPE]);
> +
>   	return NL_SKIP;
>   }
>   
> @@ -580,6 +584,30 @@ nla_put_failure:
>   }
>   
>   
> +static enum nl80211_iftype nl80211_get_ifmode(struct i802_bss *bss)
> +{
> +	struct nl_msg *msg;
> +	struct wiphy_idx_data data = {
> +		.wiphy_idx = -1,
> +	};
> +
> +	msg = nlmsg_alloc();
> +	if (!msg)
> +		return -1;
> +
> +	nl80211_cmd(bss->drv, msg, 0, NL80211_CMD_GET_INTERFACE);
> +
> +	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
> +
> +	if (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data) == 0)
> +		return data.nlmode;
> +	msg = NULL;
> +nla_put_failure:
> +	nlmsg_free(msg);
> +	return NL80211_IFTYPE_UNSPECIFIED;
> +}
> +
> +
>   static int nl80211_register_beacons(struct wpa_driver_nl80211_data *drv,
>   				    struct nl80211_wiphy_data *w)
>   {
> @@ -3623,11 +3651,23 @@ wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv)
>   	 * dynamically added interface (e.g., P2P) that was already configured
>   	 * with proper iftype.
>   	 */
> -	if (drv->ifindex != drv->global->if_add_ifindex &&
> -	    wpa_driver_nl80211_set_mode(bss, NL80211_IFTYPE_STATION) < 0) {
> -		wpa_printf(MSG_ERROR, "nl80211: Could not configure driver to "
> -			   "use managed mode");
> -		return -1;
> +	if (drv->ifindex != drv->global->if_add_ifindex) {
> +		enum nl80211_iftype nlmode;
> +
> +		nlmode = nl80211_get_ifmode(bss);
> +		if (nlmode != NL80211_IFTYPE_P2P_DEVICE)
> +			nlmode = NL80211_IFTYPE_STATION;
> +
> +		if (wpa_driver_nl80211_set_mode(bss, nlmode) < 0) {
> +			wpa_printf(MSG_ERROR, "nl80211: Could not configure "
> +				   "driver to use %s mode",
> +				   nlmode == NL80211_IFTYPE_STATION ?
> +					"managed" : "P2P-Device");
> +			return -1;
> +		}
> +
> +		/* always use managed mode internally, even for P2P-Device */
> +		drv->nlmode = NL80211_IFTYPE_STATION;
>   	}
>   
>   	if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1)) {
Sreenath - April 30, 2013, 1:13 p.m.
Hello Johannes,

Does this patch has to be applied on top of the patches submitted by 
David Spinadel or hostap default git checkout code?

Also whether wpa_supplicant has to be started on dummy 'p2p0' interface 
along with WLAN primary interface. Because with out that, control socket 
won't be created on 'p2p0' and which in turn is needed by Android 
framework for P2P operations.

Regards,
Sreenath

On 04/23/2013 06:17 PM, Johannes Berg wrote:
> From: Johannes Berg <johannes.berg@intel.com>
>
> To support Android the kernel may have a "p2p0" netdev for a
> P2P-Device even though this isn't very useful, but Android
> requires a netdev. To support this in the supplicant, if the
> interface mode is P2P_DEVICE, re-set it to the same instead
> of STATION mode.
>
> Note that this is only possible with a kernel that creates a
> netdev for the P2P-Device wdev.
>
> Change-Id: Ia558cf847e0753b9c77056deee3acc618a63755f
> Signed-hostap: Johannes Berg <johannes.berg@intel.com>
> ---
>   src/drivers/driver_nl80211.c | 50 +++++++++++++++++++++++++++++++++++++++-----
>   1 file changed, 45 insertions(+), 5 deletions(-)
>
> diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
> index 3b0dba4..7b14219 100644
> --- a/src/drivers/driver_nl80211.c
> +++ b/src/drivers/driver_nl80211.c
> @@ -537,6 +537,7 @@ static void * nl80211_cmd(struct wpa_driver_nl80211_data *drv,
>   
>   struct wiphy_idx_data {
>   	int wiphy_idx;
> +	enum nl80211_iftype nlmode;
>   };
>   
>   
> @@ -552,6 +553,9 @@ static int netdev_info_handler(struct nl_msg *msg, void *arg)
>   	if (tb[NL80211_ATTR_WIPHY])
>   		info->wiphy_idx = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
>   
> +	if (tb[NL80211_ATTR_IFTYPE])
> +		info->nlmode = nla_get_u32(tb[NL80211_ATTR_IFTYPE]);
> +
>   	return NL_SKIP;
>   }
>   
> @@ -580,6 +584,30 @@ nla_put_failure:
>   }
>   
>   
> +static enum nl80211_iftype nl80211_get_ifmode(struct i802_bss *bss)
> +{
> +	struct nl_msg *msg;
> +	struct wiphy_idx_data data = {
> +		.wiphy_idx = -1,
> +	};
> +
> +	msg = nlmsg_alloc();
> +	if (!msg)
> +		return -1;
> +
> +	nl80211_cmd(bss->drv, msg, 0, NL80211_CMD_GET_INTERFACE);
> +
> +	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
> +
> +	if (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data) == 0)
> +		return data.nlmode;
> +	msg = NULL;
> +nla_put_failure:
> +	nlmsg_free(msg);
> +	return NL80211_IFTYPE_UNSPECIFIED;
> +}
> +
> +
>   static int nl80211_register_beacons(struct wpa_driver_nl80211_data *drv,
>   				    struct nl80211_wiphy_data *w)
>   {
> @@ -3623,11 +3651,23 @@ wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv)
>   	 * dynamically added interface (e.g., P2P) that was already configured
>   	 * with proper iftype.
>   	 */
> -	if (drv->ifindex != drv->global->if_add_ifindex &&
> -	    wpa_driver_nl80211_set_mode(bss, NL80211_IFTYPE_STATION) < 0) {
> -		wpa_printf(MSG_ERROR, "nl80211: Could not configure driver to "
> -			   "use managed mode");
> -		return -1;
> +	if (drv->ifindex != drv->global->if_add_ifindex) {
> +		enum nl80211_iftype nlmode;
> +
> +		nlmode = nl80211_get_ifmode(bss);
> +		if (nlmode != NL80211_IFTYPE_P2P_DEVICE)
> +			nlmode = NL80211_IFTYPE_STATION;
> +
> +		if (wpa_driver_nl80211_set_mode(bss, nlmode) < 0) {
> +			wpa_printf(MSG_ERROR, "nl80211: Could not configure "
> +				   "driver to use %s mode",
> +				   nlmode == NL80211_IFTYPE_STATION ?
> +					"managed" : "P2P-Device");
> +			return -1;
> +		}
> +
> +		/* always use managed mode internally, even for P2P-Device */
> +		drv->nlmode = NL80211_IFTYPE_STATION;
>   	}
>   
>   	if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1)) {
Johannes Berg - April 30, 2013, 1:42 p.m.
On Tue, 2013-04-30 at 18:43 +0530, Sreenath wrote:
> Hello Johannes,
> 
> Does this patch has to be applied on top of the patches submitted by 
> David Spinadel or hostap default git checkout code?

It can be applied today.

> Also whether wpa_supplicant has to be started on dummy 'p2p0' interface 
> along with WLAN primary interface. Because with out that, control socket 
> won't be created on 'p2p0' and which in turn is needed by Android 
> framework for P2P operations.

Well, do
# iw wlan0 interface create p2p0 __p2pdev
first. Then use

wpa_supplicant ... -ip2p0 -N -iwlan0

johannes
Sreenath - April 30, 2013, 3:40 p.m.
Hello Johannes,

Thanks for the response.

After some playing around I figured out that the command to create p2p0 
interface is,

# iw wlan0 interface add p2p0 type __p2pdev

Regards,
Sreenath

On 04/30/2013 07:12 PM, Johannes Berg wrote:
> On Tue, 2013-04-30 at 18:43 +0530, Sreenath wrote:
>> Hello Johannes,
>>
>> Does this patch has to be applied on top of the patches submitted by
>> David Spinadel or hostap default git checkout code?
> It can be applied today.
>
>> Also whether wpa_supplicant has to be started on dummy 'p2p0' interface
>> along with WLAN primary interface. Because with out that, control socket
>> won't be created on 'p2p0' and which in turn is needed by Android
>> framework for P2P operations.
> Well, do
> # iw wlan0 interface create p2p0 __p2pdev
> first. Then use
>
> wpa_supplicant ... -ip2p0 -N -iwlan0
>
> johannes
>
>

Patch

diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 3b0dba4..7b14219 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -537,6 +537,7 @@  static void * nl80211_cmd(struct wpa_driver_nl80211_data *drv,
 
 struct wiphy_idx_data {
 	int wiphy_idx;
+	enum nl80211_iftype nlmode;
 };
 
 
@@ -552,6 +553,9 @@  static int netdev_info_handler(struct nl_msg *msg, void *arg)
 	if (tb[NL80211_ATTR_WIPHY])
 		info->wiphy_idx = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
 
+	if (tb[NL80211_ATTR_IFTYPE])
+		info->nlmode = nla_get_u32(tb[NL80211_ATTR_IFTYPE]);
+
 	return NL_SKIP;
 }
 
@@ -580,6 +584,30 @@  nla_put_failure:
 }
 
 
+static enum nl80211_iftype nl80211_get_ifmode(struct i802_bss *bss)
+{
+	struct nl_msg *msg;
+	struct wiphy_idx_data data = {
+		.wiphy_idx = -1,
+	};
+
+	msg = nlmsg_alloc();
+	if (!msg)
+		return -1;
+
+	nl80211_cmd(bss->drv, msg, 0, NL80211_CMD_GET_INTERFACE);
+
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
+
+	if (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data) == 0)
+		return data.nlmode;
+	msg = NULL;
+nla_put_failure:
+	nlmsg_free(msg);
+	return NL80211_IFTYPE_UNSPECIFIED;
+}
+
+
 static int nl80211_register_beacons(struct wpa_driver_nl80211_data *drv,
 				    struct nl80211_wiphy_data *w)
 {
@@ -3623,11 +3651,23 @@  wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv)
 	 * dynamically added interface (e.g., P2P) that was already configured
 	 * with proper iftype.
 	 */
-	if (drv->ifindex != drv->global->if_add_ifindex &&
-	    wpa_driver_nl80211_set_mode(bss, NL80211_IFTYPE_STATION) < 0) {
-		wpa_printf(MSG_ERROR, "nl80211: Could not configure driver to "
-			   "use managed mode");
-		return -1;
+	if (drv->ifindex != drv->global->if_add_ifindex) {
+		enum nl80211_iftype nlmode;
+
+		nlmode = nl80211_get_ifmode(bss);
+		if (nlmode != NL80211_IFTYPE_P2P_DEVICE)
+			nlmode = NL80211_IFTYPE_STATION;
+
+		if (wpa_driver_nl80211_set_mode(bss, nlmode) < 0) {
+			wpa_printf(MSG_ERROR, "nl80211: Could not configure "
+				   "driver to use %s mode",
+				   nlmode == NL80211_IFTYPE_STATION ?
+					"managed" : "P2P-Device");
+			return -1;
+		}
+
+		/* always use managed mode internally, even for P2P-Device */
+		drv->nlmode = NL80211_IFTYPE_STATION;
 	}
 
 	if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1)) {