@@ -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 */
@@ -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);