Index: uspace/srv/net/tl/tcp/conn.c
===================================================================
--- uspace/srv/net/tl/tcp/conn.c	(revision 0ac215896a5381e04f091bb4999140a0e38f21a3)
+++ uspace/srv/net/tl/tcp/conn.c	(revision d9e14fa4eda79222ef1b8ec59ec38b7ddec79512)
@@ -117,4 +117,6 @@
 
 	conn->cstate = st_listen;
+	conn->reset = false;
+	conn->ap = ap_passive;
 	conn->fin_is_acked = false;
 	conn->ident.local = *lsock;
@@ -176,4 +178,5 @@
 	conn->snd_nxt = conn->iss;
 	conn->snd_una = conn->iss;
+	conn->ap = ap_active;
 
 	tcp_tqueue_ctrl_seg(conn, CTL_SYN);
@@ -278,6 +281,20 @@
 	log_msg(LVL_DEBUG, "%s: tcp_conn_reset()", conn->name);
 	tcp_conn_state_set(conn, st_closed);
+	conn->reset = true;
+
 	tcp_conn_tw_timer_clear(conn);
 	tcp_tqueue_clear(&conn->retransmit);
+
+	fibril_condvar_broadcast(&conn->rcv_buf_cv);
+}
+
+/** Signal to the user that connection has been reset.
+ *
+ * Send an out-of-band signal to the user.
+ */
+static void tcp_reset_signal(tcp_conn_t *conn)
+{
+	/* TODO */
+	log_msg(LVL_DEBUG, "%s: tcp_reset_signal()", conn->name);
 }
 
@@ -485,6 +502,36 @@
 static cproc_t tcp_conn_seg_proc_rst(tcp_conn_t *conn, tcp_segment_t *seg)
 {
-	/* TODO */
-	return cp_continue;
+	switch (conn->cstate) {
+	case st_syn_received:
+		/* XXX In case of passive open, revert to Listen state */
+		if (conn->ap == ap_passive) {
+			tcp_conn_state_set(conn, st_listen);
+			/* XXX Revert conn->ident */
+			tcp_conn_tw_timer_clear(conn);
+			tcp_tqueue_clear(&conn->retransmit);
+		} else {
+			tcp_conn_reset(conn);
+		}
+		break;
+	case st_established:
+	case st_fin_wait_1:
+	case st_fin_wait_2:
+	case st_close_wait:
+		/* General "connection reset" signal */
+		tcp_reset_signal(conn);
+		tcp_conn_reset(conn);
+		break;
+	case st_closing:
+	case st_last_ack:
+	case st_time_wait:
+		tcp_conn_reset(conn);
+		break;
+	case st_listen:
+	case st_syn_sent:
+	case st_closed:
+		assert(false);
+	}
+
+	return cp_done;
 }
 
Index: uspace/srv/net/tl/tcp/sock.c
===================================================================
--- uspace/srv/net/tl/tcp/sock.c	(revision 0ac215896a5381e04f091bb4999140a0e38f21a3)
+++ uspace/srv/net/tl/tcp/sock.c	(revision d9e14fa4eda79222ef1b8ec59ec38b7ddec79512)
@@ -451,4 +451,7 @@
 			rc = ENOTCONN;
 			break;
+		case TCP_ERESET:
+			rc = ECONNABORTED;
+			break;
 		default:
 			assert(false);
@@ -520,4 +523,7 @@
 		rc = ENOTCONN;
 		break;
+	case TCP_ERESET:
+		rc = ECONNABORTED;
+		break;
 	default:
 		assert(false);
Index: uspace/srv/net/tl/tcp/tcp_type.h
===================================================================
--- uspace/srv/net/tl/tcp/tcp_type.h	(revision 0ac215896a5381e04f091bb4999140a0e38f21a3)
+++ uspace/srv/net/tl/tcp/tcp_type.h	(revision d9e14fa4eda79222ef1b8ec59ec38b7ddec79512)
@@ -147,4 +147,9 @@
 } tcp_tqueue_t;
 
+typedef enum {
+	ap_active,
+	ap_passive
+} acpass_t;
+
 typedef struct tcp_conn {
 	char *name;
@@ -154,6 +159,11 @@
 	tcp_sockpair_t ident;
 
+	/** Active or passive connection */
+	acpass_t ap;
+
 	/** Connection state */
 	tcp_cstate_t cstate;
+	/** True if connection was reset */
+	bool reset;
 	/** Protects @c cstate */
 	fibril_mutex_t cstate_lock;
@@ -245,8 +255,4 @@
 } tcp_segment_t;
 
-typedef enum {
-	ap_active,
-	ap_passive
-} acpass_t;
 
 typedef struct {
Index: uspace/srv/net/tl/tcp/ucall.c
===================================================================
--- uspace/srv/net/tl/tcp/ucall.c	(revision 0ac215896a5381e04f091bb4999140a0e38f21a3)
+++ uspace/srv/net/tl/tcp/ucall.c	(revision d9e14fa4eda79222ef1b8ec59ec38b7ddec79512)
@@ -126,6 +126,9 @@
 	while (size > 0) {
 		buf_free = conn->snd_buf_size - conn->snd_buf_used;
-		while (buf_free == 0)
+		while (buf_free == 0 && !conn->reset)
 			tcp_tqueue_new_data(conn);
+
+		if (conn->reset)
+			return TCP_ERESET;
 
 		xfer_size = min(size, buf_free);
@@ -157,5 +160,5 @@
 
 	/* Wait for data to become available */
-	while (conn->rcv_buf_used == 0 && !conn->rcv_buf_fin) {
+	while (conn->rcv_buf_used == 0 && !conn->rcv_buf_fin && !conn->reset) {
 		log_msg(LVL_DEBUG, "tcp_uc_receive() - wait for data");
 		fibril_condvar_wait(&conn->rcv_buf_cv, &conn->rcv_buf_lock);
@@ -165,9 +168,15 @@
 		fibril_mutex_unlock(&conn->rcv_buf_lock);
 
-		/* End of data, peer closed connection. */
-		assert(conn->rcv_buf_fin);
 		*rcvd = 0;
 		*xflags = 0;
-		return TCP_ECLOSING;
+
+		if (conn->rcv_buf_fin) {
+			/* End of data, peer closed connection */
+			return TCP_ECLOSING;
+		} else {
+			/* Connection was reset */
+			assert(conn->reset);
+			return TCP_ERESET;
+		}
 	}
 
