aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/syncookies.c5
-rw-r--r--net/ipv6/tcp_ipv6.c52
2 files changed, 53 insertions, 4 deletions
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c
index 612fc53e0bb9..5b9af508b8f2 100644
--- a/net/ipv6/syncookies.c
+++ b/net/ipv6/syncookies.c
@@ -159,6 +159,8 @@ static inline int cookie_check(struct sk_buff *skb, __u32 cookie)
159 159
160struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) 160struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
161{ 161{
162 struct tcp_options_received tcp_opt;
163 u8 *hash_location;
162 struct inet_request_sock *ireq; 164 struct inet_request_sock *ireq;
163 struct inet6_request_sock *ireq6; 165 struct inet6_request_sock *ireq6;
164 struct tcp_request_sock *treq; 166 struct tcp_request_sock *treq;
@@ -171,7 +173,6 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
171 int mss; 173 int mss;
172 struct dst_entry *dst; 174 struct dst_entry *dst;
173 __u8 rcv_wscale; 175 __u8 rcv_wscale;
174 struct tcp_options_received tcp_opt;
175 176
176 if (!sysctl_tcp_syncookies || !th->ack) 177 if (!sysctl_tcp_syncookies || !th->ack)
177 goto out; 178 goto out;
@@ -254,7 +255,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
254 255
255 /* check for timestamp cookie support */ 256 /* check for timestamp cookie support */
256 memset(&tcp_opt, 0, sizeof(tcp_opt)); 257 memset(&tcp_opt, 0, sizeof(tcp_opt));
257 tcp_parse_options(skb, &tcp_opt, 0, dst); 258 tcp_parse_options(skb, &tcp_opt, &hash_location, 0, dst);
258 259
259 if (tcp_opt.saw_tstamp) 260 if (tcp_opt.saw_tstamp)
260 cookie_check_timestamp(&tcp_opt); 261 cookie_check_timestamp(&tcp_opt);
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index f2ec38289a4a..fc0a4e5895ee 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1162,7 +1162,9 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
1162 */ 1162 */
1163static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) 1163static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
1164{ 1164{
1165 struct tcp_extend_values tmp_ext;
1165 struct tcp_options_received tmp_opt; 1166 struct tcp_options_received tmp_opt;
1167 u8 *hash_location;
1166 struct request_sock *req; 1168 struct request_sock *req;
1167 struct inet6_request_sock *treq; 1169 struct inet6_request_sock *treq;
1168 struct ipv6_pinfo *np = inet6_sk(sk); 1170 struct ipv6_pinfo *np = inet6_sk(sk);
@@ -1206,8 +1208,52 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
1206 tcp_clear_options(&tmp_opt); 1208 tcp_clear_options(&tmp_opt);
1207 tmp_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr); 1209 tmp_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr);
1208 tmp_opt.user_mss = tp->rx_opt.user_mss; 1210 tmp_opt.user_mss = tp->rx_opt.user_mss;
1211 tcp_parse_options(skb, &tmp_opt, &hash_location, 0, dst);
1212
1213 if (tmp_opt.cookie_plus > 0 &&
1214 tmp_opt.saw_tstamp &&
1215 !tp->rx_opt.cookie_out_never &&
1216 (sysctl_tcp_cookie_size > 0 ||
1217 (tp->cookie_values != NULL &&
1218 tp->cookie_values->cookie_desired > 0))) {
1219 u8 *c;
1220 u32 *d;
1221 u32 *mess = &tmp_ext.cookie_bakery[COOKIE_DIGEST_WORDS];
1222 int l = tmp_opt.cookie_plus - TCPOLEN_COOKIE_BASE;
1223
1224 if (tcp_cookie_generator(&tmp_ext.cookie_bakery[0]) != 0)
1225 goto drop_and_free;
1226
1227 /* Secret recipe starts with IP addresses */
1228 d = &ipv6_hdr(skb)->daddr.s6_addr32[0];
1229 *mess++ ^= *d++;
1230 *mess++ ^= *d++;
1231 *mess++ ^= *d++;
1232 *mess++ ^= *d++;
1233 d = &ipv6_hdr(skb)->saddr.s6_addr32[0];
1234 *mess++ ^= *d++;
1235 *mess++ ^= *d++;
1236 *mess++ ^= *d++;
1237 *mess++ ^= *d++;
1238
1239 /* plus variable length Initiator Cookie */
1240 c = (u8 *)mess;
1241 while (l-- > 0)
1242 *c++ ^= *hash_location++;
1209 1243
1210 tcp_parse_options(skb, &tmp_opt, 0, dst); 1244#ifdef CONFIG_SYN_COOKIES
1245 want_cookie = 0; /* not our kind of cookie */
1246#endif
1247 tmp_ext.cookie_out_never = 0; /* false */
1248 tmp_ext.cookie_plus = tmp_opt.cookie_plus;
1249 } else if (!tp->rx_opt.cookie_in_always) {
1250 /* redundant indications, but ensure initialization. */
1251 tmp_ext.cookie_out_never = 1; /* true */
1252 tmp_ext.cookie_plus = 0;
1253 } else {
1254 goto drop_and_free;
1255 }
1256 tmp_ext.cookie_in_always = tp->rx_opt.cookie_in_always;
1211 1257
1212 if (want_cookie && !tmp_opt.saw_tstamp) 1258 if (want_cookie && !tmp_opt.saw_tstamp)
1213 tcp_clear_options(&tmp_opt); 1259 tcp_clear_options(&tmp_opt);
@@ -1244,7 +1290,9 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
1244 1290
1245 security_inet_conn_request(sk, skb, req); 1291 security_inet_conn_request(sk, skb, req);
1246 1292
1247 if (tcp_v6_send_synack(sk, req, NULL) || want_cookie) 1293 if (tcp_v6_send_synack(sk, req,
1294 (struct request_values *)&tmp_ext) ||
1295 want_cookie)
1248 goto drop_and_free; 1296 goto drop_and_free;
1249 1297
1250 inet6_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); 1298 inet6_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT);