Index: uspace/app/wifi_supplicant/wifi_supplicant.c
===================================================================
--- uspace/app/wifi_supplicant/wifi_supplicant.c	(revision d7dadcb4162ebe9a54c5014f67b20ba124ddd307)
+++ uspace/app/wifi_supplicant/wifi_supplicant.c	(revision 053fc2bcb6fbea6b3e6edf10ca784c77402816d4)
@@ -36,4 +36,6 @@
 #include <ieee80211_iface.h>
 
+#include <inet/inetcfg.h>
+#include <inet/dhcp.h>
 #include <errno.h>
 #include <stdio.h>
@@ -173,5 +175,17 @@
 	}
 	
-	int rc = ieee80211_connect(sess, ssid_start, password);
+	int rc = ieee80211_disconnect(sess);
+	if(rc != EOK) {
+		if(rc == EREFUSED) {
+			printf("Device is not ready yet.\n");			
+		} else {
+			printf("Error when disconnecting device. "
+				"Error: %d\n", rc);
+		}
+		
+		return rc;
+	}
+	
+	ieee80211_connect(sess, ssid_start, password);
 	if(rc != EOK) {
 		if(rc == EREFUSED) {
@@ -179,6 +193,6 @@
 		} else if(rc == ETIMEOUT) {
 			printf("Timeout when authenticating to network.\n");
-		} else if(rc == EPERM) {
-			printf("Bad password provided.\n");
+		} else if(rc == ENOENT) {
+			printf("Given SSID not in scan results.\n");
 		} else {
 			printf("Error when connecting to network. "
@@ -188,4 +202,6 @@
 		return rc;
 	}
+	
+	// TODO: Wait for DHCP address ?
 	
 	printf("Successfully connected to network!\n");
@@ -274,4 +290,17 @@
 	int rc;
 	uint32_t index;
+	
+	rc = inetcfg_init();
+	if (rc != EOK) {
+		printf(NAME ": Failed connecting to inetcfg service (%d).\n",
+		    rc);
+		return 1;
+	}
+	
+	rc = dhcp_init();
+	if (rc != EOK) {
+		printf(NAME ": Failed connecting to dhcp service (%d).\n", rc);
+		return 1;
+	}
 	
 	if(argc == 2) {
Index: uspace/drv/nic/ar9271/ar9271.c
===================================================================
--- uspace/drv/nic/ar9271/ar9271.c	(revision d7dadcb4162ebe9a54c5014f67b20ba124ddd307)
+++ uspace/drv/nic/ar9271/ar9271.c	(revision 053fc2bcb6fbea6b3e6edf10ca784c77402816d4)
@@ -105,5 +105,6 @@
 static int ar9271_ieee80211_set_freq(ieee80211_dev_t *ieee80211_dev,
 	uint16_t freq);
-static int ar9271_ieee80211_bssid_change(ieee80211_dev_t *ieee80211_dev);
+static int ar9271_ieee80211_bssid_change(ieee80211_dev_t *ieee80211_dev,
+	bool connected);
 static int ar9271_ieee80211_key_config(ieee80211_dev_t *ieee80211_dev,
 	ieee80211_key_config_t *key_conf, bool insert);
@@ -351,6 +352,4 @@
 	ar9271_t *ar9271 = (ar9271_t *) ieee80211_get_specific(ieee80211_dev);
 	
-	//hw_wakeup(ar9271);
-	
 	wmi_send_command(ar9271->htc_device, WMI_DISABLE_INTR, NULL, 0, NULL);
 	wmi_send_command(ar9271->htc_device, WMI_DRAIN_TXQ_ALL, NULL, 0, NULL);
@@ -379,5 +378,6 @@
 }
 
-static int ar9271_ieee80211_bssid_change(ieee80211_dev_t *ieee80211_dev)
+static int ar9271_ieee80211_bssid_change(ieee80211_dev_t *ieee80211_dev,
+	bool connected)
 {
 	assert(ieee80211_dev);
@@ -385,6 +385,5 @@
 	ar9271_t *ar9271 = (ar9271_t *) ieee80211_get_specific(ieee80211_dev);
 
-	/* Check if we are connected or disconnected. */
-	if(ieee80211_is_connected(ieee80211_dev)) {
+	if(connected) {
 		nic_address_t bssid;
 		ieee80211_query_bssid(ieee80211_dev, &bssid);
@@ -433,14 +432,15 @@
 {
 	assert(ieee80211_dev);
-	assert(key_conf);
 	
 	ar9271_t *ar9271 = (ar9271_t *) ieee80211_get_specific(ieee80211_dev);
 	
-	uint32_t key[5];
-	uint32_t key_type;
-	uint32_t reg_ptr;
-	void *data_start;
-	
 	if(insert) {
+		assert(key_conf);
+		
+		uint32_t key[5];
+		uint32_t key_type;
+		uint32_t reg_ptr;
+		void *data_start;
+		
 		nic_address_t bssid;
 		ieee80211_query_bssid(ieee80211_dev, &bssid);
@@ -520,5 +520,6 @@
 			ieee80211_setup_key_confirm(ieee80211_dev, true);
 	} else {
-		// TODO
+		// TODO: Delete keys from device
+		ieee80211_setup_key_confirm(ieee80211_dev, false);
 	}
 	
@@ -562,5 +563,5 @@
 			data_header->keyix = AR9271_STA_KEY_INDEX;
 			int sec_suite = 
-				ieee80211_get_security_suite(ieee80211_dev);
+				ieee80211_get_pairwise_security(ieee80211_dev);
 			switch(sec_suite) {
 				case IEEE80211_SECURITY_SUITE_WEP40:
Index: uspace/drv/nic/ar9271/hw.c
===================================================================
--- uspace/drv/nic/ar9271/hw.c	(revision d7dadcb4162ebe9a54c5014f67b20ba124ddd307)
+++ uspace/drv/nic/ar9271/hw.c	(revision 053fc2bcb6fbea6b3e6edf10ca784c77402816d4)
@@ -377,47 +377,4 @@
 }
 
-int hw_wakeup(ar9271_t *ar9271)
-{
-	int rc;
-	
-	uint32_t rtc_status;
-	wmi_reg_read(ar9271->htc_device, AR9271_RTC_STATUS, &rtc_status);
-	if((rtc_status & AR9271_RTC_STATUS_MASK) == AR9271_RTC_STATUS_SHUTDOWN) {
-		rc = hw_reset_power_on(ar9271);
-		if(rc != EOK) {
-			usb_log_info("Failed to HW reset power on.\n");
-			return rc;
-		}
-
-		rc = hw_set_reset(ar9271, false);
-		if(rc != EOK) {
-			usb_log_info("Failed to HW warm reset.\n");
-			return rc;
-		}
-	}
-	
-	wmi_reg_set_bit(ar9271->htc_device, AR9271_RTC_FORCE_WAKE,
-		AR9271_RTC_FORCE_WAKE_ENABLE);
-	
-	size_t i;
-	for(i = 0; i < HW_WAIT_LOOPS; i++) {
-		wmi_reg_read(ar9271->htc_device, AR9271_RTC_STATUS, 
-			&rtc_status);
-		if((rtc_status & AR9271_RTC_STATUS_MASK) == 
-			AR9271_RTC_STATUS_ON) {
-			break;
-		}
-		wmi_reg_set_bit(ar9271->htc_device, AR9271_RTC_FORCE_WAKE,
-			AR9271_RTC_FORCE_WAKE_ENABLE);
-		udelay(50);
-	}	
-	
-	if(i == HW_WAIT_LOOPS) {
-		return EINVAL;
-	} else {
-		return EOK;
-	}
-}
-
 int hw_freq_switch(ar9271_t *ar9271, uint16_t freq)
 {
Index: uspace/drv/nic/ar9271/hw.h
===================================================================
--- uspace/drv/nic/ar9271/hw.h	(revision d7dadcb4162ebe9a54c5014f67b20ba124ddd307)
+++ uspace/drv/nic/ar9271/hw.h	(revision 053fc2bcb6fbea6b3e6edf10ca784c77402816d4)
@@ -45,5 +45,4 @@
 extern int hw_rx_init(ar9271_t *ar9271);
 extern int hw_reset(ar9271_t *ar9271);
-extern int hw_wakeup(ar9271_t *ar9271);
 extern int hw_set_bssid(ar9271_t *ar9271);
 extern int hw_set_rx_filter(ar9271_t *ar9271, bool assoc);
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;
Index: uspace/srv/net/dhcp/dhcp.c
===================================================================
--- uspace/srv/net/dhcp/dhcp.c	(revision d7dadcb4162ebe9a54c5014f67b20ba124ddd307)
+++ uspace/srv/net/dhcp/dhcp.c	(revision 053fc2bcb6fbea6b3e6edf10ca784c77402816d4)
@@ -418,4 +418,23 @@
 }
 
+static int dhcp_discover_proc(dhcp_link_t *dlink)
+{
+	dlink->state = ds_selecting;
+
+	int rc = dhcp_send_discover(dlink);
+	if (rc != EOK)
+		return EIO;
+
+	dlink->retries_left = dhcp_discover_retries;
+	
+	if(dlink->timeout->state == fts_not_set || 
+		dlink->timeout->state == fts_fired) {
+		fibril_timer_set(dlink->timeout, dhcp_discover_timeout_val,
+			dhcpsrv_discover_timeout, dlink);
+	}
+	
+	return rc;
+}
+
 int dhcpsrv_link_add(service_id_t link_id)
 {
@@ -459,8 +478,6 @@
 	}
 
-	dlink->state = ds_selecting;
-
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "Send DHCPDISCOVER");
-	rc = dhcp_send_discover(dlink);
+	rc = dhcp_discover_proc(dlink);
 	if (rc != EOK) {
 		log_msg(LOG_DEFAULT, LVL_ERROR, "Error sending DHCPDISCOVER.");
@@ -469,8 +486,4 @@
 		goto error;
 	}
-
-	dlink->retries_left = dhcp_discover_retries;
-	fibril_timer_set(dlink->timeout, dhcp_discover_timeout_val,
-	    dhcpsrv_discover_timeout, dlink);
 
 	list_append(&dlink->links, &dhcp_links);
@@ -487,4 +500,19 @@
 {
 	return ENOTSUP;
+}
+
+int dhcpsrv_discover(service_id_t link_id)
+{
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "dhcpsrv_link_add(%zu)", link_id);
+	
+	dhcp_link_t *dlink = dhcpsrv_link_find(link_id);
+
+	if (dlink == NULL) {
+		log_msg(LOG_DEFAULT, LVL_NOTE, "Link %zu doesn't exist",
+		    link_id);
+		return EINVAL;
+	}
+	
+	return dhcp_discover_proc(dlink);
 }
 
Index: uspace/srv/net/dhcp/dhcp.h
===================================================================
--- uspace/srv/net/dhcp/dhcp.h	(revision d7dadcb4162ebe9a54c5014f67b20ba124ddd307)
+++ uspace/srv/net/dhcp/dhcp.h	(revision 053fc2bcb6fbea6b3e6edf10ca784c77402816d4)
@@ -43,4 +43,5 @@
 extern int dhcpsrv_link_add(service_id_t);
 extern int dhcpsrv_link_remove(service_id_t);
+extern int dhcpsrv_discover(service_id_t);
 
 #endif
Index: uspace/srv/net/dhcp/main.c
===================================================================
--- uspace/srv/net/dhcp/main.c	(revision d7dadcb4162ebe9a54c5014f67b20ba124ddd307)
+++ uspace/srv/net/dhcp/main.c	(revision 053fc2bcb6fbea6b3e6edf10ca784c77402816d4)
@@ -109,4 +109,17 @@
 }
 
+static void dhcp_discover_srv(ipc_callid_t callid, ipc_call_t *call)
+{
+	sysarg_t link_id;
+	int rc;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "dhcp_discover_srv()");
+
+	link_id = IPC_GET_ARG1(*call);
+
+	rc = dhcpsrv_discover(link_id);
+	async_answer_0(callid, rc);
+}
+
 static void dhcp_client_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
@@ -133,4 +146,7 @@
 		case DHCP_LINK_REMOVE:
 			dhcp_link_remove_srv(callid, &call);
+			break;
+		case DHCP_DISCOVER:
+			dhcp_discover_srv(callid, &call);
 			break;
 		default:
