Fix sending non-Public Action frames over P2P Device interface

The P2P Device interface can only send Public Action frames. Non-Public
Action frames must be sent over a group interface. The previous
implementation sometimes tried to send non-Public Action frames such as
GO Discoverability over the P2P Device interface, however, the source
address of the frame was set to the group interface address so the code
in offchannel.c knew to select the correct interface for the TX.

The check breaks when the P2P Device and group interfaces have the same
MAC address. In this case the frame will be sent over the P2P Device
interface and the send will fail.

Fix this problem in two places:
1. In offchannel, route non-Public Action frames to the GO
   interface when the above conditions are met.
2. When a TX_STATUS event arrives on such routed frame, it will
   arrive on the GO interface but it must be handled by the P2P Device
   interface since it has the relevant state logic.

Signed-off-by: Lior David <qca_liord@qca.qualcomm.com>
This commit is contained in:
Lior David 2016-03-30 14:57:31 +03:00 committed by Jouni Malinen
parent 4d916ed6c5
commit a26c9c2e71
2 changed files with 29 additions and 5 deletions

View file

@ -3608,17 +3608,20 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
#endif /* CONFIG_AP */
#ifdef CONFIG_OFFCHANNEL
wpa_dbg(wpa_s, MSG_DEBUG, "EVENT_TX_STATUS pending_dst="
MACSTR, MAC2STR(wpa_s->parent->pending_action_dst));
MACSTR, MAC2STR(wpa_s->p2pdev->pending_action_dst));
/*
* Catch TX status events for Action frames we sent via group
* interface in GO mode.
* interface in GO mode, or via standalone AP interface.
* Note, wpa_s->p2pdev will be the same as wpa_s->parent,
* except when the primary interface is used as a GO interface
* (for drivers which do not have group interface concurrency)
*/
if (data->tx_status.type == WLAN_FC_TYPE_MGMT &&
data->tx_status.stype == WLAN_FC_STYPE_ACTION &&
os_memcmp(wpa_s->parent->pending_action_dst,
os_memcmp(wpa_s->p2pdev->pending_action_dst,
data->tx_status.dst, ETH_ALEN) == 0) {
offchannel_send_action_tx_status(
wpa_s->parent, data->tx_status.dst,
wpa_s->p2pdev, data->tx_status.dst,
data->tx_status.data,
data->tx_status.data_len,
data->tx_status.ack ?

View file

@ -23,8 +23,29 @@ wpas_get_tx_interface(struct wpa_supplicant *wpa_s, const u8 *src)
{
struct wpa_supplicant *iface;
if (os_memcmp(src, wpa_s->own_addr, ETH_ALEN) == 0)
if (os_memcmp(src, wpa_s->own_addr, ETH_ALEN) == 0) {
#ifdef CONFIG_P2P
if (wpa_s->p2p_mgmt && wpa_s != wpa_s->parent &&
wpa_s->parent->ap_iface &&
os_memcmp(wpa_s->parent->own_addr,
wpa_s->own_addr, ETH_ALEN) == 0 &&
wpabuf_len(wpa_s->pending_action_tx) >= 2 &&
*wpabuf_head_u8(wpa_s->pending_action_tx) !=
WLAN_ACTION_PUBLIC) {
/*
* When P2P Device interface has same MAC address as
* the GO interface, make sure non-Public Action frames
* are sent through the GO interface. The P2P Device
* interface can only send Public Action frames.
*/
wpa_printf(MSG_DEBUG,
"P2P: Use GO interface %s instead of interface %s for Action TX",
wpa_s->parent->ifname, wpa_s->ifname);
return wpa_s->parent;
}
#endif /* CONFIG_P2P */
return wpa_s;
}
/*
* Try to find a group interface that matches with the source address.