TCPCT part 1: initial SYN exchange with SYNACK data
Subsystems (3)
PATCH 1/4 TCPCT part 1: initial SYN exchange with SYNACK data
Pass 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.
--- include/net/request_sock.h | 3 ++- 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 | 12 +++++++----- net/ipv4/tcp_minisocks.c | 2 +- net/ipv4/tcp_output.c | 2 +- net/ipv6/tcp_ipv6.c | 14 +++++++------- 10 files changed, 28 insertions(+), 22 deletions(-)
include/net/request_sock.h +2 -1
@@ -33,7 +33,8 @@ struct request_sock_ops {struct kmem_cache *slab;char *slab_name;int (*rtx_syn_ack)(struct sock *sk, -struct request_sock *req); +struct request_sock *req, +void *extend_values);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
@@ -443,7 +443,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, +void *extend_values);extern int tcp_disconnect (struct sock *sk,int flags);
net/dccp/ipv4.c +3 -2
@@ -473,7 +473,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, +void *extend_unused) {int err =-1 ;struct sk_buff *skb;
@@ -622,7 +623,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, +void *extend_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
@@ -504,7 +504,7 @@ void inet_csk_reqsk_queue_prune(struct sock *parent,if (time_after_eq (now, req->expires)) {if ((req->retrans < thresh || (inet_rsk (req)->acked && req->retrans < max_retries)) - && !req->rsk_ops->rtx_syn_ack (parent, req)) { + && !req->rsk_ops->rtx_syn_ack (parent, req,NULL )) {unsigned long timeo;if (req->retrans++ ==0 )
net/ipv4/tcp_ipv4.c +7 -5
@@ -742,7 +742,7 @@ static void tcp_v4_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,* socket. */ static int __tcp_v4_send_synack (struct sock *sk,struct request_sock *req, -struct dst_entry *dst) +struct dst_entry *dst,void *extend_values) {const struct inet_request_sock *ireq =inet_rsk (req);int err =-1 ;
@@ -752,7 +752,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, extend_values);if (skb) {struct tcphdr *th =tcp_hdr (skb);
@@ -773,9 +773,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, +void *extend_values) { -return __tcp_v4_send_synack (sk, req,NULL ); +return __tcp_v4_send_synack (sk, req,NULL , extend_values); }/*
@@ -1333,7 +1334,8 @@ 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, req, dst,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
@@ -537,7 +537,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 +1 -1
@@ -2219,7 +2219,7 @@ 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,void *extend_values) {struct inet_request_sock *ireq =inet_rsk (req);struct tcp_sock *tp =tcp_sk (sk);
net/ipv6/tcp_ipv6.c +7 -7
@@ -460,7 +460,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, +void *extend_values) {struct inet6_request_sock *treq =inet6_rsk (req);struct ipv6_pinfo *np =inet6_sk (sk);
@@ -498,7 +499,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, extend_values);if (skb) {struct tcphdr *th =tcp_hdr (skb);
@@ -1242,13 +1243,12 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)security_inet_conn_request (sk, skb, req); -if (tcp_v6_send_synack (sk, req)) +if (tcp_v6_send_synack (sk, req,NULL ) || + want_cookie) goto drop; -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:if (req)
Signature · 1 line
1.6.0.4
PATCH 2/4 TCPCT part 1: initial SYN exchange with SYNACK data
Define 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.
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
These functions will also be used in subsequent patches that implement additional features.
--- include/linux/tcp.h | 31 ++++++++++++++++++++++++++++++- include/net/tcp.h | 1 + net/ipv4/sysctl_net_ipv4.c | 8 ++++++++ net/ipv4/tcp_output.c | 8 ++++++++ 4 files changed, 47 insertions(+), 1 deletions(-)
include/linux/tcp.h +30 -1
@@ -96,6 +96,7 @@ 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 */ #define TCPI_OPT_TIMESTAMPS 1#define TCPI_OPT_SACK 2
@@ -170,6 +171,34 @@ struct tcp_md5sig {__u8 tcpm_key[TCP_MD5SIG_MAXKEYLEN ];/* key (binary) */ }; +/* for TCP_COOKIE_TRANSACTIONS (TCPCT) socket option */ +#define TCP_COOKIE_MAX 16/* 128-bits */ +#define TCP_COOKIE_MIN 8/* 64-bits */ +#define TCP_COOKIE_PAIR_SIZE (2*TCP_COOKIE_MAX) + +#define TCP_S_DATA_MAX 64U/* after TCP+IP options */ +#define TCP_S_DATA_MSS_DEFAULT 536U/* default MSS (RFC1122) */ + +/* 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 else. */ +#define TCP_EXTEND_TIMESTAMP (1 << 4)/* Initiate 64-bit timestamps */ + +/* 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_S_DATA_MSS_DEFAULT ]; +}; +#ifdef __KERNEL__#include <linux/skbuff.h>
@@ -431,6 +460,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 -0
@@ -237,6 +237,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;
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 +8 -0
@@ -59,6 +59,14 @@ int sysctl_tcp_base_mss __read_mostly = 512;/* By default, RFC2861 behavior. */ int sysctl_tcp_slow_start_after_idle__read_mostly =1 ; +#ifdef CONFIG_SYSCTL +/* By default, let the user enable it. */ +int sysctl_tcp_cookie_size__read_mostly =0 ; +#else +int sysctl_tcp_cookie_size__read_mostly =TCP_COOKIE_MAX ; +#endif + +/* 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.0.4
PATCH 3/4 TCPCT part 1: initial SYN exchange with SYNACK data
Redefine two TCP header functions to accept TCP header pointer. When subtracting, return signed int to allow error checking.
In the only two existing files using the latter function, clean up confusing and inconsistent mixing of both byte and word offsets. However, remove proposed header length checking, and document the assumptions instead. In the immortal words of the reviewer:
This is transmit, and the packets can only come from the Linux TCP stack, not some external entity.
You're being way too anal here, and adding these checks to drivers would be just a lot of rediculious bloat. [sic]
These functions will also be used in subsequent patches that implement additional features.
--- drivers/net/bnx2.c | 22 +++++++++++++--------- drivers/net/tg3.c | 32 +++++++++++++++++--------------- include/linux/tcp.h | 10 ++++++++-- 3 files changed, 38 insertions(+), 26 deletions(-)
drivers/net/bnx2.c +13 -9
@@ -6330,18 +6330,17 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) }#endif if ((mss =skb_shinfo (skb)->gso_size)) { -u32 tcp_opt_len; -struct iphdr *iph; +struct tcphdr *th =tcp_hdr (skb); +int tcp_opt_words = th->doff - (sizeof (*th) >>2 ); +/* assumes positive tcp_opt_words without checking */ vlan_tag_flags |=TX_BD_FLAGS_SW_LSO ; - tcp_opt_len =tcp_optlen (skb); -if (skb_shinfo (skb)->gso_type &SKB_GSO_TCPV6 ) {u32 tcp_off =skb_transport_offset (skb) -sizeof (struct ipv6hdr ) -ETH_HLEN ; - vlan_tag_flags |= ((tcp_opt_len >>2 ) <<8 ) | + vlan_tag_flags |= (tcp_opt_words <<8 ) |TX_BD_FLAGS_SW_FLAGS ;if (likely (tcp_off ==0 )) vlan_tag_flags &= ~TX_BD_FLAGS_TCP6_OFF0_MSK ;
@@ -6354,10 +6353,15 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) mss |= (tcp_off &0xc ) <<TX_BD_TCP6_OFF2_SHL ; } }else { - iph =ip_hdr (skb); -if (tcp_opt_len || (iph->ihl >5 )) { - vlan_tag_flags |= ((iph->ihl -5 ) + - (tcp_opt_len >>2 )) <<8 ; +struct iphdr *iph =ip_hdr (skb); +int ip_opt_words = iph->ihl - (sizeof (*iph) >>2 ); +int opt_words; + +/* assumes positive ip_opt_words without checking */ + opt_words = ip_opt_words + tcp_opt_words; + +if (opt_words >0 ) { + vlan_tag_flags |= opt_words <<8 ; } } }else
drivers/net/tg3.c +17 -15
@@ -5230,7 +5230,8 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb,else {struct iphdr *iph =ip_hdr (skb); - tcp_opt_len =tcp_optlen (skb); + tcp_opt_len =tcp_option_len_th (tcp_hdr (skb)); +/* assumes positive tcp_opt_len without checking */ ip_tcp_len =ip_hdrlen (skb) +sizeof (struct tcphdr ); iph->check =0 ;
@@ -5392,7 +5393,8 @@ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb, mss =0 ;if ((mss =skb_shinfo (skb)->gso_size) !=0 ) {struct iphdr *iph; -int tcp_opt_len, ip_tcp_len, hdr_len; +int tcp_opt_len, ip_hdr_len, ip_opt_len, ip_tcp_len, hdr_len; +int opt_bytes;if (skb_header_cloned (skb) &&pskb_expand_head (skb,0 ,0 ,GFP_ATOMIC )) {
@@ -5400,10 +5402,12 @@ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb, goto out_unlock; } - tcp_opt_len =tcp_optlen (skb); - ip_tcp_len =ip_hdrlen (skb) +sizeof (struct tcphdr ); - + tcp_opt_len =tcp_option_len_th (tcp_hdr (skb)); +/* assumes positive tcp_opt_len without checking */ + ip_hdr_len =ip_hdrlen (skb); + ip_tcp_len = ip_hdr_len +sizeof (struct tcphdr ); hdr_len = ip_tcp_len + tcp_opt_len; +if (unlikely ((ETH_HLEN + hdr_len) >80 ) && (tp->tg3_flags2 &TG3_FLG2_TSO_BUG ))return (tg3_tso_bug (tp, skb));
@@ -5423,20 +5427,18 @@ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb,IPPROTO_TCP , 0); + ip_opt_len = ip_hdr_len -sizeof (struct iphdr ); +/* assumes positive ip_opt_len without checking */ + opt_bytes = ip_opt_len + tcp_opt_len; +if ((tp->tg3_flags2 &TG3_FLG2_HW_TSO ) || (GET_ASIC_REV (tp->pci_chip_rev_id) ==ASIC_REV_5705 )) { -if (tcp_opt_len || iph->ihl >5 ) { -int tsflags; - - tsflags = (iph->ihl -5 ) + (tcp_opt_len >>2 ); - mss |= (tsflags <<11 ); +if (opt_bytes >0 ) { + mss |= (opt_bytes >>2 ) <<11 ; } }else { -if (tcp_opt_len || iph->ihl >5 ) { -int tsflags; - - tsflags = (iph->ihl -5 ) + (tcp_opt_len >>2 ); - base_flags |= tsflags <<12 ; +if (opt_bytes >0 ) { + base_flags |= (opt_bytes >>2 ) <<12 ; } } }
include/linux/tcp.h +8 -2
@@ -217,9 +217,15 @@ static inline unsigned int tcp_hdrlen(const struct sk_buff *skb)return tcp_hdr (skb)->doff *4 ; } -static inline unsigned int tcp_optlen (const struct sk_buff *skb) +static inline unsigned int tcp_header_len_th (const struct tcphdr *th) { -return (tcp_hdr (skb)->doff -5 ) *4 ; +return th->doff *4 ; +} + +/* When doff is bad, this could be negative. */ +static inline int tcp_option_len_th (const struct tcphdr *th) +{ +return (int )tcp_header_len_th (th) -sizeof (*th); }/* This defines a selective acknowledgement block. */
Signature · 1 line
1.6.0.4
PATCH 4/4 TCPCT part 1: initial SYN exchange with SYNACK 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). That patch was previously reviewed:
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
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 and 1 flag byte in tcp_sock.
Allocations have been rearranged to avoid requiring GFP_ATOMIC, with only one unavoidable exception in tcp_create_openreq_child(), where the tcp_sock itself is created GFP_ATOMIC.
These functions will also be used in subsequent patches that implement additional features.
--- include/linux/tcp.h | 35 +++++++- include/net/tcp.h | 72 ++++++++++++++-- net/ipv4/syncookies.c | 5 +- net/ipv4/tcp.c | 133 +++++++++++++++++++++++++++- net/ipv4/tcp_input.c | 82 +++++++++++++++--- net/ipv4/tcp_ipv4.c | 62 +++++++++++-- net/ipv4/tcp_minisocks.c | 43 +++++++--- net/ipv4/tcp_output.c | 223 ++++++++++++++++++++++++++++++++++++++++++--- net/ipv6/syncookies.c | 5 +- net/ipv6/tcp_ipv6.c | 47 +++++++++- 10 files changed, 641 insertions(+), 66 deletions(-)
include/linux/tcp.h +31 -4
@@ -252,26 +252,36 @@ 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 */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 =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: * 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 +451,19 @@ 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; + + u8 cookie_in_always:1, + cookie_out_never:1, + extend_timestamp:1, + s_data_constant:1, + s_data_in:1, + s_data_out:1; };static inline struct tcp_sock *tcp_sk (const struct sock *sk)
@@ -459,6 +482,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 it (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 +66 -6
108 lines not on this page · raw message
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 *cryptic_value;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;
@@ -278,7 +279,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 ); +tcp_parse_options (skb, &tcp_opt, &cryptic_value,0 );if (tcp_opt.saw_tstamp)cookie_check_timestamp (&tcp_opt);
net/ipv4/tcp.c +131 -2
151 lines not on this page · raw message
net/ipv4/tcp_input.c +71 -11
150 lines not on this page · raw message
net/ipv4/tcp_ipv4.c +54 -8
112 lines not on this page · raw message
net/ipv4/tcp_minisocks.c +32 -11
85 lines not on this page · raw message
net/ipv4/tcp_output.c +208 -15
324 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 *cryptic_value;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;
@@ -186,7 +187,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 ); +tcp_parse_options (skb, &tcp_opt, &cryptic_value,0 );if (tcp_opt.saw_tstamp)cookie_check_timestamp (&tcp_opt);
net/ipv6/tcp_ipv6.c +42 -5
80 lines not on this page · raw message
Signature · 1 line
1.6.0.4
David Miller
maintainerWhen posting a patch series like this, use different subject lines in each patch.
The subject line becomes the commit message header, and if they are all the same nobody can figure out the general idea of each part of the patch series when scanning the commit header lines.
David Miller
maintainerFrom: William Allen Simpson <[email protected]>
Date: Thu, 15 Oct 2009 01:28:59 -0400
Quoted 4 lines
Pass 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.
This callback is generic and isn't designed to take opaque data. All the other arguments to this callback are strongly typed, and this is on purpose.
You'll need to find another way to implement this.
Quoted 6 lines · David Miller
This callback is generic and isn't designed to take opaque data. All the other arguments to this callback are strongly typed, and this is on purpose.
You'll need to find another way to implement this.
This was the most controversial change, so I made it the first separate patch to get strong review.
#1 You recently shot down adding a GFP_ATOMIC kref (Adam's original code), after having approved it a year ago.
#2 The entire struct could be added to all struct request_sock, but you already rejected adding fewer bytes to the much larger tcp_sock. And that isn't the best strategy, as request_sock otherwise would not have a cookie and is intended to be small.
#3 It's not possible to wrap and extend request_sock, as that is already done by IPv6 and others, causing a conflict. That was suggested by another maintainer, and I drafted some code last week, but wasn't able to figure out a non-conflicting code path.
#4 Passing a pointer parameter is the only option left that I've discovered. Now, you've rejected that as well....
So, lead me to "another way"?
Quoted 5 lines · William Allen Simpson
#3 It's not possible to wrap and extend
request_sock, as that is already done by IPv6 and others, causing a conflict. That was suggested by another maintainer, and I drafted some code last week, but wasn't able to figure out a non-conflicting code path.
After private discussion with others, I'm proposing a wrapper over a union of those other header files, that would ensure new fields would be beyond the previous extensions. It would have to be in its own .h file, and would have the unfortunate side effect of hauling in other protocols, but only into a very few net/ipv4/tcp*.c files.
The only advantage is that it doesn't matter how big this request_sock will become, as it is thrown away immediately after use (just like stack parameters in the previous proposal). Fourth time's the charm?
That is, something like:
#include <linux/ipv6.h>
#include <net/dccp/ipv6.h>
struct extend_request_sock {
union {
/* the biggest known */
struct tcp6_request_sock tcp6rsk;
struct dccp6_request_sock dccp6rsk;
} wrap;
u8 cookie_bakery[TCP_COOKIE_MAX];
u8 cookie_plus;
u8 cookie_in_always:1,
cookie_out_never:1;
}