{
struct p2p_device *dev;
struct p2p_message msg;
+ struct p2p_channels intersection, *channels = NULL;
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
"P2P: Received Invitation Response from " MACSTR,
return;
}
+ if (!msg.channel_list) {
+ wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
+ "P2P: Mandatory Channel List attribute missing in "
+ "Invitation Response from " MACSTR, MAC2STR(sa));
+#ifdef CONFIG_P2P_STRICT
+ p2p_parse_free(&msg);
+ return;
+#endif /* CONFIG_P2P_STRICT */
+ /* Try to survive without peer channel list */
+ channels = &p2p->channels;
+ } else if (p2p_peer_channels_check(p2p, &p2p->channels, dev,
+ msg.channel_list,
+ msg.channel_list_len) < 0) {
+ wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
+ "P2P: No common channels found");
+ p2p_parse_free(&msg);
+ return;
+ } else {
+ p2p_channels_intersect(&p2p->channels, &dev->channels,
+ &intersection);
+ channels = &intersection;
+ }
+
if (p2p->cfg->invitation_result)
p2p->cfg->invitation_result(p2p->cfg->cb_ctx, *msg.status,
- msg.group_bssid);
+ msg.group_bssid, channels);
p2p_parse_free(&msg);
if (s) {
int go = s->mode == WPAS_MODE_P2P_GO;
wpas_p2p_group_add_persistent(
- wpa_s, s, go, go ? op_freq : 0, 0);
+ wpa_s, s, go, go ? op_freq : 0, 0, NULL);
} else if (bssid) {
wpa_s->user_initiated_pd = 0;
wpas_p2p_join(wpa_s, bssid, go_dev_addr,
}
-static void wpas_invitation_result(void *ctx, int status, const u8 *bssid)
+static void wpas_invitation_result(void *ctx, int status, const u8 *bssid,
+ const struct p2p_channels *channels)
{
struct wpa_supplicant *wpa_s = ctx;
struct wpa_ssid *ssid;
wpas_p2p_group_add_persistent(wpa_s, ssid,
ssid->mode == WPAS_MODE_P2P_GO,
wpa_s->p2p_persistent_go_freq,
- wpa_s->p2p_go_ht40);
+ wpa_s->p2p_go_ht40, channels);
}
}
+static int freq_included(const struct p2p_channels *channels, unsigned int freq)
+{
+ if (channels == NULL)
+ return 1; /* Assume no restrictions */
+ return p2p_channels_includes_freq(channels, freq);
+}
+
+
static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s,
struct p2p_go_neg_results *params,
- int freq, int ht40)
+ int freq, int ht40,
+ const struct p2p_channels *channels)
{
u8 bssid[ETH_ALEN];
int res;
params->role_go = 1;
params->ht40 = ht40;
if (freq) {
+ if (!freq_included(channels, freq)) {
+ wpa_printf(MSG_DEBUG, "P2P: Forced GO freq %d MHz not "
+ "accepted", freq);
+ return -1;
+ }
wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on forced "
"frequency %d MHz", freq);
params->freq = freq;
} else if (wpa_s->conf->p2p_oper_reg_class == 81 &&
wpa_s->conf->p2p_oper_channel >= 1 &&
- wpa_s->conf->p2p_oper_channel <= 11) {
+ wpa_s->conf->p2p_oper_channel <= 11 &&
+ freq_included(channels,
+ 2407 + 5 * wpa_s->conf->p2p_oper_channel)) {
params->freq = 2407 + 5 * wpa_s->conf->p2p_oper_channel;
wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on configured "
"frequency %d MHz", params->freq);
- } else if (wpa_s->conf->p2p_oper_reg_class == 115 ||
- wpa_s->conf->p2p_oper_reg_class == 116 ||
- wpa_s->conf->p2p_oper_reg_class == 117 ||
- wpa_s->conf->p2p_oper_reg_class == 124 ||
- wpa_s->conf->p2p_oper_reg_class == 126 ||
- wpa_s->conf->p2p_oper_reg_class == 127) {
+ } else if ((wpa_s->conf->p2p_oper_reg_class == 115 ||
+ wpa_s->conf->p2p_oper_reg_class == 116 ||
+ wpa_s->conf->p2p_oper_reg_class == 117 ||
+ wpa_s->conf->p2p_oper_reg_class == 124 ||
+ wpa_s->conf->p2p_oper_reg_class == 126 ||
+ wpa_s->conf->p2p_oper_reg_class == 127) &&
+ freq_included(channels,
+ 5000 + 5 * wpa_s->conf->p2p_oper_channel)) {
params->freq = 5000 + 5 * wpa_s->conf->p2p_oper_channel;
wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on configured "
"frequency %d MHz", params->freq);
} else if (wpa_s->conf->p2p_oper_channel == 0 &&
wpa_s->best_overall_freq > 0 &&
p2p_supported_freq(wpa_s->global->p2p,
- wpa_s->best_overall_freq)) {
+ wpa_s->best_overall_freq) &&
+ freq_included(channels, wpa_s->best_overall_freq)) {
params->freq = wpa_s->best_overall_freq;
wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on best overall "
"channel %d MHz", params->freq);
} else if (wpa_s->conf->p2p_oper_channel == 0 &&
wpa_s->best_24_freq > 0 &&
p2p_supported_freq(wpa_s->global->p2p,
- wpa_s->best_24_freq)) {
+ wpa_s->best_24_freq) &&
+ freq_included(channels, wpa_s->best_24_freq)) {
params->freq = wpa_s->best_24_freq;
wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on best 2.4 GHz "
"channel %d MHz", params->freq);
} else if (wpa_s->conf->p2p_oper_channel == 0 &&
wpa_s->best_5_freq > 0 &&
p2p_supported_freq(wpa_s->global->p2p,
- wpa_s->best_5_freq)) {
+ wpa_s->best_5_freq) &&
+ freq_included(channels, wpa_s->best_5_freq)) {
params->freq = wpa_s->best_5_freq;
wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on best 5 GHz "
"channel %d MHz", params->freq);
for (chan = 0; chan < 11; chan++) {
params->freq = 2412 + chan * 5;
if (!wpas_p2p_disallowed_freq(wpa_s->global,
- params->freq))
+ params->freq) &&
+ freq_included(channels, params->freq))
break;
}
if (chan == 11) {
wpa_printf(MSG_DEBUG, "P2P: Force GO on the channel we are "
"already using");
params->freq = wpa_s->assoc_freq;
+ if (!freq_included(channels, params->freq)) {
+ wpa_printf(MSG_DEBUG, "P2P: Forced GO freq %d MHz not "
+ "accepted", params->freq);
+ return -1;
+ }
}
res = wpa_drv_shared_freq(wpa_s);
wpa_printf(MSG_DEBUG, "P2P: Force GO on the channel we are "
"already using on a shared interface");
params->freq = res;
+ if (!freq_included(channels, params->freq)) {
+ wpa_printf(MSG_DEBUG, "P2P: Forced GO freq %d MHz not "
+ "accepted", params->freq);
+ return -1;
+ }
} else if (res > 0 && freq != res &&
!(wpa_s->drv_flags &
WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT)) {
return -1;
}
- if (wpas_p2p_init_go_params(wpa_s, ¶ms, freq, ht40))
+ if (wpas_p2p_init_go_params(wpa_s, ¶ms, freq, ht40, NULL))
return -1;
if (params.freq &&
!p2p_supported_freq(wpa_s->global->p2p, params.freq)) {
int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid, int addr_allocated,
- int freq, int ht40)
+ int freq, int ht40,
+ const struct p2p_channels *channels)
{
struct p2p_go_neg_results params;
int go = 0;
if (ssid->mode != WPAS_MODE_P2P_GO)
return -1;
- if (wpas_p2p_init_go_params(wpa_s, ¶ms, freq, ht40))
+ if (wpas_p2p_init_go_params(wpa_s, ¶ms, freq, ht40, channels))
return -1;
params.role_go = 1;