bpf: Add sock_ops R/W access to ipv4 tos

    Sample usage for tos:

      bpf_getsockopt(skops, SOL_IP, IP_TOS, &v, sizeof(v))

    where skops is a pointer to the ctx (struct bpf_sock_ops).

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

diff --git a/net/core/filter.c b/net/core/filter.c
index 00c711c..afd8255 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -3462,6 +3462,27 @@ BPF_CALL_5(bpf_setsockopt, struct bpf_sock_ops_kern *, 
bpf_sock,
                        ret = -EINVAL;
                }
 #ifdef CONFIG_INET
+       } else if (level == SOL_IP) {
+               if (optlen != sizeof(int) || sk->sk_family != AF_INET)
+                       return -EINVAL;
+
+               val = *((int *)optval);
+               /* Only some options are supported */
+               switch (optname) {
+               case IP_TOS:
+                       if (val < -1 || val > 0xff) {
+                               ret = -EINVAL;
+                       } else {
+                               struct inet_sock *inet = inet_sk(sk);
+
+                               if (val == -1)
+                                       val = 0;
+                               inet->tos = val;
+                       }
+                       break;
+               default:
+                       ret = -EINVAL;
+               }
 #if IS_ENABLED(CONFIG_IPV6)
        } else if (level == SOL_IPV6) {
                if (optlen != sizeof(int) || sk->sk_family != AF_INET6)
@@ -3561,6 +3582,20 @@ BPF_CALL_5(bpf_getsockopt, struct bpf_sock_ops_kern *, 
bpf_sock,
                } else {
                        goto err_clear;
                }
+       } else if (level == SOL_IP) {
+               struct inet_sock *inet = inet_sk(sk);
+
+               if (optlen != sizeof(int) || sk->sk_family != AF_INET)
+                       goto err_clear;
+
+               /* Only some options are supported */
+               switch (optname) {
+               case IP_TOS:
+                       *((int *)optval) = (int)inet->tos;
+                       break;
+               default:
+                       goto err_clear;
+               }
 #if IS_ENABLED(CONFIG_IPV6)
        } else if (level == SOL_IPV6) {
                struct ipv6_pinfo *np = inet6_sk(sk);
-- 
2.9.5

Reply via email to