Index: uspace/srv/net/tl/tcp/conn.c
===================================================================
--- uspace/srv/net/tl/tcp/conn.c	(revision 854e79a6ed3807edf8743a2e61951ca2086df2c8)
+++ uspace/srv/net/tl/tcp/conn.c	(revision 004a5fee58a6c541fd63bd94a81a2f3b35735aa9)
@@ -111,4 +111,8 @@
 	tqueue_inited = true;
 
+	/* Connection state change signalling */
+	fibril_mutex_initialize(&conn->cstate_lock);
+	fibril_condvar_initialize(&conn->cstate_cv);
+
 	conn->cstate = st_listen;
 	conn->fin_is_acked = false;
@@ -152,4 +156,12 @@
 }
 
+static void tcp_conn_state_set(tcp_conn_t *conn, tcp_cstate_t nstate)
+{
+	fibril_mutex_lock(&conn->cstate_lock);
+	conn->cstate = nstate;
+	fibril_condvar_broadcast(&conn->cstate_cv);
+	fibril_mutex_unlock(&conn->cstate_lock);
+}
+
 /** Synchronize connection.
  *
@@ -165,5 +177,5 @@
 
 	tcp_tqueue_ctrl_seg(conn, CTL_SYN);
-	conn->cstate = st_syn_sent;
+	tcp_conn_state_set(conn, st_syn_sent);
 }
 
@@ -179,9 +191,9 @@
 	case st_established:
 		log_msg(LVL_DEBUG, "FIN sent -> Fin-Wait-1");
-		conn->cstate = st_fin_wait_1;
+		tcp_conn_state_set(conn, st_fin_wait_1);
 		break;
 	case st_close_wait:
 		log_msg(LVL_DEBUG, "FIN sent -> Last-Ack");
-		conn->cstate = st_last_ack;
+		tcp_conn_state_set(conn, st_last_ack);
 		break;
 	default:
@@ -328,5 +340,5 @@
 	conn->snd_wl2 = seg->seq;
 
-	conn->cstate = st_syn_received;
+	tcp_conn_state_set(conn, st_syn_received);
 
 	tcp_tqueue_ctrl_seg(conn, CTL_SYN | CTL_ACK /* XXX */);
@@ -357,5 +369,5 @@
 		log_msg(LVL_DEBUG, "Connection reset. -> Closed");
 		/* XXX Signal user error */
-		conn->cstate = st_closed;
+		tcp_conn_state_set(conn, st_closed);
 		/* XXX delete connection */
 		return;
@@ -397,9 +409,9 @@
 	if (seq_no_syn_acked(conn)) {
 		log_msg(LVL_DEBUG, " syn acked -> Established");
-		conn->cstate = st_established;
+		tcp_conn_state_set(conn, st_established);
 		tcp_tqueue_ctrl_seg(conn, CTL_ACK /* XXX */);
 	} else {
 		log_msg(LVL_DEBUG, " syn not acked -> Syn-Received");
-		conn->cstate = st_syn_received;
+		tcp_conn_state_set(conn, st_syn_received);
 		tcp_tqueue_ctrl_seg(conn, CTL_SYN | CTL_ACK /* XXX */);
 	}
@@ -517,5 +529,5 @@
 	log_msg(LVL_DEBUG, "SYN ACKed -> Established");
 
-	conn->cstate = st_established;
+	tcp_conn_state_set(conn, st_established);
 
 	/* XXX Not mentioned in spec?! */
@@ -590,5 +602,5 @@
 	if (conn->fin_is_acked) {
 		log_msg(LVL_DEBUG, " FIN acked -> Fin-Wait-2");
-		conn->cstate = st_fin_wait_2;
+		tcp_conn_state_set(conn, st_fin_wait_2);
 	}
 
@@ -656,5 +668,5 @@
 		log_msg(LVL_DEBUG, " FIN acked -> Closed");
 		tcp_conn_remove(conn);
-		conn->cstate = st_closed;
+		tcp_conn_state_set(conn, st_closed);
 		return cp_done;
 	}
@@ -844,13 +856,13 @@
 		case st_established:
 			log_msg(LVL_DEBUG, "FIN received -> Close-Wait");
-			conn->cstate = st_close_wait;
+			tcp_conn_state_set(conn, st_close_wait);
 			break;
 		case st_fin_wait_1:
 			log_msg(LVL_DEBUG, "FIN received -> Closing");
-			conn->cstate = st_closing;
+			tcp_conn_state_set(conn, st_closing);
 			break;
 		case st_fin_wait_2:
 			log_msg(LVL_DEBUG, "FIN received -> Time-Wait");
-			conn->cstate = st_time_wait;
+			tcp_conn_state_set(conn, st_time_wait);
 			/* Start the Time-Wait timer */
 			tcp_conn_tw_timer_set(conn);
@@ -980,5 +992,5 @@
 
 	tcp_conn_remove(conn);
-	conn->cstate = st_closed;
+	tcp_conn_state_set(conn, st_closed);
 }
 
Index: uspace/srv/net/tl/tcp/state.c
===================================================================
--- uspace/srv/net/tl/tcp/state.c	(revision 854e79a6ed3807edf8743a2e61951ca2086df2c8)
+++ uspace/srv/net/tl/tcp/state.c	(revision 004a5fee58a6c541fd63bd94a81a2f3b35735aa9)
@@ -58,5 +58,5 @@
  * connection.
  */
-void tcp_uc_open(uint16_t lport, tcp_sock_t *fsock, acpass_t acpass,
+tcp_error_t tcp_uc_open(uint16_t lport, tcp_sock_t *fsock, acpass_t acpass,
     tcp_conn_t **conn)
 {
@@ -77,7 +77,24 @@
 		/* Synchronize (initiate) connection */
 		tcp_conn_sync(nconn);
+
+		/* Wait for connection to be established or reset */
+		log_msg(LVL_DEBUG, "tcp_uc_open: Wait for connection.");
+		fibril_mutex_lock(&nconn->cstate_lock);
+		while (nconn->cstate == st_syn_sent ||
+		    nconn->cstate == st_syn_received) {
+			fibril_condvar_wait(&nconn->cstate_cv, &nconn->cstate_lock);
+		}
+		if (nconn->cstate != st_established) {
+			log_msg(LVL_DEBUG, "tcp_uc_open: Connection was reset.");
+			assert(nconn->cstate == st_closed);
+			fibril_mutex_unlock(&nconn->cstate_lock);
+			return TCP_ERESET;
+		}
+		fibril_mutex_unlock(&nconn->cstate_lock);
+		log_msg(LVL_DEBUG, "tcp_uc_open: Connection was established.");
 	}
 
 	*conn = nconn;
+	return TCP_EOK;
 }
 
Index: uspace/srv/net/tl/tcp/state.h
===================================================================
--- uspace/srv/net/tl/tcp/state.h	(revision 854e79a6ed3807edf8743a2e61951ca2086df2c8)
+++ uspace/srv/net/tl/tcp/state.h	(revision 004a5fee58a6c541fd63bd94a81a2f3b35735aa9)
@@ -42,5 +42,5 @@
  * User calls
  */
-extern void tcp_uc_open(uint16_t, tcp_sock_t *, acpass_t, tcp_conn_t **);
+extern tcp_error_t tcp_uc_open(uint16_t, tcp_sock_t *, acpass_t, tcp_conn_t **);
 extern tcp_error_t tcp_uc_send(tcp_conn_t *, void *, size_t, xflags_t);
 extern tcp_error_t tcp_uc_receive(tcp_conn_t *, void *, size_t, size_t *, xflags_t *);
Index: uspace/srv/net/tl/tcp/tcp_type.h
===================================================================
--- uspace/srv/net/tl/tcp/tcp_type.h	(revision 854e79a6ed3807edf8743a2e61951ca2086df2c8)
+++ uspace/srv/net/tl/tcp/tcp_type.h	(revision 004a5fee58a6c541fd63bd94a81a2f3b35735aa9)
@@ -146,4 +146,8 @@
 	/** Connection state */
 	tcp_cstate_t cstate;
+	/** Protects @c cstate */
+	fibril_mutex_t cstate_lock;
+	/** Signalled when @c cstate changes */
+	fibril_condvar_t cstate_cv;
 
 	/** Set when FIN is removed from the retransmission queue */
