~samiam/MaraDNS

ce6070d6ff7ea13d4eaa2f185e49e332a614d956 — Sam Trenholme a month ago ab89ecc
mmLunacyDNS: Removing completely.

Anyone who wants mmLunacyDNS can download MaraDNS 3.5.0014.
10 files changed, 0 insertions(+), 887 deletions(-)

D deadwood-github/tools/mmLunacyDNS/README.md
D deadwood-github/tools/mmLunacyDNS/clean.sh
D deadwood-github/tools/mmLunacyDNS/compile.mmLunacyDNS.sh
D deadwood-github/tools/mmLunacyDNS/compile.win32.service.sh
D deadwood-github/tools/mmLunacyDNS/lauxlib.h
D deadwood-github/tools/mmLunacyDNS/lua.h
D deadwood-github/tools/mmLunacyDNS/luaconf.h
D deadwood-github/tools/mmLunacyDNS/lualib.h
D deadwood-github/tools/mmLunacyDNS/mmLunacyDNS.c
D deadwood-github/tools/mmLunacyDNS/mmLunacyDNS.lua
D deadwood-github/tools/mmLunacyDNS/README.md => deadwood-github/tools/mmLunacyDNS/README.md +0 -19
@@ 1,19 0,0 @@
# THIS CODE IS DEPRECATED

mmLunacyDNS is deprecated and no longer supported.  I am only
keeping the code here for historical purposes, and may remove it
at a future time.  Anyone using mmLunacyDNS should use coLunacyDNS
instead, which is fully tested, supported, and stable.

# DO NOT USE THIS CODE

# mmLunacyDNS

mmLunacyDNS was a simple DNS server configured with Lunacy, my fork of
Lua 5.1 (the syntax is the same).  This server can only either ignore
DNS queries or reply with "A" (IPv4 IP DNS record) replies.
coLunacyDNS, on the other hand, can send “not there” responses,
query other DNS servers for records, send “server fail” replies,
and has both IPv4 and IPv6 support (mmLunacyDNS is IPv4 only).

Use coLunacyDNS instead.

D deadwood-github/tools/mmLunacyDNS/clean.sh => deadwood-github/tools/mmLunacyDNS/clean.sh +0 -11
@@ 1,11 0,0 @@
#!/bin/sh

# Clean up
rm -f *.o *.exe mmLunacyDNS

# Win32 build env has no symlinks
rm -f lauxlib.h lua.h luaconf.h lualib.h
for a in lauxlib.h lua.h luaconf.h lualib.h ; do
        ln -s ../../lunacy/$a $a
done


D deadwood-github/tools/mmLunacyDNS/compile.mmLunacyDNS.sh => deadwood-github/tools/mmLunacyDNS/compile.mmLunacyDNS.sh +0 -9
@@ 1,9 0,0 @@
#!/bin/sh

# With only one file, I will not bother with a Makefile

cd ../../lunacy/
make 
cd ../tools/mmLunacyDNS/
gcc -Os -c -o mmLunacyDNS.o mmLunacyDNS.c
gcc -Os -o mmLunacyDNS mmLunacyDNS.o ../../lunacy/liblua.a -lm

D deadwood-github/tools/mmLunacyDNS/compile.win32.service.sh => deadwood-github/tools/mmLunacyDNS/compile.win32.service.sh +0 -19
@@ 1,19 0,0 @@
#!/bin/sh

if [ ! -e /mingw ] ; then
	echo Only run this in Mingw
	exit 1
fi

# No symlinks
rm -f lauxlib.h lua.h luaconf.h lualib.h

for a in lauxlib.h lua.h luaconf.h lualib.h ; do
	cp ../../lunacy/$a .
done

cd ../../lunacy/
make
cd ../tools/mmLunacyDNS/
gcc -Os -DMINGW -c -o mmLunacyDNS.o mmLunacyDNS.c
gcc -Os -o mmLunacyDNS mmLunacyDNS.o ../../lunacy/liblua.a -lm -lwsock32

D deadwood-github/tools/mmLunacyDNS/lauxlib.h => deadwood-github/tools/mmLunacyDNS/lauxlib.h +0 -1
@@ 1,1 0,0 @@
../../lunacy/lauxlib.h
\ No newline at end of file

D deadwood-github/tools/mmLunacyDNS/lua.h => deadwood-github/tools/mmLunacyDNS/lua.h +0 -1
@@ 1,1 0,0 @@
../../lunacy/lua.h
\ No newline at end of file

D deadwood-github/tools/mmLunacyDNS/luaconf.h => deadwood-github/tools/mmLunacyDNS/luaconf.h +0 -1
@@ 1,1 0,0 @@
../../lunacy/luaconf.h
\ No newline at end of file

D deadwood-github/tools/mmLunacyDNS/lualib.h => deadwood-github/tools/mmLunacyDNS/lualib.h +0 -1
@@ 1,1 0,0 @@
../../lunacy/lualib.h
\ No newline at end of file

D deadwood-github/tools/mmLunacyDNS/mmLunacyDNS.c => deadwood-github/tools/mmLunacyDNS/mmLunacyDNS.c +0 -811
@@ 1,811 0,0 @@
/* Copyright (c) 2009-2020 Sam Trenholme
 *
 * TERMS
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * This software is provided 'as is' with no guarantees of correctness or
 * fitness for purpose.
 *
 * This software links to Lunacy, a fork of Lua 5.1
 * Lua license is in the file COPYING
 */

/* mmLunacyDNS: A tiny DNS server which uses Lua for configuration and
 * for the main loop.  This is Lunacy, a fork of Lua 5.1, and it's
 * embedded in the compiled binary
 */

#include <stdint.h>
#ifdef MINGW
#include <winsock.h>
#include <wininet.h>
#include <wincrypt.h>
#ifndef FD_SETSIZE
#define FD_SETSIZE 512
#endif /* FD_SETSIZE */
#include <winsock.h>
#include <wininet.h>
#define socklen_t int32_t
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif /* MINGW */
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>

/* Luancy stuff */
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"

/* We use a special SOCKET type for easier Windows porting */
#ifndef MINGW
#define SOCKET int
#endif

/* Log a message */
#ifndef MINGW
void log_it(char *message) {
        if(message != NULL) {
                puts(message);
        }
}
#else /* MINGW */
FILE *LOG = 0;
int isInteractive = 0;
void log_it(char *message) {
        SYSTEMTIME t;
        char d[256];
        char h[256];
        if(isInteractive == 1) {
                puts(message);
                return;
        }
        if(LOG == 0) {
                return;
        }
        GetLocalTime(&t);
        GetDateFormat(LOCALE_SYSTEM_DEFAULT, DATE_LONGDATE, &t,
                NULL, d, 250);
        GetTimeFormat(LOCALE_SYSTEM_DEFAULT, TIME_FORCE24HOURFORMAT, &t,
                NULL, h, 250);
        fprintf(LOG,"%s %s: ",d,h);
        if(message != NULL) {
                fprintf(LOG,"%s\n",message);
        } else {
                fprintf(LOG,"NULL string\n",message);
        }
        fflush(LOG);
}
#endif /* MINGW */


/* Set this to 0 to stop the server */
int serverRunning = 1;

/* This is the header placed before the 4-byte IP; we change the last four
 * bytes to set the IP we give out in replies */
char p[17] =
"\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x00\x00\x04\x7f\x7f\x7f\x7f";

/* Set the IP we send in response to DNS queries */
uint32_t set_return_ip(char *returnIp) {
        uint32_t ip;

        if(returnIp == NULL) {
                returnIp = "127.0.0.1";
        }
        /* Set the IP we give everyone */
        ip = inet_addr(returnIp);
        ip = ntohl(ip);
        p[12] = (ip & 0xff000000) >> 24;
        p[13] = (ip & 0x00ff0000) >> 16;
        p[14] = (ip & 0x0000ff00) >>  8;
        p[15] = (ip & 0x000000ff);
        return ip;
}

/* Convert a NULL-terminated string like "10.1.2.3" in to an IP */
uint32_t get_ip(char *stringIp) {
        uint32_t ip = 0;
        /* Set the IP we bind to (default is "0", which means "all IPs) */
        if(stringIp != NULL) {
                ip = inet_addr(stringIp);
        }
        /* Return the IP we bind to */
        return ip;
}

#ifdef MINGW
void windows_socket_start() {
        WSADATA wsaData;
        WORD wVersionRequested = MAKEWORD(2,2);
        WSAStartup( wVersionRequested, &wsaData);
}
#endif /* MINGW */

/* Get port: Get a port locally and return the socket the port is on */
SOCKET get_port(uint32_t ip, struct sockaddr_in *dns_udp) {
        SOCKET sock;
        int len_inet;
        struct timeval noblock;
        noblock.tv_sec = 1;
        noblock.tv_usec = 0;

        /* Bind to port 53 */
#ifdef MINGW
        windows_socket_start();
#endif /* MINGW */
        sock = socket(AF_INET,SOCK_DGRAM,0);
        if(sock == -1) {
                perror("socket error");
                exit(0);
        }
#ifdef MINGW
        setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
                (char *)&noblock, sizeof(struct timeval));
#endif /* MINGW */
        memset(dns_udp,0,sizeof(struct sockaddr_in));
        dns_udp->sin_family = AF_INET;
        dns_udp->sin_port = htons(53);
        dns_udp->sin_addr.s_addr = ip;
        if(dns_udp->sin_addr.s_addr == INADDR_NONE) {
                log_it("Problem with bind IP");
                exit(0);
        }
        len_inet = sizeof(struct sockaddr_in);
        if(bind(sock,(struct sockaddr *)dns_udp,len_inet) == -1) {
                perror("bind error");
#ifdef MINGW
                printf("WSAGetLastError code: %d\n",WSAGetLastError());
#endif /* MINGW */
                exit(0);
        }

        /* Linux kernel bug */
        /* fcntl(sock, F_SETFL, O_NONBLOCK); */

        return sock;
}

static int mmDNS_log (lua_State *L) {
        const char *message = luaL_checkstring(L,1);
        log_it((char *)message);
        return 0;
}

static const luaL_Reg mmDNSlib[] = {
        {"log", mmDNS_log},
        {NULL, NULL}
};

lua_State *init_lua(char *fileName) {
        char useFilename[512];
        lua_State *L = luaL_newstate(); // Initialize Lua
        // Add string, math, and bit32.
        // Don't add everything (io, lfs, etc. allow filesystem access)
        lua_pushcfunction(L, luaopen_string);
        lua_pushstring(L, "string");
        lua_call(L, 1, 0);
        lua_pushcfunction(L, luaopen_math);
        lua_pushstring(L, "math");
        lua_call(L, 1, 0);
        lua_pushcfunction(L, luaopen_bit32);
        lua_pushstring(L, "bit32");
        lua_call(L, 1, 0);
        luaL_register(L, "mmDNS", mmDNSlib);

        /* The filename we use is {executable name}.lua.
         * {executable name} is the name this is being called as,
         * usually mmLunacyDNS (or mmLunacyDNS.exe in Windows).
         * This way, if we want multiple Lua configuration files for
         * different use cases, we simple copy the binary (or link
         * to it) to make it use a different .lua configuration file.
         */
        if(fileName != NULL && *fileName != 0) {
                int a;
                int lastDot = 505;
                // Find the final '.' in the executable name
                for(a = 0; a < 500; a++) {
                        if(fileName[a] == 0) {
                                break;
                        }
                        if(fileName[a] == '.') {
                                lastDot = a;
                        }
                        if(fileName[a] == '/' || fileName[a] == 92) {
                                lastDot = 505;
                        }
                }
                for(a = 0; a < 500; a++) {
                        useFilename[a] = *fileName;
                        if(*fileName == 0 || a >= lastDot) {
                                break;
                        }
                        fileName++;
                }
                useFilename[a] = '.'; a++;
                useFilename[a] = 'l'; a++;
                useFilename[a] = 'u'; a++;
                useFilename[a] = 'a'; a++;
                useFilename[a] = 0;
        } else {
                // Yes, it is possible to make argv[0] null
                strcpy(useFilename,"mmLunacyDNS.lua");
        }

        // Open and parse the .lua file
        if(luaL_loadfile(L, useFilename) == 0) {
                if(lua_pcall(L, 0, 0, 0) != 0) {
                        log_it("Unable to parse lua file with name:");
                        log_it(useFilename);
                        log_it((char *)lua_tostring(L,-1));
                        return NULL;
                }
        } else {
                log_it("Unable to open lua file with name:");
                log_it(useFilename);
                log_it((char *)lua_tostring(L,-1));
                return NULL;
        }
        return L;
}

/* Convert a raw over-the-wire DNS name (in) in to a human-readable
 * name.  Anything that is not [A-Za-z0-9\-\_] is converted in to {hex}
 * where "hex" is a hex number
 */
int humanDNSname(char *in, char *out, int max) {
        int labelLen = 0;
        int inPoint = 0;
        int outPoint = 0;
        labelLen = in[inPoint];
        while(labelLen > 0) {
                char see = 0;
                if(inPoint >= max || outPoint >= max) {
                        return -1;
                }
                inPoint++;
                see = in[inPoint];
                if((see >= '0' && see <= '9') ||
                   (see >= 'a' && see <= 'z') ||
                   (see >= 'A' && see <= 'Z') ||
                    see == '-' || see == '_') {
                        if(outPoint >= max) {return -1;}
                        out[outPoint] = see;
                        outPoint++;
                } else { // Hex escape of anything not "safe"
                        int left = (see >> 4) & 15;
                        int right = see & 15;
                        if(outPoint + 5 >= max) {return -1;}
                        out[outPoint] = '{'; outPoint++;
                        if(left < 10) {
                                out[outPoint] = '0' + left;
                        } else {
                                out[outPoint] = 'a' + (left - 10);
                        }
                        outPoint++;
                        if(right < 10) {
                                out[outPoint] = '0' + right;
                        } else {
                                out[outPoint] = 'a' + (right - 10);
                        }
                        outPoint++;
                        out[outPoint] = '}'; outPoint++;
                }
                labelLen--;
                if(labelLen == 0) {
                        inPoint++;
                        labelLen = in[inPoint];
                        if(outPoint >= max) {return -1;}
                        out[outPoint] = '.';
                        outPoint++;
                }
        }
        if(outPoint >= max) {return -1;}
        out[outPoint] = 0;
        return inPoint;
}


/* Give a Lua state, which is the file 'config.lua' read, run the
 * server */
void runServer(lua_State *L) {
        int a, len_inet;
        SOCKET sock;
        char in[515];
        socklen_t lenthing = sizeof(in);
        struct sockaddr_in dns_udp;
        uint32_t ip = 0; /* 0.0.0.0; default bind IP */
        int leni = sizeof(struct sockaddr);

        // Get bindIp from the Lua program
        lua_getglobal(L,"bindIp"); // Push "bindIp" on to stack
        if(lua_type(L, -1) == LUA_TSTRING) {
                char *bindIp;
                bindIp = (char *)lua_tostring(L, -1);
                ip = get_ip(bindIp);
        } else {
                log_it("Unable to get bindIp; using 0.0.0.0");
        }
        lua_pop(L, 1); // Remove result from stack, restoring the stack

        sock = get_port(ip,&dns_udp);

        log_it("Running mmLunacyDNS");

        /* Now that we know the IP and are on port 53, process incoming
         * DNS requests */
        while(serverRunning == 1) {
                char query[500];
                int qLen = -1;
                uint32_t fromIp; /* Who sent us a query */
                char fromString[128]; /* String of sending IP */
                /* Get data from UDP port 53 */
                len_inet = recvfrom(sock,in,255,0,(struct sockaddr *)&dns_udp,
                        &lenthing);
                /* Roy Arends check: We only answer questions */
                if(len_inet < 3 || (in[2] & 0x80) != 0x00) {
                        continue;
                }
                // IPv6 support is left as an exercise for the reader
                if(dns_udp.sin_family != AF_INET) {
                        continue;
                }
                fromIp = dns_udp.sin_addr.s_addr;
                fromIp = ntohl(fromIp);
                snprintf(fromString,120,"%d.%d.%d.%d",fromIp >> 24,
                        (fromIp & 0xff0000) >> 16,
                        (fromIp & 0xff00) >> 8,
                        fromIp & 0xff);

                /* Prepare the reply */
                if(len_inet > 12 && in[5] == 1) {
                        /* Make this an answer */
                        in[2] |= 0x80;
                        in[7]++;
                        in[11] = 0; // Ignore EDNS
                }
                qLen = humanDNSname(in + 12, query, 490);
                if(qLen > 0) {
                        int qType = -1;
                        qType = (in[13 + qLen] * 256) + in[14 + qLen];
                        lua_getglobal(L, "processQuery");

                        // Function input is a table, which I will call "t"
                        lua_newtable(L);

                        // t["mmQuery"] = query, where "query" is the
                        // dns query made (with a trailing dot), such
                        // as "caulixtla.com." or "lua.org."
                        lua_pushstring(L,"mmQuery");
                        lua_pushstring(L,query);
                        lua_settable(L, -3);

                        // t["mmQtype"] is a number with the query type
                        lua_pushstring(L,"mmQtype");
                        lua_pushinteger(L,(lua_Integer)qType);
                        lua_settable(L, -3);

                        // t["mmFromIP"] is the IP the query came from,
                        // in the form of a human-readable string
                        lua_pushstring(L,"mmFromIP");
                        lua_pushstring(L,fromString);
                        lua_settable(L, -3);

                        // t["mmFromIPtype"] is a number with the number
                        // 4, for IPv4
                        lua_pushstring(L,"mmFromIPtype");
                        lua_pushinteger(L,(lua_Integer)4);
                        lua_settable(L, -3);

                        if (lua_pcall(L, 1, 1, 0) == 0) {
                                const char *rs;
                                // Pull mmType from return table
                                rs = NULL;
                                if(lua_type(L, -1) == LUA_TTABLE) {
                                        lua_getfield(L, -1, "mm1Type");
                                        if(lua_type(L, -1) == LUA_TSTRING) {
                                                rs = luaL_checkstring(L, -1);
					}
                                        if(rs == NULL) {
						lua_pop(L, 1); // t.mm1Type
					}
                                }
                                if(rs != NULL && rs[0] == 'A' && rs[1] == 0) {
                                        lua_pop(L, 1); // t.mm1Type
                                        lua_getfield(L, -1, "mm1Data");
                                        if(lua_type(L, -1) == LUA_TSTRING) {
                                                rs = luaL_checkstring(L, -1);                                           } else {
                                                lua_pop(L, 1); // t.mm1Data
                                                rs = NULL;
                                        }
                                } else if(rs != NULL) {
                                        lua_pop(L, 1); // t.mm1Type
                                        rs = NULL;
                                }
                                if(rs != NULL) {
                                        set_return_ip((char *)rs);
                                        len_inet = 17 + qLen;
                                        for(a=0;a<16;a++) {
                                                in[len_inet + a] = p[a];
                                        }

                                        /* Send the reply */
                                        sendto(sock,in,len_inet + 16,0,
                                            (struct sockaddr *)&dns_udp, leni);
                                        lua_pop(L, 1); // t.mm1Data
                                }
				lua_pop(L, 1); // processQuery return table
                        } else {
                                log_it("Error calling function processQuery");
                                log_it((char *)lua_tostring(L, -1));
                        }
                }
        }
}

#ifndef MINGW
int main(int argc, char **argv) {
        lua_State *L;
        char *look;
	int a;

	// Key the random hash compression seed
	char noise[10];
	FILE *rfile = NULL;
	rfile = fopen("/dev/urandom","rb");
	if(rfile == NULL) {
		log_it("You do not have /dev/urandom");
		log_it("I refuse to run under these conditions");
		exit(1);
	}
	for(a=0;a<8;a++) {
		int b;
		b = getc(rfile);
		noise[a] = b;
	}
	noise[8] = 0;
	uint32_t sipHashLeft = 0, sipHashRight = 0;
	for(a = 0; a < 4; a++) {
		sipHashLeft <<= 8;
		sipHashLeft ^= noise[a];
	}
	for(a = 4; a < 8; a++) {
		sipHashRight <<= 8;
		sipHashRight ^= noise[a];
	}
	SipHashSetKey(sipHashLeft, sipHashRight);

        printf("mmLunacyDNS version 2020-08-12 starting\n\n");
        // Get bindIp and returnIp from Lua script
        if(argc == 1) {
                log_it("Only debug (interactive) mode supported.");
                log_it("Running as a daemon not supported yet.");
                log_it("Usage: mmLunacyDNS -d {config file}");
                return 1;
        }
        look = argv[1];
        if(look == 0) {
                log_it("Error getting command line args.");
                return 1;
        }
        if(look[0] != '-' || look[1] != 'd') {
                log_it("Only debug (interactive) mode supported.");
                log_it("Running as a daemon not supported yet.");
                log_it("Usage: mmLunacyDNS -d {config file}");
                return 1;
        }
        if(argc == 2) {
                L = init_lua(argv[0]); // Initialize Lua
        } else if(argc == 3) {
                L = init_lua(argv[2]); // Initialize Lua
        } else {
                log_it("Only debug (interactive) mode supported.");
                log_it("Running as a daemon not supported yet.");
                log_it("Usage: mmLunacyDNS -d {config file}");
                return 1;
        }
        if(L == NULL) {
                log_it("Fatal error opening lua config file");
                return 1;
        }
        runServer(L);
}
#else /* MINGW */

/* This program is a Windows service; I would like to thank Steve Friedl who
   put a public domain simple Windows service on his web site at unixwiz.net;
   his public domain code made it possible for me to write the Win32
   service code.

   After compiling, one needs to install this service:

        mmLunacyDNS.exe --install

   Then one can start the service:

        net start mmLunacyDNS

   (It can also be started from Control Panel -> Administrative tools ->
    Services; look for the "mmLunacyDNS" service)

   To stop the service:

        net stop mmLunacyDNS

   (Or from the Services control panel)

   To remove the service:

        mmLunacyDNS.exe --remove

   This program should compile and run in a MinGW-3.1.0-1 +
   MSYS-1.0.10 environment.  I use a Windows XP virtual machine to compile
   this program.

 */


static SERVICE_STATUS           sStatus;
static SERVICE_STATUS_HANDLE    hServiceStatus = 0;
#define COUNTOF(x)       (sizeof(x) / sizeof((x)[0]) )

/* Install the service so it's in Windows' list of services */
void svc_install_service() {
        char szPath[512], svcbinary[550];

        GetModuleFileName( NULL, szPath, COUNTOF(szPath) );
        /* Call the program as "{name} service" so it knows to start as
         * a service */
        if (strstr(szPath, " ") != NULL) {
                snprintf(svcbinary, COUNTOF(svcbinary), "\"%s\" service",
                        szPath);
        } else {
                snprintf(svcbinary, COUNTOF(svcbinary), "%s service", szPath);
        }

        SC_HANDLE hSCManager = OpenSCManager(NULL, NULL,
                                SC_MANAGER_CREATE_SERVICE);

        SC_HANDLE hService = CreateService(
                        hSCManager,
                        "mmLunacyDNS",                   /* name of service */
                        "mmLunacyDNS: https://maradns.samiam.org/",
                        /* name to display */
                        SERVICE_ALL_ACCESS,           /* desired access */
                        SERVICE_WIN32_OWN_PROCESS,    /* service type */
                        SERVICE_AUTO_START,           /* start type */
                        SERVICE_ERROR_NORMAL,         /* error control type */
                        svcbinary,                    /* service's binary */
                        NULL,                         /* no load order grp */
                        NULL,                         /* no tag identifier */
                        "",                           /* dependencies */
                        0,                     /* LocalSystem account */
                        0);                    /* no password */

        if(hService == NULL) {
                printf("Problem creating service\n");
        } else {
                printf(
         "mmLunacyDNS service installed; start with: net start mmLunacyDNS\n");
        }

        CloseServiceHandle(hService);
        CloseServiceHandle(hSCManager);

}

/* Remove the service from Windows' list of services; it's probably a good
 * idea to stop the service first */
void svc_remove_service() {
        SC_HANDLE hService = 0;
        SC_HANDLE hSCManager = OpenSCManager(0,0,0);
        hService = OpenService  (hSCManager,"mmLunacyDNS",DELETE);
        if(DeleteService(hService) == 0) {
                printf("Problem deleting service\n");
        } else {
                printf("mmLunacyDNS service removed\n");
        }
        CloseServiceHandle(hService);
        CloseServiceHandle(hSCManager);
}

/* Handle a request to stop the service */
void svc_service_control(DWORD dwControl) {
        switch (dwControl) {
                case SERVICE_CONTROL_SHUTDOWN:
                case SERVICE_CONTROL_STOP:

                sStatus.dwCurrentState  = SERVICE_STOP_PENDING;
                sStatus.dwCheckPoint    = 0;
                sStatus.dwWaitHint      = 2000; /* Two seconds */
                sStatus.dwWin32ExitCode = 0;
                serverRunning = 0;

                default:
                        sStatus.dwCheckPoint = 0;
        }
        SetServiceStatus(hServiceStatus, &sStatus);
}

/* This is the code that is invoked when the service is started */
void svc_service_main(int argc, char **argv) {
        char *a = 0, *b = 0, d = 0;
        int c = 0;
        char szPath[512];
        lua_State *L;

        hServiceStatus = RegisterServiceCtrlHandler(argv[0],
                (void *)svc_service_control);
        if(hServiceStatus == 0) {
                return;
        }

        sStatus.dwServiceType                   = SERVICE_WIN32_OWN_PROCESS;
        sStatus.dwCurrentState                  = SERVICE_START_PENDING;
        sStatus.dwControlsAccepted              = SERVICE_ACCEPT_STOP
                                                | SERVICE_ACCEPT_SHUTDOWN;
        sStatus.dwWin32ExitCode                 = 0;
        sStatus.dwServiceSpecificExitCode       = 0;
        sStatus.dwCheckPoint                    = 0;
        sStatus.dwWaitHint                      = 2 * 1000; /* Two seconds */
        sStatus.dwCurrentState = SERVICE_RUNNING;

        SetServiceStatus(hServiceStatus, &sStatus);

        /* Set the CWD to the directory the service runs in */
        GetModuleFileName( NULL, szPath, COUNTOF(szPath) );
        a = szPath;
        while(*a != 0 && c < 250) {
                if(*a == '/' || *a == '\\') {
                        b = a;
                }
                a++;
                c++;
        }
        if(b != 0) {
                d = *b;
                *b = 0; /* Now ARGV[0] is the path to the program */
                chdir(szPath);
                *b = d;
        }

        LOG = fopen("mmLunacyDNSLog.txt","ab");
        log_it("==mmLunacyDNS started==");
	// Key the random hash compression seed
	char noise[10];
	HCRYPTPROV CryptContext;
	int q;
	q = CryptAcquireContext(&CryptContext, NULL, NULL, PROV_RSA_FULL,
		CRYPT_VERIFYCONTEXT);
	q = CryptGenRandom(CryptContext, 8, noise);
	if(q == 0) {
		puts("I can not generate strong random numbers");
		puts("I refuse to run under these conditions");
		exit(1);
	}
	noise[8] = 0;
 	int za;
	uint32_t sipHashLeft = 0, sipHashRight = 0;
	for(za = 0; za < 4; za++) {
		sipHashLeft <<= 8;
		sipHashLeft ^= noise[za];
	}
	for(za = 4; za < 8; za++) {
		sipHashRight <<= 8;
		sipHashRight ^= noise[za];
	}
	SipHashSetKey(sipHashLeft, sipHashRight);
        L = init_lua(argv[0]);
        if(L == NULL) {
                fprintf(LOG,"FATAL: Can not init Lua state!\n");
                exit(1);
        }
        runServer(L);
        log_it("==mmLunacyDNS stopped==");
        fclose(LOG);

        /* Clean up the stopped service; otherwise we get a nasty error in
           Win32 */
        sStatus.dwCurrentState  = SERVICE_STOPPED;
        SetServiceStatus(hServiceStatus, &sStatus);

}

/* The main() function that calls the service */
int main(int argc, char **argv) {

        int a=0;
        char *b;
        int action = 0;


        static SERVICE_TABLE_ENTRY      Services[] = {
                { "mmLunacyDNS",  (void *)svc_service_main },
                { 0 }
        };
        if(argc > 1) {

                /* Are we started as a service? */
                if (strcmp(argv[1], "service") == 0) {
                        if (!StartServiceCtrlDispatcher(Services)) {
                                printf("Fatal: Can not start service!\n");
                                return 1;
                        }
                        return 0;
                }

                b = argv[1];
                for(a=0;a<5 && *b;a++) {
                        if(*b == 'r') { /* --remove */
                                action = 1;
                        } else if(*b == 'd') { /* --nodaemon or -d */
                                action = 2;
                        }
                        b++;
                }
                if(action == 1) { /* --remove */
                        svc_remove_service();
                } else if(action == 2) { /* --nodaemon or -d */
                        lua_State *L;
                        isInteractive = 1;

	// Key the random hash compression seed (Outdent)
	char noise[10];
	HCRYPTPROV CryptContext;
	int q;
	q = CryptAcquireContext(&CryptContext, NULL, NULL, PROV_RSA_FULL,
		CRYPT_VERIFYCONTEXT);
	q = CryptGenRandom(CryptContext, 8, noise);
	if(q == 0) {
		puts("I can not generate strong random numbers");
		puts("I refuse to run under these conditions");
		exit(1);
	}
	noise[8] = 0;
        int za;
	uint32_t sipHashLeft = 0, sipHashRight = 0;
	for(za = 0; za < 4; za++) {
		sipHashLeft <<= 8;
		sipHashLeft ^= noise[za];
	}
	for(za = 4; za < 8; za++) {
		sipHashRight <<= 8;
		sipHashRight ^= noise[za];
	}
	SipHashSetKey(sipHashLeft, sipHashRight);

                        L = init_lua(argv[0]);
                        if(L != NULL) {
                                runServer(L);
                        } else {
                                puts("Fatal: Can not init Lua");
                                exit(1);
                        }
                } else { /* --install */
                        svc_install_service();
                }
        } else {
                printf("mmLunacyDNS version 2020-08-12\n\n");
                printf(
                    "mmLunacyDNS is a DNS server that is a Windows service\n\n"
                    "To install this service:\n\n\tmmLunacyDNS --install\n\n"
                    "To remove this service:\n\n\tmmLunacyDNS --remove\n\n");
        }
        return 0;
}
#endif /* MINGW */

D deadwood-github/tools/mmLunacyDNS/mmLunacyDNS.lua => deadwood-github/tools/mmLunacyDNS/mmLunacyDNS.lua +0 -14
@@ 1,14 0,0 @@
bindIp = "127.0.0.1" -- We bind the server to the IP 127.0.0.1
function processQuery(mmAll) -- Called for every DNS query received
  if mmAll.mmQtype ~= 1 then -- If it is not an A (ipv4) query
    return {mm1Type = "ignoreMe"} -- Ignore the query
  end
  -- Log query
  mmDNS.log("Got IPv4 query for " .. mmAll.mmQuery .. " from " ..
            mmAll.mmFromIP .. " type " .. 
            string.format("%d",mmAll.mmFromIPtype)) 
  if string.match(mmAll.mmQuery,'%.com%.$') then
    return {mm1Type = "A", mm1Data = "10.1.1.1"} -- Answer for anything.com
  end
  return {mm1Type = "A", mm1Data = "10.1.2.3"} -- Answer for anything not .com
end