Cumulative patch from commit 075131e32e6967977da4bbfa8a7f63dbfbf86008i

075131e Android: Do not compile wpa_supplicant if not chosen
f7154ce DFS: Use channel switch when radar is detected
6c6c58d hostapd: Make hostapd_set_freq_params() public
b72f949 DFS: Allow skipping radar channels
8d1fdde nl80211/hostapd: Extend channel switch notify handling
10e694a AP: Use monotonic clock for SA query timeout
af53896 Use monotonic clock for RADIUS cache timeouts
fe52c21 Use monotonic clock for last_sae_token_key_update
100298e AP: Use monotonic time for AP list
e5c9e40 OS utils: Add os_reltime_expired()
b3493fa AP: Use monotonic time for STA connected time
ed0ebee OS utils: Provide os_reltime_age()
8567866 P2P: Handle frequency conflict in single channel concurrency case
b125c48 P2P: Add wfd_dev_info= field for device found event
e706d2d bsd: Fix compilation error for NetBSD
f757950 eap_proxy: Extend Android.mk to support additional libraries

Change-Id: I6d4f0f559f420680903d12966c7a6a87da97d61a
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index 0dc0600..09b5f68 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -464,11 +464,11 @@
 }
 
 
-static int hostapd_set_freq_params(struct hostapd_freq_params *data, int mode,
-				   int freq, int channel, int ht_enabled,
-				   int vht_enabled, int sec_channel_offset,
-				   int vht_oper_chwidth, int center_segment0,
-				   int center_segment1, u32 vht_caps)
+int hostapd_set_freq_params(struct hostapd_freq_params *data, int mode,
+			    int freq, int channel, int ht_enabled,
+			    int vht_enabled, int sec_channel_offset,
+			    int vht_oper_chwidth, int center_segment0,
+			    int center_segment1, u32 vht_caps)
 {
 	int tmp;
 
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
index 1eab939..b5f6a02 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -14,6 +14,7 @@
 struct wpa_driver_scan_params;
 struct ieee80211_ht_capabilities;
 struct ieee80211_vht_capabilities;
+struct hostapd_freq_params;
 
 u32 hostapd_sta_flags_to_drv(u32 flags);
 int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
@@ -105,6 +106,11 @@
 			  int channel, int ht_enabled, int vht_enabled,
 			  int sec_channel_offset, int vht_oper_chwidth,
 			  int center_segment0, int center_segment1);
+int hostapd_set_freq_params(struct hostapd_freq_params *data, int mode,
+			    int freq, int channel, int ht_enabled,
+			    int vht_enabled, int sec_channel_offset,
+			    int vht_oper_chwidth, int center_segment0,
+			    int center_segment1, u32 vht_caps);
 
 
 #include "drivers/driver.h"
diff --git a/src/ap/ap_list.c b/src/ap/ap_list.c
index 9f02151..0dab39f 100644
--- a/src/ap/ap_list.c
+++ b/src/ap/ap_list.c
@@ -172,7 +172,6 @@
 			    struct hostapd_frame_info *fi)
 {
 	struct ap_info *ap;
-	struct os_time now;
 	int new_ap = 0;
 	int set_beacon = 0;
 
@@ -210,8 +209,7 @@
 	else
 		ap->ht_support = 0;
 
-	os_get_time(&now);
-	ap->last_beacon = now.sec;
+	os_get_reltime(&ap->last_beacon);
 
 	if (!new_ap && ap != iface->ap_list) {
 		/* move AP entry into the beginning of the list so that the
@@ -252,7 +250,7 @@
 static void ap_list_timer(void *eloop_ctx, void *timeout_ctx)
 {
 	struct hostapd_iface *iface = eloop_ctx;
-	struct os_time now;
+	struct os_reltime now;
 	struct ap_info *ap;
 	int set_beacon = 0;
 
@@ -261,12 +259,12 @@
 	if (!iface->ap_list)
 		return;
 
-	os_get_time(&now);
+	os_get_reltime(&now);
 
 	while (iface->ap_list) {
 		ap = iface->ap_list->prev;
-		if (ap->last_beacon + iface->conf->ap_table_expiration_time >=
-		    now.sec)
+		if (!os_reltime_expired(&now, &ap->last_beacon,
+					iface->conf->ap_table_expiration_time))
 			break;
 
 		ap_free_ap(iface, ap);
diff --git a/src/ap/ap_list.h b/src/ap/ap_list.h
index d0529a1..93dc0ed 100644
--- a/src/ap/ap_list.h
+++ b/src/ap/ap_list.h
@@ -26,7 +26,7 @@
 
 	int ht_support;
 
-	os_time_t last_beacon;
+	struct os_reltime last_beacon;
 };
 
 struct ieee802_11_elems;
diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
index ac33068..4125fd5 100644
--- a/src/ap/ctrl_iface_ap.c
+++ b/src/ap/ctrl_iface_ap.c
@@ -24,14 +24,13 @@
 static int hostapd_get_sta_conn_time(struct sta_info *sta,
 				     char *buf, size_t buflen)
 {
-	struct os_time now, age;
+	struct os_reltime age;
 	int len = 0, ret;
 
 	if (!sta->connected_time.sec)
 		return 0;
 
-	os_get_time(&now);
-	os_time_sub(&now, &sta->connected_time, &age);
+	os_reltime_age(&sta->connected_time, &age);
 
 	ret = os_snprintf(buf + len, buflen - len, "connected_time=%u\n",
 			  (unsigned int) age.sec);
diff --git a/src/ap/dfs.c b/src/ap/dfs.c
index 0a909f4..caf4092 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -44,8 +44,17 @@
 }
 
 
-static int dfs_channel_available(struct hostapd_channel_data *chan)
+static int dfs_channel_available(struct hostapd_channel_data *chan,
+				 int skip_radar)
 {
+	/*
+	 * When radar detection happens, CSA is performed. However, there's no
+	 * time for CAC, so radar channels must be skipped when finding a new
+	 * channel for CSA.
+	 */
+	if (skip_radar && chan->flag & HOSTAPD_CHAN_RADAR)
+		return 0;
+
 	if (chan->flag & HOSTAPD_CHAN_DISABLED)
 		return 0;
 	if ((chan->flag & HOSTAPD_CHAN_RADAR) &&
@@ -96,7 +105,8 @@
 
 
 static int dfs_chan_range_available(struct hostapd_hw_modes *mode,
-				    int first_chan_idx, int num_chans)
+				    int first_chan_idx, int num_chans,
+				    int skip_radar)
 {
 	struct hostapd_channel_data *first_chan, *chan;
 	int i;
@@ -112,7 +122,7 @@
 		if (first_chan->freq + i * 20 != chan->freq)
 			return 0;
 
-		if (!dfs_channel_available(chan))
+		if (!dfs_channel_available(chan, skip_radar))
 			return 0;
 	}
 
@@ -129,7 +139,7 @@
  */
 static int dfs_find_channel(struct hostapd_iface *iface,
 			    struct hostapd_channel_data **ret_chan,
-			    int idx)
+			    int idx, int skip_radar)
 {
 	struct hostapd_hw_modes *mode;
 	struct hostapd_channel_data *chan;
@@ -149,7 +159,7 @@
 			continue;
 
 		/* Skip incompatible chandefs */
-		if (!dfs_chan_range_available(mode, i, n_chans))
+		if (!dfs_chan_range_available(mode, i, n_chans, skip_radar))
 			continue;
 
 		if (ret_chan && idx == channel_idx) {
@@ -322,7 +332,8 @@
 dfs_get_valid_channel(struct hostapd_iface *iface,
 		      int *secondary_channel,
 		      u8 *vht_oper_centr_freq_seg0_idx,
-		      u8 *vht_oper_centr_freq_seg1_idx)
+		      u8 *vht_oper_centr_freq_seg1_idx,
+		      int skip_radar)
 {
 	struct hostapd_hw_modes *mode;
 	struct hostapd_channel_data *chan = NULL;
@@ -340,13 +351,13 @@
 		return NULL;
 
 	/* Get the count first */
-	num_available_chandefs = dfs_find_channel(iface, NULL, 0);
+	num_available_chandefs = dfs_find_channel(iface, NULL, 0, skip_radar);
 	if (num_available_chandefs == 0)
 		return NULL;
 
 	os_get_random((u8 *) &_rand, sizeof(_rand));
 	chan_idx = _rand % num_available_chandefs;
-	dfs_find_channel(iface, &chan, chan_idx);
+	dfs_find_channel(iface, &chan, chan_idx, skip_radar);
 
 	/* dfs_find_channel() calculations assume HT40+ */
 	if (iface->conf->secondary_channel)
@@ -518,6 +529,7 @@
 {
 	struct hostapd_channel_data *channel;
 	int res, n_chans, start_chan_idx;
+	int skip_radar = 0;
 
 	iface->cac_started = 0;
 
@@ -555,7 +567,8 @@
 			int sec;
 			u8 cf1, cf2;
 
-			channel = dfs_get_valid_channel(iface, &sec, &cf1, &cf2);
+			channel = dfs_get_valid_channel(iface, &sec, &cf1, &cf2,
+							skip_radar);
 			if (!channel) {
 				wpa_printf(MSG_ERROR, "could not get valid channel");
 				return -1;
@@ -614,25 +627,111 @@
 }
 
 
-static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
+static int hostapd_dfs_start_channel_switch_cac(struct hostapd_iface *iface)
 {
 	struct hostapd_channel_data *channel;
-	int err = 1;
 	int secondary_channel;
 	u8 vht_oper_centr_freq_seg0_idx;
 	u8 vht_oper_centr_freq_seg1_idx;
+	int skip_radar = 0;
+	int err = 1;
 
-	wpa_printf(MSG_DEBUG, "%s called", __func__);
+	/* Radar detected during active CAC */
+	iface->cac_started = 0;
 	channel = dfs_get_valid_channel(iface, &secondary_channel,
 					&vht_oper_centr_freq_seg0_idx,
-					&vht_oper_centr_freq_seg1_idx);
-	if (channel) {
-		wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d",
-			   channel->chan);
-		wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NEW_CHANNEL
-			"freq=%d chan=%d sec_chan=%d", channel->freq,
-			channel->chan, secondary_channel);
+					&vht_oper_centr_freq_seg1_idx,
+					skip_radar);
 
+	if (!channel) {
+		wpa_printf(MSG_ERROR, "No valid channel available");
+		hostapd_setup_interface_complete(iface, err);
+		return err;
+	}
+
+	wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d",
+		   channel->chan);
+	wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NEW_CHANNEL
+		"freq=%d chan=%d sec_chan=%d", channel->freq,
+		channel->chan, secondary_channel);
+
+	iface->freq = channel->freq;
+	iface->conf->channel = channel->chan;
+	iface->conf->secondary_channel = secondary_channel;
+	iface->conf->vht_oper_centr_freq_seg0_idx =
+		vht_oper_centr_freq_seg0_idx;
+	iface->conf->vht_oper_centr_freq_seg1_idx =
+		vht_oper_centr_freq_seg1_idx;
+	err = 0;
+
+	hostapd_setup_interface_complete(iface, err);
+	return err;
+}
+
+
+static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
+{
+	struct hostapd_channel_data *channel;
+	int secondary_channel;
+	u8 vht_oper_centr_freq_seg0_idx;
+	u8 vht_oper_centr_freq_seg1_idx;
+	int skip_radar = 1;
+	struct csa_settings csa_settings;
+	struct hostapd_data *hapd = iface->bss[0];
+	int err = 1;
+
+	wpa_printf(MSG_DEBUG, "%s called (CAC active: %s)", __func__,
+		   iface->cac_started ? "yes" : "no");
+
+	/* Check if active CAC */
+	if (iface->cac_started)
+		return hostapd_dfs_start_channel_switch_cac(iface);
+
+
+	/* Perform channel switch/CSA */
+	channel = dfs_get_valid_channel(iface, &secondary_channel,
+					&vht_oper_centr_freq_seg0_idx,
+					&vht_oper_centr_freq_seg1_idx,
+					skip_radar);
+
+	if (!channel) {
+		/* FIXME: Wait for channel(s) to become available */
+		hostapd_disable_iface(iface);
+		return err;
+	}
+
+	wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d",
+		   channel->chan);
+	wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NEW_CHANNEL
+		"freq=%d chan=%d sec_chan=%d", channel->freq,
+		channel->chan, secondary_channel);
+
+	/* Setup CSA request */
+	os_memset(&csa_settings, 0, sizeof(csa_settings));
+	csa_settings.cs_count = 5;
+	csa_settings.block_tx = 1;
+	err = hostapd_set_freq_params(&csa_settings.freq_params,
+				      iface->conf->hw_mode,
+				      channel->freq,
+				      channel->chan,
+				      iface->conf->ieee80211n,
+				      iface->conf->ieee80211ac,
+				      secondary_channel,
+				      iface->conf->vht_oper_chwidth,
+				      vht_oper_centr_freq_seg0_idx,
+				      vht_oper_centr_freq_seg1_idx,
+				      iface->current_mode->vht_capab);
+
+	if (err) {
+		wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params");
+		hostapd_disable_iface(iface);
+		return err;
+	}
+
+	err = hostapd_switch_channel(hapd, &csa_settings);
+	if (err) {
+		wpa_printf(MSG_WARNING, "DFS failed to schedule CSA (%d) - trying fallback",
+			   err);
 		iface->freq = channel->freq;
 		iface->conf->channel = channel->chan;
 		iface->conf->secondary_channel = secondary_channel;
@@ -640,29 +739,16 @@
 			vht_oper_centr_freq_seg0_idx;
 		iface->conf->vht_oper_centr_freq_seg1_idx =
 			vht_oper_centr_freq_seg1_idx;
-		err = 0;
-	} else {
-		wpa_printf(MSG_ERROR, "No valid channel available");
-	}
 
-	if (iface->cac_started) {
-		wpa_printf(MSG_DEBUG, "DFS radar detected during CAC");
-		iface->cac_started = 0;
-		/* FIXME: Wait for channel(s) to become available if no channel
-		 * has been found */
-		hostapd_setup_interface_complete(iface, err);
-		return err;
-	}
-
-	if (err) {
-		/* FIXME: Wait for channel(s) to become available */
 		hostapd_disable_iface(iface);
-		return err;
+		hostapd_enable_iface(iface);
+		return 0;
 	}
 
-	wpa_printf(MSG_DEBUG, "DFS radar detected");
-	hostapd_disable_iface(iface);
-	hostapd_enable_iface(iface);
+	/* Channel configuration will be updated once CSA completes and
+	 * ch_switch_notify event is received */
+
+	wpa_printf(MSG_DEBUG, "DFS waiting channel switch event");
 	return 0;
 }
 
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index 1b69ba8..b066bff 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -381,14 +381,15 @@
 
 
 void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
-			     int offset)
+			     int offset, int width, int cf1, int cf2)
 {
 #ifdef NEED_AP_MLME
-	int channel;
+	int channel, chwidth, seg0_idx = 0, seg1_idx = 0;
 
 	hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
 		       HOSTAPD_LEVEL_INFO, "driver had channel switch: "
-		       "freq=%d, ht=%d, offset=%d", freq, ht, offset);
+		       "freq=%d, ht=%d, offset=%d, width=%d, cf1=%d, cf2=%d",
+		       freq, ht, offset, width, cf1, cf2);
 
 	hapd->iface->freq = freq;
 
@@ -400,9 +401,43 @@
 		return;
 	}
 
+	switch (width) {
+	case CHAN_WIDTH_80:
+		chwidth = VHT_CHANWIDTH_80MHZ;
+		break;
+	case CHAN_WIDTH_80P80:
+		chwidth = VHT_CHANWIDTH_80P80MHZ;
+		break;
+	case CHAN_WIDTH_160:
+		chwidth = VHT_CHANWIDTH_160MHZ;
+		break;
+	case CHAN_WIDTH_20_NOHT:
+	case CHAN_WIDTH_20:
+	case CHAN_WIDTH_40:
+	default:
+		chwidth = VHT_CHANWIDTH_USE_HT;
+		break;
+	}
+
+	switch (hapd->iface->current_mode->mode) {
+	case HOSTAPD_MODE_IEEE80211A:
+		if (cf1 > 5000)
+			seg0_idx = (cf1 - 5000) / 5;
+		if (cf2 > 5000)
+			seg1_idx = (cf2 - 5000) / 5;
+		break;
+	default:
+		seg0_idx = hostapd_hw_get_channel(hapd, cf1);
+		seg1_idx = hostapd_hw_get_channel(hapd, cf2);
+		break;
+	}
+
 	hapd->iconf->channel = channel;
 	hapd->iconf->ieee80211n = ht;
 	hapd->iconf->secondary_channel = offset;
+	hapd->iconf->vht_oper_chwidth = chwidth;
+	hapd->iconf->vht_oper_centr_freq_seg0_idx = seg0_idx;
+	hapd->iconf->vht_oper_centr_freq_seg1_idx = seg1_idx;
 
 	if (hapd->iface->csa_in_progress && freq == hapd->iface->cs_freq) {
 		hostapd_cleanup_cs_params(hapd);
@@ -976,7 +1011,10 @@
 			break;
 		hostapd_event_ch_switch(hapd, data->ch_switch.freq,
 					data->ch_switch.ht_enabled,
-					data->ch_switch.ch_offset);
+					data->ch_switch.ch_offset,
+					data->ch_switch.ch_width,
+					data->ch_switch.cf1,
+					data->ch_switch.cf2);
 		break;
 	case EVENT_CONNECT_FAILED_REASON:
 		if (!data)
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 492861e..6fe2956 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -1967,7 +1967,7 @@
 	 * IEEE 802.1X/WPA code will start accounting after the station has
 	 * been authorized. */
 	if (!hapd->conf->ieee802_1x && !hapd->conf->wpa) {
-		os_get_time(&sta->connected_time);
+		os_get_reltime(&sta->connected_time);
 		accounting_sta_start(hapd, sta);
 	}
 
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index c25917d..84468de 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -241,7 +241,7 @@
 #ifdef CONFIG_SAE
 	/** Key used for generating SAE anti-clogging tokens */
 	u8 sae_token_key[8];
-	os_time_t last_sae_token_key_update;
+	struct os_reltime last_sae_token_key_update;
 #endif /* CONFIG_SAE */
 };
 
@@ -414,7 +414,7 @@
 			 const u8 *bssid, const u8 *ie, size_t ie_len,
 			 int ssi_signal);
 void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
-			     int offset);
+			     int offset, int width, int cf1, int cf2);
 
 const struct hostapd_eap_user *
 hostapd_get_eap_user(struct hostapd_data *hapd, const u8 *identity,
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index d553caa..e55f843 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -411,17 +411,17 @@
 {
 	struct wpabuf *buf;
 	u8 *token;
-	struct os_time t;
+	struct os_reltime now;
 
-	os_get_time(&t);
-	if (hapd->last_sae_token_key_update == 0 ||
-	    t.sec > hapd->last_sae_token_key_update + 60) {
+	os_get_reltime(&now);
+	if (!os_reltime_initialized(&hapd->last_sae_token_key_update) ||
+	    os_reltime_expired(&now, &hapd->last_sae_token_key_update, 60)) {
 		if (random_get_bytes(hapd->sae_token_key,
 				     sizeof(hapd->sae_token_key)) < 0)
 			return NULL;
 		wpa_hexdump(MSG_DEBUG, "SAE: Updated token key",
 			    hapd->sae_token_key, sizeof(hapd->sae_token_key));
-		hapd->last_sae_token_key_update = t.sec;
+		hapd->last_sae_token_key_update = now;
 	}
 
 	buf = wpabuf_alloc(SHA256_MAC_LEN);
diff --git a/src/ap/ieee802_11_auth.c b/src/ap/ieee802_11_auth.c
index c311e55..56c3ce0 100644
--- a/src/ap/ieee802_11_auth.c
+++ b/src/ap/ieee802_11_auth.c
@@ -29,7 +29,7 @@
 
 
 struct hostapd_cached_radius_acl {
-	os_time_t timestamp;
+	struct os_reltime timestamp;
 	macaddr addr;
 	int accepted; /* HOSTAPD_ACL_* */
 	struct hostapd_cached_radius_acl *next;
@@ -43,7 +43,7 @@
 
 
 struct hostapd_acl_query_data {
-	os_time_t timestamp;
+	struct os_reltime timestamp;
 	u8 radius_id;
 	macaddr addr;
 	u8 *auth_msg; /* IEEE 802.11 authentication frame from station */
@@ -104,15 +104,16 @@
 				 char **identity, char **radius_cui)
 {
 	struct hostapd_cached_radius_acl *entry;
-	struct os_time now;
+	struct os_reltime now;
 
-	os_get_time(&now);
+	os_get_reltime(&now);
 
 	for (entry = hapd->acl_cache; entry; entry = entry->next) {
 		if (os_memcmp(entry->addr, addr, ETH_ALEN) != 0)
 			continue;
 
-		if (now.sec - entry->timestamp > RADIUS_ACL_TIMEOUT)
+		if (os_reltime_expired(&now, &entry->timestamp,
+				       RADIUS_ACL_TIMEOUT))
 			return -1; /* entry has expired */
 		if (entry->accepted == HOSTAPD_ACL_ACCEPT_TIMEOUT)
 			if (session_timeout)
@@ -265,7 +266,6 @@
 		return HOSTAPD_ACL_REJECT;
 #else /* CONFIG_NO_RADIUS */
 		struct hostapd_acl_query_data *query;
-		struct os_time t;
 
 		/* Check whether ACL cache has an entry for this station */
 		int res = hostapd_acl_cache_get(hapd, addr, session_timeout,
@@ -305,8 +305,7 @@
 			wpa_printf(MSG_ERROR, "malloc for query data failed");
 			return HOSTAPD_ACL_REJECT;
 		}
-		os_get_time(&t);
-		query->timestamp = t.sec;
+		os_get_reltime(&query->timestamp);
 		os_memcpy(query->addr, addr, ETH_ALEN);
 		if (hostapd_radius_acl_query(hapd, addr, query)) {
 			wpa_printf(MSG_DEBUG, "Failed to send Access-Request "
@@ -338,7 +337,8 @@
 
 
 #ifndef CONFIG_NO_RADIUS
-static void hostapd_acl_expire_cache(struct hostapd_data *hapd, os_time_t now)
+static void hostapd_acl_expire_cache(struct hostapd_data *hapd,
+				     struct os_reltime *now)
 {
 	struct hostapd_cached_radius_acl *prev, *entry, *tmp;
 
@@ -346,7 +346,8 @@
 	entry = hapd->acl_cache;
 
 	while (entry) {
-		if (now - entry->timestamp > RADIUS_ACL_TIMEOUT) {
+		if (os_reltime_expired(now, &entry->timestamp,
+				       RADIUS_ACL_TIMEOUT)) {
 			wpa_printf(MSG_DEBUG, "Cached ACL entry for " MACSTR
 				   " has expired.", MAC2STR(entry->addr));
 			if (prev)
@@ -367,7 +368,7 @@
 
 
 static void hostapd_acl_expire_queries(struct hostapd_data *hapd,
-				       os_time_t now)
+				       struct os_reltime *now)
 {
 	struct hostapd_acl_query_data *prev, *entry, *tmp;
 
@@ -375,7 +376,8 @@
 	entry = hapd->acl_queries;
 
 	while (entry) {
-		if (now - entry->timestamp > RADIUS_ACL_TIMEOUT) {
+		if (os_reltime_expired(now, &entry->timestamp,
+				       RADIUS_ACL_TIMEOUT)) {
 			wpa_printf(MSG_DEBUG, "ACL query for " MACSTR
 				   " has expired.", MAC2STR(entry->addr));
 			if (prev)
@@ -403,11 +405,11 @@
 static void hostapd_acl_expire(void *eloop_ctx, void *timeout_ctx)
 {
 	struct hostapd_data *hapd = eloop_ctx;
-	struct os_time now;
+	struct os_reltime now;
 
-	os_get_time(&now);
-	hostapd_acl_expire_cache(hapd, now.sec);
-	hostapd_acl_expire_queries(hapd, now.sec);
+	os_get_reltime(&now);
+	hostapd_acl_expire_cache(hapd, &now);
+	hostapd_acl_expire_queries(hapd, &now);
 
 	eloop_register_timeout(10, 0, hostapd_acl_expire, hapd, NULL);
 }
@@ -480,7 +482,6 @@
 	struct hostapd_acl_query_data *query, *prev;
 	struct hostapd_cached_radius_acl *cache;
 	struct radius_hdr *hdr = radius_msg_get_hdr(msg);
-	struct os_time t;
 
 	query = hapd->acl_queries;
 	prev = NULL;
@@ -515,8 +516,7 @@
 		wpa_printf(MSG_DEBUG, "Failed to add ACL cache entry");
 		goto done;
 	}
-	os_get_time(&t);
-	cache->timestamp = t.sec;
+	os_get_reltime(&cache->timestamp);
 	os_memcpy(cache->addr, query->addr, sizeof(cache->addr));
 	if (hdr->code == RADIUS_CODE_ACCESS_ACCEPT) {
 		u8 *buf;
diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c
index 76688b5..eadaa4d 100644
--- a/src/ap/ieee802_11_shared.c
+++ b/src/ap/ieee802_11_shared.c
@@ -24,13 +24,13 @@
 {
 	u8 *pos = eid;
 	u32 timeout, tu;
-	struct os_time now, passed;
+	struct os_reltime now, passed;
 
 	*pos++ = WLAN_EID_TIMEOUT_INTERVAL;
 	*pos++ = 5;
 	*pos++ = WLAN_TIMEOUT_ASSOC_COMEBACK;
-	os_get_time(&now);
-	os_time_sub(&now, &sta->sa_query_start, &passed);
+	os_get_reltime(&now);
+	os_reltime_sub(&now, &sta->sa_query_start, &passed);
 	tu = (passed.sec * 1000000 + passed.usec) / 1024;
 	if (hapd->conf->assoc_sa_query_max_timeout > tu)
 		timeout = hapd->conf->assoc_sa_query_max_timeout - tu;
diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
index 7874332..4465d12 100644
--- a/src/ap/ieee802_1x.c
+++ b/src/ap/ieee802_1x.c
@@ -102,7 +102,7 @@
 	}
 
 	if (authorized) {
-		os_get_time(&sta->connected_time);
+		os_get_reltime(&sta->connected_time);
 		accounting_sta_start(hapd, sta);
 	}
 }
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index 474597e..d1d8657 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -825,9 +825,9 @@
 int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta)
 {
 	u32 tu;
-	struct os_time now, passed;
-	os_get_time(&now);
-	os_time_sub(&now, &sta->sa_query_start, &passed);
+	struct os_reltime now, passed;
+	os_get_reltime(&now);
+	os_reltime_sub(&now, &sta->sa_query_start, &passed);
 	tu = (passed.sec * 1000000 + passed.usec) / 1024;
 	if (hapd->conf->assoc_sa_query_max_timeout < tu) {
 		hostapd_logger(hapd, sta->addr,
@@ -864,7 +864,7 @@
 		return;
 	if (sta->sa_query_count == 0) {
 		/* Starting a new SA Query procedure */
-		os_get_time(&sta->sa_query_start);
+		os_get_reltime(&sta->sa_query_start);
 	}
 	trans_id = nbuf + sta->sa_query_count * WLAN_SA_QUERY_TR_ID_LEN;
 	sta->sa_query_trans_id = nbuf;
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index dc74219..ea3fe40 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -113,7 +113,7 @@
 	u8 *sa_query_trans_id; /* buffer of WLAN_SA_QUERY_TR_ID_LEN *
 				* sa_query_count octets of pending SA Query
 				* transaction identifiers */
-	struct os_time sa_query_start;
+	struct os_reltime sa_query_start;
 #endif /* CONFIG_IEEE80211W */
 
 #ifdef CONFIG_INTERWORKING
@@ -126,7 +126,7 @@
 	struct wpabuf *p2p_ie; /* P2P IE from (Re)Association Request */
 	struct wpabuf *hs20_ie; /* HS 2.0 IE from (Re)Association Request */
 
-	struct os_time connected_time;
+	struct os_reltime connected_time;
 
 #ifdef CONFIG_SAE
 	struct sae_data *sae;