Skip to content

Commit

Permalink
Only answer packets to IPs on the used interface
Browse files Browse the repository at this point in the history
  • Loading branch information
mozzieongit committed Aug 19, 2024
1 parent 325f8e3 commit 22ccd92
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 1 deletion.
104 changes: 103 additions & 1 deletion xdp-server.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@
#include <linux/udp.h>
#include <net/if.h>

#include <arpa/inet.h>
#include <netdb.h>
#include <ifaddrs.h>
#include <linux/if_link.h>

#include "query.h"
#include "dns.h"
#include "util.h"
Expand Down Expand Up @@ -101,6 +106,11 @@ static int load_xdp_program_and_map(struct xdp_server *xdp);

static int unload_xdp_program(struct xdp_server *xdp);

/*
* Figure out IP addresses to listen to.
*/
static int figure_ip_addresses(struct xdp_server *xdp);

/*
* Setup XDP sockets
*/
Expand Down Expand Up @@ -427,6 +437,9 @@ int xdp_server_init(struct xdp_server *xdp) {
umem_ptrs[i].len = 0;
}

if (!xdp->ip_addresses)
figure_ip_addresses(xdp);

return 0;
}

Expand Down Expand Up @@ -466,6 +479,90 @@ static int unload_xdp_program(struct xdp_server *xdp) {
return ret;
}

static int dest_ip_allowed6(struct xdp_server *xdp, struct ipv6hdr *ipv6) {
struct xdp_ip_address *ip = xdp->ip_addresses;
if (!ip)
// no IPs available, allowing all
return 1;

while (ip) {
if (!memcmp(&((struct sockaddr_in6 *) &ip->addr)->sin6_addr,
&ipv6->daddr,
sizeof(struct in6_addr)))
return 1;
ip = ip->next;
}

return 0;
}

static int dest_ip_allowed4(struct xdp_server *xdp, struct iphdr *ipv4) {
struct xdp_ip_address *ip = xdp->ip_addresses;
if (!ip)
// no IPs available, allowing all
return 1;

while (ip) {
if (ipv4->daddr == ((struct sockaddr_in *) &ip->addr)->sin_addr.s_addr)
return 1;
ip = ip->next;
}

return 0;
}

static void
add_ip_address(struct xdp_server *xdp, struct sockaddr_storage *addr) {
struct xdp_ip_address *ip = xdp->ip_addresses;
if (!ip) {
xdp->ip_addresses = region_alloc_zero(xdp->region,
sizeof(struct xdp_ip_address));
ip = xdp->ip_addresses;
} else {
while (ip->next)
ip = ip->next;

ip->next = region_alloc_zero(xdp->region,
sizeof(struct xdp_ip_address));
ip = ip->next;
}

memcpy(&ip->addr, addr, sizeof(struct sockaddr_storage));
}

static int figure_ip_addresses(struct xdp_server *xdp) {
struct ifaddrs *ifaddr;
int family, s, ret = 0;

if (getifaddrs(&ifaddr) == -1) {
log_msg(LOG_ERR, "xdp: couldn't determine local IP addresses. "
"Serving all IP addresses now");
return -1;
}

for (struct ifaddrs *ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == NULL)
continue;

if (strcmp(ifa->ifa_name, xdp->interface_name))
continue;

family = ifa->ifa_addr->sa_family;

switch (family) {
default:
continue;
case AF_INET:
case AF_INET6:
add_ip_address(xdp, (struct sockaddr_storage *) ifa->ifa_addr);
}
}

out:
freeifaddrs(ifaddr);
return ret;
}

static inline void swap_eth(struct ethhdr *eth) {
uint8_t tmp_mac[ETH_ALEN];
memcpy(tmp_mac, eth->h_dest, ETH_ALEN);
Expand Down Expand Up @@ -568,7 +665,6 @@ process_packet(struct xdp_server *xdp, uint8_t *pkt, uint64_t addr,

data_before_dnshdr_len = sizeof(*eth) + sizeof(*udp);

/* TODO: implement only accepting IP traffic to actual server ip? */
switch (ntohs(eth->h_proto)) {
case ETH_P_IPV6: {
ipv6 = (struct ipv6hdr *)(eth + 1);
Expand All @@ -581,6 +677,9 @@ process_packet(struct xdp_server *xdp, uint8_t *pkt, uint64_t addr,
dnslen -= (sizeof(*eth) + sizeof(*ipv6) + sizeof(*udp));
data_before_dnshdr_len += sizeof(*ipv6);

if (!dest_ip_allowed6(xdp, ipv6))
return 0;

break;
} case ETH_P_IP: {
ipv4 = (struct iphdr *)(eth + 1);
Expand All @@ -591,6 +690,9 @@ process_packet(struct xdp_server *xdp, uint8_t *pkt, uint64_t addr,
dnslen -= (sizeof(*eth) + sizeof(*ipv4) + sizeof(*udp));
data_before_dnshdr_len += sizeof(*ipv4);

if (!dest_ip_allowed4(xdp, ipv4))
return 0;

break;
}

Expand Down
7 changes: 7 additions & 0 deletions xdp-server.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ struct xsk_socket_info {
uint32_t outstanding_tx;
};

struct xdp_ip_address {
struct xdp_ip_address *next;
struct sockaddr_storage addr;
};

struct xdp_server {
/* NSD global settings */
region_type *region;
Expand All @@ -63,6 +68,8 @@ struct xdp_server {
int queue_count;
uint32_t queue_index;

struct xdp_ip_address *ip_addresses;

struct query **queries;
void *nsd;

Expand Down

0 comments on commit 22ccd92

Please sign in to comment.