Index: uspace/srv/net/il/arp/arp.c
===================================================================
--- uspace/srv/net/il/arp/arp.c	(revision 7837101e9ef7c5e24437373b9c81b9a15116b460)
+++ uspace/srv/net/il/arp/arp.c	(revision 1bfd3d3b2991b8f2df4cff87d9723059528b9bd1)
@@ -72,7 +72,4 @@
 #define NAME  "arp"
 
-/** Number of microseconds to wait for an ARP reply. */
-#define ARP_TRANS_WAIT	1000000
-
 /** ARP global data. */
 arp_globals_t arp_globals;
@@ -80,27 +77,5 @@
 DEVICE_MAP_IMPLEMENT(arp_cache, arp_device_t);
 INT_MAP_IMPLEMENT(arp_protos, arp_proto_t);
-GENERIC_CHAR_MAP_IMPLEMENT(arp_addr, arp_trans_t);
-
-static void arp_clear_trans(arp_trans_t *trans)
-{
-	if (trans->hw_addr) {
-		free(trans->hw_addr);
-		trans->hw_addr = NULL;
-	}
-	fibril_condvar_broadcast(&trans->cv);
-}
-
-static void arp_clear_addr(arp_addr_t *addresses)
-{
-	int count;
-	arp_trans_t *trans;
-
-	for (count = arp_addr_count(addresses) - 1; count >= 0; count--) {
-		trans = arp_addr_items_get_index(&addresses->values, count);
-		if (trans)
-			arp_clear_trans(trans);
-	}
-}
-
+GENERIC_CHAR_MAP_IMPLEMENT(arp_addr, measured_string_t);
 
 /** Clears the device specific data.
@@ -121,5 +96,4 @@
 			if (proto->addr_data)
 				free(proto->addr_data);
-			arp_clear_addr(&proto->addresses);
 			arp_addr_destroy(&proto->addresses);
 		}
@@ -133,5 +107,5 @@
 	arp_device_t *device;
 
-	fibril_mutex_lock(&arp_globals.lock);
+	fibril_rwlock_write_lock(&arp_globals.lock);
 	for (count = arp_cache_count(&arp_globals.cache) - 1; count >= 0;
 	    count--) {
@@ -146,5 +120,5 @@
 	}
 	arp_cache_clear(&arp_globals.cache);
-	fibril_mutex_unlock(&arp_globals.lock);
+	fibril_rwlock_write_unlock(&arp_globals.lock);
 	printf("Cache cleaned\n");
 	return EOK;
@@ -156,22 +130,18 @@
 	arp_device_t *device;
 	arp_proto_t *proto;
-	arp_trans_t *trans;
-
-	fibril_mutex_lock(&arp_globals.lock);
+
+	fibril_rwlock_write_lock(&arp_globals.lock);
 	device = arp_cache_find(&arp_globals.cache, device_id);
 	if (!device) {
-		fibril_mutex_unlock(&arp_globals.lock);
+		fibril_rwlock_write_unlock(&arp_globals.lock);
 		return ENOENT;
 	}
 	proto = arp_protos_find(&device->protos, protocol);
 	if (!proto) {
-		fibril_mutex_unlock(&arp_globals.lock);
+		fibril_rwlock_write_unlock(&arp_globals.lock);
 		return ENOENT;
 	}
-	trans = arp_addr_find(&proto->addresses, address->value, address->length);
-	if (trans)
-		arp_clear_trans(trans);
 	arp_addr_exclude(&proto->addresses, address->value, address->length);
-	fibril_mutex_unlock(&arp_globals.lock);
+	fibril_rwlock_write_unlock(&arp_globals.lock);
 	return EOK;
 }
@@ -182,13 +152,13 @@
 	arp_device_t *device;
 
-	fibril_mutex_lock(&arp_globals.lock);
+	fibril_rwlock_write_lock(&arp_globals.lock);
 	device = arp_cache_find(&arp_globals.cache, device_id);
 	if (!device) {
-		fibril_mutex_unlock(&arp_globals.lock);
+		fibril_rwlock_write_unlock(&arp_globals.lock);
 		return ENOENT;
 	}
 	arp_clear_device(device);
 	printf("Device %d cleared\n", device_id);
-	fibril_mutex_unlock(&arp_globals.lock);
+	fibril_rwlock_write_unlock(&arp_globals.lock);
 	return EOK;
 }
@@ -251,5 +221,5 @@
 	int rc;
 
-	fibril_mutex_lock(&arp_globals.lock);
+	fibril_rwlock_write_lock(&arp_globals.lock);
 
 	/* An existing device? */
@@ -259,5 +229,5 @@
 		if (device->service != service) {
 			printf("Device %d already exists\n", device->device_id);
-			fibril_mutex_unlock(&arp_globals.lock);
+			fibril_rwlock_write_unlock(&arp_globals.lock);
 			return EEXIST;
 		}
@@ -271,5 +241,5 @@
 			rc = arp_proto_create(&proto, protocol, address);
 			if (rc != EOK) {
-				fibril_mutex_unlock(&arp_globals.lock);
+				fibril_rwlock_write_unlock(&arp_globals.lock);
 				return rc;
 			}
@@ -277,5 +247,5 @@
 			    proto);
 			if (index < 0) {
-				fibril_mutex_unlock(&arp_globals.lock);
+				fibril_rwlock_write_unlock(&arp_globals.lock);
 				free(proto);
 				return index;
@@ -292,5 +262,5 @@
 		device = (arp_device_t *) malloc(sizeof(arp_device_t));
 		if (!device) {
-			fibril_mutex_unlock(&arp_globals.lock);
+			fibril_rwlock_write_unlock(&arp_globals.lock);
 			return ENOMEM;
 		}
@@ -299,5 +269,5 @@
 		rc = arp_protos_initialize(&device->protos);
 		if (rc != EOK) {
-			fibril_mutex_unlock(&arp_globals.lock);
+			fibril_rwlock_write_unlock(&arp_globals.lock);
 			free(device);
 			return rc;
@@ -305,5 +275,5 @@
 		rc = arp_proto_create(&proto, protocol, address);
 		if (rc != EOK) {
-			fibril_mutex_unlock(&arp_globals.lock);
+			fibril_rwlock_write_unlock(&arp_globals.lock);
 			free(device);
 			return rc;
@@ -311,5 +281,5 @@
 		index = arp_protos_add(&device->protos, proto->service, proto);
 		if (index < 0) {
-			fibril_mutex_unlock(&arp_globals.lock);
+			fibril_rwlock_write_unlock(&arp_globals.lock);
 			arp_protos_destroy(&device->protos);
 			free(device);
@@ -320,8 +290,8 @@
 		/* Bind the new one */
 		device->phone = nil_bind_service(device->service,
-		    (sysarg_t) device->device_id, SERVICE_ARP,
+		    (ipcarg_t) device->device_id, SERVICE_ARP,
 		    arp_globals.client_connection);
 		if (device->phone < 0) {
-			fibril_mutex_unlock(&arp_globals.lock);
+			fibril_rwlock_write_unlock(&arp_globals.lock);
 			arp_protos_destroy(&device->protos);
 			free(device);
@@ -333,5 +303,5 @@
 		    &device->packet_dimension);
 		if (rc != EOK) {
-			fibril_mutex_unlock(&arp_globals.lock);
+			fibril_rwlock_write_unlock(&arp_globals.lock);
 			arp_protos_destroy(&device->protos);
 			free(device);
@@ -343,5 +313,5 @@
 		    &device->addr_data);
 		if (rc != EOK) {
-			fibril_mutex_unlock(&arp_globals.lock);
+			fibril_rwlock_write_unlock(&arp_globals.lock);
 			arp_protos_destroy(&device->protos);
 			free(device);
@@ -353,5 +323,5 @@
 		    &device->broadcast_addr, &device->broadcast_data);
 		if (rc != EOK) {
-			fibril_mutex_unlock(&arp_globals.lock);
+			fibril_rwlock_write_unlock(&arp_globals.lock);
 			free(device->addr);
 			free(device->addr_data);
@@ -364,5 +334,5 @@
 		    device);
 		if (rc != EOK) {
-			fibril_mutex_unlock(&arp_globals.lock);
+			fibril_rwlock_write_unlock(&arp_globals.lock);
 			free(device->addr);
 			free(device->addr_data);
@@ -377,5 +347,5 @@
 		    device->service, protocol);
 	}
-	fibril_mutex_unlock(&arp_globals.lock);
+	fibril_rwlock_write_unlock(&arp_globals.lock);
 	
 	return EOK;
@@ -393,9 +363,9 @@
 	int rc;
 
-	fibril_mutex_initialize(&arp_globals.lock);
-	fibril_mutex_lock(&arp_globals.lock);
+	fibril_rwlock_initialize(&arp_globals.lock);
+	fibril_rwlock_write_lock(&arp_globals.lock);
 	arp_globals.client_connection = client_connection;
 	rc = arp_cache_initialize(&arp_globals.cache);
-	fibril_mutex_unlock(&arp_globals.lock);
+	fibril_rwlock_write_unlock(&arp_globals.lock);
 	
 	return rc;
@@ -413,13 +383,13 @@
 	arp_device_t *device;
 
-	fibril_mutex_lock(&arp_globals.lock);
+	fibril_rwlock_write_lock(&arp_globals.lock);
 	device = arp_cache_find(&arp_globals.cache, device_id);
 	if (!device) {
-		fibril_mutex_unlock(&arp_globals.lock);
+		fibril_rwlock_write_unlock(&arp_globals.lock);
 		return ENOENT;
 	}
 	device->packet_dimension.content = mtu;
-	fibril_mutex_unlock(&arp_globals.lock);
-	printf("arp - device %d changed mtu to %zu\n\n", device_id, mtu);
+	fibril_rwlock_write_unlock(&arp_globals.lock);
+	printf("arp - device %d changed mtu to %d\n\n", device_id, mtu);
 	return EOK;
 }
@@ -445,5 +415,5 @@
  * @return		ENOMEM if there is not enough memory left.
  */
-static int arp_receive_message(device_id_t device_id, packet_t *packet)
+static int arp_receive_message(device_id_t device_id, packet_t packet)
 {
 	size_t length;
@@ -451,5 +421,5 @@
 	arp_device_t *device;
 	arp_proto_t *proto;
-	arp_trans_t *trans;
+	measured_string_t *hw_source;
 	uint8_t *src_hw;
 	uint8_t *src_proto;
@@ -482,39 +452,34 @@
 	des_hw = src_proto + header->protocol_length;
 	des_proto = des_hw + header->hardware_length;
-	trans = arp_addr_find(&proto->addresses, (char *) src_proto,
-	    header->protocol_length);
+	hw_source = arp_addr_find(&proto->addresses, (char *) src_proto,
+	    CONVERT_SIZE(uint8_t, char, header->protocol_length));
 	/* Exists? */
-	if (trans && trans->hw_addr) {
-		if (trans->hw_addr->length != header->hardware_length)
+	if (hw_source) {
+		if (hw_source->length != CONVERT_SIZE(uint8_t, char,
+		    header->hardware_length)) {
 			return EINVAL;
-		memcpy(trans->hw_addr->value, src_hw, trans->hw_addr->length);
+		}
+		memcpy(hw_source->value, src_hw, hw_source->length);
 	}
 	/* Is my protocol address? */
-	if (proto->addr->length != header->protocol_length)
+	if (proto->addr->length != CONVERT_SIZE(uint8_t, char,
+	    header->protocol_length)) {
 		return EINVAL;
+	}
 	if (!str_lcmp(proto->addr->value, (char *) des_proto,
 	    proto->addr->length)) {
 		/* Not already updated? */
-		if (!trans) {
-			trans = (arp_trans_t *) malloc(sizeof(arp_trans_t));
-			if (!trans)
+		if (!hw_source) {
+			hw_source = measured_string_create_bulk((char *) src_hw,
+			    CONVERT_SIZE(uint8_t, char,
+			    header->hardware_length));
+			if (!hw_source)
 				return ENOMEM;
-			trans->hw_addr = NULL;
-			fibril_condvar_initialize(&trans->cv);
+
 			rc = arp_addr_add(&proto->addresses, (char *) src_proto,
-			    header->protocol_length, trans);
-			if (rc != EOK) {
-				/* The generic char map has already freed trans! */
+			    CONVERT_SIZE(uint8_t, char,
+			    header->protocol_length), hw_source);
+			if (rc != EOK)
 				return rc;
-			}
-		}
-		if (!trans->hw_addr) {
-			trans->hw_addr = measured_string_create_bulk(
-			    (char *) src_hw, header->hardware_length);
-			if (!trans->hw_addr)
-				return ENOMEM;
-
-			/* Notify the fibrils that wait for the translation. */
-			fibril_condvar_broadcast(&trans->cv);
 		}
 		if (ntohs(header->operation) == ARPOP_REQUEST) {
@@ -525,5 +490,5 @@
 			memcpy(src_hw, device->addr->value,
 			    device->packet_dimension.addr_len);
-			memcpy(des_hw, trans->hw_addr->value,
+			memcpy(des_hw, hw_source->value,
 			    header->hardware_length);
 			
@@ -551,56 +516,42 @@
  * @param[in] protocol	The protocol service.
  * @param[in] target	The target protocol address.
- * @param[out] translation Where the hardware address of the target is stored.
- * @return		EOK on success.
- * @return		EAGAIN if the caller should try again.
- * @return		Other error codes in case of error.
- */
-static int
+ * @return		The hardware address of the target.
+ * @return		NULL if the target parameter is NULL.
+ * @return		NULL if the device is not found.
+ * @return		NULL if the device packet is too small to send a
+ *			request.
+ * @return		NULL if the hardware address is not found in the cache.
+ */
+static measured_string_t *
 arp_translate_message(device_id_t device_id, services_t protocol,
-    measured_string_t *target, measured_string_t **translation)
+    measured_string_t *target)
 {
 	arp_device_t *device;
 	arp_proto_t *proto;
-	arp_trans_t *trans;
+	measured_string_t *addr;
 	size_t length;
-	packet_t *packet;
+	packet_t packet;
 	arp_header_t *header;
-	bool retry = false;
-	int rc;
-
-restart:
-	if (!target || !translation)
-		return EBADMEM;
+
+	if (!target)
+		return NULL;
 
 	device = arp_cache_find(&arp_globals.cache, device_id);
 	if (!device)
-		return ENOENT;
+		return NULL;
 
 	proto = arp_protos_find(&device->protos, protocol);
 	if (!proto || (proto->addr->length != target->length))
-		return ENOENT;
-
-	trans = arp_addr_find(&proto->addresses, target->value, target->length);
-	if (trans) {
-		if (trans->hw_addr) {
-			*translation = trans->hw_addr;
-			return EOK;
-		}
-		if (retry)
-			return EAGAIN;
-		rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock,
-		    ARP_TRANS_WAIT);
-		if (rc == ETIMEOUT)
-			return ENOENT;
-		retry = true;
-		goto restart;
-	}
-	if (retry)
-		return EAGAIN;
+		return NULL;
+
+	addr = arp_addr_find(&proto->addresses, target->value, target->length);
+	if (addr)
+		return addr;
 
 	/* ARP packet content size = header + (address + translation) * 2 */
-	length = 8 + 2 * (proto->addr->length + device->addr->length);
+	length = 8 + 2 * (CONVERT_SIZE(char, uint8_t, proto->addr->length) +
+	    CONVERT_SIZE(char, uint8_t, device->addr->length));
 	if (length > device->packet_dimension.content)
-		return ELIMIT;
+		return NULL;
 
 	packet = packet_get_4_remote(arp_globals.net_phone,
@@ -608,10 +559,10 @@
 	    length, device->packet_dimension.suffix);
 	if (!packet)
-		return ENOMEM;
+		return NULL;
 
 	header = (arp_header_t *) packet_suffix(packet, length);
 	if (!header) {
 		pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
-		return ENOMEM;
+		return NULL;
 	}
 
@@ -632,31 +583,13 @@
 	memcpy(((uint8_t *) header) + length, target->value, target->length);
 
-	rc = packet_set_addr(packet, (uint8_t *) device->addr->value,
-	    (uint8_t *) device->broadcast_addr->value, device->addr->length);
-	if (rc != EOK) {
+	if (packet_set_addr(packet, (uint8_t *) device->addr->value,
+	    (uint8_t *) device->broadcast_addr->value,
+	    CONVERT_SIZE(char, uint8_t, device->addr->length)) != EOK) {
 		pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
-		return rc;
+		return NULL;
 	}
 
 	nil_send_msg(device->phone, device_id, packet, SERVICE_ARP);
-
-	trans = (arp_trans_t *) malloc(sizeof(arp_trans_t));
-	if (!trans)
-		return ENOMEM;
-	trans->hw_addr = NULL;
-	fibril_condvar_initialize(&trans->cv);
-	rc = arp_addr_add(&proto->addresses, target->value, target->length,
-	    trans);
-	if (rc != EOK) {
-		/* The generic char map has already freed trans! */
-		return rc;
-	}
-	
-	rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock,
-	    ARP_TRANS_WAIT);
-	if (rc == ETIMEOUT)
-		return ENOENT;
-	retry = true;
-	goto restart;
+	return NULL;
 }
 
@@ -682,10 +615,10 @@
 	measured_string_t *translation;
 	char *data;
-	packet_t *packet;
-	packet_t *next;
+	packet_t packet;
+	packet_t next;
 	int rc;
 	
 	*answer_count = 0;
-	switch (IPC_GET_IMETHOD(*call)) {
+	switch (IPC_GET_METHOD(*call)) {
 	case IPC_M_PHONE_HUNGUP:
 		return EOK;
@@ -709,19 +642,15 @@
 			return rc;
 		
-		fibril_mutex_lock(&arp_globals.lock);
-		rc = arp_translate_message(IPC_GET_DEVICE(call),
-		    IPC_GET_SERVICE(call), address, &translation);
+		fibril_rwlock_read_lock(&arp_globals.lock);
+		translation = arp_translate_message(IPC_GET_DEVICE(call),
+		    IPC_GET_SERVICE(call), address);
 		free(address);
 		free(data);
-		if (rc != EOK) {
-			fibril_mutex_unlock(&arp_globals.lock);
-			return rc;
-		}
 		if (!translation) {
-			fibril_mutex_unlock(&arp_globals.lock);
+			fibril_rwlock_read_unlock(&arp_globals.lock);
 			return ENOENT;
 		}
 		rc = measured_strings_reply(translation, 1);
-		fibril_mutex_unlock(&arp_globals.lock);
+		fibril_rwlock_read_unlock(&arp_globals.lock);
 		return rc;
 
@@ -753,5 +682,5 @@
 			return rc;
 		
-		fibril_mutex_lock(&arp_globals.lock);
+		fibril_rwlock_read_lock(&arp_globals.lock);
 		do {
 			next = pq_detach(packet);
@@ -763,5 +692,5 @@
 			packet = next;
 		} while (packet);
-		fibril_mutex_unlock(&arp_globals.lock);
+		fibril_rwlock_read_unlock(&arp_globals.lock);
 		
 		return EOK;
@@ -807,5 +736,5 @@
 		 * result.
 		 */
-		if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) ||
+		if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) ||
 		    (res == EHANGUP))
 			return;
