Index: uspace/srv/net/tcp/conn.c
===================================================================
--- uspace/srv/net/tcp/conn.c	(revision 8d48c7e46fe4c12afd9489154fb06b10f9e2c913)
+++ uspace/srv/net/tcp/conn.c	(revision 2c4bb828a93021583aec2fd19982a935378d0df4)
@@ -58,4 +58,5 @@
 
 static LIST_INITIALIZE(conn_list);
+/** Taken after tcp_conn_t lock */
 static FIBRIL_MUTEX_INITIALIZE(conn_list_lock);
 static amap_t *amap;
@@ -1176,8 +1177,14 @@
  *
  * @param conn		Connection
- * @param seg		Segment
- */
-void tcp_conn_segment_arrived(tcp_conn_t *conn, tcp_segment_t *seg)
-{
+ * @param epp		Endpoint pair on which segment was received
+ * @param seg		Segment
+ */
+void tcp_conn_segment_arrived(tcp_conn_t *conn, inet_ep2_t *epp,
+    tcp_segment_t *seg)
+{
+	inet_ep2_t aepp;
+	inet_ep2_t oldepp;
+	int rc;
+
 	log_msg(LOG_DEFAULT, LVL_NOTE, "conn=%p", conn);
 	log_msg(LOG_DEFAULT, LVL_NOTE, "conn->name=%p", conn->name);
@@ -1185,9 +1192,56 @@
 	    conn->name, seg);
 
+	tcp_conn_lock(conn);
+
+	if (conn->cstate == st_closed) {
+		log_msg(LOG_DEFAULT, LVL_WARN, "Connection is closed.");
+		tcp_unexpected_segment(epp, seg);
+		tcp_conn_unlock(conn);
+		return;
+	}
+
+	if (inet_addr_is_any(&conn->ident.remote.addr) ||
+	    conn->ident.remote.port == inet_port_any ||
+	    inet_addr_is_any(&conn->ident.local.addr)) {
+
+		log_msg(LOG_DEFAULT, LVL_NOTE, "tcp_conn_segment_arrived: "
+		    "Changing connection ID, updating amap.");
+		oldepp = conn->ident;
+
+		/* Need to remove and re-insert connection with new identity */
+		fibril_mutex_lock(&conn_list_lock);
+
+		if (inet_addr_is_any(&conn->ident.remote.addr))
+			conn->ident.remote.addr = epp->remote.addr;
+
+		if (conn->ident.remote.port == inet_port_any)
+			conn->ident.remote.port = epp->remote.port;
+
+		if (inet_addr_is_any(&conn->ident.local.addr))
+			conn->ident.local.addr = epp->local.addr;
+
+		rc = amap_insert(amap, &conn->ident, conn, af_allow_system, &aepp);
+		if (rc != EOK) {
+			assert(rc != EEXISTS);
+			assert(rc == ENOMEM);
+			log_msg(LOG_DEFAULT, LVL_ERROR, "Out of memory.");
+			fibril_mutex_unlock(&conn_list_lock);
+			tcp_conn_unlock(conn);
+			return;
+		}
+
+		amap_remove(amap, &oldepp);
+		fibril_mutex_unlock(&conn_list_lock);
+
+		conn->name = (char *) "a";
+	}
+
 	switch (conn->cstate) {
 	case st_listen:
-		tcp_conn_sa_listen(conn, seg); break;
+		tcp_conn_sa_listen(conn, seg);
+		break;
 	case st_syn_sent:
-		tcp_conn_sa_syn_sent(conn, seg); break;
+		tcp_conn_sa_syn_sent(conn, seg);
+		break;
 	case st_syn_received:
 	case st_established:
@@ -1199,9 +1253,12 @@
 	case st_time_wait:
 		/* Process segments in order of sequence number */
-		tcp_conn_sa_queue(conn, seg); break;
+		tcp_conn_sa_queue(conn, seg);
+		break;
 	case st_closed:
 		log_msg(LOG_DEFAULT, LVL_DEBUG, "state=%d", (int) conn->cstate);
 		assert(false);
 	}
+
+	tcp_conn_unlock(conn);
 }
 
Index: uspace/srv/net/tcp/conn.h
===================================================================
--- uspace/srv/net/tcp/conn.h	(revision 8d48c7e46fe4c12afd9489154fb06b10f9e2c913)
+++ uspace/srv/net/tcp/conn.h	(revision 2c4bb828a93021583aec2fd19982a935378d0df4)
@@ -55,5 +55,6 @@
 extern void tcp_conn_unlock(tcp_conn_t *);
 extern bool tcp_conn_got_syn(tcp_conn_t *);
-extern void tcp_conn_segment_arrived(tcp_conn_t *, tcp_segment_t *);
+extern void tcp_conn_segment_arrived(tcp_conn_t *, inet_ep2_t *,
+    tcp_segment_t *);
 extern void tcp_conn_trim_seg_to_wnd(tcp_conn_t *, tcp_segment_t *);
 extern void tcp_unexpected_segment(inet_ep2_t *, tcp_segment_t *);
Index: uspace/srv/net/tcp/ucall.c
===================================================================
--- uspace/srv/net/tcp/ucall.c	(revision 8d48c7e46fe4c12afd9489154fb06b10f9e2c913)
+++ uspace/srv/net/tcp/ucall.c	(revision 2c4bb828a93021583aec2fd19982a935378d0df4)
@@ -336,26 +336,5 @@
 	}
 
-	tcp_conn_lock(conn);
-
-	if (conn->cstate == st_closed) {
-		log_msg(LOG_DEFAULT, LVL_WARN, "Connection is closed.");
-		tcp_unexpected_segment(epp, seg);
-		tcp_conn_unlock(conn);
-		tcp_conn_delref(conn);
-		return;
-	}
-
-	if (inet_addr_is_any(&conn->ident.remote.addr))
-		conn->ident.remote.addr = epp->remote.addr;
-
-	if (conn->ident.remote.port == inet_port_any)
-		conn->ident.remote.port = epp->remote.port;
-
-	if (inet_addr_is_any(&conn->ident.local.addr))
-		conn->ident.local.addr = epp->local.addr;
-
-	tcp_conn_segment_arrived(conn, seg);
-
-	tcp_conn_unlock(conn);
+	tcp_conn_segment_arrived(conn, epp, seg);
 	tcp_conn_delref(conn);
 }
