[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20190828072250.29828-7-jakub@cloudflare.com>
Date: Wed, 28 Aug 2019 09:22:44 +0200
From: Jakub Sitnicki <jakub@...udflare.com>
To: bpf@...r.kernel.org, netdev@...r.kernel.org
Cc: kernel-team@...udflare.com, Lorenz Bauer <lmb@...udflare.com>,
Marek Majkowski <marek@...udflare.com>
Subject: [RFCv2 bpf-next 06/12] inet: Run inet_lookup bpf program on socket lookup
Run a BPF program before looking up the listening socket. The program can
redirect the skb to a listening socket of its choice, providing it calls
bpf_redirect_lookup() helper and returns BPF_REDIRECT.
This lets the user-space program mappings between packet 4-tuple and
listening sockets. With the possibility to override the socket lookup from
BPF, applications don't need to bind sockets to every addresses they
receive on, or resort to listening on all addresses with INADDR_ANY.
Also port sharing conflicts become a non-issue. Application can listen on
any free port and still receive traffic destined to its assigned service
port.
Suggested-by: Marek Majkowski <marek@...udflare.com>
Reviewed-by: Lorenz Bauer <lmb@...udflare.com>
Signed-off-by: Jakub Sitnicki <jakub@...udflare.com>
---
include/net/inet_hashtables.h | 33 +++++++++++++++++++++++++++++++++
net/ipv4/inet_hashtables.c | 5 +++++
2 files changed, 38 insertions(+)
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index b2d43ee72dc1..c9c7efb961cb 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -417,4 +417,37 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
int inet_hash_connect(struct inet_timewait_death_row *death_row,
struct sock *sk);
+
+static inline struct sock *__inet_lookup_run_bpf(const struct net *net,
+ struct bpf_inet_lookup_kern *ctx)
+{
+ struct bpf_prog *prog;
+ int ret = BPF_OK;
+
+ rcu_read_lock();
+ prog = rcu_dereference(net->inet_lookup_prog);
+ if (prog)
+ ret = BPF_PROG_RUN(prog, ctx);
+ rcu_read_unlock();
+
+ return ret == BPF_REDIRECT ? ctx->redir_sk : NULL;
+}
+
+static inline struct sock *inet_lookup_run_bpf(const struct net *net, u8 proto,
+ __be32 saddr, __be16 sport,
+ __be32 daddr,
+ unsigned short hnum)
+{
+ struct bpf_inet_lookup_kern ctx = {
+ .family = AF_INET,
+ .protocol = proto,
+ .saddr = saddr,
+ .sport = sport,
+ .daddr = daddr,
+ .hnum = hnum,
+ };
+
+ return __inet_lookup_run_bpf(net, &ctx);
+}
+
#endif /* _INET_HASHTABLES_H */
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index 97824864e40d..ab6d89c27c94 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -299,6 +299,11 @@ struct sock *__inet_lookup_listener(struct net *net,
struct sock *result = NULL;
unsigned int hash2;
+ result = inet_lookup_run_bpf(net, hashinfo->protocol,
+ saddr, sport, daddr, hnum);
+ if (result)
+ goto done;
+
hash2 = ipv4_portaddr_hash(net, daddr, hnum);
ilb2 = inet_lhash2_bucket(hashinfo, hash2);
--
2.20.1
Powered by blists - more mailing lists