Accumulative patch from commit 455299fb40d79bcbeaedcfbc04d00ac8330bbbdd

455299f nl80211: Fix foreign address filtering for MLME frame events
e679f14 Mark interface disconnected on removal request
3636b89 Do not try auto connect mechanism in disconnected state
0cdb93f Do not add BSS to blacklist on local disconnection request
36b9883 Defer scan if connection is in progress on any of the shared interfaces
7c0e1e2 tls_openssl: Store TLS context per-connection
732118e Rename hostapd_parse_rates() to a more generic int list parser
b113a17 DFS: Add ieee80211h hostapd configuration parameter
695c703 nl80211: Add driver_ops for stopping AP beaconing
f90e9c1 nl80211: Add driver_ops for starting radar detection
fc96522 nl80211: Add channel flags for DFS state information
f295d0c nl80211: Add driver capability flag for radar detection
04be54f nl80211: Add driver events for radar detection
a7505b1 eloop: Allow to run event loop multiple times in a row
6124e85 wpa_supplicant: Allow vifs to scan only current channel
893a0a5 systemd: Fix systemd interface alias

Change-Id: I0a39a6868562cd458202285fed8986ac81a0cef2
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 16134da..7c9ea90 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -498,6 +498,8 @@
 
 	int ieee80211d;
 
+	int ieee80211h; /* DFS */
+
 	struct hostapd_tx_queue_params tx_queue[NUM_TX_QUEUES];
 
 	/*
diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index 2bf47c7..fec8e38 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -34,6 +34,10 @@
 #define OPENSSL_d2i_TYPE unsigned char **
 #endif
 
+#if defined(SSL_CTX_get_app_data) && defined(SSL_CTX_set_app_data)
+#define OPENSSL_SUPPORTS_CTX_APP_DATA
+#endif
+
 #ifdef SSL_F_SSL_SET_SESSION_TICKET_EXT
 #ifdef SSL_OP_NO_TICKET
 /*
@@ -63,17 +67,18 @@
 
 static int tls_openssl_ref_count = 0;
 
-struct tls_global {
+struct tls_context {
 	void (*event_cb)(void *ctx, enum tls_event ev,
 			 union tls_event_data *data);
 	void *cb_ctx;
 	int cert_in_cb;
 };
 
-static struct tls_global *tls_global = NULL;
+static struct tls_context *tls_global = NULL;
 
 
 struct tls_connection {
+	struct tls_context *context;
 	SSL *ssl;
 	BIO *ssl_in, *ssl_out;
 #ifndef OPENSSL_NO_ENGINE
@@ -100,6 +105,20 @@
 };
 
 
+static struct tls_context * tls_context_new(const struct tls_config *conf)
+{
+	struct tls_context *context = os_zalloc(sizeof(*context));
+	if (context == NULL)
+		return NULL;
+	if (conf) {
+		context->event_cb = conf->event_cb;
+		context->cb_ctx = conf->cb_ctx;
+		context->cert_in_cb = conf->cert_in_cb;
+	}
+	return context;
+}
+
+
 #ifdef CONFIG_NO_STDOUT_DEBUG
 
 static void _tls_show_errors(void)
@@ -525,6 +544,7 @@
 		wpa_printf(MSG_DEBUG, "SSL: %s:%s",
 			   str, SSL_state_string_long(ssl));
 	} else if (where & SSL_CB_ALERT) {
+		struct tls_connection *conn = SSL_get_app_data((SSL *) ssl);
 		wpa_printf(MSG_INFO, "SSL: SSL3 alert: %s:%s:%s",
 			   where & SSL_CB_READ ?
 			   "read (remote end reported an error)" :
@@ -532,21 +552,19 @@
 			   SSL_alert_type_string_long(ret),
 			   SSL_alert_desc_string_long(ret));
 		if ((ret >> 8) == SSL3_AL_FATAL) {
-			struct tls_connection *conn =
-				SSL_get_app_data((SSL *) ssl);
 			if (where & SSL_CB_READ)
 				conn->read_alerts++;
 			else
 				conn->write_alerts++;
 		}
-		if (tls_global->event_cb != NULL) {
+		if (conn->context->event_cb != NULL) {
 			union tls_event_data ev;
+			struct tls_context *context = conn->context;
 			os_memset(&ev, 0, sizeof(ev));
 			ev.alert.is_local = !(where & SSL_CB_READ);
 			ev.alert.type = SSL_alert_type_string_long(ret);
 			ev.alert.description = SSL_alert_desc_string_long(ret);
-			tls_global->event_cb(tls_global->cb_ctx, TLS_ALERT,
-					     &ev);
+			context->event_cb(context->cb_ctx, TLS_ALERT, &ev);
 		}
 	} else if (where & SSL_CB_EXIT && ret <= 0) {
 		wpa_printf(MSG_DEBUG, "SSL: %s:%s in %s",
@@ -704,17 +722,12 @@
 void * tls_init(const struct tls_config *conf)
 {
 	SSL_CTX *ssl;
+	struct tls_context *context;
 
 	if (tls_openssl_ref_count == 0) {
-		tls_global = os_zalloc(sizeof(*tls_global));
-		if (tls_global == NULL)
+		tls_global = context = tls_context_new(conf);
+		if (context == NULL)
 			return NULL;
-		if (conf) {
-			tls_global->event_cb = conf->event_cb;
-			tls_global->cb_ctx = conf->cb_ctx;
-			tls_global->cert_in_cb = conf->cert_in_cb;
-		}
-
 #ifdef CONFIG_FIPS
 #ifdef OPENSSL_FIPS
 		if (conf && conf->fips_mode) {
@@ -760,14 +773,33 @@
 #endif /* OPENSSL_NO_RC2 */
 		PKCS12_PBE_add();
 #endif  /* PKCS12_FUNCS */
+	} else {
+		context = tls_global;
+#ifdef OPENSSL_SUPPORTS_CTX_APP_DATA
+		/* Newer OpenSSL can store app-data per-SSL */
+		context = tls_context_new(conf);
+		if (context == NULL)
+			return NULL;
+#endif /* OPENSSL_SUPPORTS_CTX_APP_DATA */
 	}
 	tls_openssl_ref_count++;
 
 	ssl = SSL_CTX_new(TLSv1_method());
-	if (ssl == NULL)
+	if (ssl == NULL) {
+		tls_openssl_ref_count--;
+		if (tls_openssl_ref_count == 0) {
+			os_free(tls_global);
+			tls_global = NULL;
+		} else if (context != tls_global) {
+			os_free(context);
+		}
 		return NULL;
+	}
 
 	SSL_CTX_set_info_callback(ssl, ssl_info_cb);
+#ifdef OPENSSL_SUPPORTS_CTX_APP_DATA
+	SSL_CTX_set_app_data(ssl, context);
+#endif /* OPENSSL_SUPPORTS_CTX_APP_DATA */
 
 #ifndef OPENSSL_NO_ENGINE
 	if (conf &&
@@ -793,6 +825,11 @@
 void tls_deinit(void *ssl_ctx)
 {
 	SSL_CTX *ssl = ssl_ctx;
+#ifdef OPENSSL_SUPPORTS_CTX_APP_DATA
+	struct tls_context *context = SSL_CTX_get_app_data(ssl);
+	if (context != tls_global)
+		os_free(context);
+#endif /* OPENSSL_SUPPORTS_CTX_APP_DATA */
 	SSL_CTX_free(ssl);
 
 	tls_openssl_ref_count--;
@@ -936,6 +973,10 @@
 	SSL_CTX *ssl = ssl_ctx;
 	struct tls_connection *conn;
 	long options;
+	struct tls_context *context = tls_global;
+#ifdef OPENSSL_SUPPORTS_CTX_APP_DATA
+	context = SSL_CTX_get_app_data(ssl);
+#endif /* OPENSSL_SUPPORTS_CTX_APP_DATA */
 
 	conn = os_zalloc(sizeof(*conn));
 	if (conn == NULL)
@@ -948,6 +989,7 @@
 		return NULL;
 	}
 
+	conn->context = context;
 	SSL_set_app_data(conn->ssl, conn);
 	options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
 		SSL_OP_SINGLE_DH_USE;
@@ -1148,8 +1190,9 @@
 {
 	union tls_event_data ev;
 	struct wpabuf *cert = NULL;
+	struct tls_context *context = conn->context;
 
-	if (tls_global->event_cb == NULL)
+	if (context->event_cb == NULL)
 		return;
 
 	cert = get_x509_cert(err_cert);
@@ -1160,7 +1203,7 @@
 	ev.cert_fail.subject = subject;
 	ev.cert_fail.reason_txt = err_str;
 	ev.cert_fail.cert = cert;
-	tls_global->event_cb(tls_global->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev);
+	context->event_cb(context->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev);
 	wpabuf_free(cert);
 }
 
@@ -1171,15 +1214,16 @@
 {
 	struct wpabuf *cert = NULL;
 	union tls_event_data ev;
+	struct tls_context *context = conn->context;
 #ifdef CONFIG_SHA256
 	u8 hash[32];
 #endif /* CONFIG_SHA256 */
 
-	if (tls_global->event_cb == NULL)
+	if (context->event_cb == NULL)
 		return;
 
 	os_memset(&ev, 0, sizeof(ev));
-	if (conn->cert_probe || tls_global->cert_in_cb) {
+	if (conn->cert_probe || context->cert_in_cb) {
 		cert = get_x509_cert(err_cert);
 		ev.peer_cert.cert = cert;
 	}
@@ -1197,7 +1241,7 @@
 #endif /* CONFIG_SHA256 */
 	ev.peer_cert.depth = depth;
 	ev.peer_cert.subject = subject;
-	tls_global->event_cb(tls_global->cb_ctx, TLS_PEER_CERTIFICATE, &ev);
+	context->event_cb(context->cb_ctx, TLS_PEER_CERTIFICATE, &ev);
 	wpabuf_free(cert);
 }
 
@@ -1209,6 +1253,7 @@
 	int err, depth;
 	SSL *ssl;
 	struct tls_connection *conn;
+	struct tls_context *context;
 	char *match, *altmatch;
 	const char *err_str;
 
@@ -1222,6 +1267,7 @@
 	conn = SSL_get_app_data(ssl);
 	if (conn == NULL)
 		return 0;
+	context = conn->context;
 	match = conn->subject_match;
 	altmatch = conn->altsubject_match;
 
@@ -1304,9 +1350,9 @@
 				       TLS_FAIL_SERVER_CHAIN_PROBE);
 	}
 
-	if (preverify_ok && tls_global->event_cb != NULL)
-		tls_global->event_cb(tls_global->cb_ctx,
-				     TLS_CERT_CHAIN_SUCCESS, NULL);
+	if (preverify_ok && context->event_cb != NULL)
+		context->event_cb(context->cb_ctx,
+				  TLS_CERT_CHAIN_SUCCESS, NULL);
 
 	return preverify_ok;
 }
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 14b64a6..c27544b 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -29,6 +29,12 @@
 #define HOSTAPD_CHAN_HT40MINUS 0x00000020
 #define HOSTAPD_CHAN_HT40 0x00000040
 
+#define HOSTAPD_CHAN_DFS_UNKNOWN 0x00000000
+#define HOSTAPD_CHAN_DFS_USABLE 0x00000100
+#define HOSTAPD_CHAN_DFS_UNAVAILABLE 0x00000200
+#define HOSTAPD_CHAN_DFS_AVAILABLE 0x00000300
+#define HOSTAPD_CHAN_DFS_MASK 0x00000300
+
 /**
  * struct hostapd_channel_data - Channel information
  */
@@ -866,6 +872,8 @@
 #define WPA_DRIVER_FLAGS_OBSS_SCAN			0x04000000
 /* Driver supports IBSS (Ad-hoc) mode */
 #define WPA_DRIVER_FLAGS_IBSS				0x08000000
+/* Driver supports radar detection */
+#define WPA_DRIVER_FLAGS_RADAR				0x10000000
 	unsigned int flags;
 
 	int max_scan_ssids;
@@ -2658,6 +2666,25 @@
 	 * avoid frequency conflict in single channel concurrency.
 	 */
 	int (*switch_channel)(void *priv, unsigned int freq);
+
+	/**
+	 * start_dfs_cac - Listen for radar interference on the channel
+	 * @priv: Private driver interface data
+	 * @freq: Frequency (in MHz) of the channel
+	 * Returns: 0 on success, -1 on failure
+	 */
+	int (*start_dfs_cac)(void *priv, int freq);
+
+	/**
+	 * stop_ap - Removes beacon from AP
+	 * @priv: Private driver interface data
+	 * Returns: 0 on success, -1 on failure (or if not supported)
+	 *
+	 * This optional function can be used to disable AP mode related
+	 * configuration. Unlike deinit_ap, it does not change to station
+	 * mode.
+	 */
+	int (*stop_ap)(void *priv);
 };
 
 
@@ -3111,7 +3138,38 @@
 	 * with the specified client (for example, max client reached, etc.) in
 	 * AP mode.
 	 */
-	EVENT_CONNECT_FAILED_REASON
+	EVENT_CONNECT_FAILED_REASON,
+
+	/**
+	 * EVENT_RADAR_DETECTED - Notify of radar detection
+	 *
+	 * A radar has been detected on the supplied frequency, hostapd should
+	 * react accordingly (e.g., change channel).
+	 */
+	EVENT_DFS_RADAR_DETECTED,
+
+	/**
+	 * EVENT_CAC_FINISHED - Notify that channel availability check has been completed
+	 *
+	 * After a successful CAC, the channel can be marked clear and used.
+	 */
+	EVENT_DFS_CAC_FINISHED,
+
+	/**
+	 * EVENT_CAC_ABORTED - Notify that channel availability check has been aborted
+	 *
+	 * The CAC was not successful, and the channel remains in the previous
+	 * state. This may happen due to a radar beeing detected or other
+	 * external influences.
+	 */
+	EVENT_DFS_CAC_ABORTED,
+
+	/**
+	 * EVENT_DFS_CAC_NOP_FINISHED - Notify that non-occupancy period is over
+	 *
+	 * The channel which was previously unavailable is now available again.
+	 */
+	EVENT_DFS_NOP_FINISHED
 };
 
 
@@ -3749,6 +3807,14 @@
 			BLOCKED_CLIENT
 		} code;
 	} connect_failed_reason;
+
+	/**
+	 * struct dfs_event - Data for radar detected events
+	 * @freq: Frequency of the channel in MHz
+	 */
+	struct dfs_event {
+		int freq;
+	} dfs_event;
 };
 
 /**
diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c
index 565a01b..12ccc14 100644
--- a/src/drivers/driver_common.c
+++ b/src/drivers/driver_common.c
@@ -80,6 +80,10 @@
 	E2S(CH_SWITCH);
 	E2S(WNM);
 	E2S(CONNECT_FAILED_REASON);
+	E2S(DFS_RADAR_DETECTED);
+	E2S(DFS_CAC_FINISHED);
+	E2S(DFS_CAC_ABORTED);
+	E2S(DFS_NOP_FINISHED);
 	}
 
 	return "UNKNOWN";
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 213f3c3..c8f7478 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -1508,17 +1508,18 @@
 
 	data = nla_data(frame);
 	len = nla_len(frame);
-	if (len < 4 + ETH_ALEN) {
+	if (len < 4 + 2 * ETH_ALEN) {
 		wpa_printf(MSG_MSGDUMP, "nl80211: MLME event %d on %s(" MACSTR
 			   ") - too short",
 			   cmd, bss->ifname, MAC2STR(bss->addr));
 		return;
 	}
 	wpa_printf(MSG_MSGDUMP, "nl80211: MLME event %d on %s(" MACSTR ") A1="
-		   MACSTR, cmd, bss->ifname, MAC2STR(bss->addr),
-		   MAC2STR(data + 4));
+		   MACSTR " A2=" MACSTR, cmd, bss->ifname, MAC2STR(bss->addr),
+		   MAC2STR(data + 4), MAC2STR(data + 4 + ETH_ALEN));
 	if (cmd != NL80211_CMD_FRAME_TX_STATUS && !(data[4] & 0x01) &&
-	    os_memcmp(bss->addr, data + 4, ETH_ALEN) != 0) {
+	    os_memcmp(bss->addr, data + 4, ETH_ALEN) != 0 &&
+	    os_memcmp(bss->addr, data + 4 + ETH_ALEN, ETH_ALEN) != 0) {
 		wpa_printf(MSG_MSGDUMP, "nl80211: %s: Ignore MLME frame event "
 			   "for foreign address", bss->ifname);
 		return;
@@ -2249,6 +2250,43 @@
 }
 
 
+static void nl80211_radar_event(struct wpa_driver_nl80211_data *drv,
+				struct nlattr **tb)
+{
+	union wpa_event_data data;
+	enum nl80211_radar_event event_type;
+
+	if (!tb[NL80211_ATTR_WIPHY_FREQ] || !tb[NL80211_ATTR_RADAR_EVENT])
+		return;
+
+	os_memset(&data, 0, sizeof(data));
+	data.dfs_event.freq = nla_get_u16(tb[NL80211_ATTR_WIPHY_FREQ]);
+	event_type = nla_get_u8(tb[NL80211_ATTR_RADAR_EVENT]);
+
+	wpa_printf(MSG_DEBUG, "nl80211: DFS event on freq %d MHz",
+		   data.dfs_event.freq);
+
+	switch (event_type) {
+	case NL80211_RADAR_DETECTED:
+		wpa_supplicant_event(drv->ctx, EVENT_DFS_RADAR_DETECTED, &data);
+		break;
+	case NL80211_RADAR_CAC_FINISHED:
+		wpa_supplicant_event(drv->ctx, EVENT_DFS_CAC_FINISHED, &data);
+		break;
+	case NL80211_RADAR_CAC_ABORTED:
+		wpa_supplicant_event(drv->ctx, EVENT_DFS_CAC_ABORTED, &data);
+		break;
+	case NL80211_RADAR_NOP_FINISHED:
+		wpa_supplicant_event(drv->ctx, EVENT_DFS_NOP_FINISHED, &data);
+		break;
+	default:
+		wpa_printf(MSG_DEBUG, "nl80211: Unknown radar event %d "
+			   "received", event_type);
+		break;
+	}
+}
+
+
 static void nl80211_spurious_frame(struct i802_bss *bss, struct nlattr **tb,
 				   int wds)
 {
@@ -2393,6 +2431,9 @@
 	case NL80211_CMD_FT_EVENT:
 		mlme_event_ft_event(drv, tb);
 		break;
+	case NL80211_CMD_RADAR_DETECT:
+		nl80211_radar_event(drv, tb);
+		break;
 	default:
 		wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event "
 			"(cmd=%d)", cmd);
@@ -2655,6 +2696,7 @@
 		[NL80211_IFACE_COMB_MAXNUM] = { .type = NLA_U32 },
 		[NL80211_IFACE_COMB_STA_AP_BI_MATCH] = { .type = NLA_FLAG },
 		[NL80211_IFACE_COMB_NUM_CHANNELS] = { .type = NLA_U32 },
+		[NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS] = { .type = NLA_U32 },
 	},
 	iface_limit_policy[NUM_NL80211_IFACE_LIMIT] = {
 		[NL80211_IFACE_LIMIT_TYPES] = { .type = NLA_NESTED },
@@ -2668,6 +2710,9 @@
 	    !tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS])
 		return 0; /* broken combination */
 
+	if (tb_comb[NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS])
+		info->capa->flags |= WPA_DRIVER_FLAGS_RADAR;
+
 	nla_for_each_nested(nl_limit, tb_comb[NL80211_IFACE_COMB_LIMITS],
 			    rem_limit) {
 		err = nla_parse_nested(tb_limit, MAX_NL80211_IFACE_LIMIT,
@@ -5142,6 +5187,22 @@
 	    !tb_freq[NL80211_FREQUENCY_ATTR_DISABLED])
 		chan->max_tx_power = nla_get_u32(
 			tb_freq[NL80211_FREQUENCY_ATTR_MAX_TX_POWER]) / 100;
+	if (tb_freq[NL80211_FREQUENCY_ATTR_DFS_STATE]) {
+		enum nl80211_dfs_state state =
+			nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_DFS_STATE]);
+
+		switch (state) {
+		case NL80211_DFS_USABLE:
+			chan->flag |= HOSTAPD_CHAN_DFS_USABLE;
+			break;
+		case NL80211_DFS_AVAILABLE:
+			chan->flag |= HOSTAPD_CHAN_DFS_AVAILABLE;
+			break;
+		case NL80211_DFS_UNAVAILABLE:
+			chan->flag |= HOSTAPD_CHAN_DFS_UNAVAILABLE;
+			break;
+		}
+	}
 }
 
 
@@ -5155,6 +5216,7 @@
 		[NL80211_FREQUENCY_ATTR_NO_IBSS] = { .type = NLA_FLAG },
 		[NL80211_FREQUENCY_ATTR_RADAR] = { .type = NLA_FLAG },
 		[NL80211_FREQUENCY_ATTR_MAX_TX_POWER] = { .type = NLA_U32 },
+		[NL80211_FREQUENCY_ATTR_DFS_STATE] = { .type = NLA_U32 },
 	};
 	int new_channels = 0;
 	struct hostapd_channel_data *channel;
@@ -8962,6 +9024,18 @@
 }
 
 
+static int wpa_driver_nl80211_stop_ap(void *priv)
+{
+	struct i802_bss *bss = priv;
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+	if (!is_ap_interface(drv->nlmode))
+		return -1;
+	wpa_driver_nl80211_del_beacon(drv);
+	bss->beacon_set = 0;
+	return 0;
+}
+
+
 static int wpa_driver_nl80211_deinit_p2p_cli(void *priv)
 {
 	struct i802_bss *bss = priv;
@@ -9439,6 +9513,40 @@
 }
 
 
+static int nl80211_start_radar_detection(void *priv, int freq)
+{
+	struct i802_bss *bss = priv;
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+	struct nl_msg *msg;
+	int ret;
+
+	wpa_printf(MSG_DEBUG, "nl80211: Start radar detection (CAC)");
+	if (!(drv->capa.flags & WPA_DRIVER_FLAGS_RADAR)) {
+		wpa_printf(MSG_DEBUG, "nl80211: Driver does not support radar "
+			   "detection");
+		return -1;
+	}
+
+	msg = nlmsg_alloc();
+	if (!msg)
+		return -1;
+
+	nl80211_cmd(bss->drv, msg, 0, NL80211_CMD_RADAR_DETECT);
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+	NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
+
+	/* only HT20 is supported at this point */
+	NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, NL80211_CHAN_HT20);
+
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+	if (ret == 0)
+		return 0;
+	wpa_printf(MSG_DEBUG, "nl80211: Failed to start radar detection: "
+		   "%d (%s)", ret, strerror(-ret));
+nla_put_failure:
+	return -1;
+}
+
 #ifdef CONFIG_TDLS
 
 static int nl80211_send_tdls_mgmt(void *priv, const u8 *dst, u8 action_code,
@@ -9871,6 +9979,8 @@
 	.set_rekey_info = nl80211_set_rekey_info,
 	.poll_client = nl80211_poll_client,
 	.set_p2p_powersave = nl80211_set_p2p_powersave,
+	.start_dfs_cac = nl80211_start_radar_detection,
+	.stop_ap = wpa_driver_nl80211_stop_ap,
 #ifdef CONFIG_TDLS
 	.send_tdls_mgmt = nl80211_send_tdls_mgmt,
 	.tdls_oper = nl80211_tdls_oper,
diff --git a/src/utils/eloop.c b/src/utils/eloop.c
index 2de3e01..f62e2b7 100644
--- a/src/utils/eloop.c
+++ b/src/utils/eloop.c
@@ -799,6 +799,7 @@
 #endif /* CONFIG_ELOOP_POLL */
 	}
 
+	eloop.terminate = 0;
 out:
 #ifndef CONFIG_ELOOP_POLL
 	os_free(rfds);