aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_ipv4.c
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2011-10-24 03:06:21 -0400
committerDavid S. Miller <davem@davemloft.net>2011-10-24 03:06:21 -0400
commit66b13d99d96a1a69f47a6bc3dc47f45955967377 (patch)
treec566bee026b5e9703f789d27657aefa7c70c587c /net/ipv4/tcp_ipv4.c
parent318cf7aaa0a6d20ecf6be33eb771291e5ff2e3b9 (diff)
ipv4: tcp: fix TOS value in ACK messages sent from TIME_WAIT
There is a long standing bug in linux tcp stack, about ACK messages sent on behalf of TIME_WAIT sockets. In the IP header of the ACK message, we choose to reflect TOS field of incoming message, and this might break some setups. Example of things that were broken : - Routing using TOS as a selector - Firewalls - Trafic classification / shaping We now remember in timewait structure the inet tos field and use it in ACK generation, and route lookup. Notes : - We still reflect incoming TOS in RST messages. - We could extend MuraliRaja Muniraju patch to report TOS value in netlink messages for TIME_WAIT sockets. - A patch is needed for IPv6 Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp_ipv4.c')
-rw-r--r--net/ipv4/tcp_ipv4.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 1dad7e92f005..0ea10eefa60f 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -652,6 +652,7 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
652 arg.flags = (sk && inet_sk(sk)->transparent) ? IP_REPLY_ARG_NOSRCCHECK : 0; 652 arg.flags = (sk && inet_sk(sk)->transparent) ? IP_REPLY_ARG_NOSRCCHECK : 0;
653 653
654 net = dev_net(skb_dst(skb)->dev); 654 net = dev_net(skb_dst(skb)->dev);
655 arg.tos = ip_hdr(skb)->tos;
655 ip_send_reply(net->ipv4.tcp_sock, skb, ip_hdr(skb)->saddr, 656 ip_send_reply(net->ipv4.tcp_sock, skb, ip_hdr(skb)->saddr,
656 &arg, arg.iov[0].iov_len); 657 &arg, arg.iov[0].iov_len);
657 658
@@ -666,7 +667,7 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
666static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, 667static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
667 u32 win, u32 ts, int oif, 668 u32 win, u32 ts, int oif,
668 struct tcp_md5sig_key *key, 669 struct tcp_md5sig_key *key,
669 int reply_flags) 670 int reply_flags, u8 tos)
670{ 671{
671 const struct tcphdr *th = tcp_hdr(skb); 672 const struct tcphdr *th = tcp_hdr(skb);
672 struct { 673 struct {
@@ -726,7 +727,7 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
726 arg.csumoffset = offsetof(struct tcphdr, check) / 2; 727 arg.csumoffset = offsetof(struct tcphdr, check) / 2;
727 if (oif) 728 if (oif)
728 arg.bound_dev_if = oif; 729 arg.bound_dev_if = oif;
729 730 arg.tos = tos;
730 ip_send_reply(net->ipv4.tcp_sock, skb, ip_hdr(skb)->saddr, 731 ip_send_reply(net->ipv4.tcp_sock, skb, ip_hdr(skb)->saddr,
731 &arg, arg.iov[0].iov_len); 732 &arg, arg.iov[0].iov_len);
732 733
@@ -743,7 +744,8 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb)
743 tcptw->tw_ts_recent, 744 tcptw->tw_ts_recent,
744 tw->tw_bound_dev_if, 745 tw->tw_bound_dev_if,
745 tcp_twsk_md5_key(tcptw), 746 tcp_twsk_md5_key(tcptw),
746 tw->tw_transparent ? IP_REPLY_ARG_NOSRCCHECK : 0 747 tw->tw_transparent ? IP_REPLY_ARG_NOSRCCHECK : 0,
748 tw->tw_tos
747 ); 749 );
748 750
749 inet_twsk_put(tw); 751 inet_twsk_put(tw);
@@ -757,7 +759,8 @@ static void tcp_v4_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,
757 req->ts_recent, 759 req->ts_recent,
758 0, 760 0,
759 tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->daddr), 761 tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->daddr),
760 inet_rsk(req)->no_srccheck ? IP_REPLY_ARG_NOSRCCHECK : 0); 762 inet_rsk(req)->no_srccheck ? IP_REPLY_ARG_NOSRCCHECK : 0,
763 ip_hdr(skb)->tos);
761} 764}
762 765
763/* 766/*