/** * p2p_parse_ies - Parse P2P message IEs (both WPS and P2P IE) * @data: IEs from the message * @len: Length of data buffer in octets * @msg: Buffer for returning parsed attributes * Returns: 0 on success, -1 on failure * * Note: Caller is responsible for clearing the msg data structure before * calling this function. * * Note: Caller must free temporary memory allocations by calling * p2p_parse_free() when the parsed data is not needed anymore. */ int p2p_parse_ies(const u8 *data, size_t len, struct p2p_message *msg) { struct ieee802_11_elems elems; ieee802_11_parse_elems(data, len, &elems, 0); if (elems.ds_params && elems.ds_params_len >= 1) msg->ds_params = elems.ds_params; if (elems.ssid) msg->ssid = elems.ssid - 2; msg->wps_attributes = ieee802_11_vendor_ie_concat(data, len, WPS_DEV_OUI_WFA); if (msg->wps_attributes && p2p_parse_wps_ie(msg->wps_attributes, msg)) { p2p_parse_free(msg); return -1; } msg->p2p_attributes = ieee802_11_vendor_ie_concat(data, len, P2P_IE_VENDOR_TYPE); if (msg->p2p_attributes && p2p_parse_p2p_ie(msg->p2p_attributes, msg)) { wpa_printf(MSG_DEBUG, "P2P: Failed to parse P2P IE data"); if (msg->p2p_attributes) wpa_hexdump_buf(MSG_MSGDUMP, "P2P: P2P IE data", msg->p2p_attributes); p2p_parse_free(msg); return -1; } return 0; }
int p2p_parse_ies_separate(const u8 *wsc, size_t wsc_len, const u8 *p2p, size_t p2p_len, struct p2p_message *msg) { os_memset(msg, 0, sizeof(*msg)); msg->wps_attributes = wpabuf_alloc_copy(wsc, wsc_len); if (msg->wps_attributes && p2p_parse_wps_ie(msg->wps_attributes, msg)) { p2p_parse_free(msg); return -1; } msg->p2p_attributes = wpabuf_alloc_copy(p2p, p2p_len); if (msg->p2p_attributes && p2p_parse_p2p_ie(msg->p2p_attributes, msg)) { wpa_printf(MSG_DEBUG, "P2P: Failed to parse P2P IE data"); if (msg->p2p_attributes) wpa_hexdump_buf(MSG_MSGDUMP, "P2P: P2P IE data", msg->p2p_attributes); p2p_parse_free(msg); return -1; } return 0; }
u8 p2p_get_group_capab(const struct wpabuf *p2p_ie) { struct p2p_message msg; os_memset(&msg, 0, sizeof(msg)); if (p2p_parse_p2p_ie(p2p_ie, &msg)) return 0; if (!msg.capability) return 0; return msg.capability[1]; }
int p2p_get_cross_connect_disallowed(const struct wpabuf *p2p_ie) { struct p2p_message msg; os_memset(&msg, 0, sizeof(msg)); if (p2p_parse_p2p_ie(p2p_ie, &msg)) return 0; if (!msg.manageability) return 0; return !(msg.manageability[0] & P2P_MAN_CROSS_CONNECTION_PERMITTED); }
const u8 * p2p_get_go_dev_addr(const struct wpabuf *p2p_ie) { struct p2p_message msg; os_memset(&msg, 0, sizeof(msg)); if (p2p_parse_p2p_ie(p2p_ie, &msg)) return NULL; if (msg.p2p_device_addr) return msg.p2p_device_addr; if (msg.device_id) return msg.device_id; return NULL; }
/** * p2p_build_client_info - Build P2P Client Info Descriptor * @addr: MAC address of the peer device * @p2p_ie: P2P IE from (Re)Association Request * @dev_capab: Buffer for returning Device Capability * @dev_addr: Buffer for returning P2P Device Address * Returns: P2P Client Info Descriptor or %NULL on failure * * This function builds P2P Client Info Descriptor based on the information * available from (Re)Association Request frame. Group owner can use this to * build the P2P Group Info attribute for Probe Response frames. */ static struct wpabuf * p2p_build_client_info(const u8 *addr, struct wpabuf *p2p_ie, u8 *dev_capab, u8 *dev_addr) { const u8 *spos; struct p2p_message msg; u8 *len_pos; struct wpabuf *buf; if (p2p_ie == NULL) return NULL; os_memset(&msg, 0, sizeof(msg)); if (p2p_parse_p2p_ie(p2p_ie, &msg) || msg.capability == NULL || msg.p2p_device_info == NULL) return NULL; buf = wpabuf_alloc(ETH_ALEN + 1 + 1 + msg.p2p_device_info_len); if (buf == NULL) return NULL; *dev_capab = msg.capability[0]; os_memcpy(dev_addr, msg.p2p_device_addr, ETH_ALEN); spos = msg.p2p_device_info; /* P2P Device address */ /* P2P Client Info Descriptor */ /* Length to be set */ len_pos = wpabuf_put(buf, 1); /* P2P Device address */ wpabuf_put_data(buf, spos, ETH_ALEN); /* P2P Interface address */ wpabuf_put_data(buf, addr, ETH_ALEN); /* Device Capability Bitmap */ wpabuf_put_u8(buf, msg.capability[0]); /* * Config Methods, Primary Device Type, Number of Secondary Device * Types, Secondary Device Type List, Device Name copied from * Device Info */ wpabuf_put_data(buf, spos + ETH_ALEN, msg.p2p_device_info_len - ETH_ALEN); *len_pos = wpabuf_len(buf) - 1; return buf; }
/** * p2p_parse_ies - Parse P2P message IEs (both WPS and P2P IE) * @data: IEs from the message * @len: Length of data buffer in octets * @msg: Buffer for returning parsed attributes * Returns: 0 on success, -1 on failure * * Note: Caller is responsible for clearing the msg data structure before * calling this function. * * Note: Caller must free temporary memory allocations by calling * p2p_parse_free() when the parsed data is not needed anymore. */ int p2p_parse_ies(const u8 *data, size_t len, struct p2p_message *msg) { struct ieee802_11_elems elems; ieee802_11_parse_elems(data, len, &elems, 0); if (elems.ds_params) msg->ds_params = elems.ds_params; if (elems.ssid) msg->ssid = elems.ssid - 2; msg->wps_attributes = ieee802_11_vendor_ie_concat(data, len, WPS_DEV_OUI_WFA); if (msg->wps_attributes && p2p_parse_wps_ie(msg->wps_attributes, msg)) { p2p_parse_free(msg); return -1; } msg->p2p_attributes = ieee802_11_vendor_ie_concat(data, len, P2P_IE_VENDOR_TYPE); if (msg->p2p_attributes && p2p_parse_p2p_ie(msg->p2p_attributes, msg)) { wpa_printf(MSG_DEBUG, "P2P: Failed to parse P2P IE data"); if (msg->p2p_attributes) wpa_hexdump_buf(MSG_MSGDUMP, "P2P: P2P IE data", msg->p2p_attributes); p2p_parse_free(msg); return -1; } #ifdef CONFIG_WIFI_DISPLAY if (elems.wfd) { msg->wfd_subelems = ieee802_11_vendor_ie_concat( data, len, WFD_IE_VENDOR_TYPE); } #endif /* CONFIG_WIFI_DISPLAY */ msg->pref_freq_list = elems.pref_freq_list; msg->pref_freq_list_len = elems.pref_freq_list_len; return 0; }
int p2p_group_match_dev_id(struct p2p_group *group, struct wpabuf *p2p) { struct p2p_group_member *m; struct p2p_message msg; os_memset(&msg, 0, sizeof(msg)); if (p2p_parse_p2p_ie(p2p, &msg)) return 1; /* Failed to parse - assume no filter on Device ID */ if (!msg.device_id) return 1; /* No filter on Device ID */ if (os_memcmp(msg.device_id, group->p2p->cfg->dev_addr, ETH_ALEN) == 0) return 1; /* Match with our P2P Device Address */ for (m = group->members; m; m = m->next) { if (os_memcmp(msg.device_id, m->dev_addr, ETH_ALEN) == 0) return 1; /* Match with group client P2P Device Address */ } /* No match with Device ID */ return 0; }
/** * p2p_attr_text - Build text format description of P2P IE attributes * @data: P2P IE contents * @buf: Buffer for returning text * @end: Pointer to the end of the buf area * Returns: Number of octets written to the buffer or -1 on faikure * * This function can be used to parse P2P IE contents into text format * field=value lines. */ int p2p_attr_text(struct wpabuf *data, char *buf, char *end) { struct p2p_message msg; char *pos = buf; int ret; os_memset(&msg, 0, sizeof(msg)); if (p2p_parse_p2p_ie(data, &msg)) return -1; if (msg.capability) { ret = os_snprintf(pos, end - pos, "p2p_dev_capab=0x%x\n" "p2p_group_capab=0x%x\n", msg.capability[0], msg.capability[1]); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; } if (msg.pri_dev_type) { char devtype[WPS_DEV_TYPE_BUFSIZE]; ret = os_snprintf(pos, end - pos, "p2p_primary_device_type=%s\n", wps_dev_type_bin2str(msg.pri_dev_type, devtype, sizeof(devtype))); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; } ret = os_snprintf(pos, end - pos, "p2p_device_name=%s\n", msg.device_name); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; if (msg.p2p_device_addr) { ret = os_snprintf(pos, end - pos, "p2p_device_addr=" MACSTR "\n", MAC2STR(msg.p2p_device_addr)); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; } ret = os_snprintf(pos, end - pos, "p2p_config_methods=0x%x\n", msg.config_methods); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; ret = p2p_group_info_text(msg.group_info, msg.group_info_len, pos, end); if (ret < 0) return pos - buf; pos += ret; return pos - buf; }