Skip to content

Commit

Permalink
xdp-filter: Parse IPv6 neighbour solicitations
Browse files Browse the repository at this point in the history
Like with ARP packets for IPv4, make sure we pass neighbour
solicitations and advertisements through the filter rules for IPv6, to
avoid connectivity breaking in deny-all mode.

Signed-off-by: Toke Høiland-Jørgensen <[email protected]>
  • Loading branch information
tohojo committed Feb 10, 2025
1 parent ec85f96 commit 38e9966
Showing 1 changed file with 35 additions and 8 deletions.
43 changes: 35 additions & 8 deletions xdp-filter/xdpfilt_prog.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
#include <bpf/bpf_helpers.h>
#include <xdp/xdp_helpers.h>

#define NDISC_NEIGHBOUR_SOLICITATION 135
#define NDISC_NEIGHBOUR_ADVERTISEMENT 136

#include "common_kern_user.h"

/* Defines xdp_stats_map */
Expand Down Expand Up @@ -146,22 +149,26 @@ struct {
__uint(pinning, LIBBPF_PIN_BY_NAME);
} MAP_NAME_IPV6 SEC(".maps");

static int __always_inline lookup_verdict_ipv6(struct ipv6hdr *ipv6hdr)
static int __always_inline lookup_verdict_ipv6(struct in6_addr *src_addr, struct in6_addr *dst_addr)
{
struct in6_addr addr;

addr = ipv6hdr->daddr;
CHECK_MAP(&filter_ipv6, &addr, MAP_FLAG_DST);
addr = ipv6hdr->saddr;
CHECK_MAP(&filter_ipv6, &addr, MAP_FLAG_SRC);
if (dst_addr) {
addr = *dst_addr;
CHECK_MAP(&filter_ipv6, &addr, MAP_FLAG_DST);
}
if (src_addr) {
addr = *src_addr;
CHECK_MAP(&filter_ipv6, &addr, MAP_FLAG_SRC);
}
return VERDICT_MISS;
}

#define CHECK_VERDICT_IPV6(param) CHECK_VERDICT(ipv6, param)
#define CHECK_VERDICT_IPV6(src, dst) CHECK_VERDICT_2(ipv6, src, dst)
#define FEATURE_IPV6 FEAT_IPV6
#else
#define FEATURE_IPV6 0
#define CHECK_VERDICT_IPV6(param)
#define CHECK_VERDICT_IPV6(src, dst)
#endif /* FILT_MODE_IPV6 */

#ifdef FILT_MODE_ETHERNET
Expand Down Expand Up @@ -221,6 +228,7 @@ int FUNCNAME(struct xdp_md *ctx)

#if defined(FILT_MODE_IPV4) || defined(FILT_MODE_IPV6) || \
defined(FILT_MODE_TCP) || defined(FILT_MODE_UDP)
struct icmp6hdr *icmp6hdr;
struct ipv6hdr *ipv6hdr;
struct arphdr *arphdr;
struct iphdr *iphdr;
Expand All @@ -247,7 +255,26 @@ int FUNCNAME(struct xdp_md *ctx)
ip_type = parse_ip6hdr(&nh, data_end, &ipv6hdr);
CHECK_RET(ip_type);

CHECK_VERDICT_IPV6(ipv6hdr);
CHECK_VERDICT_IPV6(&ipv6hdr->saddr, &ipv6hdr->daddr);

if (ip_type == IPPROTO_ICMPV6) {
nh_op = parse_icmp6hdr(&nh, data_end, &icmp6hdr);
CHECK_RET(nh_op);

if (nh_op == NDISC_NEIGHBOUR_SOLICITATION ||
nh_op == NDISC_NEIGHBOUR_ADVERTISEMENT) {
struct in6_addr *addr = nh.pos;

if (addr + 1 > data_end) {
action = XDP_ABORTED;
goto out;
}
if (nh_op == NDISC_NEIGHBOUR_SOLICITATION)
CHECK_VERDICT_IPV6(NULL, addr);
else
CHECK_VERDICT_IPV6(addr, NULL);
}
}
} else {
goto out;
}
Expand Down

0 comments on commit 38e9966

Please sign in to comment.