syncookies.c (1da177e4c3f41524e886b7f1b8a0c1fc7321cac2) | syncookies.c (2e6599cb899ba4b133f42cbf9d2b1883d2dc583a) |
---|---|
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 --- 176 unchanged lines hidden (view full) --- 185 tcp_openreq_free(req); 186 187 return child; 188} 189 190struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, 191 struct ip_options *opt) 192{ | 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 --- 176 unchanged lines hidden (view full) --- 185 tcp_openreq_free(req); 186 187 return child; 188} 189 190struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, 191 struct ip_options *opt) 192{ |
193 struct inet_request_sock *ireq; 194 struct tcp_request_sock *treq; |
|
193 struct tcp_sock *tp = tcp_sk(sk); 194 __u32 cookie = ntohl(skb->h.th->ack_seq) - 1; 195 struct sock *ret = sk; 196 struct open_request *req; 197 int mss; 198 struct rtable *rt; 199 __u8 rcv_wscale; 200 201 if (!sysctl_tcp_syncookies || !skb->h.th->ack) 202 goto out; 203 204 if (time_after(jiffies, tp->last_synq_overflow + TCP_TIMEOUT_INIT) || 205 (mss = cookie_check(skb, cookie)) == 0) { 206 NET_INC_STATS_BH(LINUX_MIB_SYNCOOKIESFAILED); 207 goto out; 208 } 209 210 NET_INC_STATS_BH(LINUX_MIB_SYNCOOKIESRECV); 211 | 195 struct tcp_sock *tp = tcp_sk(sk); 196 __u32 cookie = ntohl(skb->h.th->ack_seq) - 1; 197 struct sock *ret = sk; 198 struct open_request *req; 199 int mss; 200 struct rtable *rt; 201 __u8 rcv_wscale; 202 203 if (!sysctl_tcp_syncookies || !skb->h.th->ack) 204 goto out; 205 206 if (time_after(jiffies, tp->last_synq_overflow + TCP_TIMEOUT_INIT) || 207 (mss = cookie_check(skb, cookie)) == 0) { 208 NET_INC_STATS_BH(LINUX_MIB_SYNCOOKIESFAILED); 209 goto out; 210 } 211 212 NET_INC_STATS_BH(LINUX_MIB_SYNCOOKIESRECV); 213 |
212 req = tcp_openreq_alloc(); | |
213 ret = NULL; | 214 ret = NULL; |
215 req = tcp_openreq_alloc(&or_ipv4); /* for safety */ |
|
214 if (!req) 215 goto out; 216 | 216 if (!req) 217 goto out; 218 |
217 req->rcv_isn = htonl(skb->h.th->seq) - 1; 218 req->snt_isn = cookie; | 219 ireq = inet_rsk(req); 220 treq = tcp_rsk(req); 221 treq->rcv_isn = htonl(skb->h.th->seq) - 1; 222 treq->snt_isn = cookie; |
219 req->mss = mss; | 223 req->mss = mss; |
220 req->rmt_port = skb->h.th->source; 221 req->af.v4_req.loc_addr = skb->nh.iph->daddr; 222 req->af.v4_req.rmt_addr = skb->nh.iph->saddr; 223 req->class = &or_ipv4; /* for savety */ 224 req->af.v4_req.opt = NULL; | 224 ireq->rmt_port = skb->h.th->source; 225 ireq->loc_addr = skb->nh.iph->daddr; 226 ireq->rmt_addr = skb->nh.iph->saddr; 227 ireq->opt = NULL; |
225 226 /* We throwed the options of the initial SYN away, so we hope 227 * the ACK carries the same options again (see RFC1122 4.2.3.8) 228 */ 229 if (opt && opt->optlen) { 230 int opt_size = sizeof(struct ip_options) + opt->optlen; 231 | 228 229 /* We throwed the options of the initial SYN away, so we hope 230 * the ACK carries the same options again (see RFC1122 4.2.3.8) 231 */ 232 if (opt && opt->optlen) { 233 int opt_size = sizeof(struct ip_options) + opt->optlen; 234 |
232 req->af.v4_req.opt = kmalloc(opt_size, GFP_ATOMIC); 233 if (req->af.v4_req.opt) { 234 if (ip_options_echo(req->af.v4_req.opt, skb)) { 235 kfree(req->af.v4_req.opt); 236 req->af.v4_req.opt = NULL; 237 } | 235 ireq->opt = kmalloc(opt_size, GFP_ATOMIC); 236 if (ireq->opt != NULL && ip_options_echo(ireq->opt, skb)) { 237 kfree(ireq->opt); 238 ireq->opt = NULL; |
238 } 239 } 240 | 239 } 240 } 241 |
241 req->snd_wscale = req->rcv_wscale = req->tstamp_ok = 0; 242 req->wscale_ok = req->sack_ok = 0; | 242 ireq->snd_wscale = ireq->rcv_wscale = ireq->tstamp_ok = 0; 243 ireq->wscale_ok = ireq->sack_ok = 0; |
243 req->expires = 0UL; 244 req->retrans = 0; 245 246 /* 247 * We need to lookup the route here to get at the correct 248 * window size. We should better make sure that the window size 249 * hasn't changed since we received the original syn, but I see 250 * no easy way to do this. 251 */ 252 { 253 struct flowi fl = { .nl_u = { .ip4_u = 254 { .daddr = ((opt && opt->srr) ? 255 opt->faddr : | 244 req->expires = 0UL; 245 req->retrans = 0; 246 247 /* 248 * We need to lookup the route here to get at the correct 249 * window size. We should better make sure that the window size 250 * hasn't changed since we received the original syn, but I see 251 * no easy way to do this. 252 */ 253 { 254 struct flowi fl = { .nl_u = { .ip4_u = 255 { .daddr = ((opt && opt->srr) ? 256 opt->faddr : |
256 req->af.v4_req.rmt_addr), 257 .saddr = req->af.v4_req.loc_addr, | 257 ireq->rmt_addr), 258 .saddr = ireq->loc_addr, |
258 .tos = RT_CONN_FLAGS(sk) } }, 259 .proto = IPPROTO_TCP, 260 .uli_u = { .ports = 261 { .sport = skb->h.th->dest, 262 .dport = skb->h.th->source } } }; 263 if (ip_route_output_key(&rt, &fl)) { 264 tcp_openreq_free(req); 265 goto out; 266 } 267 } 268 269 /* Try to redo what tcp_v4_send_synack did. */ 270 req->window_clamp = dst_metric(&rt->u.dst, RTAX_WINDOW); 271 tcp_select_initial_window(tcp_full_space(sk), req->mss, 272 &req->rcv_wnd, &req->window_clamp, 273 0, &rcv_wscale); 274 /* BTW win scale with syncookies is 0 by definition */ | 259 .tos = RT_CONN_FLAGS(sk) } }, 260 .proto = IPPROTO_TCP, 261 .uli_u = { .ports = 262 { .sport = skb->h.th->dest, 263 .dport = skb->h.th->source } } }; 264 if (ip_route_output_key(&rt, &fl)) { 265 tcp_openreq_free(req); 266 goto out; 267 } 268 } 269 270 /* Try to redo what tcp_v4_send_synack did. */ 271 req->window_clamp = dst_metric(&rt->u.dst, RTAX_WINDOW); 272 tcp_select_initial_window(tcp_full_space(sk), req->mss, 273 &req->rcv_wnd, &req->window_clamp, 274 0, &rcv_wscale); 275 /* BTW win scale with syncookies is 0 by definition */ |
275 req->rcv_wscale = rcv_wscale; | 276 ireq->rcv_wscale = rcv_wscale; |
276 277 ret = get_cookie_sock(sk, skb, req, &rt->u.dst); 278out: return ret; 279} | 277 278 ret = get_cookie_sock(sk, skb, req, &rt->u.dst); 279out: return ret; 280} |