Index: uspace/lib/c/generic/fibril_synch.c
===================================================================
--- uspace/lib/c/generic/fibril_synch.c	(revision 6e88fea54ce8605a469de92c0d47f6a35461c26c)
+++ uspace/lib/c/generic/fibril_synch.c	(revision 2a3214e79622fd100bc5588ff1b233dea739fc5c)
@@ -447,4 +447,133 @@
 }
 
+/** Timer fibril.
+ *
+ * @param arg	Timer
+ */
+static int fibril_timer_func(void *arg)
+{
+	fibril_timer_t *timer = (fibril_timer_t *) arg;
+	int rc;
+
+	fibril_mutex_lock(&timer->lock);
+
+	while (true) {
+		while (timer->state != fts_active &&
+		    timer->state != fts_cleanup) {
+
+			if (timer->state == fts_cleanup)
+				break;
+
+			fibril_condvar_wait(&timer->cv, &timer->lock);
+		}
+
+		if (timer->state == fts_cleanup)
+			break;
+
+		rc = fibril_condvar_wait_timeout(&timer->cv, &timer->lock,
+		    timer->delay);
+		if (rc == ETIMEOUT) {
+			timer->fun(timer->arg);
+			timer->state = fts_fired;
+		}
+	}
+
+	fibril_mutex_unlock(&timer->lock);
+	return 0;
+}
+
+/** Create new timer.
+ *
+ * @return		New timer on success, @c NULL if out of memory.
+ */
+fibril_timer_t *fibril_timer_create(void)
+{
+	fid_t fid;
+	fibril_timer_t *timer;
+
+	timer = calloc(1, sizeof(fibril_timer_t));
+	if (timer == NULL)
+		return NULL;
+
+	fid = fibril_create(fibril_timer_func, (void *) timer);
+	if (fid == 0) {
+		free(timer);
+		return NULL;
+	}
+
+	fibril_mutex_initialize(&timer->lock);
+	fibril_condvar_initialize(&timer->cv);
+
+	timer->fibril = fid;
+	timer->state = fts_not_set;
+
+	fibril_add_ready(fid);
+
+	return timer;
+}
+
+/** Destroy timer.
+ *
+ * @param timer		Timer, must not be active or accessed by other threads.
+ */
+void fibril_timer_destroy(fibril_timer_t *timer)
+{
+	fibril_mutex_lock(&timer->lock);
+	assert(timer->state != fts_active);
+	timer->state = fts_cleanup;
+	fibril_condvar_broadcast(&timer->cv);
+	fibril_mutex_unlock(&timer->lock);
+}
+
+/** Set timer.
+ *
+ * Set timer to execute a callback function after the specified
+ * interval.
+ *
+ * @param timer		Timer
+ * @param delay		Delay in microseconds
+ * @param fun		Callback function
+ * @param arg		Argument for @a fun
+ */
+void fibril_timer_set(fibril_timer_t *timer, suseconds_t delay,
+    fibril_timer_fun_t fun, void *arg)
+{
+	fibril_mutex_lock(&timer->lock);
+	timer->state = fts_active;
+	timer->delay = delay;
+	timer->fun = fun;
+	timer->arg = arg;
+	fibril_condvar_broadcast(&timer->cv);
+	fibril_mutex_unlock(&timer->lock);
+}
+
+/** Clear timer.
+ *
+ * Clears (cancels) timer and returns last state of the timer.
+ * This can be one of:
+ *    - fts_not_set	If the timer has not been set or has been cleared
+ *    - fts_active	Timer was set but did not fire
+ *    - fts_fired	Timer fired
+ *
+ * @param timer		Timer
+ * @return		Last timer state
+ */
+fibril_timer_state_t fibril_timer_clear(fibril_timer_t *timer)
+{
+	fibril_timer_state_t old_state;
+
+	fibril_mutex_lock(&timer->lock);
+	old_state = timer->state;
+	timer->state = fts_not_set;
+
+	timer->delay = 0;
+	timer->fun = NULL;
+	timer->arg = NULL;
+	fibril_condvar_broadcast(&timer->cv);
+	fibril_mutex_unlock(&timer->lock);
+
+	return old_state;
+}
+
 /** @}
  */
Index: uspace/lib/c/include/fibril_synch.h
===================================================================
--- uspace/lib/c/include/fibril_synch.h	(revision 6e88fea54ce8605a469de92c0d47f6a35461c26c)
+++ uspace/lib/c/include/fibril_synch.h	(revision 2a3214e79622fd100bc5588ff1b233dea739fc5c)
@@ -107,4 +107,35 @@
 	fibril_condvar_t name = FIBRIL_CONDVAR_INITIALIZER(name)
 
+typedef void (*fibril_timer_fun_t)(void *);
+
+typedef enum {
+	/** Timer has not been set or has been cleared */
+	fts_not_set,
+	/** Timer was set but did not fire yet */
+	fts_active,
+	/** Timer has fired and has not been cleared since */
+	fts_fired,
+	/** Timer is being destroyed */
+	fts_cleanup
+} fibril_timer_state_t;
+
+/** Fibril timer.
+ *
+ * When a timer is set it executes a callback function (in a separate
+ * fibril) after a specified time interval. The timer can be cleared
+ * (canceled) before that. From the return value of fibril_timer_clear()
+ * one can tell whether the timer fired or not.
+ */
+typedef struct {
+	fibril_mutex_t lock;
+	fibril_condvar_t cv;
+	fid_t fibril;
+	fibril_timer_state_t state;
+
+	suseconds_t delay;
+	fibril_timer_fun_t fun;
+	void *arg;
+} fibril_timer_t;
+
 extern void fibril_mutex_initialize(fibril_mutex_t *);
 extern void fibril_mutex_lock(fibril_mutex_t *);
@@ -129,4 +160,10 @@
 extern void fibril_condvar_broadcast(fibril_condvar_t *);
 
+extern fibril_timer_t *fibril_timer_create(void);
+extern void fibril_timer_destroy(fibril_timer_t *);
+extern void fibril_timer_set(fibril_timer_t *, suseconds_t, fibril_timer_fun_t,
+    void *);
+extern fibril_timer_state_t fibril_timer_clear(fibril_timer_t *);
+
 #endif
 
Index: uspace/srv/net/tl/tcp/conn.c
===================================================================
--- uspace/srv/net/tl/tcp/conn.c	(revision 6e88fea54ce8605a469de92c0d47f6a35461c26c)
+++ uspace/srv/net/tl/tcp/conn.c	(revision 2a3214e79622fd100bc5588ff1b233dea739fc5c)
@@ -45,4 +45,5 @@
 #include "segment.h"
 #include "seq_no.h"
+#include "state.h"
 #include "tcp_type.h"
 #include "tqueue.h"
@@ -51,7 +52,11 @@
 #define SND_BUF_SIZE 4096
 
+#define MAX_SEGMENT_LIFETIME	(15*1000*1000) //(2*60*1000*1000)
+#define TIME_WAIT_TIMEOUT	(2*MAX_SEGMENT_LIFETIME)
+
 LIST_INITIALIZE(conn_list);
 
 static void tcp_conn_seg_process(tcp_conn_t *conn, tcp_segment_t *seg);
+static void tcp_conn_tw_timer_set(tcp_conn_t *conn);
 
 /** Create new segment structure.
@@ -63,10 +68,14 @@
 tcp_conn_t *tcp_conn_new(tcp_sock_t *lsock, tcp_sock_t *fsock)
 {
-	tcp_conn_t *conn;
+	tcp_conn_t *conn = NULL;
 
 	/* Allocate connection structure */
 	conn = calloc(1, sizeof(tcp_conn_t));
 	if (conn == NULL)
-		return NULL;
+		goto error;
+
+	conn->tw_timer = fibril_timer_create();
+	if (conn->tw_timer == NULL)
+		goto error;
 
 	/* Allocate receive buffer */
@@ -78,8 +87,6 @@
 
 	conn->rcv_buf = calloc(1, conn->rcv_buf_size);
-	if (conn->rcv_buf == NULL) {
-		free(conn);
-		return NULL;
-	}
+	if (conn->rcv_buf == NULL)
+		goto error;
 
 	/** Allocate send buffer */
@@ -88,8 +95,6 @@
 	conn->snd_buf_fin = false;
 	conn->snd_buf = calloc(1, conn->snd_buf_size);
-	if (conn->snd_buf == NULL) {
-		free(conn);
-		return NULL;
-	}
+	if (conn->snd_buf == NULL)
+		goto error;
 
 	/* Set up receive window. */
@@ -109,4 +114,16 @@
 
 	return conn;
+
+error:
+	if (conn != NULL && conn->rcv_buf != NULL)
+		free(conn->rcv_buf);
+	if (conn != NULL && conn->snd_buf != NULL)
+		free(conn->snd_buf);
+	if (conn != NULL && conn->tw_timer != NULL)
+		fibril_timer_destroy(conn->tw_timer);
+	if (conn != NULL)
+		free(conn);
+
+	return NULL;
 }
 
@@ -803,5 +820,6 @@
 			log_msg(LVL_DEBUG, "FIN received -> Time-Wait");
 			conn->cstate = st_time_wait;
-			/* XXX start time-wait timer */
+			/* Start the Time-Wait timer */
+			tcp_conn_tw_timer_set(conn);
 			break;
 		case st_close_wait:
@@ -811,5 +829,6 @@
 			break;
 		case st_time_wait:
-			/* XXX Restart the 2 MSL time-wait timeout */
+			/* Restart the Time-Wait timer */
+			tcp_conn_tw_timer_set(conn);
 			break;
 		}
@@ -912,4 +931,29 @@
 }
 
+/** Time-Wait timeout handler.
+ *
+ * @param arg	Connection
+ */
+static void tw_timeout_func(void *arg)
+{
+	tcp_conn_t *conn = (tcp_conn_t *) arg;
+
+	log_msg(LVL_DEBUG, "tw_timeout_func(%p)", conn);
+	log_msg(LVL_DEBUG, " TW Timeout -> Closed");
+
+	tcp_conn_remove(conn);
+	conn->cstate = st_closed;
+}
+
+/** Start or restart the Time-Wait timeout.
+ *
+ * @param conn		Connection
+ */
+void tcp_conn_tw_timer_set(tcp_conn_t *conn)
+{
+	fibril_timer_set(conn->tw_timer, TIME_WAIT_TIMEOUT, tw_timeout_func,
+	    (void *)conn);
+}
+
 /** Trim segment to the receive window.
  *
Index: uspace/srv/net/tl/tcp/state.c
===================================================================
--- uspace/srv/net/tl/tcp/state.c	(revision 6e88fea54ce8605a469de92c0d47f6a35461c26c)
+++ uspace/srv/net/tl/tcp/state.c	(revision 2a3214e79622fd100bc5588ff1b233dea739fc5c)
@@ -209,10 +209,4 @@
 }
 
-/** Time-wait timeout */
-void tcp_to_time_wait(void)
-{
-	log_msg(LVL_DEBUG, "tcp_to_time_wait()");
-}
-
 /**
  * @}
Index: uspace/srv/net/tl/tcp/state.h
===================================================================
--- uspace/srv/net/tl/tcp/state.h	(revision 6e88fea54ce8605a469de92c0d47f6a35461c26c)
+++ uspace/srv/net/tl/tcp/state.h	(revision 2a3214e79622fd100bc5588ff1b233dea739fc5c)
@@ -59,5 +59,4 @@
 extern void tcp_to_user(void);
 extern void tcp_to_retransmit(void);
-extern void tcp_to_time_wait(void);
 
 #endif
Index: uspace/srv/net/tl/tcp/tcp_type.h
===================================================================
--- uspace/srv/net/tl/tcp/tcp_type.h	(revision 6e88fea54ce8605a469de92c0d47f6a35461c26c)
+++ uspace/srv/net/tl/tcp/tcp_type.h	(revision 2a3214e79622fd100bc5588ff1b233dea739fc5c)
@@ -122,4 +122,7 @@
 	tcp_tqueue_t retransmit;
 
+	/** Time-Wait timeout timer */
+	fibril_timer_t *tw_timer;
+
 	/** Receive buffer */
 	uint8_t *rcv_buf;
