Index: uspace/srv/net/il/arp/arp.c
===================================================================
--- uspace/srv/net/il/arp/arp.c	(revision 46d4d9f449e7933280b1877c70448602ec0ab0ae)
+++ uspace/srv/net/il/arp/arp.c	(revision 3bb5735550f24178daa84ad99667c7ac5d6210f2)
@@ -516,14 +516,12 @@
  * @param[in] protocol	The protocol service.
  * @param[in] target	The target protocol address.
- * @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 *
+ * @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
 arp_translate_message(device_id_t device_id, services_t protocol,
-    measured_string_t *target)
+    measured_string_t *target, measured_string_t **translation)
 {
 	arp_device_t *device;
@@ -533,19 +531,22 @@
 	packet_t *packet;
 	arp_header_t *header;
-
-	if (!target)
-		return NULL;
+	int rc;
+
+	if (!target || !translation)
+		return EBADMEM;
 
 	device = arp_cache_find(&arp_globals.cache, device_id);
 	if (!device)
-		return NULL;
+		return ENOENT;
 
 	proto = arp_protos_find(&device->protos, protocol);
 	if (!proto || (proto->addr->length != target->length))
-		return NULL;
+		return ENOENT;
 
 	addr = arp_addr_find(&proto->addresses, target->value, target->length);
-	if (addr)
-		return addr;
+	if (addr) {
+		*translation = addr;
+		return EOK;
+	}
 
 	/* ARP packet content size = header + (address + translation) * 2 */
@@ -553,5 +554,5 @@
 	    CONVERT_SIZE(char, uint8_t, device->addr->length));
 	if (length > device->packet_dimension.content)
-		return NULL;
+		return ELIMIT;
 
 	packet = packet_get_4_remote(arp_globals.net_phone,
@@ -559,10 +560,10 @@
 	    length, device->packet_dimension.suffix);
 	if (!packet)
-		return NULL;
+		return ENOMEM;
 
 	header = (arp_header_t *) packet_suffix(packet, length);
 	if (!header) {
 		pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
-		return NULL;
+		return ENOMEM;
 	}
 
@@ -583,13 +584,14 @@
 	memcpy(((uint8_t *) header) + length, target->value, target->length);
 
-	if (packet_set_addr(packet, (uint8_t *) device->addr->value,
+	rc = packet_set_addr(packet, (uint8_t *) device->addr->value,
 	    (uint8_t *) device->broadcast_addr->value,
-	    CONVERT_SIZE(char, uint8_t, device->addr->length)) != EOK) {
+	    CONVERT_SIZE(char, uint8_t, device->addr->length));
+	if (rc != EOK) {
 		pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
-		return NULL;
+		return rc;
 	}
 
 	nil_send_msg(device->phone, device_id, packet, SERVICE_ARP);
-	return NULL;
+	return EAGAIN;
 }
 
@@ -643,8 +645,12 @@
 		
 		fibril_rwlock_read_lock(&arp_globals.lock);
-		translation = arp_translate_message(IPC_GET_DEVICE(call),
-		    IPC_GET_SERVICE(call), address);
+		rc = arp_translate_message(IPC_GET_DEVICE(call),
+		    IPC_GET_SERVICE(call), address, &translation);
 		free(address);
 		free(data);
+		if (rc != EOK) {
+			fibril_rwlock_read_unlock(&arp_globals.lock);
+			return rc;
+		}
 		if (!translation) {
 			fibril_rwlock_read_unlock(&arp_globals.lock);
Index: uspace/srv/net/il/ip/ip.c
===================================================================
--- uspace/srv/net/il/ip/ip.c	(revision 46d4d9f449e7933280b1877c70448602ec0ab0ae)
+++ uspace/srv/net/il/ip/ip.c	(revision 3bb5735550f24178daa84ad99667c7ac5d6210f2)
@@ -115,4 +115,7 @@
 /** The IP localhost address. */
 #define IPV4_LOCALHOST_ADDRESS	htonl((127 << 24) + 1)
+
+/** How many times can arp_translate_req respond EAGAIN before IP gives up */
+#define ARP_EAGAIN_MAX_COUNT 10
 
 /** IP global data. */
@@ -1008,6 +1011,12 @@
 		destination.length = CONVERT_SIZE(dest.s_addr, char, 1);
 
-		rc = arp_translate_req(netif->arp->phone, netif->device_id,
-		    SERVICE_IP, &destination, &translation, &data);
+		/** Try calling translate several times, then give up */
+		int count = 0;
+		do {
+			rc = arp_translate_req(netif->arp->phone,
+			    netif->device_id, SERVICE_IP, &destination,
+			    &translation, &data);
+			count++;
+		} while (rc == EAGAIN && count <= ARP_EAGAIN_MAX_COUNT);
 		if (rc != EOK) {
 			pq_release_remote(ip_globals.net_phone,
