TCPCT part 2: (e-g) cleanup incoming cookie transactions
Subsystems (3)
v3 cover TCPCT part 2: (e-g) cleanup incoming cookie transactions
Some portions that were removed during the various part 1 patch splits, then were cut off by the sudden unexpected end of that merge window. [03 Dec 2009] I've restarted the sub-numbering (again).
Therefore, this code has had some earlier review. No comments were received during the past 7+ weeks.
The remainder of the original part 2 will be merged with part 3.
These patches are against the current linux-2.6 tree.
PATCH v3 1/3 TCPCT part 2e: accept SYNACK data
When accompanied by cookie option, Initiator (client) queues incoming SYNACK transaction data.
This is a straightforward re-implementation of an earlier (year-old) patch that no longer applies cleanly, with permission of the original author (Adam Langley). The patch was previously reviewed:
http://thread.gmane.org/gmane.linux.network/102586
This function will also be used in subsequent patches that implement additional features.
Requires:
TCPCT part 1g: Responder Cookie => Initiator
net: tcp_header_len_th and tcp_option_len_th
--- net/ipv4/tcp_input.c | 26 +++++++++++++++++++++++++- 1 files changed, 25 insertions(+), 1 deletions(-)
net/ipv4/tcp_input.c +25 -1
@@ -5395,6 +5395,12 @@ discard:return 0 ; } +/* +* Returns: +* +1 on reset, +* 0 success and/or SYNACK data, +* -1 on discard. +*/ static int tcp_rcv_synsent_state_process (struct sock *sk,struct sk_buff *skb,struct tcphdr *th) {
@@ -5403,6 +5409,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,struct tcp_sock *tp =tcp_sk (sk);struct tcp_cookie_values *cvp = tp->cookie_values;int saved_clamp = tp->rx_opt.mss_clamp; +int queued =0 ;tcp_parse_options (skb, &tp->rx_opt, &hash_location,0 );
@@ -5509,6 +5516,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, -TCPOLEN_COOKIE_BASE ;int cookie_pair_size = cookie_size + cvp->cookie_desired; +int tcp_header_len =tcp_header_len_th (th);/* A cookie extension option was sent and returned. * Note that each incoming SYNACK replaces the
@@ -5524,6 +5532,19 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, hash_location, cookie_size); cvp->cookie_pair_size = cookie_pair_size; } + + queued = skb->len - tcp_header_len; +if (queued >0 ) { +/* Queue incoming transaction data. */ +__skb_pull (skb, tcp_header_len); +__skb_queue_tail (&sk->sk_receive_queue, skb); +skb_set_owner_r (skb, sk); + sk->sk_data_ready (sk,0 ); + cvp->s_data_in =1 ;/* true */ + tp->rcv_nxt =TCP_SKB_CB (skb)->end_seq; + tp->rcv_wup =TCP_SKB_CB (skb)->end_seq; + tp->copied_seq =TCP_SKB_CB (skb)->seq +1 ; + } }smp_mb ();
@@ -5577,11 +5598,14 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, TCP_DELACK_MAX, TCP_RTO_MAX); discard: -__kfree_skb (skb); +if (queued <=0 ) +__kfree_skb (skb);return 0 ; }else {tcp_send_ack (sk); } +if (queued >0 ) +return 0 ;return -1 ; }
Signature · 1 line
1.6.3.3
PATCH v3 2/3 TCPCT part 2f: cleanup tcp_parse_options
In reply to William Allen SimpsonSplit switch, shift cases to the left, fix most lines beyond column 80.
Prepare (future) error return.
Requires:
TCPCT part 1g: Responder Cookie => Initiator
net: tcp_header_len_th and tcp_option_len_th
--- include/net/tcp.h | 3 +- net/ipv4/syncookies.c | 5 +- net/ipv4/tcp_input.c | 217 ++++++++++++++++++++++++++-------------------- net/ipv4/tcp_ipv4.c | 10 ++- net/ipv4/tcp_minisocks.c | 14 ++- net/ipv6/syncookies.c | 5 +- net/ipv6/tcp_ipv6.c | 6 +- 7 files changed, 154 insertions(+), 106 deletions(-)
include/net/tcp.h +2 -1
@@ -403,7 +403,8 @@ extern int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, size_t len, int nonblock, int flags, int *addr_len); -extern void tcp_parse_options (struct sk_buff *skb, +extern int tcp_parse_options (struct sk_buff *skb, +const struct tcphdr *th,struct tcp_options_received *opt_rx,u8 **hvpp,int estab);
net/ipv4/syncookies.c +4 -1
@@ -254,6 +254,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, struct ip_options *opt) {struct tcp_options_received tcp_opt; +int parsed;u8 *hash_location;struct inet_request_sock *ireq;struct tcp_request_sock *treq;
@@ -279,7 +280,9 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,/* check for timestamp cookie support */ memset (&tcp_opt,0 ,sizeof (tcp_opt)); -tcp_parse_options (skb, &tcp_opt, &hash_location,0 ); + parsed =tcp_parse_options (skb, th, &tcp_opt, &hash_location,0 ); +if (parsed <0 ) + goto out;if (tcp_opt.saw_tstamp)cookie_check_timestamp (&tcp_opt);
net/ipv4/tcp_input.c +122 -95
269 lines not on this page · raw message
net/ipv4/tcp_ipv4.c +7 -3
@@ -1215,6 +1215,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) {struct tcp_extend_values tmp_ext;struct tcp_options_received tmp_opt; +int parsed;u8 *hash_location;struct request_sock *req;struct inet_request_sock *ireq;
@@ -1265,7 +1266,10 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)tcp_clear_options (&tmp_opt); tmp_opt.mss_clamp =TCP_MSS_DEFAULT ; tmp_opt.user_mss = tp->rx_opt.user_mss; -tcp_parse_options (skb, &tmp_opt, &hash_location,0 ); + parsed =tcp_parse_options (skb,tcp_hdr (skb), &tmp_opt, &hash_location, +0 ); +if (parsed <0 ) + goto drop_and_free; if (tmp_opt.cookie_plus > 0 && tmp_opt.saw_tstamp &&
@@ -1278,7 +1282,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)int l = tmp_opt.cookie_plus -TCPOLEN_COOKIE_BASE ;if (tcp_cookie_generator (&tmp_ext.cookie_bakery[0 ]) !=0 ) - goto drop_and_release; + goto drop_and_free;/* Secret recipe starts with IP addresses */ *mess++ ^= daddr;
@@ -1299,7 +1303,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) tmp_ext.cookie_out_never =1 ;/* true */ tmp_ext.cookie_plus =0 ; }else { - goto drop_and_release; + goto drop_and_free; } tmp_ext.cookie_in_always = tp->rx_opt.cookie_in_always;
net/ipv4/tcp_minisocks.c +10 -4
@@ -97,9 +97,12 @@ tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb, tmp_opt.saw_tstamp =0 ;if (th->doff > (sizeof (*th) >>2 ) && tcptw->tw_ts_recent_stamp) { -tcp_parse_options (skb, &tmp_opt, &hash_location,0 ); +int parsed =tcp_parse_options (skb, th, &tmp_opt, + &hash_location,0 ); -if (tmp_opt.saw_tstamp) { +if (parsed <0 ) { + paws_reject =1 ;/* true */ + }else if (tmp_opt.saw_tstamp) { tmp_opt.ts_recent = tcptw->tw_ts_recent; tmp_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp; paws_reject =tcp_paws_reject (&tmp_opt, th->rst);
@@ -528,9 +531,12 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, tmp_opt.saw_tstamp =0 ;if (th->doff > (sizeof (struct tcphdr )>>2 )) { -tcp_parse_options (skb, &tmp_opt, &hash_location,0 ); +int parsed =tcp_parse_options (skb, th, &tmp_opt, + &hash_location,0 ); -if (tmp_opt.saw_tstamp) { +if (parsed <0 ) { + paws_reject =1 ;/* true */ + }else if (tmp_opt.saw_tstamp) { tmp_opt.ts_recent = req->ts_recent;/* We do not store true stamp, but it is not required, * it can be estimated (approximately)
net/ipv6/syncookies.c +4 -1
@@ -160,6 +160,7 @@ static inline int cookie_check(struct sk_buff *skb, __u32 cookie)struct sock *cookie_v6_check (struct sock *sk,struct sk_buff *skb) {struct tcp_options_received tcp_opt; +int parsed;u8 *hash_location;struct inet_request_sock *ireq;struct inet6_request_sock *ireq6;
@@ -187,7 +188,9 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)/* check for timestamp cookie support */ memset (&tcp_opt,0 ,sizeof (tcp_opt)); -tcp_parse_options (skb, &tcp_opt, &hash_location,0 ); + parsed =tcp_parse_options (skb, th, &tcp_opt, &hash_location,0 ); +if (parsed <0 ) + goto out;if (tcp_opt.saw_tstamp)cookie_check_timestamp (&tcp_opt);
net/ipv6/tcp_ipv6.c +5 -1
@@ -1164,6 +1164,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) {struct tcp_extend_values tmp_ext;struct tcp_options_received tmp_opt; +int parsed;u8 *hash_location;struct request_sock *req;struct inet6_request_sock *treq;
@@ -1207,7 +1208,10 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)tcp_clear_options (&tmp_opt); tmp_opt.mss_clamp =IPV6_MIN_MTU -sizeof (struct tcphdr ) -sizeof (struct ipv6hdr ); tmp_opt.user_mss = tp->rx_opt.user_mss; -tcp_parse_options (skb, &tmp_opt, &hash_location,0 ); + parsed =tcp_parse_options (skb,tcp_hdr (skb), &tmp_opt, &hash_location, +0 ); +if (parsed <0 ) + goto drop_and_free; if (tmp_opt.cookie_plus > 0 && tmp_opt.saw_tstamp &&
Signature · 1 line
1.6.3.3
PATCH v3 3/3 TCPCT part 2g: parse cookie pair and 64-bit timestamp
In reply to William Allen SimpsonParse cookie pair extended option (previously defined).
Define and parse 64-bit timestamp extended option (and minor cleanup). However, only 32-bits are used at this time.
Requires:
net: tcp_header_len_th and tcp_option_len_th
TCPCT part 2f: cleanup tcp_parse_options
--- include/linux/tcp.h | 10 ++++- include/net/tcp.h | 45 +++++++++--------- net/ipv4/tcp_input.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 148 insertions(+), 33 deletions(-)
include/linux/tcp.h +9 -1
@@ -260,13 +260,21 @@ struct tcp_options_received {u8 num_sacks;/* Number of SACK blocks */ u16 user_mss;/* mss requested by user in ioctl */ u16 mss_clamp;/* Maximal mss, negotiated at connection setup */ + +/* When the options are extended beyond the maximum 40 bytes, +* then this holds the additional data offset (in bytes, +* the least significant 2 bits are always zero). +*/ + u16 extended:14, /* Up to 13 (40/3) by 255 by 4 bytes */ + saw_tstamp64:1, /* Seen on recent packet */ + tstamp64_ok:1; /* Verified with cookie pair */ };static inline void tcp_clear_options (struct tcp_options_received *rx_opt) { rx_opt->tstamp_ok = rx_opt->sack_ok =0 ; rx_opt->wscale_ok = rx_opt->snd_wscale =0 ; - rx_opt->cookie_plus =0 ; + rx_opt->tstamp64_ok =0 ; }/* This is the max number of SACKS that we'll generate and process. It's safe
include/net/tcp.h +23 -22
62 lines not on this page · raw message
net/ipv4/tcp_input.c +116 -10
204 lines not on this page · raw message
Signature · 1 line
1.6.3.3