P2P: Reject multi-channel concurrent operations depending on driver
The driver wrapper can now indicate whether the driver supports concurrent operations on multiple channels (e.g., infra STA connection on 5 GHz channel 36 and P2P group on 2.4 GHz channel 1). If not, P2P_CONNECT commands will be rejected if they would require multi-channel concurrency. The new failure codes for P2P_CONNECT: FAIL-CHANNEL-UNAVAILABLE: The requested/needed channel is not currently available (i.e., user has an option of disconnecting another interface to make the channel available). FAIL-CHANNEL-UNSUPPORTED: The request channel is not available for P2P.
This commit is contained in:
parent
7861cb08c9
commit
d054a4622c
5 changed files with 74 additions and 12 deletions
|
@ -542,6 +542,8 @@ struct wpa_driver_capa {
|
|||
#define WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE 0x00000400
|
||||
/* This interface is P2P capable (P2P Device, GO, or P2P Client */
|
||||
#define WPA_DRIVER_FLAGS_P2P_CAPABLE 0x00000800
|
||||
/* Driver supports concurrent operations on multiple channels */
|
||||
#define WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT 0x00001000
|
||||
unsigned int flags;
|
||||
|
||||
int max_scan_ssids;
|
||||
|
|
|
@ -1255,4 +1255,12 @@ int p2p_add_device(struct p2p_data *p2p, const u8 *addr, int freq, int level,
|
|||
*/
|
||||
void p2p_set_intra_bss_dist(struct p2p_data *p2p, int enabled);
|
||||
|
||||
/**
|
||||
* p2p_supported_freq - Check whether channel is supported for P2P
|
||||
* @p2p: P2P module context from p2p_init()
|
||||
* @freq: Channel frequency in MHz
|
||||
* Returns: 0 if channel not usable for P2P, 1 if usable for P2P
|
||||
*/
|
||||
int p2p_supported_freq(struct p2p_data *p2p, unsigned int freq);
|
||||
|
||||
#endif /* P2P_H */
|
||||
|
|
|
@ -258,3 +258,14 @@ int p2p_channels_includes(const struct p2p_channels *channels, u8 reg_class,
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int p2p_supported_freq(struct p2p_data *p2p, unsigned int freq)
|
||||
{
|
||||
u8 op_reg_class, op_channel;
|
||||
if (p2p_freq_to_channel(p2p->cfg->country, freq,
|
||||
&op_reg_class, &op_channel) < 0)
|
||||
return 0;
|
||||
return p2p_channels_includes(&p2p->cfg->channels, op_reg_class,
|
||||
op_channel);
|
||||
}
|
||||
|
|
|
@ -1975,6 +1975,14 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
|
|||
new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
|
||||
persistent_group, join, auth, go_intent,
|
||||
freq);
|
||||
if (new_pin == -2) {
|
||||
os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
|
||||
return 25;
|
||||
}
|
||||
if (new_pin == -3) {
|
||||
os_memcpy(buf, "FAIL-CHANNEL-UNSUPPORTED\n", 25);
|
||||
return 25;
|
||||
}
|
||||
if (new_pin < 0)
|
||||
return -1;
|
||||
if (wps_method == WPS_PIN_DISPLAY && pin == NULL) {
|
||||
|
|
|
@ -2532,14 +2532,16 @@ static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s)
|
|||
* initiating Group Owner negotiation
|
||||
* @go_intent: GO Intent or -1 to use default
|
||||
* @freq: Frequency for the group or 0 for auto-selection
|
||||
* Returns: 0 or new PIN (if pin was %NULL) on success, -1 on failure
|
||||
* Returns: 0 or new PIN (if pin was %NULL) on success, -1 on unspecified
|
||||
* failure, -2 on failure due to channel not currently available,
|
||||
* -3 if forced channel is not supported
|
||||
*/
|
||||
int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
|
||||
const char *pin, enum p2p_wps_method wps_method,
|
||||
int persistent_group, int join, int auth, int go_intent,
|
||||
int freq)
|
||||
{
|
||||
int force_freq = 0;
|
||||
int force_freq = 0, oper_freq = 0;
|
||||
u8 bssid[ETH_ALEN];
|
||||
int ret = 0;
|
||||
enum wpa_driver_if_type iftype;
|
||||
|
@ -2585,21 +2587,52 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (freq > 0)
|
||||
force_freq = freq;
|
||||
else if (wpa_s->current_ssid && wpa_drv_get_bssid(wpa_s, bssid) == 0 &&
|
||||
if (wpa_s->current_ssid && wpa_drv_get_bssid(wpa_s, bssid) == 0 &&
|
||||
wpa_s->assoc_freq)
|
||||
force_freq = wpa_s->assoc_freq;
|
||||
oper_freq = wpa_s->assoc_freq;
|
||||
else {
|
||||
force_freq = wpa_drv_shared_freq(wpa_s);
|
||||
if (force_freq < 0)
|
||||
force_freq = 0;
|
||||
oper_freq = wpa_drv_shared_freq(wpa_s);
|
||||
if (oper_freq < 0)
|
||||
oper_freq = 0;
|
||||
}
|
||||
|
||||
if (force_freq > 0) {
|
||||
if (freq > 0) {
|
||||
if (!p2p_supported_freq(wpa_s->global->p2p, freq)) {
|
||||
wpa_printf(MSG_DEBUG, "P2P: The forced channel "
|
||||
"(%u MHz) is not supported for P2P uses",
|
||||
freq);
|
||||
return -3;
|
||||
}
|
||||
|
||||
if (oper_freq > 0 && freq != oper_freq &&
|
||||
!(wpa_s->drv_flags &
|
||||
WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT)) {
|
||||
wpa_printf(MSG_DEBUG, "P2P: Cannot start P2P group "
|
||||
"on %u MHz while connected on another "
|
||||
"channel (%u MHz)", freq, oper_freq);
|
||||
return -2;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "P2P: Trying to force us to use the "
|
||||
"requested channel (%u MHz)", freq);
|
||||
force_freq = freq;
|
||||
} else if (oper_freq > 0 &&
|
||||
!p2p_supported_freq(wpa_s->global->p2p, oper_freq)) {
|
||||
if (!(wpa_s->drv_flags &
|
||||
WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT)) {
|
||||
wpa_printf(MSG_DEBUG, "P2P: Cannot start P2P group "
|
||||
"while connected on non-P2P supported "
|
||||
"channel (%u MHz)", oper_freq);
|
||||
return -2;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "P2P: Current operating channel "
|
||||
"(%u MHz) not available for P2P - try to use "
|
||||
"another channel", oper_freq);
|
||||
force_freq = 0;
|
||||
} else if (oper_freq > 0) {
|
||||
wpa_printf(MSG_DEBUG, "P2P: Trying to force us to use the "
|
||||
"channel we are already using (%u MHz) on another "
|
||||
"interface", force_freq);
|
||||
"interface", oper_freq);
|
||||
force_freq = oper_freq;
|
||||
}
|
||||
|
||||
wpa_s->create_p2p_iface = wpas_p2p_create_iface(wpa_s);
|
||||
|
|
Loading…
Reference in a new issue