X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fipv4%2Fsyncookies.c;h=6b19530905afdbad2e7e2c46716b8d741447f7b9;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=e923d2f021aa8b49c187104b5ebe1ed03b373ea8;hpb=f7f1b0f1e2fbadeab12d24236000e778aa9b1ead;p=linux-2.6.git diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index e923d2f02..6b1953090 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c @@ -35,23 +35,23 @@ module_init(init_syncookies); #define COOKIEBITS 24 /* Upper bits store count */ #define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1) -static u32 cookie_hash(u32 saddr, u32 daddr, u32 sport, u32 dport, +static u32 cookie_hash(__be32 saddr, __be32 daddr, __be16 sport, __be16 dport, u32 count, int c) { __u32 tmp[16 + 5 + SHA_WORKSPACE_WORDS]; memcpy(tmp + 3, syncookie_secret[c], sizeof(syncookie_secret[c])); - tmp[0] = saddr; - tmp[1] = daddr; - tmp[2] = (sport << 16) + dport; + tmp[0] = (__force u32)saddr; + tmp[1] = (__force u32)daddr; + tmp[2] = ((__force u32)sport << 16) + (__force u32)dport; tmp[3] = count; sha_transform(tmp + 16, (__u8 *)tmp, tmp + 16 + 5); return tmp[17]; } -static __u32 secure_tcp_syn_cookie(__u32 saddr, __u32 daddr, __u16 sport, - __u16 dport, __u32 sseq, __u32 count, +static __u32 secure_tcp_syn_cookie(__be32 saddr, __be32 daddr, __be16 sport, + __be16 dport, __u32 sseq, __u32 count, __u32 data) { /* @@ -80,8 +80,8 @@ static __u32 secure_tcp_syn_cookie(__u32 saddr, __u32 daddr, __u16 sport, * "maxdiff" if the current (passed-in) "count". The return value * is (__u32)-1 if this test fails. */ -static __u32 check_tcp_syn_cookie(__u32 cookie, __u32 saddr, __u32 daddr, - __u16 sport, __u16 dport, __u32 sseq, +static __u32 check_tcp_syn_cookie(__u32 cookie, __be32 saddr, __be32 daddr, + __be16 sport, __be16 dport, __u32 sseq, __u32 count, __u32 maxdiff) { __u32 diff; @@ -169,20 +169,18 @@ static inline int cookie_check(struct sk_buff *skb, __u32 cookie) return mssind < NUM_MSS ? msstab[mssind] + 1 : 0; } -extern struct or_calltable or_ipv4; - static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb, - struct open_request *req, + struct request_sock *req, struct dst_entry *dst) { - struct tcp_sock *tp = tcp_sk(sk); + struct inet_connection_sock *icsk = inet_csk(sk); struct sock *child; - child = tp->af_specific->syn_recv_sock(sk, skb, req, dst); + child = icsk->icsk_af_ops->syn_recv_sock(sk, skb, req, dst); if (child) - tcp_acceptq_queue(sk, req, child); + inet_csk_reqsk_queue_add(sk, req, child); else - tcp_openreq_free(req); + reqsk_free(req); return child; } @@ -190,10 +188,12 @@ static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb, struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, struct ip_options *opt) { + struct inet_request_sock *ireq; + struct tcp_request_sock *treq; struct tcp_sock *tp = tcp_sk(sk); __u32 cookie = ntohl(skb->h.th->ack_seq) - 1; struct sock *ret = sk; - struct open_request *req; + struct request_sock *req; int mss; struct rtable *rt; __u8 rcv_wscale; @@ -209,19 +209,24 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, NET_INC_STATS_BH(LINUX_MIB_SYNCOOKIESRECV); - req = tcp_openreq_alloc(); ret = NULL; + req = reqsk_alloc(&tcp_request_sock_ops); /* for safety */ if (!req) goto out; - req->rcv_isn = htonl(skb->h.th->seq) - 1; - req->snt_isn = cookie; + if (security_inet_conn_request(sk, skb, req)) { + reqsk_free(req); + goto out; + } + ireq = inet_rsk(req); + treq = tcp_rsk(req); + treq->rcv_isn = ntohl(skb->h.th->seq) - 1; + treq->snt_isn = cookie; req->mss = mss; - req->rmt_port = skb->h.th->source; - req->af.v4_req.loc_addr = skb->nh.iph->daddr; - req->af.v4_req.rmt_addr = skb->nh.iph->saddr; - req->class = &or_ipv4; /* for savety */ - req->af.v4_req.opt = NULL; + ireq->rmt_port = skb->h.th->source; + ireq->loc_addr = skb->nh.iph->daddr; + ireq->rmt_addr = skb->nh.iph->saddr; + ireq->opt = NULL; /* We throwed the options of the initial SYN away, so we hope * the ACK carries the same options again (see RFC1122 4.2.3.8) @@ -229,17 +234,15 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, if (opt && opt->optlen) { int opt_size = sizeof(struct ip_options) + opt->optlen; - req->af.v4_req.opt = kmalloc(opt_size, GFP_ATOMIC); - if (req->af.v4_req.opt) { - if (ip_options_echo(req->af.v4_req.opt, skb)) { - kfree(req->af.v4_req.opt); - req->af.v4_req.opt = NULL; - } + ireq->opt = kmalloc(opt_size, GFP_ATOMIC); + if (ireq->opt != NULL && ip_options_echo(ireq->opt, skb)) { + kfree(ireq->opt); + ireq->opt = NULL; } } - req->snd_wscale = req->rcv_wscale = req->tstamp_ok = 0; - req->wscale_ok = req->sack_ok = 0; + ireq->snd_wscale = ireq->rcv_wscale = ireq->tstamp_ok = 0; + ireq->wscale_ok = ireq->sack_ok = 0; req->expires = 0UL; req->retrans = 0; @@ -253,15 +256,16 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ((opt && opt->srr) ? opt->faddr : - req->af.v4_req.rmt_addr), - .saddr = req->af.v4_req.loc_addr, + ireq->rmt_addr), + .saddr = ireq->loc_addr, .tos = RT_CONN_FLAGS(sk) } }, .proto = IPPROTO_TCP, .uli_u = { .ports = { .sport = skb->h.th->dest, .dport = skb->h.th->source } } }; + security_req_classify_flow(req, &fl); if (ip_route_output_key(&rt, &fl)) { - tcp_openreq_free(req); + reqsk_free(req); goto out; } } @@ -272,7 +276,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, &req->rcv_wnd, &req->window_clamp, 0, &rcv_wscale); /* BTW win scale with syncookies is 0 by definition */ - req->rcv_wscale = rcv_wscale; + ireq->rcv_wscale = rcv_wscale; ret = get_cookie_sock(sk, skb, req, &rt->u.dst); out: return ret;