}
+static void nan_de_process_elem_container(struct nan_de *de, const u8 *buf,
+ size_t len, const u8 *peer_addr,
+ unsigned int freq, bool p2p)
+{
+ const u8 *elem;
+ u16 elem_len;
+
+ elem = nan_de_get_attr(buf, len, NAN_ATTR_ELEM_CONTAINER, 0);
+ if (!elem)
+ return;
+
+ elem++;
+ elem_len = WPA_GET_LE16(elem);
+ elem += 2;
+ /* Skip the attribute if there is not enough froom for an element. */
+ if (elem_len < 1 + 2)
+ return;
+
+ /* Skip Map ID */
+ elem++;
+ elem_len--;
+
+ if (p2p && de->cb.process_p2p_usd_elems)
+ de->cb.process_p2p_usd_elems(de->cb.ctx, elem, elem_len,
+ peer_addr, freq);
+}
+
+
static void nan_de_rx_publish(struct nan_de *de, struct nan_de_service *srv,
const u8 *peer_addr, u8 instance_id,
u8 req_instance_id, u16 sdea_control,
wpa_hexdump(MSG_MSGDUMP, "NAN: ssi",
ssi, ssi_len);
}
+ nan_de_process_elem_container(de, buf, len, peer_addr,
+ freq, srv->is_p2p);
}
switch (type) {
void (*receive)(void *ctx, int id, int peer_instance_id,
const u8 *ssi, size_t ssi_len,
const u8 *peer_addr);
+
+ void (*process_p2p_usd_elems)(void *ctx, const u8 *buf,
+ u16 buf_len, const u8 *peer_addr,
+ unsigned int freq);
};
struct nan_de * nan_de_init(const u8 *nmi, bool offload, bool ap,
return buf;
}
+
+
+void p2p_process_usd_elems(struct p2p_data *p2p, const u8 *ies, u16 ies_len,
+ const u8 *peer_addr, unsigned int freq)
+{
+ struct p2p_device *dev;
+ struct p2p_message msg;
+ const u8 *p2p_dev_addr;
+
+ os_memset(&msg, 0, sizeof(msg));
+ if (p2p_parse_ies(ies, ies_len, &msg)) {
+ p2p_dbg(p2p, "Failed to parse P2P IE for a device entry");
+ p2p_parse_free(&msg);
+ return;
+ }
+ if (msg.p2p_device_addr)
+ p2p_dev_addr = msg.p2p_device_addr;
+ else
+ p2p_dev_addr = peer_addr;
+
+ dev = p2p_create_device(p2p, p2p_dev_addr);
+ if (!dev) {
+ p2p_parse_free(&msg);
+ p2p_dbg(p2p, "Failed to add a peer P2P Device");
+ return;
+ }
+
+ /* Reset info from old IEs */
+ dev->info.reg_info = 0;
+ os_memset(&dev->info.pairing_config, 0,
+ sizeof(struct p2p_pairing_config));
+
+ os_get_reltime(&dev->last_seen);
+ dev->listen_freq = freq;
+ dev->oper_freq = freq;
+
+ if (msg.capability) {
+ /*
+ * P2P Client Discoverability bit is reserved in all frames
+ * that use this function, so do not change its value here.
+ */
+ dev->info.dev_capab &= P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
+ dev->info.dev_capab |= msg.capability[0] &
+ ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY;
+ dev->info.group_capab = msg.capability[1];
+ }
+
+ if (msg.pcea_info && msg.pcea_info_len >= 2)
+ p2p_process_pcea(p2p, &msg, dev);
+
+ if (msg.pbma_info && msg.pbma_info_len == 2)
+ dev->info.pairing_config.bootstrap_methods =
+ WPA_GET_LE16(msg.pbma_info);
+
+ if (!ether_addr_equal(peer_addr, p2p_dev_addr))
+ os_memcpy(dev->interface_addr, peer_addr, ETH_ALEN);
+
+ p2p_dbg(p2p, "Updated device entry based on USD frame: " MACSTR
+ " dev_capab=0x%x group_capab=0x%x listen_freq=%d",
+ MAC2STR(dev->info.p2p_device_addr), dev->info.dev_capab,
+ dev->info.group_capab, dev->listen_freq);
+
+ p2p->cfg->dev_found(p2p->cfg->cb_ctx, dev->info.p2p_device_addr,
+ &dev->info, !(dev->flags & P2P_DEV_REPORTED_ONCE));
+
+ p2p_parse_free(&msg);
+}
* p2ps_instance - P2PS Application Service Info
*/
struct wpabuf *p2ps_instance;
+
+ /**
+ * pcea_cap_info - Capability info in PCEA
+ */
+ u16 pcea_cap_info;
+
+ /**
+ * The regulatory info encoding for operation in 6 GHz band
+ */
+ u8 reg_info;
+
+ /**
+ * p2p_pairing_config - P2P pairing configuration
+ */
+ struct p2p_pairing_config pairing_config;
};
enum p2p_prov_disc_status {
int p2p_remove_6ghz_channels(struct weighted_pcl *pref_freq_list, int size);
int p2p_channel_to_freq(int op_class, int channel);
struct wpabuf * p2p_usd_elems(struct p2p_data *p2p);
+void p2p_process_usd_elems(struct p2p_data *p2p, const u8 *ies, u16 ies_len,
+ const u8 *peer_addr, unsigned int freq);
#endif /* P2P_H */
int join, int force_freq);
void p2p_reset_pending_pd(struct p2p_data *p2p);
void p2ps_prov_free(struct p2p_data *p2p);
+void p2p_process_pcea(struct p2p_data *p2p, struct p2p_message *msg,
+ struct p2p_device *dev);
/* p2p_invitation.c */
void p2p_process_invitation_req(struct p2p_data *p2p, const u8 *sa,
}
+void p2p_process_pcea(struct p2p_data *p2p, struct p2p_message *msg,
+ struct p2p_device *dev)
+{
+ const u8 *pos, *end;
+ u8 cap_info_len;
+
+ if (!p2p || !dev || !msg || !msg->pcea_info)
+ return;
+
+ pos = msg->pcea_info;
+ end = pos + msg->pcea_info_len;
+ dev->info.pcea_cap_info = WPA_GET_LE16(pos);
+ cap_info_len = dev->info.pcea_cap_info & P2P_PCEA_LEN_MASK;
+
+ /* Field length is (n-1), n in octets */
+ if (end - pos < cap_info_len + 1)
+ return;
+ pos += cap_info_len + 1;
+
+ if (dev->info.pcea_cap_info & P2P_PCEA_6GHZ)
+ dev->support_6ghz = true;
+
+ if (dev->info.pcea_cap_info & P2P_PCEA_REG_INFO) {
+ if (end - pos < 1) {
+ p2p_dbg(p2p, "Truncated PCEA");
+ return;
+ }
+ dev->info.reg_info = *pos++;
+ }
+
+ if (dev->info.pcea_cap_info & P2P_PCEA_PASN_TYPE) {
+ if (end - pos < 1) {
+ p2p_dbg(p2p, "Truncated PCEA");
+ return;
+ }
+ dev->info.pairing_config.pasn_type = *pos++;
+ }
+
+ if (dev->info.pcea_cap_info & P2P_PCEA_PAIRING_CAPABLE)
+ dev->info.pairing_config.pairing_capable = true;
+
+ if (dev->info.pcea_cap_info & P2P_PCEA_PAIRING_SETUP_ENABLED)
+ dev->info.pairing_config.enable_pairing_setup = true;
+
+ if (dev->info.pcea_cap_info & P2P_PCEA_PMK_CACHING) {
+ dev->info.pairing_config.enable_pairing_cache = true;
+ dev->info.pairing_config.enable_pairing_verification = true;
+ }
+}
+
+
void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
const u8 *data, size_t len, int rx_freq)
{
}
+#ifdef CONFIG_P2P
+static void wpas_nan_process_p2p_usd_elems(void *ctx, const u8 *buf,
+ u16 buf_len, const u8 *peer_addr,
+ unsigned int freq)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+
+ wpas_p2p_process_usd_elems(wpa_s, buf, buf_len, peer_addr, freq);
+}
+#endif /* CONFIG_P2P */
+
+
int wpas_nan_usd_init(struct wpa_supplicant *wpa_s)
{
struct nan_callbacks cb;
cb.publish_terminated = wpas_nan_de_publish_terminated;
cb.subscribe_terminated = wpas_nan_de_subscribe_terminated;
cb.receive = wpas_nan_de_receive;
+#ifdef CONFIG_P2P
+ cb.process_p2p_usd_elems = wpas_nan_process_p2p_usd_elems;
+#endif /* CONFIG_P2P */
wpa_s->nan_de = nan_de_init(wpa_s->own_addr, offload, false, &cb);
if (!wpa_s->nan_de)
return NULL;
return p2p_usd_elems(p2p);
}
+
+
+void wpas_p2p_process_usd_elems(struct wpa_supplicant *wpa_s, const u8 *buf,
+ u16 buf_len, const u8 *peer_addr,
+ unsigned int freq)
+{
+ struct p2p_data *p2p = wpa_s->global->p2p;
+
+ if (wpa_s->global->p2p_disabled || !p2p)
+ return;
+ p2p_process_usd_elems(p2p, buf, buf_len, peer_addr, freq);
+}
void wpas_p2p_pbc_overlap_cb(void *eloop_ctx, void *timeout_ctx);
int wpas_p2p_try_edmg_channel(struct wpa_supplicant *wpa_s,
struct p2p_go_neg_results *params);
+void wpas_p2p_process_usd_elems(struct wpa_supplicant *wpa_s, const u8 *buf,
+ u16 buf_len, const u8 *peer_addr,
+ unsigned int freq);
#ifdef CONFIG_P2P