[RFC 07/10] nl80211_driver: implement init and deinit P2P device functions
Arend van Spriel
arend
Mon Feb 11 03:15:44 PST 2013
From: David Spinadel <david.spinadel at intel.com>
Signed-hostap: David Spinadel <david.spinadel at intel.com>
---
src/drivers/driver_nl80211.c | 137 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 137 insertions(+)
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 183761a..562b084 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -9372,6 +9372,139 @@ static int android_pno_stop(struct i802_bss *bss)
#endif /* ANDROID */
+#ifdef CONFIG_P2P
+static int nl80211_create_p2p_dev_handler(struct nl_msg *msg, void *arg)
+{
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+ struct nlattr *tb[NL80211_ATTR_MAX + 1];
+ struct i802_bss *p2p_dev = arg;
+
+ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), NULL);
+ if (tb[NL80211_ATTR_WDEV])
+ p2p_dev->wdev_id =
+ nla_get_u64(tb[NL80211_ATTR_WDEV]);
+
+ if (tb[NL80211_ATTR_MAC])
+ os_memcpy(p2p_dev->addr,
+ nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
+
+ return NL_SKIP;
+}
+
+static int nl80211_p2p_device_exec_cmd(struct wpa_driver_nl80211_data *drv,
+ const char *ifname,
+ enum nl80211_commands cmd,
+ int64_t wdev_id)
+{
+ struct nl_msg *msg;
+ int ret = -1;
+
+ if (wdev_id < 0) {
+ wpa_printf(MSG_DEBUG, "nl80211: Cannot execute p2p device"
+ "cmd %d without wdev_id", cmd);
+ return -1;
+ }
+ wpa_printf(MSG_DEBUG, "Executing p2p device cmd %d", cmd);
+ msg = nlmsg_alloc();
+ if (!msg)
+ return -1;
+
+ nl80211_cmd(drv, msg, 0, cmd);
+ NLA_PUT_U64(msg, NL80211_ATTR_WDEV, wdev_id);
+
+ ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+ msg = NULL;
+ if (ret) {
+nla_put_failure:
+ nlmsg_free(msg);
+ wpa_printf(MSG_ERROR, "nl80211: Failed to execute CMD %d on "
+ "%s: error =%d:%s", cmd, ifname, ret,
+ strerror(-ret));
+ }
+ return ret;
+}
+
+static void nl80211_deinit_p2p_dev(void *priv)
+{
+ struct i802_bss *p2p_dev = priv;
+ struct wpa_driver_nl80211_data *drv = p2p_dev->drv;
+ struct i802_bss *last;
+
+ if (p2p_dev->wdev_id == -1)
+ return;
+
+ /*
+ * Not stopping the P2P device here as the kernel does that when
+ * deinit is called. Need to execute STOP here if that changes.
+ */
+ nl80211_p2p_device_exec_cmd(drv, p2p_dev->ifname,
+ NL80211_CMD_DEL_INTERFACE,
+ p2p_dev->wdev_id);
+
+ for (last = &drv->first_bss; last->next != p2p_dev; last = last->next)
+ ;
+ last->next = p2p_dev->next;
+
+ os_free(p2p_dev);
+}
+
+static void *nl80211_init_p2p_dev(void *priv, const char *ifname, u8 *addr)
+{
+ struct i802_bss *bss = priv;
+ struct i802_bss *last;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ int ret;
+ int type;
+ struct i802_bss *p2p_dev = os_zalloc(sizeof(struct i802_bss));
+ if (!p2p_dev)
+ return NULL;
+
+ *p2p_dev = *bss;
+ os_strncpy(p2p_dev->ifname, ifname, IFNAMSIZ);
+
+ for (last = bss; last->next; last = last->next)
+ ;
+ last->next = p2p_dev;
+
+ p2p_dev->ifindex = nl80211_create_iface(drv, ifname,
+ NL80211_IFTYPE_P2P_DEVICE,
+ NULL, 0,
+ nl80211_create_p2p_dev_handler,
+ p2p_dev);
+ if (p2p_dev->wdev_id == -1 || p2p_dev->ifindex != 0 ||
+ is_zero_ether_addr((const u8 *)&p2p_dev->addr)) {
+ wpa_printf(MSG_ERROR, "nl80211: Failed to create a p2p device"
+ " interface %s", ifname);
+ last->next = NULL;
+ os_free(p2p_dev);
+ return NULL;
+ }
+
+ ret = nl80211_p2p_device_exec_cmd(drv, ifname,
+ NL80211_CMD_START_P2P_DEVICE,
+ p2p_dev->wdev_id);
+
+ if (ret < 0) {
+ wpa_printf(MSG_ERROR, "nl80211: Failed to start p2p device"
+ " interface %s", ifname);
+ nl80211_deinit_p2p_dev(p2p_dev);
+ return NULL;
+ }
+
+ os_memcpy(addr, p2p_dev->addr, ETH_ALEN);
+
+ /* Register P2P Public Action frame on the device interface */
+ type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_ACTION << 4);
+ nl80211_register_frame(p2p_dev, bss->nl_mgmt, type,
+ (u8 *) "\x04\x09\x50\x6f\x9a\x09", 6);
+ /* Register P2P Action frame on the device interface */
+ nl80211_register_frame(p2p_dev, bss->nl_mgmt, type,
+ (u8 *) "\x7f\x50\x6f\x9a\x09", 5);
+
+ return p2p_dev;
+}
+#endif /* CONFIG_P2P */
static int driver_nl80211_set_key(const char *ifname, void *priv,
enum wpa_alg alg, const u8 *addr,
@@ -9554,4 +9687,8 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.send_tdls_mgmt = nl80211_send_tdls_mgmt,
.tdls_oper = nl80211_tdls_oper,
#endif /* CONFIG_TDLS */
+#ifdef CONFIG_P2P
+ .init_p2p_dev = nl80211_init_p2p_dev,
+ .deinit_p2p_dev = nl80211_deinit_p2p_dev,
+#endif /* CONFIG_P2P */
};
--
1.7.10.4
More information about the Hostap
mailing list