forked from mirrors/linux
		
	TCPCT part 1g: Responder Cookie => Initiator
Parse incoming TCP_COOKIE option(s).
Calculate <SYN,ACK> TCP_COOKIE option.
Send optional <SYN,ACK> data.
This is a significantly revised implementation of an earlier (year-old)
patch that no longer applies cleanly, with permission of the original
author (Adam Langley):
    http://thread.gmane.org/gmane.linux.network/102586
Requires:
   TCPCT part 1a: add request_values parameter for sending SYNACK
   TCPCT part 1b: generate Responder Cookie secret
   TCPCT part 1c: sysctl_tcp_cookie_size, socket option TCP_COOKIE_TRANSACTIONS
   TCPCT part 1d: define TCP cookie option, extend existing struct's
   TCPCT part 1e: implement socket option TCP_COOKIE_TRANSACTIONS
   TCPCT part 1f: Initiator Cookie => Responder
Signed-off-by: William.Allen.Simpson@gmail.com
Signed-off-by: David S. Miller <davem@davemloft.net>
			
			
This commit is contained in:
		
							parent
							
								
									bd0388ae77
								
							
						
					
					
						commit
						4957faade1
					
				
					 8 changed files with 259 additions and 43 deletions
				
			
		| 
						 | 
					@ -407,6 +407,7 @@ extern int			tcp_recvmsg(struct kiocb *iocb, struct sock *sk,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern void			tcp_parse_options(struct sk_buff *skb,
 | 
					extern void			tcp_parse_options(struct sk_buff *skb,
 | 
				
			||||||
						  struct tcp_options_received *opt_rx,
 | 
											  struct tcp_options_received *opt_rx,
 | 
				
			||||||
 | 
											  u8 **hvpp,
 | 
				
			||||||
						  int estab,
 | 
											  int estab,
 | 
				
			||||||
						  struct dst_entry *dst);
 | 
											  struct dst_entry *dst);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -253,6 +253,8 @@ EXPORT_SYMBOL(cookie_check_timestamp);
 | 
				
			||||||
struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
 | 
					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;
 | 
				
			||||||
 | 
						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);
 | 
				
			||||||
| 
						 | 
					@ -263,7 +265,6 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
 | 
				
			||||||
	int mss;
 | 
						int mss;
 | 
				
			||||||
	struct rtable *rt;
 | 
						struct rtable *rt;
 | 
				
			||||||
	__u8 rcv_wscale;
 | 
						__u8 rcv_wscale;
 | 
				
			||||||
	struct tcp_options_received tcp_opt;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!sysctl_tcp_syncookies || !th->ack)
 | 
						if (!sysctl_tcp_syncookies || !th->ack)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
| 
						 | 
					@ -341,7 +342,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, 0, &rt->u.dst);
 | 
						tcp_parse_options(skb, &tcp_opt, &hash_location, 0, &rt->u.dst);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (tcp_opt.saw_tstamp)
 | 
						if (tcp_opt.saw_tstamp)
 | 
				
			||||||
		cookie_check_timestamp(&tcp_opt);
 | 
							cookie_check_timestamp(&tcp_opt);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3698,7 +3698,7 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
 | 
				
			||||||
 * the fast version below fails.
 | 
					 * the fast version below fails.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void tcp_parse_options(struct sk_buff *skb, struct tcp_options_received *opt_rx,
 | 
					void tcp_parse_options(struct sk_buff *skb, struct tcp_options_received *opt_rx,
 | 
				
			||||||
		       int estab,  struct dst_entry *dst)
 | 
							       u8 **hvpp, int estab,  struct dst_entry *dst)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned char *ptr;
 | 
						unsigned char *ptr;
 | 
				
			||||||
	struct tcphdr *th = tcp_hdr(skb);
 | 
						struct tcphdr *th = tcp_hdr(skb);
 | 
				
			||||||
| 
						 | 
					@ -3785,7 +3785,30 @@ void tcp_parse_options(struct sk_buff *skb, struct tcp_options_received *opt_rx,
 | 
				
			||||||
				 */
 | 
									 */
 | 
				
			||||||
				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;
 | 
				
			||||||
 | 
									default:
 | 
				
			||||||
 | 
										/* ignore option */
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
									};
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			ptr += opsize-2;
 | 
								ptr += opsize-2;
 | 
				
			||||||
			length -= opsize;
 | 
								length -= opsize;
 | 
				
			||||||
| 
						 | 
					@ -3813,17 +3836,20 @@ static int tcp_parse_aligned_timestamp(struct tcp_sock *tp, struct tcphdr *th)
 | 
				
			||||||
 * If it is wrong it falls back on tcp_parse_options().
 | 
					 * If it is wrong it falls back on tcp_parse_options().
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int tcp_fast_parse_options(struct sk_buff *skb, struct tcphdr *th,
 | 
					static int tcp_fast_parse_options(struct sk_buff *skb, struct tcphdr *th,
 | 
				
			||||||
				  struct tcp_sock *tp)
 | 
									  struct tcp_sock *tp, u8 **hvpp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (th->doff == sizeof(struct tcphdr) >> 2) {
 | 
						/* In the spirit of fast parsing, compare doff directly to constant
 | 
				
			||||||
 | 
						 * values.  Because equality is used, short doff can be ignored here.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (th->doff == (sizeof(*th) / 4)) {
 | 
				
			||||||
		tp->rx_opt.saw_tstamp = 0;
 | 
							tp->rx_opt.saw_tstamp = 0;
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	} else if (tp->rx_opt.tstamp_ok &&
 | 
						} else if (tp->rx_opt.tstamp_ok &&
 | 
				
			||||||
		   th->doff == (sizeof(struct tcphdr)>>2)+(TCPOLEN_TSTAMP_ALIGNED>>2)) {
 | 
							   th->doff == ((sizeof(*th) + TCPOLEN_TSTAMP_ALIGNED) / 4)) {
 | 
				
			||||||
		if (tcp_parse_aligned_timestamp(tp, th))
 | 
							if (tcp_parse_aligned_timestamp(tp, th))
 | 
				
			||||||
			return 1;
 | 
								return 1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	tcp_parse_options(skb, &tp->rx_opt, 1, NULL);
 | 
						tcp_parse_options(skb, &tp->rx_opt, hvpp, 1, NULL);
 | 
				
			||||||
	return 1;
 | 
						return 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5077,10 +5103,12 @@ static int tcp_dma_try_early_copy(struct sock *sk, struct sk_buff *skb,
 | 
				
			||||||
static int tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,
 | 
					static int tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,
 | 
				
			||||||
			      struct tcphdr *th, int syn_inerr)
 | 
								      struct tcphdr *th, int syn_inerr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						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) && tp->rx_opt.saw_tstamp &&
 | 
						if (tcp_fast_parse_options(skb, th, tp, &hash_location) &&
 | 
				
			||||||
 | 
						    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);
 | 
				
			||||||
| 
						 | 
					@ -5368,12 +5396,14 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
 | 
				
			||||||
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,
 | 
				
			||||||
					 struct tcphdr *th, unsigned len)
 | 
										 struct tcphdr *th, unsigned len)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct tcp_sock *tp = tcp_sk(sk);
 | 
						u8 *hash_location;
 | 
				
			||||||
	struct inet_connection_sock *icsk = inet_csk(sk);
 | 
						struct inet_connection_sock *icsk = inet_csk(sk);
 | 
				
			||||||
	int saved_clamp = tp->rx_opt.mss_clamp;
 | 
						struct tcp_sock *tp = tcp_sk(sk);
 | 
				
			||||||
	struct dst_entry *dst = __sk_dst_get(sk);
 | 
						struct dst_entry *dst = __sk_dst_get(sk);
 | 
				
			||||||
 | 
						struct tcp_cookie_values *cvp = tp->cookie_values;
 | 
				
			||||||
 | 
						int saved_clamp = tp->rx_opt.mss_clamp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tcp_parse_options(skb, &tp->rx_opt, 0, dst);
 | 
						tcp_parse_options(skb, &tp->rx_opt, &hash_location, 0, dst);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (th->ack) {
 | 
						if (th->ack) {
 | 
				
			||||||
		/* rfc793:
 | 
							/* rfc793:
 | 
				
			||||||
| 
						 | 
					@ -5470,6 +5500,31 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
 | 
				
			||||||
		 * Change state from SYN-SENT only after copied_seq
 | 
							 * Change state from SYN-SENT only after copied_seq
 | 
				
			||||||
		 * 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_set_state(sk, TCP_ESTABLISHED);
 | 
							tcp_set_state(sk, TCP_ESTABLISHED);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1213,9 +1213,12 @@ static struct timewait_sock_ops tcp_timewait_sock_ops = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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;
 | 
				
			||||||
 | 
						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 dst_entry *dst = NULL;
 | 
						struct dst_entry *dst = NULL;
 | 
				
			||||||
	__be32 saddr = ip_hdr(skb)->saddr;
 | 
						__be32 saddr = ip_hdr(skb)->saddr;
 | 
				
			||||||
	__be32 daddr = ip_hdr(skb)->daddr;
 | 
						__be32 daddr = ip_hdr(skb)->daddr;
 | 
				
			||||||
| 
						 | 
					@ -1271,15 +1274,49 @@ 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  = tcp_sk(sk)->rx_opt.user_mss;
 | 
						tmp_opt.user_mss  = tp->rx_opt.user_mss;
 | 
				
			||||||
 | 
						tcp_parse_options(skb, &tmp_opt, &hash_location, 0, dst);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tcp_parse_options(skb, &tmp_opt, 0, dst);
 | 
						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++ ^= daddr;
 | 
				
			||||||
 | 
							*mess++ ^= saddr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* plus variable length Initiator Cookie */
 | 
				
			||||||
 | 
							c = (u8 *)mess;
 | 
				
			||||||
 | 
							while (l-- > 0)
 | 
				
			||||||
 | 
								*c++ ^= *hash_location++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CONFIG_SYN_COOKIES
 | 
				
			||||||
 | 
							want_cookie = 0;	/* not our kind of cookie */
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
							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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tmp_opt.tstamp_ok = tmp_opt.saw_tstamp;
 | 
						tmp_opt.tstamp_ok = tmp_opt.saw_tstamp;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	tcp_openreq_init(req, &tmp_opt, skb);
 | 
						tcp_openreq_init(req, &tmp_opt, skb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (security_inet_conn_request(sk, skb, req))
 | 
						if (security_inet_conn_request(sk, skb, req))
 | 
				
			||||||
| 
						 | 
					@ -1339,7 +1376,9 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	tcp_rsk(req)->snt_isn = isn;
 | 
						tcp_rsk(req)->snt_isn = isn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (__tcp_v4_send_synack(sk, dst, req, NULL) || want_cookie)
 | 
						if (__tcp_v4_send_synack(sk, dst, req,
 | 
				
			||||||
 | 
									 (struct request_values *)&tmp_ext) ||
 | 
				
			||||||
 | 
						    want_cookie)
 | 
				
			||||||
		goto drop_and_free;
 | 
							goto drop_and_free;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inet_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT);
 | 
						inet_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -90,13 +90,14 @@ enum tcp_tw_status
 | 
				
			||||||
tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb,
 | 
					tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb,
 | 
				
			||||||
			   const struct tcphdr *th)
 | 
								   const struct tcphdr *th)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw);
 | 
					 | 
				
			||||||
	struct tcp_options_received tmp_opt;
 | 
						struct tcp_options_received tmp_opt;
 | 
				
			||||||
 | 
						u8 *hash_location;
 | 
				
			||||||
 | 
						struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw);
 | 
				
			||||||
	int paws_reject = 0;
 | 
						int paws_reject = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (th->doff > (sizeof(*th) >> 2) && tcptw->tw_ts_recent_stamp) {
 | 
						if (th->doff > (sizeof(*th) >> 2) && tcptw->tw_ts_recent_stamp) {
 | 
				
			||||||
		tmp_opt.tstamp_ok = 1;
 | 
							tmp_opt.tstamp_ok = 1;
 | 
				
			||||||
		tcp_parse_options(skb, &tmp_opt, 1, NULL);
 | 
							tcp_parse_options(skb, &tmp_opt, &hash_location, 1, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (tmp_opt.saw_tstamp) {
 | 
							if (tmp_opt.saw_tstamp) {
 | 
				
			||||||
			tmp_opt.ts_recent	= tcptw->tw_ts_recent;
 | 
								tmp_opt.ts_recent	= tcptw->tw_ts_recent;
 | 
				
			||||||
| 
						 | 
					@ -518,15 +519,16 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
 | 
				
			||||||
			   struct request_sock *req,
 | 
								   struct request_sock *req,
 | 
				
			||||||
			   struct request_sock **prev)
 | 
								   struct request_sock **prev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct tcp_options_received tmp_opt;
 | 
				
			||||||
 | 
						u8 *hash_location;
 | 
				
			||||||
 | 
						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);
 | 
				
			||||||
	int paws_reject = 0;
 | 
						int paws_reject = 0;
 | 
				
			||||||
	struct tcp_options_received tmp_opt;
 | 
					 | 
				
			||||||
	struct sock *child;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((th->doff > (sizeof(struct tcphdr)>>2)) && (req->ts_recent)) {
 | 
						if ((th->doff > (sizeof(*th) >> 2)) && (req->ts_recent)) {
 | 
				
			||||||
		tmp_opt.tstamp_ok = 1;
 | 
							tmp_opt.tstamp_ok = 1;
 | 
				
			||||||
		tcp_parse_options(skb, &tmp_opt, 1, NULL);
 | 
							tcp_parse_options(skb, &tmp_opt, &hash_location, 1, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (tmp_opt.saw_tstamp) {
 | 
							if (tmp_opt.saw_tstamp) {
 | 
				
			||||||
			tmp_opt.ts_recent = req->ts_recent;
 | 
								tmp_opt.ts_recent = req->ts_recent;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -655,48 +655,77 @@ static unsigned tcp_synack_options(struct sock *sk,
 | 
				
			||||||
				   struct request_sock *req,
 | 
									   struct request_sock *req,
 | 
				
			||||||
				   unsigned mss, struct sk_buff *skb,
 | 
									   unsigned 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,
 | 
				
			||||||
	unsigned size = 0;
 | 
									   struct tcp_extend_values *xvp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
	struct inet_request_sock *ireq = inet_rsk(req);
 | 
						struct inet_request_sock *ireq = inet_rsk(req);
 | 
				
			||||||
	char doing_ts;
 | 
						unsigned remaining = MAX_TCP_OPTION_SPACE;
 | 
				
			||||||
 | 
						u8 cookie_plus = (xvp != NULL && !xvp->cookie_out_never) ?
 | 
				
			||||||
 | 
								 xvp->cookie_plus :
 | 
				
			||||||
 | 
								 0;
 | 
				
			||||||
 | 
						bool doing_ts = ireq->tstamp_ok;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#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);
 | 
				
			||||||
	if (*md5) {
 | 
						if (*md5) {
 | 
				
			||||||
		opts->options |= OPTION_MD5;
 | 
							opts->options |= OPTION_MD5;
 | 
				
			||||||
		size += TCPOLEN_MD5SIG_ALIGNED;
 | 
							remaining -= TCPOLEN_MD5SIG_ALIGNED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* We can't fit any SACK blocks in a packet with MD5 + TS
 | 
				
			||||||
 | 
							 * options. There was discussion about disabling SACK
 | 
				
			||||||
 | 
							 * rather than TS in order to fit in better with old,
 | 
				
			||||||
 | 
							 * buggy kernels, but that was deemed to be unnecessary.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							doing_ts &= !ireq->sack_ok;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
	*md5 = NULL;
 | 
						*md5 = NULL;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* we can't fit any SACK blocks in a packet with MD5 + TS
 | 
						/* We always send an MSS option. */
 | 
				
			||||||
	   options. There was discussion about disabling SACK rather than TS in
 | 
					 | 
				
			||||||
	   order to fit in better with old, buggy kernels, but that was deemed
 | 
					 | 
				
			||||||
	   to be unnecessary. */
 | 
					 | 
				
			||||||
	doing_ts = ireq->tstamp_ok && !(*md5 && ireq->sack_ok);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	opts->mss = mss;
 | 
						opts->mss = mss;
 | 
				
			||||||
	size += TCPOLEN_MSS_ALIGNED;
 | 
						remaining -= TCPOLEN_MSS_ALIGNED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (likely(ireq->wscale_ok)) {
 | 
						if (likely(ireq->wscale_ok)) {
 | 
				
			||||||
		opts->ws = ireq->rcv_wscale;
 | 
							opts->ws = ireq->rcv_wscale;
 | 
				
			||||||
		opts->options |= OPTION_WSCALE;
 | 
							opts->options |= OPTION_WSCALE;
 | 
				
			||||||
		size += TCPOLEN_WSCALE_ALIGNED;
 | 
							remaining -= TCPOLEN_WSCALE_ALIGNED;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (likely(doing_ts)) {
 | 
						if (likely(doing_ts)) {
 | 
				
			||||||
		opts->options |= OPTION_TS;
 | 
							opts->options |= OPTION_TS;
 | 
				
			||||||
		opts->tsval = TCP_SKB_CB(skb)->when;
 | 
							opts->tsval = TCP_SKB_CB(skb)->when;
 | 
				
			||||||
		opts->tsecr = req->ts_recent;
 | 
							opts->tsecr = req->ts_recent;
 | 
				
			||||||
		size += TCPOLEN_TSTAMP_ALIGNED;
 | 
							remaining -= TCPOLEN_TSTAMP_ALIGNED;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (likely(ireq->sack_ok)) {
 | 
						if (likely(ireq->sack_ok)) {
 | 
				
			||||||
		opts->options |= OPTION_SACK_ADVERTISE;
 | 
							opts->options |= OPTION_SACK_ADVERTISE;
 | 
				
			||||||
		if (unlikely(!doing_ts))
 | 
							if (unlikely(!doing_ts))
 | 
				
			||||||
			size += TCPOLEN_SACKPERM_ALIGNED;
 | 
								remaining -= TCPOLEN_SACKPERM_ALIGNED;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return size;
 | 
						/* Similar rationale to tcp_syn_options() applies here, too.
 | 
				
			||||||
 | 
						 * If the <SYN> options fit, the same options should fit now!
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (*md5 == NULL &&
 | 
				
			||||||
 | 
						    doing_ts &&
 | 
				
			||||||
 | 
						    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;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Compute TCP options for ESTABLISHED sockets. This is not the
 | 
					/* Compute TCP options for ESTABLISHED sockets. This is not the
 | 
				
			||||||
| 
						 | 
					@ -2365,6 +2394,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
 | 
				
			||||||
				struct request_values *rvp)
 | 
									struct request_values *rvp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	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);
 | 
				
			||||||
	struct tcphdr *th;
 | 
						struct tcphdr *th;
 | 
				
			||||||
| 
						 | 
					@ -2408,8 +2438,8 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
 | 
				
			||||||
#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)
 | 
				
			||||||
			  sizeof(struct tcphdr);
 | 
								+ sizeof(*th);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	skb_push(skb, tcp_header_size);
 | 
						skb_push(skb, tcp_header_size);
 | 
				
			||||||
	skb_reset_transport_header(skb);
 | 
						skb_reset_transport_header(skb);
 | 
				
			||||||
| 
						 | 
					@ -2426,6 +2456,45 @@ 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,
 | 
				
			||||||
			     TCPCB_FLAG_SYN | TCPCB_FLAG_ACK);
 | 
								     TCPCB_FLAG_SYN | TCPCB_FLAG_ACK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (OPTION_COOKIE_EXTENSION & opts.options) {
 | 
				
			||||||
 | 
							const struct tcp_cookie_values *cvp = tp->cookie_values;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (cvp != NULL &&
 | 
				
			||||||
 | 
							    cvp->s_data_constant &&
 | 
				
			||||||
 | 
							    cvp->s_data_desired > 0) {
 | 
				
			||||||
 | 
								u8 *buf = skb_put(skb, cvp->s_data_desired);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/* copy data directly from the listening socket. */
 | 
				
			||||||
 | 
								memcpy(buf, cvp->s_data_payload, cvp->s_data_desired);
 | 
				
			||||||
 | 
								TCP_SKB_CB(skb)->end_seq += cvp->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-- ^= ((th->dest << 16) | th->source);
 | 
				
			||||||
 | 
								*tail-- ^= (u32)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);
 | 
				
			||||||
	th->ack_seq = htonl(tcp_rsk(req)->rcv_isn + 1);
 | 
						th->ack_seq = htonl(tcp_rsk(req)->rcv_isn + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -159,6 +159,8 @@ static inline int cookie_check(struct sk_buff *skb, __u32 cookie)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
 | 
					struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct tcp_options_received tcp_opt;
 | 
				
			||||||
 | 
						u8 *hash_location;
 | 
				
			||||||
	struct inet_request_sock *ireq;
 | 
						struct inet_request_sock *ireq;
 | 
				
			||||||
	struct inet6_request_sock *ireq6;
 | 
						struct inet6_request_sock *ireq6;
 | 
				
			||||||
	struct tcp_request_sock *treq;
 | 
						struct tcp_request_sock *treq;
 | 
				
			||||||
| 
						 | 
					@ -171,7 +173,6 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
 | 
				
			||||||
	int mss;
 | 
						int mss;
 | 
				
			||||||
	struct dst_entry *dst;
 | 
						struct dst_entry *dst;
 | 
				
			||||||
	__u8 rcv_wscale;
 | 
						__u8 rcv_wscale;
 | 
				
			||||||
	struct tcp_options_received tcp_opt;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!sysctl_tcp_syncookies || !th->ack)
 | 
						if (!sysctl_tcp_syncookies || !th->ack)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
| 
						 | 
					@ -254,7 +255,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, 0, dst);
 | 
						tcp_parse_options(skb, &tcp_opt, &hash_location, 0, dst);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (tcp_opt.saw_tstamp)
 | 
						if (tcp_opt.saw_tstamp)
 | 
				
			||||||
		cookie_check_timestamp(&tcp_opt);
 | 
							cookie_check_timestamp(&tcp_opt);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1162,7 +1162,9 @@ 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;
 | 
				
			||||||
 | 
						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);
 | 
				
			||||||
| 
						 | 
					@ -1206,8 +1208,52 @@ 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, dst);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tcp_parse_options(skb, &tmp_opt, 0, dst);
 | 
						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 = &ipv6_hdr(skb)->daddr.s6_addr32[0];
 | 
				
			||||||
 | 
							*mess++ ^= *d++;
 | 
				
			||||||
 | 
							*mess++ ^= *d++;
 | 
				
			||||||
 | 
							*mess++ ^= *d++;
 | 
				
			||||||
 | 
							*mess++ ^= *d++;
 | 
				
			||||||
 | 
							d = &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++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CONFIG_SYN_COOKIES
 | 
				
			||||||
 | 
							want_cookie = 0;	/* not our kind of cookie */
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
							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);
 | 
				
			||||||
| 
						 | 
					@ -1244,7 +1290,9 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	security_inet_conn_request(sk, skb, req);
 | 
						security_inet_conn_request(sk, skb, req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (tcp_v6_send_synack(sk, req, NULL) || want_cookie)
 | 
						if (tcp_v6_send_synack(sk, req,
 | 
				
			||||||
 | 
								       (struct request_values *)&tmp_ext) ||
 | 
				
			||||||
 | 
						    want_cookie)
 | 
				
			||||||
		goto drop_and_free;
 | 
							goto drop_and_free;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inet6_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT);
 | 
						inet6_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue