HS 2.0: Allow configuration of operator icons

This extends hostapd Hotspot 2.0 implementation to allow operator icons
to be made available. The existing hs20_icon parameter is used to define
the icons and the new operator_icon parameter (zero or more entries) is
used to specify which of the available icons are operator icons. The
operator icons are advertised in the Operator Icon Metadata ANQP-element
while the icon data can be fetched using the same mechanism (icon
request/binary file) that was added for the OSU Providers icons.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
Jouni Malinen 2018-04-16 13:18:57 +03:00 committed by Jouni Malinen
parent 6a8a04d742
commit 0e450db285
6 changed files with 99 additions and 21 deletions

View File

@ -2023,6 +2023,25 @@ static int hs20_parse_osu_service_desc(struct hostapd_bss_config *bss,
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 */
@ -3602,6 +3621,9 @@ static int hostapd_config_fill(struct hostapd_config *conf,
} 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);

View File

@ -2158,7 +2158,7 @@ own_ip_addr=127.0.0.1
# channels 36-48):
#hs20_operating_class=5173
# OSU icons
# 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
@ -2184,6 +2184,13 @@ own_ip_addr=127.0.0.1
#
#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

View File

@ -612,6 +612,13 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
}
os_free(conf->hs20_osu_providers);
}
if (conf->hs20_operator_icon) {
size_t i;
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);
#endif /* CONFIG_HS20 */

View File

@ -580,6 +580,8 @@ struct hostapd_bss_config {
struct hostapd_lang_string *service_desc;
} *hs20_osu_providers, *last_osu;
size_t hs20_osu_providers_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;

View File

@ -183,6 +183,8 @@ static void anqp_add_hs_capab_list(struct hostapd_data *hapd,
wpabuf_put_u8(buf, HS20_STYPE_OSU_PROVIDERS_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 */
@ -703,6 +705,29 @@ static void anqp_add_operating_class(struct hostapd_data *hapd,
}
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)
@ -737,26 +762,8 @@ static void anqp_add_osu_provider(struct wpabuf *buf,
/* Icons Available */
len2 = wpabuf_put(buf, 2);
for (i = 0; i < p->icons_count; i++) {
size_t j;
struct hs20_icon *icon = NULL;
for (j = 0; j < bss->hs20_icons_count && !icon; j++) {
if (os_strcmp(p->icons[i], bss->hs20_icons[j].name) ==
0)
icon = &bss->hs20_icons[j];
}
if (!icon)
continue; /* 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);
}
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 */
@ -865,6 +872,30 @@ static void anqp_add_icon_binary_file(struct hostapd_data *hapd,
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 */
@ -991,6 +1022,8 @@ gas_serv_build_gas_resp_payload(struct hostapd_data *hapd,
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);
#endif /* CONFIG_HS20 */
#ifdef CONFIG_MBO
@ -1178,6 +1211,11 @@ static void rx_anqp_hs_query_list(struct hostapd_data *hapd, u8 subtype,
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;
default:
wpa_printf(MSG_DEBUG, "ANQP: Unsupported HS 2.0 subtype %u",
subtype);

View File

@ -60,6 +60,8 @@
(0x10000 << HS20_STYPE_OSU_PROVIDERS_LIST)
#define ANQP_REQ_ICON_REQUEST \
(0x10000 << HS20_STYPE_ICON_REQUEST)
#define ANQP_REQ_OPERATOR_ICON_METADATA \
(0x10000 << HS20_STYPE_OPERATOR_ICON_METADATA)
/* The first MBO ANQP-element can be included in the optimized bitmap. */
#define ANQP_REQ_MBO_CELL_DATA_CONN_PREF \
(BIT(29) << MBO_ANQP_SUBTYPE_CELL_CONN_PREF)