diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 0279cd7f3..e4da5b99f 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -1513,6 +1513,19 @@ fail: os_free(wan_metrics); return -1; } + + +static int hs20_parse_oper_friendly_name(struct hostapd_bss_config *bss, + char *pos, int line) +{ + if (parse_lang_string(&bss->hs20_oper_friendly_name, + &bss->hs20_oper_friendly_name_count, pos)) { + wpa_printf(MSG_ERROR, "Line %d: Invalid " + "hs20_oper_friendly_name '%s'", line, pos); + return -1; + } + return 0; +} #endif /* CONFIG_HS20 */ @@ -2681,6 +2694,9 @@ static int hostapd_config_fill(struct hostapd_config *conf, bss->hs20 = atoi(pos); } else if (os_strcmp(buf, "disable_dgaf") == 0) { bss->disable_dgaf = atoi(pos); + } else if (os_strcmp(buf, "hs20_oper_friendly_name") == 0) { + if (hs20_parse_oper_friendly_name(bss, pos, line) < 0) + errors++; } else if (os_strcmp(buf, "hs20_wan_metrics") == 0) { if (hs20_parse_wan_metrics(bss, pos, line) < 0) { errors++; diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index 95a9835e9..b6e338054 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -1400,6 +1400,13 @@ own_ip_addr=127.0.0.1 # forging such frames to other stations in the BSS. #disable_dgaf=1 +# Operator Friendly Name +# This parameter can be used to configure one or more Operator Friendly Name +# Duples. Each entry has a two or three character language code (ISO-639) +# separated by colon from the operator friendly name string. +#hs20_oper_friendly_name=eng:Example operator +#hs20_oper_friendly_name=fin:Esimerkkioperaattori + # Connection Capability # This can be used to advertise what type of IP traffic can be sent through the # hotspot (e.g., due to firewall allowing/blocking protocols/ports). diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index a2f226e2f..e88548124 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -507,6 +507,7 @@ static void hostapd_config_free_bss(struct hostapd_bss_config *conf) #endif /* CONFIG_RADIUS_TEST */ #ifdef CONFIG_HS20 + os_free(conf->hs20_oper_friendly_name); os_free(conf->hs20_wan_metrics); os_free(conf->hs20_connection_capability); os_free(conf->hs20_operating_class); diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 0077a98b3..13f725530 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -410,6 +410,8 @@ struct hostapd_bss_config { #ifdef CONFIG_HS20 int hs20; int disable_dgaf; + unsigned int hs20_oper_friendly_name_count; + struct hostapd_lang_string *hs20_oper_friendly_name; u8 *hs20_wan_metrics; u8 *hs20_connection_capability; size_t hs20_connection_capability_len; diff --git a/src/ap/gas_serv.c b/src/ap/gas_serv.c index 3951a0772..4699a3aa9 100644 --- a/src/ap/gas_serv.c +++ b/src/ap/gas_serv.c @@ -139,6 +139,8 @@ static void anqp_add_hs_capab_list(struct hostapd_data *hapd, wpabuf_put_u8(buf, HS20_STYPE_CAPABILITY_LIST); wpabuf_put_u8(buf, 0); /* Reserved */ wpabuf_put_u8(buf, HS20_STYPE_CAPABILITY_LIST); + if (hapd->conf->hs20_oper_friendly_name) + wpabuf_put_u8(buf, HS20_STYPE_OPERATOR_FRIENDLY_NAME); if (hapd->conf->hs20_wan_metrics) wpabuf_put_u8(buf, HS20_STYPE_WAN_METRICS); if (hapd->conf->hs20_connection_capability) @@ -257,6 +259,30 @@ static void anqp_add_domain_name(struct hostapd_data *hapd, struct wpabuf *buf) } +static void anqp_add_operator_friendly_name(struct hostapd_data *hapd, + struct wpabuf *buf) +{ + if (hapd->conf->hs20_oper_friendly_name) { + u8 *len; + unsigned int i; + 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_FRIENDLY_NAME); + wpabuf_put_u8(buf, 0); /* Reserved */ + for (i = 0; i < hapd->conf->hs20_oper_friendly_name_count; i++) + { + struct hostapd_lang_string *vn; + vn = &hapd->conf->hs20_oper_friendly_name[i]; + wpabuf_put_u8(buf, 3 + vn->name_len); + wpabuf_put_data(buf, vn->lang, 3); + wpabuf_put_data(buf, vn->name, vn->name_len); + } + gas_anqp_set_element_len(buf, len); + } +} + + static void anqp_add_wan_metrics(struct hostapd_data *hapd, struct wpabuf *buf) { @@ -332,6 +358,8 @@ gas_serv_build_gas_resp_payload(struct hostapd_data *hapd, if (request & ANQP_REQ_HS_CAPABILITY_LIST) anqp_add_hs_capab_list(hapd, buf); + if (request & ANQP_REQ_OPERATOR_FRIENDLY_NAME) + anqp_add_operator_friendly_name(hapd, buf); if (request & ANQP_REQ_WAN_METRICS) anqp_add_wan_metrics(hapd, buf); if (request & ANQP_REQ_CONNECTION_CAPABILITY) @@ -449,6 +477,12 @@ static void rx_anqp_hs_query_list(struct hostapd_data *hapd, u8 subtype, set_anqp_req(ANQP_REQ_HS_CAPABILITY_LIST, "HS Capability List", 1, 0, 0, qi); break; + case HS20_STYPE_OPERATOR_FRIENDLY_NAME: + set_anqp_req(ANQP_REQ_OPERATOR_FRIENDLY_NAME, + "Operator Friendly Name", + hapd->conf->hs20_oper_friendly_name != NULL, + 0, 0, qi); + break; case HS20_STYPE_WAN_METRICS: set_anqp_req(ANQP_REQ_WAN_METRICS, "WAN Metrics", hapd->conf->hs20_wan_metrics != NULL, diff --git a/src/ap/gas_serv.h b/src/ap/gas_serv.h index 390252528..1d6db3631 100644 --- a/src/ap/gas_serv.h +++ b/src/ap/gas_serv.h @@ -25,6 +25,8 @@ (1 << (ANQP_DOMAIN_NAME - ANQP_QUERY_LIST)) #define ANQP_REQ_HS_CAPABILITY_LIST \ (0x10000 << HS20_STYPE_CAPABILITY_LIST) +#define ANQP_REQ_OPERATOR_FRIENDLY_NAME \ + (0x10000 << HS20_STYPE_OPERATOR_FRIENDLY_NAME) #define ANQP_REQ_WAN_METRICS \ (0x10000 << HS20_STYPE_WAN_METRICS) #define ANQP_REQ_CONNECTION_CAPABILITY \