diff options
author | Christoph Paasch <christoph.paasch@uclouvain.be> | 2013-03-17 04:23:34 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-03-17 14:35:13 -0400 |
commit | 1a2c6181c4a1922021b4d7df373bba612c3e5f04 (patch) | |
tree | 1346c9b1db83495a98fbcf95f8e521c67fc55cb9 | |
parent | 94d8f2b133c9ff97105adc1233d1a35e16e1e7a6 (diff) |
tcp: Remove TCPCT
TCPCT uses option-number 253, reserved for experimental use and should
not be used in production environments.
Further, TCPCT does not fully implement RFC 6013.
As a nice side-effect, removing TCPCT increases TCP's performance for
very short flows:
Doing an apache-benchmark with -c 100 -n 100000, sending HTTP-requests
for files of 1KB size.
before this patch:
average (among 7 runs) of 20845.5 Requests/Second
after:
average (among 7 runs) of 21403.6 Requests/Second
Signed-off-by: Christoph Paasch <christoph.paasch@uclouvain.be>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | Documentation/networking/ip-sysctl.txt | 8 | ||||
-rw-r--r-- | drivers/infiniband/hw/cxgb4/cm.c | 2 | ||||
-rw-r--r-- | include/linux/tcp.h | 10 | ||||
-rw-r--r-- | include/net/request_sock.h | 8 | ||||
-rw-r--r-- | include/net/tcp.h | 89 | ||||
-rw-r--r-- | include/uapi/linux/tcp.h | 26 | ||||
-rw-r--r-- | net/dccp/ipv4.c | 5 | ||||
-rw-r--r-- | net/dccp/ipv6.c | 5 | ||||
-rw-r--r-- | net/ipv4/inet_connection_sock.c | 2 | ||||
-rw-r--r-- | net/ipv4/syncookies.c | 3 | ||||
-rw-r--r-- | net/ipv4/sysctl_net_ipv4.c | 7 | ||||
-rw-r--r-- | net/ipv4/tcp.c | 267 | ||||
-rw-r--r-- | net/ipv4/tcp_input.c | 69 | ||||
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 60 | ||||
-rw-r--r-- | net/ipv4/tcp_minisocks.c | 40 | ||||
-rw-r--r-- | net/ipv4/tcp_output.c | 219 | ||||
-rw-r--r-- | net/ipv6/syncookies.c | 3 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 56 |
18 files changed, 38 insertions, 841 deletions
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index 18a24c405ac0..17953e2bc3e9 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt | |||
@@ -175,14 +175,6 @@ tcp_congestion_control - STRING | |||
175 | is inherited. | 175 | is inherited. |
176 | [see setsockopt(listenfd, SOL_TCP, TCP_CONGESTION, "name" ...) ] | 176 | [see setsockopt(listenfd, SOL_TCP, TCP_CONGESTION, "name" ...) ] |
177 | 177 | ||
178 | tcp_cookie_size - INTEGER | ||
179 | Default size of TCP Cookie Transactions (TCPCT) option, that may be | ||
180 | overridden on a per socket basis by the TCPCT socket option. | ||
181 | Values greater than the maximum (16) are interpreted as the maximum. | ||
182 | Values greater than zero and less than the minimum (8) are interpreted | ||
183 | as the minimum. Odd values are interpreted as the next even value. | ||
184 | Default: 0 (off). | ||
185 | |||
186 | tcp_dsack - BOOLEAN | 178 | tcp_dsack - BOOLEAN |
187 | Allows TCP to send "duplicate" SACKs. | 179 | Allows TCP to send "duplicate" SACKs. |
188 | 180 | ||
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index 8dcc84fd9d30..54fd31fcc332 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c | |||
@@ -2915,7 +2915,7 @@ static void build_cpl_pass_accept_req(struct sk_buff *skb, int stid , u8 tos) | |||
2915 | */ | 2915 | */ |
2916 | memset(&tmp_opt, 0, sizeof(tmp_opt)); | 2916 | memset(&tmp_opt, 0, sizeof(tmp_opt)); |
2917 | tcp_clear_options(&tmp_opt); | 2917 | tcp_clear_options(&tmp_opt); |
2918 | tcp_parse_options(skb, &tmp_opt, NULL, 0, NULL); | 2918 | tcp_parse_options(skb, &tmp_opt, 0, NULL); |
2919 | 2919 | ||
2920 | req = (struct cpl_pass_accept_req *)__skb_push(skb, sizeof(*req)); | 2920 | req = (struct cpl_pass_accept_req *)__skb_push(skb, sizeof(*req)); |
2921 | memset(req, 0, sizeof(*req)); | 2921 | memset(req, 0, sizeof(*req)); |
diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 763c108ee03d..ed6a7456eecd 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h | |||
@@ -90,9 +90,6 @@ struct tcp_options_received { | |||
90 | sack_ok : 4, /* SACK seen on SYN packet */ | 90 | sack_ok : 4, /* SACK seen on SYN packet */ |
91 | snd_wscale : 4, /* Window scaling received from sender */ | 91 | snd_wscale : 4, /* Window scaling received from sender */ |
92 | rcv_wscale : 4; /* Window scaling to send to receiver */ | 92 | rcv_wscale : 4; /* Window scaling to send to receiver */ |
93 | u8 cookie_plus:6, /* bytes in authenticator/cookie option */ | ||
94 | cookie_out_never:1, | ||
95 | cookie_in_always:1; | ||
96 | u8 num_sacks; /* Number of SACK blocks */ | 93 | u8 num_sacks; /* Number of SACK blocks */ |
97 | u16 user_mss; /* mss requested by user in ioctl */ | 94 | u16 user_mss; /* mss requested by user in ioctl */ |
98 | u16 mss_clamp; /* Maximal mss, negotiated at connection setup */ | 95 | u16 mss_clamp; /* Maximal mss, negotiated at connection setup */ |
@@ -102,7 +99,6 @@ static inline void tcp_clear_options(struct tcp_options_received *rx_opt) | |||
102 | { | 99 | { |
103 | rx_opt->tstamp_ok = rx_opt->sack_ok = 0; | 100 | rx_opt->tstamp_ok = rx_opt->sack_ok = 0; |
104 | rx_opt->wscale_ok = rx_opt->snd_wscale = 0; | 101 | rx_opt->wscale_ok = rx_opt->snd_wscale = 0; |
105 | rx_opt->cookie_plus = 0; | ||
106 | } | 102 | } |
107 | 103 | ||
108 | /* This is the max number of SACKS that we'll generate and process. It's safe | 104 | /* This is the max number of SACKS that we'll generate and process. It's safe |
@@ -320,12 +316,6 @@ struct tcp_sock { | |||
320 | struct tcp_md5sig_info __rcu *md5sig_info; | 316 | struct tcp_md5sig_info __rcu *md5sig_info; |
321 | #endif | 317 | #endif |
322 | 318 | ||
323 | /* When the cookie options are generated and exchanged, then this | ||
324 | * object holds a reference to them (cookie_values->kref). Also | ||
325 | * contains related tcp_cookie_transactions fields. | ||
326 | */ | ||
327 | struct tcp_cookie_values *cookie_values; | ||
328 | |||
329 | /* TCP fastopen related information */ | 319 | /* TCP fastopen related information */ |
330 | struct tcp_fastopen_request *fastopen_req; | 320 | struct tcp_fastopen_request *fastopen_req; |
331 | /* fastopen_rsk points to request_sock that resulted in this big | 321 | /* fastopen_rsk points to request_sock that resulted in this big |
diff --git a/include/net/request_sock.h b/include/net/request_sock.h index a51dbd17c2de..9069e65c1c56 100644 --- a/include/net/request_sock.h +++ b/include/net/request_sock.h | |||
@@ -27,19 +27,13 @@ struct sk_buff; | |||
27 | struct dst_entry; | 27 | struct dst_entry; |
28 | struct proto; | 28 | struct proto; |
29 | 29 | ||
30 | /* empty to "strongly type" an otherwise void parameter. | ||
31 | */ | ||
32 | struct request_values { | ||
33 | }; | ||
34 | |||
35 | struct request_sock_ops { | 30 | struct request_sock_ops { |
36 | int family; | 31 | int family; |
37 | int obj_size; | 32 | int obj_size; |
38 | struct kmem_cache *slab; | 33 | struct kmem_cache *slab; |
39 | char *slab_name; | 34 | char *slab_name; |
40 | int (*rtx_syn_ack)(struct sock *sk, | 35 | int (*rtx_syn_ack)(struct sock *sk, |
41 | struct request_sock *req, | 36 | struct request_sock *req); |
42 | struct request_values *rvp); | ||
43 | void (*send_ack)(struct sock *sk, struct sk_buff *skb, | 37 | void (*send_ack)(struct sock *sk, struct sk_buff *skb, |
44 | struct request_sock *req); | 38 | struct request_sock *req); |
45 | void (*send_reset)(struct sock *sk, | 39 | void (*send_reset)(struct sock *sk, |
diff --git a/include/net/tcp.h b/include/net/tcp.h index ab9f947b118b..7f2f17198d75 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
@@ -179,7 +179,6 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo); | |||
179 | #define TCPOPT_SACK 5 /* SACK Block */ | 179 | #define TCPOPT_SACK 5 /* SACK Block */ |
180 | #define TCPOPT_TIMESTAMP 8 /* Better RTT estimations/PAWS */ | 180 | #define TCPOPT_TIMESTAMP 8 /* Better RTT estimations/PAWS */ |
181 | #define TCPOPT_MD5SIG 19 /* MD5 Signature (RFC2385) */ | 181 | #define TCPOPT_MD5SIG 19 /* MD5 Signature (RFC2385) */ |
182 | #define TCPOPT_COOKIE 253 /* Cookie extension (experimental) */ | ||
183 | #define TCPOPT_EXP 254 /* Experimental */ | 182 | #define TCPOPT_EXP 254 /* Experimental */ |
184 | /* Magic number to be after the option value for sharing TCP | 183 | /* Magic number to be after the option value for sharing TCP |
185 | * experimental options. See draft-ietf-tcpm-experimental-options-00.txt | 184 | * experimental options. See draft-ietf-tcpm-experimental-options-00.txt |
@@ -454,7 +453,7 @@ extern void tcp_syn_ack_timeout(struct sock *sk, struct request_sock *req); | |||
454 | extern int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | 453 | extern int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, |
455 | size_t len, int nonblock, int flags, int *addr_len); | 454 | size_t len, int nonblock, int flags, int *addr_len); |
456 | extern void tcp_parse_options(const struct sk_buff *skb, | 455 | extern void tcp_parse_options(const struct sk_buff *skb, |
457 | struct tcp_options_received *opt_rx, const u8 **hvpp, | 456 | struct tcp_options_received *opt_rx, |
458 | int estab, struct tcp_fastopen_cookie *foc); | 457 | int estab, struct tcp_fastopen_cookie *foc); |
459 | extern const u8 *tcp_parse_md5sig_option(const struct tcphdr *th); | 458 | extern const u8 *tcp_parse_md5sig_option(const struct tcphdr *th); |
460 | 459 | ||
@@ -476,7 +475,6 @@ extern int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, | |||
476 | extern int tcp_connect(struct sock *sk); | 475 | extern int tcp_connect(struct sock *sk); |
477 | extern struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst, | 476 | extern struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst, |
478 | struct request_sock *req, | 477 | struct request_sock *req, |
479 | struct request_values *rvp, | ||
480 | struct tcp_fastopen_cookie *foc); | 478 | struct tcp_fastopen_cookie *foc); |
481 | extern int tcp_disconnect(struct sock *sk, int flags); | 479 | extern int tcp_disconnect(struct sock *sk, int flags); |
482 | 480 | ||
@@ -1589,91 +1587,6 @@ struct tcp_request_sock_ops { | |||
1589 | #endif | 1587 | #endif |
1590 | }; | 1588 | }; |
1591 | 1589 | ||
1592 | /* Using SHA1 for now, define some constants. | ||
1593 | */ | ||
1594 | #define COOKIE_DIGEST_WORDS (SHA_DIGEST_WORDS) | ||
1595 | #define COOKIE_MESSAGE_WORDS (SHA_MESSAGE_BYTES / 4) | ||
1596 | #define COOKIE_WORKSPACE_WORDS (COOKIE_DIGEST_WORDS + COOKIE_MESSAGE_WORDS) | ||
1597 | |||
1598 | extern int tcp_cookie_generator(u32 *bakery); | ||
1599 | |||
1600 | /** | ||
1601 | * struct tcp_cookie_values - each socket needs extra space for the | ||
1602 | * cookies, together with (optional) space for any SYN data. | ||
1603 | * | ||
1604 | * A tcp_sock contains a pointer to the current value, and this is | ||
1605 | * cloned to the tcp_timewait_sock. | ||
1606 | * | ||
1607 | * @cookie_pair: variable data from the option exchange. | ||
1608 | * | ||
1609 | * @cookie_desired: user specified tcpct_cookie_desired. Zero | ||
1610 | * indicates default (sysctl_tcp_cookie_size). | ||
1611 | * After cookie sent, remembers size of cookie. | ||
1612 | * Range 0, TCP_COOKIE_MIN to TCP_COOKIE_MAX. | ||
1613 | * | ||
1614 | * @s_data_desired: user specified tcpct_s_data_desired. When the | ||
1615 | * constant payload is specified (@s_data_constant), | ||
1616 | * holds its length instead. | ||
1617 | * Range 0 to TCP_MSS_DESIRED. | ||
1618 | * | ||
1619 | * @s_data_payload: constant data that is to be included in the | ||
1620 | * payload of SYN or SYNACK segments when the | ||
1621 | * cookie option is present. | ||
1622 | */ | ||
1623 | struct tcp_cookie_values { | ||
1624 | struct kref kref; | ||
1625 | u8 cookie_pair[TCP_COOKIE_PAIR_SIZE]; | ||
1626 | u8 cookie_pair_size; | ||
1627 | u8 cookie_desired; | ||
1628 | u16 s_data_desired:11, | ||
1629 | s_data_constant:1, | ||
1630 | s_data_in:1, | ||
1631 | s_data_out:1, | ||
1632 | s_data_unused:2; | ||
1633 | u8 s_data_payload[0]; | ||
1634 | }; | ||
1635 | |||
1636 | static inline void tcp_cookie_values_release(struct kref *kref) | ||
1637 | { | ||
1638 | kfree(container_of(kref, struct tcp_cookie_values, kref)); | ||
1639 | } | ||
1640 | |||
1641 | /* The length of constant payload data. Note that s_data_desired is | ||
1642 | * overloaded, depending on s_data_constant: either the length of constant | ||
1643 | * data (returned here) or the limit on variable data. | ||
1644 | */ | ||
1645 | static inline int tcp_s_data_size(const struct tcp_sock *tp) | ||
1646 | { | ||
1647 | return (tp->cookie_values != NULL && tp->cookie_values->s_data_constant) | ||
1648 | ? tp->cookie_values->s_data_desired | ||
1649 | : 0; | ||
1650 | } | ||
1651 | |||
1652 | /** | ||
1653 | * struct tcp_extend_values - tcp_ipv?.c to tcp_output.c workspace. | ||
1654 | * | ||
1655 | * As tcp_request_sock has already been extended in other places, the | ||
1656 | * only remaining method is to pass stack values along as function | ||
1657 | * parameters. These parameters are not needed after sending SYNACK. | ||
1658 | * | ||
1659 | * @cookie_bakery: cryptographic secret and message workspace. | ||
1660 | * | ||
1661 | * @cookie_plus: bytes in authenticator/cookie option, copied from | ||
1662 | * struct tcp_options_received (above). | ||
1663 | */ | ||
1664 | struct tcp_extend_values { | ||
1665 | struct request_values rv; | ||
1666 | u32 cookie_bakery[COOKIE_WORKSPACE_WORDS]; | ||
1667 | u8 cookie_plus:6, | ||
1668 | cookie_out_never:1, | ||
1669 | cookie_in_always:1; | ||
1670 | }; | ||
1671 | |||
1672 | static inline struct tcp_extend_values *tcp_xv(struct request_values *rvp) | ||
1673 | { | ||
1674 | return (struct tcp_extend_values *)rvp; | ||
1675 | } | ||
1676 | |||
1677 | extern void tcp_v4_init(void); | 1590 | extern void tcp_v4_init(void); |
1678 | extern void tcp_init(void); | 1591 | extern void tcp_init(void); |
1679 | 1592 | ||
diff --git a/include/uapi/linux/tcp.h b/include/uapi/linux/tcp.h index 6b1ead0b0c9d..8d776ebc4829 100644 --- a/include/uapi/linux/tcp.h +++ b/include/uapi/linux/tcp.h | |||
@@ -102,7 +102,6 @@ enum { | |||
102 | #define TCP_QUICKACK 12 /* Block/reenable quick acks */ | 102 | #define TCP_QUICKACK 12 /* Block/reenable quick acks */ |
103 | #define TCP_CONGESTION 13 /* Congestion control algorithm */ | 103 | #define TCP_CONGESTION 13 /* Congestion control algorithm */ |
104 | #define TCP_MD5SIG 14 /* TCP MD5 Signature (RFC2385) */ | 104 | #define TCP_MD5SIG 14 /* TCP MD5 Signature (RFC2385) */ |
105 | #define TCP_COOKIE_TRANSACTIONS 15 /* TCP Cookie Transactions */ | ||
106 | #define TCP_THIN_LINEAR_TIMEOUTS 16 /* Use linear timeouts for thin streams*/ | 105 | #define TCP_THIN_LINEAR_TIMEOUTS 16 /* Use linear timeouts for thin streams*/ |
107 | #define TCP_THIN_DUPACK 17 /* Fast retrans. after 1 dupack */ | 106 | #define TCP_THIN_DUPACK 17 /* Fast retrans. after 1 dupack */ |
108 | #define TCP_USER_TIMEOUT 18 /* How long for loss retry before timeout */ | 107 | #define TCP_USER_TIMEOUT 18 /* How long for loss retry before timeout */ |
@@ -199,29 +198,4 @@ struct tcp_md5sig { | |||
199 | __u8 tcpm_key[TCP_MD5SIG_MAXKEYLEN]; /* key (binary) */ | 198 | __u8 tcpm_key[TCP_MD5SIG_MAXKEYLEN]; /* key (binary) */ |
200 | }; | 199 | }; |
201 | 200 | ||
202 | /* for TCP_COOKIE_TRANSACTIONS (TCPCT) socket option */ | ||
203 | #define TCP_COOKIE_MIN 8 /* 64-bits */ | ||
204 | #define TCP_COOKIE_MAX 16 /* 128-bits */ | ||
205 | #define TCP_COOKIE_PAIR_SIZE (2*TCP_COOKIE_MAX) | ||
206 | |||
207 | /* Flags for both getsockopt and setsockopt */ | ||
208 | #define TCP_COOKIE_IN_ALWAYS (1 << 0) /* Discard SYN without cookie */ | ||
209 | #define TCP_COOKIE_OUT_NEVER (1 << 1) /* Prohibit outgoing cookies, | ||
210 | * supercedes everything. */ | ||
211 | |||
212 | /* Flags for getsockopt */ | ||
213 | #define TCP_S_DATA_IN (1 << 2) /* Was data received? */ | ||
214 | #define TCP_S_DATA_OUT (1 << 3) /* Was data sent? */ | ||
215 | |||
216 | /* TCP_COOKIE_TRANSACTIONS data */ | ||
217 | struct tcp_cookie_transactions { | ||
218 | __u16 tcpct_flags; /* see above */ | ||
219 | __u8 __tcpct_pad1; /* zero */ | ||
220 | __u8 tcpct_cookie_desired; /* bytes */ | ||
221 | __u16 tcpct_s_data_desired; /* bytes of variable data */ | ||
222 | __u16 tcpct_used; /* bytes in value */ | ||
223 | __u8 tcpct_value[TCP_MSS_DEFAULT]; | ||
224 | }; | ||
225 | |||
226 | |||
227 | #endif /* _UAPI_LINUX_TCP_H */ | 201 | #endif /* _UAPI_LINUX_TCP_H */ |
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 4f9f5eb478f1..ebc54fef85a5 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c | |||
@@ -500,8 +500,7 @@ static struct dst_entry* dccp_v4_route_skb(struct net *net, struct sock *sk, | |||
500 | return &rt->dst; | 500 | return &rt->dst; |
501 | } | 501 | } |
502 | 502 | ||
503 | static int dccp_v4_send_response(struct sock *sk, struct request_sock *req, | 503 | static int dccp_v4_send_response(struct sock *sk, struct request_sock *req) |
504 | struct request_values *rv_unused) | ||
505 | { | 504 | { |
506 | int err = -1; | 505 | int err = -1; |
507 | struct sk_buff *skb; | 506 | struct sk_buff *skb; |
@@ -658,7 +657,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
658 | dreq->dreq_gss = dreq->dreq_iss; | 657 | dreq->dreq_gss = dreq->dreq_iss; |
659 | dreq->dreq_service = service; | 658 | dreq->dreq_service = service; |
660 | 659 | ||
661 | if (dccp_v4_send_response(sk, req, NULL)) | 660 | if (dccp_v4_send_response(sk, req)) |
662 | goto drop_and_free; | 661 | goto drop_and_free; |
663 | 662 | ||
664 | inet_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT); | 663 | inet_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT); |
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 6e05981f271e..9c61f9c02fdb 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c | |||
@@ -213,8 +213,7 @@ out: | |||
213 | } | 213 | } |
214 | 214 | ||
215 | 215 | ||
216 | static int dccp_v6_send_response(struct sock *sk, struct request_sock *req, | 216 | static int dccp_v6_send_response(struct sock *sk, struct request_sock *req) |
217 | struct request_values *rv_unused) | ||
218 | { | 217 | { |
219 | struct inet6_request_sock *ireq6 = inet6_rsk(req); | 218 | struct inet6_request_sock *ireq6 = inet6_rsk(req); |
220 | struct ipv6_pinfo *np = inet6_sk(sk); | 219 | struct ipv6_pinfo *np = inet6_sk(sk); |
@@ -428,7 +427,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
428 | dreq->dreq_gss = dreq->dreq_iss; | 427 | dreq->dreq_gss = dreq->dreq_iss; |
429 | dreq->dreq_service = service; | 428 | dreq->dreq_service = service; |
430 | 429 | ||
431 | if (dccp_v6_send_response(sk, req, NULL)) | 430 | if (dccp_v6_send_response(sk, req)) |
432 | goto drop_and_free; | 431 | goto drop_and_free; |
433 | 432 | ||
434 | inet6_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT); | 433 | inet6_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT); |
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 786d97aee751..6acb541c9091 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c | |||
@@ -559,7 +559,7 @@ static inline void syn_ack_recalc(struct request_sock *req, const int thresh, | |||
559 | 559 | ||
560 | int inet_rtx_syn_ack(struct sock *parent, struct request_sock *req) | 560 | int inet_rtx_syn_ack(struct sock *parent, struct request_sock *req) |
561 | { | 561 | { |
562 | int err = req->rsk_ops->rtx_syn_ack(parent, req, NULL); | 562 | int err = req->rsk_ops->rtx_syn_ack(parent, req); |
563 | 563 | ||
564 | if (!err) | 564 | if (!err) |
565 | req->num_retrans++; | 565 | req->num_retrans++; |
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index ef54377fb11c..7f4a5cb8f8d0 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c | |||
@@ -267,7 +267,6 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, | |||
267 | struct ip_options *opt) | 267 | struct ip_options *opt) |
268 | { | 268 | { |
269 | struct tcp_options_received tcp_opt; | 269 | struct tcp_options_received tcp_opt; |
270 | const u8 *hash_location; | ||
271 | struct inet_request_sock *ireq; | 270 | struct inet_request_sock *ireq; |
272 | struct tcp_request_sock *treq; | 271 | struct tcp_request_sock *treq; |
273 | struct tcp_sock *tp = tcp_sk(sk); | 272 | struct tcp_sock *tp = tcp_sk(sk); |
@@ -294,7 +293,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, | |||
294 | 293 | ||
295 | /* check for timestamp cookie support */ | 294 | /* check for timestamp cookie support */ |
296 | memset(&tcp_opt, 0, sizeof(tcp_opt)); | 295 | memset(&tcp_opt, 0, sizeof(tcp_opt)); |
297 | tcp_parse_options(skb, &tcp_opt, &hash_location, 0, NULL); | 296 | tcp_parse_options(skb, &tcp_opt, 0, NULL); |
298 | 297 | ||
299 | if (!cookie_check_timestamp(&tcp_opt, sock_net(sk), &ecn_ok)) | 298 | if (!cookie_check_timestamp(&tcp_opt, sock_net(sk), &ecn_ok)) |
300 | goto out; | 299 | goto out; |
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index cca4550f4082..cb45062c8be0 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c | |||
@@ -733,13 +733,6 @@ static struct ctl_table ipv4_table[] = { | |||
733 | .proc_handler = proc_dointvec, | 733 | .proc_handler = proc_dointvec, |
734 | }, | 734 | }, |
735 | { | 735 | { |
736 | .procname = "tcp_cookie_size", | ||
737 | .data = &sysctl_tcp_cookie_size, | ||
738 | .maxlen = sizeof(int), | ||
739 | .mode = 0644, | ||
740 | .proc_handler = proc_dointvec | ||
741 | }, | ||
742 | { | ||
743 | .procname = "tcp_thin_linear_timeouts", | 736 | .procname = "tcp_thin_linear_timeouts", |
744 | .data = &sysctl_tcp_thin_linear_timeouts, | 737 | .data = &sysctl_tcp_thin_linear_timeouts, |
745 | .maxlen = sizeof(int), | 738 | .maxlen = sizeof(int), |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 8d14573ade77..17a6810af5c8 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -409,15 +409,6 @@ void tcp_init_sock(struct sock *sk) | |||
409 | 409 | ||
410 | icsk->icsk_sync_mss = tcp_sync_mss; | 410 | icsk->icsk_sync_mss = tcp_sync_mss; |
411 | 411 | ||
412 | /* TCP Cookie Transactions */ | ||
413 | if (sysctl_tcp_cookie_size > 0) { | ||
414 | /* Default, cookies without s_data_payload. */ | ||
415 | tp->cookie_values = | ||
416 | kzalloc(sizeof(*tp->cookie_values), | ||
417 | sk->sk_allocation); | ||
418 | if (tp->cookie_values != NULL) | ||
419 | kref_init(&tp->cookie_values->kref); | ||
420 | } | ||
421 | /* Presumed zeroed, in order of appearance: | 412 | /* Presumed zeroed, in order of appearance: |
422 | * cookie_in_always, cookie_out_never, | 413 | * cookie_in_always, cookie_out_never, |
423 | * s_data_constant, s_data_in, s_data_out | 414 | * s_data_constant, s_data_in, s_data_out |
@@ -2397,92 +2388,6 @@ static int do_tcp_setsockopt(struct sock *sk, int level, | |||
2397 | release_sock(sk); | 2388 | release_sock(sk); |
2398 | return err; | 2389 | return err; |
2399 | } | 2390 | } |
2400 | case TCP_COOKIE_TRANSACTIONS: { | ||
2401 | struct tcp_cookie_transactions ctd; | ||
2402 | struct tcp_cookie_values *cvp = NULL; | ||
2403 | |||
2404 | if (sizeof(ctd) > optlen) | ||
2405 | return -EINVAL; | ||
2406 | if (copy_from_user(&ctd, optval, sizeof(ctd))) | ||
2407 | return -EFAULT; | ||
2408 | |||
2409 | if (ctd.tcpct_used > sizeof(ctd.tcpct_value) || | ||
2410 | ctd.tcpct_s_data_desired > TCP_MSS_DESIRED) | ||
2411 | return -EINVAL; | ||
2412 | |||
2413 | if (ctd.tcpct_cookie_desired == 0) { | ||
2414 | /* default to global value */ | ||
2415 | } else if ((0x1 & ctd.tcpct_cookie_desired) || | ||
2416 | ctd.tcpct_cookie_desired > TCP_COOKIE_MAX || | ||
2417 | ctd.tcpct_cookie_desired < TCP_COOKIE_MIN) { | ||
2418 | return -EINVAL; | ||
2419 | } | ||
2420 | |||
2421 | if (TCP_COOKIE_OUT_NEVER & ctd.tcpct_flags) { | ||
2422 | /* Supercedes all other values */ | ||
2423 | lock_sock(sk); | ||
2424 | if (tp->cookie_values != NULL) { | ||
2425 | kref_put(&tp->cookie_values->kref, | ||
2426 | tcp_cookie_values_release); | ||
2427 | tp->cookie_values = NULL; | ||
2428 | } | ||
2429 | tp->rx_opt.cookie_in_always = 0; /* false */ | ||
2430 | tp->rx_opt.cookie_out_never = 1; /* true */ | ||
2431 | release_sock(sk); | ||
2432 | return err; | ||
2433 | } | ||
2434 | |||
2435 | /* Allocate ancillary memory before locking. | ||
2436 | */ | ||
2437 | if (ctd.tcpct_used > 0 || | ||
2438 | (tp->cookie_values == NULL && | ||
2439 | (sysctl_tcp_cookie_size > 0 || | ||
2440 | ctd.tcpct_cookie_desired > 0 || | ||
2441 | ctd.tcpct_s_data_desired > 0))) { | ||
2442 | cvp = kzalloc(sizeof(*cvp) + ctd.tcpct_used, | ||
2443 | GFP_KERNEL); | ||
2444 | if (cvp == NULL) | ||
2445 | return -ENOMEM; | ||
2446 | |||
2447 | kref_init(&cvp->kref); | ||
2448 | } | ||
2449 | lock_sock(sk); | ||
2450 | tp->rx_opt.cookie_in_always = | ||
2451 | (TCP_COOKIE_IN_ALWAYS & ctd.tcpct_flags); | ||
2452 | tp->rx_opt.cookie_out_never = 0; /* false */ | ||
2453 | |||
2454 | if (tp->cookie_values != NULL) { | ||
2455 | if (cvp != NULL) { | ||
2456 | /* Changed values are recorded by a changed | ||
2457 | * pointer, ensuring the cookie will differ, | ||
2458 | * without separately hashing each value later. | ||
2459 | */ | ||
2460 | kref_put(&tp->cookie_values->kref, | ||
2461 | tcp_cookie_values_release); | ||
2462 | } else { | ||
2463 | cvp = tp->cookie_values; | ||
2464 | } | ||
2465 | } | ||
2466 | |||
2467 | if (cvp != NULL) { | ||
2468 | cvp->cookie_desired = ctd.tcpct_cookie_desired; | ||
2469 | |||
2470 | if (ctd.tcpct_used > 0) { | ||
2471 | memcpy(cvp->s_data_payload, ctd.tcpct_value, | ||
2472 | ctd.tcpct_used); | ||
2473 | cvp->s_data_desired = ctd.tcpct_used; | ||
2474 | cvp->s_data_constant = 1; /* true */ | ||
2475 | } else { | ||
2476 | /* No constant payload data. */ | ||
2477 | cvp->s_data_desired = ctd.tcpct_s_data_desired; | ||
2478 | cvp->s_data_constant = 0; /* false */ | ||
2479 | } | ||
2480 | |||
2481 | tp->cookie_values = cvp; | ||
2482 | } | ||
2483 | release_sock(sk); | ||
2484 | return err; | ||
2485 | } | ||
2486 | default: | 2391 | default: |
2487 | /* fallthru */ | 2392 | /* fallthru */ |
2488 | break; | 2393 | break; |
@@ -2902,41 +2807,6 @@ static int do_tcp_getsockopt(struct sock *sk, int level, | |||
2902 | return -EFAULT; | 2807 | return -EFAULT; |
2903 | return 0; | 2808 | return 0; |
2904 | 2809 | ||
2905 | case TCP_COOKIE_TRANSACTIONS: { | ||
2906 | struct tcp_cookie_transactions ctd; | ||
2907 | struct tcp_cookie_values *cvp = tp->cookie_values; | ||
2908 | |||
2909 | if (get_user(len, optlen)) | ||
2910 | return -EFAULT; | ||
2911 | if (len < sizeof(ctd)) | ||
2912 | return -EINVAL; | ||
2913 | |||
2914 | memset(&ctd, 0, sizeof(ctd)); | ||
2915 | ctd.tcpct_flags = (tp->rx_opt.cookie_in_always ? | ||
2916 | TCP_COOKIE_IN_ALWAYS : 0) | ||
2917 | | (tp->rx_opt.cookie_out_never ? | ||
2918 | TCP_COOKIE_OUT_NEVER : 0); | ||
2919 | |||
2920 | if (cvp != NULL) { | ||
2921 | ctd.tcpct_flags |= (cvp->s_data_in ? | ||
2922 | TCP_S_DATA_IN : 0) | ||
2923 | | (cvp->s_data_out ? | ||
2924 | TCP_S_DATA_OUT : 0); | ||
2925 | |||
2926 | ctd.tcpct_cookie_desired = cvp->cookie_desired; | ||
2927 | ctd.tcpct_s_data_desired = cvp->s_data_desired; | ||
2928 | |||
2929 | memcpy(&ctd.tcpct_value[0], &cvp->cookie_pair[0], | ||
2930 | cvp->cookie_pair_size); | ||
2931 | ctd.tcpct_used = cvp->cookie_pair_size; | ||
2932 | } | ||
2933 | |||
2934 | if (put_user(sizeof(ctd), optlen)) | ||
2935 | return -EFAULT; | ||
2936 | if (copy_to_user(optval, &ctd, sizeof(ctd))) | ||
2937 | return -EFAULT; | ||
2938 | return 0; | ||
2939 | } | ||
2940 | case TCP_THIN_LINEAR_TIMEOUTS: | 2810 | case TCP_THIN_LINEAR_TIMEOUTS: |
2941 | val = tp->thin_lto; | 2811 | val = tp->thin_lto; |
2942 | break; | 2812 | break; |
@@ -3409,134 +3279,6 @@ EXPORT_SYMBOL(tcp_md5_hash_key); | |||
3409 | 3279 | ||
3410 | #endif | 3280 | #endif |
3411 | 3281 | ||
3412 | /* Each Responder maintains up to two secret values concurrently for | ||
3413 | * efficient secret rollover. Each secret value has 4 states: | ||
3414 | * | ||
3415 | * Generating. (tcp_secret_generating != tcp_secret_primary) | ||
3416 | * Generates new Responder-Cookies, but not yet used for primary | ||
3417 | * verification. This is a short-term state, typically lasting only | ||
3418 | * one round trip time (RTT). | ||
3419 | * | ||
3420 | * Primary. (tcp_secret_generating == tcp_secret_primary) | ||
3421 | * Used both for generation and primary verification. | ||
3422 | * | ||
3423 | * Retiring. (tcp_secret_retiring != tcp_secret_secondary) | ||
3424 | * Used for verification, until the first failure that can be | ||
3425 | * verified by the newer Generating secret. At that time, this | ||
3426 | * cookie's state is changed to Secondary, and the Generating | ||
3427 | * cookie's state is changed to Primary. This is a short-term state, | ||
3428 | * typically lasting only one round trip time (RTT). | ||
3429 | * | ||
3430 | * Secondary. (tcp_secret_retiring == tcp_secret_secondary) | ||
3431 | * Used for secondary verification, after primary verification | ||
3432 | * failures. This state lasts no more than twice the Maximum Segment | ||
3433 | * Lifetime (2MSL). Then, the secret is discarded. | ||
3434 | */ | ||
3435 | struct tcp_cookie_secret { | ||
3436 | /* The secret is divided into two parts. The digest part is the | ||
3437 | * equivalent of previously hashing a secret and saving the state, | ||
3438 | * and serves as an initialization vector (IV). The message part | ||
3439 | * serves as the trailing secret. | ||
3440 | */ | ||
3441 | u32 secrets[COOKIE_WORKSPACE_WORDS]; | ||
3442 | unsigned long expires; | ||
3443 | }; | ||
3444 | |||
3445 | #define TCP_SECRET_1MSL (HZ * TCP_PAWS_MSL) | ||
3446 | #define TCP_SECRET_2MSL (HZ * TCP_PAWS_MSL * 2) | ||
3447 | #define TCP_SECRET_LIFE (HZ * 600) | ||
3448 | |||
3449 | static struct tcp_cookie_secret tcp_secret_one; | ||
3450 | static struct tcp_cookie_secret tcp_secret_two; | ||
3451 | |||
3452 | /* Essentially a circular list, without dynamic allocation. */ | ||
3453 | static struct tcp_cookie_secret *tcp_secret_generating; | ||
3454 | static struct tcp_cookie_secret *tcp_secret_primary; | ||
3455 | static struct tcp_cookie_secret *tcp_secret_retiring; | ||
3456 | static struct tcp_cookie_secret *tcp_secret_secondary; | ||
3457 | |||
3458 | static DEFINE_SPINLOCK(tcp_secret_locker); | ||
3459 | |||
3460 | /* Select a pseudo-random word in the cookie workspace. | ||
3461 | */ | ||
3462 | static inline u32 tcp_cookie_work(const u32 *ws, const int n) | ||
3463 | { | ||
3464 | return ws[COOKIE_DIGEST_WORDS + ((COOKIE_MESSAGE_WORDS-1) & ws[n])]; | ||
3465 | } | ||
3466 | |||
3467 | /* Fill bakery[COOKIE_WORKSPACE_WORDS] with generator, updating as needed. | ||
3468 | * Called in softirq context. | ||
3469 | * Returns: 0 for success. | ||
3470 | */ | ||
3471 | int tcp_cookie_generator(u32 *bakery) | ||
3472 | { | ||
3473 | unsigned long jiffy = jiffies; | ||
3474 | |||
3475 | if (unlikely(time_after_eq(jiffy, tcp_secret_generating->expires))) { | ||
3476 | spin_lock_bh(&tcp_secret_locker); | ||
3477 | if (!time_after_eq(jiffy, tcp_secret_generating->expires)) { | ||
3478 | /* refreshed by another */ | ||
3479 | memcpy(bakery, | ||
3480 | &tcp_secret_generating->secrets[0], | ||
3481 | COOKIE_WORKSPACE_WORDS); | ||
3482 | } else { | ||
3483 | /* still needs refreshing */ | ||
3484 | get_random_bytes(bakery, COOKIE_WORKSPACE_WORDS); | ||
3485 | |||
3486 | /* The first time, paranoia assumes that the | ||
3487 | * randomization function isn't as strong. But, | ||
3488 | * this secret initialization is delayed until | ||
3489 | * the last possible moment (packet arrival). | ||
3490 | * Although that time is observable, it is | ||
3491 | * unpredictably variable. Mash in the most | ||
3492 | * volatile clock bits available, and expire the | ||
3493 | * secret extra quickly. | ||
3494 | */ | ||
3495 | if (unlikely(tcp_secret_primary->expires == | ||
3496 | tcp_secret_secondary->expires)) { | ||
3497 | struct timespec tv; | ||
3498 | |||
3499 | getnstimeofday(&tv); | ||
3500 | bakery[COOKIE_DIGEST_WORDS+0] ^= | ||
3501 | (u32)tv.tv_nsec; | ||
3502 | |||
3503 | tcp_secret_secondary->expires = jiffy | ||
3504 | + TCP_SECRET_1MSL | ||
3505 | + (0x0f & tcp_cookie_work(bakery, 0)); | ||
3506 | } else { | ||
3507 | tcp_secret_secondary->expires = jiffy | ||
3508 | + TCP_SECRET_LIFE | ||
3509 | + (0xff & tcp_cookie_work(bakery, 1)); | ||
3510 | tcp_secret_primary->expires = jiffy | ||
3511 | + TCP_SECRET_2MSL | ||
3512 | + (0x1f & tcp_cookie_work(bakery, 2)); | ||
3513 | } | ||
3514 | memcpy(&tcp_secret_secondary->secrets[0], | ||
3515 | bakery, COOKIE_WORKSPACE_WORDS); | ||
3516 | |||
3517 | rcu_assign_pointer(tcp_secret_generating, | ||
3518 | tcp_secret_secondary); | ||
3519 | rcu_assign_pointer(tcp_secret_retiring, | ||
3520 | tcp_secret_primary); | ||
3521 | /* | ||
3522 | * Neither call_rcu() nor synchronize_rcu() needed. | ||
3523 | * Retiring data is not freed. It is replaced after | ||
3524 | * further (locked) pointer updates, and a quiet time | ||
3525 | * (minimum 1MSL, maximum LIFE - 2MSL). | ||
3526 | */ | ||
3527 | } | ||
3528 | spin_unlock_bh(&tcp_secret_locker); | ||
3529 | } else { | ||
3530 | rcu_read_lock_bh(); | ||
3531 | memcpy(bakery, | ||
3532 | &rcu_dereference(tcp_secret_generating)->secrets[0], | ||
3533 | COOKIE_WORKSPACE_WORDS); | ||
3534 | rcu_read_unlock_bh(); | ||
3535 | } | ||
3536 | return 0; | ||
3537 | } | ||
3538 | EXPORT_SYMBOL(tcp_cookie_generator); | ||
3539 | |||
3540 | void tcp_done(struct sock *sk) | 3282 | void tcp_done(struct sock *sk) |
3541 | { | 3283 | { |
3542 | struct request_sock *req = tcp_sk(sk)->fastopen_rsk; | 3284 | struct request_sock *req = tcp_sk(sk)->fastopen_rsk; |
@@ -3591,7 +3333,6 @@ void __init tcp_init(void) | |||
3591 | unsigned long limit; | 3333 | unsigned long limit; |
3592 | int max_rshare, max_wshare, cnt; | 3334 | int max_rshare, max_wshare, cnt; |
3593 | unsigned int i; | 3335 | unsigned int i; |
3594 | unsigned long jiffy = jiffies; | ||
3595 | 3336 | ||
3596 | BUILD_BUG_ON(sizeof(struct tcp_skb_cb) > sizeof(skb->cb)); | 3337 | BUILD_BUG_ON(sizeof(struct tcp_skb_cb) > sizeof(skb->cb)); |
3597 | 3338 | ||
@@ -3667,13 +3408,5 @@ void __init tcp_init(void) | |||
3667 | 3408 | ||
3668 | tcp_register_congestion_control(&tcp_reno); | 3409 | tcp_register_congestion_control(&tcp_reno); |
3669 | 3410 | ||
3670 | memset(&tcp_secret_one.secrets[0], 0, sizeof(tcp_secret_one.secrets)); | ||
3671 | memset(&tcp_secret_two.secrets[0], 0, sizeof(tcp_secret_two.secrets)); | ||
3672 | tcp_secret_one.expires = jiffy; /* past due */ | ||
3673 | tcp_secret_two.expires = jiffy; /* past due */ | ||
3674 | tcp_secret_generating = &tcp_secret_one; | ||
3675 | tcp_secret_primary = &tcp_secret_one; | ||
3676 | tcp_secret_retiring = &tcp_secret_two; | ||
3677 | tcp_secret_secondary = &tcp_secret_two; | ||
3678 | tcp_tasklet_init(); | 3411 | tcp_tasklet_init(); |
3679 | } | 3412 | } |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 836d74dd0187..19f0149fb6a2 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -3760,8 +3760,8 @@ old_ack: | |||
3760 | * But, this can also be called on packets in the established flow when | 3760 | * But, this can also be called on packets in the established flow when |
3761 | * the fast version below fails. | 3761 | * the fast version below fails. |
3762 | */ | 3762 | */ |
3763 | void tcp_parse_options(const struct sk_buff *skb, struct tcp_options_received *opt_rx, | 3763 | void tcp_parse_options(const struct sk_buff *skb, |
3764 | const u8 **hvpp, int estab, | 3764 | struct tcp_options_received *opt_rx, int estab, |
3765 | struct tcp_fastopen_cookie *foc) | 3765 | struct tcp_fastopen_cookie *foc) |
3766 | { | 3766 | { |
3767 | const unsigned char *ptr; | 3767 | const unsigned char *ptr; |
@@ -3845,31 +3845,6 @@ void tcp_parse_options(const struct sk_buff *skb, struct tcp_options_received *o | |||
3845 | */ | 3845 | */ |
3846 | break; | 3846 | break; |
3847 | #endif | 3847 | #endif |
3848 | case TCPOPT_COOKIE: | ||
3849 | /* This option is variable length. | ||
3850 | */ | ||
3851 | switch (opsize) { | ||
3852 | case TCPOLEN_COOKIE_BASE: | ||
3853 | /* not yet implemented */ | ||
3854 | break; | ||
3855 | case TCPOLEN_COOKIE_PAIR: | ||
3856 | /* not yet implemented */ | ||
3857 | break; | ||
3858 | case TCPOLEN_COOKIE_MIN+0: | ||
3859 | case TCPOLEN_COOKIE_MIN+2: | ||
3860 | case TCPOLEN_COOKIE_MIN+4: | ||
3861 | case TCPOLEN_COOKIE_MIN+6: | ||
3862 | case TCPOLEN_COOKIE_MAX: | ||
3863 | /* 16-bit multiple */ | ||
3864 | opt_rx->cookie_plus = opsize; | ||
3865 | *hvpp = ptr; | ||
3866 | break; | ||
3867 | default: | ||
3868 | /* ignore option */ | ||
3869 | break; | ||
3870 | } | ||
3871 | break; | ||
3872 | |||
3873 | case TCPOPT_EXP: | 3848 | case TCPOPT_EXP: |
3874 | /* Fast Open option shares code 254 using a | 3849 | /* Fast Open option shares code 254 using a |
3875 | * 16 bits magic number. It's valid only in | 3850 | * 16 bits magic number. It's valid only in |
@@ -3915,8 +3890,7 @@ static bool tcp_parse_aligned_timestamp(struct tcp_sock *tp, const struct tcphdr | |||
3915 | * If it is wrong it falls back on tcp_parse_options(). | 3890 | * If it is wrong it falls back on tcp_parse_options(). |
3916 | */ | 3891 | */ |
3917 | static bool tcp_fast_parse_options(const struct sk_buff *skb, | 3892 | static bool tcp_fast_parse_options(const struct sk_buff *skb, |
3918 | const struct tcphdr *th, | 3893 | const struct tcphdr *th, struct tcp_sock *tp) |
3919 | struct tcp_sock *tp, const u8 **hvpp) | ||
3920 | { | 3894 | { |
3921 | /* In the spirit of fast parsing, compare doff directly to constant | 3895 | /* In the spirit of fast parsing, compare doff directly to constant |
3922 | * values. Because equality is used, short doff can be ignored here. | 3896 | * values. Because equality is used, short doff can be ignored here. |
@@ -3930,7 +3904,7 @@ static bool tcp_fast_parse_options(const struct sk_buff *skb, | |||
3930 | return true; | 3904 | return true; |
3931 | } | 3905 | } |
3932 | 3906 | ||
3933 | tcp_parse_options(skb, &tp->rx_opt, hvpp, 1, NULL); | 3907 | tcp_parse_options(skb, &tp->rx_opt, 1, NULL); |
3934 | if (tp->rx_opt.saw_tstamp) | 3908 | if (tp->rx_opt.saw_tstamp) |
3935 | tp->rx_opt.rcv_tsecr -= tp->tsoffset; | 3909 | tp->rx_opt.rcv_tsecr -= tp->tsoffset; |
3936 | 3910 | ||
@@ -5311,12 +5285,10 @@ out: | |||
5311 | static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb, | 5285 | static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb, |
5312 | const struct tcphdr *th, int syn_inerr) | 5286 | const struct tcphdr *th, int syn_inerr) |
5313 | { | 5287 | { |
5314 | const u8 *hash_location; | ||
5315 | struct tcp_sock *tp = tcp_sk(sk); | 5288 | struct tcp_sock *tp = tcp_sk(sk); |
5316 | 5289 | ||
5317 | /* RFC1323: H1. Apply PAWS check first. */ | 5290 | /* RFC1323: H1. Apply PAWS check first. */ |
5318 | if (tcp_fast_parse_options(skb, th, tp, &hash_location) && | 5291 | if (tcp_fast_parse_options(skb, th, tp) && tp->rx_opt.saw_tstamp && |
5319 | tp->rx_opt.saw_tstamp && | ||
5320 | tcp_paws_discard(sk, skb)) { | 5292 | tcp_paws_discard(sk, skb)) { |
5321 | if (!th->rst) { | 5293 | if (!th->rst) { |
5322 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSESTABREJECTED); | 5294 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSESTABREJECTED); |
@@ -5670,12 +5642,11 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack, | |||
5670 | 5642 | ||
5671 | if (mss == tp->rx_opt.user_mss) { | 5643 | if (mss == tp->rx_opt.user_mss) { |
5672 | struct tcp_options_received opt; | 5644 | struct tcp_options_received opt; |
5673 | const u8 *hash_location; | ||
5674 | 5645 | ||
5675 | /* Get original SYNACK MSS value if user MSS sets mss_clamp */ | 5646 | /* Get original SYNACK MSS value if user MSS sets mss_clamp */ |
5676 | tcp_clear_options(&opt); | 5647 | tcp_clear_options(&opt); |
5677 | opt.user_mss = opt.mss_clamp = 0; | 5648 | opt.user_mss = opt.mss_clamp = 0; |
5678 | tcp_parse_options(synack, &opt, &hash_location, 0, NULL); | 5649 | tcp_parse_options(synack, &opt, 0, NULL); |
5679 | mss = opt.mss_clamp; | 5650 | mss = opt.mss_clamp; |
5680 | } | 5651 | } |
5681 | 5652 | ||
@@ -5706,14 +5677,12 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack, | |||
5706 | static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, | 5677 | static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, |
5707 | const struct tcphdr *th, unsigned int len) | 5678 | const struct tcphdr *th, unsigned int len) |
5708 | { | 5679 | { |
5709 | const u8 *hash_location; | ||
5710 | struct inet_connection_sock *icsk = inet_csk(sk); | 5680 | struct inet_connection_sock *icsk = inet_csk(sk); |
5711 | struct tcp_sock *tp = tcp_sk(sk); | 5681 | struct tcp_sock *tp = tcp_sk(sk); |
5712 | struct tcp_cookie_values *cvp = tp->cookie_values; | ||
5713 | struct tcp_fastopen_cookie foc = { .len = -1 }; | 5682 | struct tcp_fastopen_cookie foc = { .len = -1 }; |
5714 | int saved_clamp = tp->rx_opt.mss_clamp; | 5683 | int saved_clamp = tp->rx_opt.mss_clamp; |
5715 | 5684 | ||
5716 | tcp_parse_options(skb, &tp->rx_opt, &hash_location, 0, &foc); | 5685 | tcp_parse_options(skb, &tp->rx_opt, 0, &foc); |
5717 | if (tp->rx_opt.saw_tstamp) | 5686 | if (tp->rx_opt.saw_tstamp) |
5718 | tp->rx_opt.rcv_tsecr -= tp->tsoffset; | 5687 | tp->rx_opt.rcv_tsecr -= tp->tsoffset; |
5719 | 5688 | ||
@@ -5810,30 +5779,6 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, | |||
5810 | * is initialized. */ | 5779 | * is initialized. */ |
5811 | tp->copied_seq = tp->rcv_nxt; | 5780 | tp->copied_seq = tp->rcv_nxt; |
5812 | 5781 | ||
5813 | if (cvp != NULL && | ||
5814 | cvp->cookie_pair_size > 0 && | ||
5815 | tp->rx_opt.cookie_plus > 0) { | ||
5816 | int cookie_size = tp->rx_opt.cookie_plus | ||
5817 | - TCPOLEN_COOKIE_BASE; | ||
5818 | int cookie_pair_size = cookie_size | ||
5819 | + cvp->cookie_desired; | ||
5820 | |||
5821 | /* A cookie extension option was sent and returned. | ||
5822 | * Note that each incoming SYNACK replaces the | ||
5823 | * Responder cookie. The initial exchange is most | ||
5824 | * fragile, as protection against spoofing relies | ||
5825 | * entirely upon the sequence and timestamp (above). | ||
5826 | * This replacement strategy allows the correct pair to | ||
5827 | * pass through, while any others will be filtered via | ||
5828 | * Responder verification later. | ||
5829 | */ | ||
5830 | if (sizeof(cvp->cookie_pair) >= cookie_pair_size) { | ||
5831 | memcpy(&cvp->cookie_pair[cvp->cookie_desired], | ||
5832 | hash_location, cookie_size); | ||
5833 | cvp->cookie_pair_size = cookie_pair_size; | ||
5834 | } | ||
5835 | } | ||
5836 | |||
5837 | smp_mb(); | 5782 | smp_mb(); |
5838 | 5783 | ||
5839 | tcp_finish_connect(sk, skb); | 5784 | tcp_finish_connect(sk, skb); |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index b7ab868c8284..b27c758ca23f 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -838,7 +838,6 @@ static void tcp_v4_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, | |||
838 | */ | 838 | */ |
839 | static int tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst, | 839 | static int tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst, |
840 | struct request_sock *req, | 840 | struct request_sock *req, |
841 | struct request_values *rvp, | ||
842 | u16 queue_mapping, | 841 | u16 queue_mapping, |
843 | bool nocache) | 842 | bool nocache) |
844 | { | 843 | { |
@@ -851,7 +850,7 @@ static int tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst, | |||
851 | if (!dst && (dst = inet_csk_route_req(sk, &fl4, req)) == NULL) | 850 | if (!dst && (dst = inet_csk_route_req(sk, &fl4, req)) == NULL) |
852 | return -1; | 851 | return -1; |
853 | 852 | ||
854 | skb = tcp_make_synack(sk, dst, req, rvp, NULL); | 853 | skb = tcp_make_synack(sk, dst, req, NULL); |
855 | 854 | ||
856 | if (skb) { | 855 | if (skb) { |
857 | __tcp_v4_send_check(skb, ireq->loc_addr, ireq->rmt_addr); | 856 | __tcp_v4_send_check(skb, ireq->loc_addr, ireq->rmt_addr); |
@@ -868,10 +867,9 @@ static int tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst, | |||
868 | return err; | 867 | return err; |
869 | } | 868 | } |
870 | 869 | ||
871 | static int tcp_v4_rtx_synack(struct sock *sk, struct request_sock *req, | 870 | static int tcp_v4_rtx_synack(struct sock *sk, struct request_sock *req) |
872 | struct request_values *rvp) | ||
873 | { | 871 | { |
874 | int res = tcp_v4_send_synack(sk, NULL, req, rvp, 0, false); | 872 | int res = tcp_v4_send_synack(sk, NULL, req, 0, false); |
875 | 873 | ||
876 | if (!res) | 874 | if (!res) |
877 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS); | 875 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS); |
@@ -1371,8 +1369,7 @@ static bool tcp_fastopen_check(struct sock *sk, struct sk_buff *skb, | |||
1371 | static int tcp_v4_conn_req_fastopen(struct sock *sk, | 1369 | static int tcp_v4_conn_req_fastopen(struct sock *sk, |
1372 | struct sk_buff *skb, | 1370 | struct sk_buff *skb, |
1373 | struct sk_buff *skb_synack, | 1371 | struct sk_buff *skb_synack, |
1374 | struct request_sock *req, | 1372 | struct request_sock *req) |
1375 | struct request_values *rvp) | ||
1376 | { | 1373 | { |
1377 | struct tcp_sock *tp = tcp_sk(sk); | 1374 | struct tcp_sock *tp = tcp_sk(sk); |
1378 | struct request_sock_queue *queue = &inet_csk(sk)->icsk_accept_queue; | 1375 | struct request_sock_queue *queue = &inet_csk(sk)->icsk_accept_queue; |
@@ -1467,9 +1464,7 @@ static int tcp_v4_conn_req_fastopen(struct sock *sk, | |||
1467 | 1464 | ||
1468 | int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | 1465 | int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) |
1469 | { | 1466 | { |
1470 | struct tcp_extend_values tmp_ext; | ||
1471 | struct tcp_options_received tmp_opt; | 1467 | struct tcp_options_received tmp_opt; |
1472 | const u8 *hash_location; | ||
1473 | struct request_sock *req; | 1468 | struct request_sock *req; |
1474 | struct inet_request_sock *ireq; | 1469 | struct inet_request_sock *ireq; |
1475 | struct tcp_sock *tp = tcp_sk(sk); | 1470 | struct tcp_sock *tp = tcp_sk(sk); |
@@ -1519,42 +1514,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1519 | tcp_clear_options(&tmp_opt); | 1514 | tcp_clear_options(&tmp_opt); |
1520 | tmp_opt.mss_clamp = TCP_MSS_DEFAULT; | 1515 | tmp_opt.mss_clamp = TCP_MSS_DEFAULT; |
1521 | tmp_opt.user_mss = tp->rx_opt.user_mss; | 1516 | tmp_opt.user_mss = tp->rx_opt.user_mss; |
1522 | tcp_parse_options(skb, &tmp_opt, &hash_location, 0, | 1517 | tcp_parse_options(skb, &tmp_opt, 0, want_cookie ? NULL : &foc); |
1523 | want_cookie ? NULL : &foc); | ||
1524 | |||
1525 | if (tmp_opt.cookie_plus > 0 && | ||
1526 | tmp_opt.saw_tstamp && | ||
1527 | !tp->rx_opt.cookie_out_never && | ||
1528 | (sysctl_tcp_cookie_size > 0 || | ||
1529 | (tp->cookie_values != NULL && | ||
1530 | tp->cookie_values->cookie_desired > 0))) { | ||
1531 | u8 *c; | ||
1532 | u32 *mess = &tmp_ext.cookie_bakery[COOKIE_DIGEST_WORDS]; | ||
1533 | int l = tmp_opt.cookie_plus - TCPOLEN_COOKIE_BASE; | ||
1534 | |||
1535 | if (tcp_cookie_generator(&tmp_ext.cookie_bakery[0]) != 0) | ||
1536 | goto drop_and_release; | ||
1537 | |||
1538 | /* Secret recipe starts with IP addresses */ | ||
1539 | *mess++ ^= (__force u32)daddr; | ||
1540 | *mess++ ^= (__force u32)saddr; | ||
1541 | |||
1542 | /* plus variable length Initiator Cookie */ | ||
1543 | c = (u8 *)mess; | ||
1544 | while (l-- > 0) | ||
1545 | *c++ ^= *hash_location++; | ||
1546 | |||
1547 | want_cookie = false; /* not our kind of cookie */ | ||
1548 | tmp_ext.cookie_out_never = 0; /* false */ | ||
1549 | tmp_ext.cookie_plus = tmp_opt.cookie_plus; | ||
1550 | } else if (!tp->rx_opt.cookie_in_always) { | ||
1551 | /* redundant indications, but ensure initialization. */ | ||
1552 | tmp_ext.cookie_out_never = 1; /* true */ | ||
1553 | tmp_ext.cookie_plus = 0; | ||
1554 | } else { | ||
1555 | goto drop_and_release; | ||
1556 | } | ||
1557 | tmp_ext.cookie_in_always = tp->rx_opt.cookie_in_always; | ||
1558 | 1518 | ||
1559 | if (want_cookie && !tmp_opt.saw_tstamp) | 1519 | if (want_cookie && !tmp_opt.saw_tstamp) |
1560 | tcp_clear_options(&tmp_opt); | 1520 | tcp_clear_options(&tmp_opt); |
@@ -1636,7 +1596,6 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1636 | * of tcp_v4_send_synack()->tcp_select_initial_window(). | 1596 | * of tcp_v4_send_synack()->tcp_select_initial_window(). |
1637 | */ | 1597 | */ |
1638 | skb_synack = tcp_make_synack(sk, dst, req, | 1598 | skb_synack = tcp_make_synack(sk, dst, req, |
1639 | (struct request_values *)&tmp_ext, | ||
1640 | fastopen_cookie_present(&valid_foc) ? &valid_foc : NULL); | 1599 | fastopen_cookie_present(&valid_foc) ? &valid_foc : NULL); |
1641 | 1600 | ||
1642 | if (skb_synack) { | 1601 | if (skb_synack) { |
@@ -1660,8 +1619,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1660 | if (fastopen_cookie_present(&foc) && foc.len != 0) | 1619 | if (fastopen_cookie_present(&foc) && foc.len != 0) |
1661 | NET_INC_STATS_BH(sock_net(sk), | 1620 | NET_INC_STATS_BH(sock_net(sk), |
1662 | LINUX_MIB_TCPFASTOPENPASSIVEFAIL); | 1621 | LINUX_MIB_TCPFASTOPENPASSIVEFAIL); |
1663 | } else if (tcp_v4_conn_req_fastopen(sk, skb, skb_synack, req, | 1622 | } else if (tcp_v4_conn_req_fastopen(sk, skb, skb_synack, req)) |
1664 | (struct request_values *)&tmp_ext)) | ||
1665 | goto drop_and_free; | 1623 | goto drop_and_free; |
1666 | 1624 | ||
1667 | return 0; | 1625 | return 0; |
@@ -2241,12 +2199,6 @@ void tcp_v4_destroy_sock(struct sock *sk) | |||
2241 | if (inet_csk(sk)->icsk_bind_hash) | 2199 | if (inet_csk(sk)->icsk_bind_hash) |
2242 | inet_put_port(sk); | 2200 | inet_put_port(sk); |
2243 | 2201 | ||
2244 | /* TCP Cookie Transactions */ | ||
2245 | if (tp->cookie_values != NULL) { | ||
2246 | kref_put(&tp->cookie_values->kref, | ||
2247 | tcp_cookie_values_release); | ||
2248 | tp->cookie_values = NULL; | ||
2249 | } | ||
2250 | BUG_ON(tp->fastopen_rsk != NULL); | 2202 | BUG_ON(tp->fastopen_rsk != NULL); |
2251 | 2203 | ||
2252 | /* If socket is aborted during connect operation */ | 2204 | /* If socket is aborted during connect operation */ |
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 4bdb09fca401..8f0234f8bb95 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c | |||
@@ -93,13 +93,12 @@ tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb, | |||
93 | const struct tcphdr *th) | 93 | const struct tcphdr *th) |
94 | { | 94 | { |
95 | struct tcp_options_received tmp_opt; | 95 | struct tcp_options_received tmp_opt; |
96 | const u8 *hash_location; | ||
97 | struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw); | 96 | struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw); |
98 | bool paws_reject = false; | 97 | bool paws_reject = false; |
99 | 98 | ||
100 | tmp_opt.saw_tstamp = 0; | 99 | tmp_opt.saw_tstamp = 0; |
101 | if (th->doff > (sizeof(*th) >> 2) && tcptw->tw_ts_recent_stamp) { | 100 | if (th->doff > (sizeof(*th) >> 2) && tcptw->tw_ts_recent_stamp) { |
102 | tcp_parse_options(skb, &tmp_opt, &hash_location, 0, NULL); | 101 | tcp_parse_options(skb, &tmp_opt, 0, NULL); |
103 | 102 | ||
104 | if (tmp_opt.saw_tstamp) { | 103 | if (tmp_opt.saw_tstamp) { |
105 | tmp_opt.rcv_tsecr -= tcptw->tw_ts_offset; | 104 | tmp_opt.rcv_tsecr -= tcptw->tw_ts_offset; |
@@ -388,32 +387,6 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, | |||
388 | struct tcp_request_sock *treq = tcp_rsk(req); | 387 | struct tcp_request_sock *treq = tcp_rsk(req); |
389 | struct inet_connection_sock *newicsk = inet_csk(newsk); | 388 | struct inet_connection_sock *newicsk = inet_csk(newsk); |
390 | struct tcp_sock *newtp = tcp_sk(newsk); | 389 | struct tcp_sock *newtp = tcp_sk(newsk); |
391 | struct tcp_sock *oldtp = tcp_sk(sk); | ||
392 | struct tcp_cookie_values *oldcvp = oldtp->cookie_values; | ||
393 | |||
394 | /* TCP Cookie Transactions require space for the cookie pair, | ||
395 | * as it differs for each connection. There is no need to | ||
396 | * copy any s_data_payload stored at the original socket. | ||
397 | * Failure will prevent resuming the connection. | ||
398 | * | ||
399 | * Presumed copied, in order of appearance: | ||
400 | * cookie_in_always, cookie_out_never | ||
401 | */ | ||
402 | if (oldcvp != NULL) { | ||
403 | struct tcp_cookie_values *newcvp = | ||
404 | kzalloc(sizeof(*newtp->cookie_values), | ||
405 | GFP_ATOMIC); | ||
406 | |||
407 | if (newcvp != NULL) { | ||
408 | kref_init(&newcvp->kref); | ||
409 | newcvp->cookie_desired = | ||
410 | oldcvp->cookie_desired; | ||
411 | newtp->cookie_values = newcvp; | ||
412 | } else { | ||
413 | /* Not Yet Implemented */ | ||
414 | newtp->cookie_values = NULL; | ||
415 | } | ||
416 | } | ||
417 | 390 | ||
418 | /* Now setup tcp_sock */ | 391 | /* Now setup tcp_sock */ |
419 | newtp->pred_flags = 0; | 392 | newtp->pred_flags = 0; |
@@ -422,8 +395,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, | |||
422 | newtp->rcv_nxt = treq->rcv_isn + 1; | 395 | newtp->rcv_nxt = treq->rcv_isn + 1; |
423 | 396 | ||
424 | newtp->snd_sml = newtp->snd_una = | 397 | newtp->snd_sml = newtp->snd_una = |
425 | newtp->snd_nxt = newtp->snd_up = | 398 | newtp->snd_nxt = newtp->snd_up = treq->snt_isn + 1; |
426 | treq->snt_isn + 1 + tcp_s_data_size(oldtp); | ||
427 | 399 | ||
428 | tcp_prequeue_init(newtp); | 400 | tcp_prequeue_init(newtp); |
429 | INIT_LIST_HEAD(&newtp->tsq_node); | 401 | INIT_LIST_HEAD(&newtp->tsq_node); |
@@ -460,8 +432,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, | |||
460 | tcp_set_ca_state(newsk, TCP_CA_Open); | 432 | tcp_set_ca_state(newsk, TCP_CA_Open); |
461 | tcp_init_xmit_timers(newsk); | 433 | tcp_init_xmit_timers(newsk); |
462 | skb_queue_head_init(&newtp->out_of_order_queue); | 434 | skb_queue_head_init(&newtp->out_of_order_queue); |
463 | newtp->write_seq = newtp->pushed_seq = | 435 | newtp->write_seq = newtp->pushed_seq = treq->snt_isn + 1; |
464 | treq->snt_isn + 1 + tcp_s_data_size(oldtp); | ||
465 | 436 | ||
466 | newtp->rx_opt.saw_tstamp = 0; | 437 | newtp->rx_opt.saw_tstamp = 0; |
467 | 438 | ||
@@ -538,7 +509,6 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, | |||
538 | bool fastopen) | 509 | bool fastopen) |
539 | { | 510 | { |
540 | struct tcp_options_received tmp_opt; | 511 | struct tcp_options_received tmp_opt; |
541 | const u8 *hash_location; | ||
542 | struct sock *child; | 512 | struct sock *child; |
543 | const struct tcphdr *th = tcp_hdr(skb); | 513 | const struct tcphdr *th = tcp_hdr(skb); |
544 | __be32 flg = tcp_flag_word(th) & (TCP_FLAG_RST|TCP_FLAG_SYN|TCP_FLAG_ACK); | 514 | __be32 flg = tcp_flag_word(th) & (TCP_FLAG_RST|TCP_FLAG_SYN|TCP_FLAG_ACK); |
@@ -548,7 +518,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, | |||
548 | 518 | ||
549 | tmp_opt.saw_tstamp = 0; | 519 | tmp_opt.saw_tstamp = 0; |
550 | if (th->doff > (sizeof(struct tcphdr)>>2)) { | 520 | if (th->doff > (sizeof(struct tcphdr)>>2)) { |
551 | tcp_parse_options(skb, &tmp_opt, &hash_location, 0, NULL); | 521 | tcp_parse_options(skb, &tmp_opt, 0, NULL); |
552 | 522 | ||
553 | if (tmp_opt.saw_tstamp) { | 523 | if (tmp_opt.saw_tstamp) { |
554 | tmp_opt.ts_recent = req->ts_recent; | 524 | tmp_opt.ts_recent = req->ts_recent; |
@@ -648,7 +618,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, | |||
648 | */ | 618 | */ |
649 | if ((flg & TCP_FLAG_ACK) && !fastopen && | 619 | if ((flg & TCP_FLAG_ACK) && !fastopen && |
650 | (TCP_SKB_CB(skb)->ack_seq != | 620 | (TCP_SKB_CB(skb)->ack_seq != |
651 | tcp_rsk(req)->snt_isn + 1 + tcp_s_data_size(tcp_sk(sk)))) | 621 | tcp_rsk(req)->snt_isn + 1)) |
652 | return sk; | 622 | return sk; |
653 | 623 | ||
654 | /* Also, it would be not so bad idea to check rcv_tsecr, which | 624 | /* Also, it would be not so bad idea to check rcv_tsecr, which |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 8e7742f0b5d2..ac5871ebe086 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -65,9 +65,6 @@ int sysctl_tcp_base_mss __read_mostly = TCP_BASE_MSS; | |||
65 | /* By default, RFC2861 behavior. */ | 65 | /* By default, RFC2861 behavior. */ |
66 | int sysctl_tcp_slow_start_after_idle __read_mostly = 1; | 66 | int sysctl_tcp_slow_start_after_idle __read_mostly = 1; |
67 | 67 | ||
68 | int sysctl_tcp_cookie_size __read_mostly = 0; /* TCP_COOKIE_MAX */ | ||
69 | EXPORT_SYMBOL_GPL(sysctl_tcp_cookie_size); | ||
70 | |||
71 | static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, | 68 | static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, |
72 | int push_one, gfp_t gfp); | 69 | int push_one, gfp_t gfp); |
73 | 70 | ||
@@ -386,7 +383,6 @@ static inline bool tcp_urg_mode(const struct tcp_sock *tp) | |||
386 | #define OPTION_TS (1 << 1) | 383 | #define OPTION_TS (1 << 1) |
387 | #define OPTION_MD5 (1 << 2) | 384 | #define OPTION_MD5 (1 << 2) |
388 | #define OPTION_WSCALE (1 << 3) | 385 | #define OPTION_WSCALE (1 << 3) |
389 | #define OPTION_COOKIE_EXTENSION (1 << 4) | ||
390 | #define OPTION_FAST_OPEN_COOKIE (1 << 8) | 386 | #define OPTION_FAST_OPEN_COOKIE (1 << 8) |
391 | 387 | ||
392 | struct tcp_out_options { | 388 | struct tcp_out_options { |
@@ -400,36 +396,6 @@ struct tcp_out_options { | |||
400 | struct tcp_fastopen_cookie *fastopen_cookie; /* Fast open cookie */ | 396 | struct tcp_fastopen_cookie *fastopen_cookie; /* Fast open cookie */ |
401 | }; | 397 | }; |
402 | 398 | ||
403 | /* The sysctl int routines are generic, so check consistency here. | ||
404 | */ | ||
405 | static u8 tcp_cookie_size_check(u8 desired) | ||
406 | { | ||
407 | int cookie_size; | ||
408 | |||
409 | if (desired > 0) | ||
410 | /* previously specified */ | ||
411 | return desired; | ||
412 | |||
413 | cookie_size = ACCESS_ONCE(sysctl_tcp_cookie_size); | ||
414 | if (cookie_size <= 0) | ||
415 | /* no default specified */ | ||
416 | return 0; | ||
417 | |||
418 | if (cookie_size <= TCP_COOKIE_MIN) | ||
419 | /* value too small, specify minimum */ | ||
420 | return TCP_COOKIE_MIN; | ||
421 | |||
422 | if (cookie_size >= TCP_COOKIE_MAX) | ||
423 | /* value too large, specify maximum */ | ||
424 | return TCP_COOKIE_MAX; | ||
425 | |||
426 | if (cookie_size & 1) | ||
427 | /* 8-bit multiple, illegal, fix it */ | ||
428 | cookie_size++; | ||
429 | |||
430 | return (u8)cookie_size; | ||
431 | } | ||
432 | |||
433 | /* Write previously computed TCP options to the packet. | 399 | /* Write previously computed TCP options to the packet. |
434 | * | 400 | * |
435 | * Beware: Something in the Internet is very sensitive to the ordering of | 401 | * Beware: Something in the Internet is very sensitive to the ordering of |
@@ -448,27 +414,9 @@ static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp, | |||
448 | { | 414 | { |
449 | u16 options = opts->options; /* mungable copy */ | 415 | u16 options = opts->options; /* mungable copy */ |
450 | 416 | ||
451 | /* Having both authentication and cookies for security is redundant, | ||
452 | * and there's certainly not enough room. Instead, the cookie-less | ||
453 | * extension variant is proposed. | ||
454 | * | ||
455 | * Consider the pessimal case with authentication. The options | ||
456 | * could look like: | ||
457 | * COOKIE|MD5(20) + MSS(4) + SACK|TS(12) + WSCALE(4) == 40 | ||
458 | */ | ||
459 | if (unlikely(OPTION_MD5 & options)) { | 417 | if (unlikely(OPTION_MD5 & options)) { |
460 | if (unlikely(OPTION_COOKIE_EXTENSION & options)) { | 418 | *ptr++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | |
461 | *ptr++ = htonl((TCPOPT_COOKIE << 24) | | 419 | (TCPOPT_MD5SIG << 8) | TCPOLEN_MD5SIG); |
462 | (TCPOLEN_COOKIE_BASE << 16) | | ||
463 | (TCPOPT_MD5SIG << 8) | | ||
464 | TCPOLEN_MD5SIG); | ||
465 | } else { | ||
466 | *ptr++ = htonl((TCPOPT_NOP << 24) | | ||
467 | (TCPOPT_NOP << 16) | | ||
468 | (TCPOPT_MD5SIG << 8) | | ||
469 | TCPOLEN_MD5SIG); | ||
470 | } | ||
471 | options &= ~OPTION_COOKIE_EXTENSION; | ||
472 | /* overload cookie hash location */ | 420 | /* overload cookie hash location */ |
473 | opts->hash_location = (__u8 *)ptr; | 421 | opts->hash_location = (__u8 *)ptr; |
474 | ptr += 4; | 422 | ptr += 4; |
@@ -497,44 +445,6 @@ static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp, | |||
497 | *ptr++ = htonl(opts->tsecr); | 445 | *ptr++ = htonl(opts->tsecr); |
498 | } | 446 | } |
499 | 447 | ||
500 | /* Specification requires after timestamp, so do it now. | ||
501 | * | ||
502 | * Consider the pessimal case without authentication. The options | ||
503 | * could look like: | ||
504 | * MSS(4) + SACK|TS(12) + COOKIE(20) + WSCALE(4) == 40 | ||
505 | */ | ||
506 | if (unlikely(OPTION_COOKIE_EXTENSION & options)) { | ||
507 | __u8 *cookie_copy = opts->hash_location; | ||
508 | u8 cookie_size = opts->hash_size; | ||
509 | |||
510 | /* 8-bit multiple handled in tcp_cookie_size_check() above, | ||
511 | * and elsewhere. | ||
512 | */ | ||
513 | if (0x2 & cookie_size) { | ||
514 | __u8 *p = (__u8 *)ptr; | ||
515 | |||
516 | /* 16-bit multiple */ | ||
517 | *p++ = TCPOPT_COOKIE; | ||
518 | *p++ = TCPOLEN_COOKIE_BASE + cookie_size; | ||
519 | *p++ = *cookie_copy++; | ||
520 | *p++ = *cookie_copy++; | ||
521 | ptr++; | ||
522 | cookie_size -= 2; | ||
523 | } else { | ||
524 | /* 32-bit multiple */ | ||
525 | *ptr++ = htonl(((TCPOPT_NOP << 24) | | ||
526 | (TCPOPT_NOP << 16) | | ||
527 | (TCPOPT_COOKIE << 8) | | ||
528 | TCPOLEN_COOKIE_BASE) + | ||
529 | cookie_size); | ||
530 | } | ||
531 | |||
532 | if (cookie_size > 0) { | ||
533 | memcpy(ptr, cookie_copy, cookie_size); | ||
534 | ptr += (cookie_size / 4); | ||
535 | } | ||
536 | } | ||
537 | |||
538 | if (unlikely(OPTION_SACK_ADVERTISE & options)) { | 448 | if (unlikely(OPTION_SACK_ADVERTISE & options)) { |
539 | *ptr++ = htonl((TCPOPT_NOP << 24) | | 449 | *ptr++ = htonl((TCPOPT_NOP << 24) | |
540 | (TCPOPT_NOP << 16) | | 450 | (TCPOPT_NOP << 16) | |
@@ -593,11 +503,7 @@ static unsigned int tcp_syn_options(struct sock *sk, struct sk_buff *skb, | |||
593 | struct tcp_md5sig_key **md5) | 503 | struct tcp_md5sig_key **md5) |
594 | { | 504 | { |
595 | struct tcp_sock *tp = tcp_sk(sk); | 505 | struct tcp_sock *tp = tcp_sk(sk); |
596 | struct tcp_cookie_values *cvp = tp->cookie_values; | ||
597 | unsigned int remaining = MAX_TCP_OPTION_SPACE; | 506 | unsigned int remaining = MAX_TCP_OPTION_SPACE; |
598 | u8 cookie_size = (!tp->rx_opt.cookie_out_never && cvp != NULL) ? | ||
599 | tcp_cookie_size_check(cvp->cookie_desired) : | ||
600 | 0; | ||
601 | struct tcp_fastopen_request *fastopen = tp->fastopen_req; | 507 | struct tcp_fastopen_request *fastopen = tp->fastopen_req; |
602 | 508 | ||
603 | #ifdef CONFIG_TCP_MD5SIG | 509 | #ifdef CONFIG_TCP_MD5SIG |
@@ -649,52 +555,7 @@ static unsigned int tcp_syn_options(struct sock *sk, struct sk_buff *skb, | |||
649 | tp->syn_fastopen = 1; | 555 | tp->syn_fastopen = 1; |
650 | } | 556 | } |
651 | } | 557 | } |
652 | /* Note that timestamps are required by the specification. | ||
653 | * | ||
654 | * Odd numbers of bytes are prohibited by the specification, ensuring | ||
655 | * that the cookie is 16-bit aligned, and the resulting cookie pair is | ||
656 | * 32-bit aligned. | ||
657 | */ | ||
658 | if (*md5 == NULL && | ||
659 | (OPTION_TS & opts->options) && | ||
660 | cookie_size > 0) { | ||
661 | int need = TCPOLEN_COOKIE_BASE + cookie_size; | ||
662 | |||
663 | if (0x2 & need) { | ||
664 | /* 32-bit multiple */ | ||
665 | need += 2; /* NOPs */ | ||
666 | |||
667 | if (need > remaining) { | ||
668 | /* try shrinking cookie to fit */ | ||
669 | cookie_size -= 2; | ||
670 | need -= 4; | ||
671 | } | ||
672 | } | ||
673 | while (need > remaining && TCP_COOKIE_MIN <= cookie_size) { | ||
674 | cookie_size -= 4; | ||
675 | need -= 4; | ||
676 | } | ||
677 | if (TCP_COOKIE_MIN <= cookie_size) { | ||
678 | opts->options |= OPTION_COOKIE_EXTENSION; | ||
679 | opts->hash_location = (__u8 *)&cvp->cookie_pair[0]; | ||
680 | opts->hash_size = cookie_size; | ||
681 | |||
682 | /* Remember for future incarnations. */ | ||
683 | cvp->cookie_desired = cookie_size; | ||
684 | |||
685 | if (cvp->cookie_desired != cvp->cookie_pair_size) { | ||
686 | /* Currently use random bytes as a nonce, | ||
687 | * assuming these are completely unpredictable | ||
688 | * by hostile users of the same system. | ||
689 | */ | ||
690 | get_random_bytes(&cvp->cookie_pair[0], | ||
691 | cookie_size); | ||
692 | cvp->cookie_pair_size = cookie_size; | ||
693 | } | ||
694 | 558 | ||
695 | remaining -= need; | ||
696 | } | ||
697 | } | ||
698 | return MAX_TCP_OPTION_SPACE - remaining; | 559 | return MAX_TCP_OPTION_SPACE - remaining; |
699 | } | 560 | } |
700 | 561 | ||
@@ -704,14 +565,10 @@ static unsigned int tcp_synack_options(struct sock *sk, | |||
704 | unsigned int mss, struct sk_buff *skb, | 565 | unsigned int mss, struct sk_buff *skb, |
705 | struct tcp_out_options *opts, | 566 | struct tcp_out_options *opts, |
706 | struct tcp_md5sig_key **md5, | 567 | struct tcp_md5sig_key **md5, |
707 | struct tcp_extend_values *xvp, | ||
708 | struct tcp_fastopen_cookie *foc) | 568 | struct tcp_fastopen_cookie *foc) |
709 | { | 569 | { |
710 | struct inet_request_sock *ireq = inet_rsk(req); | 570 | struct inet_request_sock *ireq = inet_rsk(req); |
711 | unsigned int remaining = MAX_TCP_OPTION_SPACE; | 571 | unsigned int remaining = MAX_TCP_OPTION_SPACE; |
712 | u8 cookie_plus = (xvp != NULL && !xvp->cookie_out_never) ? | ||
713 | xvp->cookie_plus : | ||
714 | 0; | ||
715 | 572 | ||
716 | #ifdef CONFIG_TCP_MD5SIG | 573 | #ifdef CONFIG_TCP_MD5SIG |
717 | *md5 = tcp_rsk(req)->af_specific->md5_lookup(sk, req); | 574 | *md5 = tcp_rsk(req)->af_specific->md5_lookup(sk, req); |
@@ -759,28 +616,7 @@ static unsigned int tcp_synack_options(struct sock *sk, | |||
759 | remaining -= need; | 616 | remaining -= need; |
760 | } | 617 | } |
761 | } | 618 | } |
762 | /* Similar rationale to tcp_syn_options() applies here, too. | 619 | |
763 | * If the <SYN> options fit, the same options should fit now! | ||
764 | */ | ||
765 | if (*md5 == NULL && | ||
766 | ireq->tstamp_ok && | ||
767 | cookie_plus > TCPOLEN_COOKIE_BASE) { | ||
768 | int need = cookie_plus; /* has TCPOLEN_COOKIE_BASE */ | ||
769 | |||
770 | if (0x2 & need) { | ||
771 | /* 32-bit multiple */ | ||
772 | need += 2; /* NOPs */ | ||
773 | } | ||
774 | if (need <= remaining) { | ||
775 | opts->options |= OPTION_COOKIE_EXTENSION; | ||
776 | opts->hash_size = cookie_plus - TCPOLEN_COOKIE_BASE; | ||
777 | remaining -= need; | ||
778 | } else { | ||
779 | /* There's no error return, so flag it. */ | ||
780 | xvp->cookie_out_never = 1; /* true */ | ||
781 | opts->hash_size = 0; | ||
782 | } | ||
783 | } | ||
784 | return MAX_TCP_OPTION_SPACE - remaining; | 620 | return MAX_TCP_OPTION_SPACE - remaining; |
785 | } | 621 | } |
786 | 622 | ||
@@ -2802,32 +2638,24 @@ int tcp_send_synack(struct sock *sk) | |||
2802 | * sk: listener socket | 2638 | * sk: listener socket |
2803 | * dst: dst entry attached to the SYNACK | 2639 | * dst: dst entry attached to the SYNACK |
2804 | * req: request_sock pointer | 2640 | * req: request_sock pointer |
2805 | * rvp: request_values pointer | ||
2806 | * | 2641 | * |
2807 | * Allocate one skb and build a SYNACK packet. | 2642 | * Allocate one skb and build a SYNACK packet. |
2808 | * @dst is consumed : Caller should not use it again. | 2643 | * @dst is consumed : Caller should not use it again. |
2809 | */ | 2644 | */ |
2810 | struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, | 2645 | struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, |
2811 | struct request_sock *req, | 2646 | struct request_sock *req, |
2812 | struct request_values *rvp, | ||
2813 | struct tcp_fastopen_cookie *foc) | 2647 | struct tcp_fastopen_cookie *foc) |
2814 | { | 2648 | { |
2815 | struct tcp_out_options opts; | 2649 | struct tcp_out_options opts; |
2816 | struct tcp_extend_values *xvp = tcp_xv(rvp); | ||
2817 | struct inet_request_sock *ireq = inet_rsk(req); | 2650 | struct inet_request_sock *ireq = inet_rsk(req); |
2818 | struct tcp_sock *tp = tcp_sk(sk); | 2651 | struct tcp_sock *tp = tcp_sk(sk); |
2819 | const struct tcp_cookie_values *cvp = tp->cookie_values; | ||
2820 | struct tcphdr *th; | 2652 | struct tcphdr *th; |
2821 | struct sk_buff *skb; | 2653 | struct sk_buff *skb; |
2822 | struct tcp_md5sig_key *md5; | 2654 | struct tcp_md5sig_key *md5; |
2823 | int tcp_header_size; | 2655 | int tcp_header_size; |
2824 | int mss; | 2656 | int mss; |
2825 | int s_data_desired = 0; | ||
2826 | 2657 | ||
2827 | if (cvp != NULL && cvp->s_data_constant && cvp->s_data_desired) | 2658 | skb = alloc_skb(MAX_TCP_HEADER + 15, sk_gfp_atomic(sk, GFP_ATOMIC)); |
2828 | s_data_desired = cvp->s_data_desired; | ||
2829 | skb = alloc_skb(MAX_TCP_HEADER + 15 + s_data_desired, | ||
2830 | sk_gfp_atomic(sk, GFP_ATOMIC)); | ||
2831 | if (unlikely(!skb)) { | 2659 | if (unlikely(!skb)) { |
2832 | dst_release(dst); | 2660 | dst_release(dst); |
2833 | return NULL; | 2661 | return NULL; |
@@ -2869,9 +2697,8 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, | |||
2869 | else | 2697 | else |
2870 | #endif | 2698 | #endif |
2871 | TCP_SKB_CB(skb)->when = tcp_time_stamp; | 2699 | TCP_SKB_CB(skb)->when = tcp_time_stamp; |
2872 | tcp_header_size = tcp_synack_options(sk, req, mss, | 2700 | tcp_header_size = tcp_synack_options(sk, req, mss, skb, &opts, &md5, |
2873 | skb, &opts, &md5, xvp, foc) | 2701 | foc) + sizeof(*th); |
2874 | + sizeof(*th); | ||
2875 | 2702 | ||
2876 | skb_push(skb, tcp_header_size); | 2703 | skb_push(skb, tcp_header_size); |
2877 | skb_reset_transport_header(skb); | 2704 | skb_reset_transport_header(skb); |
@@ -2889,40 +2716,6 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, | |||
2889 | tcp_init_nondata_skb(skb, tcp_rsk(req)->snt_isn, | 2716 | tcp_init_nondata_skb(skb, tcp_rsk(req)->snt_isn, |
2890 | TCPHDR_SYN | TCPHDR_ACK); | 2717 | TCPHDR_SYN | TCPHDR_ACK); |
2891 | 2718 | ||
2892 | if (OPTION_COOKIE_EXTENSION & opts.options) { | ||
2893 | if (s_data_desired) { | ||
2894 | u8 *buf = skb_put(skb, s_data_desired); | ||
2895 | |||
2896 | /* copy data directly from the listening socket. */ | ||
2897 | memcpy(buf, cvp->s_data_payload, s_data_desired); | ||
2898 | TCP_SKB_CB(skb)->end_seq += s_data_desired; | ||
2899 | } | ||
2900 | |||
2901 | if (opts.hash_size > 0) { | ||
2902 | __u32 workspace[SHA_WORKSPACE_WORDS]; | ||
2903 | u32 *mess = &xvp->cookie_bakery[COOKIE_DIGEST_WORDS]; | ||
2904 | u32 *tail = &mess[COOKIE_MESSAGE_WORDS-1]; | ||
2905 | |||
2906 | /* Secret recipe depends on the Timestamp, (future) | ||
2907 | * Sequence and Acknowledgment Numbers, Initiator | ||
2908 | * Cookie, and others handled by IP variant caller. | ||
2909 | */ | ||
2910 | *tail-- ^= opts.tsval; | ||
2911 | *tail-- ^= tcp_rsk(req)->rcv_isn + 1; | ||
2912 | *tail-- ^= TCP_SKB_CB(skb)->seq + 1; | ||
2913 | |||
2914 | /* recommended */ | ||
2915 | *tail-- ^= (((__force u32)th->dest << 16) | (__force u32)th->source); | ||
2916 | *tail-- ^= (u32)(unsigned long)cvp; /* per sockopt */ | ||
2917 | |||
2918 | sha_transform((__u32 *)&xvp->cookie_bakery[0], | ||
2919 | (char *)mess, | ||
2920 | &workspace[0]); | ||
2921 | opts.hash_location = | ||
2922 | (__u8 *)&xvp->cookie_bakery[0]; | ||
2923 | } | ||
2924 | } | ||
2925 | |||
2926 | th->seq = htonl(TCP_SKB_CB(skb)->seq); | 2719 | th->seq = htonl(TCP_SKB_CB(skb)->seq); |
2927 | /* XXX data is queued and acked as is. No buffer/window check */ | 2720 | /* XXX data is queued and acked as is. No buffer/window check */ |
2928 | th->ack_seq = htonl(tcp_rsk(req)->rcv_nxt); | 2721 | th->ack_seq = htonl(tcp_rsk(req)->rcv_nxt); |
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index 8a0848b60b35..d5dda20bd717 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c | |||
@@ -149,7 +149,6 @@ static inline int cookie_check(const struct sk_buff *skb, __u32 cookie) | |||
149 | struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | 149 | struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) |
150 | { | 150 | { |
151 | struct tcp_options_received tcp_opt; | 151 | struct tcp_options_received tcp_opt; |
152 | const u8 *hash_location; | ||
153 | struct inet_request_sock *ireq; | 152 | struct inet_request_sock *ireq; |
154 | struct inet6_request_sock *ireq6; | 153 | struct inet6_request_sock *ireq6; |
155 | struct tcp_request_sock *treq; | 154 | struct tcp_request_sock *treq; |
@@ -177,7 +176,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
177 | 176 | ||
178 | /* check for timestamp cookie support */ | 177 | /* check for timestamp cookie support */ |
179 | memset(&tcp_opt, 0, sizeof(tcp_opt)); | 178 | memset(&tcp_opt, 0, sizeof(tcp_opt)); |
180 | tcp_parse_options(skb, &tcp_opt, &hash_location, 0, NULL); | 179 | tcp_parse_options(skb, &tcp_opt, 0, NULL); |
181 | 180 | ||
182 | if (!cookie_check_timestamp(&tcp_opt, sock_net(sk), &ecn_ok)) | 181 | if (!cookie_check_timestamp(&tcp_opt, sock_net(sk), &ecn_ok)) |
183 | goto out; | 182 | goto out; |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 9b6460055df5..0a97add2ab74 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -454,7 +454,6 @@ out: | |||
454 | static int tcp_v6_send_synack(struct sock *sk, struct dst_entry *dst, | 454 | static int tcp_v6_send_synack(struct sock *sk, struct dst_entry *dst, |
455 | struct flowi6 *fl6, | 455 | struct flowi6 *fl6, |
456 | struct request_sock *req, | 456 | struct request_sock *req, |
457 | struct request_values *rvp, | ||
458 | u16 queue_mapping) | 457 | u16 queue_mapping) |
459 | { | 458 | { |
460 | struct inet6_request_sock *treq = inet6_rsk(req); | 459 | struct inet6_request_sock *treq = inet6_rsk(req); |
@@ -466,7 +465,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct dst_entry *dst, | |||
466 | if (!dst && (dst = inet6_csk_route_req(sk, fl6, req)) == NULL) | 465 | if (!dst && (dst = inet6_csk_route_req(sk, fl6, req)) == NULL) |
467 | goto done; | 466 | goto done; |
468 | 467 | ||
469 | skb = tcp_make_synack(sk, dst, req, rvp, NULL); | 468 | skb = tcp_make_synack(sk, dst, req, NULL); |
470 | 469 | ||
471 | if (skb) { | 470 | if (skb) { |
472 | __tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr); | 471 | __tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr); |
@@ -481,13 +480,12 @@ done: | |||
481 | return err; | 480 | return err; |
482 | } | 481 | } |
483 | 482 | ||
484 | static int tcp_v6_rtx_synack(struct sock *sk, struct request_sock *req, | 483 | static int tcp_v6_rtx_synack(struct sock *sk, struct request_sock *req) |
485 | struct request_values *rvp) | ||
486 | { | 484 | { |
487 | struct flowi6 fl6; | 485 | struct flowi6 fl6; |
488 | int res; | 486 | int res; |
489 | 487 | ||
490 | res = tcp_v6_send_synack(sk, NULL, &fl6, req, rvp, 0); | 488 | res = tcp_v6_send_synack(sk, NULL, &fl6, req, 0); |
491 | if (!res) | 489 | if (!res) |
492 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS); | 490 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS); |
493 | return res; | 491 | return res; |
@@ -940,9 +938,7 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) | |||
940 | */ | 938 | */ |
941 | static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | 939 | static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) |
942 | { | 940 | { |
943 | struct tcp_extend_values tmp_ext; | ||
944 | struct tcp_options_received tmp_opt; | 941 | struct tcp_options_received tmp_opt; |
945 | const u8 *hash_location; | ||
946 | struct request_sock *req; | 942 | struct request_sock *req; |
947 | struct inet6_request_sock *treq; | 943 | struct inet6_request_sock *treq; |
948 | struct ipv6_pinfo *np = inet6_sk(sk); | 944 | struct ipv6_pinfo *np = inet6_sk(sk); |
@@ -980,50 +976,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
980 | tcp_clear_options(&tmp_opt); | 976 | tcp_clear_options(&tmp_opt); |
981 | tmp_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr); | 977 | tmp_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr); |
982 | tmp_opt.user_mss = tp->rx_opt.user_mss; | 978 | tmp_opt.user_mss = tp->rx_opt.user_mss; |
983 | tcp_parse_options(skb, &tmp_opt, &hash_location, 0, NULL); | 979 | tcp_parse_options(skb, &tmp_opt, 0, NULL); |
984 | |||
985 | if (tmp_opt.cookie_plus > 0 && | ||
986 | tmp_opt.saw_tstamp && | ||
987 | !tp->rx_opt.cookie_out_never && | ||
988 | (sysctl_tcp_cookie_size > 0 || | ||
989 | (tp->cookie_values != NULL && | ||
990 | tp->cookie_values->cookie_desired > 0))) { | ||
991 | u8 *c; | ||
992 | u32 *d; | ||
993 | u32 *mess = &tmp_ext.cookie_bakery[COOKIE_DIGEST_WORDS]; | ||
994 | int l = tmp_opt.cookie_plus - TCPOLEN_COOKIE_BASE; | ||
995 | |||
996 | if (tcp_cookie_generator(&tmp_ext.cookie_bakery[0]) != 0) | ||
997 | goto drop_and_free; | ||
998 | |||
999 | /* Secret recipe starts with IP addresses */ | ||
1000 | d = (__force u32 *)&ipv6_hdr(skb)->daddr.s6_addr32[0]; | ||
1001 | *mess++ ^= *d++; | ||
1002 | *mess++ ^= *d++; | ||
1003 | *mess++ ^= *d++; | ||
1004 | *mess++ ^= *d++; | ||
1005 | d = (__force u32 *)&ipv6_hdr(skb)->saddr.s6_addr32[0]; | ||
1006 | *mess++ ^= *d++; | ||
1007 | *mess++ ^= *d++; | ||
1008 | *mess++ ^= *d++; | ||
1009 | *mess++ ^= *d++; | ||
1010 | |||
1011 | /* plus variable length Initiator Cookie */ | ||
1012 | c = (u8 *)mess; | ||
1013 | while (l-- > 0) | ||
1014 | *c++ ^= *hash_location++; | ||
1015 | |||
1016 | want_cookie = false; /* not our kind of cookie */ | ||
1017 | tmp_ext.cookie_out_never = 0; /* false */ | ||
1018 | tmp_ext.cookie_plus = tmp_opt.cookie_plus; | ||
1019 | } else if (!tp->rx_opt.cookie_in_always) { | ||
1020 | /* redundant indications, but ensure initialization. */ | ||
1021 | tmp_ext.cookie_out_never = 1; /* true */ | ||
1022 | tmp_ext.cookie_plus = 0; | ||
1023 | } else { | ||
1024 | goto drop_and_free; | ||
1025 | } | ||
1026 | tmp_ext.cookie_in_always = tp->rx_opt.cookie_in_always; | ||
1027 | 980 | ||
1028 | if (want_cookie && !tmp_opt.saw_tstamp) | 981 | if (want_cookie && !tmp_opt.saw_tstamp) |
1029 | tcp_clear_options(&tmp_opt); | 982 | tcp_clear_options(&tmp_opt); |
@@ -1101,7 +1054,6 @@ have_isn: | |||
1101 | goto drop_and_release; | 1054 | goto drop_and_release; |
1102 | 1055 | ||
1103 | if (tcp_v6_send_synack(sk, dst, &fl6, req, | 1056 | if (tcp_v6_send_synack(sk, dst, &fl6, req, |
1104 | (struct request_values *)&tmp_ext, | ||
1105 | skb_get_queue_mapping(skb)) || | 1057 | skb_get_queue_mapping(skb)) || |
1106 | want_cookie) | 1058 | want_cookie) |
1107 | goto drop_and_free; | 1059 | goto drop_and_free; |