X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=wpa_supplicant%2Fwifi_display.c;h=c363b21b92b160b5a6a12b41a9ec1cce94bf951c;hb=14f34a73031e2878101be473d8416f7c09d37833;hp=8435b63a779fa213a31c0a20d2f7e37c818ab92e;hpb=bab6677a3105f15b19b6be4a189e7baf61b4f791;p=mech_eap.git diff --git a/wpa_supplicant/wifi_display.c b/wpa_supplicant/wifi_display.c index 8435b63..c363b21 100644 --- a/wpa_supplicant/wifi_display.c +++ b/wpa_supplicant/wifi_display.c @@ -36,6 +36,34 @@ void wifi_display_deinit(struct wpa_global *global) } +struct wpabuf * wifi_display_get_wfd_ie(struct wpa_global *global) +{ + struct wpabuf *ie; + size_t len; + int i; + + if (global->p2p == NULL) + return NULL; + + len = 0; + for (i = 0; i < MAX_WFD_SUBELEMS; i++) { + if (global->wfd_subelem[i]) + len += wpabuf_len(global->wfd_subelem[i]); + } + + ie = wpabuf_alloc(len); + if (ie == NULL) + return NULL; + + for (i = 0; i < MAX_WFD_SUBELEMS; i++) { + if (global->wfd_subelem[i]) + wpabuf_put_buf(ie, global->wfd_subelem[i]); + } + + return ie; +} + + static int wifi_display_update_wfd_ie(struct wpa_global *global) { struct wpabuf *ie, *buf; @@ -205,15 +233,31 @@ int wifi_display_subelem_set(struct wpa_global *global, char *cmd) if (pos == NULL) return -1; *pos++ = '\0'; - subelem = atoi(cmd); - if (subelem < 0 || subelem >= MAX_WFD_SUBELEMS) - return -1; len = os_strlen(pos); if (len & 1) return -1; len /= 2; + if (os_strcmp(cmd, "all") == 0) { + int res; + + e = wpabuf_alloc(len); + if (e == NULL) + return -1; + if (hexstr2bin(pos, wpabuf_put(e, len), len) < 0) { + wpabuf_free(e); + return -1; + } + res = wifi_display_subelem_set_from_ies(global, e); + wpabuf_free(e); + return res; + } + + subelem = atoi(cmd); + if (subelem < 0 || subelem >= MAX_WFD_SUBELEMS) + return -1; + if (len == 0) { /* Clear subelement */ e = NULL; @@ -238,11 +282,78 @@ int wifi_display_subelem_set(struct wpa_global *global, char *cmd) } +int wifi_display_subelem_set_from_ies(struct wpa_global *global, + struct wpabuf *ie) +{ + int subelements[MAX_WFD_SUBELEMS] = {}; + const u8 *pos, *end; + unsigned int len, subelem; + struct wpabuf *e; + + wpa_printf(MSG_DEBUG, "WFD IEs set: %p - %lu", + ie, ie ? (unsigned long) wpabuf_len(ie) : 0); + + if (ie == NULL || wpabuf_len(ie) < 6) + return -1; + + pos = wpabuf_head(ie); + end = pos + wpabuf_len(ie); + + while (end > pos) { + if (pos + 3 > end) + break; + + len = WPA_GET_BE16(pos + 1) + 3; + + wpa_printf(MSG_DEBUG, "WFD Sub-Element ID %d - len %d", + *pos, len - 3); + + if (len > (unsigned int) (end - pos)) + break; + + subelem = *pos; + if (subelem < MAX_WFD_SUBELEMS && subelements[subelem] == 0) { + e = wpabuf_alloc_copy(pos, len); + if (e == NULL) + return -1; + + wpabuf_free(global->wfd_subelem[subelem]); + global->wfd_subelem[subelem] = e; + subelements[subelem] = 1; + } + + pos += len; + } + + for (subelem = 0; subelem < MAX_WFD_SUBELEMS; subelem++) { + if (subelements[subelem] == 0) { + wpabuf_free(global->wfd_subelem[subelem]); + global->wfd_subelem[subelem] = NULL; + } + } + + return wifi_display_update_wfd_ie(global); +} + + int wifi_display_subelem_get(struct wpa_global *global, char *cmd, char *buf, size_t buflen) { int subelem; + if (os_strcmp(cmd, "all") == 0) { + struct wpabuf *ie; + int res; + + ie = wifi_display_get_wfd_ie(global); + if (ie == NULL) + return 0; + res = wpa_snprintf_hex(buf, buflen, wpabuf_head(ie), + wpabuf_len(ie)); + wpabuf_free(ie); + return res; + } + subelem = atoi(cmd); if (subelem < 0 || subelem >= MAX_WFD_SUBELEMS) return -1; @@ -276,8 +387,20 @@ char * wifi_display_subelem_hex(const struct wpabuf *wfd_subelems, u8 id) while (i + WIFI_DISPLAY_SUBELEM_HEADER_LEN < buflen) { elen = WPA_GET_BE16(buf + i + 1); + if (i + WIFI_DISPLAY_SUBELEM_HEADER_LEN + elen > buflen) + break; /* truncated subelement */ if (buf[i] == id) { + /* + * Limit explicitly to an arbitrary length to avoid + * unnecessarily large allocations. In practice, this + * is limited to maximum frame length anyway, so the + * maximum memory allocation here is not really that + * large. Anyway, the Wi-Fi Display subelements that + * are fetched with this function are even shorter. + */ + if (elen > 1000) + break; subelem = os_zalloc(2 * elen + 1); if (!subelem) return NULL;