diff options
Diffstat (limited to 'net/ipv6/syncookies.c')
| -rw-r--r-- | net/ipv6/syncookies.c | 58 | 
1 files changed, 22 insertions, 36 deletions
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index 34d1f0690d7..09fd34f0dbf 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c @@ -27,28 +27,17 @@ extern __u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS];  #define COOKIEBITS 24	/* Upper bits store count */  #define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1) -/* - * This table has to be sorted and terminated with (__u16)-1. - * XXX generate a better table. - * Unresolved Issues: HIPPI with a 64k MSS is not well supported. - * - * Taken directly from ipv4 implementation. - * Should this list be modified for ipv6 use or is it close enough? - * rfc 2460 8.3 suggests mss values 20 bytes less than ipv4 counterpart - */ +/* Table must be sorted. */  static __u16 const msstab[] = { -	64 - 1, -	256 - 1, -	512 - 1, -	536 - 1, -	1024 - 1, -	1440 - 1, -	1460 - 1, -	4312 - 1, -	(__u16)-1 +	64, +	512, +	536, +	1280 - 60, +	1480 - 60, +	1500 - 60, +	4460 - 60, +	9000 - 60,  }; -/* The number doesn't include the -1 terminator */ -#define NUM_MSS (ARRAY_SIZE(msstab) - 1)  /*   * This (misnamed) value is the age of syncookie which is permitted. @@ -134,9 +123,11 @@ __u32 cookie_v6_init_sequence(struct sock *sk, struct sk_buff *skb, __u16 *mssp)  	tcp_synq_overflow(sk); -	for (mssind = 0; mss > msstab[mssind + 1]; mssind++) -		; -	*mssp = msstab[mssind] + 1; +	for (mssind = ARRAY_SIZE(msstab) - 1; mssind ; mssind--) +		if (mss >= msstab[mssind]) +			break; + +	*mssp = msstab[mssind];  	NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_SYNCOOKIESSENT); @@ -154,7 +145,7 @@ static inline int cookie_check(struct sk_buff *skb, __u32 cookie)  					    th->source, th->dest, seq,  					    jiffies / (HZ * 60), COUNTER_TRIES); -	return mssind < NUM_MSS ? msstab[mssind] + 1 : 0; +	return mssind < ARRAY_SIZE(msstab) ? msstab[mssind] : 0;  }  struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) @@ -173,8 +164,9 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)  	int mss;  	struct dst_entry *dst;  	__u8 rcv_wscale; +	bool ecn_ok; -	if (!sysctl_tcp_syncookies || !th->ack) +	if (!sysctl_tcp_syncookies || !th->ack || th->rst)  		goto out;  	if (tcp_synq_no_recent_overflow(sk) || @@ -189,8 +181,8 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)  	memset(&tcp_opt, 0, sizeof(tcp_opt));  	tcp_parse_options(skb, &tcp_opt, &hash_location, 0); -	if (tcp_opt.saw_tstamp) -		cookie_check_timestamp(&tcp_opt); +	if (!cookie_check_timestamp(&tcp_opt, &ecn_ok)) +		goto out;  	ret = NULL;  	req = inet6_reqsk_alloc(&tcp6_request_sock_ops); @@ -224,9 +216,8 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)  	req->expires = 0UL;  	req->retrans = 0; -	ireq->ecn_ok		= 0; +	ireq->ecn_ok		= ecn_ok;  	ireq->snd_wscale	= tcp_opt.snd_wscale; -	ireq->rcv_wscale	= tcp_opt.rcv_wscale;  	ireq->sack_ok		= tcp_opt.sack_ok;  	ireq->wscale_ok		= tcp_opt.wscale_ok;  	ireq->tstamp_ok		= tcp_opt.saw_tstamp; @@ -240,17 +231,12 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)  	 * me if there is a preferred way.  	 */  	{ -		struct in6_addr *final_p = NULL, final; +		struct in6_addr *final_p, final;  		struct flowi fl;  		memset(&fl, 0, sizeof(fl));  		fl.proto = IPPROTO_TCP;  		ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr); -		if (np->opt && np->opt->srcrt) { -			struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; -			ipv6_addr_copy(&final, &fl.fl6_dst); -			ipv6_addr_copy(&fl.fl6_dst, rt0->addr); -			final_p = &final; -		} +		final_p = fl6_update_dst(&fl, np->opt, &final);  		ipv6_addr_copy(&fl.fl6_src, &ireq6->loc_addr);  		fl.oif = sk->sk_bound_dev_if;  		fl.mark = sk->sk_mark;  |