summaryrefslogtreecommitdiff
path: root/kernels/linux-libre-lts-knock/tcp_stealth_4.9_1.diff
diff options
context:
space:
mode:
Diffstat (limited to 'kernels/linux-libre-lts-knock/tcp_stealth_4.9_1.diff')
-rw-r--r--kernels/linux-libre-lts-knock/tcp_stealth_4.9_1.diff642
1 files changed, 0 insertions, 642 deletions
diff --git a/kernels/linux-libre-lts-knock/tcp_stealth_4.9_1.diff b/kernels/linux-libre-lts-knock/tcp_stealth_4.9_1.diff
deleted file mode 100644
index 40ca22975..000000000
--- a/kernels/linux-libre-lts-knock/tcp_stealth_4.9_1.diff
+++ /dev/null
@@ -1,642 +0,0 @@
-diff --git a/include/linux/tcp.h b/include/linux/tcp.h
-index a17ae7b..e48e86f 100644
---- a/include/linux/tcp.h
-+++ b/include/linux/tcp.h
-@@ -19,6 +19,7 @@
-
-
- #include <linux/skbuff.h>
-+#include <linux/cryptohash.h>
- #include <linux/win_minmax.h>
- #include <net/sock.h>
- #include <net/inet_connection_sock.h>
-@@ -353,6 +354,21 @@ struct tcp_sock {
- struct tcp_md5sig_info __rcu *md5sig_info;
- #endif
-
-+#ifdef CONFIG_TCP_STEALTH
-+/* Stealth TCP socket configuration */
-+ struct {
-+ #define TCP_STEALTH_MODE_AUTH BIT(0)
-+ #define TCP_STEALTH_MODE_INTEGRITY BIT(1)
-+ #define TCP_STEALTH_MODE_INTEGRITY_LEN BIT(2)
-+ u8 mode;
-+ u8 secret[MD5_MESSAGE_BYTES];
-+ u16 integrity_hash;
-+ size_t integrity_len;
-+ struct skb_mstamp mstamp;
-+ bool saw_tsval;
-+ } stealth;
-+#endif
-+
- /* TCP fastopen related information */
- struct tcp_fastopen_request *fastopen_req;
- /* fastopen_rsk points to request_sock that resulted in this big
-diff --git a/include/net/secure_seq.h b/include/net/secure_seq.h
-index 3f36d45..ec392a1 100644
---- a/include/net/secure_seq.h
-+++ b/include/net/secure_seq.h
-@@ -14,5 +14,10 @@ u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr,
- __be16 sport, __be16 dport);
- u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr,
- __be16 sport, __be16 dport);
-+#ifdef CONFIG_TCP_STEALTH
-+u32 tcp_stealth_do_auth(struct sock *sk, struct sk_buff *skb);
-+u32 tcp_stealth_sequence_number(struct sock *sk, __be32 *daddr,
-+ u32 daddr_size, __be16 dport);
-+#endif
-
- #endif /* _NET_SECURE_SEQ */
-diff --git a/include/net/tcp.h b/include/net/tcp.h
-index 123979f..f7a0d7c 100644
---- a/include/net/tcp.h
-+++ b/include/net/tcp.h
-@@ -429,6 +429,12 @@ void tcp_parse_options(const struct sk_buff *skb,
- struct tcp_options_received *opt_rx,
- int estab, struct tcp_fastopen_cookie *foc);
- const u8 *tcp_parse_md5sig_option(const struct tcphdr *th);
-+#ifdef CONFIG_TCP_STEALTH
-+const bool tcp_parse_tsval_option(u32 *tsval, const struct tcphdr *th);
-+int tcp_stealth_integrity(u16 *hash, u8 *secret, u8 *payload, int len);
-+#define be32_isn_to_be16_av(x) (((__be16 *)&x)[0])
-+#define be32_isn_to_be16_ih(x) (((__be16 *)&x)[1])
-+#endif
-
- /*
- * TCP v4 functions exported for the inet6 API
-diff --git a/include/uapi/linux/tcp.h b/include/uapi/linux/tcp.h
-index 73ac0db..d2a35e9 100644
---- a/include/uapi/linux/tcp.h
-+++ b/include/uapi/linux/tcp.h
-@@ -116,6 +116,9 @@ enum {
- #define TCP_SAVE_SYN 27 /* Record SYN headers for new connections */
- #define TCP_SAVED_SYN 28 /* Get SYN headers recorded for connection */
- #define TCP_REPAIR_WINDOW 29 /* Get/set window parameters */
-+#define TCP_STEALTH 30
-+#define TCP_STEALTH_INTEGRITY 31
-+#define TCP_STEALTH_INTEGRITY_LEN 32
-
- struct tcp_repair_opt {
- __u32 opt_code;
-diff --git a/net/core/secure_seq.c b/net/core/secure_seq.c
-index fd3ce46..2d49cee 100644
---- a/net/core/secure_seq.c
-+++ b/net/core/secure_seq.c
-@@ -8,7 +8,11 @@
- #include <linux/ktime.h>
- #include <linux/string.h>
- #include <linux/net.h>
-+#include <linux/socket.h>
-+#include <linux/ip.h>
-+#include <linux/ipv6.h>
-
-+#include <net/tcp.h>
- #include <net/secure_seq.h>
-
- #if IS_ENABLED(CONFIG_IPV6) || IS_ENABLED(CONFIG_INET)
-@@ -39,6 +43,102 @@ static u32 seq_scale(u32 seq)
- }
- #endif
-
-+#ifdef CONFIG_TCP_STEALTH
-+u32 tcp_stealth_sequence_number(struct sock *sk, __be32 *daddr,
-+ u32 daddr_size, __be16 dport)
-+{
-+ struct tcp_sock *tp = tcp_sk(sk);
-+ struct tcp_md5sig_key *md5;
-+
-+ __u32 sec[MD5_MESSAGE_BYTES / sizeof(__u32)];
-+ __u32 i;
-+ __u32 tsval = 0;
-+
-+ __be32 iv[MD5_DIGEST_WORDS] = { 0 };
-+ __be32 isn;
-+
-+ memcpy(iv, daddr, (daddr_size > sizeof(iv)) ? sizeof(iv) : daddr_size);
-+
-+#ifdef CONFIG_TCP_MD5SIG
-+ md5 = tp->af_specific->md5_lookup(sk, sk);
-+#else
-+ md5 = NULL;
-+#endif
-+ if (likely(sysctl_tcp_timestamps && !md5) || tp->stealth.saw_tsval)
-+ tsval = tp->stealth.mstamp.stamp_jiffies;
-+
-+ ((__be16 *)iv)[2] ^= cpu_to_be16(tp->stealth.integrity_hash);
-+ iv[2] ^= cpu_to_be32(tsval);
-+ ((__be16 *)iv)[6] ^= dport;
-+
-+ for (i = 0; i < MD5_DIGEST_WORDS; i++)
-+ iv[i] = le32_to_cpu(iv[i]);
-+ for (i = 0; i < MD5_MESSAGE_BYTES / sizeof(__le32); i++)
-+ sec[i] = le32_to_cpu(((__le32 *)tp->stealth.secret)[i]);
-+
-+ md5_transform(iv, sec);
-+
-+ isn = cpu_to_be32(iv[0]) ^ cpu_to_be32(iv[1]) ^
-+ cpu_to_be32(iv[2]) ^ cpu_to_be32(iv[3]);
-+
-+ if (tp->stealth.mode & TCP_STEALTH_MODE_INTEGRITY)
-+ be32_isn_to_be16_ih(isn) =
-+ cpu_to_be16(tp->stealth.integrity_hash);
-+
-+ return be32_to_cpu(isn);
-+}
-+EXPORT_SYMBOL(tcp_stealth_sequence_number);
-+
-+u32 tcp_stealth_do_auth(struct sock *sk, struct sk_buff *skb)
-+{
-+ struct tcp_sock *tp = tcp_sk(sk);
-+ struct tcphdr *th = tcp_hdr(skb);
-+ __be32 isn = th->seq;
-+ __be32 hash;
-+ __be32 *daddr;
-+ u32 daddr_size;
-+
-+ tp->stealth.saw_tsval =
-+ tcp_parse_tsval_option(&tp->stealth.mstamp.stamp_jiffies, th);
-+
-+ if (tp->stealth.mode & TCP_STEALTH_MODE_INTEGRITY_LEN)
-+ tp->stealth.integrity_hash =
-+ be16_to_cpu(be32_isn_to_be16_ih(isn));
-+
-+ switch (tp->inet_conn.icsk_inet.sk.sk_family) {
-+#if IS_ENABLED(CONFIG_IPV6)
-+ case PF_INET6:
-+ daddr_size = sizeof(ipv6_hdr(skb)->daddr.s6_addr32);
-+ daddr = ipv6_hdr(skb)->daddr.s6_addr32;
-+ break;
-+#endif
-+ case PF_INET:
-+ daddr_size = sizeof(ip_hdr(skb)->daddr);
-+ daddr = &ip_hdr(skb)->daddr;
-+ break;
-+ default:
-+ pr_err("TCP Stealth: Unknown network layer protocol, stop!\n");
-+ return 1;
-+ }
-+
-+ hash = tcp_stealth_sequence_number(sk, daddr, daddr_size, th->dest);
-+ cpu_to_be32s(&hash);
-+
-+ if (tp->stealth.mode & TCP_STEALTH_MODE_AUTH &&
-+ tp->stealth.mode & TCP_STEALTH_MODE_INTEGRITY_LEN &&
-+ be32_isn_to_be16_av(isn) == be32_isn_to_be16_av(hash))
-+ return 0;
-+
-+ if (tp->stealth.mode & TCP_STEALTH_MODE_AUTH &&
-+ !(tp->stealth.mode & TCP_STEALTH_MODE_INTEGRITY_LEN) &&
-+ isn == hash)
-+ return 0;
-+
-+ return 1;
-+}
-+EXPORT_SYMBOL(tcp_stealth_do_auth);
-+#endif
-+
- #if IS_ENABLED(CONFIG_IPV6)
- __u32 secure_tcpv6_sequence_number(const __be32 *saddr, const __be32 *daddr,
- __be16 sport, __be16 dport)
-diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
-index b54b3ca..9ec6794 100644
---- a/net/ipv4/Kconfig
-+++ b/net/ipv4/Kconfig
-@@ -728,3 +728,13 @@ config TCP_MD5SIG
- on the Internet.
-
- If unsure, say N.
-+
-+config TCP_STEALTH
-+ bool "TCP: Stealth TCP socket support"
-+ default n
-+ ---help---
-+ This option enables support for stealth TCP sockets. If you do not
-+ know what this means, you do not need it.
-+
-+ If unsure, say N.
-+
-diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
-index 814af89..c9f2ba5 100644
---- a/net/ipv4/tcp.c
-+++ b/net/ipv4/tcp.c
-@@ -269,6 +269,7 @@
- #include <linux/err.h>
- #include <linux/time.h>
- #include <linux/slab.h>
-+#include <linux/vmalloc.h>
-
- #include <net/icmp.h>
- #include <net/inet_common.h>
-@@ -2386,6 +2387,49 @@ static int tcp_repair_options_est(struct tcp_sock *tp,
- return 0;
- }
-
-+#ifdef CONFIG_TCP_STEALTH
-+int tcp_stealth_integrity(__be16 *hash, u8 *secret, u8 *payload, int len)
-+{
-+ struct scatterlist sg[2];
-+ struct crypto_ahash *tfm;
-+ struct ahash_request *req;
-+ __be16 h[MD5_DIGEST_WORDS * 2];
-+ int i;
-+ int err = 0;
-+
-+ tfm = crypto_alloc_ahash("md5", 0, CRYPTO_ALG_ASYNC);
-+ if (IS_ERR(tfm)) {
-+ err = -PTR_ERR(tfm);
-+ goto out;
-+ }
-+ req = ahash_request_alloc(tfm, GFP_ATOMIC);
-+ if (!req)
-+ err = -EFAULT;
-+ goto out;
-+
-+ sg_init_table(sg, 2);
-+ sg_set_buf(&sg[0], secret, MD5_MESSAGE_BYTES);
-+ sg_set_buf(&sg[1], payload, len);
-+
-+ ahash_request_set_callback(req, 0, NULL, NULL);
-+ ahash_request_set_crypt(req, sg, (u8 *)h, MD5_MESSAGE_BYTES + len);
-+
-+ if (crypto_ahash_digest(req)) {
-+ err = -EFAULT;
-+ goto out;
-+ }
-+
-+ *hash = be16_to_cpu(h[0]);
-+ for (i = 1; i < MD5_DIGEST_WORDS * 2; i++)
-+ *hash ^= be16_to_cpu(h[i]);
-+
-+out:
-+ ahash_request_free(req);
-+ crypto_free_ahash(tfm);
-+ return err;
-+}
-+#endif
-+
- /*
- * Socket option code for TCP.
- */
-@@ -2417,6 +2461,66 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
- release_sock(sk);
- return err;
- }
-+#ifdef CONFIG_TCP_STEALTH
-+ case TCP_STEALTH: {
-+ u8 secret[MD5_MESSAGE_BYTES] = { 0 };
-+
-+ val = copy_from_user(secret, optval,
-+ min_t(unsigned int, optlen,
-+ MD5_MESSAGE_BYTES));
-+ if (val != 0)
-+ return -EFAULT;
-+
-+ lock_sock(sk);
-+ memcpy(tp->stealth.secret, secret, MD5_MESSAGE_BYTES);
-+ tp->stealth.mode = TCP_STEALTH_MODE_AUTH;
-+ tp->stealth.mstamp.v64 = 0;
-+ tp->stealth.saw_tsval = false;
-+ release_sock(sk);
-+ return err;
-+ }
-+ case TCP_STEALTH_INTEGRITY: {
-+ u8 *payload;
-+
-+ lock_sock(sk);
-+
-+ if (!(tp->stealth.mode & TCP_STEALTH_MODE_AUTH)) {
-+ err = -EOPNOTSUPP;
-+ goto stealth_integrity_out_1;
-+ }
-+
-+ if (optlen < 1 || optlen > USHRT_MAX) {
-+ err = -EINVAL;
-+ goto stealth_integrity_out_1;
-+ }
-+
-+ payload = vmalloc(optlen);
-+ if (!payload) {
-+ err = -ENOMEM;
-+ goto stealth_integrity_out_1;
-+ }
-+
-+ val = copy_from_user(payload, optval, optlen);
-+ if (val != 0) {
-+ err = -EFAULT;
-+ goto stealth_integrity_out_2;
-+ }
-+
-+ err = tcp_stealth_integrity(&tp->stealth.integrity_hash,
-+ tp->stealth.secret, payload,
-+ optlen);
-+ if (err)
-+ goto stealth_integrity_out_2;
-+
-+ tp->stealth.mode |= TCP_STEALTH_MODE_INTEGRITY;
-+
-+stealth_integrity_out_2:
-+ vfree(payload);
-+stealth_integrity_out_1:
-+ release_sock(sk);
-+ return err;
-+ }
-+#endif
- default:
- /* fallthru */
- break;
-@@ -2671,6 +2775,18 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
- tp->notsent_lowat = val;
- sk->sk_write_space(sk);
- break;
-+#ifdef CONFIG_TCP_STEALTH
-+ case TCP_STEALTH_INTEGRITY_LEN:
-+ if (!(tp->stealth.mode & TCP_STEALTH_MODE_AUTH)) {
-+ err = -EOPNOTSUPP;
-+ } else if (val < 1 || val > USHRT_MAX) {
-+ err = -EINVAL;
-+ } else {
-+ tp->stealth.integrity_len = val;
-+ tp->stealth.mode |= TCP_STEALTH_MODE_INTEGRITY_LEN;
-+ }
-+ break;
-+#endif
- default:
- err = -ENOPROTOOPT;
- break;
-diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
-index c71d49c..24f6d73 100644
---- a/net/ipv4/tcp_input.c
-+++ b/net/ipv4/tcp_input.c
-@@ -77,6 +77,9 @@
- #include <linux/errqueue.h>
-
- int sysctl_tcp_timestamps __read_mostly = 1;
-+#ifdef CONFIG_TCP_STEALTH
-+EXPORT_SYMBOL(sysctl_tcp_timestamps);
-+#endif
- int sysctl_tcp_window_scaling __read_mostly = 1;
- int sysctl_tcp_sack __read_mostly = 1;
- int sysctl_tcp_fack __read_mostly = 1;
-@@ -3926,6 +3929,47 @@ static bool tcp_fast_parse_options(const struct sk_buff *skb,
- return true;
- }
-
-+#ifdef CONFIG_TCP_STEALTH
-+/* Parse only the TSVal field of the TCP Timestamp option header.
-+ */
-+const bool tcp_parse_tsval_option(u32 *tsval, const struct tcphdr *th)
-+{
-+ int length = (th->doff << 2) - sizeof(*th);
-+ const u8 *ptr = (const u8 *)(th + 1);
-+
-+ /* If the TCP option is too short, we can short cut */
-+ if (length < TCPOLEN_TIMESTAMP)
-+ return false;
-+
-+ while (length > 0) {
-+ int opcode = *ptr++;
-+ int opsize;
-+
-+ switch (opcode) {
-+ case TCPOPT_EOL:
-+ return false;
-+ case TCPOPT_NOP:
-+ length--;
-+ continue;
-+ case TCPOPT_TIMESTAMP:
-+ opsize = *ptr++;
-+ if (opsize != TCPOLEN_TIMESTAMP || opsize > length)
-+ return false;
-+ *tsval = get_unaligned_be32(ptr);
-+ return true;
-+ default:
-+ opsize = *ptr++;
-+ if (opsize < 2 || opsize > length)
-+ return false;
-+ }
-+ ptr += opsize - 2;
-+ length -= opsize;
-+ }
-+ return false;
-+}
-+EXPORT_SYMBOL(tcp_parse_tsval_option);
-+#endif
-+
- #ifdef CONFIG_TCP_MD5SIG
- /*
- * Parse MD5 Signature option
-@@ -4631,6 +4675,31 @@ err:
-
- }
-
-+#ifdef CONFIG_TCP_STEALTH
-+static int __tcp_stealth_integrity_check(struct sock *sk, struct sk_buff *skb)
-+{
-+ struct tcphdr *th = tcp_hdr(skb);
-+ struct tcp_sock *tp = tcp_sk(sk);
-+ u16 hash;
-+ __be32 seq = cpu_to_be32(TCP_SKB_CB(skb)->seq - 1);
-+ char *data = skb->data + th->doff * 4;
-+ int len = skb->len - th->doff * 4;
-+
-+ if (len < tp->stealth.integrity_len)
-+ return 1;
-+
-+ if (tcp_stealth_integrity(&hash, tp->stealth.secret, data,
-+ tp->stealth.integrity_len))
-+ return 1;
-+
-+ if (be32_isn_to_be16_ih(seq) != cpu_to_be16(hash))
-+ return 1;
-+
-+ tp->stealth.mode &= ~TCP_STEALTH_MODE_INTEGRITY_LEN;
-+ return 0;
-+}
-+#endif
-+
- static void tcp_data_queue(struct sock *sk, struct sk_buff *skb)
- {
- struct tcp_sock *tp = tcp_sk(sk);
-@@ -4641,6 +4710,15 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb)
- __kfree_skb(skb);
- return;
- }
-+
-+#ifdef CONFIG_TCP_STEALTH
-+ if (unlikely(tp->stealth.mode & TCP_STEALTH_MODE_INTEGRITY_LEN) &&
-+ __tcp_stealth_integrity_check(sk, skb)) {
-+ tcp_reset(sk);
-+ goto drop;
-+ }
-+#endif
-+
- skb_dst_drop(skb);
- __skb_pull(skb, tcp_hdr(skb)->doff * 4);
-
-@@ -5456,6 +5534,15 @@ void tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
- int eaten = 0;
- bool fragstolen = false;
-
-+#ifdef CONFIG_TCP_STEALTH
-+ if (unlikely(tp->stealth.mode &
-+ TCP_STEALTH_MODE_INTEGRITY_LEN) &&
-+ __tcp_stealth_integrity_check(sk, skb)) {
-+ tcp_reset(sk);
-+ goto discard;
-+ }
-+#endif
-+
- if (tp->ucopy.task == current &&
- tp->copied_seq == tp->rcv_nxt &&
- len - tcp_header_len <= tp->ucopy.len &&
-diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
-index 2259114..542da7a 100644
---- a/net/ipv4/tcp_ipv4.c
-+++ b/net/ipv4/tcp_ipv4.c
-@@ -74,6 +74,7 @@
- #include <net/xfrm.h>
- #include <net/secure_seq.h>
- #include <net/busy_poll.h>
-+#include <net/secure_seq.h>
-
- #include <linux/inet.h>
- #include <linux/ipv6.h>
-@@ -233,6 +234,21 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
- sk->sk_gso_type = SKB_GSO_TCPV4;
- sk_setup_caps(sk, &rt->dst);
-
-+#ifdef CONFIG_TCP_STEALTH
-+ /* If CONFIG_TCP_STEALTH is defined, we need to know the timestamp as
-+ * early as possible and thus move taking the snapshot of tcp_time_stamp
-+ * here.
-+ */
-+ skb_mstamp_get(&tp->stealth.mstamp);
-+
-+ if (!tp->write_seq && likely(!tp->repair) &&
-+ unlikely(tp->stealth.mode & TCP_STEALTH_MODE_AUTH))
-+ tp->write_seq = tcp_stealth_sequence_number(sk,
-+ &inet->inet_daddr,
-+ sizeof(inet->inet_daddr),
-+ usin->sin_port);
-+#endif
-+
- if (!tp->write_seq && likely(!tp->repair))
- tp->write_seq = secure_tcp_sequence_number(inet->inet_saddr,
- inet->inet_daddr,
-@@ -1382,6 +1398,8 @@ static struct sock *tcp_v4_cookie_check(struct sock *sk, struct sk_buff *skb)
- */
- int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
- {
-+ struct tcp_sock *tp = tcp_sk(sk);
-+ struct tcphdr *th = tcp_hdr(skb);
- struct sock *rsk;
-
- if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */
-@@ -1403,6 +1421,15 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
- if (tcp_checksum_complete(skb))
- goto csum_err;
-
-+#ifdef CONFIG_TCP_STEALTH
-+ if (sk->sk_state == TCP_LISTEN && th->syn && !th->fin &&
-+ unlikely(tp->stealth.mode & TCP_STEALTH_MODE_AUTH) &&
-+ tcp_stealth_do_auth(sk, skb)) {
-+ rsk = sk;
-+ goto reset;
-+ }
-+#endif
-+
- if (sk->sk_state == TCP_LISTEN) {
- struct sock *nsk = tcp_v4_cookie_check(sk, skb);
-
-diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
-index 896e9df..7bf3142 100644
---- a/net/ipv4/tcp_output.c
-+++ b/net/ipv4/tcp_output.c
-@@ -939,6 +939,13 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
- tcb = TCP_SKB_CB(skb);
- memset(&opts, 0, sizeof(opts));
-
-+#ifdef TCP_STEALTH
-+ if (unlikely(tcb->tcp_flags & TCPHDR_SYN &&
-+ tp->stealth.mode & TCP_STEALTH_MODE_AUTH)) {
-+ skb->skb_mstamp = tp->stealth.mstamp;
-+ }
-+#endif
-+
- if (unlikely(tcb->tcp_flags & TCPHDR_SYN))
- tcp_options_size = tcp_syn_options(sk, skb, &opts, &md5);
- else
-@@ -3349,7 +3356,15 @@ int tcp_connect(struct sock *sk)
- return -ENOBUFS;
-
- tcp_init_nondata_skb(buff, tp->write_seq++, TCPHDR_SYN);
-+#ifdef CONFIG_TCP_STEALTH
-+ /* The timetamp was already made at the time the ISN was generated
-+ * as we need to know its value in the stealth_tcp_sequence_number()
-+ * function.
-+ */
-+ tp->retrans_stamp = tp->stealth.mstamp.stamp_jiffies;
-+#else
- tp->retrans_stamp = tcp_time_stamp;
-+#endif
- tcp_connect_queue_skb(sk, buff);
- tcp_ecn_send_syn(sk, buff);
-
-diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
-index b9f1fee..b301a49 100644
---- a/net/ipv6/tcp_ipv6.c
-+++ b/net/ipv6/tcp_ipv6.c
-@@ -62,6 +62,7 @@
- #include <net/inet_common.h>
- #include <net/secure_seq.h>
- #include <net/busy_poll.h>
-+#include <net/secure_seq.h>
-
- #include <linux/proc_fs.h>
- #include <linux/seq_file.h>
-@@ -278,6 +279,21 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
-
- sk_set_txhash(sk);
-
-+#ifdef CONFIG_TCP_STEALTH
-+ /* If CONFIG_TCP_STEALTH is defined, we need to know the timestamp as
-+ * early as possible and thus move taking the snapshot of tcp_time_stamp
-+ * here.
-+ */
-+ skb_mstamp_get(&tp->stealth.mstamp);
-+
-+ if (!tp->write_seq && likely(!tp->repair) &&
-+ unlikely(tp->stealth.mode & TCP_STEALTH_MODE_AUTH))
-+ tp->write_seq = tcp_stealth_sequence_number(sk,
-+ sk->sk_v6_daddr.s6_addr32,
-+ sizeof(sk->sk_v6_daddr),
-+ inet->inet_dport);
-+#endif
-+
- if (!tp->write_seq && likely(!tp->repair))
- tp->write_seq = secure_tcpv6_sequence_number(np->saddr.s6_addr32,
- sk->sk_v6_daddr.s6_addr32,
-@@ -1215,7 +1231,8 @@ static void tcp_v6_restore_cb(struct sk_buff *skb)
- static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
- {
- struct ipv6_pinfo *np = inet6_sk(sk);
-- struct tcp_sock *tp;
-+ struct tcp_sock *tp = tcp_sk(sk);
-+ struct tcphdr *th = tcp_hdr(skb);
- struct sk_buff *opt_skb = NULL;
-
- /* Imagine: socket is IPv6. IPv4 packet arrives,
-@@ -1275,6 +1292,13 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
- if (tcp_checksum_complete(skb))
- goto csum_err;
-
-+#ifdef CONFIG_TCP_STEALTH
-+ if (sk->sk_state == TCP_LISTEN && th->syn && !th->fin &&
-+ tp->stealth.mode & TCP_STEALTH_MODE_AUTH &&
-+ tcp_stealth_do_auth(sk, skb))
-+ goto reset;
-+#endif
-+
- if (sk->sk_state == TCP_LISTEN) {
- struct sock *nsk = tcp_v6_cookie_check(sk, skb);
-