Main Page | Class List | File List | Class Members | File Members

syncookies.c

Go to the documentation of this file.
00001 /* 00002 * Syncookies implementation for the Linux kernel 00003 * 00004 * Copyright (C) 1997 Andi Kleen 00005 * Based on ideas by D.J.Bernstein and Eric Schenk. 00006 * 00007 * This program is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU General Public License 00009 * as published by the Free Software Foundation; either version 00010 * 2 of the License, or (at your option) any later version. 00011 * 00012 * $Id: syncookies.c,v 1.17 2001/10/26 14:55:41 davem Exp $ 00013 * 00014 * Missing: IPv6 support. 00015 */ 00016 00017 #include <linux/tcp.h> 00018 #include <linux/slab.h> 00019 #include <linux/random.h> 00020 #include <net/tcp.h> 00021 00022 extern int sysctl_tcp_syncookies; 00023 00024 /* 00025 * This table has to be sorted and terminated with (__u16)-1. 00026 * XXX generate a better table. 00027 * Unresolved Issues: HIPPI with a 64k MSS is not well supported. 00028 */ 00029 static __u16 const msstab[] = { 00030 64 - 1, 00031 256 - 1, 00032 512 - 1, 00033 536 - 1, 00034 1024 - 1, 00035 1440 - 1, 00036 1460 - 1, 00037 4312 - 1, 00038 (__u16)-1 00039 }; 00040 /* The number doesn't include the -1 terminator */ 00041 #define NUM_MSS (sizeof(msstab)/sizeof(msstab[0]) - 1) 00042 00043 /* 00044 * Generate a syncookie. mssp points to the mss, which is returned 00045 * rounded down to the value encoded in the cookie. 00046 */ 00047 __u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb, __u16 *mssp) 00048 { 00049 int mssind; 00050 const __u16 mss = *mssp; 00051 00052 00053 sk->tp_pinfo.af_tcp.last_synq_overflow = jiffies; 00054 00055 /* XXX sort msstab[] by probability? Binary search? */ 00056 for (mssind = 0; mss > msstab[mssind + 1]; mssind++) 00057 ; 00058 *mssp = msstab[mssind] + 1; 00059 00060 NET_INC_STATS_BH(SyncookiesSent); 00061 00062 return secure_tcp_syn_cookie(skb->nh.iph->saddr, skb->nh.iph->daddr, 00063 skb->h.th->source, skb->h.th->dest, 00064 ntohl(skb->h.th->seq), 00065 jiffies / (HZ * 60), mssind); 00066 } 00067 00068 /* 00069 * This (misnamed) value is the age of syncookie which is permitted. 00070 * Its ideal value should be dependent on TCP_TIMEOUT_INIT and 00071 * sysctl_tcp_retries1. It's a rather complicated formula (exponential 00072 * backoff) to compute at runtime so it's currently hardcoded here. 00073 */ 00074 #define COUNTER_TRIES 4 00075 /* 00076 * Check if a ack sequence number is a valid syncookie. 00077 * Return the decoded mss if it is, or 0 if not. 00078 */ 00079 static inline int cookie_check(struct sk_buff *skb, __u32 cookie) 00080 { 00081 __u32 seq; 00082 __u32 mssind; 00083 00084 seq = ntohl(skb->h.th->seq)-1; 00085 mssind = check_tcp_syn_cookie(cookie, 00086 skb->nh.iph->saddr, skb->nh.iph->daddr, 00087 skb->h.th->source, skb->h.th->dest, 00088 seq, jiffies / (HZ * 60), COUNTER_TRIES); 00089 00090 return mssind < NUM_MSS ? msstab[mssind] + 1 : 0; 00091 } 00092 00093 extern struct or_calltable or_ipv4; 00094 00095 static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb, 00096 struct open_request *req, 00097 struct dst_entry *dst) 00098 { 00099 struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); 00100 struct sock *child; 00101 00102 child = tp->af_specific->syn_recv_sock(sk, skb, req, dst); 00103 if (child) 00104 tcp_acceptq_queue(sk, req, child); 00105 else 00106 tcp_openreq_free(req); 00107 00108 return child; 00109 } 00110 00111 struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, 00112 struct ip_options *opt) 00113 { 00114 __u32 cookie = ntohl(skb->h.th->ack_seq) - 1; 00115 struct sock *ret = sk; 00116 struct open_request *req; 00117 int mss; 00118 struct rtable *rt; 00119 __u8 rcv_wscale; 00120 00121 if (!sysctl_tcp_syncookies || !skb->h.th->ack) 00122 goto out; 00123 00124 if (time_after(jiffies, sk->tp_pinfo.af_tcp.last_synq_overflow + TCP_TIMEOUT_INIT) || 00125 (mss = cookie_check(skb, cookie)) == 0) { 00126 NET_INC_STATS_BH(SyncookiesFailed); 00127 goto out; 00128 } 00129 00130 NET_INC_STATS_BH(SyncookiesRecv); 00131 00132 req = tcp_openreq_alloc(); 00133 ret = NULL; 00134 if (!req) 00135 goto out; 00136 00137 req->rcv_isn = htonl(skb->h.th->seq) - 1; 00138 req->snt_isn = cookie; 00139 req->mss = mss; 00140 req->rmt_port = skb->h.th->source; 00141 req->af.v4_req.loc_addr = skb->nh.iph->daddr; 00142 req->af.v4_req.rmt_addr = skb->nh.iph->saddr; 00143 req->class = &or_ipv4; /* for savety */ 00144 req->af.v4_req.opt = NULL; 00145 00146 /* We throwed the options of the initial SYN away, so we hope 00147 * the ACK carries the same options again (see RFC1122 4.2.3.8) 00148 */ 00149 if (opt && opt->optlen) { 00150 int opt_size = sizeof(struct ip_options) + opt->optlen; 00151 00152 req->af.v4_req.opt = kmalloc(opt_size, GFP_ATOMIC); 00153 if (req->af.v4_req.opt) { 00154 if (ip_options_echo(req->af.v4_req.opt, skb)) { 00155 kfree(req->af.v4_req.opt); 00156 req->af.v4_req.opt = NULL; 00157 } 00158 } 00159 } 00160 00161 req->snd_wscale = req->rcv_wscale = req->tstamp_ok = 0; 00162 req->wscale_ok = req->sack_ok = 0; 00163 req->expires = 0UL; 00164 req->retrans = 0; 00165 00166 /* 00167 * We need to lookup the route here to get at the correct 00168 * window size. We should better make sure that the window size 00169 * hasn't changed since we received the original syn, but I see 00170 * no easy way to do this. 00171 */ 00172 if (ip_route_output(&rt, 00173 opt && 00174 opt->srr ? opt->faddr : req->af.v4_req.rmt_addr, 00175 req->af.v4_req.loc_addr, 00176 RT_CONN_FLAGS(sk), 00177 0)) { 00178 tcp_openreq_free(req); 00179 goto out; 00180 } 00181 00182 /* Try to redo what tcp_v4_send_synack did. */ 00183 req->window_clamp = rt->u.dst.window; 00184 tcp_select_initial_window(tcp_full_space(sk), req->mss, 00185 &req->rcv_wnd, &req->window_clamp, 00186 0, &rcv_wscale); 00187 /* BTW win scale with syncookies is 0 by definition */ 00188 req->rcv_wscale = rcv_wscale; 00189 00190 ret = get_cookie_sock(sk, skb, req, &rt->u.dst); 00191 out: return ret; 00192 }

Generated on Wed Dec 1 21:25:33 2004 for Linux 2.4.23 Networking by doxygen 1.3.8