X-Git-Url: http://www.project-moonshot.org/gitweb/?p=mech_eap.git;a=blobdiff_plain;f=libeap%2Fsrc%2Fp2p%2Fp2p_parse.c;h=bd1e68bd424171a87423f38340024ab3db884259;hp=25337a557ef2f2af2e97962e2e86058ff72a3c14;hb=4f319dde67a76fe0aaf33f6d2788968012584ada;hpb=ed09b5e64dd485851310307979d5eed14678087b diff --git a/libeap/src/p2p/p2p_parse.c b/libeap/src/p2p/p2p_parse.c index 25337a5..bd1e68b 100644 --- a/libeap/src/p2p/p2p_parse.c +++ b/libeap/src/p2p/p2p_parse.c @@ -2,14 +2,8 @@ * P2P - IE parser * Copyright (c) 2009-2010, Atheros Communications * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. + * This software may be distributed under the terms of the BSD license. + * See README for more details. */ #include "includes.h" @@ -155,7 +149,8 @@ static int p2p_parse_attribute(u8 id, const u8 *data, u16 len, pos += 2; nlen = WPA_GET_BE16(pos); pos += 2; - if (data + len - pos < (int) nlen || nlen > 32) { + if (data + len - pos < (int) nlen || + nlen > WPS_DEV_NAME_MAX_LEN) { wpa_printf(MSG_DEBUG, "P2P: Invalid Device Name " "length %d (buf len %d)", (int) nlen, (int) (data + len - pos)); @@ -166,7 +161,7 @@ static int p2p_parse_attribute(u8 id, const u8 *data, u16 len, for (i = 0; i < nlen; i++) { if (msg->device_name[i] == '\0') break; - if (msg->device_name[i] < 32) + if (is_ctrl_char(msg->device_name[i])) msg->device_name[i] = '_'; } wpa_printf(MSG_DEBUG, "P2P: * Device Info: addr " MACSTR @@ -208,7 +203,7 @@ static int p2p_parse_attribute(u8 id, const u8 *data, u16 len, MAC2STR(msg->group_bssid)); break; case P2P_ATTR_GROUP_ID: - if (len < ETH_ALEN || len > ETH_ALEN + 32) { + if (len < ETH_ALEN || len > ETH_ALEN + SSID_MAX_LEN) { wpa_printf(MSG_DEBUG, "P2P: Invalid P2P Group ID " "attribute length %d", len); return -1; @@ -273,6 +268,125 @@ static int p2p_parse_attribute(u8 id, const u8 *data, u16 len, wpa_printf(MSG_DEBUG, "P2P: * Minor Reason Code: %u", *msg->minor_reason_code); break; + case P2P_ATTR_OOB_GO_NEG_CHANNEL: + if (len < 6) { + wpa_printf(MSG_DEBUG, "P2P: Too short OOB GO Neg " + "Channel attribute (length %d)", len); + return -1; + } + msg->oob_go_neg_channel = data; + wpa_printf(MSG_DEBUG, "P2P: * OOB GO Neg Channel: " + "Country %c%c(0x%02x) Operating Class %d " + "Channel Number %d Role %d", + data[0], data[1], data[2], data[3], data[4], + data[5]); + break; + case P2P_ATTR_SERVICE_HASH: + if (len < P2PS_HASH_LEN) { + wpa_printf(MSG_DEBUG, + "P2P: Too short Service Hash (length %u)", + len); + return -1; + } + msg->service_hash_count = len / P2PS_HASH_LEN; + msg->service_hash = data; + wpa_hexdump(MSG_DEBUG, "P2P: * Service Hash(s)", data, len); + break; + case P2P_ATTR_SESSION_INFORMATION_DATA: + msg->session_info = data; + msg->session_info_len = len; + wpa_printf(MSG_DEBUG, "P2P: * Service Instance: %u bytes - %p", + len, data); + break; + case P2P_ATTR_CONNECTION_CAPABILITY: + if (len < 1) { + wpa_printf(MSG_DEBUG, + "P2P: Too short Connection Capability (length %u)", + len); + return -1; + } + msg->conn_cap = data; + wpa_printf(MSG_DEBUG, "P2P: * Connection Capability: 0x%x", + *msg->conn_cap); + break; + case P2P_ATTR_ADVERTISEMENT_ID: + if (len < 10) { + wpa_printf(MSG_DEBUG, + "P2P: Too short Advertisement ID (length %u)", + len); + return -1; + } + msg->adv_id = data; + msg->adv_mac = &data[sizeof(u32)]; + wpa_printf(MSG_DEBUG, "P2P: * Advertisement ID %x", + WPA_GET_LE32(data)); + break; + case P2P_ATTR_ADVERTISED_SERVICE: + if (len < 8) { + wpa_printf(MSG_DEBUG, + "P2P: Too short Service Instance (length %u)", + len); + return -1; + } + msg->adv_service_instance = data; + msg->adv_service_instance_len = len; + if (len <= 255 + 8) { + char str[256]; + u8 namelen; + + namelen = data[6]; + if (namelen > len - 7) + break; + os_memcpy(str, &data[7], namelen); + str[namelen] = '\0'; + wpa_printf(MSG_DEBUG, "P2P: * Service Instance: %x-%s", + WPA_GET_LE32(data), str); + } else { + wpa_printf(MSG_DEBUG, "P2P: * Service Instance: %p", + data); + } + break; + case P2P_ATTR_SESSION_ID: + if (len < sizeof(u32) + ETH_ALEN) { + wpa_printf(MSG_DEBUG, + "P2P: Too short Session ID Info (length %u)", + len); + return -1; + } + msg->session_id = data; + msg->session_mac = &data[sizeof(u32)]; + wpa_printf(MSG_DEBUG, "P2P: * Session ID: %x " MACSTR, + WPA_GET_LE32(data), MAC2STR(msg->session_mac)); + break; + case P2P_ATTR_FEATURE_CAPABILITY: + if (!len) { + wpa_printf(MSG_DEBUG, + "P2P: Too short Feature Capability (length %u)", + len); + return -1; + } + msg->feature_cap = data; + msg->feature_cap_len = len; + wpa_printf(MSG_DEBUG, "P2P: * Feature Cap (length=%u)", len); + break; + case P2P_ATTR_PERSISTENT_GROUP: + { + if (len < ETH_ALEN || len > ETH_ALEN + SSID_MAX_LEN) { + wpa_printf(MSG_DEBUG, + "P2P: Invalid Persistent Group Info (length %u)", + len); + return -1; + } + + msg->persistent_dev = data; + msg->persistent_ssid_len = len - ETH_ALEN; + msg->persistent_ssid = &data[ETH_ALEN]; + wpa_printf(MSG_DEBUG, "P2P: * Persistent Group: " MACSTR " %s", + MAC2STR(msg->persistent_dev), + wpa_ssid_txt(msg->persistent_ssid, + msg->persistent_ssid_len)); + break; + } default: wpa_printf(MSG_DEBUG, "P2P: Skipped unknown attribute %d " "(length %d)", id, len); @@ -301,23 +415,27 @@ int p2p_parse_p2p_ie(const struct wpabuf *buf, struct p2p_message *msg) while (pos < end) { u16 attr_len; - if (pos + 2 >= end) { + u8 id; + + if (end - pos < 3) { wpa_printf(MSG_DEBUG, "P2P: Invalid P2P attribute"); return -1; } - attr_len = WPA_GET_LE16(pos + 1); + id = *pos++; + attr_len = WPA_GET_LE16(pos); + pos += 2; wpa_printf(MSG_DEBUG, "P2P: Attribute %d length %u", - pos[0], attr_len); - if (pos + 3 + attr_len > end) { + id, attr_len); + if (attr_len > end - pos) { wpa_printf(MSG_DEBUG, "P2P: Attribute underflow " "(len=%u left=%d)", - attr_len, (int) (end - pos - 3)); + attr_len, (int) (end - pos)); wpa_hexdump(MSG_MSGDUMP, "P2P: Data", pos, end - pos); return -1; } - if (p2p_parse_attribute(pos[0], pos + 3, attr_len, msg)) + if (p2p_parse_attribute(id, pos, attr_len, msg)) return -1; - pos += 3 + attr_len; + pos += attr_len; } return 0; @@ -327,6 +445,7 @@ int p2p_parse_p2p_ie(const struct wpabuf *buf, struct p2p_message *msg) static int p2p_parse_wps_ie(const struct wpabuf *buf, struct p2p_message *msg) { struct wps_parse_attr attr; + int i; wpa_printf(MSG_DEBUG, "P2P: Parsing WPS IE"); if (wps_parse_msg(buf, &attr)) @@ -344,6 +463,7 @@ static int p2p_parse_wps_ie(const struct wpabuf *buf, struct p2p_message *msg) msg->dev_password_id = WPA_GET_BE16(attr.dev_password_id); wpa_printf(MSG_DEBUG, "P2P: Device Password ID: %d", msg->dev_password_id); + msg->dev_password_id_present = 1; } if (attr.primary_dev_type) { char devtype[WPS_DEV_TYPE_BUFSIZE]; @@ -352,6 +472,27 @@ static int p2p_parse_wps_ie(const struct wpabuf *buf, struct p2p_message *msg) wps_dev_type_bin2str(msg->wps_pri_dev_type, devtype, sizeof(devtype))); } + if (attr.sec_dev_type_list) { + msg->wps_sec_dev_type_list = attr.sec_dev_type_list; + msg->wps_sec_dev_type_list_len = attr.sec_dev_type_list_len; + } + + for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) { + msg->wps_vendor_ext[i] = attr.vendor_ext[i]; + msg->wps_vendor_ext_len[i] = attr.vendor_ext_len[i]; + } + + msg->manufacturer = attr.manufacturer; + msg->manufacturer_len = attr.manufacturer_len; + msg->model_name = attr.model_name; + msg->model_name_len = attr.model_name_len; + msg->model_number = attr.model_number; + msg->model_number_len = attr.model_number_len; + msg->serial_number = attr.serial_number; + msg->serial_number_len = attr.serial_number_len; + + msg->oob_dev_password = attr.oob_dev_password; + msg->oob_dev_password_len = attr.oob_dev_password_len; return 0; } @@ -375,7 +516,7 @@ 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) + if (elems.ds_params) msg->ds_params = elems.ds_params; if (elems.ssid) msg->ssid = elems.ssid - 2; @@ -400,6 +541,16 @@ int p2p_parse_ies(const u8 *data, size_t len, struct p2p_message *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; } @@ -429,6 +580,33 @@ int p2p_parse(const u8 *data, size_t len, struct p2p_message *msg) } +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; +} + + /** * p2p_parse_free - Free temporary data from P2P parsing * @msg: Parsed attributes @@ -439,6 +617,10 @@ void p2p_parse_free(struct p2p_message *msg) msg->p2p_attributes = NULL; wpabuf_free(msg->wps_attributes); msg->wps_attributes = NULL; +#ifdef CONFIG_WIFI_DISPLAY + wpabuf_free(msg->wfd_subelems); + msg->wfd_subelems = NULL; +#endif /* CONFIG_WIFI_DISPLAY */ } @@ -495,8 +677,8 @@ int p2p_group_info_parse(const u8 *gi, size_t gi_len, t += 2; if (count > cend - t) return -1; /* invalid Device Name TLV */ - if (count >= 32) - count = 32; + if (count >= WPS_DEV_NAME_MAX_LEN) + count = WPS_DEV_NAME_MAX_LEN; cli->dev_name = (const char *) t; cli->dev_name_len = count; @@ -524,7 +706,7 @@ static int p2p_group_info_text(const u8 *gi, size_t gi_len, char *buf, for (i = 0; i < info.num_clients; i++) { struct p2p_client_info *cli; - char name[33]; + char name[WPS_DEV_NAME_MAX_LEN + 1]; char devtype[WPS_DEV_TYPE_BUFSIZE]; u8 s; int count; @@ -534,7 +716,7 @@ static int p2p_group_info_text(const u8 *gi, size_t gi_len, char *buf, "dev=" MACSTR " iface=" MACSTR, MAC2STR(cli->p2p_device_addr), MAC2STR(cli->p2p_interface_addr)); - if (ret < 0 || ret >= end - pos) + if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; @@ -545,7 +727,7 @@ static int p2p_group_info_text(const u8 *gi, size_t gi_len, char *buf, wps_dev_type_bin2str(cli->pri_dev_type, devtype, sizeof(devtype))); - if (ret < 0 || ret >= end - pos) + if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; @@ -554,7 +736,7 @@ static int p2p_group_info_text(const u8 *gi, size_t gi_len, char *buf, wps_dev_type_bin2str( &cli->sec_dev_types[s * 8], devtype, sizeof(devtype))); - if (ret < 0 || ret >= end - pos) + if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; } @@ -563,13 +745,13 @@ static int p2p_group_info_text(const u8 *gi, size_t gi_len, char *buf, name[cli->dev_name_len] = '\0'; count = (int) cli->dev_name_len - 1; while (count >= 0) { - if (name[count] < 32) + if (is_ctrl_char(name[count])) name[count] = '_'; count--; } ret = os_snprintf(pos, end - pos, " dev_name='%s'\n", name); - if (ret < 0 || ret >= end - pos) + if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; } @@ -603,7 +785,7 @@ int p2p_attr_text(struct wpabuf *data, char *buf, char *end) "p2p_dev_capab=0x%x\n" "p2p_group_capab=0x%x\n", msg.capability[0], msg.capability[1]); - if (ret < 0 || ret >= end - pos) + if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; } @@ -615,14 +797,14 @@ int p2p_attr_text(struct wpabuf *data, char *buf, char *end) wps_dev_type_bin2str(msg.pri_dev_type, devtype, sizeof(devtype))); - if (ret < 0 || ret >= end - pos) + if (os_snprintf_error(end - pos, ret)) 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) + if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; @@ -630,14 +812,14 @@ int p2p_attr_text(struct wpabuf *data, char *buf, char *end) ret = os_snprintf(pos, end - pos, "p2p_device_addr=" MACSTR "\n", MAC2STR(msg.p2p_device_addr)); - if (ret < 0 || ret >= end - pos) + if (os_snprintf_error(end - pos, ret)) 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) + if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret;