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/ipv6/tcp_ipv6.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/ipv6/tcp_ipv6.c')
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 52 |
1 files changed, 50 insertions, 2 deletions
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 | */ |
1163 | static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | 1163 | static 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); |