diff options
author | Ilpo Järvinen <ilpo.jarvinen@helsinki.fi> | 2008-08-23 08:10:12 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-08-23 08:10:12 -0400 |
commit | cbe2d128a01315fb4bd55b96cf8b963f5df28ea2 (patch) | |
tree | f110e926a365da22bc2d63402b3d7f079a391dd0 /net/ipv4/tcp_input.c | |
parent | 23edcc4147ad36f8d55f0eb79c21e245ffb9f211 (diff) |
tcp: Add tcp_validate_incoming & put duplicated code there
Large block of code duplication removed.
Sadly, the return value thing is a bit tricky here but it
seems the most sensible way to return positive from validator
on success rather than negative.
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp_input.c')
-rw-r--r-- | net/ipv4/tcp_input.c | 147 |
1 files changed, 69 insertions, 78 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 67ccce2a96bd..e1b15d4e6171 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -4691,6 +4691,67 @@ out: | |||
4691 | } | 4691 | } |
4692 | #endif /* CONFIG_NET_DMA */ | 4692 | #endif /* CONFIG_NET_DMA */ |
4693 | 4693 | ||
4694 | /* Does PAWS and seqno based validation of an incoming segment, flags will | ||
4695 | * play significant role here. | ||
4696 | */ | ||
4697 | static int tcp_validate_incoming(struct sock *sk, struct sk_buff *skb, | ||
4698 | struct tcphdr *th, int syn_inerr) | ||
4699 | { | ||
4700 | struct tcp_sock *tp = tcp_sk(sk); | ||
4701 | |||
4702 | /* RFC1323: H1. Apply PAWS check first. */ | ||
4703 | if (tcp_fast_parse_options(skb, th, tp) && tp->rx_opt.saw_tstamp && | ||
4704 | tcp_paws_discard(sk, skb)) { | ||
4705 | if (!th->rst) { | ||
4706 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSESTABREJECTED); | ||
4707 | tcp_send_dupack(sk, skb); | ||
4708 | goto discard; | ||
4709 | } | ||
4710 | /* Reset is accepted even if it did not pass PAWS. */ | ||
4711 | } | ||
4712 | |||
4713 | /* Step 1: check sequence number */ | ||
4714 | if (!tcp_sequence(tp, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq)) { | ||
4715 | /* RFC793, page 37: "In all states except SYN-SENT, all reset | ||
4716 | * (RST) segments are validated by checking their SEQ-fields." | ||
4717 | * And page 69: "If an incoming segment is not acceptable, | ||
4718 | * an acknowledgment should be sent in reply (unless the RST | ||
4719 | * bit is set, if so drop the segment and return)". | ||
4720 | */ | ||
4721 | if (!th->rst) | ||
4722 | tcp_send_dupack(sk, skb); | ||
4723 | goto discard; | ||
4724 | } | ||
4725 | |||
4726 | /* Step 2: check RST bit */ | ||
4727 | if (th->rst) { | ||
4728 | tcp_reset(sk); | ||
4729 | goto discard; | ||
4730 | } | ||
4731 | |||
4732 | /* ts_recent update must be made after we are sure that the packet | ||
4733 | * is in window. | ||
4734 | */ | ||
4735 | tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq); | ||
4736 | |||
4737 | /* step 3: check security and precedence [ignored] */ | ||
4738 | |||
4739 | /* step 4: Check for a SYN in window. */ | ||
4740 | if (th->syn && !before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) { | ||
4741 | if (syn_inerr) | ||
4742 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS); | ||
4743 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONSYN); | ||
4744 | tcp_reset(sk); | ||
4745 | return -1; | ||
4746 | } | ||
4747 | |||
4748 | return 1; | ||
4749 | |||
4750 | discard: | ||
4751 | __kfree_skb(skb); | ||
4752 | return 0; | ||
4753 | } | ||
4754 | |||
4694 | /* | 4755 | /* |
4695 | * TCP receive function for the ESTABLISHED state. | 4756 | * TCP receive function for the ESTABLISHED state. |
4696 | * | 4757 | * |
@@ -4718,6 +4779,7 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, | |||
4718 | struct tcphdr *th, unsigned len) | 4779 | struct tcphdr *th, unsigned len) |
4719 | { | 4780 | { |
4720 | struct tcp_sock *tp = tcp_sk(sk); | 4781 | struct tcp_sock *tp = tcp_sk(sk); |
4782 | int res; | ||
4721 | 4783 | ||
4722 | /* | 4784 | /* |
4723 | * Header prediction. | 4785 | * Header prediction. |
@@ -4899,51 +4961,12 @@ slow_path: | |||
4899 | goto csum_error; | 4961 | goto csum_error; |
4900 | 4962 | ||
4901 | /* | 4963 | /* |
4902 | * RFC1323: H1. Apply PAWS check first. | ||
4903 | */ | ||
4904 | if (tcp_fast_parse_options(skb, th, tp) && tp->rx_opt.saw_tstamp && | ||
4905 | tcp_paws_discard(sk, skb)) { | ||
4906 | if (!th->rst) { | ||
4907 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSESTABREJECTED); | ||
4908 | tcp_send_dupack(sk, skb); | ||
4909 | goto discard; | ||
4910 | } | ||
4911 | /* Resets are accepted even if PAWS failed. | ||
4912 | |||
4913 | ts_recent update must be made after we are sure | ||
4914 | that the packet is in window. | ||
4915 | */ | ||
4916 | } | ||
4917 | |||
4918 | /* | ||
4919 | * Standard slow path. | 4964 | * Standard slow path. |
4920 | */ | 4965 | */ |
4921 | 4966 | ||
4922 | if (!tcp_sequence(tp, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq)) { | 4967 | res = tcp_validate_incoming(sk, skb, th, 1); |
4923 | /* RFC793, page 37: "In all states except SYN-SENT, all reset | 4968 | if (res <= 0) |
4924 | * (RST) segments are validated by checking their SEQ-fields." | 4969 | return -res; |
4925 | * And page 69: "If an incoming segment is not acceptable, | ||
4926 | * an acknowledgment should be sent in reply (unless the RST bit | ||
4927 | * is set, if so drop the segment and return)". | ||
4928 | */ | ||
4929 | if (!th->rst) | ||
4930 | tcp_send_dupack(sk, skb); | ||
4931 | goto discard; | ||
4932 | } | ||
4933 | |||
4934 | if (th->rst) { | ||
4935 | tcp_reset(sk); | ||
4936 | goto discard; | ||
4937 | } | ||
4938 | |||
4939 | tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq); | ||
4940 | |||
4941 | if (th->syn && !before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) { | ||
4942 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS); | ||
4943 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONSYN); | ||
4944 | tcp_reset(sk); | ||
4945 | return 1; | ||
4946 | } | ||
4947 | 4970 | ||
4948 | step5: | 4971 | step5: |
4949 | if (th->ack) | 4972 | if (th->ack) |
@@ -5225,6 +5248,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
5225 | struct tcp_sock *tp = tcp_sk(sk); | 5248 | struct tcp_sock *tp = tcp_sk(sk); |
5226 | struct inet_connection_sock *icsk = inet_csk(sk); | 5249 | struct inet_connection_sock *icsk = inet_csk(sk); |
5227 | int queued = 0; | 5250 | int queued = 0; |
5251 | int res; | ||
5228 | 5252 | ||
5229 | tp->rx_opt.saw_tstamp = 0; | 5253 | tp->rx_opt.saw_tstamp = 0; |
5230 | 5254 | ||
@@ -5277,42 +5301,9 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
5277 | return 0; | 5301 | return 0; |
5278 | } | 5302 | } |
5279 | 5303 | ||
5280 | if (tcp_fast_parse_options(skb, th, tp) && tp->rx_opt.saw_tstamp && | 5304 | res = tcp_validate_incoming(sk, skb, th, 0); |
5281 | tcp_paws_discard(sk, skb)) { | 5305 | if (res <= 0) |
5282 | if (!th->rst) { | 5306 | return -res; |
5283 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSESTABREJECTED); | ||
5284 | tcp_send_dupack(sk, skb); | ||
5285 | goto discard; | ||
5286 | } | ||
5287 | /* Reset is accepted even if it did not pass PAWS. */ | ||
5288 | } | ||
5289 | |||
5290 | /* step 1: check sequence number */ | ||
5291 | if (!tcp_sequence(tp, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq)) { | ||
5292 | if (!th->rst) | ||
5293 | tcp_send_dupack(sk, skb); | ||
5294 | goto discard; | ||
5295 | } | ||
5296 | |||
5297 | /* step 2: check RST bit */ | ||
5298 | if (th->rst) { | ||
5299 | tcp_reset(sk); | ||
5300 | goto discard; | ||
5301 | } | ||
5302 | |||
5303 | tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq); | ||
5304 | |||
5305 | /* step 3: check security and precedence [ignored] */ | ||
5306 | |||
5307 | /* step 4: | ||
5308 | * | ||
5309 | * Check for a SYN in window. | ||
5310 | */ | ||
5311 | if (th->syn && !before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) { | ||
5312 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONSYN); | ||
5313 | tcp_reset(sk); | ||
5314 | return 1; | ||
5315 | } | ||
5316 | 5307 | ||
5317 | /* step 5: check the ACK field */ | 5308 | /* step 5: check the ACK field */ |
5318 | if (th->ack) { | 5309 | if (th->ack) { |