diff -Nur orig/include/net/inet_sock.h patched/include/net/inet_sock.h
--- orig/include/net/inet_sock.h	2010-08-02 01:11:14.000000000 +0300
+++ patched/include/net/inet_sock.h	2011-03-26 07:41:39.569716034 +0200
@@ -150,6 +150,7 @@
 		__be32			addr;
 		struct flowi		fl;
 	} cork;
+	__u16                    zph_tos;        /* ZPH TOS received on connect */ 
 };
 
 #define IPCORK_OPT	1	/* ip-options has been held in ipcork.opt */
diff -Nur orig/net/ipv4/ip_sockglue.c patched/net/ipv4/ip_sockglue.c
--- orig/net/ipv4/ip_sockglue.c	2010-08-02 01:11:14.000000000 +0300
+++ patched/net/ipv4/ip_sockglue.c	2011-03-26 07:41:39.573716021 +0200
@@ -1211,6 +1211,10 @@
 			int hlim = inet->mc_ttl;
 			put_cmsg(&msg, SOL_IP, IP_TTL, sizeof(hlim), &hlim);
 		}
+		if (inet->cmsg_flags&IP_CMSG_TOS) {
+			int hlim = inet->zph_tos & 0xFF;
+			put_cmsg(&msg, SOL_IP, IP_TOS, sizeof(hlim), &hlim);
+		}
 		len -= msg.msg_controllen;
 		return put_user(len, optlen);
 	}
diff -Nur orig/net/ipv4/tcp_input.c patched/net/ipv4/tcp_input.c
--- orig/net/ipv4/tcp_input.c	2011-03-26 00:01:59.000000000 +0200
+++ patched/net/ipv4/tcp_input.c	2011-03-26 08:14:05.000000000 +0200
@@ -4366,6 +4366,8 @@
 	struct tcphdr *th = tcp_hdr(skb);
 	struct tcp_sock *tp = tcp_sk(sk);
 	int eaten = -1;
+	struct inet_sock *inet = inet_sk(sk);
+	struct iphdr *iph = ip_hdr(skb);
 
 	if (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq)
 		goto drop;
@@ -4376,6 +4378,12 @@
 	TCP_ECN_accept_cwr(tp, skb);
 
 	tp->rx_opt.dsack = 0;
+	
+	// ZPH: Copy the TOS value of the first data ACK segment
+	// received from the remote peer.
+	if (0==(inet->zph_tos & 0x8000)) {
+		inet->zph_tos = 0x8000 | iph->tos;
+	}
 
 	/*  Queue data for delivery to the user.
 	 *  Packets in sequence go to the receive queue.
@@ -5442,6 +5450,8 @@
 	struct inet_connection_sock *icsk = inet_csk(sk);
 	struct tcp_sock *tp = tcp_sk(sk);
 	struct tcp_cookie_values *cvp = tp->cookie_values;
+	struct inet_sock *inet = inet_sk(sk);
+	struct iphdr *iph = ip_hdr(skb);
 	int saved_clamp = tp->rx_opt.mss_clamp;
 
 	tcp_parse_options(skb, &tp->rx_opt, &hash_location, 0);
@@ -5500,6 +5510,15 @@
 
 		TCP_ECN_rcv_synack(tp, th);
 
+    /* ZPH:
+		 * Copy TOS field from the SYNACK packet to zph_tos field of the af_inet
+		 * member of sock structure. This value shall be overwritten when the first
+		 * data segment is received from the peer. However, for completeness in
+		 * case the socket TOS is being asked befor that, we copy the TOS value from
+		 * the SYNACK packet.
+		 */
+		inet->zph_tos = iph->tos;
+
 		tp->snd_wl1 = TCP_SKB_CB(skb)->seq;
 		tcp_ack(sk, skb, FLAG_SLOWPATH);
 
