2 * Syncookies implementation for the Linux kernel
4 * Copyright (C) 1997 Andi Kleen
5 * Based on ideas by D.J.Bernstein and Eric Schenk.
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.
12 * $Id: syncookies.c,v 1.12 2000/07/26 01:04:19 davem Exp $
14 * Missing: IPv6 support.
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>
24 extern int sysctl_tcp_syncookies
;
26 static unsigned long tcp_lastsynq_overflow
;
29 * This table has to be sorted and terminated with (__u16)-1.
30 * XXX generate a better table.
31 * Unresolved Issues: HIPPI with a 64k MSS is not well supported.
33 static __u16
const msstab
[] = {
44 /* The number doesn't include the -1 terminator */
45 #define NUM_MSS (sizeof(msstab)/sizeof(msstab[0]) - 1)
48 * Generate a syncookie. mssp points to the mss, which is returned
49 * rounded down to the value encoded in the cookie.
51 __u32
cookie_v4_init_sequence(struct sock
*sk
, struct sk_buff
*skb
,
55 const __u16 mss
= *mssp
;
57 tcp_lastsynq_overflow
= jiffies
;
58 /* XXX sort msstab[] by probability? Binary search? */
59 for (mssind
= 0; mss
> msstab
[mssind
+1]; mssind
++)
61 *mssp
= msstab
[mssind
]+1;
63 NET_INC_STATS_BH(SyncookiesSent
);
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
);
72 * This (misnamed) value is the age of syncookie which is permitted.
73 * Its ideal value should be dependent on TCP_TIMEOUT_INIT and
74 * sysctl_tcp_retries1. It's a rather complicated formula (exponential
75 * backoff) to compute at runtime so it's currently hardcoded here.
77 #define COUNTER_TRIES 4
79 * Check if a ack sequence number is a valid syncookie.
80 * Return the decoded mss if it is, or 0 if not.
82 static inline int cookie_check(struct sk_buff
*skb
, __u32 cookie
)
87 if ((jiffies
- tcp_lastsynq_overflow
) > TCP_TIMEOUT_INIT
)
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
);
96 return mssind
< NUM_MSS
? msstab
[mssind
]+1 : 0;
99 extern struct or_calltable or_ipv4
;
101 static inline struct sock
*
102 get_cookie_sock(struct sock
*sk
, struct sk_buff
*skb
, struct open_request
*req
,
103 struct dst_entry
*dst
)
105 struct tcp_opt
*tp
= &(sk
->tp_pinfo
.af_tcp
);
108 child
= tp
->af_specific
->syn_recv_sock(sk
, skb
, req
, dst
);
110 tcp_acceptq_queue(sk
, req
, child
);
112 tcp_openreq_free(req
);
118 cookie_v4_check(struct sock
*sk
, struct sk_buff
*skb
, struct ip_options
*opt
)
120 __u32 cookie
= ntohl(skb
->h
.th
->ack_seq
)-1;
121 struct open_request
*req
;
126 if (!sysctl_tcp_syncookies
)
131 mss
= cookie_check(skb
, cookie
);
133 NET_INC_STATS_BH(SyncookiesFailed
);
137 NET_INC_STATS_BH(SyncookiesRecv
);
139 req
= tcp_openreq_alloc();
143 req
->rcv_isn
= htonl(skb
->h
.th
->seq
)-1;
144 req
->snt_isn
= cookie
;
146 req
->rmt_port
= skb
->h
.th
->source
;
147 req
->af
.v4_req
.loc_addr
= skb
->nh
.iph
->daddr
;
148 req
->af
.v4_req
.rmt_addr
= skb
->nh
.iph
->saddr
;
149 req
->class = &or_ipv4
; /* for savety */
151 req
->af
.v4_req
.opt
= NULL
;
153 /* We throwed the options of the initial SYN away, so we hope
154 * the ACK carries the same options again (see RFC1122 4.2.3.8)
156 if (opt
&& opt
->optlen
) {
157 int opt_size
= sizeof(struct ip_options
) + opt
->optlen
;
159 req
->af
.v4_req
.opt
= kmalloc(opt_size
, GFP_ATOMIC
);
160 if (req
->af
.v4_req
.opt
) {
161 if (ip_options_echo(req
->af
.v4_req
.opt
, skb
)) {
162 kfree(req
->af
.v4_req
.opt
);
163 req
->af
.v4_req
.opt
= NULL
;
168 req
->snd_wscale
= req
->rcv_wscale
= req
->tstamp_ok
= 0;
169 req
->wscale_ok
= req
->sack_ok
= 0;
174 * We need to lookup the route here to get at the correct
175 * window size. We should better make sure that the window size
176 * hasn't changed since we received the original syn, but I see
177 * no easy way to do this.
179 if (ip_route_output(&rt
,
181 opt
->srr
? opt
->faddr
: req
->af
.v4_req
.rmt_addr
,
182 req
->af
.v4_req
.loc_addr
,
183 sk
->protinfo
.af_inet
.tos
| RTO_CONN
,
185 tcp_openreq_free(req
);
189 /* Try to redo what tcp_v4_send_synack did. */
190 req
->window_clamp
= rt
->u
.dst
.window
;
191 tcp_select_initial_window(tcp_full_space(sk
),req
->mss
,
192 &req
->rcv_wnd
, &req
->window_clamp
,
194 /* BTW win scale with syncookies is 0 by definition */
195 req
->rcv_wscale
= rcv_wscale
;
197 return get_cookie_sock(sk
, skb
, req
, &rt
->u
.dst
);