@@ -9808,7 +9808,7 @@ 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;
+ struct i802_bss *tbss;
if (p2p_dev->wdev_id == -1)
return;
@@ -9821,11 +9821,19 @@ static void nl80211_deinit_p2p_dev(void *priv)
NL80211_CMD_DEL_INTERFACE,
p2p_dev->wdev_id);
- for (last = &drv->first_bss; last->next && last->next != p2p_dev;
- last = last->next)
- ;
- if (last->next && last->next == p2p_dev)
- last->next = p2p_dev->next;
+ for (tbss = &drv->first_bss; tbss; tbss = tbss->next) {
+ if (tbss->next == p2p_dev) {
+ tbss->next = p2p_dev->next;
+ break;
+ }
+ }
+
+ if (p2p_dev->nl_mgmt) {
+ eloop_unregister_read_sock(nl_socket_get_fd(p2p_dev->nl_mgmt));
+ nl_destroy_handles(&p2p_dev->nl_mgmt);
+ }
+
+ nl80211_destroy_bss(p2p_dev);
os_free(p2p_dev);
}
@@ -9833,15 +9841,16 @@ static void nl80211_deinit_p2p_dev(void *priv)
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;
+ p2p_dev->drv = drv;
+ p2p_dev->ctx = drv->ctx;
os_strncpy(p2p_dev->ifname, ifname, IFNAMSIZ);
p2p_dev->ifindex = nl80211_create_iface(drv, ifname,
@@ -9857,6 +9866,17 @@ static void *nl80211_init_p2p_dev(void *priv, const char *ifname, u8 *addr)
return NULL;
}
+ ret = nl80211_init_bss(p2p_dev);
+ if (ret) {
+ nl80211_deinit_p2p_dev(p2p_dev);
+ return NULL;
+ }
+
+ if (nl80211_alloc_mgmt_handle(p2p_dev)) {
+ nl80211_deinit_p2p_dev(p2p_dev);
+ return NULL;
+ }
+
ret = nl80211_p2p_device_exec_cmd(drv, ifname,
NL80211_CMD_START_P2P_DEVICE,
p2p_dev->wdev_id);
@@ -9868,18 +9888,17 @@ static void *nl80211_init_p2p_dev(void *priv, const char *ifname, u8 *addr)
return NULL;
}
- for (last = bss; last->next; last = last->next)
- ;
- last->next = p2p_dev;
-
os_memcpy(addr, p2p_dev->addr, ETH_ALEN);
+ p2p_dev->next = drv->first_bss.next;
+ drv->first_bss.next = p2p_dev;
+
/* 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,
+ nl80211_register_frame(p2p_dev, p2p_dev->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,
+ nl80211_register_frame(p2p_dev, p2p_dev->nl_mgmt, type,
(u8 *) "\x7f\x50\x6f\x9a\x09", 5);
return p2p_dev;
This works in hwsim now, with a mac80211 patch:
@@ -2681,6 +2681,9 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
stype = mgmt->frame_control & cpu_to_le16(IEEE80211_FCTL_STYPE);
+ if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE)
+ return RX_CONTINUE;
+
if (!ieee80211_vif_is_mesh(&sdata->vif) &&
sdata->vif.type != NL80211_IFTYPE_ADHOC &&
sdata->vif.type != NL80211_IFTYPE_STATION)
@@ -3030,7 +3033,8 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx,
!ieee80211_is_probe_resp(hdr->frame_control) &&
!ieee80211_is_beacon(hdr->frame_control))
return 0;
- if (!ether_addr_equal(sdata->vif.addr, hdr->addr1))
+ if (!ether_addr_equal(sdata->vif.addr, hdr->addr1) &&
+ !multicast)
status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
break;
default: