mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	tcp: Remove TCPCT
TCPCT uses option-number 253, reserved for experimental use and should not be used in production environments. Further, TCPCT does not fully implement RFC 6013. As a nice side-effect, removing TCPCT increases TCP's performance for very short flows: Doing an apache-benchmark with -c 100 -n 100000, sending HTTP-requests for files of 1KB size. before this patch: average (among 7 runs) of 20845.5 Requests/Second after: average (among 7 runs) of 21403.6 Requests/Second Signed-off-by: Christoph Paasch <christoph.paasch@uclouvain.be> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									94d8f2b133
								
							
						
					
					
						commit
						1a2c6181c4
					
				
					 18 changed files with 37 additions and 840 deletions
				
			
		| 
						 | 
					@ -175,14 +175,6 @@ tcp_congestion_control - STRING
 | 
				
			||||||
	is inherited.
 | 
						is inherited.
 | 
				
			||||||
	[see setsockopt(listenfd, SOL_TCP, TCP_CONGESTION, "name" ...) ]
 | 
						[see setsockopt(listenfd, SOL_TCP, TCP_CONGESTION, "name" ...) ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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
 | 
					tcp_dsack - BOOLEAN
 | 
				
			||||||
	Allows TCP to send "duplicate" SACKs.
 | 
						Allows TCP to send "duplicate" SACKs.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2915,7 +2915,7 @@ static void build_cpl_pass_accept_req(struct sk_buff *skb, int stid , u8 tos)
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	memset(&tmp_opt, 0, sizeof(tmp_opt));
 | 
						memset(&tmp_opt, 0, sizeof(tmp_opt));
 | 
				
			||||||
	tcp_clear_options(&tmp_opt);
 | 
						tcp_clear_options(&tmp_opt);
 | 
				
			||||||
	tcp_parse_options(skb, &tmp_opt, NULL, 0, NULL);
 | 
						tcp_parse_options(skb, &tmp_opt, 0, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	req = (struct cpl_pass_accept_req *)__skb_push(skb, sizeof(*req));
 | 
						req = (struct cpl_pass_accept_req *)__skb_push(skb, sizeof(*req));
 | 
				
			||||||
	memset(req, 0, sizeof(*req));
 | 
						memset(req, 0, sizeof(*req));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -90,9 +90,6 @@ struct tcp_options_received {
 | 
				
			||||||
		sack_ok : 4,	/* SACK seen on SYN packet		*/
 | 
							sack_ok : 4,	/* SACK seen on SYN packet		*/
 | 
				
			||||||
		snd_wscale : 4,	/* Window scaling received from sender	*/
 | 
							snd_wscale : 4,	/* Window scaling received from sender	*/
 | 
				
			||||||
		rcv_wscale : 4;	/* Window scaling to send to receiver	*/
 | 
							rcv_wscale : 4;	/* Window scaling to send to receiver	*/
 | 
				
			||||||
	u8	cookie_plus:6,	/* bytes in authenticator/cookie option	*/
 | 
					 | 
				
			||||||
		cookie_out_never:1,
 | 
					 | 
				
			||||||
		cookie_in_always:1;
 | 
					 | 
				
			||||||
	u8	num_sacks;	/* Number of SACK blocks		*/
 | 
						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 */
 | 
						u16	mss_clamp;	/* Maximal mss, negotiated at connection setup */
 | 
				
			||||||
| 
						 | 
					@ -102,7 +99,6 @@ static inline void tcp_clear_options(struct tcp_options_received *rx_opt)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	rx_opt->tstamp_ok = rx_opt->sack_ok = 0;
 | 
						rx_opt->tstamp_ok = rx_opt->sack_ok = 0;
 | 
				
			||||||
	rx_opt->wscale_ok = rx_opt->snd_wscale = 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
 | 
					/* This is the max number of SACKS that we'll generate and process. It's safe
 | 
				
			||||||
| 
						 | 
					@ -320,12 +316,6 @@ struct tcp_sock {
 | 
				
			||||||
	struct tcp_md5sig_info	__rcu *md5sig_info;
 | 
						struct tcp_md5sig_info	__rcu *md5sig_info;
 | 
				
			||||||
#endif
 | 
					#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;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* TCP fastopen related information */
 | 
					/* TCP fastopen related information */
 | 
				
			||||||
	struct tcp_fastopen_request *fastopen_req;
 | 
						struct tcp_fastopen_request *fastopen_req;
 | 
				
			||||||
	/* fastopen_rsk points to request_sock that resulted in this big
 | 
						/* fastopen_rsk points to request_sock that resulted in this big
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,19 +27,13 @@ struct sk_buff;
 | 
				
			||||||
struct dst_entry;
 | 
					struct dst_entry;
 | 
				
			||||||
struct proto;
 | 
					struct proto;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* empty to "strongly type" an otherwise void parameter.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
struct request_values {
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct request_sock_ops {
 | 
					struct request_sock_ops {
 | 
				
			||||||
	int		family;
 | 
						int		family;
 | 
				
			||||||
	int		obj_size;
 | 
						int		obj_size;
 | 
				
			||||||
	struct kmem_cache	*slab;
 | 
						struct kmem_cache	*slab;
 | 
				
			||||||
	char		*slab_name;
 | 
						char		*slab_name;
 | 
				
			||||||
	int		(*rtx_syn_ack)(struct sock *sk,
 | 
						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,
 | 
						void		(*send_ack)(struct sock *sk, struct sk_buff *skb,
 | 
				
			||||||
				    struct request_sock *req);
 | 
									    struct request_sock *req);
 | 
				
			||||||
	void		(*send_reset)(struct sock *sk,
 | 
						void		(*send_reset)(struct sock *sk,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -179,7 +179,6 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo);
 | 
				
			||||||
#define TCPOPT_SACK             5       /* SACK Block */
 | 
					#define TCPOPT_SACK             5       /* SACK Block */
 | 
				
			||||||
#define TCPOPT_TIMESTAMP	8	/* Better RTT estimations/PAWS */
 | 
					#define TCPOPT_TIMESTAMP	8	/* Better RTT estimations/PAWS */
 | 
				
			||||||
#define TCPOPT_MD5SIG		19	/* MD5 Signature (RFC2385) */
 | 
					#define TCPOPT_MD5SIG		19	/* MD5 Signature (RFC2385) */
 | 
				
			||||||
#define TCPOPT_COOKIE		253	/* Cookie extension (experimental) */
 | 
					 | 
				
			||||||
#define TCPOPT_EXP		254	/* Experimental */
 | 
					#define TCPOPT_EXP		254	/* Experimental */
 | 
				
			||||||
/* Magic number to be after the option value for sharing TCP
 | 
					/* Magic number to be after the option value for sharing TCP
 | 
				
			||||||
 * experimental options. See draft-ietf-tcpm-experimental-options-00.txt
 | 
					 * experimental options. See draft-ietf-tcpm-experimental-options-00.txt
 | 
				
			||||||
| 
						 | 
					@ -454,7 +453,7 @@ extern void tcp_syn_ack_timeout(struct sock *sk, struct request_sock *req);
 | 
				
			||||||
extern int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 | 
					extern int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 | 
				
			||||||
		       size_t len, int nonblock, int flags, int *addr_len);
 | 
							       size_t len, int nonblock, int flags, int *addr_len);
 | 
				
			||||||
extern void tcp_parse_options(const struct sk_buff *skb,
 | 
					extern void tcp_parse_options(const struct sk_buff *skb,
 | 
				
			||||||
			      struct tcp_options_received *opt_rx, const u8 **hvpp,
 | 
								      struct tcp_options_received *opt_rx,
 | 
				
			||||||
			      int estab, struct tcp_fastopen_cookie *foc);
 | 
								      int estab, struct tcp_fastopen_cookie *foc);
 | 
				
			||||||
extern const u8 *tcp_parse_md5sig_option(const struct tcphdr *th);
 | 
					extern const u8 *tcp_parse_md5sig_option(const struct tcphdr *th);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -476,7 +475,6 @@ extern int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr,
 | 
				
			||||||
extern int tcp_connect(struct sock *sk);
 | 
					extern int tcp_connect(struct sock *sk);
 | 
				
			||||||
extern struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst,
 | 
					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,
 | 
					 | 
				
			||||||
					struct tcp_fastopen_cookie *foc);
 | 
										struct tcp_fastopen_cookie *foc);
 | 
				
			||||||
extern int tcp_disconnect(struct sock *sk, int flags);
 | 
					extern int tcp_disconnect(struct sock *sk, int flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1589,91 +1587,6 @@ struct tcp_request_sock_ops {
 | 
				
			||||||
#endif
 | 
					#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);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 *	struct tcp_cookie_values - each socket needs extra space for the
 | 
					 | 
				
			||||||
 *	cookies, together with (optional) space for any SYN data.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *	A tcp_sock contains a pointer to the current value, and this is
 | 
					 | 
				
			||||||
 *	cloned to the tcp_timewait_sock.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @cookie_pair:	variable data from the option exchange.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @cookie_desired:	user specified tcpct_cookie_desired.  Zero
 | 
					 | 
				
			||||||
 *			indicates default (sysctl_tcp_cookie_size).
 | 
					 | 
				
			||||||
 *			After cookie sent, remembers size of cookie.
 | 
					 | 
				
			||||||
 *			Range 0, TCP_COOKIE_MIN to TCP_COOKIE_MAX.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @s_data_desired:	user specified tcpct_s_data_desired.  When the
 | 
					 | 
				
			||||||
 *			constant payload is specified (@s_data_constant),
 | 
					 | 
				
			||||||
 *			holds its length instead.
 | 
					 | 
				
			||||||
 *			Range 0 to TCP_MSS_DESIRED.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @s_data_payload:	constant data that is to be included in the
 | 
					 | 
				
			||||||
 *			payload of SYN or SYNACK segments when the
 | 
					 | 
				
			||||||
 *			cookie option is present.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
struct tcp_cookie_values {
 | 
					 | 
				
			||||||
	struct kref	kref;
 | 
					 | 
				
			||||||
	u8		cookie_pair[TCP_COOKIE_PAIR_SIZE];
 | 
					 | 
				
			||||||
	u8		cookie_pair_size;
 | 
					 | 
				
			||||||
	u8		cookie_desired;
 | 
					 | 
				
			||||||
	u16		s_data_desired:11,
 | 
					 | 
				
			||||||
			s_data_constant:1,
 | 
					 | 
				
			||||||
			s_data_in:1,
 | 
					 | 
				
			||||||
			s_data_out:1,
 | 
					 | 
				
			||||||
			s_data_unused:2;
 | 
					 | 
				
			||||||
	u8		s_data_payload[0];
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline void tcp_cookie_values_release(struct kref *kref)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	kfree(container_of(kref, struct tcp_cookie_values, kref));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* The length of constant payload data.  Note that s_data_desired is
 | 
					 | 
				
			||||||
 * overloaded, depending on s_data_constant: either the length of constant
 | 
					 | 
				
			||||||
 * data (returned here) or the limit on variable data.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static inline int tcp_s_data_size(const struct tcp_sock *tp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return (tp->cookie_values != NULL && tp->cookie_values->s_data_constant)
 | 
					 | 
				
			||||||
		? tp->cookie_values->s_data_desired
 | 
					 | 
				
			||||||
		: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 *	struct tcp_extend_values - tcp_ipv?.c to tcp_output.c workspace.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *	As tcp_request_sock has already been extended in other places, the
 | 
					 | 
				
			||||||
 *	only remaining method is to pass stack values along as function
 | 
					 | 
				
			||||||
 *	parameters.  These parameters are not needed after sending SYNACK.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @cookie_bakery:	cryptographic secret and message workspace.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @cookie_plus:	bytes in authenticator/cookie option, copied from
 | 
					 | 
				
			||||||
 *			struct tcp_options_received (above).
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
struct tcp_extend_values {
 | 
					 | 
				
			||||||
	struct request_values		rv;
 | 
					 | 
				
			||||||
	u32				cookie_bakery[COOKIE_WORKSPACE_WORDS];
 | 
					 | 
				
			||||||
	u8				cookie_plus:6,
 | 
					 | 
				
			||||||
					cookie_out_never:1,
 | 
					 | 
				
			||||||
					cookie_in_always:1;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline struct tcp_extend_values *tcp_xv(struct request_values *rvp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return (struct tcp_extend_values *)rvp;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern void tcp_v4_init(void);
 | 
					extern void tcp_v4_init(void);
 | 
				
			||||||
extern void tcp_init(void);
 | 
					extern void tcp_init(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -102,7 +102,6 @@ enum {
 | 
				
			||||||
#define TCP_QUICKACK		12	/* Block/reenable quick acks */
 | 
					#define TCP_QUICKACK		12	/* Block/reenable quick acks */
 | 
				
			||||||
#define TCP_CONGESTION		13	/* Congestion control algorithm */
 | 
					#define TCP_CONGESTION		13	/* Congestion control algorithm */
 | 
				
			||||||
#define TCP_MD5SIG		14	/* TCP MD5 Signature (RFC2385) */
 | 
					#define TCP_MD5SIG		14	/* TCP MD5 Signature (RFC2385) */
 | 
				
			||||||
#define TCP_COOKIE_TRANSACTIONS	15	/* TCP Cookie Transactions */
 | 
					 | 
				
			||||||
#define TCP_THIN_LINEAR_TIMEOUTS 16      /* Use linear timeouts for thin streams*/
 | 
					#define TCP_THIN_LINEAR_TIMEOUTS 16      /* Use linear timeouts for thin streams*/
 | 
				
			||||||
#define TCP_THIN_DUPACK         17      /* Fast retrans. after 1 dupack */
 | 
					#define TCP_THIN_DUPACK         17      /* Fast retrans. after 1 dupack */
 | 
				
			||||||
#define TCP_USER_TIMEOUT	18	/* How long for loss retry before timeout */
 | 
					#define TCP_USER_TIMEOUT	18	/* How long for loss retry before timeout */
 | 
				
			||||||
| 
						 | 
					@ -199,29 +198,4 @@ struct tcp_md5sig {
 | 
				
			||||||
	__u8	tcpm_key[TCP_MD5SIG_MAXKEYLEN];		/* key (binary) */
 | 
						__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];
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif /* _UAPI_LINUX_TCP_H */
 | 
					#endif /* _UAPI_LINUX_TCP_H */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -500,8 +500,7 @@ static struct dst_entry* dccp_v4_route_skb(struct net *net, struct sock *sk,
 | 
				
			||||||
	return &rt->dst;
 | 
						return &rt->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;
 | 
						int err = -1;
 | 
				
			||||||
	struct sk_buff *skb;
 | 
						struct sk_buff *skb;
 | 
				
			||||||
| 
						 | 
					@ -658,7 +657,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
 | 
				
			||||||
	dreq->dreq_gss     = dreq->dreq_iss;
 | 
						dreq->dreq_gss     = dreq->dreq_iss;
 | 
				
			||||||
	dreq->dreq_service = service;
 | 
						dreq->dreq_service = service;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (dccp_v4_send_response(sk, req, NULL))
 | 
						if (dccp_v4_send_response(sk, req))
 | 
				
			||||||
		goto drop_and_free;
 | 
							goto drop_and_free;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inet_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT);
 | 
						inet_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -213,8 +213,7 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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 inet6_request_sock *ireq6 = inet6_rsk(req);
 | 
				
			||||||
	struct ipv6_pinfo *np = inet6_sk(sk);
 | 
						struct ipv6_pinfo *np = inet6_sk(sk);
 | 
				
			||||||
| 
						 | 
					@ -428,7 +427,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
 | 
				
			||||||
	dreq->dreq_gss     = dreq->dreq_iss;
 | 
						dreq->dreq_gss     = dreq->dreq_iss;
 | 
				
			||||||
	dreq->dreq_service = service;
 | 
						dreq->dreq_service = service;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (dccp_v6_send_response(sk, req, NULL))
 | 
						if (dccp_v6_send_response(sk, req))
 | 
				
			||||||
		goto drop_and_free;
 | 
							goto drop_and_free;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inet6_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT);
 | 
						inet6_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -559,7 +559,7 @@ static inline void syn_ack_recalc(struct request_sock *req, const int thresh,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int inet_rtx_syn_ack(struct sock *parent, struct request_sock *req)
 | 
					int inet_rtx_syn_ack(struct sock *parent, struct request_sock *req)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int err = req->rsk_ops->rtx_syn_ack(parent, req, NULL);
 | 
						int err = req->rsk_ops->rtx_syn_ack(parent, req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!err)
 | 
						if (!err)
 | 
				
			||||||
		req->num_retrans++;
 | 
							req->num_retrans++;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -267,7 +267,6 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
 | 
				
			||||||
			     struct ip_options *opt)
 | 
								     struct ip_options *opt)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct tcp_options_received tcp_opt;
 | 
						struct tcp_options_received tcp_opt;
 | 
				
			||||||
	const u8 *hash_location;
 | 
					 | 
				
			||||||
	struct inet_request_sock *ireq;
 | 
						struct inet_request_sock *ireq;
 | 
				
			||||||
	struct tcp_request_sock *treq;
 | 
						struct tcp_request_sock *treq;
 | 
				
			||||||
	struct tcp_sock *tp = tcp_sk(sk);
 | 
						struct tcp_sock *tp = tcp_sk(sk);
 | 
				
			||||||
| 
						 | 
					@ -294,7 +293,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* check for timestamp cookie support */
 | 
						/* check for timestamp cookie support */
 | 
				
			||||||
	memset(&tcp_opt, 0, sizeof(tcp_opt));
 | 
						memset(&tcp_opt, 0, sizeof(tcp_opt));
 | 
				
			||||||
	tcp_parse_options(skb, &tcp_opt, &hash_location, 0, NULL);
 | 
						tcp_parse_options(skb, &tcp_opt, 0, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!cookie_check_timestamp(&tcp_opt, sock_net(sk), &ecn_ok))
 | 
						if (!cookie_check_timestamp(&tcp_opt, sock_net(sk), &ecn_ok))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -732,13 +732,6 @@ static struct ctl_table ipv4_table[] = {
 | 
				
			||||||
		.mode		= 0644,
 | 
							.mode		= 0644,
 | 
				
			||||||
		.proc_handler	= proc_dointvec,
 | 
							.proc_handler	= proc_dointvec,
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		.procname	= "tcp_cookie_size",
 | 
					 | 
				
			||||||
		.data		= &sysctl_tcp_cookie_size,
 | 
					 | 
				
			||||||
		.maxlen		= sizeof(int),
 | 
					 | 
				
			||||||
		.mode		= 0644,
 | 
					 | 
				
			||||||
		.proc_handler	= proc_dointvec
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		.procname       = "tcp_thin_linear_timeouts",
 | 
							.procname       = "tcp_thin_linear_timeouts",
 | 
				
			||||||
		.data           = &sysctl_tcp_thin_linear_timeouts,
 | 
							.data           = &sysctl_tcp_thin_linear_timeouts,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										267
									
								
								net/ipv4/tcp.c
									
									
									
									
									
								
							
							
						
						
									
										267
									
								
								net/ipv4/tcp.c
									
									
									
									
									
								
							| 
						 | 
					@ -409,15 +409,6 @@ void tcp_init_sock(struct sock *sk)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	icsk->icsk_sync_mss = tcp_sync_mss;
 | 
						icsk->icsk_sync_mss = tcp_sync_mss;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* 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:
 | 
						/* Presumed zeroed, in order of appearance:
 | 
				
			||||||
	 *	cookie_in_always, cookie_out_never,
 | 
						 *	cookie_in_always, cookie_out_never,
 | 
				
			||||||
	 *	s_data_constant, s_data_in, s_data_out
 | 
						 *	s_data_constant, s_data_in, s_data_out
 | 
				
			||||||
| 
						 | 
					@ -2397,92 +2388,6 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
 | 
				
			||||||
		release_sock(sk);
 | 
							release_sock(sk);
 | 
				
			||||||
		return err;
 | 
							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;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			kref_init(&cvp->kref);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		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);
 | 
					 | 
				
			||||||
			} 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 */
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			tp->cookie_values = cvp;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		release_sock(sk);
 | 
					 | 
				
			||||||
		return err;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		/* fallthru */
 | 
							/* fallthru */
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
| 
						 | 
					@ -2902,41 +2807,6 @@ static int do_tcp_getsockopt(struct sock *sk, int level,
 | 
				
			||||||
			return -EFAULT;
 | 
								return -EFAULT;
 | 
				
			||||||
		return 0;
 | 
							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;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			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;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	case TCP_THIN_LINEAR_TIMEOUTS:
 | 
						case TCP_THIN_LINEAR_TIMEOUTS:
 | 
				
			||||||
		val = tp->thin_lto;
 | 
							val = tp->thin_lto;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
| 
						 | 
					@ -3409,134 +3279,6 @@ EXPORT_SYMBOL(tcp_md5_hash_key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Each Responder maintains up to two secret values concurrently for
 | 
					 | 
				
			||||||
 * efficient secret rollover.  Each secret value has 4 states:
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Generating.  (tcp_secret_generating != tcp_secret_primary)
 | 
					 | 
				
			||||||
 *    Generates new Responder-Cookies, but not yet used for primary
 | 
					 | 
				
			||||||
 *    verification.  This is a short-term state, typically lasting only
 | 
					 | 
				
			||||||
 *    one round trip time (RTT).
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Primary.  (tcp_secret_generating == tcp_secret_primary)
 | 
					 | 
				
			||||||
 *    Used both for generation and primary verification.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Retiring.  (tcp_secret_retiring != tcp_secret_secondary)
 | 
					 | 
				
			||||||
 *    Used for verification, until the first failure that can be
 | 
					 | 
				
			||||||
 *    verified by the newer Generating secret.  At that time, this
 | 
					 | 
				
			||||||
 *    cookie's state is changed to Secondary, and the Generating
 | 
					 | 
				
			||||||
 *    cookie's state is changed to Primary.  This is a short-term state,
 | 
					 | 
				
			||||||
 *    typically lasting only one round trip time (RTT).
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Secondary.  (tcp_secret_retiring == tcp_secret_secondary)
 | 
					 | 
				
			||||||
 *    Used for secondary verification, after primary verification
 | 
					 | 
				
			||||||
 *    failures.  This state lasts no more than twice the Maximum Segment
 | 
					 | 
				
			||||||
 *    Lifetime (2MSL).  Then, the secret is discarded.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
struct tcp_cookie_secret {
 | 
					 | 
				
			||||||
	/* The secret is divided into two parts.  The digest part is the
 | 
					 | 
				
			||||||
	 * equivalent of previously hashing a secret and saving the state,
 | 
					 | 
				
			||||||
	 * and serves as an initialization vector (IV).  The message part
 | 
					 | 
				
			||||||
	 * serves as the trailing secret.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	u32				secrets[COOKIE_WORKSPACE_WORDS];
 | 
					 | 
				
			||||||
	unsigned long			expires;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define TCP_SECRET_1MSL (HZ * TCP_PAWS_MSL)
 | 
					 | 
				
			||||||
#define TCP_SECRET_2MSL (HZ * TCP_PAWS_MSL * 2)
 | 
					 | 
				
			||||||
#define TCP_SECRET_LIFE (HZ * 600)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static struct tcp_cookie_secret tcp_secret_one;
 | 
					 | 
				
			||||||
static struct tcp_cookie_secret tcp_secret_two;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Essentially a circular list, without dynamic allocation. */
 | 
					 | 
				
			||||||
static struct tcp_cookie_secret *tcp_secret_generating;
 | 
					 | 
				
			||||||
static struct tcp_cookie_secret *tcp_secret_primary;
 | 
					 | 
				
			||||||
static struct tcp_cookie_secret *tcp_secret_retiring;
 | 
					 | 
				
			||||||
static struct tcp_cookie_secret *tcp_secret_secondary;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static DEFINE_SPINLOCK(tcp_secret_locker);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Select a pseudo-random word in the cookie workspace.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static inline u32 tcp_cookie_work(const u32 *ws, const int n)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return ws[COOKIE_DIGEST_WORDS + ((COOKIE_MESSAGE_WORDS-1) & ws[n])];
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Fill bakery[COOKIE_WORKSPACE_WORDS] with generator, updating as needed.
 | 
					 | 
				
			||||||
 * Called in softirq context.
 | 
					 | 
				
			||||||
 * Returns: 0 for success.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
int tcp_cookie_generator(u32 *bakery)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	unsigned long jiffy = jiffies;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (unlikely(time_after_eq(jiffy, tcp_secret_generating->expires))) {
 | 
					 | 
				
			||||||
		spin_lock_bh(&tcp_secret_locker);
 | 
					 | 
				
			||||||
		if (!time_after_eq(jiffy, tcp_secret_generating->expires)) {
 | 
					 | 
				
			||||||
			/* refreshed by another */
 | 
					 | 
				
			||||||
			memcpy(bakery,
 | 
					 | 
				
			||||||
			       &tcp_secret_generating->secrets[0],
 | 
					 | 
				
			||||||
			       COOKIE_WORKSPACE_WORDS);
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			/* still needs refreshing */
 | 
					 | 
				
			||||||
			get_random_bytes(bakery, COOKIE_WORKSPACE_WORDS);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			/* The first time, paranoia assumes that the
 | 
					 | 
				
			||||||
			 * randomization function isn't as strong.  But,
 | 
					 | 
				
			||||||
			 * this secret initialization is delayed until
 | 
					 | 
				
			||||||
			 * the last possible moment (packet arrival).
 | 
					 | 
				
			||||||
			 * Although that time is observable, it is
 | 
					 | 
				
			||||||
			 * unpredictably variable.  Mash in the most
 | 
					 | 
				
			||||||
			 * volatile clock bits available, and expire the
 | 
					 | 
				
			||||||
			 * secret extra quickly.
 | 
					 | 
				
			||||||
			 */
 | 
					 | 
				
			||||||
			if (unlikely(tcp_secret_primary->expires ==
 | 
					 | 
				
			||||||
				     tcp_secret_secondary->expires)) {
 | 
					 | 
				
			||||||
				struct timespec tv;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				getnstimeofday(&tv);
 | 
					 | 
				
			||||||
				bakery[COOKIE_DIGEST_WORDS+0] ^=
 | 
					 | 
				
			||||||
					(u32)tv.tv_nsec;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				tcp_secret_secondary->expires = jiffy
 | 
					 | 
				
			||||||
					+ TCP_SECRET_1MSL
 | 
					 | 
				
			||||||
					+ (0x0f & tcp_cookie_work(bakery, 0));
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				tcp_secret_secondary->expires = jiffy
 | 
					 | 
				
			||||||
					+ TCP_SECRET_LIFE
 | 
					 | 
				
			||||||
					+ (0xff & tcp_cookie_work(bakery, 1));
 | 
					 | 
				
			||||||
				tcp_secret_primary->expires = jiffy
 | 
					 | 
				
			||||||
					+ TCP_SECRET_2MSL
 | 
					 | 
				
			||||||
					+ (0x1f & tcp_cookie_work(bakery, 2));
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			memcpy(&tcp_secret_secondary->secrets[0],
 | 
					 | 
				
			||||||
			       bakery, COOKIE_WORKSPACE_WORDS);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			rcu_assign_pointer(tcp_secret_generating,
 | 
					 | 
				
			||||||
					   tcp_secret_secondary);
 | 
					 | 
				
			||||||
			rcu_assign_pointer(tcp_secret_retiring,
 | 
					 | 
				
			||||||
					   tcp_secret_primary);
 | 
					 | 
				
			||||||
			/*
 | 
					 | 
				
			||||||
			 * Neither call_rcu() nor synchronize_rcu() needed.
 | 
					 | 
				
			||||||
			 * Retiring data is not freed.  It is replaced after
 | 
					 | 
				
			||||||
			 * further (locked) pointer updates, and a quiet time
 | 
					 | 
				
			||||||
			 * (minimum 1MSL, maximum LIFE - 2MSL).
 | 
					 | 
				
			||||||
			 */
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		spin_unlock_bh(&tcp_secret_locker);
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		rcu_read_lock_bh();
 | 
					 | 
				
			||||||
		memcpy(bakery,
 | 
					 | 
				
			||||||
		       &rcu_dereference(tcp_secret_generating)->secrets[0],
 | 
					 | 
				
			||||||
		       COOKIE_WORKSPACE_WORDS);
 | 
					 | 
				
			||||||
		rcu_read_unlock_bh();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
EXPORT_SYMBOL(tcp_cookie_generator);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void tcp_done(struct sock *sk)
 | 
					void tcp_done(struct sock *sk)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct request_sock *req = tcp_sk(sk)->fastopen_rsk;
 | 
						struct request_sock *req = tcp_sk(sk)->fastopen_rsk;
 | 
				
			||||||
| 
						 | 
					@ -3591,7 +3333,6 @@ void __init tcp_init(void)
 | 
				
			||||||
	unsigned long limit;
 | 
						unsigned long limit;
 | 
				
			||||||
	int max_rshare, max_wshare, cnt;
 | 
						int max_rshare, max_wshare, cnt;
 | 
				
			||||||
	unsigned int i;
 | 
						unsigned int i;
 | 
				
			||||||
	unsigned long jiffy = jiffies;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	BUILD_BUG_ON(sizeof(struct tcp_skb_cb) > sizeof(skb->cb));
 | 
						BUILD_BUG_ON(sizeof(struct tcp_skb_cb) > sizeof(skb->cb));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3667,13 +3408,5 @@ void __init tcp_init(void)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tcp_register_congestion_control(&tcp_reno);
 | 
						tcp_register_congestion_control(&tcp_reno);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memset(&tcp_secret_one.secrets[0], 0, sizeof(tcp_secret_one.secrets));
 | 
					 | 
				
			||||||
	memset(&tcp_secret_two.secrets[0], 0, sizeof(tcp_secret_two.secrets));
 | 
					 | 
				
			||||||
	tcp_secret_one.expires = jiffy; /* past due */
 | 
					 | 
				
			||||||
	tcp_secret_two.expires = jiffy; /* past due */
 | 
					 | 
				
			||||||
	tcp_secret_generating = &tcp_secret_one;
 | 
					 | 
				
			||||||
	tcp_secret_primary = &tcp_secret_one;
 | 
					 | 
				
			||||||
	tcp_secret_retiring = &tcp_secret_two;
 | 
					 | 
				
			||||||
	tcp_secret_secondary = &tcp_secret_two;
 | 
					 | 
				
			||||||
	tcp_tasklet_init();
 | 
						tcp_tasklet_init();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3760,8 +3760,8 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
 | 
				
			||||||
 * But, this can also be called on packets in the established flow when
 | 
					 * But, this can also be called on packets in the established flow when
 | 
				
			||||||
 * the fast version below fails.
 | 
					 * the fast version below fails.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void tcp_parse_options(const struct sk_buff *skb, struct tcp_options_received *opt_rx,
 | 
					void tcp_parse_options(const struct sk_buff *skb,
 | 
				
			||||||
		       const u8 **hvpp, int estab,
 | 
							       struct tcp_options_received *opt_rx, int estab,
 | 
				
			||||||
		       struct tcp_fastopen_cookie *foc)
 | 
							       struct tcp_fastopen_cookie *foc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const unsigned char *ptr;
 | 
						const unsigned char *ptr;
 | 
				
			||||||
| 
						 | 
					@ -3845,31 +3845,6 @@ void tcp_parse_options(const struct sk_buff *skb, struct tcp_options_received *o
 | 
				
			||||||
				 */
 | 
									 */
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
			case TCPOPT_COOKIE:
 | 
					 | 
				
			||||||
				/* This option is variable length.
 | 
					 | 
				
			||||||
				 */
 | 
					 | 
				
			||||||
				switch (opsize) {
 | 
					 | 
				
			||||||
				case TCPOLEN_COOKIE_BASE:
 | 
					 | 
				
			||||||
					/* not yet implemented */
 | 
					 | 
				
			||||||
					break;
 | 
					 | 
				
			||||||
				case TCPOLEN_COOKIE_PAIR:
 | 
					 | 
				
			||||||
					/* not yet implemented */
 | 
					 | 
				
			||||||
					break;
 | 
					 | 
				
			||||||
				case TCPOLEN_COOKIE_MIN+0:
 | 
					 | 
				
			||||||
				case TCPOLEN_COOKIE_MIN+2:
 | 
					 | 
				
			||||||
				case TCPOLEN_COOKIE_MIN+4:
 | 
					 | 
				
			||||||
				case TCPOLEN_COOKIE_MIN+6:
 | 
					 | 
				
			||||||
				case TCPOLEN_COOKIE_MAX:
 | 
					 | 
				
			||||||
					/* 16-bit multiple */
 | 
					 | 
				
			||||||
					opt_rx->cookie_plus = opsize;
 | 
					 | 
				
			||||||
					*hvpp = ptr;
 | 
					 | 
				
			||||||
					break;
 | 
					 | 
				
			||||||
				default:
 | 
					 | 
				
			||||||
					/* ignore option */
 | 
					 | 
				
			||||||
					break;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			case TCPOPT_EXP:
 | 
								case TCPOPT_EXP:
 | 
				
			||||||
				/* Fast Open option shares code 254 using a
 | 
									/* Fast Open option shares code 254 using a
 | 
				
			||||||
				 * 16 bits magic number. It's valid only in
 | 
									 * 16 bits magic number. It's valid only in
 | 
				
			||||||
| 
						 | 
					@ -3915,8 +3890,7 @@ static bool tcp_parse_aligned_timestamp(struct tcp_sock *tp, const struct tcphdr
 | 
				
			||||||
 * If it is wrong it falls back on tcp_parse_options().
 | 
					 * If it is wrong it falls back on tcp_parse_options().
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static bool tcp_fast_parse_options(const struct sk_buff *skb,
 | 
					static bool tcp_fast_parse_options(const struct sk_buff *skb,
 | 
				
			||||||
				   const struct tcphdr *th,
 | 
									   const struct tcphdr *th, struct tcp_sock *tp)
 | 
				
			||||||
				   struct tcp_sock *tp, const u8 **hvpp)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	/* In the spirit of fast parsing, compare doff directly to constant
 | 
						/* In the spirit of fast parsing, compare doff directly to constant
 | 
				
			||||||
	 * values.  Because equality is used, short doff can be ignored here.
 | 
						 * values.  Because equality is used, short doff can be ignored here.
 | 
				
			||||||
| 
						 | 
					@ -3930,7 +3904,7 @@ static bool tcp_fast_parse_options(const struct sk_buff *skb,
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tcp_parse_options(skb, &tp->rx_opt, hvpp, 1, NULL);
 | 
						tcp_parse_options(skb, &tp->rx_opt, 1, NULL);
 | 
				
			||||||
	if (tp->rx_opt.saw_tstamp)
 | 
						if (tp->rx_opt.saw_tstamp)
 | 
				
			||||||
		tp->rx_opt.rcv_tsecr -= tp->tsoffset;
 | 
							tp->rx_opt.rcv_tsecr -= tp->tsoffset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5311,12 +5285,10 @@ static bool tcp_dma_try_early_copy(struct sock *sk, struct sk_buff *skb,
 | 
				
			||||||
static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,
 | 
					static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,
 | 
				
			||||||
				  const struct tcphdr *th, int syn_inerr)
 | 
									  const struct tcphdr *th, int syn_inerr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const u8 *hash_location;
 | 
					 | 
				
			||||||
	struct tcp_sock *tp = tcp_sk(sk);
 | 
						struct tcp_sock *tp = tcp_sk(sk);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* RFC1323: H1. Apply PAWS check first. */
 | 
						/* RFC1323: H1. Apply PAWS check first. */
 | 
				
			||||||
	if (tcp_fast_parse_options(skb, th, tp, &hash_location) &&
 | 
						if (tcp_fast_parse_options(skb, th, tp) && tp->rx_opt.saw_tstamp &&
 | 
				
			||||||
	    tp->rx_opt.saw_tstamp &&
 | 
					 | 
				
			||||||
	    tcp_paws_discard(sk, skb)) {
 | 
						    tcp_paws_discard(sk, skb)) {
 | 
				
			||||||
		if (!th->rst) {
 | 
							if (!th->rst) {
 | 
				
			||||||
			NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSESTABREJECTED);
 | 
								NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSESTABREJECTED);
 | 
				
			||||||
| 
						 | 
					@ -5670,12 +5642,11 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (mss == tp->rx_opt.user_mss) {
 | 
						if (mss == tp->rx_opt.user_mss) {
 | 
				
			||||||
		struct tcp_options_received opt;
 | 
							struct tcp_options_received opt;
 | 
				
			||||||
		const u8 *hash_location;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Get original SYNACK MSS value if user MSS sets mss_clamp */
 | 
							/* Get original SYNACK MSS value if user MSS sets mss_clamp */
 | 
				
			||||||
		tcp_clear_options(&opt);
 | 
							tcp_clear_options(&opt);
 | 
				
			||||||
		opt.user_mss = opt.mss_clamp = 0;
 | 
							opt.user_mss = opt.mss_clamp = 0;
 | 
				
			||||||
		tcp_parse_options(synack, &opt, &hash_location, 0, NULL);
 | 
							tcp_parse_options(synack, &opt, 0, NULL);
 | 
				
			||||||
		mss = opt.mss_clamp;
 | 
							mss = opt.mss_clamp;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5706,14 +5677,12 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack,
 | 
				
			||||||
static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
 | 
					static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
 | 
				
			||||||
					 const struct tcphdr *th, unsigned int len)
 | 
										 const struct tcphdr *th, unsigned int len)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const u8 *hash_location;
 | 
					 | 
				
			||||||
	struct inet_connection_sock *icsk = inet_csk(sk);
 | 
						struct inet_connection_sock *icsk = inet_csk(sk);
 | 
				
			||||||
	struct tcp_sock *tp = tcp_sk(sk);
 | 
						struct tcp_sock *tp = tcp_sk(sk);
 | 
				
			||||||
	struct tcp_cookie_values *cvp = tp->cookie_values;
 | 
					 | 
				
			||||||
	struct tcp_fastopen_cookie foc = { .len = -1 };
 | 
						struct tcp_fastopen_cookie foc = { .len = -1 };
 | 
				
			||||||
	int saved_clamp = tp->rx_opt.mss_clamp;
 | 
						int saved_clamp = tp->rx_opt.mss_clamp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tcp_parse_options(skb, &tp->rx_opt, &hash_location, 0, &foc);
 | 
						tcp_parse_options(skb, &tp->rx_opt, 0, &foc);
 | 
				
			||||||
	if (tp->rx_opt.saw_tstamp)
 | 
						if (tp->rx_opt.saw_tstamp)
 | 
				
			||||||
		tp->rx_opt.rcv_tsecr -= tp->tsoffset;
 | 
							tp->rx_opt.rcv_tsecr -= tp->tsoffset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5810,30 +5779,6 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
 | 
				
			||||||
		 * is initialized. */
 | 
							 * is initialized. */
 | 
				
			||||||
		tp->copied_seq = tp->rcv_nxt;
 | 
							tp->copied_seq = tp->rcv_nxt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (cvp != NULL &&
 | 
					 | 
				
			||||||
		    cvp->cookie_pair_size > 0 &&
 | 
					 | 
				
			||||||
		    tp->rx_opt.cookie_plus > 0) {
 | 
					 | 
				
			||||||
			int cookie_size = tp->rx_opt.cookie_plus
 | 
					 | 
				
			||||||
					- TCPOLEN_COOKIE_BASE;
 | 
					 | 
				
			||||||
			int cookie_pair_size = cookie_size
 | 
					 | 
				
			||||||
					     + cvp->cookie_desired;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			/* A cookie extension option was sent and returned.
 | 
					 | 
				
			||||||
			 * Note that each incoming SYNACK replaces the
 | 
					 | 
				
			||||||
			 * Responder cookie.  The initial exchange is most
 | 
					 | 
				
			||||||
			 * fragile, as protection against spoofing relies
 | 
					 | 
				
			||||||
			 * entirely upon the sequence and timestamp (above).
 | 
					 | 
				
			||||||
			 * This replacement strategy allows the correct pair to
 | 
					 | 
				
			||||||
			 * pass through, while any others will be filtered via
 | 
					 | 
				
			||||||
			 * Responder verification later.
 | 
					 | 
				
			||||||
			 */
 | 
					 | 
				
			||||||
			if (sizeof(cvp->cookie_pair) >= cookie_pair_size) {
 | 
					 | 
				
			||||||
				memcpy(&cvp->cookie_pair[cvp->cookie_desired],
 | 
					 | 
				
			||||||
				       hash_location, cookie_size);
 | 
					 | 
				
			||||||
				cvp->cookie_pair_size = cookie_pair_size;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		smp_mb();
 | 
							smp_mb();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		tcp_finish_connect(sk, skb);
 | 
							tcp_finish_connect(sk, skb);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -838,7 +838,6 @@ static void tcp_v4_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst,
 | 
					static int tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst,
 | 
				
			||||||
			      struct request_sock *req,
 | 
								      struct request_sock *req,
 | 
				
			||||||
			      struct request_values *rvp,
 | 
					 | 
				
			||||||
			      u16 queue_mapping,
 | 
								      u16 queue_mapping,
 | 
				
			||||||
			      bool nocache)
 | 
								      bool nocache)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -851,7 +850,7 @@ static int tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst,
 | 
				
			||||||
	if (!dst && (dst = inet_csk_route_req(sk, &fl4, req)) == NULL)
 | 
						if (!dst && (dst = inet_csk_route_req(sk, &fl4, req)) == NULL)
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	skb = tcp_make_synack(sk, dst, req, rvp, NULL);
 | 
						skb = tcp_make_synack(sk, dst, req, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (skb) {
 | 
						if (skb) {
 | 
				
			||||||
		__tcp_v4_send_check(skb, ireq->loc_addr, ireq->rmt_addr);
 | 
							__tcp_v4_send_check(skb, ireq->loc_addr, ireq->rmt_addr);
 | 
				
			||||||
| 
						 | 
					@ -868,10 +867,9 @@ static int tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst,
 | 
				
			||||||
	return err;
 | 
						return err;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int tcp_v4_rtx_synack(struct sock *sk, struct request_sock *req,
 | 
					static int tcp_v4_rtx_synack(struct sock *sk, struct request_sock *req)
 | 
				
			||||||
			     struct request_values *rvp)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int res = tcp_v4_send_synack(sk, NULL, req, rvp, 0, false);
 | 
						int res = tcp_v4_send_synack(sk, NULL, req, 0, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!res)
 | 
						if (!res)
 | 
				
			||||||
		TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS);
 | 
							TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS);
 | 
				
			||||||
| 
						 | 
					@ -1371,8 +1369,7 @@ static bool tcp_fastopen_check(struct sock *sk, struct sk_buff *skb,
 | 
				
			||||||
static int tcp_v4_conn_req_fastopen(struct sock *sk,
 | 
					static int tcp_v4_conn_req_fastopen(struct sock *sk,
 | 
				
			||||||
				    struct sk_buff *skb,
 | 
									    struct sk_buff *skb,
 | 
				
			||||||
				    struct sk_buff *skb_synack,
 | 
									    struct sk_buff *skb_synack,
 | 
				
			||||||
				    struct request_sock *req,
 | 
									    struct request_sock *req)
 | 
				
			||||||
				    struct request_values *rvp)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct tcp_sock *tp = tcp_sk(sk);
 | 
						struct tcp_sock *tp = tcp_sk(sk);
 | 
				
			||||||
	struct request_sock_queue *queue = &inet_csk(sk)->icsk_accept_queue;
 | 
						struct request_sock_queue *queue = &inet_csk(sk)->icsk_accept_queue;
 | 
				
			||||||
| 
						 | 
					@ -1467,9 +1464,7 @@ static int tcp_v4_conn_req_fastopen(struct sock *sk,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
 | 
					int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct tcp_extend_values tmp_ext;
 | 
					 | 
				
			||||||
	struct tcp_options_received tmp_opt;
 | 
						struct tcp_options_received tmp_opt;
 | 
				
			||||||
	const u8 *hash_location;
 | 
					 | 
				
			||||||
	struct request_sock *req;
 | 
						struct request_sock *req;
 | 
				
			||||||
	struct inet_request_sock *ireq;
 | 
						struct inet_request_sock *ireq;
 | 
				
			||||||
	struct tcp_sock *tp = tcp_sk(sk);
 | 
						struct tcp_sock *tp = tcp_sk(sk);
 | 
				
			||||||
| 
						 | 
					@ -1519,42 +1514,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
 | 
				
			||||||
	tcp_clear_options(&tmp_opt);
 | 
						tcp_clear_options(&tmp_opt);
 | 
				
			||||||
	tmp_opt.mss_clamp = TCP_MSS_DEFAULT;
 | 
						tmp_opt.mss_clamp = TCP_MSS_DEFAULT;
 | 
				
			||||||
	tmp_opt.user_mss  = tp->rx_opt.user_mss;
 | 
						tmp_opt.user_mss  = tp->rx_opt.user_mss;
 | 
				
			||||||
	tcp_parse_options(skb, &tmp_opt, &hash_location, 0,
 | 
						tcp_parse_options(skb, &tmp_opt, 0, want_cookie ? NULL : &foc);
 | 
				
			||||||
	    want_cookie ? NULL : &foc);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (tmp_opt.cookie_plus > 0 &&
 | 
					 | 
				
			||||||
	    tmp_opt.saw_tstamp &&
 | 
					 | 
				
			||||||
	    !tp->rx_opt.cookie_out_never &&
 | 
					 | 
				
			||||||
	    (sysctl_tcp_cookie_size > 0 ||
 | 
					 | 
				
			||||||
	     (tp->cookie_values != NULL &&
 | 
					 | 
				
			||||||
	      tp->cookie_values->cookie_desired > 0))) {
 | 
					 | 
				
			||||||
		u8 *c;
 | 
					 | 
				
			||||||
		u32 *mess = &tmp_ext.cookie_bakery[COOKIE_DIGEST_WORDS];
 | 
					 | 
				
			||||||
		int l = tmp_opt.cookie_plus - TCPOLEN_COOKIE_BASE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (tcp_cookie_generator(&tmp_ext.cookie_bakery[0]) != 0)
 | 
					 | 
				
			||||||
			goto drop_and_release;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* Secret recipe starts with IP addresses */
 | 
					 | 
				
			||||||
		*mess++ ^= (__force u32)daddr;
 | 
					 | 
				
			||||||
		*mess++ ^= (__force u32)saddr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* plus variable length Initiator Cookie */
 | 
					 | 
				
			||||||
		c = (u8 *)mess;
 | 
					 | 
				
			||||||
		while (l-- > 0)
 | 
					 | 
				
			||||||
			*c++ ^= *hash_location++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		want_cookie = false;	/* not our kind of cookie */
 | 
					 | 
				
			||||||
		tmp_ext.cookie_out_never = 0; /* false */
 | 
					 | 
				
			||||||
		tmp_ext.cookie_plus = tmp_opt.cookie_plus;
 | 
					 | 
				
			||||||
	} else if (!tp->rx_opt.cookie_in_always) {
 | 
					 | 
				
			||||||
		/* redundant indications, but ensure initialization. */
 | 
					 | 
				
			||||||
		tmp_ext.cookie_out_never = 1; /* true */
 | 
					 | 
				
			||||||
		tmp_ext.cookie_plus = 0;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		goto drop_and_release;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	tmp_ext.cookie_in_always = tp->rx_opt.cookie_in_always;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (want_cookie && !tmp_opt.saw_tstamp)
 | 
						if (want_cookie && !tmp_opt.saw_tstamp)
 | 
				
			||||||
		tcp_clear_options(&tmp_opt);
 | 
							tcp_clear_options(&tmp_opt);
 | 
				
			||||||
| 
						 | 
					@ -1636,7 +1596,6 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
 | 
				
			||||||
	 * of tcp_v4_send_synack()->tcp_select_initial_window().
 | 
						 * of tcp_v4_send_synack()->tcp_select_initial_window().
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	skb_synack = tcp_make_synack(sk, dst, req,
 | 
						skb_synack = tcp_make_synack(sk, dst, req,
 | 
				
			||||||
	    (struct request_values *)&tmp_ext,
 | 
					 | 
				
			||||||
	    fastopen_cookie_present(&valid_foc) ? &valid_foc : NULL);
 | 
						    fastopen_cookie_present(&valid_foc) ? &valid_foc : NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (skb_synack) {
 | 
						if (skb_synack) {
 | 
				
			||||||
| 
						 | 
					@ -1660,8 +1619,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
 | 
				
			||||||
		if (fastopen_cookie_present(&foc) && foc.len != 0)
 | 
							if (fastopen_cookie_present(&foc) && foc.len != 0)
 | 
				
			||||||
			NET_INC_STATS_BH(sock_net(sk),
 | 
								NET_INC_STATS_BH(sock_net(sk),
 | 
				
			||||||
			    LINUX_MIB_TCPFASTOPENPASSIVEFAIL);
 | 
								    LINUX_MIB_TCPFASTOPENPASSIVEFAIL);
 | 
				
			||||||
	} else if (tcp_v4_conn_req_fastopen(sk, skb, skb_synack, req,
 | 
						} else if (tcp_v4_conn_req_fastopen(sk, skb, skb_synack, req))
 | 
				
			||||||
	    (struct request_values *)&tmp_ext))
 | 
					 | 
				
			||||||
		goto drop_and_free;
 | 
							goto drop_and_free;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					@ -2241,12 +2199,6 @@ void tcp_v4_destroy_sock(struct sock *sk)
 | 
				
			||||||
	if (inet_csk(sk)->icsk_bind_hash)
 | 
						if (inet_csk(sk)->icsk_bind_hash)
 | 
				
			||||||
		inet_put_port(sk);
 | 
							inet_put_port(sk);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* TCP Cookie Transactions */
 | 
					 | 
				
			||||||
	if (tp->cookie_values != NULL) {
 | 
					 | 
				
			||||||
		kref_put(&tp->cookie_values->kref,
 | 
					 | 
				
			||||||
			 tcp_cookie_values_release);
 | 
					 | 
				
			||||||
		tp->cookie_values = NULL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	BUG_ON(tp->fastopen_rsk != NULL);
 | 
						BUG_ON(tp->fastopen_rsk != NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* If socket is aborted during connect operation */
 | 
						/* If socket is aborted during connect operation */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -93,13 +93,12 @@ tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb,
 | 
				
			||||||
			   const struct tcphdr *th)
 | 
								   const struct tcphdr *th)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct tcp_options_received tmp_opt;
 | 
						struct tcp_options_received tmp_opt;
 | 
				
			||||||
	const u8 *hash_location;
 | 
					 | 
				
			||||||
	struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw);
 | 
						struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw);
 | 
				
			||||||
	bool paws_reject = false;
 | 
						bool paws_reject = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tmp_opt.saw_tstamp = 0;
 | 
						tmp_opt.saw_tstamp = 0;
 | 
				
			||||||
	if (th->doff > (sizeof(*th) >> 2) && tcptw->tw_ts_recent_stamp) {
 | 
						if (th->doff > (sizeof(*th) >> 2) && tcptw->tw_ts_recent_stamp) {
 | 
				
			||||||
		tcp_parse_options(skb, &tmp_opt, &hash_location, 0, NULL);
 | 
							tcp_parse_options(skb, &tmp_opt, 0, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (tmp_opt.saw_tstamp) {
 | 
							if (tmp_opt.saw_tstamp) {
 | 
				
			||||||
			tmp_opt.rcv_tsecr	-= tcptw->tw_ts_offset;
 | 
								tmp_opt.rcv_tsecr	-= tcptw->tw_ts_offset;
 | 
				
			||||||
| 
						 | 
					@ -388,32 +387,6 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,
 | 
				
			||||||
		struct tcp_request_sock *treq = tcp_rsk(req);
 | 
							struct tcp_request_sock *treq = tcp_rsk(req);
 | 
				
			||||||
		struct inet_connection_sock *newicsk = inet_csk(newsk);
 | 
							struct inet_connection_sock *newicsk = inet_csk(newsk);
 | 
				
			||||||
		struct tcp_sock *newtp = tcp_sk(newsk);
 | 
							struct tcp_sock *newtp = tcp_sk(newsk);
 | 
				
			||||||
		struct tcp_sock *oldtp = tcp_sk(sk);
 | 
					 | 
				
			||||||
		struct tcp_cookie_values *oldcvp = oldtp->cookie_values;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* TCP Cookie Transactions require space for the cookie pair,
 | 
					 | 
				
			||||||
		 * as it differs for each connection.  There is no need to
 | 
					 | 
				
			||||||
		 * copy any s_data_payload stored at the original socket.
 | 
					 | 
				
			||||||
		 * Failure will prevent resuming the connection.
 | 
					 | 
				
			||||||
		 *
 | 
					 | 
				
			||||||
		 * Presumed copied, in order of appearance:
 | 
					 | 
				
			||||||
		 *	cookie_in_always, cookie_out_never
 | 
					 | 
				
			||||||
		 */
 | 
					 | 
				
			||||||
		if (oldcvp != NULL) {
 | 
					 | 
				
			||||||
			struct tcp_cookie_values *newcvp =
 | 
					 | 
				
			||||||
				kzalloc(sizeof(*newtp->cookie_values),
 | 
					 | 
				
			||||||
					GFP_ATOMIC);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (newcvp != NULL) {
 | 
					 | 
				
			||||||
				kref_init(&newcvp->kref);
 | 
					 | 
				
			||||||
				newcvp->cookie_desired =
 | 
					 | 
				
			||||||
						oldcvp->cookie_desired;
 | 
					 | 
				
			||||||
				newtp->cookie_values = newcvp;
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				/* Not Yet Implemented */
 | 
					 | 
				
			||||||
				newtp->cookie_values = NULL;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Now setup tcp_sock */
 | 
							/* Now setup tcp_sock */
 | 
				
			||||||
		newtp->pred_flags = 0;
 | 
							newtp->pred_flags = 0;
 | 
				
			||||||
| 
						 | 
					@ -422,8 +395,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,
 | 
				
			||||||
		newtp->rcv_nxt = treq->rcv_isn + 1;
 | 
							newtp->rcv_nxt = treq->rcv_isn + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		newtp->snd_sml = newtp->snd_una =
 | 
							newtp->snd_sml = newtp->snd_una =
 | 
				
			||||||
		newtp->snd_nxt = newtp->snd_up =
 | 
							newtp->snd_nxt = newtp->snd_up = treq->snt_isn + 1;
 | 
				
			||||||
			treq->snt_isn + 1 + tcp_s_data_size(oldtp);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		tcp_prequeue_init(newtp);
 | 
							tcp_prequeue_init(newtp);
 | 
				
			||||||
		INIT_LIST_HEAD(&newtp->tsq_node);
 | 
							INIT_LIST_HEAD(&newtp->tsq_node);
 | 
				
			||||||
| 
						 | 
					@ -460,8 +432,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,
 | 
				
			||||||
		tcp_set_ca_state(newsk, TCP_CA_Open);
 | 
							tcp_set_ca_state(newsk, TCP_CA_Open);
 | 
				
			||||||
		tcp_init_xmit_timers(newsk);
 | 
							tcp_init_xmit_timers(newsk);
 | 
				
			||||||
		skb_queue_head_init(&newtp->out_of_order_queue);
 | 
							skb_queue_head_init(&newtp->out_of_order_queue);
 | 
				
			||||||
		newtp->write_seq = newtp->pushed_seq =
 | 
							newtp->write_seq = newtp->pushed_seq = treq->snt_isn + 1;
 | 
				
			||||||
			treq->snt_isn + 1 + tcp_s_data_size(oldtp);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		newtp->rx_opt.saw_tstamp = 0;
 | 
							newtp->rx_opt.saw_tstamp = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -538,7 +509,6 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
 | 
				
			||||||
			   bool fastopen)
 | 
								   bool fastopen)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct tcp_options_received tmp_opt;
 | 
						struct tcp_options_received tmp_opt;
 | 
				
			||||||
	const u8 *hash_location;
 | 
					 | 
				
			||||||
	struct sock *child;
 | 
						struct sock *child;
 | 
				
			||||||
	const struct tcphdr *th = tcp_hdr(skb);
 | 
						const struct tcphdr *th = tcp_hdr(skb);
 | 
				
			||||||
	__be32 flg = tcp_flag_word(th) & (TCP_FLAG_RST|TCP_FLAG_SYN|TCP_FLAG_ACK);
 | 
						__be32 flg = tcp_flag_word(th) & (TCP_FLAG_RST|TCP_FLAG_SYN|TCP_FLAG_ACK);
 | 
				
			||||||
| 
						 | 
					@ -548,7 +518,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tmp_opt.saw_tstamp = 0;
 | 
						tmp_opt.saw_tstamp = 0;
 | 
				
			||||||
	if (th->doff > (sizeof(struct tcphdr)>>2)) {
 | 
						if (th->doff > (sizeof(struct tcphdr)>>2)) {
 | 
				
			||||||
		tcp_parse_options(skb, &tmp_opt, &hash_location, 0, NULL);
 | 
							tcp_parse_options(skb, &tmp_opt, 0, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (tmp_opt.saw_tstamp) {
 | 
							if (tmp_opt.saw_tstamp) {
 | 
				
			||||||
			tmp_opt.ts_recent = req->ts_recent;
 | 
								tmp_opt.ts_recent = req->ts_recent;
 | 
				
			||||||
| 
						 | 
					@ -648,7 +618,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if ((flg & TCP_FLAG_ACK) && !fastopen &&
 | 
						if ((flg & TCP_FLAG_ACK) && !fastopen &&
 | 
				
			||||||
	    (TCP_SKB_CB(skb)->ack_seq !=
 | 
						    (TCP_SKB_CB(skb)->ack_seq !=
 | 
				
			||||||
	     tcp_rsk(req)->snt_isn + 1 + tcp_s_data_size(tcp_sk(sk))))
 | 
						     tcp_rsk(req)->snt_isn + 1))
 | 
				
			||||||
		return sk;
 | 
							return sk;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Also, it would be not so bad idea to check rcv_tsecr, which
 | 
						/* Also, it would be not so bad idea to check rcv_tsecr, which
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -65,9 +65,6 @@ int sysctl_tcp_base_mss __read_mostly = TCP_BASE_MSS;
 | 
				
			||||||
/* By default, RFC2861 behavior.  */
 | 
					/* By default, RFC2861 behavior.  */
 | 
				
			||||||
int sysctl_tcp_slow_start_after_idle __read_mostly = 1;
 | 
					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);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
 | 
					static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
 | 
				
			||||||
			   int push_one, gfp_t gfp);
 | 
								   int push_one, gfp_t gfp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -386,7 +383,6 @@ static inline bool tcp_urg_mode(const struct tcp_sock *tp)
 | 
				
			||||||
#define OPTION_TS		(1 << 1)
 | 
					#define OPTION_TS		(1 << 1)
 | 
				
			||||||
#define OPTION_MD5		(1 << 2)
 | 
					#define OPTION_MD5		(1 << 2)
 | 
				
			||||||
#define OPTION_WSCALE		(1 << 3)
 | 
					#define OPTION_WSCALE		(1 << 3)
 | 
				
			||||||
#define OPTION_COOKIE_EXTENSION	(1 << 4)
 | 
					 | 
				
			||||||
#define OPTION_FAST_OPEN_COOKIE	(1 << 8)
 | 
					#define OPTION_FAST_OPEN_COOKIE	(1 << 8)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct tcp_out_options {
 | 
					struct tcp_out_options {
 | 
				
			||||||
| 
						 | 
					@ -400,36 +396,6 @@ struct tcp_out_options {
 | 
				
			||||||
	struct tcp_fastopen_cookie *fastopen_cookie;	/* Fast open cookie */
 | 
						struct tcp_fastopen_cookie *fastopen_cookie;	/* Fast open cookie */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* The sysctl int routines are generic, so check consistency here.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static u8 tcp_cookie_size_check(u8 desired)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int cookie_size;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (desired > 0)
 | 
					 | 
				
			||||||
		/* previously specified */
 | 
					 | 
				
			||||||
		return desired;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cookie_size = ACCESS_ONCE(sysctl_tcp_cookie_size);
 | 
					 | 
				
			||||||
	if (cookie_size <= 0)
 | 
					 | 
				
			||||||
		/* no default specified */
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (cookie_size <= TCP_COOKIE_MIN)
 | 
					 | 
				
			||||||
		/* value too small, specify minimum */
 | 
					 | 
				
			||||||
		return TCP_COOKIE_MIN;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (cookie_size >= TCP_COOKIE_MAX)
 | 
					 | 
				
			||||||
		/* value too large, specify maximum */
 | 
					 | 
				
			||||||
		return TCP_COOKIE_MAX;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (cookie_size & 1)
 | 
					 | 
				
			||||||
		/* 8-bit multiple, illegal, fix it */
 | 
					 | 
				
			||||||
		cookie_size++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return (u8)cookie_size;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Write previously computed TCP options to the packet.
 | 
					/* Write previously computed TCP options to the packet.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Beware: Something in the Internet is very sensitive to the ordering of
 | 
					 * Beware: Something in the Internet is very sensitive to the ordering of
 | 
				
			||||||
| 
						 | 
					@ -448,27 +414,9 @@ static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	u16 options = opts->options;	/* mungable copy */
 | 
						u16 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_MD5 & options)) {
 | 
				
			||||||
		if (unlikely(OPTION_COOKIE_EXTENSION & options)) {
 | 
							*ptr++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
 | 
				
			||||||
			*ptr++ = htonl((TCPOPT_COOKIE << 24) |
 | 
								       (TCPOPT_MD5SIG << 8) | TCPOLEN_MD5SIG);
 | 
				
			||||||
				       (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 */
 | 
							/* overload cookie hash location */
 | 
				
			||||||
		opts->hash_location = (__u8 *)ptr;
 | 
							opts->hash_location = (__u8 *)ptr;
 | 
				
			||||||
		ptr += 4;
 | 
							ptr += 4;
 | 
				
			||||||
| 
						 | 
					@ -497,44 +445,6 @@ static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp,
 | 
				
			||||||
		*ptr++ = htonl(opts->tsecr);
 | 
							*ptr++ = htonl(opts->tsecr);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* 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)) {
 | 
						if (unlikely(OPTION_SACK_ADVERTISE & options)) {
 | 
				
			||||||
		*ptr++ = htonl((TCPOPT_NOP << 24) |
 | 
							*ptr++ = htonl((TCPOPT_NOP << 24) |
 | 
				
			||||||
			       (TCPOPT_NOP << 16) |
 | 
								       (TCPOPT_NOP << 16) |
 | 
				
			||||||
| 
						 | 
					@ -593,11 +503,7 @@ static unsigned int tcp_syn_options(struct sock *sk, struct sk_buff *skb,
 | 
				
			||||||
				struct tcp_md5sig_key **md5)
 | 
									struct tcp_md5sig_key **md5)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct tcp_sock *tp = tcp_sk(sk);
 | 
						struct tcp_sock *tp = tcp_sk(sk);
 | 
				
			||||||
	struct tcp_cookie_values *cvp = tp->cookie_values;
 | 
					 | 
				
			||||||
	unsigned int remaining = MAX_TCP_OPTION_SPACE;
 | 
						unsigned int remaining = MAX_TCP_OPTION_SPACE;
 | 
				
			||||||
	u8 cookie_size = (!tp->rx_opt.cookie_out_never && cvp != NULL) ?
 | 
					 | 
				
			||||||
			 tcp_cookie_size_check(cvp->cookie_desired) :
 | 
					 | 
				
			||||||
			 0;
 | 
					 | 
				
			||||||
	struct tcp_fastopen_request *fastopen = tp->fastopen_req;
 | 
						struct tcp_fastopen_request *fastopen = tp->fastopen_req;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_TCP_MD5SIG
 | 
					#ifdef CONFIG_TCP_MD5SIG
 | 
				
			||||||
| 
						 | 
					@ -649,52 +555,7 @@ static unsigned int tcp_syn_options(struct sock *sk, struct sk_buff *skb,
 | 
				
			||||||
			tp->syn_fastopen = 1;
 | 
								tp->syn_fastopen = 1;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	/* 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;
 | 
						return MAX_TCP_OPTION_SPACE - remaining;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -704,14 +565,10 @@ static unsigned int tcp_synack_options(struct sock *sk,
 | 
				
			||||||
				   unsigned int mss, struct sk_buff *skb,
 | 
									   unsigned int mss, struct sk_buff *skb,
 | 
				
			||||||
				   struct tcp_out_options *opts,
 | 
									   struct tcp_out_options *opts,
 | 
				
			||||||
				   struct tcp_md5sig_key **md5,
 | 
									   struct tcp_md5sig_key **md5,
 | 
				
			||||||
				   struct tcp_extend_values *xvp,
 | 
					 | 
				
			||||||
				   struct tcp_fastopen_cookie *foc)
 | 
									   struct tcp_fastopen_cookie *foc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct inet_request_sock *ireq = inet_rsk(req);
 | 
						struct inet_request_sock *ireq = inet_rsk(req);
 | 
				
			||||||
	unsigned int remaining = MAX_TCP_OPTION_SPACE;
 | 
						unsigned int remaining = MAX_TCP_OPTION_SPACE;
 | 
				
			||||||
	u8 cookie_plus = (xvp != NULL && !xvp->cookie_out_never) ?
 | 
					 | 
				
			||||||
			 xvp->cookie_plus :
 | 
					 | 
				
			||||||
			 0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_TCP_MD5SIG
 | 
					#ifdef CONFIG_TCP_MD5SIG
 | 
				
			||||||
	*md5 = tcp_rsk(req)->af_specific->md5_lookup(sk, req);
 | 
						*md5 = tcp_rsk(req)->af_specific->md5_lookup(sk, req);
 | 
				
			||||||
| 
						 | 
					@ -759,28 +616,7 @@ static unsigned int tcp_synack_options(struct sock *sk,
 | 
				
			||||||
			remaining -= need;
 | 
								remaining -= need;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	/* Similar rationale to tcp_syn_options() applies here, too.
 | 
					 | 
				
			||||||
	 * If the <SYN> options fit, the same options should fit now!
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	if (*md5 == NULL &&
 | 
					 | 
				
			||||||
	    ireq->tstamp_ok &&
 | 
					 | 
				
			||||||
	    cookie_plus > TCPOLEN_COOKIE_BASE) {
 | 
					 | 
				
			||||||
		int need = cookie_plus; /* has TCPOLEN_COOKIE_BASE */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (0x2 & need) {
 | 
					 | 
				
			||||||
			/* 32-bit multiple */
 | 
					 | 
				
			||||||
			need += 2; /* NOPs */
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if (need <= remaining) {
 | 
					 | 
				
			||||||
			opts->options |= OPTION_COOKIE_EXTENSION;
 | 
					 | 
				
			||||||
			opts->hash_size = cookie_plus - TCPOLEN_COOKIE_BASE;
 | 
					 | 
				
			||||||
			remaining -= need;
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			/* There's no error return, so flag it. */
 | 
					 | 
				
			||||||
			xvp->cookie_out_never = 1; /* true */
 | 
					 | 
				
			||||||
			opts->hash_size = 0;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return MAX_TCP_OPTION_SPACE - remaining;
 | 
						return MAX_TCP_OPTION_SPACE - remaining;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2802,32 +2638,24 @@ int tcp_send_synack(struct sock *sk)
 | 
				
			||||||
 * sk: listener socket
 | 
					 * sk: listener socket
 | 
				
			||||||
 * dst: dst entry attached to the SYNACK
 | 
					 * dst: dst entry attached to the SYNACK
 | 
				
			||||||
 * req: request_sock pointer
 | 
					 * req: request_sock pointer
 | 
				
			||||||
 * rvp: request_values pointer
 | 
					 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Allocate one skb and build a SYNACK packet.
 | 
					 * Allocate one skb and build a SYNACK packet.
 | 
				
			||||||
 * @dst is consumed : Caller should not use it again.
 | 
					 * @dst is consumed : Caller should not use it again.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
 | 
					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 tcp_fastopen_cookie *foc)
 | 
									struct tcp_fastopen_cookie *foc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct tcp_out_options opts;
 | 
						struct tcp_out_options opts;
 | 
				
			||||||
	struct tcp_extend_values *xvp = tcp_xv(rvp);
 | 
					 | 
				
			||||||
	struct inet_request_sock *ireq = inet_rsk(req);
 | 
						struct inet_request_sock *ireq = inet_rsk(req);
 | 
				
			||||||
	struct tcp_sock *tp = tcp_sk(sk);
 | 
						struct tcp_sock *tp = tcp_sk(sk);
 | 
				
			||||||
	const struct tcp_cookie_values *cvp = tp->cookie_values;
 | 
					 | 
				
			||||||
	struct tcphdr *th;
 | 
						struct tcphdr *th;
 | 
				
			||||||
	struct sk_buff *skb;
 | 
						struct sk_buff *skb;
 | 
				
			||||||
	struct tcp_md5sig_key *md5;
 | 
						struct tcp_md5sig_key *md5;
 | 
				
			||||||
	int tcp_header_size;
 | 
						int tcp_header_size;
 | 
				
			||||||
	int mss;
 | 
						int mss;
 | 
				
			||||||
	int s_data_desired = 0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (cvp != NULL && cvp->s_data_constant && cvp->s_data_desired)
 | 
						skb = alloc_skb(MAX_TCP_HEADER + 15, sk_gfp_atomic(sk, GFP_ATOMIC));
 | 
				
			||||||
		s_data_desired = cvp->s_data_desired;
 | 
					 | 
				
			||||||
	skb = alloc_skb(MAX_TCP_HEADER + 15 + s_data_desired,
 | 
					 | 
				
			||||||
			sk_gfp_atomic(sk, GFP_ATOMIC));
 | 
					 | 
				
			||||||
	if (unlikely(!skb)) {
 | 
						if (unlikely(!skb)) {
 | 
				
			||||||
		dst_release(dst);
 | 
							dst_release(dst);
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
| 
						 | 
					@ -2869,9 +2697,8 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
	TCP_SKB_CB(skb)->when = tcp_time_stamp;
 | 
						TCP_SKB_CB(skb)->when = tcp_time_stamp;
 | 
				
			||||||
	tcp_header_size = tcp_synack_options(sk, req, mss,
 | 
						tcp_header_size = tcp_synack_options(sk, req, mss, skb, &opts, &md5,
 | 
				
			||||||
					     skb, &opts, &md5, xvp, foc)
 | 
										     foc) + sizeof(*th);
 | 
				
			||||||
			+ sizeof(*th);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	skb_push(skb, tcp_header_size);
 | 
						skb_push(skb, tcp_header_size);
 | 
				
			||||||
	skb_reset_transport_header(skb);
 | 
						skb_reset_transport_header(skb);
 | 
				
			||||||
| 
						 | 
					@ -2889,40 +2716,6 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
 | 
				
			||||||
	tcp_init_nondata_skb(skb, tcp_rsk(req)->snt_isn,
 | 
						tcp_init_nondata_skb(skb, tcp_rsk(req)->snt_isn,
 | 
				
			||||||
			     TCPHDR_SYN | TCPHDR_ACK);
 | 
								     TCPHDR_SYN | TCPHDR_ACK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (OPTION_COOKIE_EXTENSION & opts.options) {
 | 
					 | 
				
			||||||
		if (s_data_desired) {
 | 
					 | 
				
			||||||
			u8 *buf = skb_put(skb, s_data_desired);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			/* copy data directly from the listening socket. */
 | 
					 | 
				
			||||||
			memcpy(buf, cvp->s_data_payload, s_data_desired);
 | 
					 | 
				
			||||||
			TCP_SKB_CB(skb)->end_seq += s_data_desired;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (opts.hash_size > 0) {
 | 
					 | 
				
			||||||
			__u32 workspace[SHA_WORKSPACE_WORDS];
 | 
					 | 
				
			||||||
			u32 *mess = &xvp->cookie_bakery[COOKIE_DIGEST_WORDS];
 | 
					 | 
				
			||||||
			u32 *tail = &mess[COOKIE_MESSAGE_WORDS-1];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			/* Secret recipe depends on the Timestamp, (future)
 | 
					 | 
				
			||||||
			 * Sequence and Acknowledgment Numbers, Initiator
 | 
					 | 
				
			||||||
			 * Cookie, and others handled by IP variant caller.
 | 
					 | 
				
			||||||
			 */
 | 
					 | 
				
			||||||
			*tail-- ^= opts.tsval;
 | 
					 | 
				
			||||||
			*tail-- ^= tcp_rsk(req)->rcv_isn + 1;
 | 
					 | 
				
			||||||
			*tail-- ^= TCP_SKB_CB(skb)->seq + 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			/* recommended */
 | 
					 | 
				
			||||||
			*tail-- ^= (((__force u32)th->dest << 16) | (__force u32)th->source);
 | 
					 | 
				
			||||||
			*tail-- ^= (u32)(unsigned long)cvp; /* per sockopt */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			sha_transform((__u32 *)&xvp->cookie_bakery[0],
 | 
					 | 
				
			||||||
				      (char *)mess,
 | 
					 | 
				
			||||||
				      &workspace[0]);
 | 
					 | 
				
			||||||
			opts.hash_location =
 | 
					 | 
				
			||||||
				(__u8 *)&xvp->cookie_bakery[0];
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	th->seq = htonl(TCP_SKB_CB(skb)->seq);
 | 
						th->seq = htonl(TCP_SKB_CB(skb)->seq);
 | 
				
			||||||
	/* XXX data is queued and acked as is. No buffer/window check */
 | 
						/* XXX data is queued and acked as is. No buffer/window check */
 | 
				
			||||||
	th->ack_seq = htonl(tcp_rsk(req)->rcv_nxt);
 | 
						th->ack_seq = htonl(tcp_rsk(req)->rcv_nxt);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -149,7 +149,6 @@ static inline int cookie_check(const struct sk_buff *skb, __u32 cookie)
 | 
				
			||||||
struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
 | 
					struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct tcp_options_received tcp_opt;
 | 
						struct tcp_options_received tcp_opt;
 | 
				
			||||||
	const u8 *hash_location;
 | 
					 | 
				
			||||||
	struct inet_request_sock *ireq;
 | 
						struct inet_request_sock *ireq;
 | 
				
			||||||
	struct inet6_request_sock *ireq6;
 | 
						struct inet6_request_sock *ireq6;
 | 
				
			||||||
	struct tcp_request_sock *treq;
 | 
						struct tcp_request_sock *treq;
 | 
				
			||||||
| 
						 | 
					@ -177,7 +176,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* check for timestamp cookie support */
 | 
						/* check for timestamp cookie support */
 | 
				
			||||||
	memset(&tcp_opt, 0, sizeof(tcp_opt));
 | 
						memset(&tcp_opt, 0, sizeof(tcp_opt));
 | 
				
			||||||
	tcp_parse_options(skb, &tcp_opt, &hash_location, 0, NULL);
 | 
						tcp_parse_options(skb, &tcp_opt, 0, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!cookie_check_timestamp(&tcp_opt, sock_net(sk), &ecn_ok))
 | 
						if (!cookie_check_timestamp(&tcp_opt, sock_net(sk), &ecn_ok))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -454,7 +454,6 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 | 
				
			||||||
static int tcp_v6_send_synack(struct sock *sk, struct dst_entry *dst,
 | 
					static int tcp_v6_send_synack(struct sock *sk, struct dst_entry *dst,
 | 
				
			||||||
			      struct flowi6 *fl6,
 | 
								      struct flowi6 *fl6,
 | 
				
			||||||
			      struct request_sock *req,
 | 
								      struct request_sock *req,
 | 
				
			||||||
			      struct request_values *rvp,
 | 
					 | 
				
			||||||
			      u16 queue_mapping)
 | 
								      u16 queue_mapping)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct inet6_request_sock *treq = inet6_rsk(req);
 | 
						struct inet6_request_sock *treq = inet6_rsk(req);
 | 
				
			||||||
| 
						 | 
					@ -466,7 +465,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct dst_entry *dst,
 | 
				
			||||||
	if (!dst && (dst = inet6_csk_route_req(sk, fl6, req)) == NULL)
 | 
						if (!dst && (dst = inet6_csk_route_req(sk, fl6, req)) == NULL)
 | 
				
			||||||
		goto done;
 | 
							goto done;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	skb = tcp_make_synack(sk, dst, req, rvp, NULL);
 | 
						skb = tcp_make_synack(sk, dst, req, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (skb) {
 | 
						if (skb) {
 | 
				
			||||||
		__tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr);
 | 
							__tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr);
 | 
				
			||||||
| 
						 | 
					@ -481,13 +480,12 @@ static int tcp_v6_send_synack(struct sock *sk, struct dst_entry *dst,
 | 
				
			||||||
	return err;
 | 
						return err;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int tcp_v6_rtx_synack(struct sock *sk, struct request_sock *req,
 | 
					static int tcp_v6_rtx_synack(struct sock *sk, struct request_sock *req)
 | 
				
			||||||
			     struct request_values *rvp)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct flowi6 fl6;
 | 
						struct flowi6 fl6;
 | 
				
			||||||
	int res;
 | 
						int res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	res = tcp_v6_send_synack(sk, NULL, &fl6, req, rvp, 0);
 | 
						res = tcp_v6_send_synack(sk, NULL, &fl6, req, 0);
 | 
				
			||||||
	if (!res)
 | 
						if (!res)
 | 
				
			||||||
		TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS);
 | 
							TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS);
 | 
				
			||||||
	return res;
 | 
						return res;
 | 
				
			||||||
| 
						 | 
					@ -940,9 +938,7 @@ 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)
 | 
					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;
 | 
						struct tcp_options_received tmp_opt;
 | 
				
			||||||
	const u8 *hash_location;
 | 
					 | 
				
			||||||
	struct request_sock *req;
 | 
						struct request_sock *req;
 | 
				
			||||||
	struct inet6_request_sock *treq;
 | 
						struct inet6_request_sock *treq;
 | 
				
			||||||
	struct ipv6_pinfo *np = inet6_sk(sk);
 | 
						struct ipv6_pinfo *np = inet6_sk(sk);
 | 
				
			||||||
| 
						 | 
					@ -980,50 +976,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
 | 
				
			||||||
	tcp_clear_options(&tmp_opt);
 | 
						tcp_clear_options(&tmp_opt);
 | 
				
			||||||
	tmp_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr);
 | 
						tmp_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr);
 | 
				
			||||||
	tmp_opt.user_mss = tp->rx_opt.user_mss;
 | 
						tmp_opt.user_mss = tp->rx_opt.user_mss;
 | 
				
			||||||
	tcp_parse_options(skb, &tmp_opt, &hash_location, 0, NULL);
 | 
						tcp_parse_options(skb, &tmp_opt, 0, NULL);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (tmp_opt.cookie_plus > 0 &&
 | 
					 | 
				
			||||||
	    tmp_opt.saw_tstamp &&
 | 
					 | 
				
			||||||
	    !tp->rx_opt.cookie_out_never &&
 | 
					 | 
				
			||||||
	    (sysctl_tcp_cookie_size > 0 ||
 | 
					 | 
				
			||||||
	     (tp->cookie_values != NULL &&
 | 
					 | 
				
			||||||
	      tp->cookie_values->cookie_desired > 0))) {
 | 
					 | 
				
			||||||
		u8 *c;
 | 
					 | 
				
			||||||
		u32 *d;
 | 
					 | 
				
			||||||
		u32 *mess = &tmp_ext.cookie_bakery[COOKIE_DIGEST_WORDS];
 | 
					 | 
				
			||||||
		int l = tmp_opt.cookie_plus - TCPOLEN_COOKIE_BASE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (tcp_cookie_generator(&tmp_ext.cookie_bakery[0]) != 0)
 | 
					 | 
				
			||||||
			goto drop_and_free;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* Secret recipe starts with IP addresses */
 | 
					 | 
				
			||||||
		d = (__force u32 *)&ipv6_hdr(skb)->daddr.s6_addr32[0];
 | 
					 | 
				
			||||||
		*mess++ ^= *d++;
 | 
					 | 
				
			||||||
		*mess++ ^= *d++;
 | 
					 | 
				
			||||||
		*mess++ ^= *d++;
 | 
					 | 
				
			||||||
		*mess++ ^= *d++;
 | 
					 | 
				
			||||||
		d = (__force u32 *)&ipv6_hdr(skb)->saddr.s6_addr32[0];
 | 
					 | 
				
			||||||
		*mess++ ^= *d++;
 | 
					 | 
				
			||||||
		*mess++ ^= *d++;
 | 
					 | 
				
			||||||
		*mess++ ^= *d++;
 | 
					 | 
				
			||||||
		*mess++ ^= *d++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* plus variable length Initiator Cookie */
 | 
					 | 
				
			||||||
		c = (u8 *)mess;
 | 
					 | 
				
			||||||
		while (l-- > 0)
 | 
					 | 
				
			||||||
			*c++ ^= *hash_location++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		want_cookie = false;	/* not our kind of cookie */
 | 
					 | 
				
			||||||
		tmp_ext.cookie_out_never = 0; /* false */
 | 
					 | 
				
			||||||
		tmp_ext.cookie_plus = tmp_opt.cookie_plus;
 | 
					 | 
				
			||||||
	} else if (!tp->rx_opt.cookie_in_always) {
 | 
					 | 
				
			||||||
		/* redundant indications, but ensure initialization. */
 | 
					 | 
				
			||||||
		tmp_ext.cookie_out_never = 1; /* true */
 | 
					 | 
				
			||||||
		tmp_ext.cookie_plus = 0;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		goto drop_and_free;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	tmp_ext.cookie_in_always = tp->rx_opt.cookie_in_always;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (want_cookie && !tmp_opt.saw_tstamp)
 | 
						if (want_cookie && !tmp_opt.saw_tstamp)
 | 
				
			||||||
		tcp_clear_options(&tmp_opt);
 | 
							tcp_clear_options(&tmp_opt);
 | 
				
			||||||
| 
						 | 
					@ -1101,7 +1054,6 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
 | 
				
			||||||
		goto drop_and_release;
 | 
							goto drop_and_release;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (tcp_v6_send_synack(sk, dst, &fl6, req,
 | 
						if (tcp_v6_send_synack(sk, dst, &fl6, req,
 | 
				
			||||||
			       (struct request_values *)&tmp_ext,
 | 
					 | 
				
			||||||
			       skb_get_queue_mapping(skb)) ||
 | 
								       skb_get_queue_mapping(skb)) ||
 | 
				
			||||||
	    want_cookie)
 | 
						    want_cookie)
 | 
				
			||||||
		goto drop_and_free;
 | 
							goto drop_and_free;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue