diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ap/ap_config.c | 2 | ||||
-rw-r--r-- | src/ap/ap_config.h | 4 | ||||
-rw-r--r-- | src/ap/ap_drv_ops.c | 14 | ||||
-rw-r--r-- | src/ap/beacon.c | 9 | ||||
-rw-r--r-- | src/ap/hostapd.c | 2 | ||||
-rw-r--r-- | src/ap/hostapd.h | 4 | ||||
-rw-r--r-- | src/ap/ieee802_11.h | 3 | ||||
-rw-r--r-- | src/ap/ieee802_11_shared.c | 91 | ||||
-rw-r--r-- | src/common/ieee802_11_defs.h | 2 |
9 files changed, 131 insertions, 0 deletions
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index 0e6f476..cfb6b2d 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -426,6 +426,8 @@ static void hostapd_config_free_bss(struct hostapd_bss_config *conf) ssid->dyn_vlan_keys = NULL; } + os_free(conf->time_zone); + #ifdef CONFIG_IEEE80211R { struct ft_remote_r0kh *r0kh, *r0kh_prev; diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index ce63a10..7748fd7 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -342,6 +342,10 @@ struct hostapd_bss_config { int tdls; int disable_11n; + /* IEEE 802.11v */ + int time_advertisement; + char *time_zone; + /* IEEE 802.11u - Interworking */ int interworking; int access_network_type; diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c index b585650..31a8ee6 100644 --- a/src/ap/ap_drv_ops.c +++ b/src/ap/ap_drv_ops.c @@ -52,6 +52,20 @@ int hostapd_build_ap_extra_ies(struct hostapd_data *hapd, *beacon_ret = *proberesp_ret = *assocresp_ret = NULL; pos = buf; + pos = hostapd_eid_time_adv(hapd, pos); + if (pos != buf) { + if (wpabuf_resize(&beacon, pos - buf) != 0) + goto fail; + wpabuf_put_data(beacon, buf, pos - buf); + } + pos = hostapd_eid_time_zone(hapd, pos); + if (pos != buf) { + if (wpabuf_resize(&proberesp, pos - buf) != 0) + goto fail; + wpabuf_put_data(proberesp, buf, pos - buf); + } + + pos = buf; pos = hostapd_eid_ext_capab(hapd, pos); if (pos != buf) { if (wpabuf_resize(&assocresp, pos - buf) != 0) diff --git a/src/ap/beacon.c b/src/ap/beacon.c index 696d5e4..831506c 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -357,6 +357,9 @@ void handle_probe_req(struct hostapd_data *hapd, pos = hostapd_eid_ext_capab(hapd, pos); + pos = hostapd_eid_time_adv(hapd, pos); + pos = hostapd_eid_time_zone(hapd, pos); + pos = hostapd_eid_interworking(hapd, pos); pos = hostapd_eid_adv_proto(hapd, pos); pos = hostapd_eid_roaming_consortium(hapd, pos); @@ -494,6 +497,12 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd) tailpos = hostapd_eid_ext_capab(hapd, tailpos); + /* + * TODO: Time Advertisement element should only be included in some + * DTIM Beacon frames. + */ + tailpos = hostapd_eid_time_adv(hapd, tailpos); + tailpos = hostapd_eid_interworking(hapd, tailpos); tailpos = hostapd_eid_adv_proto(hapd, tailpos); tailpos = hostapd_eid_roaming_consortium(hapd, tailpos); diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index 4dad78a..23c8b1a 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -261,6 +261,8 @@ static void hostapd_cleanup(struct hostapd_data *hapd) wpabuf_free(hapd->p2p_probe_resp_ie); hapd->p2p_probe_resp_ie = NULL; #endif /* CONFIG_P2P */ + + wpabuf_free(hapd->time_adv); } diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h index 803776c..5401e80 100644 --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h @@ -108,6 +108,10 @@ struct hostapd_data { int parameter_set_count; + /* Time Advertisement */ + u8 time_update_counter; + struct wpabuf *time_adv; + #ifdef CONFIG_FULL_DYNAMIC_VLAN struct full_dynamic_vlan *full_dynamic_vlan; #endif /* CONFIG_FULL_DYNAMIC_VLAN */ diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h index 1c2c367..6706400 100644 --- a/src/ap/ieee802_11.h +++ b/src/ap/ieee802_11.h @@ -72,5 +72,8 @@ void ieee802_11_sa_query_action(struct hostapd_data *hapd, u8 * hostapd_eid_interworking(struct hostapd_data *hapd, u8 *eid); u8 * hostapd_eid_adv_proto(struct hostapd_data *hapd, u8 *eid); u8 * hostapd_eid_roaming_consortium(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_time_adv(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_time_zone(struct hostapd_data *hapd, u8 *eid); +int hostapd_update_time_adv(struct hostapd_data *hapd); #endif /* IEEE802_11_H */ diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c index 6b17bc6..12a2a70 100644 --- a/src/ap/ieee802_11_shared.c +++ b/src/ap/ieee802_11_shared.c @@ -20,6 +20,7 @@ #include "sta_info.h" #include "ap_config.h" #include "ap_drv_ops.h" +#include "ieee802_11.h" #ifdef CONFIG_IEEE80211W @@ -188,6 +189,8 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid) *pos++ = 0x00; *pos = 0x00; + if (hapd->conf->time_advertisement == 2) + *pos |= 0x08; /* Bit 27 - UTC TSF Offset */ if (hapd->conf->interworking) *pos |= 0x80; /* Bit 31 - Interworking */ pos++; @@ -309,3 +312,91 @@ u8 * hostapd_eid_roaming_consortium(struct hostapd_data *hapd, u8 *eid) return pos; } + + +u8 * hostapd_eid_time_adv(struct hostapd_data *hapd, u8 *eid) +{ + if (hapd->conf->time_advertisement != 2) + return eid; + + if (hapd->time_adv == NULL && + hostapd_update_time_adv(hapd) < 0) + return eid; + + os_memcpy(eid, wpabuf_head(hapd->time_adv), + wpabuf_len(hapd->time_adv)); + eid += wpabuf_len(hapd->time_adv); + + return eid; +} + + +u8 * hostapd_eid_time_zone(struct hostapd_data *hapd, u8 *eid) +{ + size_t len; + + if (hapd->conf->time_advertisement != 2) + return eid; + + len = os_strlen(hapd->conf->time_zone); + + *eid++ = WLAN_EID_TIME_ZONE; + *eid++ = len; + os_memcpy(eid, hapd->conf->time_zone, len); + eid += len; + + return eid; +} + + +int hostapd_update_time_adv(struct hostapd_data *hapd) +{ + const int elen = 2 + 1 + 10 + 5 + 1; + struct os_time t; + struct os_tm tm; + u8 *pos; + + if (hapd->conf->time_advertisement != 2) + return 0; + + if (os_get_time(&t) < 0 || os_gmtime(t.sec, &tm) < 0) + return -1; + + if (!hapd->time_adv) { + hapd->time_adv = wpabuf_alloc(elen); + if (hapd->time_adv == NULL) + return -1; + pos = wpabuf_put(hapd->time_adv, elen); + } else + pos = wpabuf_mhead_u8(hapd->time_adv); + + *pos++ = WLAN_EID_TIME_ADVERTISEMENT; + *pos++ = 1 + 10 + 5 + 1; + + *pos++ = 2; /* UTC time at which the TSF timer is 0 */ + + /* Time Value at TSF 0 */ + /* FIX: need to calculate this based on the current TSF value */ + WPA_PUT_LE16(pos, tm.year); /* Year */ + pos += 2; + *pos++ = tm.month; /* Month */ + *pos++ = tm.day; /* Day of month */ + *pos++ = tm.hour; /* Hours */ + *pos++ = tm.min; /* Minutes */ + *pos++ = tm.sec; /* Seconds */ + WPA_PUT_LE16(pos, 0); /* Milliseconds (not used) */ + pos += 2; + *pos++ = 0; /* Reserved */ + + /* Time Error */ + /* TODO: fill in an estimate on the error */ + *pos++ = 0; + *pos++ = 0; + *pos++ = 0; + *pos++ = 0; + *pos++ = 0; + + *pos++ = hapd->time_update_counter++; + + return 0; +} diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 5a8ee5f..1286167 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -229,10 +229,12 @@ #define WLAN_EID_RIC_DATA 57 #define WLAN_EID_HT_OPERATION 61 #define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62 +#define WLAN_EID_TIME_ADVERTISEMENT 69 #define WLAN_EID_20_40_BSS_COEXISTENCE 72 #define WLAN_EID_20_40_BSS_INTOLERANT 73 #define WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS 74 #define WLAN_EID_MMIE 76 +#define WLAN_EID_TIME_ZONE 98 #define WLAN_EID_LINK_ID 101 #define WLAN_EID_INTERWORKING 107 #define WLAN_EID_ADV_PROTO 108 |