aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/syncookies.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/syncookies.c')
-rw-r--r--net/ipv6/syncookies.c75
1 files changed, 36 insertions, 39 deletions
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c
index bf63ac8a49b9..535a3ad262f1 100644
--- a/net/ipv6/syncookies.c
+++ b/net/ipv6/syncookies.c
@@ -24,26 +24,23 @@
24#define COOKIEBITS 24 /* Upper bits store count */ 24#define COOKIEBITS 24 /* Upper bits store count */
25#define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1) 25#define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1)
26 26
27/* Table must be sorted. */ 27static u32 syncookie6_secret[2][16-4+SHA_DIGEST_WORDS];
28
29/* RFC 2460, Section 8.3:
30 * [ipv6 tcp] MSS must be computed as the maximum packet size minus 60 [..]
31 *
32 * Due to IPV6_MIN_MTU=1280 the lowest possible MSS is 1220, which allows
33 * using higher values than ipv4 tcp syncookies.
34 * The other values are chosen based on ethernet (1500 and 9k MTU), plus
35 * one that accounts for common encap (PPPoe) overhead. Table must be sorted.
36 */
28static __u16 const msstab[] = { 37static __u16 const msstab[] = {
29 64, 38 1280 - 60, /* IPV6_MIN_MTU - 60 */
30 512,
31 536,
32 1280 - 60,
33 1480 - 60, 39 1480 - 60,
34 1500 - 60, 40 1500 - 60,
35 4460 - 60,
36 9000 - 60, 41 9000 - 60,
37}; 42};
38 43
39/*
40 * This (misnamed) value is the age of syncookie which is permitted.
41 * Its ideal value should be dependent on TCP_TIMEOUT_INIT and
42 * sysctl_tcp_retries1. It's a rather complicated formula (exponential
43 * backoff) to compute at runtime so it's currently hardcoded here.
44 */
45#define COUNTER_TRIES 4
46
47static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb, 44static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb,
48 struct request_sock *req, 45 struct request_sock *req,
49 struct dst_entry *dst) 46 struct dst_entry *dst)
@@ -66,14 +63,18 @@ static DEFINE_PER_CPU(__u32 [16 + 5 + SHA_WORKSPACE_WORDS],
66static u32 cookie_hash(const struct in6_addr *saddr, const struct in6_addr *daddr, 63static u32 cookie_hash(const struct in6_addr *saddr, const struct in6_addr *daddr,
67 __be16 sport, __be16 dport, u32 count, int c) 64 __be16 sport, __be16 dport, u32 count, int c)
68{ 65{
69 __u32 *tmp = __get_cpu_var(ipv6_cookie_scratch); 66 __u32 *tmp;
67
68 net_get_random_once(syncookie6_secret, sizeof(syncookie6_secret));
69
70 tmp = __get_cpu_var(ipv6_cookie_scratch);
70 71
71 /* 72 /*
72 * we have 320 bits of information to hash, copy in the remaining 73 * we have 320 bits of information to hash, copy in the remaining
73 * 192 bits required for sha_transform, from the syncookie_secret 74 * 192 bits required for sha_transform, from the syncookie6_secret
74 * and overwrite the digest with the secret 75 * and overwrite the digest with the secret
75 */ 76 */
76 memcpy(tmp + 10, syncookie_secret[c], 44); 77 memcpy(tmp + 10, syncookie6_secret[c], 44);
77 memcpy(tmp, saddr, 16); 78 memcpy(tmp, saddr, 16);
78 memcpy(tmp + 4, daddr, 16); 79 memcpy(tmp + 4, daddr, 16);
79 tmp[8] = ((__force u32)sport << 16) + (__force u32)dport; 80 tmp[8] = ((__force u32)sport << 16) + (__force u32)dport;
@@ -86,8 +87,9 @@ static u32 cookie_hash(const struct in6_addr *saddr, const struct in6_addr *dadd
86static __u32 secure_tcp_syn_cookie(const struct in6_addr *saddr, 87static __u32 secure_tcp_syn_cookie(const struct in6_addr *saddr,
87 const struct in6_addr *daddr, 88 const struct in6_addr *daddr,
88 __be16 sport, __be16 dport, __u32 sseq, 89 __be16 sport, __be16 dport, __u32 sseq,
89 __u32 count, __u32 data) 90 __u32 data)
90{ 91{
92 u32 count = tcp_cookie_time();
91 return (cookie_hash(saddr, daddr, sport, dport, 0, 0) + 93 return (cookie_hash(saddr, daddr, sport, dport, 0, 0) +
92 sseq + (count << COOKIEBITS) + 94 sseq + (count << COOKIEBITS) +
93 ((cookie_hash(saddr, daddr, sport, dport, count, 1) + data) 95 ((cookie_hash(saddr, daddr, sport, dport, count, 1) + data)
@@ -96,15 +98,14 @@ static __u32 secure_tcp_syn_cookie(const struct in6_addr *saddr,
96 98
97static __u32 check_tcp_syn_cookie(__u32 cookie, const struct in6_addr *saddr, 99static __u32 check_tcp_syn_cookie(__u32 cookie, const struct in6_addr *saddr,
98 const struct in6_addr *daddr, __be16 sport, 100 const struct in6_addr *daddr, __be16 sport,
99 __be16 dport, __u32 sseq, __u32 count, 101 __be16 dport, __u32 sseq)
100 __u32 maxdiff)
101{ 102{
102 __u32 diff; 103 __u32 diff, count = tcp_cookie_time();
103 104
104 cookie -= cookie_hash(saddr, daddr, sport, dport, 0, 0) + sseq; 105 cookie -= cookie_hash(saddr, daddr, sport, dport, 0, 0) + sseq;
105 106
106 diff = (count - (cookie >> COOKIEBITS)) & ((__u32) -1 >> COOKIEBITS); 107 diff = (count - (cookie >> COOKIEBITS)) & ((__u32) -1 >> COOKIEBITS);
107 if (diff >= maxdiff) 108 if (diff >= MAX_SYNCOOKIE_AGE)
108 return (__u32)-1; 109 return (__u32)-1;
109 110
110 return (cookie - 111 return (cookie -
@@ -125,8 +126,7 @@ u32 __cookie_v6_init_sequence(const struct ipv6hdr *iph,
125 *mssp = msstab[mssind]; 126 *mssp = msstab[mssind];
126 127
127 return secure_tcp_syn_cookie(&iph->saddr, &iph->daddr, th->source, 128 return secure_tcp_syn_cookie(&iph->saddr, &iph->daddr, th->source,
128 th->dest, ntohl(th->seq), 129 th->dest, ntohl(th->seq), mssind);
129 jiffies / (HZ * 60), mssind);
130} 130}
131EXPORT_SYMBOL_GPL(__cookie_v6_init_sequence); 131EXPORT_SYMBOL_GPL(__cookie_v6_init_sequence);
132 132
@@ -146,8 +146,7 @@ int __cookie_v6_check(const struct ipv6hdr *iph, const struct tcphdr *th,
146{ 146{
147 __u32 seq = ntohl(th->seq) - 1; 147 __u32 seq = ntohl(th->seq) - 1;
148 __u32 mssind = check_tcp_syn_cookie(cookie, &iph->saddr, &iph->daddr, 148 __u32 mssind = check_tcp_syn_cookie(cookie, &iph->saddr, &iph->daddr,
149 th->source, th->dest, seq, 149 th->source, th->dest, seq);
150 jiffies / (HZ * 60), COUNTER_TRIES);
151 150
152 return mssind < ARRAY_SIZE(msstab) ? msstab[mssind] : 0; 151 return mssind < ARRAY_SIZE(msstab) ? msstab[mssind] : 0;
153} 152}
@@ -157,7 +156,6 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
157{ 156{
158 struct tcp_options_received tcp_opt; 157 struct tcp_options_received tcp_opt;
159 struct inet_request_sock *ireq; 158 struct inet_request_sock *ireq;
160 struct inet6_request_sock *ireq6;
161 struct tcp_request_sock *treq; 159 struct tcp_request_sock *treq;
162 struct ipv6_pinfo *np = inet6_sk(sk); 160 struct ipv6_pinfo *np = inet6_sk(sk);
163 struct tcp_sock *tp = tcp_sk(sk); 161 struct tcp_sock *tp = tcp_sk(sk);
@@ -194,7 +192,6 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
194 goto out; 192 goto out;
195 193
196 ireq = inet_rsk(req); 194 ireq = inet_rsk(req);
197 ireq6 = inet6_rsk(req);
198 treq = tcp_rsk(req); 195 treq = tcp_rsk(req);
199 treq->listener = NULL; 196 treq->listener = NULL;
200 197
@@ -202,22 +199,22 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
202 goto out_free; 199 goto out_free;
203 200
204 req->mss = mss; 201 req->mss = mss;
205 ireq->rmt_port = th->source; 202 ireq->ir_rmt_port = th->source;
206 ireq->loc_port = th->dest; 203 ireq->ir_num = ntohs(th->dest);
207 ireq6->rmt_addr = ipv6_hdr(skb)->saddr; 204 ireq->ir_v6_rmt_addr = ipv6_hdr(skb)->saddr;
208 ireq6->loc_addr = ipv6_hdr(skb)->daddr; 205 ireq->ir_v6_loc_addr = ipv6_hdr(skb)->daddr;
209 if (ipv6_opt_accepted(sk, skb) || 206 if (ipv6_opt_accepted(sk, skb) ||
210 np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo || 207 np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo ||
211 np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) { 208 np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) {
212 atomic_inc(&skb->users); 209 atomic_inc(&skb->users);
213 ireq6->pktopts = skb; 210 ireq->pktopts = skb;
214 } 211 }
215 212
216 ireq6->iif = sk->sk_bound_dev_if; 213 ireq->ir_iif = sk->sk_bound_dev_if;
217 /* So that link locals have meaning */ 214 /* So that link locals have meaning */
218 if (!sk->sk_bound_dev_if && 215 if (!sk->sk_bound_dev_if &&
219 ipv6_addr_type(&ireq6->rmt_addr) & IPV6_ADDR_LINKLOCAL) 216 ipv6_addr_type(&ireq->ir_v6_rmt_addr) & IPV6_ADDR_LINKLOCAL)
220 ireq6->iif = inet6_iif(skb); 217 ireq->ir_iif = inet6_iif(skb);
221 218
222 req->expires = 0UL; 219 req->expires = 0UL;
223 req->num_retrans = 0; 220 req->num_retrans = 0;
@@ -241,12 +238,12 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
241 struct flowi6 fl6; 238 struct flowi6 fl6;
242 memset(&fl6, 0, sizeof(fl6)); 239 memset(&fl6, 0, sizeof(fl6));
243 fl6.flowi6_proto = IPPROTO_TCP; 240 fl6.flowi6_proto = IPPROTO_TCP;
244 fl6.daddr = ireq6->rmt_addr; 241 fl6.daddr = ireq->ir_v6_rmt_addr;
245 final_p = fl6_update_dst(&fl6, np->opt, &final); 242 final_p = fl6_update_dst(&fl6, np->opt, &final);
246 fl6.saddr = ireq6->loc_addr; 243 fl6.saddr = ireq->ir_v6_loc_addr;
247 fl6.flowi6_oif = sk->sk_bound_dev_if; 244 fl6.flowi6_oif = sk->sk_bound_dev_if;
248 fl6.flowi6_mark = sk->sk_mark; 245 fl6.flowi6_mark = sk->sk_mark;
249 fl6.fl6_dport = inet_rsk(req)->rmt_port; 246 fl6.fl6_dport = ireq->ir_rmt_port;
250 fl6.fl6_sport = inet_sk(sk)->inet_sport; 247 fl6.fl6_sport = inet_sk(sk)->inet_sport;
251 security_req_classify_flow(req, flowi6_to_flowi(&fl6)); 248 security_req_classify_flow(req, flowi6_to_flowi(&fl6));
252 249