Skip to content

Commit

Permalink
xdp-dns: lpm trie for domain lookup
Browse files Browse the repository at this point in the history
if insert 6bpfire3net in LPM trie map

domain 3foo6bpfire3net will not match because only the
common suffix 6bpfire3net matches, LPM trie is for prefix
match, need to reverse the suffix to prefix, which is to
reverse the 6bpfire3net string and insert in LPM trie map

then reverse 3foo6bpfire3net and do LPM trie map lookup
which will match the common prefix with reversed 6bpfire3net

see more detail in

#1
#2
vincentmli/BPFire#36

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
  • Loading branch information
vincentmli committed Sep 10, 2024
1 parent 872c9b9 commit dcd807d
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 24 deletions.
60 changes: 40 additions & 20 deletions xdp-dns/xdp_dns.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,22 @@ struct meta_data {
__u16 unused;
};

/* Define the LPM Trie Map for domain names */
struct domain_key {
struct bpf_lpm_trie_key lpm_key;
char data[MAX_DOMAIN_SIZE + 1];
};

struct {
__uint(type, BPF_MAP_TYPE_HASH);
__type(key, char[MAX_DOMAIN_SIZE + 1]);
__uint(type, BPF_MAP_TYPE_LPM_TRIE);
__type(key, struct domain_key);
__type(value, __u8);
__uint(max_entries, 1024);
__uint(max_entries, 10000);
__uint(pinning, LIBBPF_PIN_BY_NAME);
__uint(map_flags, BPF_F_NO_PREALLOC);
} domain_denylist SEC(".maps");


/*
* Store the VLAN header
*/
Expand Down Expand Up @@ -191,6 +199,14 @@ static __always_inline __u8 custom_strlen(const char *str, struct cursor *c) {
return len;
}

static __always_inline void reverse_string(char *str, __u8 len) {
for (int i = 0; i < (len - 1) / 2; i++) {
char temp = str[i];
str[i] = str[len - 1 - i];
str[len - 1 - i] = temp;
}
}

SEC("xdp")
int xdp_dns(struct xdp_md *ctx)
{
Expand All @@ -201,9 +217,10 @@ int xdp_dns(struct xdp_md *ctx)
struct udphdr *udp;
struct dnshdr *dns;
char *qname;
// __u8 value = 1;
//__u8 value = 1;
__u8 len = 0;
char domain_key[MAX_DOMAIN_SIZE + 1 ] = {0}; // Buffer for map lookup

struct domain_key dkey = {0}; // LPM trie key

if (bpf_xdp_adjust_meta(ctx, -(int)sizeof(struct meta_data)))
return XDP_PASS;
Expand Down Expand Up @@ -246,26 +263,29 @@ int xdp_dns(struct xdp_md *ctx)
return XDP_ABORTED; // Return FORMERR?

int copy_len = len < MAX_DOMAIN_SIZE ? len : MAX_DOMAIN_SIZE;
custom_memcpy(domain_key, qname, copy_len);
domain_key[MAX_DOMAIN_SIZE] = '\0'; // Ensure null-termination
custom_memcpy(dkey.data, qname, copy_len);
dkey.data[MAX_DOMAIN_SIZE] = '\0'; // Ensure null-termination
reverse_string(dkey.data, copy_len);

// Set the LPM key prefix length (the length of the domain name string)
dkey.lpm_key.prefixlen = copy_len * 8; // Prefix length in bits

bpf_printk("domain_key %s copy_len is %d from %pI4", dkey.data, copy_len, &ipv4->saddr);

if (bpf_map_lookup_elem(&domain_denylist, &dkey)) {
bpf_printk("Domain %s found in denylist, dropping packet\n", dkey.data);
return XDP_DROP;
} else {
bpf_printk("Domain %s not found in denylist\n", dkey.data);
}

/*
bpf_printk("domain_key %s copy_len is %d from %pI4", domain_key, copy_len, &ipv4->saddr);
if (bpf_map_update_elem(&domain_denylist, &domain_key, &value, BPF_ANY) < 0) {
bpf_printk("Domain %s not updated in denylist\n", domain_key);
if (bpf_map_update_elem(&domain_denylist, &dkey, &value, BPF_ANY) < 0) {
bpf_printk("Domain %s not updated in denylist\n", dkey.data);
} else {
bpf_printk("Domain %s updated in denylist\n", domain_key);
bpf_printk("Domain %s updated in denylist\n", dkey.data);
}
*/
if (bpf_map_lookup_elem(&domain_denylist, domain_key)) {
bpf_printk("Domain %s found in denylist, dropping packet\n", domain_key);
return XDP_DROP;
}
else {
bpf_printk("Domain %s not found in denylist\n", domain_key);
}

break;
}
Expand Down
26 changes: 22 additions & 4 deletions xdp-dns/xdp_dns.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@
#include <errno.h>
#include <stdlib.h>

#define MAX_DOMAIN_SIZE 128 // Increased size to handle larger domains
#define MAX_DOMAIN_SIZE 18 // Increased size to handle larger domains

struct domain_key {
struct bpf_lpm_trie_key lpm_key;
char data[MAX_DOMAIN_SIZE + 1];
};

// Function to encode a domain name with label lengths
static void encode_domain(const char *domain, char *encoded) {
Expand Down Expand Up @@ -33,9 +38,18 @@ static void encode_domain(const char *domain, char *encoded) {
*enc_ptr++ = 0;
}

static void reverse_string(char *str) {
int len = strlen(str);
for (int i = 0; i < len / 2; i++) {
char temp = str[i];
str[i] = str[len - i - 1];
str[len - i - 1] = temp;
}
}

int main(int argc, char *argv[]) {
int map_fd;
char domain_key[MAX_DOMAIN_SIZE + 1] = {0};
struct domain_key dkey = {0};
__u8 value = 1;

// Check for proper number of arguments
Expand All @@ -45,7 +59,11 @@ int main(int argc, char *argv[]) {
}

// Encode the domain name with label lengths
encode_domain(argv[1], domain_key);
encode_domain(argv[1], dkey.data);
reverse_string(dkey.data);

// Set the LPM trie key prefix length
dkey.lpm_key.prefixlen = strlen(dkey.data) * 8;

// Open the BPF map
map_fd = bpf_obj_get("/sys/fs/bpf/xdp-dns/domain_denylist");
Expand All @@ -55,7 +73,7 @@ int main(int argc, char *argv[]) {
}

// Update the map with the encoded domain name
if (bpf_map_update_elem(map_fd, domain_key, &value, BPF_ANY) != 0) {
if (bpf_map_update_elem(map_fd, &dkey, &value, BPF_ANY) != 0) {
fprintf(stderr, "Failed to update map: %s\n", strerror(errno));
return 1;
}
Expand Down

0 comments on commit dcd807d

Please sign in to comment.