Commit 7656d684 authored by Martin KaFai Lau's avatar Martin KaFai Lau Committed by Alexei Starovoitov

tcp: Add saw_unknown to struct tcp_options_received

In a later patch, the bpf prog only wants to be called to handle
a header option if that particular header option cannot be handled by
the kernel.  This unknown option could be written by the peer's bpf-prog.
It could also be a new standard option that the running kernel does not
support it while a bpf-prog can handle it.

This patch adds a "saw_unknown" bit to "struct tcp_options_received"
and it uses an existing one byte hole to do that.  "saw_unknown" will
be set in tcp_parse_options() if it sees an option that the kernel
cannot handle.
Signed-off-by: default avatarMartin KaFai Lau <kafai@fb.com>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
Reviewed-by: default avatarEric Dumazet <edumazet@google.com>
Acked-by: default avatarJohn Fastabend <john.fastabend@gmail.com>
Link: https://lore.kernel.org/bpf/20200820190033.2884430-1-kafai@fb.com
parent ca584ba0
...@@ -92,6 +92,8 @@ struct tcp_options_received { ...@@ -92,6 +92,8 @@ struct tcp_options_received {
smc_ok : 1, /* SMC seen on SYN packet */ smc_ok : 1, /* SMC seen on SYN packet */
snd_wscale : 4, /* Window scaling received from sender */ snd_wscale : 4, /* Window scaling received from sender */
rcv_wscale : 4; /* Window scaling to send to receiver */ rcv_wscale : 4; /* Window scaling to send to receiver */
u8 saw_unknown:1, /* Received unknown option */
unused:7;
u8 num_sacks; /* Number of SACK blocks */ u8 num_sacks; /* Number of SACK blocks */
u16 user_mss; /* mss requested by user in ioctl */ u16 user_mss; /* mss requested by user in ioctl */
u16 mss_clamp; /* Maximal mss, negotiated at connection setup */ u16 mss_clamp; /* Maximal mss, negotiated at connection setup */
......
...@@ -3801,7 +3801,7 @@ static void tcp_parse_fastopen_option(int len, const unsigned char *cookie, ...@@ -3801,7 +3801,7 @@ static void tcp_parse_fastopen_option(int len, const unsigned char *cookie,
foc->exp = exp_opt; foc->exp = exp_opt;
} }
static void smc_parse_options(const struct tcphdr *th, static bool smc_parse_options(const struct tcphdr *th,
struct tcp_options_received *opt_rx, struct tcp_options_received *opt_rx,
const unsigned char *ptr, const unsigned char *ptr,
int opsize) int opsize)
...@@ -3810,10 +3810,13 @@ static void smc_parse_options(const struct tcphdr *th, ...@@ -3810,10 +3810,13 @@ static void smc_parse_options(const struct tcphdr *th,
if (static_branch_unlikely(&tcp_have_smc)) { if (static_branch_unlikely(&tcp_have_smc)) {
if (th->syn && !(opsize & 1) && if (th->syn && !(opsize & 1) &&
opsize >= TCPOLEN_EXP_SMC_BASE && opsize >= TCPOLEN_EXP_SMC_BASE &&
get_unaligned_be32(ptr) == TCPOPT_SMC_MAGIC) get_unaligned_be32(ptr) == TCPOPT_SMC_MAGIC) {
opt_rx->smc_ok = 1; opt_rx->smc_ok = 1;
return true;
}
} }
#endif #endif
return false;
} }
/* Try to parse the MSS option from the TCP header. Return 0 on failure, clamped /* Try to parse the MSS option from the TCP header. Return 0 on failure, clamped
...@@ -3874,6 +3877,7 @@ void tcp_parse_options(const struct net *net, ...@@ -3874,6 +3877,7 @@ void tcp_parse_options(const struct net *net,
ptr = (const unsigned char *)(th + 1); ptr = (const unsigned char *)(th + 1);
opt_rx->saw_tstamp = 0; opt_rx->saw_tstamp = 0;
opt_rx->saw_unknown = 0;
while (length > 0) { while (length > 0) {
int opcode = *ptr++; int opcode = *ptr++;
...@@ -3964,15 +3968,21 @@ void tcp_parse_options(const struct net *net, ...@@ -3964,15 +3968,21 @@ void tcp_parse_options(const struct net *net,
*/ */
if (opsize >= TCPOLEN_EXP_FASTOPEN_BASE && if (opsize >= TCPOLEN_EXP_FASTOPEN_BASE &&
get_unaligned_be16(ptr) == get_unaligned_be16(ptr) ==
TCPOPT_FASTOPEN_MAGIC) TCPOPT_FASTOPEN_MAGIC) {
tcp_parse_fastopen_option(opsize - tcp_parse_fastopen_option(opsize -
TCPOLEN_EXP_FASTOPEN_BASE, TCPOLEN_EXP_FASTOPEN_BASE,
ptr + 2, th->syn, foc, true); ptr + 2, th->syn, foc, true);
else break;
smc_parse_options(th, opt_rx, ptr, }
opsize);
if (smc_parse_options(th, opt_rx, ptr, opsize))
break;
opt_rx->saw_unknown = 1;
break; break;
default:
opt_rx->saw_unknown = 1;
} }
ptr += opsize-2; ptr += opsize-2;
length -= opsize; length -= opsize;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment