diff options
author | KOVACS Krisztian <hidden@sch.bme.hu> | 2008-10-01 10:41:00 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-10-01 10:41:00 -0400 |
commit | 88ef4a5a78e63420dd1dd770f1bd1dc198926b04 (patch) | |
tree | 42409d6d26fb6f954c501ac156d34265437d18f9 /net/ipv4 | |
parent | 79876874ce20d37ecdc7f481ebf142466999152f (diff) |
tcp: Handle TCP SYN+ACK/ACK/RST transparency
The TCP stack sends out SYN+ACK/ACK/RST reply packets in response to
incoming packets. The non-local source address check on output bites
us again, as replies for transparently redirected traffic won't have a
chance to leave the node.
This patch selectively sets the FLOWI_FLAG_ANYSRC flag when doing the
route lookup for those replies. Transparent replies are enabled if the
listening socket has the transparent socket flag set.
Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index d13688e3558d..8b24bd833cb4 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -591,6 +591,7 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) | |||
591 | ip_hdr(skb)->saddr, /* XXX */ | 591 | ip_hdr(skb)->saddr, /* XXX */ |
592 | sizeof(struct tcphdr), IPPROTO_TCP, 0); | 592 | sizeof(struct tcphdr), IPPROTO_TCP, 0); |
593 | arg.csumoffset = offsetof(struct tcphdr, check) / 2; | 593 | arg.csumoffset = offsetof(struct tcphdr, check) / 2; |
594 | arg.flags = (sk && inet_sk(sk)->transparent) ? IP_REPLY_ARG_NOSRCCHECK : 0; | ||
594 | 595 | ||
595 | net = dev_net(skb->dst->dev); | 596 | net = dev_net(skb->dst->dev); |
596 | ip_send_reply(net->ipv4.tcp_sock, skb, | 597 | ip_send_reply(net->ipv4.tcp_sock, skb, |
@@ -606,7 +607,8 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) | |||
606 | 607 | ||
607 | static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, | 608 | static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, |
608 | u32 win, u32 ts, int oif, | 609 | u32 win, u32 ts, int oif, |
609 | struct tcp_md5sig_key *key) | 610 | struct tcp_md5sig_key *key, |
611 | int reply_flags) | ||
610 | { | 612 | { |
611 | struct tcphdr *th = tcp_hdr(skb); | 613 | struct tcphdr *th = tcp_hdr(skb); |
612 | struct { | 614 | struct { |
@@ -659,6 +661,7 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, | |||
659 | ip_hdr(skb)->daddr, &rep.th); | 661 | ip_hdr(skb)->daddr, &rep.th); |
660 | } | 662 | } |
661 | #endif | 663 | #endif |
664 | arg.flags = reply_flags; | ||
662 | arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr, | 665 | arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr, |
663 | ip_hdr(skb)->saddr, /* XXX */ | 666 | ip_hdr(skb)->saddr, /* XXX */ |
664 | arg.iov[0].iov_len, IPPROTO_TCP, 0); | 667 | arg.iov[0].iov_len, IPPROTO_TCP, 0); |
@@ -681,7 +684,8 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb) | |||
681 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, | 684 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, |
682 | tcptw->tw_ts_recent, | 685 | tcptw->tw_ts_recent, |
683 | tw->tw_bound_dev_if, | 686 | tw->tw_bound_dev_if, |
684 | tcp_twsk_md5_key(tcptw) | 687 | tcp_twsk_md5_key(tcptw), |
688 | tw->tw_transparent ? IP_REPLY_ARG_NOSRCCHECK : 0 | ||
685 | ); | 689 | ); |
686 | 690 | ||
687 | inet_twsk_put(tw); | 691 | inet_twsk_put(tw); |
@@ -694,7 +698,8 @@ static void tcp_v4_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, | |||
694 | tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, | 698 | tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, |
695 | req->ts_recent, | 699 | req->ts_recent, |
696 | 0, | 700 | 0, |
697 | tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->daddr)); | 701 | tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->daddr), |
702 | inet_rsk(req)->no_srccheck ? IP_REPLY_ARG_NOSRCCHECK : 0); | ||
698 | } | 703 | } |
699 | 704 | ||
700 | /* | 705 | /* |
@@ -1244,6 +1249,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1244 | ireq = inet_rsk(req); | 1249 | ireq = inet_rsk(req); |
1245 | ireq->loc_addr = daddr; | 1250 | ireq->loc_addr = daddr; |
1246 | ireq->rmt_addr = saddr; | 1251 | ireq->rmt_addr = saddr; |
1252 | ireq->no_srccheck = inet_sk(sk)->transparent; | ||
1247 | ireq->opt = tcp_v4_save_options(sk, skb); | 1253 | ireq->opt = tcp_v4_save_options(sk, skb); |
1248 | if (!want_cookie) | 1254 | if (!want_cookie) |
1249 | TCP_ECN_create_request(req, tcp_hdr(skb)); | 1255 | TCP_ECN_create_request(req, tcp_hdr(skb)); |