aboutsummaryrefslogtreecommitdiff
path: root/contrib/wpa/src/p2p/p2p.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/wpa/src/p2p/p2p.c')
-rw-r--r--contrib/wpa/src/p2p/p2p.c147
1 files changed, 129 insertions, 18 deletions
diff --git a/contrib/wpa/src/p2p/p2p.c b/contrib/wpa/src/p2p/p2p.c
index a08ba02686c6..9ac505735cbb 100644
--- a/contrib/wpa/src/p2p/p2p.c
+++ b/contrib/wpa/src/p2p/p2p.c
@@ -428,7 +428,9 @@ static struct p2p_device * p2p_create_device(struct p2p_data *p2p,
oldest = dev;
}
if (count + 1 > p2p->cfg->max_peers && oldest) {
- p2p_dbg(p2p, "Remove oldest peer entry to make room for a new peer");
+ p2p_dbg(p2p,
+ "Remove oldest peer entry to make room for a new peer "
+ MACSTR, MAC2STR(oldest->info.p2p_device_addr));
dl_list_del(&oldest->list);
p2p_device_free(p2p, oldest);
}
@@ -453,6 +455,8 @@ static void p2p_copy_client_info(struct p2p_device *dev,
dev->info.config_methods = cli->config_methods;
os_memcpy(dev->info.pri_dev_type, cli->pri_dev_type, 8);
dev->info.wps_sec_dev_type_list_len = 8 * cli->num_sec_dev_types;
+ if (dev->info.wps_sec_dev_type_list_len > WPS_SEC_DEV_TYPE_MAX_LEN)
+ dev->info.wps_sec_dev_type_list_len = WPS_SEC_DEV_TYPE_MAX_LEN;
os_memcpy(dev->info.wps_sec_dev_type_list, cli->sec_dev_types,
dev->info.wps_sec_dev_type_list_len);
}
@@ -663,6 +667,8 @@ static void p2p_update_peer_vendor_elems(struct p2p_device *dev, const u8 *ies,
if (wpabuf_resize(&dev->info.vendor_elems, 2 + len) < 0)
break;
wpabuf_put_data(dev->info.vendor_elems, pos - 2, 2 + len);
+ if (wpabuf_size(dev->info.vendor_elems) > 2000)
+ break;
}
}
@@ -1029,7 +1035,7 @@ static void p2p_search(struct p2p_data *p2p)
res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, type, freq,
p2p->num_req_dev_types, p2p->req_dev_types,
- p2p->find_dev_id, pw_id);
+ p2p->find_dev_id, pw_id, p2p->include_6ghz);
if (res < 0) {
p2p_dbg(p2p, "Scan request schedule failed");
p2p_continue_find(p2p);
@@ -1153,7 +1159,7 @@ int p2p_find(struct p2p_data *p2p, unsigned int timeout,
enum p2p_discovery_type type,
unsigned int num_req_dev_types, const u8 *req_dev_types,
const u8 *dev_id, unsigned int search_delay,
- u8 seek_count, const char **seek, int freq)
+ u8 seek_count, const char **seek, int freq, bool include_6ghz)
{
int res;
struct os_reltime start;
@@ -1178,7 +1184,7 @@ int p2p_find(struct p2p_data *p2p, unsigned int timeout,
p2p->find_dev_id = p2p->find_dev_id_buf;
} else
p2p->find_dev_id = NULL;
-
+ p2p->include_6ghz = p2p_wfd_enabled(p2p) && include_6ghz;
if (seek_count == 0 || !seek) {
/* Not an ASP search */
p2p->p2ps_seek = 0;
@@ -1254,7 +1260,8 @@ int p2p_find(struct p2p_data *p2p, unsigned int timeout,
P2P_SCAN_SPECIFIC, freq,
p2p->num_req_dev_types,
p2p->req_dev_types, dev_id,
- DEV_PW_DEFAULT);
+ DEV_PW_DEFAULT,
+ p2p->include_6ghz);
break;
}
/* fall through */
@@ -1262,13 +1269,13 @@ int p2p_find(struct p2p_data *p2p, unsigned int timeout,
res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_FULL, 0,
p2p->num_req_dev_types,
p2p->req_dev_types, dev_id,
- DEV_PW_DEFAULT);
+ DEV_PW_DEFAULT, p2p->include_6ghz);
break;
case P2P_FIND_ONLY_SOCIAL:
res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_SOCIAL, 0,
p2p->num_req_dev_types,
p2p->req_dev_types, dev_id,
- DEV_PW_DEFAULT);
+ DEV_PW_DEFAULT, p2p->include_6ghz);
break;
default:
return -1;
@@ -1390,8 +1397,8 @@ static int p2p_prepare_channel_pref(struct p2p_data *p2p,
p2p->channels.reg_class[0].reg_class = p2p->op_reg_class;
p2p->channels.reg_class[0].channel[0] = p2p->op_channel;
} else {
- os_memcpy(&p2p->channels, &p2p->cfg->channels,
- sizeof(struct p2p_channels));
+ p2p_copy_channels(&p2p->channels, &p2p->cfg->channels,
+ p2p->allow_6ghz);
}
return 0;
@@ -1404,6 +1411,8 @@ static void p2p_prepare_channel_best(struct p2p_data *p2p)
const int op_classes_5ghz[] = { 124, 125, 115, 0 };
const int op_classes_ht40[] = { 126, 127, 116, 117, 0 };
const int op_classes_vht[] = { 128, 0 };
+ const int op_classes_edmg[] = { 181, 182, 183, 0 };
+ const int op_classes_6ghz[] = { 131, 0 };
p2p_dbg(p2p, "Prepare channel best");
@@ -1435,6 +1444,17 @@ static void p2p_prepare_channel_best(struct p2p_data *p2p)
p2p_dbg(p2p, "Select first pref_chan entry as operating channel preference");
p2p->op_reg_class = p2p->cfg->pref_chan[0].op_class;
p2p->op_channel = p2p->cfg->pref_chan[0].chan;
+ } else if (p2p_channel_select(&p2p->cfg->channels, op_classes_edmg,
+ &p2p->op_reg_class, &p2p->op_channel) ==
+ 0) {
+ p2p_dbg(p2p, "Select possible EDMG channel (op_class %u channel %u) as operating channel preference",
+ p2p->op_reg_class, p2p->op_channel);
+ } else if (p2p->allow_6ghz &&
+ (p2p_channel_select(&p2p->cfg->channels, op_classes_6ghz,
+ &p2p->op_reg_class, &p2p->op_channel) ==
+ 0)) {
+ p2p_dbg(p2p, "Select possible 6 GHz channel (op_class %u channel %u) as operating channel preference",
+ p2p->op_reg_class, p2p->op_channel);
} else if (p2p_channel_select(&p2p->cfg->channels, op_classes_vht,
&p2p->op_reg_class, &p2p->op_channel) ==
0) {
@@ -1472,8 +1492,7 @@ static void p2p_prepare_channel_best(struct p2p_data *p2p)
p2p->op_channel, p2p->op_reg_class);
}
- os_memcpy(&p2p->channels, &p2p->cfg->channels,
- sizeof(struct p2p_channels));
+ p2p_copy_channels(&p2p->channels, &p2p->cfg->channels, p2p->allow_6ghz);
}
@@ -1556,9 +1575,10 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
p2p_dbg(p2p, "Request to start group negotiation - peer=" MACSTR
" GO Intent=%d Intended Interface Address=" MACSTR
" wps_method=%d persistent_group=%d pd_before_go_neg=%d "
- "oob_pw_id=%u",
+ "oob_pw_id=%u allow_6ghz=%d",
MAC2STR(peer_addr), go_intent, MAC2STR(own_interface_addr),
- wps_method, persistent_group, pd_before_go_neg, oob_pw_id);
+ wps_method, persistent_group, pd_before_go_neg, oob_pw_id,
+ p2p->allow_6ghz);
dev = p2p_get_device(p2p, peer_addr);
if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
@@ -1656,9 +1676,9 @@ int p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr,
p2p_dbg(p2p, "Request to authorize group negotiation - peer=" MACSTR
" GO Intent=%d Intended Interface Address=" MACSTR
- " wps_method=%d persistent_group=%d oob_pw_id=%u",
+ " wps_method=%d persistent_group=%d oob_pw_id=%u allow_6ghz=%d",
MAC2STR(peer_addr), go_intent, MAC2STR(own_interface_addr),
- wps_method, persistent_group, oob_pw_id);
+ wps_method, persistent_group, oob_pw_id, p2p->allow_6ghz);
dev = p2p_get_device(p2p, peer_addr);
if (dev == NULL) {
@@ -2907,6 +2927,14 @@ void p2p_group_formation_failed(struct p2p_data *p2p)
}
+bool is_p2p_6ghz_disabled(struct p2p_data *p2p)
+{
+ if (p2p)
+ return p2p->cfg->p2p_6ghz_disable;
+ return false;
+}
+
+
struct p2p_data * p2p_init(const struct p2p_config *cfg)
{
struct p2p_data *p2p;
@@ -3451,12 +3479,18 @@ static void p2p_prov_disc_resp_cb(struct p2p_data *p2p, int success)
p2p->pending_action_state = P2P_NO_PENDING_ACTION;
- if (!success)
+ if (!success) {
+ if (p2p->state == P2P_SEARCH)
+ p2p_continue_find(p2p);
return;
+ }
if (!p2p->cfg->prov_disc_resp_cb ||
- p2p->cfg->prov_disc_resp_cb(p2p->cfg->cb_ctx) < 1)
+ p2p->cfg->prov_disc_resp_cb(p2p->cfg->cb_ctx) < 1) {
+ if (p2p->state == P2P_SEARCH)
+ p2p_continue_find(p2p);
return;
+ }
p2p_dbg(p2p,
"Post-Provision Discovery operations started - do not try to continue other P2P operations");
@@ -3490,12 +3524,17 @@ int p2p_scan_res_handler(struct p2p_data *p2p, const u8 *bssid, int freq,
}
-void p2p_scan_res_handled(struct p2p_data *p2p)
+void p2p_scan_res_handled(struct p2p_data *p2p, unsigned int delay)
{
if (!p2p->p2p_scan_running) {
p2p_dbg(p2p, "p2p_scan was not running, but scan results received");
}
p2p->p2p_scan_running = 0;
+
+ /* Use this delay only when p2p_find doesn't set it */
+ if (!p2p->search_delay)
+ p2p->search_delay = delay;
+
eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
if (p2p_run_after_scan(p2p))
@@ -3962,6 +4001,11 @@ static void p2p_timeout_wait_peer_idle(struct p2p_data *p2p)
}
p2p_dbg(p2p, "Go to Listen state while waiting for the peer to become ready for GO Negotiation");
+ p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
+ if (p2p->pending_listen_freq) {
+ p2p_dbg(p2p, "Clear pending_listen_freq for %s", __func__);
+ p2p->pending_listen_freq = 0;
+ }
p2p_set_state(p2p, P2P_WAIT_PEER_CONNECT);
p2p_listen_in_find(p2p, 0);
}
@@ -4915,6 +4959,7 @@ int p2p_send_action(struct p2p_data *p2p, unsigned int freq, const u8 *dst,
res = p2p->cfg->send_action(p2p->cfg->cb_ctx, freq, dst, src, bssid,
buf, len, wait_time, &scheduled);
if (res == 0 && scheduled && p2p->in_listen && freq > 0 &&
+ p2p->drv_in_listen > 0 &&
(unsigned int) p2p->drv_in_listen != freq) {
p2p_dbg(p2p,
"Stop listen on %d MHz to allow a frame to be sent immediately on %d MHz",
@@ -5538,3 +5583,69 @@ struct wpabuf * p2p_build_probe_resp_template(struct p2p_data *p2p,
return buf;
}
+
+
+bool p2p_is_peer_6ghz_capab(struct p2p_data *p2p, const u8 *addr)
+{
+ struct p2p_device *dev;
+
+ dev = p2p_get_device(p2p, addr);
+ if (!dev)
+ return false;
+
+ return !!(dev->info.dev_capab & P2P_DEV_CAPAB_6GHZ_BAND_CAPABLE);
+}
+
+
+void p2p_set_6ghz_dev_capab(struct p2p_data *p2p, bool allow_6ghz)
+{
+ p2p->p2p_6ghz_capable = allow_6ghz;
+ p2p->allow_6ghz = allow_6ghz;
+ p2p_dbg(p2p, "Set 6 GHz capability to %d", allow_6ghz);
+
+ if (allow_6ghz)
+ p2p->dev_capab |= P2P_DEV_CAPAB_6GHZ_BAND_CAPABLE;
+ else
+ p2p->dev_capab &= ~P2P_DEV_CAPAB_6GHZ_BAND_CAPABLE;
+}
+
+
+bool is_p2p_6ghz_capable(struct p2p_data *p2p)
+{
+ return p2p->p2p_6ghz_capable;
+}
+
+
+bool p2p_wfd_enabled(struct p2p_data *p2p)
+{
+#ifdef CONFIG_WIFI_DISPLAY
+ return p2p->wfd_ie_probe_req != NULL;
+#else /* CONFIG_WIFI_DISPLAY */
+ return false;
+#endif /* CONFIG_WIFI_DISPLAY */
+}
+
+
+bool p2p_peer_wfd_enabled(struct p2p_data *p2p, const u8 *peer_addr)
+{
+#ifdef CONFIG_WIFI_DISPLAY
+ struct p2p_device *dev;
+
+ dev = p2p_get_device(p2p, peer_addr);
+ return dev && dev->info.wfd_subelems != NULL;
+#else /* CONFIG_WIFI_DISPLAY */
+ return false;
+#endif /* CONFIG_WIFI_DISPLAY */
+}
+
+
+bool is_p2p_allow_6ghz(struct p2p_data *p2p)
+{
+ return p2p->allow_6ghz;
+}
+
+
+void set_p2p_allow_6ghz(struct p2p_data *p2p, bool value)
+{
+ p2p->allow_6ghz = value;
+}