Index: uspace/lib/c/generic/dhcp.c
===================================================================
--- uspace/lib/c/generic/dhcp.c	(revision d7dadcb4162ebe9a54c5014f67b20ba124ddd307)
+++ uspace/lib/c/generic/dhcp.c	(revision 053fc2bcb6fbea6b3e6edf10ca784c77402816d4)
@@ -84,4 +84,14 @@
 }
 
+int dhcp_discover(sysarg_t link_id)
+{
+	async_exch_t *exch = async_exchange_begin(dhcp_sess);
+
+	int rc = async_req_1_0(exch, DHCP_DISCOVER, link_id);
+	async_exchange_end(exch);
+
+	return rc;
+}
+
 /** @}
  */
Index: uspace/lib/c/include/inet/dhcp.h
===================================================================
--- uspace/lib/c/include/inet/dhcp.h	(revision d7dadcb4162ebe9a54c5014f67b20ba124ddd307)
+++ uspace/lib/c/include/inet/dhcp.h	(revision 053fc2bcb6fbea6b3e6edf10ca784c77402816d4)
@@ -41,4 +41,5 @@
 extern int dhcp_link_add(sysarg_t);
 extern int dhcp_link_remove(sysarg_t);
+extern int dhcp_discover(sysarg_t);
 
 #endif
Index: uspace/lib/c/include/ipc/dhcp.h
===================================================================
--- uspace/lib/c/include/ipc/dhcp.h	(revision d7dadcb4162ebe9a54c5014f67b20ba124ddd307)
+++ uspace/lib/c/include/ipc/dhcp.h	(revision 053fc2bcb6fbea6b3e6edf10ca784c77402816d4)
@@ -41,5 +41,6 @@
 typedef enum {
 	DHCP_LINK_ADD = IPC_FIRST_USER_METHOD,
-	DHCP_LINK_REMOVE
+	DHCP_LINK_REMOVE,
+	DHCP_DISCOVER
 } dhcp_request_t;
 
Index: uspace/lib/drv/generic/remote_ieee80211.c
===================================================================
--- uspace/lib/drv/generic/remote_ieee80211.c	(revision d7dadcb4162ebe9a54c5014f67b20ba124ddd307)
+++ uspace/lib/drv/generic/remote_ieee80211.c	(revision 053fc2bcb6fbea6b3e6edf10ca784c77402816d4)
@@ -38,7 +38,10 @@
 #include <macros.h>
 #include <str.h>
+#include <inet/dhcp.h>
+#include <inet/inetcfg.h>
 
 #include "ops/ieee80211.h"
 #include "ieee80211_iface.h"
+#include "nic_iface.h"
 
 #define MAX_STRING_SIZE 32
@@ -80,4 +83,37 @@
 }
 
+static bool mac_matches(uint8_t *mac1, uint8_t *mac2)
+{
+	for(size_t i = 0; i < ETH_ADDR; i++) {
+		if(mac1[i] != mac2[i])
+			return false;
+	}
+	
+	return true;
+}
+
+static sysarg_t get_link_id(uint8_t *mac)
+{
+	sysarg_t *link_list;
+	inet_link_info_t link_info;
+	size_t count;
+	
+	int rc = inetcfg_get_link_list(&link_list, &count);
+	if (rc != EOK)
+		return -1;
+	
+	for (size_t i = 0; i < count; i++) {
+		rc = inetcfg_link_get(link_list[i], &link_info);
+		if (rc != EOK)
+			return -1;
+		
+		if(mac_matches(mac, link_info.mac_addr)) {
+			return link_list[i];
+		}
+	}
+	
+	return -1;
+}
+
 /** Connect to specified network.
  *
@@ -130,4 +166,18 @@
 
 	async_wait_for(aid, &rc);
+	if (rc != EOK)
+		return rc;
+	
+	/* Send DHCP discover. */
+	nic_address_t wifi_mac;
+	rc = nic_get_address(dev_sess, &wifi_mac);
+	if (rc != EOK)
+		return rc;
+	
+	sysarg_t link_id = get_link_id(wifi_mac.address);
+	if(link_id == ((sysarg_t) -1))
+		return EINVAL;
+	
+	rc = dhcp_discover(link_id);
 	
 	return (int) rc;
@@ -147,4 +197,66 @@
 	    IEEE80211_DISCONNECT);
 	async_exchange_end(exch);
+	
+	if(rc != EOK)
+		return rc;
+	
+	nic_address_t wifi_mac;
+	rc = nic_get_address(dev_sess, &wifi_mac);
+	if (rc != EOK)
+		return rc;
+	
+	inet_link_info_t link_info;
+	inet_addr_info_t addr_info;
+	inet_sroute_info_t route_info;
+	sysarg_t *addr_list;
+	sysarg_t *route_list;
+	size_t count;
+	
+	/* Remove previous DHCP address. */
+	rc = inetcfg_get_addr_list(&addr_list, &count);
+	if (rc != EOK)
+		return rc;
+	
+	for (size_t i = 0; i < count; i++) {
+		rc = inetcfg_addr_get(addr_list[i], &addr_info);
+		if (rc != EOK)
+			return rc;
+		
+		rc = inetcfg_link_get(addr_info.ilink, &link_info);
+		if (rc != EOK)
+			return rc;
+		
+		if(mac_matches(wifi_mac.address, link_info.mac_addr)) {
+			if(str_test_prefix(addr_info.name, "dhcp")) {
+				rc = inetcfg_addr_delete(addr_list[i]);
+				if(rc != EOK)
+					return rc;
+				break;
+			}
+		}
+	}
+	
+	/* 
+	 * TODO: At this moment there can be only one DHCP route,
+	 * so it must be reimplemented after this limitation will be
+	 * dropped.
+	 */
+	/* Remove previous DHCP static route. */
+	rc = inetcfg_get_sroute_list(&route_list, &count);
+	if (rc != EOK)
+		return rc;
+	
+	for (size_t i = 0; i < count; i++) {
+		rc = inetcfg_sroute_get(route_list[i], &route_info);
+		if (rc != EOK)
+			return rc;
+		
+		if(str_test_prefix(route_info.name, "dhcp")) {
+			rc = inetcfg_sroute_delete(route_list[i]);
+			if(rc != EOK)
+				return rc;
+			break;
+		}
+	}
 	
 	return rc;
Index: uspace/lib/ieee80211/include/ieee80211.h
===================================================================
--- uspace/lib/ieee80211/include/ieee80211.h	(revision d7dadcb4162ebe9a54c5014f67b20ba124ddd307)
+++ uspace/lib/ieee80211/include/ieee80211.h	(revision 053fc2bcb6fbea6b3e6edf10ca784c77402816d4)
@@ -60,6 +60,6 @@
 #define IEEE80211_MAX_AMPDU_FACTOR 13
 
-/* Max passphrase length in WPA/WPA2 protocols. */
-#define IEEE80211_WPA_MAX_PASSWORD_LENGTH 64
+/* Max authentication password length. */
+#define IEEE80211_MAX_PASSW_LEN 64
 
 /** IEEE 802.11 b/g supported data rates in units of 500 kb/s. */
@@ -139,8 +139,9 @@
 	 * 
 	 * @param ieee80211_dev Pointer to IEEE 802.11 device structure.
-	 * 
-	 * @return EOK if succeed, negative error code otherwise.
-	 */
-	int (*bssid_change)(struct ieee80211_dev *);
+	 * @param connected True if connected to new BSSID, otherwise false.
+	 * 
+	 * @return EOK if succeed, negative error code otherwise.
+	 */
+	int (*bssid_change)(struct ieee80211_dev *, bool);
 	
 	/**
@@ -181,5 +182,5 @@
 	uint16_t freq);
 extern uint16_t ieee80211_get_aid(ieee80211_dev_t* ieee80211_dev);
-extern int ieee80211_get_security_suite(ieee80211_dev_t* ieee80211_dev);
+extern int ieee80211_get_pairwise_security(ieee80211_dev_t* ieee80211_dev);
 extern bool ieee80211_is_ready(ieee80211_dev_t* ieee80211_dev);
 extern void ieee80211_set_ready(ieee80211_dev_t* ieee80211_dev, bool ready);
Index: uspace/lib/ieee80211/include/ieee80211_impl.h
===================================================================
--- uspace/lib/ieee80211/include/ieee80211_impl.h	(revision d7dadcb4162ebe9a54c5014f67b20ba124ddd307)
+++ uspace/lib/ieee80211/include/ieee80211_impl.h	(revision 053fc2bcb6fbea6b3e6edf10ca784c77402816d4)
@@ -47,5 +47,6 @@
 extern int ieee80211_set_freq_impl(ieee80211_dev_t *ieee80211_dev, 
 	uint16_t freq);
-extern int ieee80211_bssid_change_impl(ieee80211_dev_t *ieee80211_dev);
+extern int ieee80211_bssid_change_impl(ieee80211_dev_t *ieee80211_dev,
+	bool connected);
 extern int ieee80211_key_config_impl(ieee80211_dev_t *ieee80211_dev,
 	ieee80211_key_config_t *key_conf, bool insert);
Index: uspace/lib/ieee80211/include/ieee80211_private.h
===================================================================
--- uspace/lib/ieee80211/include/ieee80211_private.h	(revision d7dadcb4162ebe9a54c5014f67b20ba124ddd307)
+++ uspace/lib/ieee80211/include/ieee80211_private.h	(revision 053fc2bcb6fbea6b3e6edf10ca784c77402816d4)
@@ -54,6 +54,9 @@
 #define HANDSHAKE_TIMEOUT 3000000
 
-/* Max period to rerun scan. */
-#define MAX_SCAN_SPAN_SEC 30
+/* Scanning period. */
+#define SCAN_PERIOD_USEC 35000000
+
+/* Time to wait for beacons on channel. */
+#define SCAN_CHANNEL_WAIT_USEC 200000
 
 /* Max time to keep scan result. */
@@ -187,5 +190,6 @@
 	IEEE80211_AUTH_DISCONNECTED,
 	IEEE80211_AUTH_AUTHENTICATED,
-	IEEE80211_AUTH_ASSOCIATED
+	IEEE80211_AUTH_ASSOCIATED,
+	IEEE80211_AUTH_CONNECTED
 } ieee80211_auth_phase_t;
 
@@ -202,6 +206,5 @@
 typedef struct {
 	list_t list;
-	time_t last_scan;
-	fibril_mutex_t scan_mutex;
+	fibril_mutex_t results_mutex;
 	size_t size;
 } ieee80211_scan_result_list_t;
@@ -210,5 +213,5 @@
 typedef struct {
 	uint16_t aid;
-	char password[IEEE80211_WPA_MAX_PASSWORD_LENGTH];
+	char password[IEEE80211_MAX_PASSW_LEN];
 	uint8_t ptk[MAX_PTK_LENGTH];
 	uint8_t gtk[MAX_GTK_LENGTH];
@@ -256,4 +259,10 @@
 	/** Current authentication phase. */
 	ieee80211_auth_phase_t current_auth_phase;
+	
+	/** Flag indicating whether client wants connect to network. */
+	bool pending_conn_req;
+	
+	/** Scanning guard. */
+	fibril_mutex_t scan_mutex;
 	
 	/** General purpose guard. */
@@ -368,5 +377,5 @@
 {
 	list_initialize(&results->list);
-	fibril_mutex_initialize(&results->scan_mutex);
+	fibril_mutex_initialize(&results->results_mutex);
 }
 
@@ -387,4 +396,10 @@
 }
 
+extern void ieee80211_set_connect_request(ieee80211_dev_t *ieee80211_dev);
+extern bool ieee80211_pending_connect_request(ieee80211_dev_t *ieee80211_dev);
+extern ieee80211_auth_phase_t ieee80211_get_auth_phase(ieee80211_dev_t 
+	*ieee80211_dev);
+extern void ieee80211_set_auth_phase(ieee80211_dev_t *ieee80211_dev,
+	ieee80211_auth_phase_t auth_phase);
 extern int ieee80211_probe_request(ieee80211_dev_t *ieee80211_dev, 
 	char *ssid);
Index: uspace/lib/ieee80211/src/ieee80211.c
===================================================================
--- uspace/lib/ieee80211/src/ieee80211.c	(revision d7dadcb4162ebe9a54c5014f67b20ba124ddd307)
+++ uspace/lib/ieee80211/src/ieee80211.c	(revision 053fc2bcb6fbea6b3e6edf10ca784c77402816d4)
@@ -51,4 +51,6 @@
 #define IEEE80211_EXT_DATA_RATES_SIZE 4
 
+#define ATOMIC_GET(state)
+
 /** Frame encapsulation used in IEEE 802.11. */
 static const uint8_t rfc1042_header[] = { 
@@ -282,5 +284,9 @@
 	ieee80211_dev)
 {
-	return ieee80211_dev->current_op_mode;
+	fibril_mutex_lock(&ieee80211_dev->gen_mutex);
+	ieee80211_operating_mode_t op_mode = ieee80211_dev->current_op_mode;
+	fibril_mutex_unlock(&ieee80211_dev->gen_mutex);
+	
+	return op_mode;
 }
 
@@ -294,9 +300,15 @@
 uint16_t ieee80211_query_current_freq(ieee80211_dev_t* ieee80211_dev)
 {
-	return ieee80211_dev->current_freq;
+	fibril_mutex_lock(&ieee80211_dev->gen_mutex);
+	uint16_t current_freq = ieee80211_dev->current_freq;
+	fibril_mutex_unlock(&ieee80211_dev->gen_mutex);
+	
+	return current_freq;
 }
 
 /**
  * Query BSSID the device is connected to.
+ * 
+ * Note: Expecting locked results_mutex.
  * 
  * @param ieee80211_dev IEEE 802.11 device.
@@ -306,10 +318,23 @@
 	nic_address_t *bssid)
 {
+	fibril_mutex_lock(&ieee80211_dev->gen_mutex);
+	
 	if(bssid) {
-		ieee80211_scan_result_t *auth_data =
-			&ieee80211_dev->bssid_info.res_link->scan_result;
-		
-		memcpy(bssid, (void *)&auth_data->bssid, sizeof(nic_address_t));
-	}
+		ieee80211_scan_result_link_t *res_link = 
+			ieee80211_dev->bssid_info.res_link;
+		
+		if(res_link) {
+			memcpy(bssid, &res_link->scan_result.bssid, 
+				sizeof(nic_address_t));
+		} else {
+			nic_address_t broadcast_addr;
+			memcpy(broadcast_addr.address,
+				ieee80211_broadcast_mac_addr,
+				ETH_ADDR);
+			memcpy(bssid, &broadcast_addr, sizeof(nic_address_t));
+		}
+	}
+	
+	fibril_mutex_unlock(&ieee80211_dev->gen_mutex);
 }
 
@@ -323,9 +348,13 @@
 uint16_t ieee80211_get_aid(ieee80211_dev_t* ieee80211_dev)
 {
-	return ieee80211_dev->bssid_info.aid;
-}
-
-/**
- * Get security suite used for HW encryption. 
+	fibril_mutex_lock(&ieee80211_dev->gen_mutex);
+	uint16_t aid = ieee80211_dev->bssid_info.aid;
+	fibril_mutex_unlock(&ieee80211_dev->gen_mutex);
+	
+	return aid;
+}
+
+/**
+ * Get pairwise security suite used for HW encryption. 
  * 
  * @param ieee80211_dev IEEE 802.11 device.
@@ -333,10 +362,13 @@
  * @return Security suite indicator.
  */
-int ieee80211_get_security_suite(ieee80211_dev_t* ieee80211_dev)
-{
+int ieee80211_get_pairwise_security(ieee80211_dev_t* ieee80211_dev)
+{
+	fibril_mutex_lock(&ieee80211_dev->gen_mutex);
 	ieee80211_scan_result_link_t *auth_link = 
 		ieee80211_dev->bssid_info.res_link;
-	
-	return auth_link->scan_result.security.pair_alg;
+	int suite = auth_link->scan_result.security.pair_alg;
+	fibril_mutex_unlock(&ieee80211_dev->gen_mutex);
+	
+	return suite;
 }
 
@@ -350,5 +382,42 @@
 bool ieee80211_is_connected(ieee80211_dev_t* ieee80211_dev)
 {
-	return ieee80211_dev->current_auth_phase == IEEE80211_AUTH_ASSOCIATED;
+	fibril_mutex_lock(&ieee80211_dev->gen_mutex);
+	bool conn_state = 
+		ieee80211_dev->current_auth_phase == IEEE80211_AUTH_CONNECTED;
+	fibril_mutex_unlock(&ieee80211_dev->gen_mutex);
+	return conn_state;
+}
+
+void ieee80211_set_auth_phase(ieee80211_dev_t *ieee80211_dev,
+	ieee80211_auth_phase_t auth_phase)
+{
+	fibril_mutex_lock(&ieee80211_dev->gen_mutex);
+	ieee80211_dev->current_auth_phase = auth_phase;
+	fibril_mutex_unlock(&ieee80211_dev->gen_mutex);
+}
+
+ieee80211_auth_phase_t ieee80211_get_auth_phase(ieee80211_dev_t 
+	*ieee80211_dev)
+{
+	fibril_mutex_lock(&ieee80211_dev->gen_mutex);
+	ieee80211_auth_phase_t conn_state = ieee80211_dev->current_auth_phase;
+	fibril_mutex_unlock(&ieee80211_dev->gen_mutex);
+	return conn_state;
+}
+
+void ieee80211_set_connect_request(ieee80211_dev_t *ieee80211_dev)
+{
+	fibril_mutex_lock(&ieee80211_dev->gen_mutex);
+	ieee80211_dev->pending_conn_req = true;
+	fibril_mutex_unlock(&ieee80211_dev->gen_mutex);
+}
+
+bool ieee80211_pending_connect_request(ieee80211_dev_t *ieee80211_dev)
+{
+	fibril_mutex_lock(&ieee80211_dev->gen_mutex);
+	bool conn_request = ieee80211_dev->pending_conn_req;
+	ieee80211_dev->pending_conn_req = false;
+	fibril_mutex_unlock(&ieee80211_dev->gen_mutex);
+	return conn_request;
 }
 
@@ -362,5 +431,7 @@
 	ieee80211_operating_mode_t op_mode)
 {
+	fibril_mutex_lock(&ieee80211_dev->gen_mutex);
 	ieee80211_dev->current_op_mode = op_mode;
+	fibril_mutex_unlock(&ieee80211_dev->gen_mutex);
 }
 
@@ -374,5 +445,7 @@
 	uint16_t freq)
 {
+	fibril_mutex_lock(&ieee80211_dev->gen_mutex);
 	ieee80211_dev->current_freq = freq;
+	fibril_mutex_unlock(&ieee80211_dev->gen_mutex);
 }
 
@@ -408,5 +481,9 @@
 extern bool ieee80211_query_using_key(ieee80211_dev_t* ieee80211_dev)
 {
-	return ieee80211_dev->using_hw_key;
+	fibril_mutex_lock(&ieee80211_dev->gen_mutex);
+	bool using_key = ieee80211_dev->using_hw_key;
+	fibril_mutex_unlock(&ieee80211_dev->gen_mutex);
+	
+	return using_key;
 }
 
@@ -414,5 +491,21 @@
 	bool using_key)
 {
+	fibril_mutex_lock(&ieee80211_dev->gen_mutex);
 	ieee80211_dev->using_hw_key = using_key;
+	fibril_mutex_unlock(&ieee80211_dev->gen_mutex);
+}
+
+static int ieee80211_scan(void *arg)
+{
+	assert(arg);
+	
+	ieee80211_dev_t *ieee80211_dev = (ieee80211_dev_t *) arg;
+	
+	while(true) {
+		ieee80211_dev->ops->scan(ieee80211_dev);
+		async_usleep(35000000);
+	}
+	
+	return EOK;
 }
 
@@ -439,7 +532,10 @@
 		return rc;
 	
-	rc = ieee80211_dev->ops->scan(ieee80211_dev);
-	if(rc != EOK)
-		return rc;
+	/* Add scanning fibril. */
+	fid_t fibril = fibril_create(ieee80211_scan, ieee80211_dev);
+	if (fibril == 0) {
+		return ENOMEM;
+	}
+	fibril_add_ready(fibril);
 	
 	return EOK;
@@ -458,5 +554,8 @@
 		nic_get_specific(nic);
 	
-	if(!ieee80211_is_connected(ieee80211_dev)) {
+	ieee80211_auth_phase_t auth_phase = 
+		ieee80211_get_auth_phase(ieee80211_dev);
+	if(auth_phase != IEEE80211_AUTH_ASSOCIATED && 
+		auth_phase != IEEE80211_AUTH_CONNECTED) {
 		return;
 	}
@@ -478,5 +577,5 @@
 	memset(add_data, 0, 8);
 	
-	if(ieee80211_dev->using_hw_key) {
+	if(ieee80211_query_using_key(ieee80211_dev)) {
 		int sec_suite = auth_data->security.pair_alg;
 		switch(sec_suite) {
@@ -630,4 +729,5 @@
 	ieee80211_dev->ready = false;
 	ieee80211_dev->using_hw_key = false;
+	ieee80211_dev->pending_conn_req = false;
 	ieee80211_dev->current_op_mode = IEEE80211_OPMODE_STATION;
 	ieee80211_dev->current_auth_phase = IEEE80211_AUTH_DISCONNECTED;
@@ -637,4 +737,5 @@
 	ieee80211_scan_result_list_init(&ieee80211_dev->ap_list);
 	
+	fibril_mutex_initialize(&ieee80211_dev->scan_mutex);
 	fibril_mutex_initialize(&ieee80211_dev->gen_mutex);
 	fibril_condvar_initialize(&ieee80211_dev->gen_cond);
@@ -923,7 +1024,7 @@
 	
 	/* 
-	 * Save password and SSID to be used in eventual authentication 
-	 * handshake. 
+	 * Save password to be used in eventual authentication handshake. 
 	 */
+	memset(ieee80211_dev->bssid_info.password, 0, IEEE80211_MAX_PASSW_LEN);
 	memcpy(ieee80211_dev->bssid_info.password, password, 
 		str_size(password));
@@ -945,9 +1046,4 @@
 	ieee80211_scan_result_t *auth_data =
 		&ieee80211_dev->bssid_info.res_link->scan_result;
-	
-	ieee80211_dev->current_auth_phase = IEEE80211_AUTH_DISCONNECTED;
-	ieee80211_dev->bssid_info.aid = (uint16_t) -1;
-	memcpy(auth_data->bssid.address, ieee80211_broadcast_mac_addr, 
-		ETH_ADDR);
 	
 	nic_t *nic = nic_get_from_ddf_dev(ieee80211_dev->ddf_dev);
@@ -975,5 +1071,11 @@
 	free(buffer);
 	
-	ieee80211_dev->ops->bssid_change(ieee80211_dev);
+	ieee80211_dev->bssid_info.res_link = NULL;
+	ieee80211_dev->ops->bssid_change(ieee80211_dev, false);
+	
+	if(ieee80211_query_using_key(ieee80211_dev))
+		ieee80211_dev->ops->key_config(ieee80211_dev, NULL, false);
+	
+	ieee80211_set_auth_phase(ieee80211_dev, IEEE80211_AUTH_DISCONNECTED);
 	
 	return EOK;
@@ -1121,8 +1223,4 @@
 	/* Not empty SSID. */
 	if(ssid_ie_header->length > 0) {
-		fibril_mutex_t *scan_mutex = &ieee80211_dev->ap_list.scan_mutex;
-		
-		fibril_mutex_lock(scan_mutex);
-		
 		ieee80211_scan_result_list_t *result_list =
 			&ieee80211_dev->ap_list;
@@ -1138,5 +1236,4 @@
 			if(!str_cmp(ssid, result->scan_result.ssid)) {
 				result->last_beacon = time(NULL);
-				fibril_mutex_unlock(scan_mutex);
 				return EOK;
 			}
@@ -1145,5 +1242,4 @@
 		/* Results are full. */
 		if(result_list->size == IEEE80211_MAX_RESULTS_LENGTH - 1) {
-			fibril_mutex_unlock(scan_mutex);
 			return EOK;
 		}
@@ -1183,7 +1279,7 @@
 		ap_data->last_beacon = time(NULL);
 		
+		fibril_mutex_lock(&ieee80211_dev->ap_list.results_mutex);
 		ieee80211_scan_result_list_append(result_list, ap_data);
-		
-		fibril_mutex_unlock(scan_mutex);
+		fibril_mutex_unlock(&ieee80211_dev->ap_list.results_mutex);
 	}
 	
@@ -1202,8 +1298,17 @@
 	ieee80211_mgmt_header_t *mgmt_header)
 {
-	fibril_mutex_lock(&ieee80211_dev->gen_mutex);
-	
-	ieee80211_dev->current_auth_phase = IEEE80211_AUTH_AUTHENTICATED;
-	
+	ieee80211_auth_body_t *auth_body =
+		(ieee80211_auth_body_t *)
+		((void *)mgmt_header + sizeof(ieee80211_mgmt_header_t));
+	
+	if(auth_body->status != 0) {
+		ieee80211_set_auth_phase(ieee80211_dev, 
+			IEEE80211_AUTH_DISCONNECTED);
+	} else {
+		ieee80211_set_auth_phase(ieee80211_dev, 
+			IEEE80211_AUTH_AUTHENTICATED);
+	}
+	
+	fibril_mutex_lock(&ieee80211_dev->gen_mutex);
 	fibril_condvar_signal(&ieee80211_dev->gen_cond);
 	fibril_mutex_unlock(&ieee80211_dev->gen_mutex);
@@ -1223,20 +1328,20 @@
 	ieee80211_mgmt_header_t *mgmt_header)
 {
-	ieee80211_scan_result_t *auth_data =
-		&ieee80211_dev->bssid_info.res_link->scan_result;
-	
-	fibril_mutex_lock(&ieee80211_dev->gen_mutex);
-	
 	ieee80211_assoc_resp_body_t *assoc_resp =
 		(ieee80211_assoc_resp_body_t *) ((void *)mgmt_header +
 		sizeof(ieee80211_mgmt_header_t));
 	
-	ieee80211_dev->bssid_info.aid = uint16_t_le2host(assoc_resp->aid);
-	memcpy(auth_data->bssid.address, mgmt_header->bssid, ETH_ADDR);
-	
-	ieee80211_dev->current_auth_phase = IEEE80211_AUTH_ASSOCIATED;
-	
-	ieee80211_dev->ops->bssid_change(ieee80211_dev);
-	
+	if(assoc_resp->status != 0) {
+		ieee80211_set_auth_phase(ieee80211_dev, 
+			IEEE80211_AUTH_DISCONNECTED);
+	} else {
+		ieee80211_dev->bssid_info.aid = 
+			uint16_t_le2host(assoc_resp->aid);
+		ieee80211_set_auth_phase(ieee80211_dev, 
+			IEEE80211_AUTH_ASSOCIATED);
+		ieee80211_dev->ops->bssid_change(ieee80211_dev, true);
+	}
+	
+	fibril_mutex_lock(&ieee80211_dev->gen_mutex);
 	fibril_condvar_signal(&ieee80211_dev->gen_cond);
 	fibril_mutex_unlock(&ieee80211_dev->gen_mutex);
@@ -1418,7 +1523,5 @@
 
 	if(handshake_done) {
-		/* Insert keys into device. */
-		
-		/* Pairwise key. */
+		/* Insert Pairwise key. */
 		ieee80211_key_config_t key_config;
 		key_config.suite = auth_data->security.pair_alg;
@@ -1432,5 +1535,5 @@
 			&key_config, true);
 		
-		/* Group key. */
+		/* Insert Group key. */
 		key_config.suite = auth_data->security.group_alg;
 		key_config.flags =
Index: uspace/lib/ieee80211/src/ieee80211_iface_impl.c
===================================================================
--- uspace/lib/ieee80211/src/ieee80211_iface_impl.c	(revision d7dadcb4162ebe9a54c5014f67b20ba124ddd307)
+++ uspace/lib/ieee80211/src/ieee80211_iface_impl.c	(revision 053fc2bcb6fbea6b3e6edf10ca784c77402816d4)
@@ -48,5 +48,5 @@
  * @param results Structure where should be stored scan results.
  * 
- * @return EOK. 
+ * @return EOK if everything went OK, EREFUSED when device is not ready yet.
  */
 int ieee80211_get_scan_results_impl(ddf_fun_t *fun, 
@@ -59,13 +59,9 @@
 		return EREFUSED;
 	
-	fibril_mutex_lock(&ieee80211_dev->ap_list.scan_mutex);
-	time_t scan_span = time(NULL) - ieee80211_dev->ap_list.last_scan;
-	fibril_mutex_unlock(&ieee80211_dev->ap_list.scan_mutex);
-	
-	if(now || scan_span > MAX_SCAN_SPAN_SEC) {
+	if(now) {
 		ieee80211_dev->ops->scan(ieee80211_dev);
 	}
 	
-	fibril_mutex_lock(&ieee80211_dev->ap_list.scan_mutex);
+	fibril_mutex_lock(&ieee80211_dev->ap_list.results_mutex);
 	if(results) {
 		ieee80211_scan_result_list_t *result_list =
@@ -82,5 +78,5 @@
 		results->length = i;
 	}
-	fibril_mutex_unlock(&ieee80211_dev->ap_list.scan_mutex);
+	fibril_mutex_unlock(&ieee80211_dev->ap_list.results_mutex);
 	
 	return EOK;
@@ -103,10 +99,8 @@
 	ieee80211_scan_result_link_t *auth_data, char *password)
 {
-	int rc;
-	
 	ieee80211_dev->bssid_info.res_link = auth_data;
 	
 	/* Set channel. */
-	rc = ieee80211_dev->ops->set_freq(ieee80211_dev, 
+	int rc = ieee80211_dev->ops->set_freq(ieee80211_dev, 
 		ieee80211_channel_to_freq(auth_data->scan_result.channel));
 	if(rc != EOK)
@@ -122,6 +116,10 @@
 	if(rc != EOK)
 		return rc;
-	if(ieee80211_dev->current_auth_phase != IEEE80211_AUTH_AUTHENTICATED)
+	if(ieee80211_get_auth_phase(ieee80211_dev) != 
+		IEEE80211_AUTH_AUTHENTICATED) {
+		ieee80211_set_auth_phase(ieee80211_dev, 
+			IEEE80211_AUTH_DISCONNECTED);
 		return EINVAL;
+	}
 	
 	/* Try to associate. */
@@ -134,21 +132,26 @@
 	if(rc != EOK)
 		return rc;
-	if(ieee80211_dev->current_auth_phase != IEEE80211_AUTH_ASSOCIATED)
+	if(ieee80211_get_auth_phase(ieee80211_dev) != 
+		IEEE80211_AUTH_ASSOCIATED) {
+		ieee80211_set_auth_phase(ieee80211_dev, 
+			IEEE80211_AUTH_DISCONNECTED);
 		return EINVAL;
+	}
 	
 	/* On open network, we are finished. */
-	if(auth_data->scan_result.security.type == IEEE80211_SECURITY_OPEN)
-		return EOK;
-	
-	/* Otherwise wait for 4-way handshake to complete. */
-	fibril_mutex_lock(&ieee80211_dev->gen_mutex);
-	rc = fibril_condvar_wait_timeout(&ieee80211_dev->gen_cond,
-			&ieee80211_dev->gen_mutex,
-			HANDSHAKE_TIMEOUT);
-	fibril_mutex_unlock(&ieee80211_dev->gen_mutex);
-	if(rc != EOK)
-		return rc;
-	if(ieee80211_dev->current_auth_phase != IEEE80211_AUTH_ASSOCIATED)
-		return EINVAL;
+	if(auth_data->scan_result.security.type != IEEE80211_SECURITY_OPEN) {
+		/* Otherwise wait for 4-way handshake to complete. */
+		fibril_mutex_lock(&ieee80211_dev->gen_mutex);
+		rc = fibril_condvar_wait_timeout(&ieee80211_dev->gen_cond,
+				&ieee80211_dev->gen_mutex,
+				HANDSHAKE_TIMEOUT);
+		fibril_mutex_unlock(&ieee80211_dev->gen_mutex);
+		if(rc != EOK) {
+			ieee80211_deauthenticate(ieee80211_dev);
+			return rc;
+		}
+	}
+	
+	ieee80211_set_auth_phase(ieee80211_dev, IEEE80211_AUTH_CONNECTED);
 	
 	return EOK;
@@ -163,5 +166,5 @@
  * @return EOK if everything OK, ETIMEOUT when timeout during authenticating,
  * EINVAL when SSID not in scan results list, EPERM when incorrect password
- * passed.
+ * passed, EREFUSED when device is not ready yet.
  */
 int ieee80211_connect_impl(ddf_fun_t *fun, char *ssid_start, char *password)
@@ -170,4 +173,6 @@
 	assert(password);
 	
+	int rc;
+	
 	nic_t *nic_data = nic_get_from_ddf_fun(fun);
 	ieee80211_dev_t *ieee80211_dev = nic_get_specific(nic_data);
@@ -177,10 +182,15 @@
 	
 	if(ieee80211_is_connected(ieee80211_dev)) {
-		int rc = ieee80211_dev->iface->disconnect(fun);
+		rc = ieee80211_dev->iface->disconnect(fun);
 		if(rc != EOK)
 			return rc;
 	}
 	
-	fibril_mutex_lock(&ieee80211_dev->ap_list.scan_mutex);
+	ieee80211_set_connect_request(ieee80211_dev);
+	
+	rc = ENOENT;
+	fibril_mutex_lock(&ieee80211_dev->scan_mutex);
+	
+	ieee80211_dev->pending_conn_req = false;
 
 	ieee80211_scan_result_list_foreach(ieee80211_dev->ap_list, result) {
@@ -188,13 +198,13 @@
 			result->scan_result.ssid, 
 			str_size(ssid_start))) {
-			fibril_mutex_unlock(&ieee80211_dev->ap_list.scan_mutex);
-			return ieee80211_connect_proc(ieee80211_dev, result,
+			rc = ieee80211_connect_proc(ieee80211_dev, result,
 				password);
+			break;
 		}
 	}
 	
-	fibril_mutex_unlock(&ieee80211_dev->ap_list.scan_mutex);
-	
-	return EINVAL;
+	fibril_mutex_unlock(&ieee80211_dev->scan_mutex);
+	
+	return rc;
 }
 
@@ -204,5 +214,5 @@
  * @param fun Device function.
  * 
- * @return EOK if everything OK, EINVAL when not connected to any network.
+ * @return EOK if everything OK, EREFUSED if device is not ready yet.
  */
 int ieee80211_disconnect_impl(ddf_fun_t *fun)
@@ -215,7 +225,10 @@
 	
 	if(!ieee80211_is_connected(ieee80211_dev)) {
-		return EINVAL;
+		return EOK;
 	} else {
-		return ieee80211_deauthenticate(ieee80211_dev);
+		fibril_mutex_lock(&ieee80211_dev->ap_list.results_mutex);
+		int rc = ieee80211_deauthenticate(ieee80211_dev);
+		fibril_mutex_unlock(&ieee80211_dev->ap_list.results_mutex);
+		return rc;
 	}
 }
Index: uspace/lib/ieee80211/src/ieee80211_impl.c
===================================================================
--- uspace/lib/ieee80211/src/ieee80211_impl.c	(revision d7dadcb4162ebe9a54c5014f67b20ba124ddd307)
+++ uspace/lib/ieee80211/src/ieee80211_impl.c	(revision 053fc2bcb6fbea6b3e6edf10ca784c77402816d4)
@@ -90,5 +90,6 @@
  * @return EOK. 
  */
-int ieee80211_bssid_change_impl(ieee80211_dev_t *ieee80211_dev)
+int ieee80211_bssid_change_impl(ieee80211_dev_t *ieee80211_dev, 
+	bool connected)
 {
 	return EOK;
@@ -118,43 +119,45 @@
 int ieee80211_scan_impl(ieee80211_dev_t *ieee80211_dev)
 {
-	if(ieee80211_is_connected(ieee80211_dev))
-		return EOK;
-	
-	fibril_mutex_lock(&ieee80211_dev->ap_list.scan_mutex);
-	
-	/* Remove old entries we don't receive beacons from. */
-	ieee80211_scan_result_list_t *result_list = 
-		&ieee80211_dev->ap_list;
-	list_foreach_safe(result_list->list, cur_link, next_link) {
-		ieee80211_scan_result_link_t *cur_result = 
-			list_get_instance(cur_link,
-			ieee80211_scan_result_link_t, 
-			link);
-		if((time(NULL) - cur_result->last_beacon) > 
-			MAX_KEEP_SCAN_SPAN_SEC) {
-			ieee80211_scan_result_list_remove(result_list, 
-				cur_result);
+	fibril_mutex_lock(&ieee80211_dev->scan_mutex);
+	
+	if(ieee80211_get_auth_phase(ieee80211_dev) == 
+		IEEE80211_AUTH_DISCONNECTED) {
+		fibril_mutex_lock(&ieee80211_dev->ap_list.results_mutex);
+		/* Remove old entries we don't receive beacons from. */
+		ieee80211_scan_result_list_t *result_list = 
+			&ieee80211_dev->ap_list;
+		list_foreach_safe(result_list->list, cur_link, next_link) {
+			ieee80211_scan_result_link_t *cur_result = 
+				list_get_instance(cur_link,
+				ieee80211_scan_result_link_t, 
+				link);
+			if((time(NULL) - cur_result->last_beacon) > 
+				MAX_KEEP_SCAN_SPAN_SEC) {
+				ieee80211_scan_result_list_remove(result_list, 
+					cur_result);
+			}
 		}
-	}
-	
-	fibril_mutex_unlock(&ieee80211_dev->ap_list.scan_mutex);
-	
-	uint16_t orig_freq = ieee80211_dev->current_freq;
-	
-	for(uint16_t freq = IEEE80211_FIRST_FREQ;
-		freq <= IEEE80211_MAX_FREQ; 
-		freq += IEEE80211_CHANNEL_GAP) {
-		ieee80211_dev->ops->set_freq(ieee80211_dev, freq);
-		ieee80211_probe_request(ieee80211_dev, NULL);
-		
-		/* Wait for probe responses. */
-		usleep(100000);
-	}
-	
-	ieee80211_dev->ops->set_freq(ieee80211_dev, orig_freq);
-	
-	fibril_mutex_lock(&ieee80211_dev->ap_list.scan_mutex);
-	time(&ieee80211_dev->ap_list.last_scan);
-	fibril_mutex_unlock(&ieee80211_dev->ap_list.scan_mutex);
+		fibril_mutex_unlock(&ieee80211_dev->ap_list.results_mutex);
+
+		uint16_t orig_freq = ieee80211_dev->current_freq;
+
+		for(uint16_t freq = IEEE80211_FIRST_FREQ;
+			freq <= IEEE80211_MAX_FREQ; 
+			freq += IEEE80211_CHANNEL_GAP) {
+			if(ieee80211_pending_connect_request(ieee80211_dev)) {
+				break;
+			}
+			
+			ieee80211_dev->ops->set_freq(ieee80211_dev, freq);
+			ieee80211_probe_request(ieee80211_dev, NULL);
+
+			/* Wait for probe responses. */
+			async_usleep(SCAN_CHANNEL_WAIT_USEC);
+		}
+
+		ieee80211_dev->ops->set_freq(ieee80211_dev, orig_freq);
+	}
+	
+	fibril_mutex_unlock(&ieee80211_dev->scan_mutex);
 	
 	return EOK;
