Index: uspace/lib/net/ieee80211/ieee80211.c
===================================================================
--- uspace/lib/net/ieee80211/ieee80211.c	(revision 56c0930934f3eb8763355d11f38eb65b6896d53e)
+++ uspace/lib/net/ieee80211/ieee80211.c	(revision 9e5a51c3f68bce51a13b957d870bf35d97aa6fad)
@@ -42,4 +42,23 @@
 #include <ieee80211.h>
 
+/** Broadcast MAC address used to spread probe request through channel. */
+static const uint8_t ieee80211_broadcast_mac_addr[] = {
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+/** IEEE 802.11 b/g supported data rates in units of 500 kb/s. */
+static const uint8_t ieee80211bg_data_rates[] = {
+	2, 4, 11, 12, 18, 22, 24, 36
+};
+
+/** IEEE 802.11 b/g extended supported data rates in units of 500 kb/s.
+ * 
+ *  These are defined separately, because probe request message can
+ *  only handle up to 8 data rates in supported rates IE. 
+ */
+static const uint8_t ieee80211bg_ext_data_rates[] = {
+	48, 72, 96, 108
+};
+
 /** Network interface options for IEEE 802.11 driver. */
 static nic_iface_t ieee80211_nic_iface;
@@ -47,11 +66,4 @@
 /** Basic driver operations for IEEE 802.11 NIC driver. */
 static driver_ops_t ieee80211_nic_driver_ops;
-
-bool ieee80211_is_data_frame(ieee80211_header_t *header)
-{
-	return (header->frame_ctrl & 
-		host2uint16_t_le(IEEE80211_FRAME_CTRL_FRAME_TYPE)) ==
-		host2uint16_t_le(IEEE80211_FRAME_CTRL_DATA_FRAME);
-}
 
 static int ieee80211_open(ddf_fun_t *fun)
@@ -70,9 +82,7 @@
 		return rc;
 	
-	/*
 	rc = ieee80211_dev->ops->scan(ieee80211_dev);
 	if(rc != EOK)
 		return rc;
-	 */
 	
 	return EOK;
@@ -93,4 +103,8 @@
 	/* IEEE802.11 TX handler must be implemented. */
 	if(!ieee80211_ops->tx_handler)
+		return EINVAL;
+	
+	/* IEEE802.11 set frequency handler must be implemented. */
+	if(!ieee80211_ops->set_freq)
 		return EINVAL;
 	
@@ -119,4 +133,7 @@
 	ieee80211_dev->current_op_mode = IEEE80211_OPMODE_STATION;
 	
+	memcpy(ieee80211_dev->bssid_mask, ieee80211_broadcast_mac_addr, 
+		ETH_ADDR);
+	
 	/* Bind NIC to device */
 	nic_t *nic = nic_create_and_bind(ddf_dev);
@@ -175,4 +192,106 @@
 }
 
+static uint8_t ieee80211_freq_to_channel(uint16_t freq)
+{
+	return (freq - IEEE80211_FIRST_FREQ) / IEEE80211_CHANNEL_GAP + 1;
+}
+
+int ieee80211_probe_request(ieee80211_dev_t *ieee80211_dev)
+{
+	nic_t *nic = nic_get_from_ddf_dev(ieee80211_dev->ddf_dev);
+	nic_address_t nic_address;
+	nic_query_address(nic, &nic_address);
+	
+	size_t data_rates_size = 
+		sizeof(ieee80211bg_data_rates) / 
+		sizeof(ieee80211bg_data_rates[0]);
+	
+	size_t ext_data_rates_size = 
+		sizeof(ieee80211bg_ext_data_rates) / 
+		sizeof(ieee80211bg_ext_data_rates[0]);
+	
+	/* 3 headers - (rates, ext rates, current channel) and their data
+	 * lengths + pad. 
+	 */
+	size_t payload_size = 
+		sizeof(ieee80211_ie_header_t) * 3 +
+		data_rates_size + ext_data_rates_size + sizeof(uint8_t) + 2;
+	
+	size_t buffer_size = sizeof(ieee80211_mgmt_header_t) + payload_size;
+	void *buffer = malloc(buffer_size);
+	memset(buffer, 0, buffer_size);
+	
+	ieee80211_mgmt_header_t *mgmt_header = 
+		(ieee80211_mgmt_header_t *) buffer;
+	
+	mgmt_header->frame_ctrl = host2uint16_t_le(
+		IEEE80211_MGMT_FRAME | 
+		IEEE80211_MGMT_PROBE_REQ_FRAME
+		);
+	memcpy(mgmt_header->dest_addr, ieee80211_broadcast_mac_addr, ETH_ADDR);
+	memcpy(mgmt_header->src_addr, nic_address.address, ETH_ADDR);
+	memcpy(mgmt_header->bssid, ieee80211_broadcast_mac_addr, ETH_ADDR);
+	
+	/* Jump to payload -> header + padding. */
+	uint8_t *it = buffer + sizeof(ieee80211_mgmt_header_t) + 2;
+	
+	*it++ = IEEE80211_RATES_IE;
+	*it++ = data_rates_size;
+	memcpy(it, ieee80211bg_data_rates, data_rates_size);
+	it += data_rates_size;
+	
+	*it++ = IEEE80211_EXT_RATES_IE;
+	*it++ = ext_data_rates_size;
+	memcpy(it, ieee80211bg_ext_data_rates, ext_data_rates_size);
+	it += ext_data_rates_size;
+	
+	*it++ = IEEE80211_CHANNEL_IE;
+	*it++ = 1;
+	*it = ieee80211_freq_to_channel(ieee80211_dev->current_freq);
+	
+	ieee80211_dev->ops->tx_handler(ieee80211_dev, buffer, buffer_size);
+	
+	free(buffer);
+	
+	return EOK;
+}
+
+int ieee80211_probe_auth(ieee80211_dev_t *ieee80211_dev)
+{
+	uint8_t test_bssid[] = {0x14, 0xF6, 0x5A, 0xAF, 0x5E, 0xB7};
+	
+	nic_t *nic = nic_get_from_ddf_dev(ieee80211_dev->ddf_dev);
+	nic_address_t nic_address;
+	nic_query_address(nic, &nic_address);
+	
+	size_t buffer_size = sizeof(ieee80211_mgmt_header_t) + 
+		sizeof(ieee80211_auth_body_t);
+	void *buffer = malloc(buffer_size);
+	memset(buffer, 0, buffer_size);
+	
+	ieee80211_mgmt_header_t *mgmt_header = 
+		(ieee80211_mgmt_header_t *) buffer;
+	
+	mgmt_header->frame_ctrl = host2uint16_t_le(
+		IEEE80211_MGMT_FRAME | 
+		IEEE80211_MGMT_AUTH_FRAME
+		);
+	memcpy(mgmt_header->dest_addr, test_bssid, ETH_ADDR);
+	memcpy(mgmt_header->src_addr, nic_address.address, ETH_ADDR);
+	memcpy(mgmt_header->bssid, test_bssid, ETH_ADDR);
+	
+	ieee80211_auth_body_t *auth_body =
+		(ieee80211_auth_body_t *) 
+		(buffer + sizeof(ieee80211_mgmt_header_t));
+	auth_body->auth_alg = host2uint16_t_le(0);
+	auth_body->auth_trans_no = host2uint16_t_le(0);
+	
+	ieee80211_dev->ops->tx_handler(ieee80211_dev, buffer, buffer_size);
+	
+	free(buffer);
+	
+	return EOK;
+}
+
 /** @}
  */
Index: uspace/lib/net/ieee80211/ieee80211_impl.c
===================================================================
--- uspace/lib/net/ieee80211/ieee80211_impl.c	(revision 56c0930934f3eb8763355d11f38eb65b6896d53e)
+++ uspace/lib/net/ieee80211/ieee80211_impl.c	(revision 9e5a51c3f68bce51a13b957d870bf35d97aa6fad)
@@ -40,25 +40,4 @@
 #include <ieee80211_impl.h>
 
-static int ieee80211_freq_to_channel(uint16_t freq)
-{
-	return (freq - IEEE80211_FIRST_FREQ) / IEEE80211_CHANNEL_GAP + 1;
-}
-
-static int ieee80211_probe_request(ieee80211_dev_t *ieee80211_dev)
-{
-	size_t buffer_size = sizeof(ieee80211_header_t);
-	void *buffer = malloc(buffer_size);
-	
-	/* TODO */
-	
-	ieee80211_freq_to_channel(ieee80211_dev->current_freq);
-	
-	ieee80211_dev->ops->tx_handler(ieee80211_dev, buffer, buffer_size);
-	
-	free(buffer);
-	
-	return EOK;
-}
-
 /**
  * Default implementation of IEEE802.11 scan function.
@@ -70,8 +49,19 @@
 int ieee80211_scan_impl(ieee80211_dev_t *ieee80211_dev)
 {
-	/* TODO */
-	int rc = ieee80211_probe_request(ieee80211_dev);
-	if(rc != EOK)
-		return rc;
+	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);
+		
+		/* Wait for probe responses. */
+		usleep(100000);
+	}
+	
+	ieee80211_dev->ops->set_freq(ieee80211_dev, orig_freq);
+	
+	/* TODO: Collect results. */
 	
 	return EOK;
Index: uspace/lib/net/include/ieee80211.h
===================================================================
--- uspace/lib/net/include/ieee80211.h	(revision 56c0930934f3eb8763355d11f38eb65b6896d53e)
+++ uspace/lib/net/include/ieee80211.h	(revision 9e5a51c3f68bce51a13b957d870bf35d97aa6fad)
@@ -52,7 +52,4 @@
 #define IEEE80211_CHANNEL_GAP 5
 
-#define IEEE80211_FRAME_CTRL_FRAME_TYPE 0x000C
-#define IEEE80211_FRAME_CTRL_DATA_FRAME 0x0008
-
 struct ieee80211_dev;
 
@@ -65,4 +62,34 @@
 } ieee80211_operating_mode_t;
 
+/** IEEE 802.11 frame types. */
+typedef enum {
+	IEEE80211_MGMT_FRAME = 0x0,
+	IEEE80211_CTRL_FRAME = 0x4,
+	IEEE80211_DATA_FRAME = 0x8,
+	IEEE80211_EXT_FRAME = 0xC
+} ieee80211_frame_type_t;
+
+/** IEEE 802.11 frame subtypes. */
+typedef enum {
+	IEEE80211_MGMT_ASSOC_REQ_FRAME = 0x00,
+	IEEE80211_MGMT_ASSOC_RESP_FRAME = 0x10,
+	IEEE80211_MGMT_REASSOC_REQ_FRAME = 0x20,
+	IEEE80211_MGMT_REASSOC_RESP_FRAME = 0x30,
+	IEEE80211_MGMT_PROBE_REQ_FRAME = 0x40,
+	IEEE80211_MGMT_PROBE_RESP_FRAME = 0x50,
+	IEEE80211_MGMT_BEACON_FRAME = 0x80,
+	IEEE80211_MGMT_DIASSOC_FRAME = 0xA0,
+	IEEE80211_MGMT_AUTH_FRAME = 0xB0,
+	IEEE80211_MGMT_DEAUTH_FRAME = 0xC0,
+} ieee80211_frame_subtype_t;
+
+/** IEEE 802.11 information element types. */
+typedef enum {
+	IEEE80211_SSID_IE = 0,		/**< Target SSID. */
+	IEEE80211_RATES_IE = 1,		/**< Supported data rates. */
+	IEEE80211_CHANNEL_IE = 3,	/**< Current channel number. */
+	IEEE80211_EXT_RATES_IE = 50	/**< Extended data rates. */
+} ieee80211_ie_type_t;
+
 /** IEEE 802.11 functions. */
 typedef struct {
@@ -70,4 +97,5 @@
 	int (*scan)(struct ieee80211_dev *);
 	int (*tx_handler)(struct ieee80211_dev *, void *, size_t);
+	int (*set_freq)(struct ieee80211_dev *, uint16_t);
 } ieee80211_ops_t;
 
@@ -89,4 +117,7 @@
 	ieee80211_operating_mode_t current_op_mode;
 	
+	/** BSSIDs we listen to. */
+	uint8_t bssid_mask[ETH_ADDR];
+	
 	/* TODO: Probably to be removed later - nic.open function is now 
 	 * executed multiple times, have to find out reason and fix it. 
@@ -96,5 +127,15 @@
 } ieee80211_dev_t;
 
-/** IEEE 802.11 header structure. */
+/** IEEE 802.11 management header structure. */
+typedef struct {
+	uint16_t frame_ctrl;		/**< Little Endian value! */
+	uint16_t duration_id;		/**< Little Endian value! */
+	uint8_t dest_addr[ETH_ADDR];
+	uint8_t src_addr[ETH_ADDR];
+	uint8_t bssid[ETH_ADDR];
+	uint16_t seq_ctrl;		/**< Little Endian value! */
+} __attribute__((packed)) __attribute__ ((aligned(2))) ieee80211_mgmt_header_t;
+
+/** IEEE 802.11 data header structure. */
 typedef struct {
 	uint16_t frame_ctrl;		/**< Little Endian value! */
@@ -105,11 +146,31 @@
 	uint16_t seq_ctrl;		/**< Little Endian value! */
 	uint8_t address4[ETH_ADDR];
-} __attribute__((packed)) __attribute__ ((aligned(2))) ieee80211_header_t;
+	uint16_t qos_ctrl;		/**< Little Endian value! */
+} __attribute__((packed)) __attribute__ ((aligned(2))) ieee80211_data_header_t;
 
-extern bool ieee80211_is_data_frame(ieee80211_header_t *header);
+/** IEEE 802.11 information element header. */
+typedef struct {
+	uint8_t element_id;
+	uint8_t length;
+} __attribute__((packed)) __attribute__ ((aligned(2))) ieee80211_ie_header_t;
+
+/** IEEE 802.11 authentication frame body. */
+typedef struct {
+	uint16_t auth_alg;		/**< Little Endian value! */
+	uint16_t auth_trans_no;		/**< Little Endian value! */
+	uint16_t status;		/**< Little Endian value! */
+} __attribute__((packed)) __attribute__ ((aligned(2))) ieee80211_auth_body_t;
+
+typedef struct {
+	uint8_t bssid[ETH_ADDR];
+	uint16_t auth_alg;
+} __attribute__((packed)) __attribute__ ((aligned(2))) ieee80211_auth_data_t;
+
 extern int ieee80211_device_init(ieee80211_dev_t *ieee80211_dev, 
 	void *driver_data, ddf_dev_t *ddf_dev);
 extern int ieee80211_init(ieee80211_dev_t *ieee80211_dev, 
 	ieee80211_ops_t *ieee80211_ops);
+extern int ieee80211_probe_request(ieee80211_dev_t *ieee80211_dev);
+extern int ieee80211_probe_auth(ieee80211_dev_t *ieee80211_dev);
 
 #endif /* LIBNET_IEEE80211_H */
