<p>External control for TDLS setup requests</p>
</li>
- <li>
- <h3>OsuDir - s - (read/write)</h3>
- <p>OSU provider information directory</p>
- </li>
-
<li>
<h3>WowlanTriggers - s - (read/write)</h3>
<p>Wake-on-WLAN triggers</p>
<tr><td>HS20WanMetrics</td><td>ay</td></tr>
<tr><td>HS20ConnectionCapability</td><td>ay</td></tr>
<tr><td>HS20OperatingClass</td><td>ay</td></tr>
- <tr><td>HS20OSUProvidersList</td><td>ay</td></tr>
- <tr><td>HS20OperatorIconMetadata</td><td>ay</td></tr>
- <tr><td>HS20OSUProvidersNAIList</td><td>ay</td></tr>
</table>
<p>Unnamed ANQP elements have a generic entry name 'anqp[id]' where 'id' is the InfoID of the ANQP element as described in IEEE Std 802.11-2020, Table 9-331 (ANQP-element definitions).</p>
</li>
return 0;
}
-
-static int hs20_parse_icon(struct hostapd_bss_config *bss, char *pos)
-{
- struct hs20_icon *icon;
- char *end;
-
- icon = os_realloc_array(bss->hs20_icons, bss->hs20_icons_count + 1,
- sizeof(struct hs20_icon));
- if (icon == NULL)
- return -1;
- bss->hs20_icons = icon;
- icon = &bss->hs20_icons[bss->hs20_icons_count];
- os_memset(icon, 0, sizeof(*icon));
-
- icon->width = atoi(pos);
- pos = os_strchr(pos, ':');
- if (pos == NULL)
- return -1;
- pos++;
-
- icon->height = atoi(pos);
- pos = os_strchr(pos, ':');
- if (pos == NULL)
- return -1;
- pos++;
-
- end = os_strchr(pos, ':');
- if (end == NULL || end - pos > 3)
- return -1;
- os_memcpy(icon->language, pos, end - pos);
- pos = end + 1;
-
- end = os_strchr(pos, ':');
- if (end == NULL || end - pos > 255)
- return -1;
- os_memcpy(icon->type, pos, end - pos);
- pos = end + 1;
-
- end = os_strchr(pos, ':');
- if (end == NULL || end - pos > 255)
- return -1;
- os_memcpy(icon->name, pos, end - pos);
- pos = end + 1;
-
- if (os_strlen(pos) > 255)
- return -1;
- os_memcpy(icon->file, pos, os_strlen(pos));
-
- bss->hs20_icons_count++;
-
- return 0;
-}
-
-
-static int hs20_parse_osu_ssid(struct hostapd_bss_config *bss,
- char *pos, int line)
-{
- size_t slen;
- char *str;
-
- str = wpa_config_parse_string(pos, &slen);
- if (str == NULL || slen < 1 || slen > SSID_MAX_LEN) {
- wpa_printf(MSG_ERROR, "Line %d: Invalid SSID '%s'", line, pos);
- os_free(str);
- return -1;
- }
-
- os_memcpy(bss->osu_ssid, str, slen);
- bss->osu_ssid_len = slen;
- os_free(str);
-
- return 0;
-}
-
-
-static int hs20_parse_osu_server_uri(struct hostapd_bss_config *bss,
- char *pos, int line)
-{
- struct hs20_osu_provider *p;
-
- p = os_realloc_array(bss->hs20_osu_providers,
- bss->hs20_osu_providers_count + 1, sizeof(*p));
- if (p == NULL)
- return -1;
-
- bss->hs20_osu_providers = p;
- bss->last_osu = &bss->hs20_osu_providers[bss->hs20_osu_providers_count];
- bss->hs20_osu_providers_count++;
- os_memset(bss->last_osu, 0, sizeof(*p));
- bss->last_osu->server_uri = os_strdup(pos);
-
- return 0;
-}
-
-
-static int hs20_parse_osu_friendly_name(struct hostapd_bss_config *bss,
- char *pos, int line)
-{
- if (bss->last_osu == NULL) {
- wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
- return -1;
- }
-
- if (parse_lang_string(&bss->last_osu->friendly_name,
- &bss->last_osu->friendly_name_count, pos)) {
- wpa_printf(MSG_ERROR, "Line %d: Invalid osu_friendly_name '%s'",
- line, pos);
- return -1;
- }
-
- return 0;
-}
-
-
-static int hs20_parse_osu_nai(struct hostapd_bss_config *bss,
- char *pos, int line)
-{
- if (bss->last_osu == NULL) {
- wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
- return -1;
- }
-
- os_free(bss->last_osu->osu_nai);
- bss->last_osu->osu_nai = os_strdup(pos);
- if (bss->last_osu->osu_nai == NULL)
- return -1;
-
- return 0;
-}
-
-
-static int hs20_parse_osu_nai2(struct hostapd_bss_config *bss,
- char *pos, int line)
-{
- if (bss->last_osu == NULL) {
- wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
- return -1;
- }
-
- os_free(bss->last_osu->osu_nai2);
- bss->last_osu->osu_nai2 = os_strdup(pos);
- if (bss->last_osu->osu_nai2 == NULL)
- return -1;
- bss->hs20_osu_providers_nai_count++;
-
- return 0;
-}
-
-
-static int hs20_parse_osu_method_list(struct hostapd_bss_config *bss, char *pos,
- int line)
-{
- if (bss->last_osu == NULL) {
- wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
- return -1;
- }
-
- if (hostapd_parse_intlist(&bss->last_osu->method_list, pos)) {
- wpa_printf(MSG_ERROR, "Line %d: Invalid osu_method_list", line);
- return -1;
- }
-
- return 0;
-}
-
-
-static int hs20_parse_osu_icon(struct hostapd_bss_config *bss, char *pos,
- int line)
-{
- char **n;
- struct hs20_osu_provider *p = bss->last_osu;
-
- if (p == NULL) {
- wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
- return -1;
- }
-
- n = os_realloc_array(p->icons, p->icons_count + 1, sizeof(char *));
- if (n == NULL)
- return -1;
- p->icons = n;
- p->icons[p->icons_count] = os_strdup(pos);
- if (p->icons[p->icons_count] == NULL)
- return -1;
- p->icons_count++;
-
- return 0;
-}
-
-
-static int hs20_parse_osu_service_desc(struct hostapd_bss_config *bss,
- char *pos, int line)
-{
- if (bss->last_osu == NULL) {
- wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
- return -1;
- }
-
- if (parse_lang_string(&bss->last_osu->service_desc,
- &bss->last_osu->service_desc_count, pos)) {
- wpa_printf(MSG_ERROR, "Line %d: Invalid osu_service_desc '%s'",
- line, pos);
- return -1;
- }
-
- return 0;
-}
-
-
-static int hs20_parse_operator_icon(struct hostapd_bss_config *bss, char *pos,
- int line)
-{
- char **n;
-
- n = os_realloc_array(bss->hs20_operator_icon,
- bss->hs20_operator_icon_count + 1, sizeof(char *));
- if (!n)
- return -1;
- bss->hs20_operator_icon = n;
- bss->hs20_operator_icon[bss->hs20_operator_icon_count] = os_strdup(pos);
- if (!bss->hs20_operator_icon[bss->hs20_operator_icon_count])
- return -1;
- bss->hs20_operator_icon_count++;
-
- return 0;
-}
-
#endif /* CONFIG_HS20 */
os_free(bss->hs20_operating_class);
bss->hs20_operating_class = oper_class;
bss->hs20_operating_class_len = oper_class_len;
- } else if (os_strcmp(buf, "hs20_icon") == 0) {
- if (hs20_parse_icon(bss, pos) < 0) {
- wpa_printf(MSG_ERROR, "Line %d: Invalid hs20_icon '%s'",
- line, pos);
- return 1;
- }
- } else if (os_strcmp(buf, "osu_ssid") == 0) {
- if (hs20_parse_osu_ssid(bss, pos, line) < 0)
- return 1;
- } else if (os_strcmp(buf, "osu_server_uri") == 0) {
- if (hs20_parse_osu_server_uri(bss, pos, line) < 0)
- return 1;
- } else if (os_strcmp(buf, "osu_friendly_name") == 0) {
- if (hs20_parse_osu_friendly_name(bss, pos, line) < 0)
- return 1;
- } else if (os_strcmp(buf, "osu_nai") == 0) {
- if (hs20_parse_osu_nai(bss, pos, line) < 0)
- return 1;
- } else if (os_strcmp(buf, "osu_nai2") == 0) {
- if (hs20_parse_osu_nai2(bss, pos, line) < 0)
- return 1;
- } else if (os_strcmp(buf, "osu_method_list") == 0) {
- if (hs20_parse_osu_method_list(bss, pos, line) < 0)
- return 1;
- } else if (os_strcmp(buf, "osu_icon") == 0) {
- if (hs20_parse_osu_icon(bss, pos, line) < 0)
- return 1;
- } else if (os_strcmp(buf, "osu_service_desc") == 0) {
- if (hs20_parse_osu_service_desc(bss, pos, line) < 0)
- return 1;
- } else if (os_strcmp(buf, "operator_icon") == 0) {
- if (hs20_parse_operator_icon(bss, pos, line) < 0)
- return 1;
} else if (os_strcmp(buf, "subscr_remediation_url") == 0) {
os_free(bss->subscr_remediation_url);
bss->subscr_remediation_url = os_strdup(pos);
# @1@ = MAC address of the STA (colon separated hex octets)
#hs20_t_c_server_url=https://example.com/t_and_c?addr=@1@&ap=123
-# OSU and Operator icons
-# <Icon Width>:<Icon Height>:<Language code>:<Icon Type>:<Name>:<file path>
-#hs20_icon=32:32:eng:image/png:icon32:/tmp/icon32.png
-#hs20_icon=64:64:eng:image/png:icon64:/tmp/icon64.png
-
-# OSU SSID (see ssid2 for format description)
-# This is the SSID used for all OSU connections to all the listed OSU Providers.
-#osu_ssid="example"
-
-# OSU Providers
-# One or more sets of following parameter. Each OSU provider is started by the
-# mandatory osu_server_uri item. The other parameters add information for the
-# last added OSU provider. osu_nai specifies the OSU_NAI value for OSEN
-# authentication when using a standalone OSU BSS. osu_nai2 specifies the OSU_NAI
-# value for OSEN authentication when using a shared BSS (Single SSID) for OSU.
-#
-#osu_server_uri=https://example.com/osu/
-#osu_friendly_name=eng:Example operator
-#osu_friendly_name=fin:Esimerkkipalveluntarjoaja
-#osu_nai=anonymous@example.com
-#osu_nai2=anonymous@example.com
-#osu_method_list=1 0
-#osu_icon=icon32
-#osu_icon=icon64
-#osu_service_desc=eng:Example services
-#osu_service_desc=fin:Esimerkkipalveluja
-#
-#osu_server_uri=...
-
-# Operator Icons
-# Operator icons are specified using references to the hs20_icon entries
-# (Name subfield). This information, if present, is advertsised in the
-# Operator Icon Metadata ANQO-element.
-#operator_icon=icon32
-#operator_icon=icon64
-
##### Multiband Operation (MBO) ###############################################
#
# MBO enabled
os_free(conf->hs20_wan_metrics);
os_free(conf->hs20_connection_capability);
os_free(conf->hs20_operating_class);
- os_free(conf->hs20_icons);
- if (conf->hs20_osu_providers) {
- for (i = 0; i < conf->hs20_osu_providers_count; i++) {
- struct hs20_osu_provider *p;
- size_t j;
- p = &conf->hs20_osu_providers[i];
- os_free(p->friendly_name);
- os_free(p->server_uri);
- os_free(p->method_list);
- for (j = 0; j < p->icons_count; j++)
- os_free(p->icons[j]);
- os_free(p->icons);
- os_free(p->osu_nai);
- os_free(p->osu_nai2);
- os_free(p->service_desc);
- }
- os_free(conf->hs20_osu_providers);
- }
- if (conf->hs20_operator_icon) {
- for (i = 0; i < conf->hs20_operator_icon_count; i++)
- os_free(conf->hs20_operator_icon[i]);
- os_free(conf->hs20_operator_icon);
- }
os_free(conf->subscr_remediation_url);
os_free(conf->hs20_sim_provisioning_url);
os_free(conf->t_c_filename);
size_t hs20_connection_capability_len;
u8 *hs20_operating_class;
u8 hs20_operating_class_len;
- struct hs20_icon {
- u16 width;
- u16 height;
- char language[3];
- char type[256];
- char name[256];
- char file[256];
- } *hs20_icons;
- size_t hs20_icons_count;
- u8 osu_ssid[SSID_MAX_LEN];
- size_t osu_ssid_len;
- struct hs20_osu_provider {
- unsigned int friendly_name_count;
- struct hostapd_lang_string *friendly_name;
- char *server_uri;
- int *method_list;
- char **icons;
- size_t icons_count;
- char *osu_nai;
- char *osu_nai2;
- unsigned int service_desc_count;
- struct hostapd_lang_string *service_desc;
- } *hs20_osu_providers, *last_osu;
- size_t hs20_osu_providers_count;
- size_t hs20_osu_providers_nai_count;
- char **hs20_operator_icon;
- size_t hs20_operator_icon_count;
unsigned int hs20_deauth_req_timeout;
char *subscr_remediation_url;
u8 subscr_remediation_method;
wpabuf_put_u8(buf, HS20_STYPE_NAI_HOME_REALM_QUERY);
if (hapd->conf->hs20_operating_class)
wpabuf_put_u8(buf, HS20_STYPE_OPERATING_CLASS);
- if (hapd->conf->hs20_osu_providers_count)
- wpabuf_put_u8(buf, HS20_STYPE_OSU_PROVIDERS_LIST);
- if (hapd->conf->hs20_osu_providers_nai_count)
- wpabuf_put_u8(buf, HS20_STYPE_OSU_PROVIDERS_NAI_LIST);
- if (hapd->conf->hs20_icons_count)
- wpabuf_put_u8(buf, HS20_STYPE_ICON_REQUEST);
- if (hapd->conf->hs20_operator_icon_count)
- wpabuf_put_u8(buf, HS20_STYPE_OPERATOR_ICON_METADATA);
gas_anqp_set_element_len(buf, len);
}
#endif /* CONFIG_HS20 */
}
}
-
-static void anqp_add_icon(struct wpabuf *buf, struct hostapd_bss_config *bss,
- const char *name)
-{
- size_t j;
- struct hs20_icon *icon = NULL;
-
- for (j = 0; j < bss->hs20_icons_count && !icon; j++) {
- if (os_strcmp(name, bss->hs20_icons[j].name) == 0)
- icon = &bss->hs20_icons[j];
- }
- if (!icon)
- return; /* icon info not found */
-
- wpabuf_put_le16(buf, icon->width);
- wpabuf_put_le16(buf, icon->height);
- wpabuf_put_data(buf, icon->language, 3);
- wpabuf_put_u8(buf, os_strlen(icon->type));
- wpabuf_put_str(buf, icon->type);
- wpabuf_put_u8(buf, os_strlen(icon->name));
- wpabuf_put_str(buf, icon->name);
-}
-
-
-static void anqp_add_osu_provider(struct wpabuf *buf,
- struct hostapd_bss_config *bss,
- struct hs20_osu_provider *p)
-{
- u8 *len, *len2, *count;
- unsigned int i;
-
- len = wpabuf_put(buf, 2); /* OSU Provider Length to be filled */
-
- /* OSU Friendly Name Duples */
- len2 = wpabuf_put(buf, 2);
- for (i = 0; i < p->friendly_name_count; i++) {
- struct hostapd_lang_string *s = &p->friendly_name[i];
- wpabuf_put_u8(buf, 3 + s->name_len);
- wpabuf_put_data(buf, s->lang, 3);
- wpabuf_put_data(buf, s->name, s->name_len);
- }
- WPA_PUT_LE16(len2, (u8 *) wpabuf_put(buf, 0) - len2 - 2);
-
- /* OSU Server URI */
- if (p->server_uri) {
- wpabuf_put_u8(buf, os_strlen(p->server_uri));
- wpabuf_put_str(buf, p->server_uri);
- } else
- wpabuf_put_u8(buf, 0);
-
- /* OSU Method List */
- count = wpabuf_put(buf, 1);
- for (i = 0; p->method_list && p->method_list[i] >= 0; i++)
- wpabuf_put_u8(buf, p->method_list[i]);
- *count = i;
-
- /* Icons Available */
- len2 = wpabuf_put(buf, 2);
- for (i = 0; i < p->icons_count; i++)
- anqp_add_icon(buf, bss, p->icons[i]);
- WPA_PUT_LE16(len2, (u8 *) wpabuf_put(buf, 0) - len2 - 2);
-
- /* OSU_NAI */
- if (p->osu_nai) {
- wpabuf_put_u8(buf, os_strlen(p->osu_nai));
- wpabuf_put_str(buf, p->osu_nai);
- } else
- wpabuf_put_u8(buf, 0);
-
- /* OSU Service Description Duples */
- len2 = wpabuf_put(buf, 2);
- for (i = 0; i < p->service_desc_count; i++) {
- struct hostapd_lang_string *s = &p->service_desc[i];
- wpabuf_put_u8(buf, 3 + s->name_len);
- wpabuf_put_data(buf, s->lang, 3);
- wpabuf_put_data(buf, s->name, s->name_len);
- }
- WPA_PUT_LE16(len2, (u8 *) wpabuf_put(buf, 0) - len2 - 2);
-
- WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
-}
-
-
-static void anqp_add_osu_providers_list(struct hostapd_data *hapd,
- struct wpabuf *buf)
-{
- if (hapd->conf->hs20_osu_providers_count) {
- size_t i;
- u8 *len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
- wpabuf_put_be24(buf, OUI_WFA);
- wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
- wpabuf_put_u8(buf, HS20_STYPE_OSU_PROVIDERS_LIST);
- wpabuf_put_u8(buf, 0); /* Reserved */
-
- /* OSU SSID */
- wpabuf_put_u8(buf, hapd->conf->osu_ssid_len);
- wpabuf_put_data(buf, hapd->conf->osu_ssid,
- hapd->conf->osu_ssid_len);
-
- /* Number of OSU Providers */
- wpabuf_put_u8(buf, hapd->conf->hs20_osu_providers_count);
-
- for (i = 0; i < hapd->conf->hs20_osu_providers_count; i++) {
- anqp_add_osu_provider(
- buf, hapd->conf,
- &hapd->conf->hs20_osu_providers[i]);
- }
-
- gas_anqp_set_element_len(buf, len);
- }
-}
-
-
-static void anqp_add_osu_provider_nai(struct wpabuf *buf,
- struct hs20_osu_provider *p)
-{
- /* OSU_NAI for shared BSS (Single SSID) */
- if (p->osu_nai2) {
- wpabuf_put_u8(buf, os_strlen(p->osu_nai2));
- wpabuf_put_str(buf, p->osu_nai2);
- } else {
- wpabuf_put_u8(buf, 0);
- }
-}
-
-
-static void anqp_add_osu_providers_nai_list(struct hostapd_data *hapd,
- struct wpabuf *buf)
-{
- if (hapd->conf->hs20_osu_providers_nai_count) {
- size_t i;
- u8 *len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
- wpabuf_put_be24(buf, OUI_WFA);
- wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
- wpabuf_put_u8(buf, HS20_STYPE_OSU_PROVIDERS_NAI_LIST);
- wpabuf_put_u8(buf, 0); /* Reserved */
-
- for (i = 0; i < hapd->conf->hs20_osu_providers_count; i++) {
- anqp_add_osu_provider_nai(
- buf, &hapd->conf->hs20_osu_providers[i]);
- }
-
- gas_anqp_set_element_len(buf, len);
- }
-}
-
-
-static void anqp_add_icon_binary_file(struct hostapd_data *hapd,
- struct wpabuf *buf,
- const u8 *name, size_t name_len)
-{
- struct hs20_icon *icon;
- size_t i;
- u8 *len;
-
- wpa_hexdump_ascii(MSG_DEBUG, "HS 2.0: Requested Icon Filename",
- name, name_len);
- for (i = 0; i < hapd->conf->hs20_icons_count; i++) {
- icon = &hapd->conf->hs20_icons[i];
- if (name_len == os_strlen(icon->name) &&
- os_memcmp(name, icon->name, name_len) == 0)
- break;
- }
-
- if (i < hapd->conf->hs20_icons_count)
- icon = &hapd->conf->hs20_icons[i];
- else
- icon = NULL;
-
- len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
- wpabuf_put_be24(buf, OUI_WFA);
- wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
- wpabuf_put_u8(buf, HS20_STYPE_ICON_BINARY_FILE);
- wpabuf_put_u8(buf, 0); /* Reserved */
-
- if (icon) {
- char *data;
- size_t data_len;
-
- data = os_readfile(icon->file, &data_len);
- if (data == NULL || data_len > 65535) {
- wpabuf_put_u8(buf, 2); /* Download Status:
- * Unspecified file error */
- wpabuf_put_u8(buf, 0);
- wpabuf_put_le16(buf, 0);
- } else {
- wpabuf_put_u8(buf, 0); /* Download Status: Success */
- wpabuf_put_u8(buf, os_strlen(icon->type));
- wpabuf_put_str(buf, icon->type);
- wpabuf_put_le16(buf, data_len);
- wpabuf_put_data(buf, data, data_len);
- }
- os_free(data);
- } else {
- wpabuf_put_u8(buf, 1); /* Download Status: File not found */
- wpabuf_put_u8(buf, 0);
- wpabuf_put_le16(buf, 0);
- }
-
- gas_anqp_set_element_len(buf, len);
-}
-
-
-static void anqp_add_operator_icon_metadata(struct hostapd_data *hapd,
- struct wpabuf *buf)
-{
- struct hostapd_bss_config *bss = hapd->conf;
- size_t i;
- u8 *len;
-
- if (!bss->hs20_operator_icon_count)
- return;
-
- len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
-
- wpabuf_put_be24(buf, OUI_WFA);
- wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
- wpabuf_put_u8(buf, HS20_STYPE_OPERATOR_ICON_METADATA);
- wpabuf_put_u8(buf, 0); /* Reserved */
-
- for (i = 0; i < bss->hs20_operator_icon_count; i++)
- anqp_add_icon(buf, bss, bss->hs20_operator_icon[i]);
-
- gas_anqp_set_element_len(buf, len);
-}
-
#endif /* CONFIG_HS20 */
gas_serv_build_gas_resp_payload(struct hostapd_data *hapd,
unsigned int request,
const u8 *home_realm, size_t home_realm_len,
- const u8 *icon_name, size_t icon_name_len,
const u16 *extra_req,
unsigned int num_extra_req)
{
len = 1400;
if (request & (ANQP_REQ_NAI_REALM | ANQP_REQ_NAI_HOME_REALM))
len += 1000;
- if (request & ANQP_REQ_ICON_REQUEST)
- len += 65536;
#ifdef CONFIG_FILS
if (request & ANQP_FILS_REALM_INFO)
len += 2 * dl_list_len(&hapd->conf->fils_realms);
anqp_add_connection_capability(hapd, buf);
if (request & ANQP_REQ_OPERATING_CLASS)
anqp_add_operating_class(hapd, buf);
- if (request & ANQP_REQ_OSU_PROVIDERS_LIST)
- anqp_add_osu_providers_list(hapd, buf);
- if (request & ANQP_REQ_ICON_REQUEST)
- anqp_add_icon_binary_file(hapd, buf, icon_name, icon_name_len);
- if (request & ANQP_REQ_OPERATOR_ICON_METADATA)
- anqp_add_operator_icon_metadata(hapd, buf);
- if (request & ANQP_REQ_OSU_PROVIDERS_NAI_LIST)
- anqp_add_osu_providers_nai_list(hapd, buf);
#endif /* CONFIG_HS20 */
#ifdef CONFIG_MBO
unsigned int request;
const u8 *home_realm_query;
size_t home_realm_query_len;
- const u8 *icon_name;
- size_t icon_name_len;
int p2p_sd;
u16 extra_req[ANQP_MAX_EXTRA_REQ];
unsigned int num_extra_req;
set_anqp_req(ANQP_REQ_OPERATING_CLASS, "Operating Class",
hapd->conf->hs20_operating_class != NULL, qi);
break;
- case HS20_STYPE_OSU_PROVIDERS_LIST:
- set_anqp_req(ANQP_REQ_OSU_PROVIDERS_LIST, "OSU Providers list",
- hapd->conf->hs20_osu_providers_count, qi);
- break;
- case HS20_STYPE_OPERATOR_ICON_METADATA:
- set_anqp_req(ANQP_REQ_OPERATOR_ICON_METADATA,
- "Operator Icon Metadata",
- hapd->conf->hs20_operator_icon_count, qi);
- break;
- case HS20_STYPE_OSU_PROVIDERS_NAI_LIST:
- set_anqp_req(ANQP_REQ_OSU_PROVIDERS_NAI_LIST,
- "OSU Providers NAI List",
- hapd->conf->hs20_osu_providers_nai_count, qi);
- break;
default:
wpa_printf(MSG_DEBUG, "ANQP: Unsupported HS 2.0 subtype %u",
subtype);
}
-static void rx_anqp_hs_icon_request(struct hostapd_data *hapd,
- const u8 *pos, const u8 *end,
- struct anqp_query_info *qi)
-{
- qi->request |= ANQP_REQ_ICON_REQUEST;
- qi->icon_name = pos;
- qi->icon_name_len = end - pos;
- if (hapd->conf->hs20_icons_count) {
- wpa_printf(MSG_DEBUG, "ANQP: HS 2.0 Icon Request Query "
- "(local)");
- } else {
- wpa_printf(MSG_DEBUG, "ANQP: HS 2.0 Icon Request Query not "
- "available");
- }
-}
-
-
static void rx_anqp_vendor_specific_hs20(struct hostapd_data *hapd,
const u8 *pos, const u8 *end,
struct anqp_query_info *qi)
case HS20_STYPE_NAI_HOME_REALM_QUERY:
rx_anqp_hs_nai_home_realm(hapd, pos, end, qi);
break;
- case HS20_STYPE_ICON_REQUEST:
- rx_anqp_hs_icon_request(hapd, pos, end, qi);
- break;
default:
wpa_printf(MSG_DEBUG, "ANQP: Unsupported HS 2.0 query subtype "
"%u", subtype);
buf = gas_serv_build_gas_resp_payload(hapd, qi->request,
qi->home_realm_query,
qi->home_realm_query_len,
- qi->icon_name, qi->icon_name_len,
qi->extra_req, qi->num_extra_req);
wpa_hexdump_buf(MSG_MSGDUMP, "ANQP: Locally generated ANQP responses",
buf);
#define HS20_STYPE_CONNECTION_CAPABILITY 5
#define HS20_STYPE_NAI_HOME_REALM_QUERY 6
#define HS20_STYPE_OPERATING_CLASS 7
-#define HS20_STYPE_OSU_PROVIDERS_LIST 8
-#define HS20_STYPE_ICON_REQUEST 10
-#define HS20_STYPE_ICON_BINARY_FILE 11
-#define HS20_STYPE_OPERATOR_ICON_METADATA 12
-#define HS20_STYPE_OSU_PROVIDERS_NAI_LIST 13
#define HS20_DGAF_DISABLED 0x01
#define HS20_PPS_MO_ID_PRESENT 0x02
ANQP_DUP(hs20_wan_metrics);
ANQP_DUP(hs20_connection_capability);
ANQP_DUP(hs20_operating_class);
- ANQP_DUP(hs20_osu_providers_list);
- ANQP_DUP(hs20_operator_icon_metadata);
- ANQP_DUP(hs20_osu_providers_nai_list);
#endif /* CONFIG_HS20 */
#undef ANQP_DUP
wpabuf_free(anqp->hs20_wan_metrics);
wpabuf_free(anqp->hs20_connection_capability);
wpabuf_free(anqp->hs20_operating_class);
- wpabuf_free(anqp->hs20_osu_providers_list);
- wpabuf_free(anqp->hs20_operator_icon_metadata);
- wpabuf_free(anqp->hs20_osu_providers_nai_list);
#endif /* CONFIG_HS20 */
os_free(anqp);
struct wpabuf *hs20_wan_metrics;
struct wpabuf *hs20_connection_capability;
struct wpabuf *hs20_operating_class;
- struct wpabuf *hs20_osu_providers_list;
- struct wpabuf *hs20_operator_icon_metadata;
- struct wpabuf *hs20_osu_providers_nai_list;
#endif /* CONFIG_HS20 */
};
os_free(config->sae_groups);
wpabuf_free(config->ap_vendor_elements);
wpabuf_free(config->ap_assocresp_elements);
- os_free(config->osu_dir);
os_free(config->bgscan);
os_free(config->wowlan_triggers);
os_free(config->fst_group_id);
{ INT(sched_scan_interval), 0 },
{ INT(sched_scan_start_delay), 0 },
{ INT(tdls_external_control), 0},
- { STR(osu_dir), 0 },
{ STR(wowlan_triggers), CFG_CHANGED_WOWLAN_TRIGGERS },
{ INT(p2p_search_delay), 0},
{ INT_RANGE(mac_addr, 0, 2), 0 },
u8 ip_addr_start[4];
u8 ip_addr_end[4];
- /**
- * osu_dir - OSU provider information directory
- *
- * If set, allow FETCH_OSU control interface command to be used to fetch
- * OSU provider information into all APs and store the results in this
- * directory.
- */
- char *osu_dir;
-
/**
* wowlan_triggers - Wake-on-WLAN triggers
*
if (config->twt_requester)
fprintf(f, "twt_requester=%d\n", config->twt_requester);
- if (config->osu_dir)
- fprintf(f, "osu_dir=%s\n", config->osu_dir);
-
if (config->fst_group_id)
fprintf(f, "fst_group_id=%s\n", config->fst_group_id);
if (config->fst_priority)
anqp->hs20_connection_capability);
pos = anqp_add_hex(pos, end, "hs20_operating_class",
anqp->hs20_operating_class);
- pos = anqp_add_hex(pos, end, "hs20_osu_providers_list",
- anqp->hs20_osu_providers_list);
- pos = anqp_add_hex(pos, end, "hs20_operator_icon_metadata",
- anqp->hs20_operator_icon_metadata);
- pos = anqp_add_hex(pos, end, "hs20_osu_providers_nai_list",
- anqp->hs20_osu_providers_nai_list);
#endif /* CONFIG_HS20 */
dl_list_for_each(elem, &anqp->anqp_elems,
if (subtypes == 0)
return -1;
- return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0, 0);
+ return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0);
}
ret = hs20_anqp_send_req(wpa_s, addr,
BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
- buf, len, 0);
+ buf, len);
os_free(buf);
ret = hs20_anqp_send_req(wpa_s, dst_addr,
BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
- buf, len, 0);
+ buf, len);
os_free(buf);
return ret;
}
-
-static int get_hs20_icon(struct wpa_supplicant *wpa_s, char *cmd, char *reply,
- int buflen)
-{
- u8 dst_addr[ETH_ALEN];
- int used;
- char *ctx = NULL, *icon, *poffset, *psize;
-
- used = hwaddr_aton2(cmd, dst_addr);
- if (used < 0)
- return -1;
- cmd += used;
-
- icon = str_token(cmd, " ", &ctx);
- poffset = str_token(cmd, " ", &ctx);
- psize = str_token(cmd, " ", &ctx);
- if (!icon || !poffset || !psize)
- return -1;
-
- wpa_s->fetch_osu_icon_in_progress = 0;
- return hs20_get_icon(wpa_s, dst_addr, icon, atoi(poffset), atoi(psize),
- reply, buflen);
-}
-
-
-static int del_hs20_icon(struct wpa_supplicant *wpa_s, char *cmd)
-{
- u8 dst_addr[ETH_ALEN];
- int used;
- char *icon;
-
- if (!cmd[0])
- return hs20_del_icon(wpa_s, NULL, NULL);
-
- used = hwaddr_aton2(cmd, dst_addr);
- if (used < 0)
- return -1;
-
- while (cmd[used] == ' ')
- used++;
- icon = cmd[used] ? &cmd[used] : NULL;
-
- return hs20_del_icon(wpa_s, dst_addr, icon);
-}
-
-
-static int hs20_icon_request(struct wpa_supplicant *wpa_s, char *cmd, int inmem)
-{
- u8 dst_addr[ETH_ALEN];
- int used;
- char *icon;
-
- used = hwaddr_aton2(cmd, dst_addr);
- if (used < 0)
- return -1;
-
- while (cmd[used] == ' ')
- used++;
- icon = &cmd[used];
-
- wpa_s->fetch_osu_icon_in_progress = 0;
- return hs20_anqp_send_req(wpa_s, dst_addr, BIT(HS20_STYPE_ICON_REQUEST),
- (u8 *) icon, os_strlen(icon), inmem);
-}
-
#endif /* CONFIG_HS20 */
wnm_btm_reset(wpa_s);
-#ifdef CONFIG_INTERWORKING
-#ifdef CONFIG_HS20
- hs20_cancel_fetch_osu(wpa_s);
- hs20_del_icon(wpa_s, NULL, NULL);
-#endif /* CONFIG_HS20 */
-#endif /* CONFIG_INTERWORKING */
-
wpa_s->ext_mgmt_frame_handling = 0;
wpa_s->ext_eapol_frame_io = 0;
#ifdef CONFIG_TESTING_OPTIONS
} else if (os_strncmp(buf, "HS20_GET_NAI_HOME_REALM_LIST ", 29) == 0) {
if (hs20_get_nai_home_realm_list(wpa_s, buf + 29) < 0)
reply_len = -1;
- } else if (os_strncmp(buf, "HS20_ICON_REQUEST ", 18) == 0) {
- if (hs20_icon_request(wpa_s, buf + 18, 0) < 0)
- reply_len = -1;
- } else if (os_strncmp(buf, "REQ_HS20_ICON ", 14) == 0) {
- if (hs20_icon_request(wpa_s, buf + 14, 1) < 0)
- reply_len = -1;
- } else if (os_strncmp(buf, "GET_HS20_ICON ", 14) == 0) {
- reply_len = get_hs20_icon(wpa_s, buf + 14, reply, reply_size);
- } else if (os_strncmp(buf, "DEL_HS20_ICON ", 14) == 0) {
- if (del_hs20_icon(wpa_s, buf + 14) < 0)
- reply_len = -1;
- } else if (os_strcmp(buf, "FETCH_OSU") == 0) {
- if (hs20_fetch_osu(wpa_s, 0) < 0)
- reply_len = -1;
- } else if (os_strcmp(buf, "FETCH_OSU no-scan") == 0) {
- if (hs20_fetch_osu(wpa_s, 1) < 0)
- reply_len = -1;
- } else if (os_strcmp(buf, "CANCEL_FETCH_OSU") == 0) {
- hs20_cancel_fetch_osu(wpa_s);
#endif /* CONFIG_HS20 */
} else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
{
wpabuf_head(anqp->hs20_operating_class),
wpabuf_len(anqp->hs20_operating_class)))
goto nomem;
- if (anqp->hs20_osu_providers_list &&
- !wpa_dbus_dict_append_byte_array(
- &iter_dict, "HS20OSUProvidersList",
- wpabuf_head(anqp->hs20_osu_providers_list),
- wpabuf_len(anqp->hs20_osu_providers_list)))
- goto nomem;
- if (anqp->hs20_operator_icon_metadata &&
- !wpa_dbus_dict_append_byte_array(
- &iter_dict, "HS20OperatorIconMetadata",
- wpabuf_head(anqp->hs20_operator_icon_metadata),
- wpabuf_len(anqp->hs20_operator_icon_metadata)))
- goto nomem;
- if (anqp->hs20_osu_providers_nai_list &&
- !wpa_dbus_dict_append_byte_array(
- &iter_dict, "HS20OSUProvidersNAIList",
- wpabuf_head(anqp->hs20_osu_providers_nai_list),
- wpabuf_len(anqp->hs20_osu_providers_nai_list)))
- goto nomem;
#endif /* CONFIG_HS20 */
dl_list_for_each(elem, &anqp->anqp_elems,
#include "notify.h"
-#define OSU_MAX_ITEMS 10
-
-struct osu_lang_string {
- char lang[4];
- char text[253];
-};
-
-struct osu_icon {
- u16 width;
- u16 height;
- char lang[4];
- char icon_type[256];
- char filename[256];
- unsigned int id;
- unsigned int failed:1;
-};
-
-struct osu_provider {
- u8 bssid[ETH_ALEN];
- u8 osu_ssid[SSID_MAX_LEN];
- u8 osu_ssid_len;
- u8 osu_ssid2[SSID_MAX_LEN];
- u8 osu_ssid2_len;
- char server_uri[256];
- u32 osu_methods; /* bit 0 = OMA-DM, bit 1 = SOAP-XML SPP */
- char osu_nai[256];
- char osu_nai2[256];
- struct osu_lang_string friendly_name[OSU_MAX_ITEMS];
- size_t friendly_name_count;
- struct osu_lang_string serv_desc[OSU_MAX_ITEMS];
- size_t serv_desc_count;
- struct osu_icon icon[OSU_MAX_ITEMS];
- size_t icon_count;
-};
-
-
void hs20_configure_frame_filters(struct wpa_supplicant *wpa_s)
{
struct wpa_bss *bss = wpa_s->current_bss;
wpabuf_put_u8(buf, 0); /* Reserved */
if (payload)
wpabuf_put_data(buf, payload, payload_len);
- } else if (stypes == BIT(HS20_STYPE_ICON_REQUEST)) {
- wpabuf_put_u8(buf, HS20_STYPE_ICON_REQUEST);
- wpabuf_put_u8(buf, 0); /* Reserved */
- if (payload)
- wpabuf_put_data(buf, payload, payload_len);
} else {
u8 i;
wpabuf_put_u8(buf, HS20_STYPE_QUERY_LIST);
int hs20_anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, u32 stypes,
- const u8 *payload, size_t payload_len, int inmem)
+ const u8 *payload, size_t payload_len)
{
struct wpabuf *buf;
int ret = 0;
int freq;
struct wpa_bss *bss;
int res;
- struct icon_entry *icon_entry;
bss = wpa_bss_get_bssid(wpa_s, dst);
if (!bss) {
wpa_printf(MSG_DEBUG, "ANQP: Query started with dialog token "
"%u", res);
- if (inmem) {
- icon_entry = os_zalloc(sizeof(struct icon_entry));
- if (!icon_entry)
- return -1;
- os_memcpy(icon_entry->bssid, dst, ETH_ALEN);
- icon_entry->file_name = os_malloc(payload_len + 1);
- if (!icon_entry->file_name) {
- os_free(icon_entry);
- return -1;
- }
- os_memcpy(icon_entry->file_name, payload, payload_len);
- icon_entry->file_name[payload_len] = '\0';
- icon_entry->dialog_token = res;
-
- dl_list_add(&wpa_s->icon_head, &icon_entry->list);
- }
-
return ret;
}
-static struct icon_entry * hs20_find_icon(struct wpa_supplicant *wpa_s,
- const u8 *bssid,
- const char *file_name)
-{
- struct icon_entry *icon;
-
- dl_list_for_each(icon, &wpa_s->icon_head, struct icon_entry, list) {
- if (ether_addr_equal(icon->bssid, bssid) &&
- os_strcmp(icon->file_name, file_name) == 0 && icon->image)
- return icon;
- }
-
- return NULL;
-}
-
-
-int hs20_get_icon(struct wpa_supplicant *wpa_s, const u8 *bssid,
- const char *file_name, size_t offset, size_t size,
- char *reply, size_t buf_len)
-{
- struct icon_entry *icon;
- size_t out_size;
- char *b64;
- size_t b64_size;
- int reply_size;
-
- wpa_printf(MSG_DEBUG, "HS20: Get icon " MACSTR " %s @ %u +%u (%u)",
- MAC2STR(bssid), file_name, (unsigned int) offset,
- (unsigned int) size, (unsigned int) buf_len);
-
- icon = hs20_find_icon(wpa_s, bssid, file_name);
- if (!icon || !icon->image || offset >= icon->image_len)
- return -1;
- if (size > icon->image_len - offset)
- size = icon->image_len - offset;
- out_size = buf_len - 3 /* max base64 padding */;
- if (size * 4 > out_size * 3)
- size = out_size * 3 / 4;
- if (size == 0)
- return -1;
-
- b64 = base64_encode(&icon->image[offset], size, &b64_size);
- if (b64 && buf_len >= b64_size) {
- os_memcpy(reply, b64, b64_size);
- reply_size = b64_size;
- } else {
- reply_size = -1;
- }
- os_free(b64);
- return reply_size;
-}
-
-
-static void hs20_free_icon_entry(struct icon_entry *icon)
-{
- wpa_printf(MSG_DEBUG, "HS20: Free stored icon from " MACSTR
- " dialog_token=%u file_name=%s image_len=%u",
- MAC2STR(icon->bssid), icon->dialog_token,
- icon->file_name ? icon->file_name : "N/A",
- (unsigned int) icon->image_len);
- os_free(icon->file_name);
- os_free(icon->image);
- os_free(icon);
-}
-
-
-int hs20_del_icon(struct wpa_supplicant *wpa_s, const u8 *bssid,
- const char *file_name)
-{
- struct icon_entry *icon, *tmp;
- int count = 0;
-
- if (!bssid)
- wpa_printf(MSG_DEBUG, "HS20: Delete all stored icons");
- else if (!file_name)
- wpa_printf(MSG_DEBUG, "HS20: Delete all stored icons for "
- MACSTR, MAC2STR(bssid));
- else
- wpa_printf(MSG_DEBUG, "HS20: Delete stored icons for "
- MACSTR " file name %s", MAC2STR(bssid), file_name);
-
- dl_list_for_each_safe(icon, tmp, &wpa_s->icon_head, struct icon_entry,
- list) {
- if ((!bssid || ether_addr_equal(icon->bssid, bssid)) &&
- (!file_name ||
- os_strcmp(icon->file_name, file_name) == 0)) {
- dl_list_del(&icon->list);
- hs20_free_icon_entry(icon);
- count++;
- }
- }
- return count == 0 ? -1 : 0;
-}
-
-
-static void hs20_set_osu_access_permission(const char *osu_dir,
- const char *fname)
-{
- struct stat statbuf;
-
- /* Get OSU directory information */
- if (stat(osu_dir, &statbuf) < 0) {
- wpa_printf(MSG_WARNING, "Cannot stat the OSU directory %s",
- osu_dir);
- return;
- }
-
- if (chmod(fname, statbuf.st_mode) < 0) {
- wpa_printf(MSG_WARNING,
- "Cannot change the permissions for %s", fname);
- return;
- }
-
- if (lchown(fname, statbuf.st_uid, statbuf.st_gid) < 0) {
- wpa_printf(MSG_WARNING, "Cannot change the ownership for %s",
- fname);
- }
-}
-
-
-static void hs20_remove_duplicate_icons(struct wpa_supplicant *wpa_s,
- struct icon_entry *new_icon)
-{
- struct icon_entry *icon, *tmp;
-
- dl_list_for_each_safe(icon, tmp, &wpa_s->icon_head, struct icon_entry,
- list) {
- if (icon == new_icon)
- continue;
- if (ether_addr_equal(icon->bssid, new_icon->bssid) &&
- os_strcmp(icon->file_name, new_icon->file_name) == 0) {
- dl_list_del(&icon->list);
- hs20_free_icon_entry(icon);
- }
- }
-}
-
-
-static int hs20_process_icon_binary_file(struct wpa_supplicant *wpa_s,
- const u8 *sa, const u8 *pos,
- size_t slen, u8 dialog_token)
-{
- char fname[256];
- int png;
- FILE *f;
- u16 data_len;
- struct icon_entry *icon;
-
- dl_list_for_each(icon, &wpa_s->icon_head, struct icon_entry, list) {
- if (icon->dialog_token == dialog_token && !icon->image &&
- ether_addr_equal(icon->bssid, sa)) {
- icon->image = os_memdup(pos, slen);
- if (!icon->image)
- return -1;
- icon->image_len = slen;
- hs20_remove_duplicate_icons(wpa_s, icon);
- wpa_msg(wpa_s, MSG_INFO,
- RX_HS20_ICON MACSTR " %s %u",
- MAC2STR(sa), icon->file_name,
- (unsigned int) icon->image_len);
- return 0;
- }
- }
-
- wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR " Icon Binary File",
- MAC2STR(sa));
-
- if (slen < 4) {
- wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: Too short Icon Binary File "
- "value from " MACSTR, MAC2STR(sa));
- return -1;
- }
-
- wpa_printf(MSG_DEBUG, "HS 2.0: Download Status Code %u", *pos);
- if (*pos != 0)
- return -1;
- pos++;
- slen--;
-
- if ((size_t) 1 + pos[0] > slen) {
- wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: Too short Icon Binary File "
- "value from " MACSTR, MAC2STR(sa));
- return -1;
- }
- wpa_hexdump_ascii(MSG_DEBUG, "Icon Type", pos + 1, pos[0]);
- png = os_strncasecmp((char *) pos + 1, "image/png", 9) == 0;
- slen -= 1 + pos[0];
- pos += 1 + pos[0];
-
- if (slen < 2) {
- wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: Too short Icon Binary File "
- "value from " MACSTR, MAC2STR(sa));
- return -1;
- }
- data_len = WPA_GET_LE16(pos);
- pos += 2;
- slen -= 2;
-
- if (data_len > slen) {
- wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: Too short Icon Binary File "
- "value from " MACSTR, MAC2STR(sa));
- return -1;
- }
-
- wpa_printf(MSG_DEBUG, "Icon Binary Data: %u bytes", data_len);
- if (wpa_s->conf->osu_dir == NULL)
- return -1;
-
- wpa_s->osu_icon_id++;
- if (wpa_s->osu_icon_id == 0)
- wpa_s->osu_icon_id++;
- snprintf(fname, sizeof(fname), "%s/osu-icon-%u.%s",
- wpa_s->conf->osu_dir, wpa_s->osu_icon_id,
- png ? "png" : "icon");
- f = fopen(fname, "wb");
- if (f == NULL)
- return -1;
-
- hs20_set_osu_access_permission(wpa_s->conf->osu_dir, fname);
-
- if (fwrite(pos, slen, 1, f) != 1) {
- fclose(f);
- unlink(fname);
- return -1;
- }
- fclose(f);
-
- wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP_ICON "%s", fname);
- return 0;
-}
-
-
-static void hs20_continue_icon_fetch(void *eloop_ctx, void *sock_ctx)
-{
- struct wpa_supplicant *wpa_s = eloop_ctx;
- if (wpa_s->fetch_osu_icon_in_progress)
- hs20_next_osu_icon(wpa_s);
-}
-
-
-static void hs20_osu_icon_fetch_result(struct wpa_supplicant *wpa_s, int res)
-{
- size_t i, j;
- struct os_reltime now, tmp;
- int dur;
-
- os_get_reltime(&now);
- os_reltime_sub(&now, &wpa_s->osu_icon_fetch_start, &tmp);
- dur = tmp.sec * 1000 + tmp.usec / 1000;
- wpa_printf(MSG_DEBUG, "HS 2.0: Icon fetch dur=%d ms res=%d",
- dur, res);
-
- for (i = 0; i < wpa_s->osu_prov_count; i++) {
- struct osu_provider *osu = &wpa_s->osu_prov[i];
- for (j = 0; j < osu->icon_count; j++) {
- struct osu_icon *icon = &osu->icon[j];
- if (icon->id || icon->failed)
- continue;
- if (res < 0)
- icon->failed = 1;
- else
- icon->id = wpa_s->osu_icon_id;
- return;
- }
- }
-}
-
-
void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s,
struct wpa_bss *bss, const u8 *sa,
const u8 *data, size_t slen, u8 dialog_token)
const u8 *pos = data;
u8 subtype;
struct wpa_bss_anqp *anqp = NULL;
- int ret;
if (slen < 2)
return;
wpabuf_alloc_copy(pos, slen);
}
break;
- case HS20_STYPE_OSU_PROVIDERS_LIST:
- wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR
- " OSU Providers list", MAC2STR(sa));
- wpa_s->num_prov_found++;
- if (anqp) {
- wpabuf_free(anqp->hs20_osu_providers_list);
- anqp->hs20_osu_providers_list =
- wpabuf_alloc_copy(pos, slen);
- }
- break;
- case HS20_STYPE_ICON_BINARY_FILE:
- ret = hs20_process_icon_binary_file(wpa_s, sa, pos, slen,
- dialog_token);
- if (wpa_s->fetch_osu_icon_in_progress) {
- hs20_osu_icon_fetch_result(wpa_s, ret);
- eloop_cancel_timeout(hs20_continue_icon_fetch,
- wpa_s, NULL);
- eloop_register_timeout(0, 0, hs20_continue_icon_fetch,
- wpa_s, NULL);
- }
- break;
- case HS20_STYPE_OPERATOR_ICON_METADATA:
- wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR
- " Operator Icon Metadata", MAC2STR(sa));
- wpa_hexdump(MSG_DEBUG, "Operator Icon Metadata", pos, slen);
- if (anqp) {
- wpabuf_free(anqp->hs20_operator_icon_metadata);
- anqp->hs20_operator_icon_metadata =
- wpabuf_alloc_copy(pos, slen);
- }
- break;
- case HS20_STYPE_OSU_PROVIDERS_NAI_LIST:
- wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR
- " OSU Providers NAI List", MAC2STR(sa));
- if (anqp) {
- wpabuf_free(anqp->hs20_osu_providers_nai_list);
- anqp->hs20_osu_providers_nai_list =
- wpabuf_alloc_copy(pos, slen);
- }
- break;
default:
wpa_printf(MSG_DEBUG, "HS20: Unsupported subtype %u", subtype);
break;
}
-void hs20_notify_parse_done(struct wpa_supplicant *wpa_s)
-{
- if (!wpa_s->fetch_osu_icon_in_progress)
- return;
- if (eloop_is_timeout_registered(hs20_continue_icon_fetch, wpa_s, NULL))
- return;
- /*
- * We are going through icon fetch, but no icon response was received.
- * Assume this means the current AP could not provide an answer to avoid
- * getting stuck in fetch iteration.
- */
- hs20_icon_fetch_failed(wpa_s);
-}
-
-
-static void hs20_free_osu_prov_entry(struct osu_provider *prov)
-{
-}
-
-
-void hs20_free_osu_prov(struct wpa_supplicant *wpa_s)
-{
- size_t i;
- for (i = 0; i < wpa_s->osu_prov_count; i++)
- hs20_free_osu_prov_entry(&wpa_s->osu_prov[i]);
- os_free(wpa_s->osu_prov);
- wpa_s->osu_prov = NULL;
- wpa_s->osu_prov_count = 0;
-}
-
-
-static void hs20_osu_fetch_done(struct wpa_supplicant *wpa_s)
-{
- char fname[256];
- FILE *f;
- size_t i, j;
-
- wpa_s->fetch_osu_info = 0;
- wpa_s->fetch_osu_icon_in_progress = 0;
-
- if (wpa_s->conf->osu_dir == NULL) {
- hs20_free_osu_prov(wpa_s);
- wpa_s->fetch_anqp_in_progress = 0;
- return;
- }
-
- snprintf(fname, sizeof(fname), "%s/osu-providers.txt",
- wpa_s->conf->osu_dir);
- f = fopen(fname, "w");
- if (f == NULL) {
- wpa_msg(wpa_s, MSG_INFO,
- "Could not write OSU provider information");
- hs20_free_osu_prov(wpa_s);
- wpa_s->fetch_anqp_in_progress = 0;
- return;
- }
-
- hs20_set_osu_access_permission(wpa_s->conf->osu_dir, fname);
-
- for (i = 0; i < wpa_s->osu_prov_count; i++) {
- struct osu_provider *osu = &wpa_s->osu_prov[i];
- if (i > 0)
- fprintf(f, "\n");
- fprintf(f, "OSU-PROVIDER " MACSTR "\n"
- "uri=%s\n"
- "methods=%08x\n",
- MAC2STR(osu->bssid), osu->server_uri, osu->osu_methods);
- if (osu->osu_ssid_len) {
- fprintf(f, "osu_ssid=%s\n",
- wpa_ssid_txt(osu->osu_ssid,
- osu->osu_ssid_len));
- }
- if (osu->osu_ssid2_len) {
- fprintf(f, "osu_ssid2=%s\n",
- wpa_ssid_txt(osu->osu_ssid2,
- osu->osu_ssid2_len));
- }
- if (osu->osu_nai[0])
- fprintf(f, "osu_nai=%s\n", osu->osu_nai);
- if (osu->osu_nai2[0])
- fprintf(f, "osu_nai2=%s\n", osu->osu_nai2);
- for (j = 0; j < osu->friendly_name_count; j++) {
- fprintf(f, "friendly_name=%s:%s\n",
- osu->friendly_name[j].lang,
- osu->friendly_name[j].text);
- }
- for (j = 0; j < osu->serv_desc_count; j++) {
- fprintf(f, "desc=%s:%s\n",
- osu->serv_desc[j].lang,
- osu->serv_desc[j].text);
- }
- for (j = 0; j < osu->icon_count; j++) {
- struct osu_icon *icon = &osu->icon[j];
- if (icon->failed)
- continue; /* could not fetch icon */
- fprintf(f, "icon=%u:%u:%u:%s:%s:%s\n",
- icon->id, icon->width, icon->height, icon->lang,
- icon->icon_type, icon->filename);
- }
- }
- fclose(f);
- hs20_free_osu_prov(wpa_s);
-
- wpa_msg(wpa_s, MSG_INFO, "OSU provider fetch completed");
- wpa_s->fetch_anqp_in_progress = 0;
-}
-
-
-void hs20_next_osu_icon(struct wpa_supplicant *wpa_s)
-{
- size_t i, j;
-
- wpa_printf(MSG_DEBUG, "HS 2.0: Ready to fetch next icon");
-
- for (i = 0; i < wpa_s->osu_prov_count; i++) {
- struct osu_provider *osu = &wpa_s->osu_prov[i];
- for (j = 0; j < osu->icon_count; j++) {
- struct osu_icon *icon = &osu->icon[j];
- if (icon->id || icon->failed)
- continue;
-
- wpa_printf(MSG_DEBUG, "HS 2.0: Try to fetch icon '%s' "
- "from " MACSTR, icon->filename,
- MAC2STR(osu->bssid));
- os_get_reltime(&wpa_s->osu_icon_fetch_start);
- if (hs20_anqp_send_req(wpa_s, osu->bssid,
- BIT(HS20_STYPE_ICON_REQUEST),
- (u8 *) icon->filename,
- os_strlen(icon->filename),
- 0) < 0) {
- icon->failed = 1;
- continue;
- }
- return;
- }
- }
-
- wpa_printf(MSG_DEBUG, "HS 2.0: No more icons to fetch");
- hs20_osu_fetch_done(wpa_s);
-}
-
-
-static void hs20_osu_add_prov(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
- const u8 *osu_ssid, u8 osu_ssid_len,
- const u8 *osu_ssid2, u8 osu_ssid2_len,
- const u8 *pos, size_t len)
-{
- struct osu_provider *prov;
- const u8 *end = pos + len;
- u16 len2;
- const u8 *pos2;
- u8 uri_len, osu_method_len, osu_nai_len;
-
- wpa_hexdump(MSG_DEBUG, "HS 2.0: Parsing OSU Provider", pos, len);
- prov = os_realloc_array(wpa_s->osu_prov,
- wpa_s->osu_prov_count + 1,
- sizeof(*prov));
- if (prov == NULL)
- return;
- wpa_s->osu_prov = prov;
- prov = &prov[wpa_s->osu_prov_count];
- os_memset(prov, 0, sizeof(*prov));
-
- os_memcpy(prov->bssid, bss->bssid, ETH_ALEN);
- os_memcpy(prov->osu_ssid, osu_ssid, osu_ssid_len);
- prov->osu_ssid_len = osu_ssid_len;
- if (osu_ssid2)
- os_memcpy(prov->osu_ssid2, osu_ssid2, osu_ssid2_len);
- prov->osu_ssid2_len = osu_ssid2_len;
-
- /* OSU Friendly Name Length */
- if (end - pos < 2) {
- wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU "
- "Friendly Name Length");
- return;
- }
- len2 = WPA_GET_LE16(pos);
- pos += 2;
- if (len2 > end - pos) {
- wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU "
- "Friendly Name Duples");
- return;
- }
- pos2 = pos;
- pos += len2;
-
- /* OSU Friendly Name Duples */
- while (pos - pos2 >= 4 && prov->friendly_name_count < OSU_MAX_ITEMS) {
- struct osu_lang_string *f;
- u8 slen;
-
- slen = pos2[0];
- if (1 + slen > pos - pos2) {
- wpa_printf(MSG_DEBUG, "Invalid OSU Friendly Name");
- break;
- }
- if (slen < 3) {
- wpa_printf(MSG_DEBUG,
- "Invalid OSU Friendly Name (no room for language)");
- break;
- }
- f = &prov->friendly_name[prov->friendly_name_count++];
- pos2++;
- os_memcpy(f->lang, pos2, 3);
- pos2 += 3;
- slen -= 3;
- os_memcpy(f->text, pos2, slen);
- pos2 += slen;
- }
-
- /* OSU Server URI */
- if (end - pos < 1) {
- wpa_printf(MSG_DEBUG,
- "HS 2.0: Not enough room for OSU Server URI length");
- return;
- }
- uri_len = *pos++;
- if (uri_len > end - pos) {
- wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU Server "
- "URI");
- return;
- }
- os_memcpy(prov->server_uri, pos, uri_len);
- pos += uri_len;
-
- /* OSU Method list */
- if (end - pos < 1) {
- wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU Method "
- "list length");
- return;
- }
- osu_method_len = pos[0];
- if (osu_method_len > end - pos - 1) {
- wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU Method "
- "list");
- return;
- }
- pos2 = pos + 1;
- pos += 1 + osu_method_len;
- while (pos2 < pos) {
- if (*pos2 < 32)
- prov->osu_methods |= BIT(*pos2);
- pos2++;
- }
-
- /* Icons Available Length */
- if (end - pos < 2) {
- wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for Icons "
- "Available Length");
- return;
- }
- len2 = WPA_GET_LE16(pos);
- pos += 2;
- if (len2 > end - pos) {
- wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for Icons "
- "Available");
- return;
- }
- pos2 = pos;
- pos += len2;
-
- /* Icons Available */
- while (pos2 < pos) {
- struct osu_icon *icon = &prov->icon[prov->icon_count];
- u8 flen;
-
- if (2 + 2 + 3 + 1 + 1 > pos - pos2) {
- wpa_printf(MSG_DEBUG, "HS 2.0: Invalid Icon Metadata");
- break;
- }
-
- icon->width = WPA_GET_LE16(pos2);
- pos2 += 2;
- icon->height = WPA_GET_LE16(pos2);
- pos2 += 2;
- os_memcpy(icon->lang, pos2, 3);
- pos2 += 3;
-
- flen = *pos2++;
- if (flen > pos - pos2) {
- wpa_printf(MSG_DEBUG, "HS 2.0: Not room for Icon Type");
- break;
- }
- os_memcpy(icon->icon_type, pos2, flen);
- pos2 += flen;
-
- if (pos - pos2 < 1) {
- wpa_printf(MSG_DEBUG, "HS 2.0: Not room for Icon "
- "Filename length");
- break;
- }
- flen = *pos2++;
- if (flen > pos - pos2) {
- wpa_printf(MSG_DEBUG, "HS 2.0: Not room for Icon "
- "Filename");
- break;
- }
- os_memcpy(icon->filename, pos2, flen);
- pos2 += flen;
-
- prov->icon_count++;
- }
-
- /* OSU_NAI */
- if (end - pos < 1) {
- wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU_NAI");
- return;
- }
- osu_nai_len = *pos++;
- if (osu_nai_len > end - pos) {
- wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU_NAI");
- return;
- }
- os_memcpy(prov->osu_nai, pos, osu_nai_len);
- pos += osu_nai_len;
-
- /* OSU Service Description Length */
- if (end - pos < 2) {
- wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU "
- "Service Description Length");
- return;
- }
- len2 = WPA_GET_LE16(pos);
- pos += 2;
- if (len2 > end - pos) {
- wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU "
- "Service Description Duples");
- return;
- }
- pos2 = pos;
- pos += len2;
-
- /* OSU Service Description Duples */
- while (pos - pos2 >= 4 && prov->serv_desc_count < OSU_MAX_ITEMS) {
- struct osu_lang_string *f;
- u8 descr_len;
-
- descr_len = *pos2++;
- if (descr_len > pos - pos2 || descr_len < 3) {
- wpa_printf(MSG_DEBUG, "Invalid OSU Service "
- "Description");
- break;
- }
- f = &prov->serv_desc[prov->serv_desc_count++];
- os_memcpy(f->lang, pos2, 3);
- os_memcpy(f->text, pos2 + 3, descr_len - 3);
- pos2 += descr_len;
- }
-
- wpa_printf(MSG_DEBUG, "HS 2.0: Added OSU Provider through " MACSTR,
- MAC2STR(bss->bssid));
- wpa_s->osu_prov_count++;
-}
-
-
-void hs20_osu_icon_fetch(struct wpa_supplicant *wpa_s)
-{
- struct wpa_bss *bss;
- struct wpabuf *prov_anqp;
- const u8 *pos, *end;
- u16 len;
- const u8 *osu_ssid, *osu_ssid2;
- u8 osu_ssid_len, osu_ssid2_len;
- u8 num_providers;
-
- hs20_free_osu_prov(wpa_s);
-
- dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
- if (bss->anqp == NULL)
- continue;
- prov_anqp = bss->anqp->hs20_osu_providers_list;
- if (prov_anqp == NULL)
- continue;
- osu_ssid2 = NULL;
- osu_ssid2_len = 0;
- wpa_printf(MSG_DEBUG, "HS 2.0: Parsing OSU Providers list from "
- MACSTR, MAC2STR(bss->bssid));
- wpa_hexdump_buf(MSG_DEBUG, "HS 2.0: OSU Providers list",
- prov_anqp);
- pos = wpabuf_head(prov_anqp);
- end = pos + wpabuf_len(prov_anqp);
-
- /* OSU SSID */
- if (end - pos < 1)
- continue;
- if (1 + pos[0] > end - pos) {
- wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for "
- "OSU SSID");
- continue;
- }
- osu_ssid_len = *pos++;
- if (osu_ssid_len > SSID_MAX_LEN) {
- wpa_printf(MSG_DEBUG, "HS 2.0: Invalid OSU SSID "
- "Length %u", osu_ssid_len);
- continue;
- }
- osu_ssid = pos;
- pos += osu_ssid_len;
-
- if (end - pos < 1) {
- wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for "
- "Number of OSU Providers");
- continue;
- }
- num_providers = *pos++;
- wpa_printf(MSG_DEBUG, "HS 2.0: Number of OSU Providers: %u",
- num_providers);
-
- /* OSU Providers */
- while (end - pos > 2 && num_providers > 0) {
- num_providers--;
- len = WPA_GET_LE16(pos);
- pos += 2;
- if (len > (unsigned int) (end - pos))
- break;
- hs20_osu_add_prov(wpa_s, bss, osu_ssid,
- osu_ssid_len, osu_ssid2,
- osu_ssid2_len, pos, len);
- pos += len;
- }
-
- if (pos != end) {
- wpa_printf(MSG_DEBUG, "HS 2.0: Ignored %d bytes of "
- "extra data after OSU Providers",
- (int) (end - pos));
- }
-
- prov_anqp = bss->anqp->hs20_osu_providers_nai_list;
- if (!prov_anqp)
- continue;
- wpa_printf(MSG_DEBUG,
- "HS 2.0: Parsing OSU Providers NAI List from "
- MACSTR, MAC2STR(bss->bssid));
- wpa_hexdump_buf(MSG_DEBUG, "HS 2.0: OSU Providers NAI List",
- prov_anqp);
- pos = wpabuf_head(prov_anqp);
- end = pos + wpabuf_len(prov_anqp);
- num_providers = 0;
- while (end - pos > 0) {
- len = *pos++;
- if (end - pos < len) {
- wpa_printf(MSG_DEBUG,
- "HS 2.0: Not enough room for OSU_NAI");
- break;
- }
- if (num_providers >= wpa_s->osu_prov_count) {
- wpa_printf(MSG_DEBUG,
- "HS 2.0: Ignore unexpected OSU Provider NAI List entries");
- break;
- }
- os_memcpy(wpa_s->osu_prov[num_providers].osu_nai2,
- pos, len);
- pos += len;
- num_providers++;
- }
- }
-
- wpa_s->fetch_osu_icon_in_progress = 1;
- hs20_next_osu_icon(wpa_s);
-}
-
-
-static void hs20_osu_scan_res_handler(struct wpa_supplicant *wpa_s,
- struct wpa_scan_results *scan_res)
-{
- wpa_printf(MSG_DEBUG, "OSU provisioning fetch scan completed");
- if (!wpa_s->fetch_osu_waiting_scan) {
- wpa_printf(MSG_DEBUG, "OSU fetch have been canceled");
- return;
- }
- wpa_s->network_select = 0;
- wpa_s->fetch_all_anqp = 1;
- wpa_s->fetch_osu_info = 1;
- wpa_s->fetch_osu_icon_in_progress = 0;
-
- interworking_start_fetch_anqp(wpa_s);
-}
-
-
-int hs20_fetch_osu(struct wpa_supplicant *wpa_s, int skip_scan)
-{
- if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
- wpa_printf(MSG_DEBUG, "HS 2.0: Cannot start fetch_osu - "
- "interface disabled");
- return -1;
- }
-
- if (wpa_s->scanning) {
- wpa_printf(MSG_DEBUG, "HS 2.0: Cannot start fetch_osu - "
- "scanning");
- return -1;
- }
-
- if (wpa_s->conf->osu_dir == NULL) {
- wpa_printf(MSG_DEBUG, "HS 2.0: Cannot start fetch_osu - "
- "osu_dir not configured");
- return -1;
- }
-
- if (wpa_s->fetch_anqp_in_progress || wpa_s->network_select) {
- wpa_printf(MSG_DEBUG, "HS 2.0: Cannot start fetch_osu - "
- "fetch in progress (%d, %d)",
- wpa_s->fetch_anqp_in_progress,
- wpa_s->network_select);
- return -1;
- }
-
- wpa_msg(wpa_s, MSG_INFO, "Starting OSU provisioning information fetch");
- wpa_s->num_osu_scans = 0;
- wpa_s->num_prov_found = 0;
- if (skip_scan) {
- wpa_s->network_select = 0;
- wpa_s->fetch_all_anqp = 1;
- wpa_s->fetch_osu_info = 1;
- wpa_s->fetch_osu_icon_in_progress = 0;
-
- interworking_start_fetch_anqp(wpa_s);
- } else {
- hs20_start_osu_scan(wpa_s);
- }
-
- return 0;
-}
-
-
-void hs20_start_osu_scan(struct wpa_supplicant *wpa_s)
-{
- wpa_s->fetch_osu_waiting_scan = 1;
- wpa_s->num_osu_scans++;
- wpa_s->scan_req = MANUAL_SCAN_REQ;
- wpa_s->scan_res_handler = hs20_osu_scan_res_handler;
- wpa_supplicant_req_scan(wpa_s, 0, 0);
-}
-
-
-void hs20_cancel_fetch_osu(struct wpa_supplicant *wpa_s)
-{
- wpa_printf(MSG_DEBUG, "Cancel OSU fetch");
- interworking_stop_fetch_anqp(wpa_s);
- wpa_s->fetch_osu_waiting_scan = 0;
- wpa_s->network_select = 0;
- wpa_s->fetch_osu_info = 0;
- wpa_s->fetch_osu_icon_in_progress = 0;
-}
-
-
-void hs20_icon_fetch_failed(struct wpa_supplicant *wpa_s)
-{
- hs20_osu_icon_fetch_result(wpa_s, -1);
- eloop_cancel_timeout(hs20_continue_icon_fetch, wpa_s, NULL);
- eloop_register_timeout(0, 0, hs20_continue_icon_fetch, wpa_s, NULL);
-}
-
-
void hs20_rx_subscription_remediation(struct wpa_supplicant *wpa_s,
const char *url, u8 osu_method)
{
wpas_notify_hs20_t_c_acceptance(wpa_s, url);
}
-
-
-void hs20_init(struct wpa_supplicant *wpa_s)
-{
- dl_list_init(&wpa_s->icon_head);
-}
-
-
-void hs20_deinit(struct wpa_supplicant *wpa_s)
-{
- eloop_cancel_timeout(hs20_continue_icon_fetch, wpa_s, NULL);
- hs20_free_osu_prov(wpa_s);
- if (wpa_s->icon_head.next)
- hs20_del_icon(wpa_s, NULL, NULL);
-}
const struct wpa_ssid *ssid);
int hs20_anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, u32 stypes,
- const u8 *payload, size_t payload_len, int inmem);
+ const u8 *payload, size_t payload_len);
void hs20_put_anqp_req(u32 stypes, const u8 *payload, size_t payload_len,
struct wpabuf *buf);
void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s,
int is_hs20_network(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
struct wpa_bss *bss);
int hs20_get_pps_mo_id(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
-void hs20_notify_parse_done(struct wpa_supplicant *wpa_s);
void hs20_rx_subscription_remediation(struct wpa_supplicant *wpa_s,
const char *url, u8 osu_method);
u16 reauth_delay, const char *url);
void hs20_rx_t_c_acceptance(struct wpa_supplicant *wpa_s, const char *url);
-void hs20_free_osu_prov(struct wpa_supplicant *wpa_s);
-void hs20_next_osu_icon(struct wpa_supplicant *wpa_s);
-void hs20_osu_icon_fetch(struct wpa_supplicant *wpa_s);
-int hs20_fetch_osu(struct wpa_supplicant *wpa_s, int skip_scan);
-void hs20_cancel_fetch_osu(struct wpa_supplicant *wpa_s);
-void hs20_icon_fetch_failed(struct wpa_supplicant *wpa_s);
-void hs20_start_osu_scan(struct wpa_supplicant *wpa_s);
-void hs20_init(struct wpa_supplicant *wpa_s);
-void hs20_deinit(struct wpa_supplicant *wpa_s);
-int hs20_get_icon(struct wpa_supplicant *wpa_s, const u8 *bssid,
- const char *file_name, size_t offset, size_t size,
- char *reply, size_t buf_len);
-int hs20_del_icon(struct wpa_supplicant *wpa_s, const u8 *bssid,
- const char *file_name);
#endif /* HS20_SUPPLICANT_H */
wpabuf_put_u8(extra, HS20_STYPE_CONNECTION_CAPABILITY);
if (all)
wpabuf_put_u8(extra, HS20_STYPE_OPERATING_CLASS);
- if (all) {
- wpabuf_put_u8(extra, HS20_STYPE_OSU_PROVIDERS_LIST);
- wpabuf_put_u8(extra, HS20_STYPE_OSU_PROVIDERS_NAI_LIST);
- }
gas_anqp_set_element_len(extra, len_pos);
}
#endif /* CONFIG_HS20 */
int found = 0;
wpa_printf(MSG_DEBUG, "Interworking: next_anqp_fetch - "
- "fetch_anqp_in_progress=%d fetch_osu_icon_in_progress=%d",
- wpa_s->fetch_anqp_in_progress,
- wpa_s->fetch_osu_icon_in_progress);
+ "fetch_anqp_in_progress=%d",
+ wpa_s->fetch_anqp_in_progress);
if (eloop_terminated() || !wpa_s->fetch_anqp_in_progress) {
wpa_printf(MSG_DEBUG, "Interworking: Stop next-ANQP-fetch");
return;
}
-#ifdef CONFIG_HS20
- if (wpa_s->fetch_osu_icon_in_progress) {
- wpa_printf(MSG_DEBUG, "Interworking: Next icon (in progress)");
- hs20_next_osu_icon(wpa_s);
- return;
- }
-#endif /* CONFIG_HS20 */
-
dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
if (!(bss->caps & IEEE80211_CAP_ESS))
continue;
}
if (found == 0) {
-#ifdef CONFIG_HS20
- if (wpa_s->fetch_osu_info) {
- if (wpa_s->num_prov_found == 0 &&
- wpa_s->fetch_osu_waiting_scan &&
- wpa_s->num_osu_scans < 3) {
- wpa_printf(MSG_DEBUG, "HS 2.0: No OSU providers seen - try to scan again");
- hs20_start_osu_scan(wpa_s);
- return;
- }
- wpa_printf(MSG_DEBUG, "Interworking: Next icon");
- hs20_osu_icon_fetch(wpa_s);
- return;
- }
-#endif /* CONFIG_HS20 */
wpa_msg(wpa_s, MSG_INFO, "ANQP fetch completed");
wpa_s->fetch_anqp_in_progress = 0;
if (wpa_s->network_select)
wpa_s->network_select = 0;
wpa_s->fetch_all_anqp = 1;
- wpa_s->fetch_osu_info = 0;
interworking_start_fetch_anqp(wpa_s);
" dialog_token=%u result=%d status_code=%u",
MAC2STR(dst), dialog_token, result, status_code);
if (result != GAS_QUERY_SUCCESS) {
-#ifdef CONFIG_HS20
- if (wpa_s->fetch_osu_icon_in_progress)
- hs20_icon_fetch_failed(wpa_s);
-#endif /* CONFIG_HS20 */
anqp_result = "FAILURE";
goto out;
}
pos[1] < 2 || pos[3] != ACCESS_NETWORK_QUERY_PROTOCOL) {
wpa_msg(wpa_s, MSG_DEBUG,
"ANQP: Unexpected Advertisement Protocol in response");
-#ifdef CONFIG_HS20
- if (wpa_s->fetch_osu_icon_in_progress)
- hs20_icon_fetch_failed(wpa_s);
-#endif /* CONFIG_HS20 */
anqp_result = "INVALID_FRAME";
goto out;
}
out_parse_done:
if (bss)
wpas_notify_bss_anqp_changed(wpa_s, bss->id);
-#ifdef CONFIG_HS20
- hs20_notify_parse_done(wpa_s);
-#endif /* CONFIG_HS20 */
out:
wpas_notify_anqp_query_done(wpa_s, dst, anqp_result);
}
wpa_s->auto_network_select = 0;
wpa_s->auto_select = !!auto_select;
wpa_s->fetch_all_anqp = 0;
- wpa_s->fetch_osu_info = 0;
wpa_msg(wpa_s, MSG_DEBUG,
"Interworking: Start scan for network selection");
wpa_s->scan_res_handler = interworking_scan_res_handler;
"ap_vendor_elements", "ignore_old_scan_res", "freq_list",
"scan_cur_freq", "scan_res_valid_for_connect",
"sched_scan_interval",
- "tdls_external_control", "osu_dir", "wowlan_triggers",
+ "tdls_external_control", "wowlan_triggers",
"p2p_search_delay", "mac_addr", "rand_addr_lifetime",
"preassoc_mac_addr", "key_mgmt_offload", "passive_scan",
"reassoc_same_bss_optim", "wps_priority",
"scan_cur_freq", "scan_res_valid_for_connect",
"sched_scan_interval",
"sched_scan_start_delay",
- "tdls_external_control", "osu_dir", "wowlan_triggers",
+ "tdls_external_control", "wowlan_triggers",
"p2p_search_delay", "mac_addr", "rand_addr_lifetime",
"preassoc_mac_addr", "key_mgmt_offload", "passive_scan",
"reassoc_same_bss_optim", "extended_key_id"
return wpa_ctrl_command(ctrl, cmd);
}
-
-static int wpa_cli_cmd_hs20_icon_request(struct wpa_ctrl *ctrl, int argc,
- char *argv[])
-{
- char cmd[512];
-
- if (argc < 2) {
- printf("Command needs two arguments (dst mac addr and "
- "icon name)\n");
- return -1;
- }
-
- if (write_cmd(cmd, sizeof(cmd), "HS20_ICON_REQUEST", argc, argv) < 0)
- return -1;
-
- return wpa_ctrl_command(ctrl, cmd);
-}
-
-
-static int wpa_cli_cmd_fetch_osu(struct wpa_ctrl *ctrl, int argc, char *argv[])
-{
- return wpa_ctrl_command(ctrl, "FETCH_OSU");
-}
-
-
-static int wpa_cli_cmd_cancel_fetch_osu(struct wpa_ctrl *ctrl, int argc,
- char *argv[])
-{
- return wpa_ctrl_command(ctrl, "CANCEL_FETCH_OSU");
-}
-
#endif /* CONFIG_HS20 */
{ "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
wpa_cli_complete_bss, cli_cmd_flag_none,
"<addr> <home realm> = get HS20 nai home realm list" },
- { "hs20_icon_request", wpa_cli_cmd_hs20_icon_request,
- wpa_cli_complete_bss, cli_cmd_flag_none,
- "<addr> <icon name> = get Hotspot 2.0 OSU icon" },
- { "fetch_osu", wpa_cli_cmd_fetch_osu, NULL, cli_cmd_flag_none,
- "= fetch OSU provider information from all APs" },
- { "cancel_fetch_osu", wpa_cli_cmd_cancel_fetch_osu, NULL,
- cli_cmd_flag_none,
- "= cancel fetch_osu command" },
#endif /* CONFIG_HS20 */
{ "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
cli_cmd_flag_none,
#ifdef CONFIG_HS20
if (wpa_s->drv_priv)
wpa_drv_configure_frame_filters(wpa_s, 0);
- hs20_deinit(wpa_s);
#endif /* CONFIG_HS20 */
for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
-#ifdef CONFIG_HS20
- hs20_init(wpa_s);
-#endif /* CONFIG_HS20 */
#ifdef CONFIG_MBO
if (!wpa_s->disable_mbo_oce && wpa_s->conf->oce) {
if ((wpa_s->conf->oce & OCE_STA) &&
WPAS_TEST_FAILURE_SCAN_TRIGGER,
};
-struct icon_entry {
- struct dl_list list;
- u8 bssid[ETH_ALEN];
- u8 dialog_token;
- char *file_name;
- u8 *image;
- size_t image_len;
-};
-
struct wpa_bss_tmp_disallowed {
struct dl_list list;
u8 bssid[ETH_ALEN];
unsigned int auto_network_select:1;
unsigned int interworking_fast_assoc_tried:1;
unsigned int fetch_all_anqp:1;
- unsigned int fetch_osu_info:1;
- unsigned int fetch_osu_waiting_scan:1;
- unsigned int fetch_osu_icon_in_progress:1;
struct wpa_bss *interworking_gas_bss;
- unsigned int osu_icon_id;
- struct dl_list icon_head; /* struct icon_entry */
- struct osu_provider *osu_prov;
- size_t osu_prov_count;
- struct os_reltime osu_icon_fetch_start;
- unsigned int num_osu_scans;
- unsigned int num_prov_found;
#endif /* CONFIG_INTERWORKING */
unsigned int drv_capa_known;