aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_input.c
diff options
context:
space:
mode:
authorWilliam Allen Simpson <william.allen.simpson@gmail.com>2009-12-02 13:25:27 -0500
committerDavid S. Miller <davem@davemloft.net>2009-12-03 01:07:26 -0500
commit4957faade11b3a278c3b3cade3411ddc20afa791 (patch)
tree57f994bab69353baf5f554b89cf9107c3372ecce /net/ipv4/tcp_input.c
parentbd0388ae77075026d6a9f9eb6026dfd1d52ce0e9 (diff)
TCPCT part 1g: Responder Cookie => Initiator
Parse incoming TCP_COOKIE option(s). Calculate <SYN,ACK> TCP_COOKIE option. Send optional <SYN,ACK> data. This is a significantly revised implementation of an earlier (year-old) patch that no longer applies cleanly, with permission of the original author (Adam Langley): http://thread.gmane.org/gmane.linux.network/102586 Requires: TCPCT part 1a: add request_values parameter for sending SYNACK TCPCT part 1b: generate Responder Cookie secret TCPCT part 1c: sysctl_tcp_cookie_size, socket option TCP_COOKIE_TRANSACTIONS TCPCT part 1d: define TCP cookie option, extend existing struct's TCPCT part 1e: implement socket option TCP_COOKIE_TRANSACTIONS TCPCT part 1f: Initiator Cookie => Responder Signed-off-by: William.Allen.Simpson@gmail.com Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp_input.c')
-rw-r--r--net/ipv4/tcp_input.c75
1 files changed, 65 insertions, 10 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index be166e0e11c5..57ae96a04220 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -3698,7 +3698,7 @@ old_ack:
3698 * the fast version below fails. 3698 * the fast version below fails.
3699 */ 3699 */
3700void tcp_parse_options(struct sk_buff *skb, struct tcp_options_received *opt_rx, 3700void tcp_parse_options(struct sk_buff *skb, struct tcp_options_received *opt_rx,
3701 int estab, struct dst_entry *dst) 3701 u8 **hvpp, int estab, struct dst_entry *dst)
3702{ 3702{
3703 unsigned char *ptr; 3703 unsigned char *ptr;
3704 struct tcphdr *th = tcp_hdr(skb); 3704 struct tcphdr *th = tcp_hdr(skb);
@@ -3785,7 +3785,30 @@ void tcp_parse_options(struct sk_buff *skb, struct tcp_options_received *opt_rx,
3785 */ 3785 */
3786 break; 3786 break;
3787#endif 3787#endif
3788 } 3788 case TCPOPT_COOKIE:
3789 /* This option is variable length.
3790 */
3791 switch (opsize) {
3792 case TCPOLEN_COOKIE_BASE:
3793 /* not yet implemented */
3794 break;
3795 case TCPOLEN_COOKIE_PAIR:
3796 /* not yet implemented */
3797 break;
3798 case TCPOLEN_COOKIE_MIN+0:
3799 case TCPOLEN_COOKIE_MIN+2:
3800 case TCPOLEN_COOKIE_MIN+4:
3801 case TCPOLEN_COOKIE_MIN+6:
3802 case TCPOLEN_COOKIE_MAX:
3803 /* 16-bit multiple */
3804 opt_rx->cookie_plus = opsize;
3805 *hvpp = ptr;
3806 default:
3807 /* ignore option */
3808 break;
3809 };
3810 break;
3811 };
3789 3812
3790 ptr += opsize-2; 3813 ptr += opsize-2;
3791 length -= opsize; 3814 length -= opsize;
@@ -3813,17 +3836,20 @@ static int tcp_parse_aligned_timestamp(struct tcp_sock *tp, struct tcphdr *th)
3813 * If it is wrong it falls back on tcp_parse_options(). 3836 * If it is wrong it falls back on tcp_parse_options().
3814 */ 3837 */
3815static int tcp_fast_parse_options(struct sk_buff *skb, struct tcphdr *th, 3838static int tcp_fast_parse_options(struct sk_buff *skb, struct tcphdr *th,
3816 struct tcp_sock *tp) 3839 struct tcp_sock *tp, u8 **hvpp)
3817{ 3840{
3818 if (th->doff == sizeof(struct tcphdr) >> 2) { 3841 /* In the spirit of fast parsing, compare doff directly to constant
3842 * values. Because equality is used, short doff can be ignored here.
3843 */
3844 if (th->doff == (sizeof(*th) / 4)) {
3819 tp->rx_opt.saw_tstamp = 0; 3845 tp->rx_opt.saw_tstamp = 0;
3820 return 0; 3846 return 0;
3821 } else if (tp->rx_opt.tstamp_ok && 3847 } else if (tp->rx_opt.tstamp_ok &&
3822 th->doff == (sizeof(struct tcphdr)>>2)+(TCPOLEN_TSTAMP_ALIGNED>>2)) { 3848 th->doff == ((sizeof(*th) + TCPOLEN_TSTAMP_ALIGNED) / 4)) {
3823 if (tcp_parse_aligned_timestamp(tp, th)) 3849 if (tcp_parse_aligned_timestamp(tp, th))
3824 return 1; 3850 return 1;
3825 } 3851 }
3826 tcp_parse_options(skb, &tp->rx_opt, 1, NULL); 3852 tcp_parse_options(skb, &tp->rx_opt, hvpp, 1, NULL);
3827 return 1; 3853 return 1;
3828} 3854}
3829 3855
@@ -5077,10 +5103,12 @@ out:
5077static int tcp_validate_incoming(struct sock *sk, struct sk_buff *skb, 5103static int tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,
5078 struct tcphdr *th, int syn_inerr) 5104 struct tcphdr *th, int syn_inerr)
5079{ 5105{
5106 u8 *hash_location;
5080 struct tcp_sock *tp = tcp_sk(sk); 5107 struct tcp_sock *tp = tcp_sk(sk);
5081 5108
5082 /* RFC1323: H1. Apply PAWS check first. */ 5109 /* RFC1323: H1. Apply PAWS check first. */
5083 if (tcp_fast_parse_options(skb, th, tp) && tp->rx_opt.saw_tstamp && 5110 if (tcp_fast_parse_options(skb, th, tp, &hash_location) &&
5111 tp->rx_opt.saw_tstamp &&
5084 tcp_paws_discard(sk, skb)) { 5112 tcp_paws_discard(sk, skb)) {
5085 if (!th->rst) { 5113 if (!th->rst) {
5086 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSESTABREJECTED); 5114 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSESTABREJECTED);
@@ -5368,12 +5396,14 @@ discard:
5368static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, 5396static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
5369 struct tcphdr *th, unsigned len) 5397 struct tcphdr *th, unsigned len)
5370{ 5398{
5371 struct tcp_sock *tp = tcp_sk(sk); 5399 u8 *hash_location;
5372 struct inet_connection_sock *icsk = inet_csk(sk); 5400 struct inet_connection_sock *icsk = inet_csk(sk);
5373 int saved_clamp = tp->rx_opt.mss_clamp; 5401 struct tcp_sock *tp = tcp_sk(sk);
5374 struct dst_entry *dst = __sk_dst_get(sk); 5402 struct dst_entry *dst = __sk_dst_get(sk);
5403 struct tcp_cookie_values *cvp = tp->cookie_values;
5404 int saved_clamp = tp->rx_opt.mss_clamp;
5375 5405
5376 tcp_parse_options(skb, &tp->rx_opt, 0, dst); 5406 tcp_parse_options(skb, &tp->rx_opt, &hash_location, 0, dst);
5377 5407
5378 if (th->ack) { 5408 if (th->ack) {
5379 /* rfc793: 5409 /* rfc793:
@@ -5470,6 +5500,31 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
5470 * Change state from SYN-SENT only after copied_seq 5500 * Change state from SYN-SENT only after copied_seq
5471 * is initialized. */ 5501 * is initialized. */
5472 tp->copied_seq = tp->rcv_nxt; 5502 tp->copied_seq = tp->rcv_nxt;
5503
5504 if (cvp != NULL &&
5505 cvp->cookie_pair_size > 0 &&
5506 tp->rx_opt.cookie_plus > 0) {
5507 int cookie_size = tp->rx_opt.cookie_plus
5508 - TCPOLEN_COOKIE_BASE;
5509 int cookie_pair_size = cookie_size
5510 + cvp->cookie_desired;
5511
5512 /* A cookie extension option was sent and returned.
5513 * Note that each incoming SYNACK replaces the
5514 * Responder cookie. The initial exchange is most
5515 * fragile, as protection against spoofing relies
5516 * entirely upon the sequence and timestamp (above).
5517 * This replacement strategy allows the correct pair to
5518 * pass through, while any others will be filtered via
5519 * Responder verification later.
5520 */
5521 if (sizeof(cvp->cookie_pair) >= cookie_pair_size) {
5522 memcpy(&cvp->cookie_pair[cvp->cookie_desired],
5523 hash_location, cookie_size);
5524 cvp->cookie_pair_size = cookie_pair_size;
5525 }
5526 }
5527
5473 smp_mb(); 5528 smp_mb();
5474 tcp_set_state(sk, TCP_ESTABLISHED); 5529 tcp_set_state(sk, TCP_ESTABLISHED);
5475 5530