diff --git a/xdp-dns/xdp_dns.bpf.c b/xdp-dns/xdp_dns.bpf.c
index 8339aeaa..77445c86 100644
--- a/xdp-dns/xdp_dns.bpf.c
+++ b/xdp-dns/xdp_dns.bpf.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2021, NLnet Labs. All rights reserved.
+ * Copyright (c) 2024, BPFire. All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -40,7 +41,7 @@
// do not use libc includes because this causes clang
// to include 32bit headers on 64bit ( only ) systems.
#define memcpy __builtin_memcpy
-#define MAX_DOMAIN_SIZE 18
+#define MAX_DOMAIN_SIZE 128
struct meta_data {
__u16 eth_proto;
@@ -49,14 +50,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
*/
@@ -191,8 +200,16 @@ 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)
+int xdp_dns_denylist(struct xdp_md *ctx)
{
struct meta_data *md = (void *)(long)ctx->data_meta;
struct cursor c;
@@ -201,9 +218,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;
@@ -246,26 +264,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;
}
diff --git a/xdp-dns/xdp_dns.c b/xdp-dns/xdp_dns.c
index 666aea6a..5ecd3b9f 100644
--- a/xdp-dns/xdp_dns.c
+++ b/xdp-dns/xdp_dns.c
@@ -1,3 +1,20 @@
+/*
+ * Copyright (c) 2024, BPFire. All rights reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
#include
#include
#include
@@ -7,6 +24,11 @@
#define MAX_DOMAIN_SIZE 128 // 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) {
const char *ptr = domain;
@@ -33,9 +55,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
@@ -45,7 +76,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");
@@ -55,7 +90,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;
}