diff options
| author | William Allen Simpson <william.allen.simpson@gmail.com> | 2009-12-02 13:17:05 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2009-12-03 01:07:25 -0500 |
| commit | 435cf559f02ea3a3159eb316f97dc88bdebe9432 (patch) | |
| tree | 0b2a7e9110c46b193176b0a59fe5689eae7c18f3 /net/ipv4/tcp_minisocks.c | |
| parent | 519855c508b9a17878c0977a3cdefc09b59b30df (diff) | |
TCPCT part 1d: define TCP cookie option, extend existing struct's
Data structures are carefully composed to require minimal additions.
For example, the struct tcp_options_received cookie_plus variable fits
between existing 16-bit and 8-bit variables, requiring no additional
space (taking alignment into consideration). There are no additions to
tcp_request_sock, and only 1 pointer in tcp_sock.
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
The principle difference is using a TCP option to carry the cookie nonce,
instead of a user configured offset in the data. This is more flexible and
less subject to user configuration error. Such a cookie option has been
suggested for many years, and is also useful without SYN data, allowing
several related concepts to use the same extension option.
"Re: SYN floods (was: does history repeat itself?)", September 9, 1996.
http://www.merit.net/mail.archives/nanog/1996-09/msg00235.html
"Re: what a new TCP header might look like", May 12, 1998.
ftp://ftp.isi.edu/end2end/end2end-interest-1998.mail
These functions will also be used in subsequent patches that implement
additional features.
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
Signed-off-by: William.Allen.Simpson@gmail.com
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp_minisocks.c')
| -rw-r--r-- | net/ipv4/tcp_minisocks.c | 46 |
1 files changed, 38 insertions, 8 deletions
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index d3f6bbfc76f0..96852af43ca7 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c | |||
| @@ -383,14 +383,43 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, | |||
| 383 | const struct inet_request_sock *ireq = inet_rsk(req); | 383 | const struct inet_request_sock *ireq = inet_rsk(req); |
| 384 | struct tcp_request_sock *treq = tcp_rsk(req); | 384 | struct tcp_request_sock *treq = tcp_rsk(req); |
| 385 | struct inet_connection_sock *newicsk = inet_csk(newsk); | 385 | struct inet_connection_sock *newicsk = inet_csk(newsk); |
| 386 | struct tcp_sock *newtp; | 386 | struct tcp_sock *newtp = tcp_sk(newsk); |
| 387 | struct tcp_sock *oldtp = tcp_sk(sk); | ||
| 388 | struct tcp_cookie_values *oldcvp = oldtp->cookie_values; | ||
| 389 | |||
| 390 | /* TCP Cookie Transactions require space for the cookie pair, | ||
| 391 | * as it differs for each connection. There is no need to | ||
| 392 | * copy any s_data_payload stored at the original socket. | ||
| 393 | * Failure will prevent resuming the connection. | ||
| 394 | * | ||
| 395 | * Presumed copied, in order of appearance: | ||
| 396 | * cookie_in_always, cookie_out_never | ||
| 397 | */ | ||
| 398 | if (oldcvp != NULL) { | ||
| 399 | struct tcp_cookie_values *newcvp = | ||
| 400 | kzalloc(sizeof(*newtp->cookie_values), | ||
| 401 | GFP_ATOMIC); | ||
| 402 | |||
| 403 | if (newcvp != NULL) { | ||
| 404 | kref_init(&newcvp->kref); | ||
| 405 | newcvp->cookie_desired = | ||
| 406 | oldcvp->cookie_desired; | ||
| 407 | newtp->cookie_values = newcvp; | ||
| 408 | } else { | ||
| 409 | /* Not Yet Implemented */ | ||
| 410 | newtp->cookie_values = NULL; | ||
| 411 | } | ||
| 412 | } | ||
| 387 | 413 | ||
| 388 | /* Now setup tcp_sock */ | 414 | /* Now setup tcp_sock */ |
| 389 | newtp = tcp_sk(newsk); | ||
| 390 | newtp->pred_flags = 0; | 415 | newtp->pred_flags = 0; |
| 391 | newtp->rcv_wup = newtp->copied_seq = newtp->rcv_nxt = treq->rcv_isn + 1; | 416 | |
| 392 | newtp->snd_sml = newtp->snd_una = newtp->snd_nxt = treq->snt_isn + 1; | 417 | newtp->rcv_wup = newtp->copied_seq = |
| 393 | newtp->snd_up = treq->snt_isn + 1; | 418 | newtp->rcv_nxt = treq->rcv_isn + 1; |
| 419 | |||
| 420 | newtp->snd_sml = newtp->snd_una = | ||
| 421 | newtp->snd_nxt = newtp->snd_up = | ||
| 422 | treq->snt_isn + 1 + tcp_s_data_size(oldtp); | ||
| 394 | 423 | ||
| 395 | tcp_prequeue_init(newtp); | 424 | tcp_prequeue_init(newtp); |
| 396 | 425 | ||
| @@ -423,8 +452,8 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, | |||
| 423 | tcp_set_ca_state(newsk, TCP_CA_Open); | 452 | tcp_set_ca_state(newsk, TCP_CA_Open); |
| 424 | tcp_init_xmit_timers(newsk); | 453 | tcp_init_xmit_timers(newsk); |
| 425 | skb_queue_head_init(&newtp->out_of_order_queue); | 454 | skb_queue_head_init(&newtp->out_of_order_queue); |
| 426 | newtp->write_seq = treq->snt_isn + 1; | 455 | newtp->write_seq = newtp->pushed_seq = |
| 427 | newtp->pushed_seq = newtp->write_seq; | 456 | treq->snt_isn + 1 + tcp_s_data_size(oldtp); |
| 428 | 457 | ||
| 429 | newtp->rx_opt.saw_tstamp = 0; | 458 | newtp->rx_opt.saw_tstamp = 0; |
| 430 | 459 | ||
| @@ -590,7 +619,8 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, | |||
| 590 | * Invalid ACK: reset will be sent by listening socket | 619 | * Invalid ACK: reset will be sent by listening socket |
| 591 | */ | 620 | */ |
| 592 | if ((flg & TCP_FLAG_ACK) && | 621 | if ((flg & TCP_FLAG_ACK) && |
| 593 | (TCP_SKB_CB(skb)->ack_seq != tcp_rsk(req)->snt_isn + 1)) | 622 | (TCP_SKB_CB(skb)->ack_seq != |
| 623 | tcp_rsk(req)->snt_isn + 1 + tcp_s_data_size(tcp_sk(sk)))) | ||
| 594 | return sk; | 624 | return sk; |
| 595 | 625 | ||
| 596 | /* Also, it would be not so bad idea to check rcv_tsecr, which | 626 | /* Also, it would be not so bad idea to check rcv_tsecr, which |
