Following the ipv4 changes, run a BPF program attached to netns in context of which we're doing the socket lookup so that it can redirect the skb to a socket of its choice. The program runs before the listening socket lookup. Suggested-by: Marek Majkowski <marek@xxxxxxxxxxxxxx> Reviewed-by: Lorenz Bauer <lmb@xxxxxxxxxxxxxx> Signed-off-by: Jakub Sitnicki <jakub@xxxxxxxxxxxxxx> --- include/net/inet6_hashtables.h | 19 +++++++++++++++++++ net/ipv6/inet6_hashtables.c | 5 +++++ 2 files changed, 24 insertions(+) diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h index fe96bf247aac..c2393d148d8d 100644 --- a/include/net/inet6_hashtables.h +++ b/include/net/inet6_hashtables.h @@ -104,6 +104,25 @@ struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo, const int dif); int inet6_hash(struct sock *sk); + +static inline struct sock *inet6_lookup_run_bpf(struct net *net, u8 proto, + const struct in6_addr *saddr, + __be16 sport, + const struct in6_addr *daddr, + unsigned short hnum) +{ + struct bpf_inet_lookup_kern ctx = { + .family = AF_INET6, + .protocol = proto, + .saddr6 = *saddr, + .sport = sport, + .daddr6 = *daddr, + .hnum = hnum, + }; + + return __inet_lookup_run_bpf(net, &ctx); +} + #endif /* IS_ENABLED(CONFIG_IPV6) */ #define INET6_MATCH(__sk, __net, __saddr, __daddr, __ports, __dif, __sdif) \ diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c index cf60fae9533b..40dd0a3d80ed 100644 --- a/net/ipv6/inet6_hashtables.c +++ b/net/ipv6/inet6_hashtables.c @@ -157,6 +157,11 @@ struct sock *inet6_lookup_listener(struct net *net, struct sock *result = NULL; unsigned int hash2; + result = inet6_lookup_run_bpf(net, hashinfo->protocol, + saddr, sport, daddr, hnum); + if (result) + goto done; + hash2 = ipv6_portaddr_hash(net, daddr, hnum); ilb2 = inet_lhash2_bucket(hashinfo, hash2); -- 2.20.1