aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_input.c
diff options
context:
space:
mode:
authorIlpo Järvinen <ilpo.jarvinen@helsinki.fi>2008-08-23 08:10:12 -0400
committerDavid S. Miller <davem@davemloft.net>2008-08-23 08:10:12 -0400
commitcbe2d128a01315fb4bd55b96cf8b963f5df28ea2 (patch)
treef110e926a365da22bc2d63402b3d7f079a391dd0 /net/ipv4/tcp_input.c
parent23edcc4147ad36f8d55f0eb79c21e245ffb9f211 (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.c147
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 */
4697static 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
4750discard:
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
4948step5: 4971step5:
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) {