1 /*
2  *  Syncookies implementation for the Linux kernel
3  *
4  *  Copyright (C) 1997 Andi Kleen
5  *  Based on ideas by D.J.Bernstein and Eric Schenk.
6  *
7  *	This program is free software; you can redistribute it and/or
8  *      modify it under the terms of the GNU General Public License
9  *      as published by the Free Software Foundation; either version
10  *      2 of the License, or (at your option) any later version.
11  *
12  *  $Id: syncookies.c,v 1.17 2001/10/26 14:55:41 davem Exp $
13  *
14  *  Missing: IPv6 support.
15  */
16 
17 #include <linux/tcp.h>
18 #include <linux/slab.h>
19 #include <linux/random.h>
20 #include <net/tcp.h>
21 
22 extern int sysctl_tcp_syncookies;
23 
24 /*
25  * This table has to be sorted and terminated with (__u16)-1.
26  * XXX generate a better table.
27  * Unresolved Issues: HIPPI with a 64k MSS is not well supported.
28  */
29 static __u16 const msstab[] = {
30 	64 - 1,
31 	256 - 1,
32 	512 - 1,
33 	536 - 1,
34 	1024 - 1,
35 	1440 - 1,
36 	1460 - 1,
37 	4312 - 1,
38 	(__u16)-1
39 };
40 /* The number doesn't include the -1 terminator */
41 #define NUM_MSS (sizeof(msstab)/sizeof(msstab[0]) - 1)
42 
43 /*
44  * Generate a syncookie.  mssp points to the mss, which is returned
45  * rounded down to the value encoded in the cookie.
46  */
cookie_v4_init_sequence(struct sock * sk,struct sk_buff * skb,__u16 * mssp)47 __u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb, __u16 *mssp)
48 {
49 	int mssind;
50 	const __u16 mss = *mssp;
51 
52 
53 	sk->tp_pinfo.af_tcp.last_synq_overflow = jiffies;
54 
55 	/* XXX sort msstab[] by probability?  Binary search? */
56 	for (mssind = 0; mss > msstab[mssind + 1]; mssind++)
57 		;
58 	*mssp = msstab[mssind] + 1;
59 
60 	NET_INC_STATS_BH(SyncookiesSent);
61 
62 	return secure_tcp_syn_cookie(skb->nh.iph->saddr, skb->nh.iph->daddr,
63 				     skb->h.th->source, skb->h.th->dest,
64 				     ntohl(skb->h.th->seq),
65 				     jiffies / (HZ * 60), mssind);
66 }
67 
68 /*
69  * This (misnamed) value is the age of syncookie which is permitted.
70  * Its ideal value should be dependent on TCP_TIMEOUT_INIT and
71  * sysctl_tcp_retries1. It's a rather complicated formula (exponential
72  * backoff) to compute at runtime so it's currently hardcoded here.
73  */
74 #define COUNTER_TRIES 4
75 /*
76  * Check if a ack sequence number is a valid syncookie.
77  * Return the decoded mss if it is, or 0 if not.
78  */
cookie_check(struct sk_buff * skb,__u32 cookie)79 static inline int cookie_check(struct sk_buff *skb, __u32 cookie)
80 {
81 	__u32 seq;
82 	__u32 mssind;
83 
84 	seq = ntohl(skb->h.th->seq)-1;
85 	mssind = check_tcp_syn_cookie(cookie,
86 				      skb->nh.iph->saddr, skb->nh.iph->daddr,
87 				      skb->h.th->source, skb->h.th->dest,
88 				      seq, jiffies / (HZ * 60), COUNTER_TRIES);
89 
90 	return mssind < NUM_MSS ? msstab[mssind] + 1 : 0;
91 }
92 
93 extern struct or_calltable or_ipv4;
94 
get_cookie_sock(struct sock * sk,struct sk_buff * skb,struct open_request * req,struct dst_entry * dst)95 static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb,
96 					   struct open_request *req,
97 					   struct dst_entry *dst)
98 {
99 	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
100 	struct sock *child;
101 
102 	child = tp->af_specific->syn_recv_sock(sk, skb, req, dst);
103 	if (child)
104 		tcp_acceptq_queue(sk, req, child);
105 	else
106 		tcp_openreq_free(req);
107 
108 	return child;
109 }
110 
cookie_v4_check(struct sock * sk,struct sk_buff * skb,struct ip_options * opt)111 struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
112 			     struct ip_options *opt)
113 {
114 	__u32 cookie = ntohl(skb->h.th->ack_seq) - 1;
115 	struct sock *ret = sk;
116 	struct open_request *req;
117 	int mss;
118 	struct rtable *rt;
119 	__u8 rcv_wscale;
120 
121 	if (!sysctl_tcp_syncookies || !skb->h.th->ack)
122 		goto out;
123 
124   	if (time_after(jiffies, sk->tp_pinfo.af_tcp.last_synq_overflow + TCP_TIMEOUT_INIT) ||
125 	    (mss = cookie_check(skb, cookie)) == 0) {
126 	 	NET_INC_STATS_BH(SyncookiesFailed);
127 		goto out;
128 	}
129 
130 	NET_INC_STATS_BH(SyncookiesRecv);
131 
132 	req = tcp_openreq_alloc();
133 	ret = NULL;
134 	if (!req)
135 		goto out;
136 
137 	req->rcv_isn		= htonl(skb->h.th->seq) - 1;
138 	req->snt_isn		= cookie;
139 	req->mss		= mss;
140  	req->rmt_port		= skb->h.th->source;
141 	req->af.v4_req.loc_addr = skb->nh.iph->daddr;
142 	req->af.v4_req.rmt_addr = skb->nh.iph->saddr;
143 	req->class		= &or_ipv4; /* for savety */
144 	req->af.v4_req.opt	= NULL;
145 
146 	/* We throwed the options of the initial SYN away, so we hope
147 	 * the ACK carries the same options again (see RFC1122 4.2.3.8)
148 	 */
149 	if (opt && opt->optlen) {
150 		int opt_size = sizeof(struct ip_options) + opt->optlen;
151 
152 		req->af.v4_req.opt = kmalloc(opt_size, GFP_ATOMIC);
153 		if (req->af.v4_req.opt) {
154 			if (ip_options_echo(req->af.v4_req.opt, skb)) {
155 				kfree(req->af.v4_req.opt);
156 				req->af.v4_req.opt = NULL;
157 			}
158 		}
159 	}
160 
161 	req->snd_wscale = req->rcv_wscale = req->tstamp_ok = 0;
162 	req->wscale_ok	= req->sack_ok = 0;
163 	req->expires	= 0UL;
164 	req->retrans	= 0;
165 
166 	/*
167 	 * We need to lookup the route here to get at the correct
168 	 * window size. We should better make sure that the window size
169 	 * hasn't changed since we received the original syn, but I see
170 	 * no easy way to do this.
171 	 */
172 	if (ip_route_output(&rt,
173 			    opt &&
174 			    opt->srr ? opt->faddr : req->af.v4_req.rmt_addr,
175 			    req->af.v4_req.loc_addr,
176 			    RT_CONN_FLAGS(sk),
177 			    0)) {
178 		tcp_openreq_free(req);
179 		goto out;
180 	}
181 
182 	/* Try to redo what tcp_v4_send_synack did. */
183 	req->window_clamp = rt->u.dst.window;
184 	tcp_select_initial_window(tcp_full_space(sk), req->mss,
185 				  &req->rcv_wnd, &req->window_clamp,
186 				  0, &rcv_wscale);
187 	/* BTW win scale with syncookies is 0 by definition */
188 	req->rcv_wscale	  = rcv_wscale;
189 
190 	ret = get_cookie_sock(sk, skb, req, &rt->u.dst);
191 out:	return ret;
192 }
193