1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17#include <linux/config.h>
18#if defined(CONFIG_SYN_COOKIES)
19#include <linux/tcp.h>
20#include <linux/malloc.h>
21#include <linux/random.h>
22#include <net/tcp.h>
23
24extern int sysctl_tcp_syncookies;
25
26static unsigned long tcp_lastsynq_overflow;
27
28
29
30
31
32
33static __u16 const msstab[] = {
34 64-1,
35 256-1,
36 512-1,
37 536-1,
38 1024-1,
39 1440-1,
40 1460-1,
41 4312-1,
42 (__u16)-1
43};
44
45#define NUM_MSS (sizeof(msstab)/sizeof(msstab[0]) - 1)
46
47
48
49
50
51__u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb,
52 __u16 *mssp)
53{
54 int mssind;
55 const __u16 mss = *mssp;
56
57 tcp_lastsynq_overflow = jiffies;
58
59 for (mssind = 0; mss > msstab[mssind+1]; mssind++)
60 ;
61 *mssp = msstab[mssind]+1;
62
63 net_statistics.SyncookiesSent++;
64
65 return secure_tcp_syn_cookie(skb->nh.iph->saddr, skb->nh.iph->daddr,
66 skb->h.th->source, skb->h.th->dest,
67 ntohl(skb->h.th->seq),
68 jiffies / (HZ*60), mssind);
69}
70
71
72
73
74
75
76
77#define COUNTER_TRIES 4
78
79
80
81
82static inline int cookie_check(struct sk_buff *skb, __u32 cookie)
83{
84 __u32 seq;
85 __u32 mssind;
86
87 if ((jiffies - tcp_lastsynq_overflow) > TCP_TIMEOUT_INIT)
88 return 0;
89
90 seq = ntohl(skb->h.th->seq)-1;
91 mssind = check_tcp_syn_cookie(cookie,
92 skb->nh.iph->saddr, skb->nh.iph->daddr,
93 skb->h.th->source, skb->h.th->dest,
94 seq, jiffies/(HZ*60), COUNTER_TRIES);
95
96 return mssind < NUM_MSS ? msstab[mssind]+1 : 0;
97}
98
99extern struct or_calltable or_ipv4;
100
101static inline struct sock *
102get_cookie_sock(struct sock *sk, struct sk_buff *skb, struct open_request *req,
103 struct dst_entry *dst)
104{
105 struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
106
107 sk = tp->af_specific->syn_recv_sock(sk, skb, req, dst);
108 req->sk = sk;
109
110
111 tcp_synq_queue(tp, req);
112
113 return sk;
114}
115
116struct sock *
117cookie_v4_check(struct sock *sk, struct sk_buff *skb, struct ip_options *opt)
118{
119 __u32 cookie = ntohl(skb->h.th->ack_seq)-1;
120 struct open_request *req;
121 int mss;
122 struct rtable *rt;
123 __u8 rcv_wscale;
124
125 if (!sysctl_tcp_syncookies)
126 return sk;
127 if (!skb->h.th->ack)
128 return sk;
129
130 mss = cookie_check(skb, cookie);
131 if (mss == 0) {
132 net_statistics.SyncookiesFailed++;
133 return sk;
134 }
135
136 net_statistics.SyncookiesRecv++;
137
138 req = tcp_openreq_alloc();
139 if (req == NULL)
140 return NULL;
141
142 req->rcv_isn = htonl(skb->h.th->seq)-1;
143 req->snt_isn = cookie;
144 req->mss = mss;
145 req->rmt_port = skb->h.th->source;
146 req->af.v4_req.loc_addr = skb->nh.iph->daddr;
147 req->af.v4_req.rmt_addr = skb->nh.iph->saddr;
148 req->class = &or_ipv4;
149
150 req->af.v4_req.opt = NULL;
151
152
153
154
155 if (opt && opt->optlen) {
156 int opt_size = sizeof(struct ip_options) + opt->optlen;
157
158 req->af.v4_req.opt = kmalloc(opt_size, GFP_ATOMIC);
159 if (req->af.v4_req.opt) {
160 if (ip_options_echo(req->af.v4_req.opt, skb)) {
161 kfree_s(req->af.v4_req.opt, opt_size);
162 req->af.v4_req.opt = NULL;
163 }
164 }
165 }
166
167 req->snd_wscale = req->rcv_wscale = req->tstamp_ok = 0;
168 req->wscale_ok = 0;
169 req->expires = 0UL;
170 req->retrans = 0;
171
172
173
174
175
176
177
178 if (ip_route_output(&rt,
179 opt &&
180 opt->srr ? opt->faddr : req->af.v4_req.rmt_addr,
181 req->af.v4_req.loc_addr,
182 sk->ip_tos | RTO_CONN,
183 0)) {
184 tcp_openreq_free(req);
185 return NULL;
186 }
187
188
189 req->window_clamp = rt->u.dst.window;
190 tcp_select_initial_window(sock_rspace(sk)/2,req->mss,
191 &req->rcv_wnd, &req->window_clamp,
192 0, &rcv_wscale);
193 req->rcv_wscale = rcv_wscale;
194
195 return get_cookie_sock(sk, skb, req, &rt->u.dst);
196}
197
198#endif
199