adding support for two new bpf's get/set sockopts: TCP_SAVE_SYN (set)
and TCP_SAVED_SYN (get). this would allow for bpf program to build
logic based on data from ingress SYN packet

Signed-off-by: Nikita V. Shirokov <tehn...@fb.com>
---
 net/core/filter.c | 25 +++++++++++++++++++++----
 1 file changed, 21 insertions(+), 4 deletions(-)

diff --git a/net/core/filter.c b/net/core/filter.c
index c25eb36f1320..feb578506009 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -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) {
-- 
2.17.1

Reply via email to