P2P2: Process Element container attribute from NAN SDFs
Process the Element Container attribute from NAN SDF frames and check if P2P attributes are present. Add a P2P peer device entry if the NAN SDF frame has matching service and P2P capabilities. Signed-off-by: Shivani Baranwal <quic_shivbara@quicinc.com>
This commit is contained in:
parent
fa389f2a3b
commit
b4f9742ee2
9 changed files with 201 additions and 0 deletions
|
@ -777,6 +777,34 @@ static void nan_de_get_sdea(const u8 *buf, size_t len, u8 instance_id,
|
|||
}
|
||||
|
||||
|
||||
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,
|
||||
|
@ -1101,6 +1129,8 @@ static void nan_de_rx_sda(struct nan_de *de, const u8 *peer_addr,
|
|||
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) {
|
||||
|
|
|
@ -53,6 +53,10 @@ struct nan_callbacks {
|
|||
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,
|
||||
|
|
|
@ -5841,3 +5841,70 @@ struct wpabuf * p2p_usd_elems(struct p2p_data *p2p)
|
|||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -465,6 +465,21 @@ struct p2p_peer_info {
|
|||
* 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 {
|
||||
|
@ -2504,5 +2519,7 @@ void set_p2p_allow_6ghz(struct p2p_data *p2p, bool value);
|
|||
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 */
|
||||
|
|
|
@ -881,6 +881,8 @@ int p2p_send_prov_disc_req(struct p2p_data *p2p, struct p2p_device *dev,
|
|||
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,
|
||||
|
|
|
@ -563,6 +563,57 @@ do { \
|
|||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -336,6 +336,18 @@ static void wpas_nan_de_receive(void *ctx, int id, int peer_instance_id,
|
|||
}
|
||||
|
||||
|
||||
#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;
|
||||
|
@ -350,6 +362,9 @@ int wpas_nan_usd_init(struct wpa_supplicant *wpa_s)
|
|||
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)
|
||||
|
|
|
@ -10280,3 +10280,15 @@ struct wpabuf * wpas_p2p_usd_elems(struct wpa_supplicant *wpa_s)
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -178,6 +178,9 @@ int wpas_p2p_nfc_tag_enabled(struct wpa_supplicant *wpa_s, int enabled);
|
|||
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
|
||||
|
||||
|
|
Loading…
Reference in a new issue