diff options
author | William Allen Simpson <william.allen.simpson@gmail.com> | 2009-12-02 13:25:27 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-12-03 01:07:26 -0500 |
commit | 4957faade11b3a278c3b3cade3411ddc20afa791 (patch) | |
tree | 57f994bab69353baf5f554b89cf9107c3372ecce /net/ipv4/tcp_ipv4.c | |
parent | bd0388ae77075026d6a9f9eb6026dfd1d52ce0e9 (diff) |
TCPCT part 1g: Responder Cookie => Initiator
Parse incoming TCP_COOKIE option(s).
Calculate <SYN,ACK> TCP_COOKIE option.
Send optional <SYN,ACK> data.
This is a significantly revised implementation of an earlier (year-old)
patch that no longer applies cleanly, with permission of the original
author (Adam Langley):
http://thread.gmane.org/gmane.linux.network/102586
Requires:
TCPCT part 1a: add request_values parameter for sending SYNACK
TCPCT part 1b: generate Responder Cookie secret
TCPCT part 1c: sysctl_tcp_cookie_size, socket option TCP_COOKIE_TRANSACTIONS
TCPCT part 1d: define TCP cookie option, extend existing struct's
TCPCT part 1e: implement socket option TCP_COOKIE_TRANSACTIONS
TCPCT part 1f: Initiator Cookie => Responder
Signed-off-by: William.Allen.Simpson@gmail.com
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp_ipv4.c')
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 47 |
1 files changed, 43 insertions, 4 deletions
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index a2bcac9b388e..59c911f3889d 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -1213,9 +1213,12 @@ static struct timewait_sock_ops tcp_timewait_sock_ops = { | |||
1213 | 1213 | ||
1214 | int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | 1214 | int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) |
1215 | { | 1215 | { |
1216 | struct tcp_extend_values tmp_ext; | ||
1216 | struct tcp_options_received tmp_opt; | 1217 | struct tcp_options_received tmp_opt; |
1218 | u8 *hash_location; | ||
1217 | struct request_sock *req; | 1219 | struct request_sock *req; |
1218 | struct inet_request_sock *ireq; | 1220 | struct inet_request_sock *ireq; |
1221 | struct tcp_sock *tp = tcp_sk(sk); | ||
1219 | struct dst_entry *dst = NULL; | 1222 | struct dst_entry *dst = NULL; |
1220 | __be32 saddr = ip_hdr(skb)->saddr; | 1223 | __be32 saddr = ip_hdr(skb)->saddr; |
1221 | __be32 daddr = ip_hdr(skb)->daddr; | 1224 | __be32 daddr = ip_hdr(skb)->daddr; |
@@ -1271,15 +1274,49 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1271 | 1274 | ||
1272 | tcp_clear_options(&tmp_opt); | 1275 | tcp_clear_options(&tmp_opt); |
1273 | tmp_opt.mss_clamp = TCP_MSS_DEFAULT; | 1276 | tmp_opt.mss_clamp = TCP_MSS_DEFAULT; |
1274 | tmp_opt.user_mss = tcp_sk(sk)->rx_opt.user_mss; | 1277 | tmp_opt.user_mss = tp->rx_opt.user_mss; |
1278 | tcp_parse_options(skb, &tmp_opt, &hash_location, 0, dst); | ||
1279 | |||
1280 | if (tmp_opt.cookie_plus > 0 && | ||
1281 | tmp_opt.saw_tstamp && | ||
1282 | !tp->rx_opt.cookie_out_never && | ||
1283 | (sysctl_tcp_cookie_size > 0 || | ||
1284 | (tp->cookie_values != NULL && | ||
1285 | tp->cookie_values->cookie_desired > 0))) { | ||
1286 | u8 *c; | ||
1287 | u32 *mess = &tmp_ext.cookie_bakery[COOKIE_DIGEST_WORDS]; | ||
1288 | int l = tmp_opt.cookie_plus - TCPOLEN_COOKIE_BASE; | ||
1289 | |||
1290 | if (tcp_cookie_generator(&tmp_ext.cookie_bakery[0]) != 0) | ||
1291 | goto drop_and_release; | ||
1292 | |||
1293 | /* Secret recipe starts with IP addresses */ | ||
1294 | *mess++ ^= daddr; | ||
1295 | *mess++ ^= saddr; | ||
1275 | 1296 | ||
1276 | tcp_parse_options(skb, &tmp_opt, 0, dst); | 1297 | /* plus variable length Initiator Cookie */ |
1298 | c = (u8 *)mess; | ||
1299 | while (l-- > 0) | ||
1300 | *c++ ^= *hash_location++; | ||
1301 | |||
1302 | #ifdef CONFIG_SYN_COOKIES | ||
1303 | want_cookie = 0; /* not our kind of cookie */ | ||
1304 | #endif | ||
1305 | tmp_ext.cookie_out_never = 0; /* false */ | ||
1306 | tmp_ext.cookie_plus = tmp_opt.cookie_plus; | ||
1307 | } else if (!tp->rx_opt.cookie_in_always) { | ||
1308 | /* redundant indications, but ensure initialization. */ | ||
1309 | tmp_ext.cookie_out_never = 1; /* true */ | ||
1310 | tmp_ext.cookie_plus = 0; | ||
1311 | } else { | ||
1312 | goto drop_and_release; | ||
1313 | } | ||
1314 | tmp_ext.cookie_in_always = tp->rx_opt.cookie_in_always; | ||
1277 | 1315 | ||
1278 | if (want_cookie && !tmp_opt.saw_tstamp) | 1316 | if (want_cookie && !tmp_opt.saw_tstamp) |
1279 | tcp_clear_options(&tmp_opt); | 1317 | tcp_clear_options(&tmp_opt); |
1280 | 1318 | ||
1281 | tmp_opt.tstamp_ok = tmp_opt.saw_tstamp; | 1319 | tmp_opt.tstamp_ok = tmp_opt.saw_tstamp; |
1282 | |||
1283 | tcp_openreq_init(req, &tmp_opt, skb); | 1320 | tcp_openreq_init(req, &tmp_opt, skb); |
1284 | 1321 | ||
1285 | if (security_inet_conn_request(sk, skb, req)) | 1322 | if (security_inet_conn_request(sk, skb, req)) |
@@ -1339,7 +1376,9 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1339 | } | 1376 | } |
1340 | tcp_rsk(req)->snt_isn = isn; | 1377 | tcp_rsk(req)->snt_isn = isn; |
1341 | 1378 | ||
1342 | if (__tcp_v4_send_synack(sk, dst, req, NULL) || want_cookie) | 1379 | if (__tcp_v4_send_synack(sk, dst, req, |
1380 | (struct request_values *)&tmp_ext) || | ||
1381 | want_cookie) | ||
1343 | goto drop_and_free; | 1382 | goto drop_and_free; |
1344 | 1383 | ||
1345 | inet_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); | 1384 | inet_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); |