diff --git a/hostapd/Makefile b/hostapd/Makefile index 9664c028d..bc468c599 100644 --- a/hostapd/Makefile +++ b/hostapd/Makefile @@ -744,6 +744,10 @@ CFLAGS += -DCONFIG_P2P_MANAGER OBJS += ../src/ap/p2p_hostapd.o endif +ifdef CONFIG_INTERWORKING +CFLAGS += -DCONFIG_INTERWORKING +endif + ifdef CONFIG_WPA_CLI_EDIT OBJS_c += ../src/utils/edit.o else diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 6ffa98137..a148e399f 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -2058,6 +2058,38 @@ struct hostapd_config * hostapd_config_read(const char *fname) extern int rsn_testing; rsn_testing = atoi(pos); #endif /* CONFIG_RSN_TESTING */ +#ifdef CONFIG_INTERWORKING + } else if (os_strcmp(buf, "interworking") == 0) { + bss->interworking = atoi(pos); + } else if (os_strcmp(buf, "access_network_type") == 0) { + bss->access_network_type = atoi(pos); + if (bss->access_network_type < 0 || + bss->access_network_type > 15) { + wpa_printf(MSG_ERROR, "Line %d: invalid " + "access_network_type", line); + errors++; + } + } else if (os_strcmp(buf, "internet") == 0) { + bss->internet = atoi(pos); + } else if (os_strcmp(buf, "asra") == 0) { + bss->asra = atoi(pos); + } else if (os_strcmp(buf, "esr") == 0) { + bss->esr = atoi(pos); + } else if (os_strcmp(buf, "uesa") == 0) { + bss->uesa = atoi(pos); + } else if (os_strcmp(buf, "venue_group") == 0) { + bss->venue_group = atoi(pos); + bss->venue_info_set = 1; + } else if (os_strcmp(buf, "venue_type") == 0) { + bss->venue_type = atoi(pos); + bss->venue_info_set = 1; + } else if (os_strcmp(buf, "hessid") == 0) { + if (hwaddr_aton(pos, bss->hessid)) { + wpa_printf(MSG_ERROR, "Line %d: invalid " + "hessid", line); + errors++; + } +#endif /* CONFIG_INTERWORKING */ } else { wpa_printf(MSG_ERROR, "Line %d: unknown configuration " "item '%s'", line, buf); diff --git a/hostapd/defconfig b/hostapd/defconfig index 97af2d3fc..36f286f0c 100644 --- a/hostapd/defconfig +++ b/hostapd/defconfig @@ -236,3 +236,8 @@ CONFIG_IPV6=y # can be configured to include faster routines for exptmod, sqr, and div to # speed up DH and RSA calculation considerably #CONFIG_INTERNAL_LIBTOMMATH_FAST=y + +# Interworking (IEEE 802.11u) +# This can be used to enable functionality to improve interworking with +# external networks. +#CONFIG_INTERWORKING=y diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index 5384ee793..be0272060 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -1023,6 +1023,55 @@ own_ip_addr=127.0.0.1 # Prohibit use of TDLS Channel Switching in this BSS #tdls_prohibit_chan_switch=1 +##### IEEE 802.11u-2011 ####################################################### + +# Enable Interworking service +#interworking=1 + +# Access Network Type +# 0 = Private network +# 1 = Private network with guest access +# 2 = Chargeable public network +# 3 = Free public network +# 4 = Personal device network +# 5 = Emergency services only network +# 14 = Test or experimental +# 15 = Wildcard +#access_network_type=0 + +# Whether the network provides connectivity to the Internet +# 0 = Unspecified +# 1 = Network provides connectivity to the Internet +#internet=1 + +# Additional Step Required for Access +# Note: This is only used with open network, i.e., ASRA shall ne set to 0 if +# RSN is used. +#asra=0 + +# Emergency services reachable +#esr=0 + +# Unauthenticated emergency service accessible +#uesa=0 + +# Venue Info (optional) +# The available values are defined in IEEE Std 802.11u-2011, 7.3.1.34. +# Example values (group,type): +# 0,0 = Unspecified +# 1,7 = Convention Center +# 1,13 = Coffee Shop +# 2,0 = Unspecified Business +# 7,1 Private Residence +#venue_group=7 +#venue_type=1 + +# Homogeneous ESS identifier (optional; dot11HESSID) +# If set, this shall be identifical to one of the BSSIDs in the homogeneous +# ESS and this shall be set to the same value across all BSSs in homogeneous +# ESS. +#hessid=02:03:04:05:06:07 + ##### Multiple BSSID support ################################################## # # Above configuration is using the default interface (wlan#, or multi-SSID VLAN diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 09eed5abd..46975f774 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -334,6 +334,18 @@ struct hostapd_bss_config { #define TDLS_PROHIBIT_CHAN_SWITCH BIT(1) int tdls; int disable_11n; + + /* IEEE 802.11u - Interworking */ + int interworking; + int access_network_type; + int internet; + int asra; + int esr; + int uesa; + int venue_info_set; + u8 venue_group; + u8 venue_type; + u8 hessid[ETH_ALEN]; }; diff --git a/src/ap/beacon.c b/src/ap/beacon.c index 7a4b267bb..4fd403335 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -197,6 +197,46 @@ static u8 * hostapd_eid_wpa(struct hostapd_data *hapd, u8 *eid, size_t len, } +static u8 * hostapd_eid_interworking(struct hostapd_data *hapd, u8 *eid) +{ + u8 *pos = eid; +#ifdef CONFIG_INTERWORKING + u8 *len; + + if (!hapd->conf->interworking) + return eid; + + *pos++ = WLAN_EID_INTERWORKING; + len = pos++; + + *pos = hapd->conf->access_network_type; + if (hapd->conf->internet) + *pos |= INTERWORKING_ANO_INTERNET; + if (hapd->conf->asra) + *pos |= INTERWORKING_ANO_ASRA; + if (hapd->conf->esr) + *pos |= INTERWORKING_ANO_ESR; + if (hapd->conf->uesa) + *pos |= INTERWORKING_ANO_UESA; + pos++; + + if (hapd->conf->venue_info_set) { + *pos++ = hapd->conf->venue_group; + *pos++ = hapd->conf->venue_type; + } + + if (!is_zero_ether_addr(hapd->conf->hessid)) { + os_memcpy(pos, hapd->conf->hessid, ETH_ALEN); + pos += ETH_ALEN; + } + + *len = pos - len - 1; +#endif /* CONFIG_INTERWORKING */ + + return pos; +} + + void handle_probe_req(struct hostapd_data *hapd, const struct ieee80211_mgmt *mgmt, size_t len) { @@ -356,6 +396,8 @@ void handle_probe_req(struct hostapd_data *hapd, pos = hostapd_eid_ext_capab(hapd, pos); + pos = hostapd_eid_interworking(hapd, pos); + /* Wi-Fi Alliance WMM */ pos = hostapd_eid_wmm(hapd, pos); @@ -486,6 +528,8 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd) tailpos = hostapd_eid_ext_capab(hapd, tailpos); + tailpos = hostapd_eid_interworking(hapd, tailpos); + /* Wi-Fi Alliance WMM */ tailpos = hostapd_eid_wmm(hapd, tailpos); diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 7293957a4..8e4301550 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -166,17 +166,28 @@ u16 hostapd_own_capab_info(struct hostapd_data *hapd, struct sta_info *sta, u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid) { u8 *pos = eid; + u8 len = 0; - if ((hapd->conf->tdls & (TDLS_PROHIBIT | TDLS_PROHIBIT_CHAN_SWITCH)) == - 0) + if (hapd->conf->tdls & (TDLS_PROHIBIT | TDLS_PROHIBIT_CHAN_SWITCH)) + len = 5; + if (len < 4 && hapd->conf->interworking) + len = 4; + if (len == 0) return eid; *pos++ = WLAN_EID_EXT_CAPAB; - *pos++ = 5; - *pos++ = 0x00; + *pos++ = len; *pos++ = 0x00; *pos++ = 0x00; *pos++ = 0x00; + + *pos = 0x00; + if (hapd->conf->interworking) + *pos |= 0x80; /* Bit 31 - Interworking */ + pos++; + + if (len < 5) + return pos; *pos = 0x00; if (hapd->conf->tdls & TDLS_PROHIBIT) *pos |= 0x40; /* Bit 38 - TDLS Prohibited */ diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 1c3d3cf8e..e51024554 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -224,6 +224,7 @@ #define WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS 74 #define WLAN_EID_MMIE 76 #define WLAN_EID_LINK_ID 101 +#define WLAN_EID_INTERWORKING 107 #define WLAN_EID_ADV_PROTO 108 #define WLAN_EID_EXT_CAPAB 127 #define WLAN_EID_VENDOR_SPECIFIC 221 @@ -274,6 +275,13 @@ #define WLAN_TIMEOUT_KEY_LIFETIME 2 #define WLAN_TIMEOUT_ASSOC_COMEBACK 3 +/* Interworking element (IEEE 802.11u) - Access Network Options */ +#define INTERWORKING_ANO_ACCESS_NETWORK_MASK 0x0f +#define INTERWORKING_ANO_INTERNET 0x10 +#define INTERWORKING_ANO_ASRA 0x20 +#define INTERWORKING_ANO_ESR 0x40 +#define INTERWORKING_ANO_UESA 0x80 + /* Advertisement Protocol ID definitions (IEEE Std 802.11u-2011) */ enum adv_proto_id { ACCESS_NETWORK_QUERY_PROTOCOL = 0,