Index: uspace/srv/net/tl/tcp/tcp.c
===================================================================
--- uspace/srv/net/tl/tcp/tcp.c	(revision b5eae307acebbbe9180272fb7c98f315b08758fb)
+++ uspace/srv/net/tl/tcp/tcp.c	(revision 4449c6cb631ad8343054effc2668e54a01579700)
@@ -36,4 +36,5 @@
 
 #include <async.h>
+#include <bitops.h>
 #include <byteorder.h>
 #include <errno.h>
@@ -191,11 +192,30 @@
 	tcp_pdu_t *pdu;
 	size_t hdr_size;
-
-	/* XXX Header options */
-	hdr_size = sizeof(tcp_header_t);
+	tcp_header_t *hdr;
+	uint32_t data_offset;
+
+	if (pdu_raw_size < sizeof(tcp_header_t)) {
+		log_msg(LVL_WARN, "pdu_raw_size = %zu < sizeof(tcp_header_t) = %zu",
+		    pdu_raw_size, sizeof(tcp_header_t));
+		pq_release_remote(net_sess, packet_get_id(packet));
+		return EINVAL;
+	}
+
+	hdr = (tcp_header_t *)pdu_raw;
+	data_offset = BIT_RANGE_EXTRACT(uint32_t, DF_DATA_OFFSET_h, DF_DATA_OFFSET_l,
+	    uint16_t_be2host(hdr->doff_flags));
+
+	hdr_size = sizeof(uint32_t) * data_offset;
 
 	if (pdu_raw_size < hdr_size) {
 		log_msg(LVL_WARN, "pdu_raw_size = %zu < hdr_size = %zu",
 		    pdu_raw_size, hdr_size);
+		pq_release_remote(net_sess, packet_get_id(packet));
+		return EINVAL;
+	}
+
+	if (hdr_size < sizeof(tcp_header_t)) {
+		log_msg(LVL_WARN, "hdr_size = %zu < sizeof(tcp_header_t) = %zu",
+		    hdr_size, sizeof(tcp_header_t));
 		pq_release_remote(net_sess, packet_get_id(packet));
 		return EINVAL;
