summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorNikita V. Shirokov <tehnerd@fb.com>2018-03-26 08:36:57 -0700
committerDaniel Borkmann <daniel@iogearbox.net>2018-03-28 21:05:35 +0200
commit6f5c39fa5cd4a78c5432021e981aa8f79437a32c (patch)
treeca8000b083f974d4d87861ea89cb43e25049fa77 /net
parent20cfb7a04f0a8b7f8f45cf630e23524d51bb3cd9 (diff)
downloadlinux-6f5c39fa5cd4a78c5432021e981aa8f79437a32c.tar.gz
linux-6f5c39fa5cd4a78c5432021e981aa8f79437a32c.tar.bz2
linux-6f5c39fa5cd4a78c5432021e981aa8f79437a32c.zip
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 <tehnerd@fb.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Diffstat (limited to 'net')
-rw-r--r--net/core/filter.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/net/core/filter.c b/net/core/filter.c
index 00c711c5f1a2..afd825534ac4 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);