/*
 * DNS redirect preload library for headless MITM interception.
 *
 * Hooks getaddrinfo() via LD_PRELOAD to redirect Google API domain
 * resolution to 127.0.0.1, so the LS connects to our local MITM proxy
 * instead of the real Google servers.
 *
 * This works because the LS binary (Go + CGO) uses libc's getaddrinfo()
 * for DNS resolution, even though it uses raw syscalls for connect().
 *
 * Build: gcc -shared -fPIC -o dns_redirect.so dns_redirect.c -ldl
 *
 * Environment variables:
 *   DNS_REDIRECT_LOG — optional path to log redirected lookups
 *
 * The list of redirected domains is compiled in. Only exact matches
 * are redirected; all other lookups pass through to the real resolver.
 */
#define _GNU_SOURCE
#include <dlfcn.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

/* Google API domains whose DNS resolution should be redirected to 127.0.0.1 */
static const char *REDIRECT_DOMAINS[] = {
    "daily-cloudcode-pa.googleapis.com",
    "cloudcode-pa.googleapis.com",
    "autopush-cloudcode-pa.googleapis.com",
    NULL
};

typedef int (*getaddrinfo_t)(const char *, const char *,
                             const struct addrinfo *, struct addrinfo **);

static int should_redirect(const char *host) {
    if (!host) return 0;
    for (int i = 0; REDIRECT_DOMAINS[i]; i++) {
        if (strcmp(host, REDIRECT_DOMAINS[i]) == 0) return 1;
    }
    return 0;
}

int getaddrinfo(const char *node, const char *service,
                const struct addrinfo *hints, struct addrinfo **res) {
    getaddrinfo_t real_getaddrinfo =
        (getaddrinfo_t)dlsym(RTLD_NEXT, "getaddrinfo");

    if (should_redirect(node)) {
        /* Optional logging */
        const char *log_path = getenv("DNS_REDIRECT_LOG");
        if (log_path) {
            int fd = open(log_path, O_WRONLY | O_CREAT | O_APPEND, 0666);
            if (fd >= 0) {
                char buf[256];
                int len = snprintf(buf, sizeof(buf),
                    "[dns_redirect] %s -> 127.0.0.1\n", node);
                write(fd, buf, len);
                close(fd);
            }
        }

        /* Resolve to localhost — the MITM proxy is listening there */
        return real_getaddrinfo("127.0.0.1", service, hints, res);
    }

    return real_getaddrinfo(node, service, hints, res);
}
