|
@@ -4007,6 +4007,12 @@ BPF_CALL_5(bpf_setsockopt, struct bpf_sock_ops_kern *, bpf_sock,
|
|
|
tp->snd_ssthresh = val;
|
|
|
}
|
|
|
break;
|
|
|
+ case TCP_SAVE_SYN:
|
|
|
+ if (val < 0 || val > 1)
|
|
|
+ ret = -EINVAL;
|
|
|
+ else
|
|
|
+ tp->save_syn = val;
|
|
|
+ break;
|
|
|
default:
|
|
|
ret = -EINVAL;
|
|
|
}
|
|
@@ -4032,21 +4038,32 @@ static const struct bpf_func_proto bpf_setsockopt_proto = {
|
|
|
BPF_CALL_5(bpf_getsockopt, struct bpf_sock_ops_kern *, bpf_sock,
|
|
|
int, level, int, optname, char *, optval, int, optlen)
|
|
|
{
|
|
|
+ struct inet_connection_sock *icsk;
|
|
|
struct sock *sk = bpf_sock->sk;
|
|
|
+ struct tcp_sock *tp;
|
|
|
|
|
|
if (!sk_fullsock(sk))
|
|
|
goto err_clear;
|
|
|
-
|
|
|
#ifdef CONFIG_INET
|
|
|
if (level == SOL_TCP && sk->sk_prot->getsockopt == tcp_getsockopt) {
|
|
|
- if (optname == TCP_CONGESTION) {
|
|
|
- struct inet_connection_sock *icsk = inet_csk(sk);
|
|
|
+ switch (optname) {
|
|
|
+ case TCP_CONGESTION:
|
|
|
+ icsk = inet_csk(sk);
|
|
|
|
|
|
if (!icsk->icsk_ca_ops || optlen <= 1)
|
|
|
goto err_clear;
|
|
|
strncpy(optval, icsk->icsk_ca_ops->name, optlen);
|
|
|
optval[optlen - 1] = 0;
|
|
|
- } else {
|
|
|
+ break;
|
|
|
+ case TCP_SAVED_SYN:
|
|
|
+ tp = tcp_sk(sk);
|
|
|
+
|
|
|
+ if (optlen <= 0 || !tp->saved_syn ||
|
|
|
+ optlen > tp->saved_syn[0])
|
|
|
+ goto err_clear;
|
|
|
+ memcpy(optval, tp->saved_syn + 1, optlen);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
goto err_clear;
|
|
|
}
|
|
|
} else if (level == SOL_IP) {
|