aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ap/ap_config.c2
-rw-r--r--src/ap/ap_config.h4
-rw-r--r--src/ap/ap_drv_ops.c14
-rw-r--r--src/ap/beacon.c9
-rw-r--r--src/ap/hostapd.c2
-rw-r--r--src/ap/hostapd.h4
-rw-r--r--src/ap/ieee802_11.h3
-rw-r--r--src/ap/ieee802_11_shared.c91
-rw-r--r--src/common/ieee802_11_defs.h2
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