|
@@ -65,9 +65,6 @@ int sysctl_tcp_base_mss __read_mostly = TCP_BASE_MSS;
|
|
|
/* By default, RFC2861 behavior. */
|
|
|
int sysctl_tcp_slow_start_after_idle __read_mostly = 1;
|
|
|
|
|
|
-int sysctl_tcp_cookie_size __read_mostly = 0; /* TCP_COOKIE_MAX */
|
|
|
-EXPORT_SYMBOL_GPL(sysctl_tcp_cookie_size);
|
|
|
-
|
|
|
static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
|
|
|
int push_one, gfp_t gfp);
|
|
|
|
|
@@ -386,7 +383,6 @@ static inline bool tcp_urg_mode(const struct tcp_sock *tp)
|
|
|
#define OPTION_TS (1 << 1)
|
|
|
#define OPTION_MD5 (1 << 2)
|
|
|
#define OPTION_WSCALE (1 << 3)
|
|
|
-#define OPTION_COOKIE_EXTENSION (1 << 4)
|
|
|
#define OPTION_FAST_OPEN_COOKIE (1 << 8)
|
|
|
|
|
|
struct tcp_out_options {
|
|
@@ -400,36 +396,6 @@ struct tcp_out_options {
|
|
|
struct tcp_fastopen_cookie *fastopen_cookie; /* Fast open cookie */
|
|
|
};
|
|
|
|
|
|
-/* The sysctl int routines are generic, so check consistency here.
|
|
|
- */
|
|
|
-static u8 tcp_cookie_size_check(u8 desired)
|
|
|
-{
|
|
|
- int cookie_size;
|
|
|
-
|
|
|
- if (desired > 0)
|
|
|
- /* previously specified */
|
|
|
- return desired;
|
|
|
-
|
|
|
- cookie_size = ACCESS_ONCE(sysctl_tcp_cookie_size);
|
|
|
- if (cookie_size <= 0)
|
|
|
- /* no default specified */
|
|
|
- return 0;
|
|
|
-
|
|
|
- if (cookie_size <= TCP_COOKIE_MIN)
|
|
|
- /* value too small, specify minimum */
|
|
|
- return TCP_COOKIE_MIN;
|
|
|
-
|
|
|
- if (cookie_size >= TCP_COOKIE_MAX)
|
|
|
- /* value too large, specify maximum */
|
|
|
- return TCP_COOKIE_MAX;
|
|
|
-
|
|
|
- if (cookie_size & 1)
|
|
|
- /* 8-bit multiple, illegal, fix it */
|
|
|
- cookie_size++;
|
|
|
-
|
|
|
- return (u8)cookie_size;
|
|
|
-}
|
|
|
-
|
|
|
/* Write previously computed TCP options to the packet.
|
|
|
*
|
|
|
* 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,
|
|
|
{
|
|
|
u16 options = opts->options; /* mungable copy */
|
|
|
|
|
|
- /* Having both authentication and cookies for security is redundant,
|
|
|
- * and there's certainly not enough room. Instead, the cookie-less
|
|
|
- * extension variant is proposed.
|
|
|
- *
|
|
|
- * Consider the pessimal case with authentication. The options
|
|
|
- * could look like:
|
|
|
- * COOKIE|MD5(20) + MSS(4) + SACK|TS(12) + WSCALE(4) == 40
|
|
|
- */
|
|
|
if (unlikely(OPTION_MD5 & options)) {
|
|
|
- if (unlikely(OPTION_COOKIE_EXTENSION & options)) {
|
|
|
- *ptr++ = htonl((TCPOPT_COOKIE << 24) |
|
|
|
- (TCPOLEN_COOKIE_BASE << 16) |
|
|
|
- (TCPOPT_MD5SIG << 8) |
|
|
|
- TCPOLEN_MD5SIG);
|
|
|
- } else {
|
|
|
- *ptr++ = htonl((TCPOPT_NOP << 24) |
|
|
|
- (TCPOPT_NOP << 16) |
|
|
|
- (TCPOPT_MD5SIG << 8) |
|
|
|
- TCPOLEN_MD5SIG);
|
|
|
- }
|
|
|
- options &= ~OPTION_COOKIE_EXTENSION;
|
|
|
+ *ptr++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
|
|
|
+ (TCPOPT_MD5SIG << 8) | TCPOLEN_MD5SIG);
|
|
|
/* overload cookie hash location */
|
|
|
opts->hash_location = (__u8 *)ptr;
|
|
|
ptr += 4;
|
|
@@ -497,44 +445,6 @@ static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp,
|
|
|
*ptr++ = htonl(opts->tsecr);
|
|
|
}
|
|
|
|
|
|
- /* Specification requires after timestamp, so do it now.
|
|
|
- *
|
|
|
- * Consider the pessimal case without authentication. The options
|
|
|
- * could look like:
|
|
|
- * MSS(4) + SACK|TS(12) + COOKIE(20) + WSCALE(4) == 40
|
|
|
- */
|
|
|
- if (unlikely(OPTION_COOKIE_EXTENSION & options)) {
|
|
|
- __u8 *cookie_copy = opts->hash_location;
|
|
|
- u8 cookie_size = opts->hash_size;
|
|
|
-
|
|
|
- /* 8-bit multiple handled in tcp_cookie_size_check() above,
|
|
|
- * and elsewhere.
|
|
|
- */
|
|
|
- if (0x2 & cookie_size) {
|
|
|
- __u8 *p = (__u8 *)ptr;
|
|
|
-
|
|
|
- /* 16-bit multiple */
|
|
|
- *p++ = TCPOPT_COOKIE;
|
|
|
- *p++ = TCPOLEN_COOKIE_BASE + cookie_size;
|
|
|
- *p++ = *cookie_copy++;
|
|
|
- *p++ = *cookie_copy++;
|
|
|
- ptr++;
|
|
|
- cookie_size -= 2;
|
|
|
- } else {
|
|
|
- /* 32-bit multiple */
|
|
|
- *ptr++ = htonl(((TCPOPT_NOP << 24) |
|
|
|
- (TCPOPT_NOP << 16) |
|
|
|
- (TCPOPT_COOKIE << 8) |
|
|
|
- TCPOLEN_COOKIE_BASE) +
|
|
|
- cookie_size);
|
|
|
- }
|
|
|
-
|
|
|
- if (cookie_size > 0) {
|
|
|
- memcpy(ptr, cookie_copy, cookie_size);
|
|
|
- ptr += (cookie_size / 4);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
if (unlikely(OPTION_SACK_ADVERTISE & options)) {
|
|
|
*ptr++ = htonl((TCPOPT_NOP << 24) |
|
|
|
(TCPOPT_NOP << 16) |
|
|
@@ -593,11 +503,7 @@ static unsigned int tcp_syn_options(struct sock *sk, struct sk_buff *skb,
|
|
|
struct tcp_md5sig_key **md5)
|
|
|
{
|
|
|
struct tcp_sock *tp = tcp_sk(sk);
|
|
|
- struct tcp_cookie_values *cvp = tp->cookie_values;
|
|
|
unsigned int remaining = MAX_TCP_OPTION_SPACE;
|
|
|
- u8 cookie_size = (!tp->rx_opt.cookie_out_never && cvp != NULL) ?
|
|
|
- tcp_cookie_size_check(cvp->cookie_desired) :
|
|
|
- 0;
|
|
|
struct tcp_fastopen_request *fastopen = tp->fastopen_req;
|
|
|
|
|
|
#ifdef CONFIG_TCP_MD5SIG
|
|
@@ -649,52 +555,7 @@ static unsigned int tcp_syn_options(struct sock *sk, struct sk_buff *skb,
|
|
|
tp->syn_fastopen = 1;
|
|
|
}
|
|
|
}
|
|
|
- /* Note that timestamps are required by the specification.
|
|
|
- *
|
|
|
- * Odd numbers of bytes are prohibited by the specification, ensuring
|
|
|
- * that the cookie is 16-bit aligned, and the resulting cookie pair is
|
|
|
- * 32-bit aligned.
|
|
|
- */
|
|
|
- if (*md5 == NULL &&
|
|
|
- (OPTION_TS & opts->options) &&
|
|
|
- cookie_size > 0) {
|
|
|
- int need = TCPOLEN_COOKIE_BASE + cookie_size;
|
|
|
-
|
|
|
- if (0x2 & need) {
|
|
|
- /* 32-bit multiple */
|
|
|
- need += 2; /* NOPs */
|
|
|
-
|
|
|
- if (need > remaining) {
|
|
|
- /* try shrinking cookie to fit */
|
|
|
- cookie_size -= 2;
|
|
|
- need -= 4;
|
|
|
- }
|
|
|
- }
|
|
|
- while (need > remaining && TCP_COOKIE_MIN <= cookie_size) {
|
|
|
- cookie_size -= 4;
|
|
|
- need -= 4;
|
|
|
- }
|
|
|
- if (TCP_COOKIE_MIN <= cookie_size) {
|
|
|
- opts->options |= OPTION_COOKIE_EXTENSION;
|
|
|
- opts->hash_location = (__u8 *)&cvp->cookie_pair[0];
|
|
|
- opts->hash_size = cookie_size;
|
|
|
-
|
|
|
- /* Remember for future incarnations. */
|
|
|
- cvp->cookie_desired = cookie_size;
|
|
|
-
|
|
|
- if (cvp->cookie_desired != cvp->cookie_pair_size) {
|
|
|
- /* Currently use random bytes as a nonce,
|
|
|
- * assuming these are completely unpredictable
|
|
|
- * by hostile users of the same system.
|
|
|
- */
|
|
|
- get_random_bytes(&cvp->cookie_pair[0],
|
|
|
- cookie_size);
|
|
|
- cvp->cookie_pair_size = cookie_size;
|
|
|
- }
|
|
|
|
|
|
- remaining -= need;
|
|
|
- }
|
|
|
- }
|
|
|
return MAX_TCP_OPTION_SPACE - remaining;
|
|
|
}
|
|
|
|
|
@@ -704,14 +565,10 @@ static unsigned int tcp_synack_options(struct sock *sk,
|
|
|
unsigned int mss, struct sk_buff *skb,
|
|
|
struct tcp_out_options *opts,
|
|
|
struct tcp_md5sig_key **md5,
|
|
|
- struct tcp_extend_values *xvp,
|
|
|
struct tcp_fastopen_cookie *foc)
|
|
|
{
|
|
|
struct inet_request_sock *ireq = inet_rsk(req);
|
|
|
unsigned int remaining = MAX_TCP_OPTION_SPACE;
|
|
|
- u8 cookie_plus = (xvp != NULL && !xvp->cookie_out_never) ?
|
|
|
- xvp->cookie_plus :
|
|
|
- 0;
|
|
|
|
|
|
#ifdef CONFIG_TCP_MD5SIG
|
|
|
*md5 = tcp_rsk(req)->af_specific->md5_lookup(sk, req);
|
|
@@ -759,28 +616,7 @@ static unsigned int tcp_synack_options(struct sock *sk,
|
|
|
remaining -= need;
|
|
|
}
|
|
|
}
|
|
|
- /* Similar rationale to tcp_syn_options() applies here, too.
|
|
|
- * If the <SYN> options fit, the same options should fit now!
|
|
|
- */
|
|
|
- if (*md5 == NULL &&
|
|
|
- ireq->tstamp_ok &&
|
|
|
- cookie_plus > TCPOLEN_COOKIE_BASE) {
|
|
|
- int need = cookie_plus; /* has TCPOLEN_COOKIE_BASE */
|
|
|
-
|
|
|
- if (0x2 & need) {
|
|
|
- /* 32-bit multiple */
|
|
|
- need += 2; /* NOPs */
|
|
|
- }
|
|
|
- if (need <= remaining) {
|
|
|
- opts->options |= OPTION_COOKIE_EXTENSION;
|
|
|
- opts->hash_size = cookie_plus - TCPOLEN_COOKIE_BASE;
|
|
|
- remaining -= need;
|
|
|
- } else {
|
|
|
- /* There's no error return, so flag it. */
|
|
|
- xvp->cookie_out_never = 1; /* true */
|
|
|
- opts->hash_size = 0;
|
|
|
- }
|
|
|
- }
|
|
|
+
|
|
|
return MAX_TCP_OPTION_SPACE - remaining;
|
|
|
}
|
|
|
|
|
@@ -2802,32 +2638,24 @@ int tcp_send_synack(struct sock *sk)
|
|
|
* sk: listener socket
|
|
|
* dst: dst entry attached to the SYNACK
|
|
|
* req: request_sock pointer
|
|
|
- * rvp: request_values pointer
|
|
|
*
|
|
|
* Allocate one skb and build a SYNACK packet.
|
|
|
* @dst is consumed : Caller should not use it again.
|
|
|
*/
|
|
|
struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
|
|
|
struct request_sock *req,
|
|
|
- struct request_values *rvp,
|
|
|
struct tcp_fastopen_cookie *foc)
|
|
|
{
|
|
|
struct tcp_out_options opts;
|
|
|
- struct tcp_extend_values *xvp = tcp_xv(rvp);
|
|
|
struct inet_request_sock *ireq = inet_rsk(req);
|
|
|
struct tcp_sock *tp = tcp_sk(sk);
|
|
|
- const struct tcp_cookie_values *cvp = tp->cookie_values;
|
|
|
struct tcphdr *th;
|
|
|
struct sk_buff *skb;
|
|
|
struct tcp_md5sig_key *md5;
|
|
|
int tcp_header_size;
|
|
|
int mss;
|
|
|
- int s_data_desired = 0;
|
|
|
|
|
|
- if (cvp != NULL && cvp->s_data_constant && cvp->s_data_desired)
|
|
|
- s_data_desired = cvp->s_data_desired;
|
|
|
- skb = alloc_skb(MAX_TCP_HEADER + 15 + s_data_desired,
|
|
|
- sk_gfp_atomic(sk, GFP_ATOMIC));
|
|
|
+ skb = alloc_skb(MAX_TCP_HEADER + 15, sk_gfp_atomic(sk, GFP_ATOMIC));
|
|
|
if (unlikely(!skb)) {
|
|
|
dst_release(dst);
|
|
|
return NULL;
|
|
@@ -2869,9 +2697,8 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
|
|
|
else
|
|
|
#endif
|
|
|
TCP_SKB_CB(skb)->when = tcp_time_stamp;
|
|
|
- tcp_header_size = tcp_synack_options(sk, req, mss,
|
|
|
- skb, &opts, &md5, xvp, foc)
|
|
|
- + sizeof(*th);
|
|
|
+ tcp_header_size = tcp_synack_options(sk, req, mss, skb, &opts, &md5,
|
|
|
+ foc) + sizeof(*th);
|
|
|
|
|
|
skb_push(skb, tcp_header_size);
|
|
|
skb_reset_transport_header(skb);
|
|
@@ -2889,40 +2716,6 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
|
|
|
tcp_init_nondata_skb(skb, tcp_rsk(req)->snt_isn,
|
|
|
TCPHDR_SYN | TCPHDR_ACK);
|
|
|
|
|
|
- if (OPTION_COOKIE_EXTENSION & opts.options) {
|
|
|
- if (s_data_desired) {
|
|
|
- u8 *buf = skb_put(skb, s_data_desired);
|
|
|
-
|
|
|
- /* copy data directly from the listening socket. */
|
|
|
- memcpy(buf, cvp->s_data_payload, s_data_desired);
|
|
|
- TCP_SKB_CB(skb)->end_seq += s_data_desired;
|
|
|
- }
|
|
|
-
|
|
|
- if (opts.hash_size > 0) {
|
|
|
- __u32 workspace[SHA_WORKSPACE_WORDS];
|
|
|
- u32 *mess = &xvp->cookie_bakery[COOKIE_DIGEST_WORDS];
|
|
|
- u32 *tail = &mess[COOKIE_MESSAGE_WORDS-1];
|
|
|
-
|
|
|
- /* Secret recipe depends on the Timestamp, (future)
|
|
|
- * Sequence and Acknowledgment Numbers, Initiator
|
|
|
- * Cookie, and others handled by IP variant caller.
|
|
|
- */
|
|
|
- *tail-- ^= opts.tsval;
|
|
|
- *tail-- ^= tcp_rsk(req)->rcv_isn + 1;
|
|
|
- *tail-- ^= TCP_SKB_CB(skb)->seq + 1;
|
|
|
-
|
|
|
- /* recommended */
|
|
|
- *tail-- ^= (((__force u32)th->dest << 16) | (__force u32)th->source);
|
|
|
- *tail-- ^= (u32)(unsigned long)cvp; /* per sockopt */
|
|
|
-
|
|
|
- sha_transform((__u32 *)&xvp->cookie_bakery[0],
|
|
|
- (char *)mess,
|
|
|
- &workspace[0]);
|
|
|
- opts.hash_location =
|
|
|
- (__u8 *)&xvp->cookie_bakery[0];
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
th->seq = htonl(TCP_SKB_CB(skb)->seq);
|
|
|
/* XXX data is queued and acked as is. No buffer/window check */
|
|
|
th->ack_seq = htonl(tcp_rsk(req)->rcv_nxt);
|