TCPCT part 1: cookie option exchange
Subsystems (5)
v8 cover TCPCT part 1: cookie option exchange
Initiator Responder
========= =========
<SYN> ->
Cookie
<- <SYN,ACK(SYN)>
Cookie
optional dataV8:
Updated to patch cleanly with recent large commits.
Compiled and lightly tested. Awaiting performance testing results.
Cosmetic changes, based on review by David Miller.
Merged some part 2 code to relieve ennui.
V7:
Updated to patch cleanly with recent large commits.
Compiled and lightly tested. Awaiting performance testing results.
Revised RCU spinlocks, based on review by Eric and Joe.
Trivial savings of 2 if tests, based on review by Joe.
Cosmetic changes to comment blocks, based on review by Eric.
Processing optional SYNACK data removed until later.
V6:
The new TCP_MSS_* symbols are now in an entirely separate patch. Applied.
Updated and reorganized to split the code base into several pieces, as requested by Eric. No significant changes.
...
Re: [net-next-2.6 PATCH v8 1/7] TCPCT part 1a: add request_values parameter for sending SYNACK
Add optional function parameters associated with sending SYNACK. These parameters are not needed after sending SYNACK, and are not used for retransmission. Avoids extending struct tcp_request_sock, and avoids allocating kernel memory.
Also affects DCCP as it uses common struct request_sock_ops, but this parameter is currently reserved for future use.
--- include/net/request_sock.h | 8 +++++++- include/net/tcp.h | 3 ++- net/dccp/ipv4.c | 5 +++-- net/dccp/ipv6.c | 5 +++-- net/dccp/minisocks.c | 2 +- net/ipv4/inet_connection_sock.c | 2 +- net/ipv4/tcp_ipv4.c | 18 ++++++++++-------- net/ipv4/tcp_minisocks.c | 2 +- net/ipv4/tcp_output.c | 3 ++- net/ipv6/tcp_ipv6.c | 27 ++++++++++++--------------- 10 files changed, 42 insertions(+), 33 deletions(-)
include/net/request_sock.h +7 -1
@@ -27,13 +27,19 @@ struct sk_buff;struct dst_entry ;struct proto ; +/* empty to "strongly type" an otherwise void parameter. +*/ +struct request_values { +}; +struct request_sock_ops {int family;int obj_size;struct kmem_cache *slab;char *slab_name;int (*rtx_syn_ack)(struct sock *sk, -struct request_sock *req); +struct request_sock *req, +struct request_values *rvp);void (*send_ack)(struct sock *sk,struct sk_buff *skb,struct request_sock *req); void (*send_reset)(struct sock *sk,
include/net/tcp.h +2 -1
@@ -440,7 +440,8 @@ extern int tcp_connect(struct sock *sk);extern struct sk_buff *tcp_make_synack (struct sock *sk,struct dst_entry *dst, -struct request_sock *req); +struct request_sock *req, +struct request_values *rvp);extern int tcp_disconnect (struct sock *sk,int flags);
net/dccp/ipv4.c +3 -2
@@ -477,7 +477,8 @@ static struct dst_entry* dccp_v4_route_skb(struct net *net, struct sock *sk,return &rt->u.dst; } -static int dccp_v4_send_response (struct sock *sk,struct request_sock *req) +static int dccp_v4_send_response (struct sock *sk,struct request_sock *req, +struct request_values *rv_unused) {int err =-1 ;struct sk_buff *skb;
@@ -626,7 +627,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) dreq->dreq_iss =dccp_v4_init_sequence (skb); dreq->dreq_service = service; -if (dccp_v4_send_response (sk, req)) +if (dccp_v4_send_response (sk, req,NULL )) goto drop_and_free;inet_csk_reqsk_queue_hash_add (sk, req,DCCP_TIMEOUT_INIT );
net/dccp/ipv6.c +3 -2
@@ -241,7 +241,8 @@ out: } -static int dccp_v6_send_response (struct sock *sk,struct request_sock *req) +static int dccp_v6_send_response (struct sock *sk,struct request_sock *req, +struct request_values *rv_unused) {struct inet6_request_sock *ireq6 =inet6_rsk (req);struct ipv6_pinfo *np =inet6_sk (sk);
@@ -468,7 +469,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb) dreq->dreq_iss =dccp_v6_init_sequence (skb); dreq->dreq_service = service; -if (dccp_v6_send_response (sk, req)) +if (dccp_v6_send_response (sk, req,NULL )) goto drop_and_free;inet6_csk_reqsk_queue_hash_add (sk, req,DCCP_TIMEOUT_INIT );
net/dccp/minisocks.c +1 -1
@@ -184,7 +184,7 @@ struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,* counter (backoff, monitored by dccp_response_timer). */ req->retrans++; - req->rsk_ops->rtx_syn_ack (sk, req); + req->rsk_ops->rtx_syn_ack (sk, req,NULL ); }/* Network Duplicate, discard packet */ return NULL ;
net/ipv4/inet_connection_sock.c +1 -1
@@ -531,7 +531,7 @@ void inet_csk_reqsk_queue_prune(struct sock *parent, &expire, &resend);if (!expire && (!resend || - !req->rsk_ops->rtx_syn_ack (parent, req) || + !req->rsk_ops->rtx_syn_ack (parent, req,NULL ) ||inet_rsk (req)->acked)) {unsigned long timeo;
net/ipv4/tcp_ipv4.c +10 -8
@@ -742,8 +742,9 @@ static void tcp_v4_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,* This still operates on a request_sock only, not on a big * socket. */ -static int __tcp_v4_send_synack (struct sock *sk,struct request_sock *req, -struct dst_entry *dst) +static int __tcp_v4_send_synack (struct sock *sk,struct dst_entry *dst, +struct request_sock *req, +struct request_values *rvp) {const struct inet_request_sock *ireq =inet_rsk (req);int err =-1 ;
@@ -753,7 +754,7 @@ static int __tcp_v4_send_synack(struct sock *sk, struct request_sock *req,if (!dst && (dst =inet_csk_route_req (sk, req)) ==NULL )return -1 ; - skb =tcp_make_synack (sk, dst, req); + skb =tcp_make_synack (sk, dst, req, rvp);if (skb) {struct tcphdr *th =tcp_hdr (skb);
@@ -774,9 +775,10 @@ static int __tcp_v4_send_synack(struct sock *sk, struct request_sock *req,return err; } -static int tcp_v4_send_synack (struct sock *sk,struct request_sock *req) +static int tcp_v4_send_synack (struct sock *sk,struct request_sock *req, +struct request_values *rvp) { -return __tcp_v4_send_synack (sk, req,NULL ); +return __tcp_v4_send_synack (sk,NULL , req, rvp); }/*
@@ -1211,13 +1213,13 @@ static struct timewait_sock_ops tcp_timewait_sock_ops = {int tcp_v4_conn_request (struct sock *sk,struct sk_buff *skb) { -struct inet_request_sock *ireq;struct tcp_options_received tmp_opt;struct request_sock *req; +struct inet_request_sock *ireq; +struct dst_entry *dst =NULL ;__be32 saddr =ip_hdr (skb)->saddr;__be32 daddr =ip_hdr (skb)->daddr;__u32 isn =TCP_SKB_CB (skb)->when; -struct dst_entry *dst =NULL ;#ifdef CONFIG_SYN_COOKIES int want_cookie =0 ;#else
@@ -1337,7 +1339,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) }tcp_rsk (req)->snt_isn = isn; -if (__tcp_v4_send_synack (sk, req, dst) || want_cookie) +if (__tcp_v4_send_synack (sk, dst, req,NULL ) || want_cookie) goto drop_and_free;inet_csk_reqsk_queue_hash_add (sk, req,TCP_TIMEOUT_INIT );
net/ipv4/tcp_minisocks.c +1 -1
@@ -531,7 +531,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,* Enforce "SYN-ACK" according to figure 8, figure 6 * of RFC793, fixed by RFC1122. */ - req->rsk_ops->rtx_syn_ack (sk, req); + req->rsk_ops->rtx_syn_ack (sk, req,NULL );return NULL ; }
net/ipv4/tcp_output.c +2 -1
@@ -2224,7 +2224,8 @@ int tcp_send_synack(struct sock *sk)/* Prepare a SYN-ACK. */ struct sk_buff *tcp_make_synack (struct sock *sk,struct dst_entry *dst, -struct request_sock *req) +struct request_sock *req, +struct request_values *rvp) {struct inet_request_sock *ireq =inet_rsk (req);struct tcp_sock *tp =tcp_sk (sk);
net/ipv6/tcp_ipv6.c +12 -15
@@ -461,7 +461,8 @@ out: } -static int tcp_v6_send_synack (struct sock *sk,struct request_sock *req) +static int tcp_v6_send_synack (struct sock *sk,struct request_sock *req, +struct request_values *rvp) {struct inet6_request_sock *treq =inet6_rsk (req);struct ipv6_pinfo *np =inet6_sk (sk);
@@ -499,7 +500,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req)if ((err =xfrm_lookup (sock_net (sk), &dst, &fl, sk,0 )) <0 ) goto done; - skb =tcp_make_synack (sk, dst, req); + skb =tcp_make_synack (sk, dst, req, rvp);if (skb) {struct tcphdr *th =tcp_hdr (skb);
@@ -1161,13 +1162,13 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)*/ static int tcp_v6_conn_request (struct sock *sk,struct sk_buff *skb) { +struct tcp_options_received tmp_opt; +struct request_sock *req;struct inet6_request_sock *treq;struct ipv6_pinfo *np =inet6_sk (sk); -struct tcp_options_received tmp_opt;struct tcp_sock *tp =tcp_sk (sk); -struct request_sock *req =NULL ; -__u32 isn =TCP_SKB_CB (skb)->when;struct dst_entry *dst =__sk_dst_get (sk); +__u32 isn =TCP_SKB_CB (skb)->when;#ifdef CONFIG_SYN_COOKIES int want_cookie =0 ;#else
@@ -1239,23 +1240,19 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) isn =tcp_v6_init_sequence (skb); } -tcp_rsk (req)->snt_isn = isn;security_inet_conn_request (sk, skb, req); -if (tcp_v6_send_synack (sk, req)) - goto drop; +if (tcp_v6_send_synack (sk, req,NULL ) || want_cookie) + goto drop_and_free; -if (!want_cookie) { -inet6_csk_reqsk_queue_hash_add (sk, req,TCP_TIMEOUT_INIT ); -return 0 ; - } +inet6_csk_reqsk_queue_hash_add (sk, req,TCP_TIMEOUT_INIT ); +return 0 ; +drop_and_free: +reqsk_free (req); drop: -if (req) -reqsk_free (req); -return 0 ;/* don't send reset */ }
Signature · 1 line
1.6.3.3
Re: [net-next-2.6 PATCH v8 2/7] TCPCT part 1b: generate Responder Cookie secret
In reply to William Allen SimpsonDefine (missing) hash message size for SHA1.
Define hashing size constants specific to TCP cookies.
Add new function: tcp_cookie_generator().
Maintain global secret values for tcp_cookie_generator().
This is a significantly revised implementation of earlier (15-year-old) Photuris [RFC-2522] code for the KA9Q cooperative multitasking platform.
Linux RCU technique appears to be well-suited to this application, though neither of the circular queue items are freed.
These functions will also be used in subsequent patches that implement additional features.
--- include/linux/cryptohash.h | 1 + include/net/tcp.h | 8 +++ net/ipv4/tcp.c | 140 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+), 0 deletions(-)
include/linux/cryptohash.h +1 -0
@@ -2,6 +2,7 @@#define __CRYPTOHASH_H#define SHA_DIGEST_WORDS 5 +#define SHA_MESSAGE_BYTES (512 /*bits*/ / 8)#define SHA_WORKSPACE_WORDS 80void sha_init (__u32 *buf);
include/net/tcp.h +8 -0
@@ -1478,6 +1478,14 @@ struct tcp_request_sock_ops {#endif }; +/* Using SHA1 for now, define some constants. +*/ +#define COOKIE_DIGEST_WORDS (SHA_DIGEST_WORDS) +#define COOKIE_MESSAGE_WORDS (SHA_MESSAGE_BYTES / 4) +#define COOKIE_WORKSPACE_WORDS (COOKIE_DIGEST_WORDS + COOKIE_MESSAGE_WORDS) + +extern int tcp_cookie_generator (u32 *bakery); +extern void tcp_v4_init (void );extern void tcp_init (void );
net/ipv4/tcp.c +140 -0
164 lines not on this page · raw message
Signature · 1 line
1.6.3.3
Re: [net-next-2.6 PATCH v8 3/7] TCPCT part 1c: sysctl_tcp_cookie_size, socket option TCP_COOKIE_TRANSACTIONS
In reply to William Allen SimpsonDefine sysctl (tcp_cookie_size) to turn on and off the cookie option default globally, instead of a compiled configuration option.
Define per socket option (TCP_COOKIE_TRANSACTIONS) for setting constant data values, retrieving variable cookie values, and other facilities.
Move inline tcp_clear_options() unchanged from net/tcp.h to linux/tcp.h, near its corresponding struct tcp_options_received (prior to changes).
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):
http://thread.gmane.org/gmane.linux.network/102586
These functions will also be used in subsequent patches that implement additional features.
Requires:
net: TCP_MSS_DEFAULT, TCP_MSS_DESIRED
--- Documentation/networking/ip-sysctl.txt | 8 +++++++ include/linux/tcp.h | 33 +++++++++++++++++++++++++++++++- include/net/tcp.h | 6 +---- net/ipv4/sysctl_net_ipv4.c | 8 +++++++ net/ipv4/tcp_output.c | 3 ++ 5 files changed, 52 insertions(+), 6 deletions(-)
Documentation/networking/ip-sysctl.txt +8 -0
@@ -164,6 +164,14 @@ tcp_congestion_control - STRING additional choices may be available based on kernel configuration. Default is set as part of kernel configuration. +tcp_cookie_size - INTEGER + Default size of TCP Cookie Transactions (TCPCT) option, that may be + overridden on a per socket basis by the TCPCT socket option. + Values greater than the maximum (16) are interpreted as the maximum. + Values greater than zero and less than the minimum (8) are interpreted + as the minimum. Odd values are interpreted as the next even value. + Default: 0 (off). + tcp_dsack - BOOLEAN Allows TCP to send "duplicate" SACKs.
include/linux/tcp.h +32 -1
@@ -102,7 +102,9 @@ enum {#define TCP_QUICKACK 12/* Block/reenable quick acks */ #define TCP_CONGESTION 13/* Congestion control algorithm */ #define TCP_MD5SIG 14/* TCP MD5 Signature (RFC2385) */ +#define TCP_COOKIE_TRANSACTIONS 15/* TCP Cookie Transactions */ +/* for TCP_INFO socket option */ #define TCPI_OPT_TIMESTAMPS 1#define TCPI_OPT_SACK 2#define TCPI_OPT_WSCALE 4
@@ -174,6 +176,30 @@ struct tcp_md5sig {__u8 tcpm_key[TCP_MD5SIG_MAXKEYLEN ];/* key (binary) */ }; +/* for TCP_COOKIE_TRANSACTIONS (TCPCT) socket option */ +#define TCP_COOKIE_MIN 8/* 64-bits */ +#define TCP_COOKIE_MAX 16/* 128-bits */ +#define TCP_COOKIE_PAIR_SIZE (2*TCP_COOKIE_MAX) + +/* Flags for both getsockopt and setsockopt */ +#define TCP_COOKIE_IN_ALWAYS (1 << 0)/* Discard SYN without cookie */ +#define TCP_COOKIE_OUT_NEVER (1 << 1)/* Prohibit outgoing cookies, +* supercedes everything. */ + +/* Flags for getsockopt */ +#define TCP_S_DATA_IN (1 << 2)/* Was data received? */ +#define TCP_S_DATA_OUT (1 << 3)/* Was data sent? */ + +/* TCP_COOKIE_TRANSACTIONS data */ +struct tcp_cookie_transactions { +__u16 tcpct_flags;/* see above */ +__u8 __tcpct_pad1;/* zero */ +__u8 tcpct_cookie_desired;/* bytes */ +__u16 tcpct_s_data_desired;/* bytes of variable data */ +__u16 tcpct_used;/* bytes in value */ +__u8 tcpct_value[TCP_MSS_DEFAULT ]; +}; +#ifdef __KERNEL__#include <linux/skbuff.h>
@@ -227,6 +253,11 @@ struct tcp_options_received {u16 mss_clamp;/* Maximal mss, negotiated at connection setup */ }; +static inline void tcp_clear_options (struct tcp_options_received *rx_opt) +{ + rx_opt->tstamp_ok = rx_opt->sack_ok = rx_opt->wscale_ok = rx_opt->snd_wscale =0 ; +} +/* This is the max number of SACKS that we'll generate and process. It's safe * to increse this, although since: * size = TCPOLEN_SACK_BASE_ALIGNED (4) + n * TCPOLEN_SACK_PERBLOCK (8)
@@ -435,6 +466,6 @@ static inline struct tcp_timewait_sock *tcp_twsk(const struct sock *sk)return (struct tcp_timewait_sock *)sk; } -#endif +#endif /* __KERNEL__ */ #endif /* _LINUX_TCP_H */
include/net/tcp.h +1 -5
@@ -234,6 +234,7 @@ extern int sysctl_tcp_base_mss;extern int sysctl_tcp_workaround_signed_windows;extern int sysctl_tcp_slow_start_after_idle;extern int sysctl_tcp_max_ssthresh; +extern int sysctl_tcp_cookie_size;extern atomic_t tcp_memory_allocated;extern struct percpu_counter tcp_sockets_allocated;
@@ -340,11 +341,6 @@ static inline void tcp_dec_quickack_mode(struct sock *sk,extern void tcp_enter_quickack_mode (struct sock *sk); -static inline void tcp_clear_options (struct tcp_options_received *rx_opt) -{ - rx_opt->tstamp_ok = rx_opt->sack_ok = rx_opt->wscale_ok = rx_opt->snd_wscale =0 ; -} -#define TCP_ECN_OK 1#define TCP_ECN_QUEUE_CWR 2#define TCP_ECN_DEMAND_CWR 4
net/ipv4/sysctl_net_ipv4.c +8 -0
@@ -714,6 +714,14 @@ static struct ctl_table ipv4_table[] = { }, { .ctl_name = CTL_UNNUMBERED, + .procname = "tcp_cookie_size", + .data = &sysctl_tcp_cookie_size, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec + }, + { + .ctl_name = CTL_UNNUMBERED, .procname = "udp_mem", .data = &sysctl_udp_mem, .maxlen = sizeof(sysctl_udp_mem),
net/ipv4/tcp_output.c +3 -0
@@ -59,6 +59,9 @@ int sysctl_tcp_base_mss __read_mostly = 512;/* By default, RFC2861 behavior. */ int sysctl_tcp_slow_start_after_idle__read_mostly =1 ; +int sysctl_tcp_cookie_size__read_mostly =0 ;/* TCP_COOKIE_MAX */ + +/* Account for new data that has been sent to the network. */ static void tcp_event_new_data_sent (struct sock *sk,struct sk_buff *skb) {
Signature · 1 line
1.6.3.3
Re: [net-next-2.6 PATCH v8 4/7] TCPCT part 1d: define TCP cookie option, extend existing struct's
In reply to William Allen SimpsonData 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
--- include/linux/tcp.h | 29 +++++++++++++--- include/net/tcp.h | 83 ++++++++++++++++++++++++++++++++++++++++++++++ net/ipv4/tcp_ipv4.c | 20 +++++++++++ net/ipv4/tcp_minisocks.c | 46 +++++++++++++++++++++---- net/ipv6/tcp_ipv6.c | 13 +++++++ 5 files changed, 177 insertions(+), 14 deletions(-)
include/linux/tcp.h +23 -6
@@ -247,31 +247,38 @@ struct tcp_options_received { sack_ok : 4, /* SACK seen on SYN packet */ snd_wscale : 4, /* Window scaling received from sender */ rcv_wscale : 4; /* Window scaling to send to receiver */ -/* SACKs data */ + u8 cookie_plus:6, /* bytes in authenticator/cookie option */ + cookie_out_never:1, + cookie_in_always:1;u8 num_sacks;/* Number of SACK blocks */ -u16 user_mss;/* mss requested by user in ioctl */ +u16 user_mss;/* mss requested by user in ioctl */ u16 mss_clamp;/* Maximal mss, negotiated at connection setup */ };static inline void tcp_clear_options (struct tcp_options_received *rx_opt) { - rx_opt->tstamp_ok = rx_opt->sack_ok = rx_opt->wscale_ok = rx_opt->snd_wscale =0 ; + rx_opt->tstamp_ok = rx_opt->sack_ok =0 ; + rx_opt->wscale_ok = rx_opt->snd_wscale =0 ; + rx_opt->cookie_plus =0 ; }/* This is the max number of SACKS that we'll generate and process. It's safe -* to increse this, although since: +* to increase this, although since: * size = TCPOLEN_SACK_BASE_ALIGNED (4) + n * TCPOLEN_SACK_PERBLOCK (8) * only four options will fit in a standard TCP header */ #define TCP_NUM_SACKS 4 +struct tcp_cookie_values ; +struct tcp_request_sock_ops ; +struct tcp_request_sock {struct inet_request_sock req;#ifdef CONFIG_TCP_MD5SIG /* Only used by TCP MD5 Signature so far. */ const struct tcp_request_sock_ops *af_specific;#endif -u32 rcv_isn; -u32 snt_isn; +u32 rcv_isn; +u32 snt_isn; };static inline struct tcp_request_sock *tcp_rsk (const struct request_sock *req)
@@ -441,6 +448,12 @@ struct tcp_sock {/* TCP MD5 Signature Option information */ struct tcp_md5sig_info *md5sig_info;#endif + +/* When the cookie options are generated and exchanged, then this +* object holds a reference to them (cookie_values->kref). Also +* contains related tcp_cookie_transactions fields. +*/ +struct tcp_cookie_values *cookie_values; };static inline struct tcp_sock *tcp_sk (const struct sock *sk)
@@ -459,6 +472,10 @@ struct tcp_timewait_sock {u16 tw_md5_keylen;u8 tw_md5_key[TCP_MD5SIG_MAXKEYLEN ];#endif +/* Few sockets in timewait have cookies; in that case, then this +* object holds a reference to them (tw_cookie_values->kref). +*/ +struct tcp_cookie_values *tw_cookie_values; };static inline struct tcp_timewait_sock *tcp_twsk (const struct sock *sk)
include/net/tcp.h +83 -0
107 lines not on this page · raw message
net/ipv4/tcp_ipv4.c +20 -0
@@ -1833,6 +1833,19 @@ static int tcp_v4_init_sock(struct sock *sk) tp->af_specific = &tcp_sock_ipv4_specific;#endif +/* TCP Cookie Transactions */ +if (sysctl_tcp_cookie_size >0 ) { +/* Default, cookies without s_data_payload. */ + tp->cookie_values = +kzalloc (sizeof (*tp->cookie_values), + sk->sk_allocation); +if (tp->cookie_values !=NULL ) +kref_init (&tp->cookie_values->kref); + } +/* Presumed zeroed, in order of appearance: +* cookie_in_always, cookie_out_never, +* s_data_constant, s_data_in, s_data_out +*/ sk->sk_sndbuf = sysctl_tcp_wmem[1 ]; sk->sk_rcvbuf = sysctl_tcp_rmem[1 ];
@@ -1886,6 +1899,13 @@ void tcp_v4_destroy_sock(struct sock *sk) sk->sk_sndmsg_page =NULL ; } +/* TCP Cookie Transactions */ +if (tp->cookie_values !=NULL ) { +kref_put (&tp->cookie_values->kref, + tcp_cookie_values_release); + tp->cookie_values =NULL ; + } +percpu_counter_dec (&tcp_sockets_allocated); }
net/ipv4/tcp_minisocks.c +38 -8
67 lines not on this page · raw message
net/ipv6/tcp_ipv6.c +13 -0
@@ -1864,6 +1864,19 @@ static int tcp_v6_init_sock(struct sock *sk) tp->af_specific = &tcp_sock_ipv6_specific;#endif +/* TCP Cookie Transactions */ +if (sysctl_tcp_cookie_size >0 ) { +/* Default, cookies without s_data_payload. */ + tp->cookie_values = +kzalloc (sizeof (*tp->cookie_values), + sk->sk_allocation); +if (tp->cookie_values !=NULL ) +kref_init (&tp->cookie_values->kref); + } +/* Presumed zeroed, in order of appearance: +* cookie_in_always, cookie_out_never, +* s_data_constant, s_data_in, s_data_out +*/ sk->sk_sndbuf = sysctl_tcp_wmem[1 ]; sk->sk_rcvbuf = sysctl_tcp_rmem[1 ];
Signature · 1 line
1.6.3.3
Re: [net-next-2.6 PATCH v8 5/7] TCPCT part 1e: implement socket option TCP_COOKIE_TRANSACTIONS
In reply to William Allen SimpsonProvide per socket control of the TCP cookie option and SYN/SYNACK 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):
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.
Allocations have been rearranged to avoid requiring GFP_ATOMIC.
Requires:
net: TCP_MSS_DEFAULT, TCP_MSS_DESIRED
TCPCT part 1c: sysctl_tcp_cookie_size, socket option TCP_COOKIE_TRANSACTIONS TCPCT part 1d: define TCP cookie option, extend existing struct's
--- net/ipv4/tcp.c | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 131 insertions(+), 2 deletions(-)
net/ipv4/tcp.c +131 -2
@@ -2085,8 +2085,9 @@ static int do_tcp_setsockopt(struct sock *sk, int level,int val;int err =0 ; -/* This is a string value all the others are int's */ -if (optname ==TCP_CONGESTION ) { +/* These are data/string values, all the others are ints */ +switch (optname) { +case TCP_CONGESTION : {char name[TCP_CA_NAME_MAX ];if (optlen <1 )
@@ -2103,6 +2104,93 @@ static int do_tcp_setsockopt(struct sock *sk, int level,release_sock (sk);return err; } +case TCP_COOKIE_TRANSACTIONS : { +struct tcp_cookie_transactions ctd; +struct tcp_cookie_values *cvp =NULL ; + +if (sizeof (ctd) > optlen) +return -EINVAL ; +if (copy_from_user (&ctd, optval,sizeof (ctd))) +return -EFAULT ; + +if (ctd.tcpct_used >sizeof (ctd.tcpct_value) || + ctd.tcpct_s_data_desired >TCP_MSS_DESIRED ) +return -EINVAL ; + +if (ctd.tcpct_cookie_desired ==0 ) { +/* default to global value */ + }else if ((0x1 & ctd.tcpct_cookie_desired) || + ctd.tcpct_cookie_desired >TCP_COOKIE_MAX || + ctd.tcpct_cookie_desired <TCP_COOKIE_MIN ) { +return -EINVAL ; + } + +if (TCP_COOKIE_OUT_NEVER & ctd.tcpct_flags) { +/* Supercedes all other values */ +lock_sock (sk); +if (tp->cookie_values !=NULL ) { +kref_put (&tp->cookie_values->kref, + tcp_cookie_values_release); + tp->cookie_values =NULL ; + } + tp->rx_opt.cookie_in_always =0 ;/* false */ + tp->rx_opt.cookie_out_never =1 ;/* true */ +release_sock (sk); +return err; + } + +/* Allocate ancillary memory before locking. +*/ +if (ctd.tcpct_used >0 || + (tp->cookie_values ==NULL && + (sysctl_tcp_cookie_size >0 || + ctd.tcpct_cookie_desired >0 || + ctd.tcpct_s_data_desired >0 ))) { + cvp =kzalloc (sizeof (*cvp) + ctd.tcpct_used, +GFP_KERNEL ); +if (cvp ==NULL ) +return -ENOMEM ; + } +lock_sock (sk); + tp->rx_opt.cookie_in_always = + (TCP_COOKIE_IN_ALWAYS & ctd.tcpct_flags); + tp->rx_opt.cookie_out_never =0 ;/* false */ + +if (tp->cookie_values !=NULL ) { +if (cvp !=NULL ) { +/* Changed values are recorded by a changed +* pointer, ensuring the cookie will differ, +* without separately hashing each value later. +*/ +kref_put (&tp->cookie_values->kref, + tcp_cookie_values_release); +kref_init (&cvp->kref); + tp->cookie_values = cvp; + }else { + cvp = tp->cookie_values; + } + } +if (cvp !=NULL ) { + cvp->cookie_desired = ctd.tcpct_cookie_desired; + +if (ctd.tcpct_used >0 ) { +memcpy (cvp->s_data_payload, ctd.tcpct_value, + ctd.tcpct_used); + cvp->s_data_desired = ctd.tcpct_used; + cvp->s_data_constant =1 ;/* true */ + }else { +/* No constant payload data. */ + cvp->s_data_desired = ctd.tcpct_s_data_desired; + cvp->s_data_constant =0 ;/* false */ + } + } +release_sock (sk); +return err; + } +default : +/* fallthru */ +break ; + };if (optlen <sizeof (int ))return -EINVAL ;
@@ -2427,6 +2515,47 @@ static int do_tcp_getsockopt(struct sock *sk, int level,if (copy_to_user (optval, icsk->icsk_ca_ops->name, len))return -EFAULT ;return 0 ; + +case TCP_COOKIE_TRANSACTIONS : { +struct tcp_cookie_transactions ctd; +struct tcp_cookie_values *cvp = tp->cookie_values; + +if (get_user (len, optlen)) +return -EFAULT ; +if (len <sizeof (ctd)) +return -EINVAL ; + +memset (&ctd,0 ,sizeof (ctd)); + ctd.tcpct_flags = (tp->rx_opt.cookie_in_always ? +TCP_COOKIE_IN_ALWAYS :0 ) + | (tp->rx_opt.cookie_out_never ? +TCP_COOKIE_OUT_NEVER :0 ); + +if (cvp !=NULL ) { + ctd.tcpct_flags |= (cvp->s_data_in ? +TCP_S_DATA_IN :0 ) + | (cvp->s_data_out ? +TCP_S_DATA_OUT :0 ); + + ctd.tcpct_cookie_desired = cvp->cookie_desired; + ctd.tcpct_s_data_desired = cvp->s_data_desired; + +/* Cookie(s) saved, return as nonce */ +if (sizeof (ctd.tcpct_value) < cvp->cookie_pair_size) { +/* impossible? */ +return -EINVAL ; + } +memcpy (&ctd.tcpct_value[0 ], &cvp->cookie_pair[0 ], + cvp->cookie_pair_size); + ctd.tcpct_used = cvp->cookie_pair_size; + } + +if (put_user (sizeof (ctd), optlen)) +return -EFAULT ; +if (copy_to_user (optval, &ctd,sizeof (ctd))) +return -EFAULT ; +return 0 ; + }default :return -ENOPROTOOPT ; }
Signature · 1 line
1.6.3.3
Re: [net-next-2.6 PATCH v8 6/7] TCPCT part 1f: Initiator Cookie => Responder
In reply to William Allen SimpsonCalculate and format <SYN> TCP_COOKIE option.
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 1c: sysctl_tcp_cookie_size, socket option TCP_COOKIE_TRANSACTIONS TCPCT part 1d: define TCP cookie option, extend existing struct's
--- net/ipv4/tcp_output.c | 193 +++++++++++++++++++++++++++++++++++++++++-------- 1 files changed, 163 insertions(+), 30 deletions(-)
net/ipv4/tcp_output.c +163 -30
@@ -365,15 +365,45 @@ static inline int tcp_urg_mode(const struct tcp_sock *tp)#define OPTION_TS (1 << 1)#define OPTION_MD5 (1 << 2)#define OPTION_WSCALE (1 << 3) +#define OPTION_COOKIE_EXTENSION (1 << 4)struct tcp_out_options {u8 options;/* bit field of OPTION_* */ u8 ws;/* window scale, 0 to disable */ u8 num_sack_blocks;/* number of SACK blocks to include */ +u8 hash_size;/* bytes in hash_location */ u16 mss;/* 0 to disable */ __u32 tsval, tsecr;/* need to include OPTION_TS */ +__u8 *hash_location;/* temporary pointer, overloaded */ }; +/* The sysctl int routines are generic, so check consistency here. +*/ +static u8 tcp_cookie_size_check (u8 desired) +{ +if (desired >0 ) { +/* previously specified */ +return desired; + } +if (sysctl_tcp_cookie_size <=0 ) { +/* no default specified */ +return 0 ; + } +if (sysctl_tcp_cookie_size <=TCP_COOKIE_MIN ) { +/* value too small, specify minimum */ +return TCP_COOKIE_MIN ; + } +if (sysctl_tcp_cookie_size >=TCP_COOKIE_MAX ) { +/* value too large, specify maximum */ +return TCP_COOKIE_MAX ; + } +if (0x1 & sysctl_tcp_cookie_size) { +/* 8-bit multiple, illegal, fix it */ +return (u8)(sysctl_tcp_cookie_size +0x1 ); + } +return (u8 )sysctl_tcp_cookie_size; +} +/* Write previously computed TCP options to the packet. * * Beware: Something in the Internet is very sensitive to the ordering of
@@ -388,17 +418,34 @@ struct tcp_out_options {* (but it may well be that other scenarios fail similarly). */ static void tcp_options_write (__be32 *ptr,struct tcp_sock *tp, -const struct tcp_out_options *opts, -__u8 **md5_hash) { -if (unlikely (OPTION_MD5 & opts->options)) { - *ptr++ =htonl ((TCPOPT_NOP <<24 ) | - (TCPOPT_NOP <<16 ) | - (TCPOPT_MD5SIG <<8 ) | -TCPOLEN_MD5SIG ); - *md5_hash = (__u8 *)ptr; +struct tcp_out_options *opts) +{ +u8 options = opts->options;/* mungable copy */ + +/* Having both authentication and cookies for security is redundant, +* and there's certainly not enough room. Instead, the cookie-less +* extension variant is proposed. +* +* Consider the pessimal case with authentication. The options +* could look like: +* COOKIE|MD5(20) + MSS(4) + SACK|TS(12) + WSCALE(4) == 40 +*/ +if (unlikely (OPTION_MD5 & options)) { +if (unlikely (OPTION_COOKIE_EXTENSION & options)) { + *ptr++ =htonl ((TCPOPT_COOKIE <<24 ) | + (TCPOLEN_COOKIE_BASE <<16 ) | + (TCPOPT_MD5SIG <<8 ) | +TCPOLEN_MD5SIG ); + }else { + *ptr++ =htonl ((TCPOPT_NOP <<24 ) | + (TCPOPT_NOP <<16 ) | + (TCPOPT_MD5SIG <<8 ) | +TCPOLEN_MD5SIG ); + } + options &= ~OPTION_COOKIE_EXTENSION ; +/* overload cookie hash location */ + opts->hash_location = (__u8 *)ptr; ptr +=4 ; - }else { - *md5_hash =NULL ; }if (unlikely (opts->mss)) {
@@ -407,12 +454,13 @@ static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp, opts->mss); } -if (likely (OPTION_TS & opts->options)) { -if (unlikely (OPTION_SACK_ADVERTISE & opts->options)) { +if (likely (OPTION_TS & options)) { +if (unlikely (OPTION_SACK_ADVERTISE & options)) { *ptr++ =htonl ((TCPOPT_SACK_PERM <<24 ) | (TCPOLEN_SACK_PERM <<16 ) | (TCPOPT_TIMESTAMP <<8 ) |TCPOLEN_TIMESTAMP ); + options &= ~OPTION_SACK_ADVERTISE ; }else { *ptr++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
@@ -423,15 +471,52 @@ static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp, *ptr++ =htonl (opts->tsecr); } -if (unlikely (OPTION_SACK_ADVERTISE & opts->options && - !(OPTION_TS & opts->options))) { +/* Specification requires after timestamp, so do it now. +* +* Consider the pessimal case without authentication. The options +* could look like: +* MSS(4) + SACK|TS(12) + COOKIE(20) + WSCALE(4) == 40 +*/ +if (unlikely (OPTION_COOKIE_EXTENSION & options)) { +__u8 *cookie_copy = opts->hash_location; +u8 cookie_size = opts->hash_size; + +/* 8-bit multiple handled in tcp_cookie_size_check() above, +* and elsewhere. +*/ +if (0x2 & cookie_size) { +__u8 *p = (__u8 *)ptr; + +/* 16-bit multiple */ + *p++ =TCPOPT_COOKIE ; + *p++ =TCPOLEN_COOKIE_BASE + cookie_size; + *p++ = *cookie_copy++; + *p++ = *cookie_copy++; + ptr++; + cookie_size -=2 ; + }else { +/* 32-bit multiple */ + *ptr++ =htonl (((TCPOPT_NOP <<24 ) | + (TCPOPT_NOP <<16 ) | + (TCPOPT_COOKIE <<8 ) | +TCPOLEN_COOKIE_BASE ) + + cookie_size); + } + +if (cookie_size >0 ) { +memcpy (ptr, cookie_copy, cookie_size); + ptr += (cookie_size /4 ); + } + } + +if (unlikely (OPTION_SACK_ADVERTISE & options)) { *ptr++ =htonl ((TCPOPT_NOP <<24 ) | (TCPOPT_NOP <<16 ) | (TCPOPT_SACK_PERM <<8 ) |TCPOLEN_SACK_PERM ); } -if (unlikely (OPTION_WSCALE & opts->options)) { +if (unlikely (OPTION_WSCALE & options)) { *ptr++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_WINDOW << 16) | (TCPOLEN_WINDOW << 8) |
@@ -466,14 +551,18 @@ static unsigned tcp_syn_options(struct sock *sk, struct sk_buff *skb,struct tcp_out_options *opts, struct tcp_md5sig_key **md5) { struct tcp_sock *tp = tcp_sk(sk); -unsigned size =0 ; +struct tcp_cookie_values *cvp = tp->cookie_values;struct dst_entry *dst =__sk_dst_get (sk); +unsigned remaining =MAX_TCP_OPTION_SPACE ; +u8 cookie_size = (!tp->rx_opt.cookie_out_never && cvp !=NULL ) ? +tcp_cookie_size_check (cvp->cookie_desired) : +0 ;#ifdef CONFIG_TCP_MD5SIG *md5 = tp->af_specific->md5_lookup (sk, sk);if (*md5) { opts->options |=OPTION_MD5 ; - size +=TCPOLEN_MD5SIG_ALIGNED ; + remaining -=TCPOLEN_MD5SIG_ALIGNED ; }#else *md5 =NULL ;
@@ -489,7 +578,7 @@ static unsigned tcp_syn_options(struct sock *sk, struct sk_buff *skb,* SACKs don't matter, we never delay an ACK when we have any of those * going out. */ opts->mss =tcp_advertise_mss (sk); - size +=TCPOLEN_MSS_ALIGNED ; + remaining -=TCPOLEN_MSS_ALIGNED ; if (likely(sysctl_tcp_timestamps && !dst_feature(dst, RTAX_FEATURE_NO_TSTAMP) &&
@@ -497,22 +586,68 @@ static unsigned tcp_syn_options(struct sock *sk, struct sk_buff *skb, opts->options |=OPTION_TS ; opts->tsval =TCP_SKB_CB (skb)->when; opts->tsecr = tp->rx_opt.ts_recent; - size +=TCPOLEN_TSTAMP_ALIGNED ; + remaining -=TCPOLEN_TSTAMP_ALIGNED ; }if (likely (sysctl_tcp_window_scaling && !dst_feature (dst,RTAX_FEATURE_NO_WSCALE ))) { opts->ws = tp->rx_opt.rcv_wscale; opts->options |=OPTION_WSCALE ; - size +=TCPOLEN_WSCALE_ALIGNED ; + remaining -=TCPOLEN_WSCALE_ALIGNED ; }if (likely (sysctl_tcp_sack && !dst_feature (dst,RTAX_FEATURE_NO_SACK ))) { opts->options |=OPTION_SACK_ADVERTISE ;if (unlikely (!(OPTION_TS & opts->options))) - size +=TCPOLEN_SACKPERM_ALIGNED ; + remaining -=TCPOLEN_SACKPERM_ALIGNED ; } -return size; +/* Note that timestamps are required by the specification. +* +* Odd numbers of bytes are prohibited by the specification, ensuring +* that the cookie is 16-bit aligned, and the resulting cookie pair is +* 32-bit aligned. +*/ +if (*md5 ==NULL && + (OPTION_TS & opts->options) && + cookie_size >0 ) { +int need =TCPOLEN_COOKIE_BASE + cookie_size; + +if (0x2 & need) { +/* 32-bit multiple */ + need +=2 ;/* NOPs */ + +if (need > remaining) { +/* try shrinking cookie to fit */ + cookie_size -=2 ; + need -=4 ; + } + } +while (need > remaining &&TCP_COOKIE_MIN <= cookie_size) { + cookie_size -=4 ; + need -=4 ; + } +if (TCP_COOKIE_MIN <= cookie_size) { + opts->options |=OPTION_COOKIE_EXTENSION ; + opts->hash_location = (__u8 *)&cvp->cookie_pair[0 ]; + opts->hash_size = cookie_size; + +/* Remember for future incarnations. */ + cvp->cookie_desired = cookie_size; + +if (cvp->cookie_desired != cvp->cookie_pair_size) { +/* Currently use random bytes as a nonce, +* assuming these are completely unpredictable +* by hostile users of the same system. +*/ +get_random_bytes (&cvp->cookie_pair[0 ], + cookie_size); + cvp->cookie_pair_size = cookie_size; + } + + remaining -= need; + } + } +return MAX_TCP_OPTION_SPACE - remaining; }/* Set up TCP options for SYN-ACKs. */
@@ -627,7 +762,6 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,struct tcp_out_options opts;unsigned tcp_options_size, tcp_header_size;struct tcp_md5sig_key *md5; -__u8 *md5_hash_location;struct tcphdr *th;int err;
@@ -698,7 +832,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, } } -tcp_options_write ((__be32 *)(th +1 ), tp, &opts, &md5_hash_location); +tcp_options_write ((__be32 *)(th +1 ), tp, &opts);if (likely ((tcb->flags &TCPCB_FLAG_SYN ) ==0 ))TCP_ECN_send (sk, skb, tcp_header_size);
@@ -706,7 +840,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,/* Calculate the MD5 hash, as we have all we need now */ if (md5) { sk->sk_route_caps &= ~NETIF_F_GSO_MASK ; - tp->af_specific->calc_md5_hash (md5_hash_location, + tp->af_specific->calc_md5_hash (opts.hash_location, md5, sk,NULL , skb); }#endif
@@ -2230,14 +2364,13 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,struct request_sock *req, struct request_values *rvp) { + struct tcp_out_options opts;struct inet_request_sock *ireq =inet_rsk (req);struct tcp_sock *tp =tcp_sk (sk);struct tcphdr *th; -int tcp_header_size; -struct tcp_out_options opts;struct sk_buff *skb;struct tcp_md5sig_key *md5; -__u8 *md5_hash_location; +int tcp_header_size;int mss; skb =sock_wmalloc (sk,MAX_TCP_HEADER +15 ,1 ,GFP_ATOMIC );
@@ -2298,14 +2431,14 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,/* RFC1323: The window in SYN & SYN/ACK segments is never scaled. */ th->window =htons (min (req->rcv_wnd,65535U )); -tcp_options_write ((__be32 *)(th +1 ), tp, &opts, &md5_hash_location); +tcp_options_write ((__be32 *)(th +1 ), tp, &opts); th->doff = (tcp_header_size >>2 );TCP_INC_STATS (sock_net (sk),TCP_MIB_OUTSEGS );#ifdef CONFIG_TCP_MD5SIG /* Okay, we have all we need - do the md5 hash if needed */ if (md5) { -tcp_rsk (req)->af_specific->calc_md5_hash (md5_hash_location, +tcp_rsk (req)->af_specific->calc_md5_hash (opts.hash_location, md5,NULL , req, skb); }#endif
Signature · 1 line
1.6.3.3
Re: [net-next-2.6 PATCH v8 7/7] TCPCT part 1g: Responder Cookie => Initiator
In reply to William Allen SimpsonParse 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
--- include/net/tcp.h | 1 + net/ipv4/syncookies.c | 5 +- net/ipv4/tcp_input.c | 75 +++++++++++++++++++++++++++++---- net/ipv4/tcp_ipv4.c | 47 +++++++++++++++++++-- net/ipv4/tcp_minisocks.c | 14 ++++--- net/ipv4/tcp_output.c | 103 ++++++++++++++++++++++++++++++++++++++-------- net/ipv6/syncookies.c | 5 +- net/ipv6/tcp_ipv6.c | 52 ++++++++++++++++++++++- 8 files changed, 259 insertions(+), 43 deletions(-)
include/net/tcp.h +1 -0
@@ -407,6 +407,7 @@ extern int tcp_recvmsg(struct kiocb *iocb, struct sock *sk,extern void tcp_parse_options (struct sk_buff *skb,struct tcp_options_received *opt_rx, +u8 **hvpp,int estab,struct dst_entry *dst);
net/ipv4/syncookies.c +3 -2
@@ -253,6 +253,8 @@ EXPORT_SYMBOL(cookie_check_timestamp);struct sock *cookie_v4_check (struct sock *sk,struct sk_buff *skb,struct ip_options *opt) { +struct tcp_options_received tcp_opt; +u8 *hash_location;struct inet_request_sock *ireq;struct tcp_request_sock *treq;struct tcp_sock *tp =tcp_sk (sk);
@@ -263,7 +265,6 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,int mss;struct rtable *rt;__u8 rcv_wscale; -struct tcp_options_received tcp_opt;if (!sysctl_tcp_syncookies || !th->ack) goto out;
@@ -341,7 +342,7 @@ 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,0 , &rt->u.dst); +tcp_parse_options (skb, &tcp_opt, &hash_location,0 , &rt->u.dst);if (tcp_opt.saw_tstamp)cookie_check_timestamp (&tcp_opt);
net/ipv4/tcp_input.c +65 -10
124 lines not on this page · raw message
net/ipv4/tcp_ipv4.c +43 -4
74 lines not on this page · raw message
net/ipv4/tcp_minisocks.c +8 -6
@@ -90,13 +90,14 @@ enum tcp_tw_status tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb, const struct tcphdr *th) { - struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw); struct tcp_options_received tmp_opt; +u8 *hash_location; +struct tcp_timewait_sock *tcptw =tcp_twsk ((struct sock *)tw);int paws_reject =0 ;if (th->doff > (sizeof (*th) >>2 ) && tcptw->tw_ts_recent_stamp) { tmp_opt.tstamp_ok =1 ; -tcp_parse_options (skb, &tmp_opt,1 ,NULL ); +tcp_parse_options (skb, &tmp_opt, &hash_location,1 ,NULL );if (tmp_opt.saw_tstamp) { tmp_opt.ts_recent = tcptw->tw_ts_recent;
@@ -518,15 +519,16 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,struct request_sock *req, struct request_sock **prev) { + struct tcp_options_received tmp_opt; +u8 *hash_location; +struct sock *child;const struct tcphdr *th =tcp_hdr (skb);__be32 flg =tcp_flag_word (th) & (TCP_FLAG_RST |TCP_FLAG_SYN |TCP_FLAG_ACK );int paws_reject =0 ; -struct tcp_options_received tmp_opt; -struct sock *child; -if ((th->doff > (sizeof (struct tcphdr )>>2 )) && (req->ts_recent)) { +if ((th->doff > (sizeof (*th) >>2 )) && (req->ts_recent)) { tmp_opt.tstamp_ok =1 ; -tcp_parse_options (skb, &tmp_opt,1 ,NULL ); +tcp_parse_options (skb, &tmp_opt, &hash_location,1 ,NULL );if (tmp_opt.saw_tstamp) { tmp_opt.ts_recent = req->ts_recent;
net/ipv4/tcp_output.c +86 -17
154 lines not on this page · raw message
net/ipv6/syncookies.c +3 -2
@@ -159,6 +159,8 @@ 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; +u8 *hash_location;struct inet_request_sock *ireq;struct inet6_request_sock *ireq6;struct tcp_request_sock *treq;
@@ -171,7 +173,6 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)int mss;struct dst_entry *dst;__u8 rcv_wscale; -struct tcp_options_received tcp_opt;if (!sysctl_tcp_syncookies || !th->ack) goto out;
@@ -254,7 +255,7 @@ 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,0 , dst); +tcp_parse_options (skb, &tcp_opt, &hash_location,0 , dst);if (tcp_opt.saw_tstamp)cookie_check_timestamp (&tcp_opt);
net/ipv6/tcp_ipv6.c +50 -2
72 lines not on this page · raw message
Signature · 1 line
1.6.3.3
David Miller
maintainerFrom: William Allen Simpson <[email protected]>
Date: Wed, 02 Dec 2009 23:04:23 -0500
Quoted 7 lines
Initiator Responder
========= =========
<SYN> ->
Cookie<- <SYN,ACK(SYN)> Cookie optional data
All applied, thanks.
I had to apply the following fix on top to cure a warning on 64-bit.
tcp: Fix warning on 64-bit.
net/ipv4/tcp_output.c: In function $B!F(Btcp_make_synack$B!G(B:net/ipv4/tcp_output.c:2488: warning: cast from pointer to integer of different size
--- net/ipv4/tcp_output.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
net/ipv4/tcp_output.c +1 -1
@@ -2485,7 +2485,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,/* recommended */ *tail-- ^= ((th->dest <<16 ) | th->source); - *tail-- ^= (u32 )cvp;/* per sockopt */ + *tail-- ^= (u32 )(unsigned long )cvp;/* per sockopt */ sha_transform((__u32 *)&xvp->cookie_bakery[0], (char *)mess,
Signature · 1 line
1.6.5
David Miller
maintainerFrom: David Miller <[email protected]>
Date: Wed, 02 Dec 2009 22:13:49 -0800 (PST)
Quoted 1 line
I had to apply the following fix on top to cure a warning on 64-bit.
I also had to apply another patch to fix build failures:
tcp: sysctl_tcp_cookie_size needs to be exported to modules.
Otherwise:
ERROR: "sysctl_tcp_cookie_size" [net/ipv6/ipv6.ko] undefined! make[1]: *** [__modpost] Error 1
--- net/ipv4/tcp_output.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
net/ipv4/tcp_output.c +1 -0
@@ -60,6 +60,7 @@ int sysctl_tcp_base_mss __read_mostly = 512;int sysctl_tcp_slow_start_after_idle__read_mostly =1 ;int sysctl_tcp_cookie_size__read_mostly =0 ;/* TCP_COOKIE_MAX */ +EXPORT_SYMBOL_GPL (sysctl_tcp_cookie_size);/* Account for new data that has been sent to the network. */
Signature · 1 line
1.6.5