fix: populate ldns submodule and add autotools to LDNS build stage

- Re-cloned zonemaster-ldns with --recurse-submodules so the bundled
  ldns C library source (including Changelog and configure.ac) is present
- Added autoconf, automake, libtool to Dockerfile.backend ldns-build stage
  so libtoolize + autoreconf can generate ldns/configure during make

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-21 08:33:38 +02:00
parent 8d4eaa1489
commit eaaa8f6a11
541 changed files with 138189 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
LDNSDIR=..
CC=gcc
CFLAGS=-g3 -W -Wall -Wextra -pedantic -I$(LDNSDIR)
CFLAGS+=-D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D__EXTENSIONS__
LFLAGS=-L$(LDNSDIR)/lib -lcrypto
LIBS=-lldns
STATIC=$(LDNSDIR)/lib/libldns.a -lcrypto
OBJ=main.o zones.o zinfo.o server.o process.o config_file.o
all: masterdont
all-static: $(OBJ)
$(CC) -o masterdont $(CFLAGS) $(OBJ) $(STATIC)
masterdont: $(OBJ)
$(CC) -o masterdont $(CFLAGS) $(OBJ) $(LFLAGS) $(LIBS)
depend:
$(CC) $(CFLAGS) -MM *.c > makefile.dep
clean:
rm -f $(OBJ) masterdont
-include makefile.dep

View File

@@ -0,0 +1,6 @@
Masterdont README
(C) NLnet Labs, 2008.
License: BSD license

View File

@@ -0,0 +1,26 @@
/* standard includes */
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>
#include <getopt.h>
#include <errno.h>
#include <signal.h>
/* for networking */
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <fcntl.h>
#include <sys/stat.h>
/* ldns */
#include "ldns/ldns.h"
#define DEFAULT_CONFIG "example/masterdont.conf"

View File

@@ -0,0 +1,210 @@
/* config_file.c - masterdont config file reading */
#include "config.h"
#include "config_file.h"
#include "zones.h"
#include "zinfo.h"
/* used during config file reading */
static struct config_read cread;
/* config syntax error */
static void config_err(char* str)
{
if(cread.include_depth == 0)
fprintf(stderr, "error: %s\n", str);
else fprintf(stderr, "error in %s %d: %s\n",
cread.fnames[cread.include_depth-1],
cread.lineno[cread.include_depth-1], str);
exit(1);
}
/* skip to end of line */
static void skip_to_eol(FILE* in)
{
int c;
while( (c=fgetc(in)) != EOF) {
if(c == '\n') {
cread.lineno[cread.include_depth-1]++;
return;
}
}
/* EOF is end of line too for ending a comment */
}
/* fill quoted string, remove ending quote */
static void fillup_quoted(FILE* in, char* buf, size_t sz, char q)
{
size_t pos = strlen(buf);
int c;
if(pos>0 && buf[pos-1] == q) {
buf[pos-1] = 0;
return;
}
while( (c=fgetc(in)) != EOF ) {
if(c == q) {
buf[pos] = 0;
return;
}
buf[pos++] = c;
if(pos >= sz) config_err("string too long");
}
config_err("no ending quote for string");
}
/* skip whitespace */
static char skip_white(FILE* in)
{
int c;
while( (c=fgetc(in)) != EOF ) {
if(c == ' ' || c == '\t' || c == '\r')
continue;
else if(c == '\n') {
cread.lineno[cread.include_depth-1]++;
continue;
}
return c;
}
return 0;
}
/* mini lexer and parser; grab one word from the input file, skip
* whitespace and comments. return 0 on EOF */
static char* read_token(FILE* in)
{
static char buf[10240];
buf[sizeof(buf)-1] = 0;
while(!feof(in)) {
buf[0] = skip_white(in);
if(feof(in)) return 0;
if(fscanf(in, "%10230s", buf+1) != 1) {
return 0;
}
if(buf[0] == '#') {
skip_to_eol(in);
continue;
} else if(buf[0] == '\"' || buf[0] == '\'') {
fillup_quoted(in, buf, sizeof(buf), buf[0]);
return buf+1;
}
return buf;
}
return 0;
}
struct config_file* config_file_create()
{
struct config_file* cfg = (struct config_file*)calloc(1, sizeof(*cfg));
if(!cfg) {
printf("out of memory\n");
exit(1);
}
cfg->port = DEFAULT_PORT;
return cfg;
}
void config_file_delete(struct config_file* cfg)
{
if(!cfg) return;
free(cfg);
}
/* open new include file */
static void config_open_include(const char* fname)
{
if(cread.include_depth >= MAX_INCLUDES)
config_err("too many include files");
cread.fnames[cread.include_depth] = strdup(fname);
if(!cread.fnames[cread.include_depth])
config_err("out of memory");
cread.fstack[cread.include_depth] = fopen(fname, "ra");
if(!cread.fstack[cread.include_depth]) {
perror(fname);
config_err("could not open config file");
}
cread.lineno[cread.include_depth] = 1;
cread.include_depth ++;
}
/* close include file */
static void config_close_include(void)
{
if(cread.include_depth == 0) config_err("unexpected end of file");
free(cread.fnames[cread.include_depth-1]);
fclose(cread.fstack[cread.include_depth-1]);
cread.fstack[cread.include_depth-1] = NULL;
cread.include_depth--;
}
void config_file_read(struct config_file* cfg, const char* fname,
struct zones_t* zones)
{
char* p;
char key[1024];
cread.cfg = cfg;
cread.zones = zones;
cread.include_depth = 0;
cread.zone_read = 0;
config_open_include(fname);
while(cread.include_depth > 0) {
p = read_token(cread.fstack[cread.include_depth-1]);
if(p == 0) {
config_close_include();
continue;
}
if(strcmp(p, "server:") == 0)
continue;
else if(strcmp(p, "zone:") == 0) {
if(cread.zone_read) config_file_add_zone(&cread);
cread.zone_read = 1;
cread.zone_linenr = cread.lineno[cread.include_depth-1];
cread.zone_name = NULL;
cread.zone_dir = NULL;
continue;
}
key[sizeof(key)-1]=0;
strncpy(key, p, sizeof(key)-1);
while((p=read_token(cread.fstack[cread.include_depth-1]))==0){
config_close_include();
if(cread.include_depth == 0)
config_err("unexpected end of file");
}
if(strcmp(key, "include:") == 0) {
config_open_include(p);
} else if(strcmp(key, "port:") == 0) {
cfg->port = atoi(p);
if(cfg->port == 0) config_err("invalid port number");
} else if(strcmp(key, "name:") == 0) {
free(cread.zone_name);
cread.zone_name = strdup(p);
if(!cread.zone_name) config_err("out of memory");
} else if(strcmp(key, "dir:") == 0) {
free(cread.zone_dir);
cread.zone_dir = strdup(p);
if(!cread.zone_dir) config_err("out of memory");
}
}
if(cread.zone_read) config_file_add_zone(&cread);
}
void config_file_add_zone(struct config_read* cr)
{
struct zone_entry_t* entry;
if(cr->zone_name == NULL) {
fprintf(stderr, "in zone declared on line %d\n",
cr->zone_linenr);
config_err("zone has no name");
}
if(cr->zone_dir == NULL) {
fprintf(stderr, "in zone declared on line %d\n",
cr->zone_linenr);
config_err("zone has no dir");
}
entry = zones_insert(cr->zones, cr->zone_name, LDNS_RR_CLASS_IN);
if(!entry) {
config_err("out of memory adding zone");
}
entry->zinfo->dir = cr->zone_dir;
free(cr->zone_name);
}

View File

@@ -0,0 +1,61 @@
/* confile_file.h - masterdont config file reading */
#ifndef CONFIG_FILE_H
#define CONFIG_FILE_H
struct zones_t;
#define DEFAULT_PORT 53 /* default is to use the DNS port */
#define MAX_TCP 200 /* max number concurrent tcp queries */
#define SERVER_BUFFER_SIZE 65535 /* bytes */
#define TCP_LISTEN_BACKLOG 15 /* max number of waiting connections */
#define TCP_PKT_SIZE 16384 /* bytes size max tcp packet */
/** a config file that has been read in */
struct config_file {
/** port number to use */
int port;
};
/** max number of nested include files */
#define MAX_INCLUDES 100
/** during config read */
struct config_read {
/** the cfg file */
struct config_file* cfg;
/** zone tree */
struct zones_t* zones;
/** current include depth */
int include_depth;
/** stack of include files */
FILE* fstack[MAX_INCLUDES];
/** name of include files */
char* fnames[MAX_INCLUDES];
/** line number */
int lineno[MAX_INCLUDES];
/** is the temp zone entry filled out? */
int zone_read;
/** line number where we started reading this zone */
int zone_linenr;
/** zone entry we are reading */
char* zone_name;
/** zone dir */
char* zone_dir;
};
/** create structure with defaults */
struct config_file* config_file_create(void);
/** delete structure */
void config_file_delete(struct config_file* cfg);
/** read in a config file */
void config_file_read(struct config_file* cfg, const char* fname,
struct zones_t* zones);
/** during config read, add another zone */
void config_file_add_zone(struct config_read* cr);
#endif

View File

@@ -0,0 +1,6 @@
example.com. 345600 IN SOA ns0.example.org. root.example.com. 1 3600 28800 2419200 3600
example.com. 345600 IN NS ns0.example.org.
example.com. 345600 IN NS ns1.example.org.
txt1.example.com. 345600 IN TXT "text record 1"
txt2.example.com. 345600 IN TXT "text record 2"
txt3.example.com. 345600 IN TXT "text record 3"

View File

@@ -0,0 +1 @@
example.com. 345600 IN SOA ns0.example.org. root.example.com. 2 3600 28800 2419200 3600

View File

@@ -0,0 +1,14 @@
example.com. 345600 IN SOA ns0.example.org. root.example.com. 3 3600 28800 2419200 3600
example.com. 3600 IN NS ns2.example.org.
example.com. 3600 IN NS ns4.example.org.
example.com. 3600 IN NS ns23.example.org.
example.com. 3600 IN NS bigserv.example.net.
mail.example.com. 3600 IN AAAA ffff::23
mail.example.com. 3600 IN MX 10 mail.example.com.
mail.example.com. 3600 IN A 192.0.2.11
printer.example.com. 3600 IN AAAA ffff::25
terms.example.com. 3600 IN AAAA ffff::24
terms.example.com. 3600 IN AAAA ffff::26
webmail.example.com. 3600 IN MX 10 mail.example.com.
webmail.example.com. 3600 IN A 192.0.2.10
www.example.com. 3600 IN A 192.0.2.10

View File

@@ -0,0 +1,43 @@
example.com. 345600 IN SOA ns0.example.org. root.example.com. 4 3600 28800 2419200 3600
example.com. 3600 IN DNSKEY 256 3 RSASHA1 AQO3DvdpH7f2yXcA036AJQsq4Gwv7W2SZuMvxYT8kF7n9UrfryKoUIYXuuDIEQeWGspYIc2Cnn7O4oZ4Kfo3KmnQVdlndpNA+ZmkZVs15ITivguqk/dF4+zY9yLZ07IMQSqw1YwWsx+zR33ifDCZFauSvmfjKjs0YmBUd4R77sgagw== ;{id = 3824 (zsk), size = 1024b}
example.com. 3600 IN DNSKEY 256 3 RSASHA1 AQPWGopOSwd0/yNjbMvjNQo3dmQlNohrjSWbHz/CZFzoPwVrR7EIF96sTLYuGptTMzu3bGiPzXOKtMu5aZOTI3BLsMwWznWLWsxMvYK3hgNMNuMxUmp2XnpMJPHmm5Ejpe94o8f+T/X/riKKIxTvI55kvjmvAKoCTnIof2ov6cYcAQ== ;{id = 44537 (zsk), size = 1024b}
example.com. 3600 IN DNSKEY 257 3 RSASHA1 AQO4lUVyvP98naIWgtzCoPlYz/dwZee+Wpo5FWzzz+n7fXS6fg3TrgWtjccffQYTAd/iAKstTBdyGCg4sl2nS5n0lLAXP8VWM0dRpyieuMHzOYKktHcB0fyUmjhC3k+yA5KGjZZV/YYHc+AG2+IIXbDseYU5V0d56ayHN4qgEOKaHQ== ;{id = 25320 (ksk), size = 1024b}
example.com. 3600 IN DNSKEY 257 3 RSASHA1 AQO5v4qLMhH88u+O2rSXA349FO48DlVX8cCQCW3P8edee/4moLd3wLwGm4SoUwX/TyP9HLoyMjCw1gGJPyvlR6IA4u1NAE7Ik2Vpj8NtA9y1evpOd6AYBYlRKon0SAsl5x7QqcN0lKaE2zklXh3lUdQTKrh94xAyXu+SsiSdaaVy+w== ;{id = 53988 (ksk), size = 1024b}
example.com. 3600 IN NSEC mail.example.com. NS SOA RRSIG NSEC DNSKEY
example.com. 3600 IN RRSIG NS RSASHA1 2 3600 20060825081644 20060728081644 44537 example.com. fEEQbmPKKpKmF0ZgqStbyKfVvrTdtzB382znH92V3iiDH3YBYUyDq9ADBQdQtwTzWaDbFtuBvGEGVAO4nBqFdXliRWCTbGJVa2KESD/FmKYTRyJpfxXCeZmYU23FT6d0lydaz9rs6LnAFEyLHpw7IcVmFbGVB7unFYe3CDPa9Ng= ;{id = 44537}
example.com. 345600 IN RRSIG SOA RSASHA1 2 345600 20060825081644 20060728081644 44537 example.com. rNOxOsc6N1/+lTUm/PB+2kJ+RrIsGjKTxOyFVdXsmCc1DVCDYjQwMDh4Pv8w4quNJl6Sd4SUmi23lda9FN+OHErFySSXhCaI+y9g8E3tq6BXONztye4N8AUKen5miojVPCyJ7NGqToQ70rBI/fsaPLIOKBClHtoe3J+cWMZ+Kss= ;{id = 44537}
example.com. 3600 IN RRSIG NSEC RSASHA1 2 3600 20060825081644 20060728081644 44537 example.com. vV/e13MMU/dP59KkKHagLHPX/qTm9AenDQshYIIBWoUu0QQTke98fsgEg4MLrzhCI1QDyG3zaz2o043VlbNBzcfQ5ld0yaltRRCB5bolKV5j+UjSYW96fuJwg51GOT+t/j49JZCBKeg+C1abnyDMxderv1gBCVVX9EyrqhAHoWE= ;{id = 44537}
example.com. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20060825081644 20060728081644 25319 example.com. iWsni/uzhcOFV+UKayIYEWmnvvA5DanCogzfzIiVLLc9v0Pn/G8dEEAJlt4WD60WCnM+kIRoTcbSZDY9Jh+gRi2KCxIVBqelY+Bkl7X9iLYiuWG4wMC90TXFndTg4Mvlo5ZRJ/bB6t/hWTu8ZEVb8Zkj6kU//JSeDATphzZ9oIA= ;{id = 25319}
example.com. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20060825081644 20060728081644 44537 example.com. mw527qWhZacjEK+auPdkUFc56EymJyQ9MGo/tsNOLOJVYjkF/b9AXpPQCHHmSuwoB7ZQX7wawF1dfL/iYqSNgNopmEcvrYcSiRL19rV2vp5hBA6I5Ywy3ZVBhX3yY7pUY3SNEe7e0V/zKZk4W2TmjPnDgOdH5GzpO5glKzO0Pig= ;{id = 44537}
example.com. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20060825081644 20060728081644 53987 example.com. N9hXL7+oXNAtuqsBAsiT8I4fvlNw5DRy4kwuKl6pzGnQ02U6cLvOdzsN1N6VYM4YJ6xBQL+2u8oZwYC5YtLiWISt2GbaCHPShksX3HZEmCnzgKZ+BTgUd40fnJZ809lZdcB9KR0LlwR5XUnqMYWYtaH7UGEdvqLhrv3rJPkJfYQ= ;{id = 53987}
example.com. 3600 IN NS ns2.example.org.
example.com. 3600 IN NS ns4.example.org.
example.com. 3600 IN NS ns23.example.org.
example.com. 3600 IN NS bigserv.example.net.
mail.example.com. 3600 IN NSEC printer.example.com. A MX AAAA RRSIG NSEC
mail.example.com. 3600 IN RRSIG A RSASHA1 3 3600 20060825081644 20060728081644 44537 example.com. ONq5uFbBsvt6XRZdGA7TdZkRy9DcV3ZXS1CXL1AMZ78+MaS+YufBes9wUo/8rBJPoGrBx1u6HRiLOUjc+7LpLJa0NSGCCwPsispbAgNwBKNBYBHd2ftxWImchh1qp5OfFvjkSp9jftr4DlQOW3Sjz8/kvzNU3b+Cr+ERF6vlJks= ;{id = 44537}
mail.example.com. 3600 IN RRSIG MX RSASHA1 3 3600 20060825081644 20060728081644 44537 example.com. qLVUn1ZB1f0x+aVf9oH1UvFt8aAz2knH+X95ciB71dY2f8+vKqbKvbDRh0D5sQrLVd/tyuc0Y3EBBaflg4/b7g0ta4hxt7Z7cWTWwj0NKYbGu1wzcILYfFHhgBlN+k8GYknLNTPhmgcZGXnZaHv+5bVtivBLQOS+ftB311uJ0to= ;{id = 44537}
mail.example.com. 3600 IN RRSIG AAAA RSASHA1 3 3600 20060825081644 20060728081644 44537 example.com. wQZS2hK2JAWiVaoUJ+f6qLc/Ce/LrW5sx0odBcAOHcqY7TO9LPJQzjrmVNh3DjLDKrwICv9F5u5nv66Bf3XYPAOEk7cToirfz/HUfEng10DvDIuOtjvBZDRoyGWFFJi8EewNLtfywMR9Z16iE2NjanSZaRIKOCQMfGmf7AoG9+Y= ;{id = 44537}
mail.example.com. 3600 IN RRSIG NSEC RSASHA1 3 3600 20060825081644 20060728081644 44537 example.com. sPpuFDPjNGAn0r94NyfHljJQWwIcgerYTiku0S2F3V2KTkh1fNSJXzndv/GGHn+q3EQ+75QVkjYK9xbmzpB9IswL7BoVM2zeKGR6i3xfkiDJb3itQ/BFKs5oLYt2APb8tXmj8/VlfchIi8C1TV1W7C7bAPvSnKBVmST0zJEfTT4= ;{id = 44537}
mail.example.com. 3600 IN AAAA ffff::23
mail.example.com. 3600 IN MX 10 mail.example.com.
mail.example.com. 3600 IN A 192.0.2.11
printer.example.com. 3600 IN NSEC terms.example.com. AAAA RRSIG NSEC
printer.example.com. 3600 IN RRSIG AAAA RSASHA1 3 3600 20060825081644 20060728081644 44537 example.com. vh6w7zmKvU+CfbbiuLjQgRf65EdJvy7Ih5nSs7yhxrGRdl+d2HQDNGWGQF0dETEKbP43j1RctlX3o+Q/l7tuLyHAK0LGNfCSCqVtdO93ia/5o/tUnMjb6xUAsNN7CYfhAvm2AhUzQFzsD54UrIpSbhsSG28P3KcpP/sB2+aQ1BQ= ;{id = 44537}
printer.example.com. 3600 IN RRSIG NSEC RSASHA1 3 3600 20060825081644 20060728081644 44537 example.com. TYBHHaR2OifDTlZNZbTq3pgFO57QI/FAVGAKut9evCO9PNJjNYywWEaBWUO0G9+0CY/r25e+/bwZ6tLneadDD7D48TkYG7KoktKnZ0YXtwioeb24FcoC5t3pv3nzC8Ti/ZKDyH5IbwPXsZx+dFYTZy1y6cpkIguAVQAVKBfc1j4= ;{id = 44537}
printer.example.com. 3600 IN AAAA ffff::25
terms.example.com. 3600 IN NSEC webmail.example.com. AAAA RRSIG NSEC
terms.example.com. 3600 IN RRSIG AAAA RSASHA1 3 3600 20060825081644 20060728081644 44537 example.com. A9wUkjY+/YXimx7pf8ucTUwIoP9gOugXqBeVDfOUfrofX7kfOoKalZWHw+9IyBz4PQsK9SyckXkrkS1WY9Lt/5VVJz3CH7IBQR5qopy28Z0jd59WqoTPd/levCXCnlGQa4PSODyQIvjx9ijKo4GmWzQAPXpVZkjw3/MzmUQA1KQ= ;{id = 44537}
terms.example.com. 3600 IN RRSIG NSEC RSASHA1 3 3600 20060825081644 20060728081644 44537 example.com. g+dMgzeYRhKT2MxgzBZT4gboOdyhOAjKe7YWrPNIQL8Okb4m5zotU99ZGJEasDyYe2PaSsiq0vSpEPdsbeFNGWrva2qsSGySpDXtYAgfbwUdG8WP05gJhHcywog7FzH2HKpYhScSXdtaTs/433dgU15ympSzrkB6IRgcMvMb5Ck= ;{id = 44537}
terms.example.com. 3600 IN AAAA ffff::24
terms.example.com. 3600 IN AAAA ffff::26
webmail.example.com. 3600 IN NSEC www.example.com. A MX RRSIG NSEC
webmail.example.com. 3600 IN RRSIG A RSASHA1 3 3600 20060825081644 20060728081644 44537 example.com. tUOcWj9KnDE8OgbdLx7twjkGm6omZmOnhO9kZcVdO3mwKZ0kwwqDRluLyUMcfry2+/JqSR1HPQmk8ZSLow1xZBIfBHvnM62xGwZeKNS9UMaTsGCo3/oUaNC48iFnW7CylRHoO05XxXXIe4rB8mqUDMVj/XtAw8Zr/UHF0kjqsWk= ;{id = 44537}
webmail.example.com. 3600 IN RRSIG MX RSASHA1 3 3600 20060825081644 20060728081644 44537 example.com. dgnSDob+xGj24/c7flGX6sCsMY2bDMR3HisBMNoTNdZHA1khOz6CVvad8hhsoNlDbHFu5yHLu4hDjZ70GdSqg9jXVaxLWq2D/r/CfLQZIkc60TmUvuKoWtrl8ecTd8YqOiSSSSiLacpJH1CrWZi7lrIg1OOTfIpMRfr/zUxJsBE= ;{id = 44537}
webmail.example.com. 3600 IN RRSIG NSEC RSASHA1 3 3600 20060825081644 20060728081644 44537 example.com. hXfeHNCXX51mIBxzsEXWozYi8SeMt+g2+E4BIiG8GkIE34yxGQNJK8cxPlb2E2P01lOv05ugzD26tfDymAPP0itdcmlaf2NWxO70OqegDUUOo6x873gCeaoKCqxy8lIhwC5Iqgs8tnIk/1PPBxi4P7InGmqsfrRqJN4QfmPuT8c= ;{id = 44537}
webmail.example.com. 3600 IN MX 10 mail.example.com.
webmail.example.com. 3600 IN A 192.0.2.10
www.example.com. 3600 IN NSEC example.com. A RRSIG NSEC
www.example.com. 3600 IN RRSIG A RSASHA1 3 3600 20060825081644 20060728081644 44537 example.com. rkO1E0zZV+NiEKUrkUEC396ubGOYWML8VbpbWpDcBTwPGP0gGEkva8qt0vE6qlsw3gO4tkT1Ir+TXAWvnRvFtY3bpkNnajhIvV2J+16/p8YtCIxH19IUrAwf1pANMNNtQuFU1CLIVOaXRx8oXRfFY2t+GFYdDqXyjzqgcVU7mww= ;{id = 44537}
www.example.com. 3600 IN RRSIG NSEC RSASHA1 3 3600 20060825081644 20060728081644 44537 example.com. y3AmY5RDR5J4ELdDCGYgvh8sawaxYjGJMch6gxfGPYCu9jqpECkpustTw+GgAnTlLej6iKK/3EfoKUobOVgpIPDqAWNqa8lL8m3P2Kbxp+OXGotSz5atVSlDRei66XwalKhGw9u7EDOLZc/bSbbbxSJa14XwTKA4Tr2Op5KLT/4= ;{id = 44537}
www.example.com. 3600 IN A 192.0.2.10

View File

@@ -0,0 +1,19 @@
example.com. 345600 IN SOA ns0.example.org. root.example.com. 5 3600 28800 2419200 3600
example.com. 3600 IN NS ns2.example.org.
example.com. 3600 IN NS ns4.example.org.
example.com. 3600 IN NS ns23.example.org.
example.com. 3600 IN NS bigserv.example.net.
mail.example.com. 3600 IN AAAA ffff::23
mail.example.com. 3600 IN TXT "if you can find this, all outgoing mail is signed, no, really"
mail.example.com. 3600 IN MX 10 mail.example.com.
mail.example.com. 3600 IN A 192.0.2.11
newservice.example.com. 3600 IN A 192.0.2.123
ooo.example.com. 3600 IN TXT "amazing new protocol here"
terms.example.com. 3600 IN A 192.0.2.24
terms.example.com. 3600 IN A 192.0.2.26
webmail.example.com. 3600 IN MX 20 mail.example.com.
webmail.example.com. 3600 IN A 192.0.2.10
www.example.com. 3600 IN NSEC example.com. A RRSIG NSEC
www.example.com. 3600 IN RRSIG A RSASHA1 3 3600 20060825081644 20060728081644 44537 example.com. rkO1E0zZV+NiEKUrkUEC396ubGOYWML8VbpbWpDcBTwPGP0gGEkva8qt0vE6qlsw3gO4tkT1Ir+TXAWvnRvFtY3bpkNnajhIvV2J+16/p8YtCIxH19IUrAwf1pANMNNtQuFU1CLIVOaXRx8oXRfFY2t+GFYdDqXyjzqgcVU7mww= ;{id = 44537}
www.example.com. 3600 IN RRSIG NSEC RSASHA1 3 3600 20060825081644 20060728081644 44537 example.com. y3AmY5RDR5J4ELdDCGYgvh8sawaxYjGJMch6gxfGPYCu9jqpECkpustTw+GgAnTlLej6iKK/3EfoKUobOVgpIPDqAWNqa8lL8m3P2Kbxp+OXGotSz5atVSlDRei66XwalKhGw9u7EDOLZc/bSbbbxSJa14XwTKA4Tr2Op5KLT/4= ;{id = 44537}
www.example.com. 3600 IN A 192.0.2.10

View File

@@ -0,0 +1,52 @@
example.com. 345600 IN SOA ns0.example.org. root.example.com. 8 3600 28800 2419200 3600
example.com. 3600 IN DNSKEY 256 3 RSASHA1 AQO3DvdpH7f2yXcA036AJQsq4Gwv7W2SZuMvxYT8kF7n9UrfryKoUIYXuuDIEQeWGspYIc2Cnn7O4oZ4Kfo3KmnQVdlndpNA+ZmkZVs15ITivguqk/dF4+zY9yLZ07IMQSqw1YwWsx+zR33ifDCZFauSvmfjKjs0YmBUd4R77sgagw== ;{id = 3824 (zsk), size = 1024b}
example.com. 3600 IN DNSKEY 256 3 RSASHA1 AQPWGopOSwd0/yNjbMvjNQo3dmQlNohrjSWbHz/CZFzoPwVrR7EIF96sTLYuGptTMzu3bGiPzXOKtMu5aZOTI3BLsMwWznWLWsxMvYK3hgNMNuMxUmp2XnpMJPHmm5Ejpe94o8f+T/X/riKKIxTvI55kvjmvAKoCTnIof2ov6cYcAQ== ;{id = 44537 (zsk), size = 1024b}
example.com. 3600 IN DNSKEY 257 3 RSASHA1 AQO4lUVyvP98naIWgtzCoPlYz/dwZee+Wpo5FWzzz+n7fXS6fg3TrgWtjccffQYTAd/iAKstTBdyGCg4sl2nS5n0lLAXP8VWM0dRpyieuMHzOYKktHcB0fyUmjhC3k+yA5KGjZZV/YYHc+AG2+IIXbDseYU5V0d56ayHN4qgEOKaHQ== ;{id = 25320 (ksk), size = 1024b}
example.com. 3600 IN DNSKEY 257 3 RSASHA1 AQO5v4qLMhH88u+O2rSXA349FO48DlVX8cCQCW3P8edee/4moLd3wLwGm4SoUwX/TyP9HLoyMjCw1gGJPyvlR6IA4u1NAE7Ik2Vpj8NtA9y1evpOd6AYBYlRKon0SAsl5x7QqcN0lKaE2zklXh3lUdQTKrh94xAyXu+SsiSdaaVy+w== ;{id = 53988 (ksk), size = 1024b}
example.com. 3600 IN NSEC mail.example.com. NS SOA RRSIG NSEC DNSKEY
example.com. 3600 IN RRSIG NS RSASHA1 2 3600 20060825092020 20060728092020 44537 example.com. JDvtFaXw8KGGKvLaAZfKqGdJMVEFEwxSgPWCN7e1WE68ExSAeBgLHIcNcwrIU3aoW5fDwQ91TEVsP5eq+6UqDYCMhiQ6bZig9SXYOJyCL338OaIGPuRP0dnf2uCX1HqUB4ez3lERDDMZ2DQ0G3oOIlxn06y6qrldlkZqkVeM29s= ;{id = 44537}
example.com. 345600 IN RRSIG SOA RSASHA1 2 345600 20060825092020 20060728092020 44537 example.com. NwDSvPs90yDrmJ4c75491MaPO0xFJ/4ibSiWVr4uL594Vht1Rw8CFslvAk7kzUEv5bMxZ8hW5nBZEXRCvYtCmoizfZuFtMaHNT7Rbs2pIqExI66mZ7WFvg/nDUs14+s5+eiBCWVXoSdIpCrqZfTAPXTzAKK9IWfmHCQ5+IseKbU= ;{id = 44537}
example.com. 3600 IN RRSIG NSEC RSASHA1 2 3600 20060825092020 20060728092020 44537 example.com. HN3vqhoVWJ3BdjoOTAw7Pusf+G0iTWiy7lgR7bPBk/haEvWsoyZExCetjdz2nAwjcS3ZAH7MLSGWhYr6E+x0fmYgCRZOlpl8ZFytJt3wyf0CCJGu+g1STbkwl29R9R7+U6PbUxYI7uMtpgjc8Am5J9CD5pwTwDLb4NIbPKq3FuY= ;{id = 44537}
example.com. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20060825092020 20060728092020 25319 example.com. sTRi/2l0kbu2bbW2zGPtKUi1qKlLByqlOq9BHfYZG3pA6Un9lAkbIYhzU5rDPmEsMmQt+EzCzzkQ9SaEYfMR6J9xyuYMYKv6PH0cMA1K9+9ihpZDpWqhPRr8Eqp+m4RdK1yw9wXezX/+92AZQ4SUlCyVZsjGX3Wfh8J2wKwke4I= ;{id = 25319}
example.com. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20060825092020 20060728092020 44537 example.com. n37ERfliiBsHv+oF4O++3gIBgf+rEfEcZTRR7nF7bF2D4t56CqVF6Nk+Yx8Khc58WLAIGwzLpx4ovNcXwzJJKZV6CKq2/OTnshE4ExiqksoekxOKL7p0imR8N9P6GWB22SoQzUnkd/A2nnQ+uiDV92uFN0ed0qPmIZK79BIT0Yo= ;{id = 44537}
example.com. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20060825092020 20060728092020 53987 example.com. nAtY5OZo03E0KhaC8pVDUjkDLgnLP9UZRt9rPyNm1HQKPGr8+A2bdF8LYzn4K6fDFPBw+WwEHRe+OAgeWY4wCUwHu9P+gaI+TsW+HCG/5NI4071RH1I/dbZCnO9MU7VvrAdQfTykgLBJ7chxTwIlILNRom9bYJGtRTOLlfqQ36E= ;{id = 53987}
example.com. 3600 IN NS ns2.example.org.
example.com. 3600 IN NS ns4.example.org.
example.com. 3600 IN NS ns23.example.org.
example.com. 3600 IN NS bigserv.example.net.
mail.example.com. 3600 IN NSEC newservice.example.com. A MX TXT AAAA RRSIG NSEC
mail.example.com. 3600 IN RRSIG A RSASHA1 3 3600 20060825092020 20060728092020 44537 example.com. nVVW5DDjzVvxsieP4jZIIDKd/TJOdN4bEOBQT7xbnh5h8NgHt+AwkpJsg8ZcL16mejPFsml+6yjA3oEIAsx5WJrGxEAz86sfvrJHWfMy+PqoCSRnyJCIJk7qTSrmm6+5dQ7xetvnQ3OnI56PDnTH+ZyV93zNUsUBZn53G87y/OE= ;{id = 44537}
mail.example.com. 3600 IN RRSIG MX RSASHA1 3 3600 20060825092020 20060728092020 44537 example.com. C16CNYAvDLrmv+7RFqDrJj0BwU9g3Cu4TxXi9Tus5ZSL5LNwTN3ZukVmK/7cVU3DLAxMpNWM6XEfC7a/TXmh3uVtdWUQYx20wq1r2SR9JSd4tvaPM+pvAHz/qsALsuuhM++nxJyaV51gHy+mlkKXBUT7ibXTMV1YF9n5CTDTcck= ;{id = 44537}
mail.example.com. 3600 IN RRSIG TXT RSASHA1 3 3600 20060825092020 20060728092020 44537 example.com. K4+qpHQcMvmDi6b4ddCuWiZGEQexwc+VIrx64+QHfLWr5PwfEzNvKoBLaB++Fz/f/CdhDXEeFQe77q53v6pHrEJTcSXySZem1ucftd43AiIruN/RZZe95sFnFI2OvipmrpT+fW3E0Jb0mUZnJ5MXjVYHeQ2AoRsUiuDU99NqzIo= ;{id = 44537}
mail.example.com. 3600 IN RRSIG AAAA RSASHA1 3 3600 20060825092020 20060728092020 44537 example.com. VA1TXptPfMQZ+wPMhXr9ITzha5NGj2/tYujcDa3IVrvBm3a+Dy+j1bEKY0PUVPiQLYbpvwaCTmMpr4JvvjgGM4oo8PBNuMaITx6vH0XqgqgE9gtQZDV7VBXioyZKmGPnuCEOqDYpg7xRz0l2vgWbMrSROrYtTNYT7r1yioKV30A= ;{id = 44537}
mail.example.com. 3600 IN RRSIG NSEC RSASHA1 3 3600 20060825092020 20060728092020 44537 example.com. Q1YduJFkXBYWiWy5bVhlsua5y7+n/mrGuVC0IwGHYKY8XRSkPyTy/kI6lIWeX1s9e2W1lq0CSOjv1DG8I6TRPkQ16pa3fKeLO6q78XOGxG734XclivdHVp2AwlHhi819C5gm11B2fEVNKEsSMpT3sc/jzG/zswxdDRTSPEnjo6M= ;{id = 44537}
mail.example.com. 3600 IN AAAA ffff::25
mail.example.com. 3600 IN TXT "mime-type compressed/zip: bs2a445adgh2345jd46j"
mail.example.com. 3600 IN MX 10 mail.example.com.
mail.example.com. 3600 IN A 192.0.2.11
newservice.example.com. 3600 IN NSEC ooo.example.com. A AAAA RRSIG NSEC
newservice.example.com. 3600 IN RRSIG A RSASHA1 3 3600 20060825092020 20060728092020 44537 example.com. CQDTD31oH0DDaPlcLj1LGFCo5y/fWmxwvJXYq7UitFg6j9J6NG4xZoW+mmY2UEyPRtHqx4y0EkBayV7n8rBpPyHEWtkUnUDm9qO7zkYVYulSOXqdkEM6cxpGqqkav5YRVHWhRaFmnMtCwh3siB4iHwv9We01NnTGUozTCTzMZNA= ;{id = 44537}
newservice.example.com. 3600 IN RRSIG AAAA RSASHA1 3 3600 20060825092020 20060728092020 44537 example.com. obtQbyd9bueK6fhgBs8TEVAkUn8M9cD90J+1ANgqoXGVtd9WdQtW8KRqGxiTyuFZpseLOtMkcMxV3nwE6ynnF7uckJ5BKeKdhRYEeUfLGNcKBi4hROArRrnubVDHKOLNP9S/ig+PDvDRpDlH/kINK9gXvii0RfGz0DrZtHM1iAw= ;{id = 44537}
newservice.example.com. 3600 IN RRSIG NSEC RSASHA1 3 3600 20060825092020 20060728092020 44537 example.com. jwrBMXoyWiogVPkMFPdb0liOOSdPNwXjlD4IoCCXH/WozK/U/zd+sCI0ISa6YGUNtr0zP/yANXjA3cC0D31x/rUIJi26dkG6BQSCjbOeilanoQXVQwLxgEyGZl1Rbbn5K1M5WqgwFl9rBj2nAAPFWgpKbv780hVzQen/wLSiJv4= ;{id = 44537}
newservice.example.com. 3600 IN AAAA ::1
newservice.example.com. 3600 IN A 192.0.2.123
ooo.example.com. 3600 IN NSEC terms.example.com. TXT RRSIG NSEC
ooo.example.com. 3600 IN RRSIG TXT RSASHA1 3 3600 20060825092020 20060728092020 44537 example.com. Nfo4zsHBaQDnXJjQfitjAaSM9yExU2uKRdnFyYgTiN75IdM79UZVTzjNCHo/MNw4Bh02gT8JmgLzXZmkQZvdKvunE1DfI4LD8qadmKbYrFH0RrqF0cKT396+CecTLUz3n0r8dL14BZk/L6IcFOUXOYBc+swzDmZJKpD+9x4YY1Y= ;{id = 44537}
ooo.example.com. 3600 IN RRSIG NSEC RSASHA1 3 3600 20060825092020 20060728092020 44537 example.com. Du89E7Mp11ka5Uy2/Fm383HTPFjZJ+EQIKI19yaUkI1onEItOierSS6W7UoQpxsLv5jqMTqOP+i1r4VD9LaBviGy331XZdAppG5TbZBdR1VAJ+6c/AZ8pKTqKPJa8m/vmtgRPKvjugb4Des7WlyyBSd7AWRu6PZmYj+/fLghjt8= ;{id = 44537}
ooo.example.com. 3600 IN TXT "amazing new protocol here"
terms.example.com. 3600 IN NSEC webmail.example.com. A MX RRSIG NSEC
terms.example.com. 3600 IN RRSIG A RSASHA1 3 3600 20060825092020 20060728092020 44537 example.com. eSjZ5Km2/7Q4X2OX0fRRGpZjoqhs5sdyWZDjKxpATPKcg2zcnXDl3l38e6jv97Xr0KW06n/lT4qrLOase4jPwWISzdw3NGt8M/zsyfJtQ+cPyztvGelCUsaDNYV/kHAVkjQvRLJ3S/0gM9KsKJ44XVZZu9xHXQT4O+l/Nwf4+s8= ;{id = 44537}
terms.example.com. 3600 IN RRSIG MX RSASHA1 3 3600 20060825092020 20060728092020 44537 example.com. aVYMrNgHMMpmQ2a/I5FlaLjkgPbuSwxjDmA/oHUeh3FadyrjksPrEktNcUkIS4gINH5ehrTE2BV/SFvsZoX5D8fKW+1S+ip3IRm71fqC3H/HlFZR73e28sfdrD/OlozAv9VKtGlnhFvvbO84xszla1gD2lR457R5iqwxAnggLEk= ;{id = 44537}
terms.example.com. 3600 IN RRSIG NSEC RSASHA1 3 3600 20060825092020 20060728092020 44537 example.com. lYPcJcL/67wVy3sMJ81FT2XNp8QKm5ug/0DkbaYyzk47wQWFgoVEeNp6CxxFesdn3ISl2auLpQeNTOdRFk4ogl3N2nhQ5TrVGQuoErpfeIWew4mt6DqIXnvoigH3TiTL9v9/TCHj2I7cnWNJB9V5n23Ud45gGRkP0BrvJpfgG0Q= ;{id = 44537}
terms.example.com. 3600 IN MX 23 mail.example.com.
terms.example.com. 3600 IN A 192.0.2.24
webmail.example.com. 3600 IN NSEC www.example.com. A MX RRSIG NSEC
webmail.example.com. 3600 IN RRSIG A RSASHA1 3 3600 20060825092020 20060728092020 44537 example.com. EOuxJKZPw6aHvydi6vmzqmxvDBsibMIUOP0kFzPzpdArOysjapYI8UQalE/zIU0DRktsG4yJnotnbQmTIcwomFaI0K9rCecA6Lf4HzzVpoNRxyxFTEfynqKfYE2675s6edv4XjN1LJkKLnm7hFJcLl/hv/A37hWhNKo6NxT5+zA= ;{id = 44537}
webmail.example.com. 3600 IN RRSIG MX RSASHA1 3 3600 20060825092020 20060728092020 44537 example.com. LA1TRH5Ie9eDxjRNh1DhrcaMmHH8/1EqR1MDTdFaJMUQyQ/U2erLm5pUGbTS/LWIdbcwJf4dfeJTWSTP3y9vKSX7RHxc1EqgW3t39qCEZJuuqWdpzveIBD3GfWgxmMRE+PGjyjn39RjSbd755ZvnG9wNqz2Jex5PI3Adzn0L/Fc= ;{id = 44537}
webmail.example.com. 3600 IN RRSIG NSEC RSASHA1 3 3600 20060825092020 20060728092020 44537 example.com. d29T9PyCbhzSeCBQBMaqqCdUdlIY9qvJ8AqqyXXWMmr+FNMS+rLsZgTF2V1VUOwHY9v6onIVbhNiQ4VFrFfr9NteokBvAuLin+I7ZHCOeAZ+y8f7rybnUL30UaJyefpEi9T6fSz95nNugd/P3T6IPPZ1r7sOjz7aLq0gh+cepZ4= ;{id = 44537}
webmail.example.com. 3600 IN MX 20 mail.example.com.
webmail.example.com. 3600 IN A 192.0.2.10
www.example.com. 3600 IN NSEC example.com. A RRSIG NSEC
www.example.com. 3600 IN RRSIG A RSASHA1 3 3600 20060825092020 20060728092020 44537 example.com. lr+AfP5GRrU9mNB5+A6rAkElWMxFHag1a7EBplEeQmTW5GuEuxS4jRgI9AdBPMu/j2iGkC9mMhla515gqz8JIkRdxXngeDFhAhT6lvLeNxyHGl3fWJmehEYDjQxBQVzQcKwQjDmylGi+8MESI/pWMOeGOTOYicvoS3Czb66OC+c= ;{id = 44537}
www.example.com. 3600 IN RRSIG NSEC RSASHA1 3 3600 20060825092020 20060728092020 44537 example.com. 09jeDB1cPACMTVG+a4Oyc+wV7+a3esqVfggz5adkoxCRdQEFK9Rlv1ZxFrd+Cdz8K1aeGT7Kwx/vMkVwUB+DUFMT3SlzNXoTAvEGHZWIZu31eSGcH4quXb4/p1A7YGFo1zqZj77vTflLEcRZUpv4NDrr2ma6lRHAIF97/X3rU7c= ;{id = 44537}
www.example.com. 3600 IN A 192.0.2.10

View File

@@ -0,0 +1,19 @@
# example config file for Masterdont.
# this is a comment.
# global server settings.
server:
# port number to use. default 53 (DNS).
port: 10053
# a number of zone entries follow.
zone:
# domain name of the zone.
name: "example.com"
# directory where data is stored for the zone.
# In the directory files created are named zone.example.com.*
dir: "example"
#zone:
#name: "example.net"
#dir: "example"

View File

@@ -0,0 +1,6 @@
example.com. 345600 IN SOA ns0.example.org. root.example.com. 1 3600 28800 2419200 3600
example.com. 345600 IN NS ns0.example.org.
example.com. 345600 IN NS ns1.example.org.
txt1.example.com. 345600 IN TXT "text record 1"
txt2.example.com. 345600 IN TXT "text record 2"
txt3.example.com. 345600 IN TXT "text record 3"

View File

@@ -0,0 +1 @@
1

View File

@@ -0,0 +1,48 @@
#include "config.h"
#include "config_file.h"
#include "zones.h"
#include "server.h"
static void
usage(const char* me)
{
printf("usage: %s [options]\n", me);
printf("Hidden master stealth server: serves AXFR, IXFR.\n");
printf("-h print this information.\n");
printf("-c <file> set config file to use.\n");
printf("\n");
}
int main(int argc, char* argv[])
{
const char* config = DEFAULT_CONFIG;
int c;
while((c=getopt(argc, argv, "c:h")) != -1)
{
switch(c) {
case 'c':
config = optarg;
break;
default:
printf("Unknown option '-%c' (%x).\n", c, c);
case 'h':
usage(argv[0]);
return 1;
}
}
argc -= optind;
argv += optind;
if(argc > 0) {
printf("Too many arguments.\n");
usage(argv[0]);
return 1;
}
/* start server */
while(server_start(config)) {
printf("Masterdont reload\n");
}
printf("Masterdont stopped\n");
return 0;
}

View File

@@ -0,0 +1,51 @@
config_file.o: config_file.c config.h ../ldns/ldns.h ../ldns/util.h \
../ldns/buffer.h ../ldns/error.h ../ldns/common.h ../ldns/dname.h \
../ldns/rdata.h ../ldns/dnssec.h ../ldns/packet.h ../ldns/rr.h \
../ldns/keys.h ../ldns/zone.h ../ldns/resolver.h ../ldns/tsig.h \
../ldns/dnssec_zone.h ../ldns/rbtree.h ../ldns/dnssec_verify.h \
../ldns/dnssec_sign.h ../ldns/higher.h ../ldns/host2str.h \
../ldns/host2wire.h ../ldns/net.h ../ldns/str2host.h ../ldns/update.h \
../ldns/wire2host.h ../ldns/rr_functions.h ../ldns/parse.h \
config_file.h zones.h zinfo.h
main.o: main.c config.h ../ldns/ldns.h ../ldns/util.h ../ldns/buffer.h \
../ldns/error.h ../ldns/common.h ../ldns/dname.h ../ldns/rdata.h \
../ldns/dnssec.h ../ldns/packet.h ../ldns/rr.h ../ldns/keys.h \
../ldns/zone.h ../ldns/resolver.h ../ldns/tsig.h ../ldns/dnssec_zone.h \
../ldns/rbtree.h ../ldns/dnssec_verify.h ../ldns/dnssec_sign.h \
../ldns/higher.h ../ldns/host2str.h ../ldns/host2wire.h ../ldns/net.h \
../ldns/str2host.h ../ldns/update.h ../ldns/wire2host.h \
../ldns/rr_functions.h ../ldns/parse.h config_file.h zones.h server.h
process.o: process.c config.h ../ldns/ldns.h ../ldns/util.h \
../ldns/buffer.h ../ldns/error.h ../ldns/common.h ../ldns/dname.h \
../ldns/rdata.h ../ldns/dnssec.h ../ldns/packet.h ../ldns/rr.h \
../ldns/keys.h ../ldns/zone.h ../ldns/resolver.h ../ldns/tsig.h \
../ldns/dnssec_zone.h ../ldns/rbtree.h ../ldns/dnssec_verify.h \
../ldns/dnssec_sign.h ../ldns/higher.h ../ldns/host2str.h \
../ldns/host2wire.h ../ldns/net.h ../ldns/str2host.h ../ldns/update.h \
../ldns/wire2host.h ../ldns/rr_functions.h ../ldns/parse.h process.h \
zones.h zinfo.h server.h
server.o: server.c config.h ../ldns/ldns.h ../ldns/util.h \
../ldns/buffer.h ../ldns/error.h ../ldns/common.h ../ldns/dname.h \
../ldns/rdata.h ../ldns/dnssec.h ../ldns/packet.h ../ldns/rr.h \
../ldns/keys.h ../ldns/zone.h ../ldns/resolver.h ../ldns/tsig.h \
../ldns/dnssec_zone.h ../ldns/rbtree.h ../ldns/dnssec_verify.h \
../ldns/dnssec_sign.h ../ldns/higher.h ../ldns/host2str.h \
../ldns/host2wire.h ../ldns/net.h ../ldns/str2host.h ../ldns/update.h \
../ldns/wire2host.h ../ldns/rr_functions.h ../ldns/parse.h \
config_file.h server.h zones.h process.h
zinfo.o: zinfo.c config.h ../ldns/ldns.h ../ldns/util.h ../ldns/buffer.h \
../ldns/error.h ../ldns/common.h ../ldns/dname.h ../ldns/rdata.h \
../ldns/dnssec.h ../ldns/packet.h ../ldns/rr.h ../ldns/keys.h \
../ldns/zone.h ../ldns/resolver.h ../ldns/tsig.h ../ldns/dnssec_zone.h \
../ldns/rbtree.h ../ldns/dnssec_verify.h ../ldns/dnssec_sign.h \
../ldns/higher.h ../ldns/host2str.h ../ldns/host2wire.h ../ldns/net.h \
../ldns/str2host.h ../ldns/update.h ../ldns/wire2host.h \
../ldns/rr_functions.h ../ldns/parse.h zinfo.h zones.h
zones.o: zones.c config.h ../ldns/ldns.h ../ldns/util.h ../ldns/buffer.h \
../ldns/error.h ../ldns/common.h ../ldns/dname.h ../ldns/rdata.h \
../ldns/dnssec.h ../ldns/packet.h ../ldns/rr.h ../ldns/keys.h \
../ldns/zone.h ../ldns/resolver.h ../ldns/tsig.h ../ldns/dnssec_zone.h \
../ldns/rbtree.h ../ldns/dnssec_verify.h ../ldns/dnssec_sign.h \
../ldns/higher.h ../ldns/host2str.h ../ldns/host2wire.h ../ldns/net.h \
../ldns/str2host.h ../ldns/update.h ../ldns/wire2host.h \
../ldns/rr_functions.h ../ldns/parse.h zones.h zinfo.h

View File

@@ -0,0 +1,193 @@
#include "config.h"
#include "process.h"
#include "zones.h"
#include "zinfo.h"
#include "server.h"
ldns_pkt_rcode
process_pkts(struct socket_service* sv, ldns_pkt* q, ldns_pkt* r,
struct zones_t* zones)
{
if(ldns_pkt_edns(q)) {
ldns_pkt_set_edns_do(r, ldns_pkt_edns_do(q));
ldns_pkt_set_edns_udp_size(r, 4096);
}
if(ldns_pkt_tsig(q)) {
printf("tsig todo\n");
}
switch(ldns_pkt_get_opcode(q)) {
case LDNS_PACKET_QUERY:
return process_pkt_query(sv, q, r, zones);
case LDNS_PACKET_NOTIFY:
return process_pkt_notify(sv, q, r, zones);
default:
return LDNS_RCODE_NOTIMPL;
}
}
ldns_pkt_rcode
process_pkt_notify(struct socket_service* sv, ldns_pkt* q, ldns_pkt* r,
struct zones_t* zones)
{
(void)(sv); (void)(q); (void)(r); (void)zones;
return LDNS_RCODE_NOTIMPL;
}
ldns_pkt_rcode
process_pkt_query(struct socket_service* sv, ldns_pkt* q, ldns_pkt* r,
struct zones_t* zones)
{
ldns_rr *qrr;
struct zone_entry_t* entry ;
if(ldns_pkt_qdcount(q) != 1) /* one question */
return LDNS_RCODE_FORMERR;
qrr = ldns_rr_list_rr(ldns_pkt_question(q), 0);
/* find query name zone */
entry = zones_find_rdf(zones, ldns_rr_owner(qrr),
ldns_rr_get_class(qrr));
if(!entry) {
return LDNS_RCODE_REFUSED;
}
printf("Got zone for q. %s\n", entry->zstr);
/* copy question */
ldns_pkt_push_rr(r, LDNS_SECTION_QUESTION, ldns_rr_clone(qrr));
switch(ldns_rr_get_type(qrr)) {
case LDNS_RR_TYPE_ANY:
ldns_pkt_set_aa(r, false);
case LDNS_RR_TYPE_SOA:
return process_pkt_soa(sv, q, r, entry);
case LDNS_RR_TYPE_AXFR:
return process_pkt_axfr(sv, entry);
case LDNS_RR_TYPE_IXFR:
return process_pkt_ixfr(sv, q, r, entry);
default:
return LDNS_RCODE_REFUSED;
}
}
ldns_pkt_rcode
process_pkt_soa(struct socket_service* sv, ldns_pkt* q, ldns_pkt* r,
struct zone_entry_t* entry)
{
ldns_rr_list* soa = ldns_rr_list_clone(entry->zinfo->last_soa);
(void)sv; (void)q;
if(!soa) /* have zone but not soa; no data for zone */
return LDNS_RCODE_SERVFAIL;
/* put the answer into the packet */
ldns_pkt_push_rr_list(r, LDNS_SECTION_ANSWER, soa);
return LDNS_RCODE_NOERROR;
}
ldns_pkt_rcode
process_pkt_ixfr(struct socket_service* sv, ldns_pkt* q, ldns_pkt* r,
struct zone_entry_t* entry)
{
uint32_t serial_from, serial_to;
ldns_rr_list *rr_add=0, *rr_remove=0;
ldns_rr *soa_from=0;
ldns_rr_list *soa_to=0;
if(ldns_pkt_nscount(q) != 1 ||
ldns_rr_get_type(ldns_rr_list_rr(ldns_pkt_authority(q), 0))
!= LDNS_RR_TYPE_SOA) {
printf("ixfr without serial indication\n");
return LDNS_RCODE_FORMERR;
}
if(!entry->zinfo->is_present) {
printf("ixfr request for zone without data\n");
return LDNS_RCODE_SERVFAIL;
}
serial_to = entry->zinfo->last_serial;
serial_from = ldns_rdf2native_int32(ldns_rr_rdf(
ldns_rr_list_rr(ldns_pkt_authority(q), 0), 2));
soa_to = ldns_rr_list_clone(entry->zinfo->last_soa);
if(!soa_to) {
return LDNS_RCODE_SERVFAIL;
}
if(serial_to == serial_from) {
printf("ixfr request for latest version\n");
ldns_pkt_push_rr_list(r, LDNS_SECTION_ANSWER, soa_to);
return LDNS_RCODE_NOERROR;
}
/* if UDP - reply with SOA and TC indication */
if(!sv->is_tcp) {
ldns_pkt_set_tc(r, true);
ldns_pkt_push_rr_list(r, LDNS_SECTION_ANSWER, soa_to);
return LDNS_RCODE_NOERROR;
}
zinfo_get_zone_diff(entry, serial_from, serial_to, &rr_remove,
&rr_add, &soa_from, &soa_to);
if(!rr_remove || !rr_add || !soa_from || !soa_to) {
printf("get_zone_diff failed, fallback to AXFR\n");
return process_pkt_axfr(sv, entry);
}
/* create rrlist for reply */
if(sv->reply)
ldns_rr_list_deep_free(sv->reply);
sv->reply = ldns_rr_list_new();
if(!sv->reply) {
printf("out of memory\n");
return LDNS_RCODE_SERVFAIL;
}
/* a 'condensed' IXFR zone transfer (see RFC 1995) */
ldns_rr_list_push_rr(sv->reply, ldns_rr_clone(soa_to));
ldns_rr_list_push_rr(sv->reply, soa_from);
/* deletes */
ldns_rr_list_cat(sv->reply, rr_remove);
ldns_rr_list_push_rr(sv->reply, ldns_rr_clone(soa_to));
/* adds */
ldns_rr_list_cat(sv->reply, rr_add);
ldns_rr_list_push_rr(sv->reply, soa_to);
/* not deep free since rrs moved to the answer */
ldns_rr_list_free(rr_remove);
ldns_rr_list_free(rr_add);
/* do not need to delete soa_from, soa_to: they are in rrlist. */
return LDNS_RCODE_NOERROR;
}
ldns_pkt_rcode
process_pkt_axfr(struct socket_service* sv, struct zone_entry_t* entry)
{
uint32_t serial;
ldns_zone* z = 0;
serial = entry->zinfo->last_serial;
zinfo_get_zone_full(entry, serial, &z);
if(!z) {
/* no data for this zone! */
printf("Could not get latest zone info for zone %s %u\n",
entry->zstr, serial);
return LDNS_RCODE_SERVFAIL;
}
/* create list of RRs in sv->rrlist */
if(sv->reply)
ldns_rr_list_deep_free(sv->reply);
sv->reply = ldns_rr_list_new();
if(!sv->reply) {
printf("out of memory\n");
return LDNS_RCODE_SERVFAIL;
}
/* move zone contents over */
ldns_rr_list_push_rr(sv->reply, ldns_rr_clone(ldns_zone_soa(z)));
ldns_rr_list_cat(sv->reply, ldns_zone_rrs(z));
ldns_rr_list_push_rr(sv->reply, ldns_rr_clone(ldns_zone_soa(z)));
ldns_rr_list_set_rr_count(ldns_zone_rrs(z), 0);
ldns_zone_deep_free(z);
return LDNS_RCODE_NOERROR;
}

View File

@@ -0,0 +1,51 @@
/*
* process.h, process queries to determine the answer RRs and packets.
*/
#ifndef PROCESS_H
#define PROCESS_H
struct socket_service;
struct zones_t;
struct zone_entry_t;
/**
* Calculate the reply for the query in q. Put answer in packet p.
* P is an empty packet on routine start, with header.
*/
ldns_pkt_rcode process_pkts(struct socket_service* sv,
ldns_pkt* q, ldns_pkt* r, struct zones_t* zones);
/**
* Process QUERY
*/
ldns_pkt_rcode process_pkt_query(struct socket_service* sv,
ldns_pkt* q, ldns_pkt* r, struct zones_t* zones);
/**
* Process NOTIFY
*/
ldns_pkt_rcode process_pkt_notify(struct socket_service* sv,
ldns_pkt* q, ldns_pkt* r, struct zones_t* zones);
/**
* Process SOA queries
* pass correct zone entry.
*/
ldns_pkt_rcode process_pkt_soa(struct socket_service* sv,
ldns_pkt* q, ldns_pkt* r, struct zone_entry_t* entry);
/**
* Process IXFR
* pass correct zone entry.
*/
ldns_pkt_rcode process_pkt_ixfr(struct socket_service* sv,
ldns_pkt* q, ldns_pkt* r, struct zone_entry_t* entry);
/**
* Process AXFR
* pass correct zone entry.
*/
ldns_pkt_rcode process_pkt_axfr(struct socket_service* sv,
struct zone_entry_t* entry);
#endif /* PROCESS_H */

View File

@@ -0,0 +1,632 @@
#include "config.h"
#include "config_file.h"
#include "server.h"
#include "zones.h"
#include "process.h"
/* global variables set by signals */
static int work = 1;
static int hupped = 0;
/* signal handler for server */
void server_handle_signal(int sig)
{
switch(sig) {
case SIGHUP:
hupped = 1;
work = 0;
break;
case SIGTERM:
case SIGINT:
case SIGQUIT:
work = 0;
break;
default:
printf("unhandled signal %d\n", sig);
break;
}
}
int server_start(const char* config)
{
struct server_info_t* sinfo = (struct server_info_t*)calloc(1,
sizeof(struct server_info_t));
if(!sinfo) {
printf("out of memory\n");
return 0;
}
FD_ZERO(&sinfo->rset);
FD_ZERO(&sinfo->wset);
FD_ZERO(&sinfo->eset);
work = 1;
hupped = 0;
signal(SIGHUP, server_handle_signal);
signal(SIGQUIT, server_handle_signal);
signal(SIGTERM, server_handle_signal);
signal(SIGINT, server_handle_signal);
signal(SIGPIPE, SIG_IGN);
sinfo->zones = zones_create();
sinfo->cfg = config_file_create(config);
config_file_read(sinfo->cfg, config, sinfo->zones);
zones_read(sinfo->zones);
server_bind(sinfo, sinfo->cfg->port);
if(!sinfo->sock_list) {
printf("Could not start server.\n");
server_free(sinfo);
return 0;
}
printf("service for %d zones (%s) on port %d\n",
(int)sinfo->zones->ztree->count, config, sinfo->cfg->port);
printf("Masterdont started pid %d\n", (int)getpid());
while(work) {
server_handle_net(sinfo);
}
server_free(sinfo);
return hupped;
}
void server_handle_net(struct server_info_t *sinfo)
{
struct socket_service* p, **prevp;
int delete_me;
fd_set rset, wset, eset;
rset = sinfo->rset;
wset = sinfo->wset;
eset = sinfo->eset;
if(select(sinfo->maxfd+1, &rset, &wset, &eset, NULL) == -1) {
if(errno==EINTR)
return;
printf("select: %s\n", strerror(errno));
return;
}
p = sinfo->sock_list;
prevp = &sinfo->sock_list;
while(p) {
delete_me = 0;
if(FD_ISSET(p->s, &rset))
handle_read(sinfo, p, &delete_me, sinfo->zones);
if(!delete_me && FD_ISSET(p->s, &wset))
handle_write(sinfo, p, &delete_me);
/* eset ignored */
if(delete_me) {
printf("delete me\n");
FD_CLR(p->s, &sinfo->rset);
FD_CLR(p->s, &sinfo->wset);
FD_CLR(p->s, &sinfo->eset);
if(p->is_tcp)
sinfo->num_tcp --;
/* cannot lower maxfd */
*prevp = p->next; /* snip out of list */
server_service_free(p);
p = *prevp; /* go to next */
} else {
prevp = &p->next;
p = p->next;
}
}
}
void server_free(struct server_info_t* sinfo)
{
struct socket_service* p = sinfo->sock_list, *np=0;
config_file_delete(sinfo->cfg);
zones_free(sinfo->zones);
while(p) {
np = p->next;
server_service_free(p);
p = np;
}
free(sinfo);
}
void server_bind(struct server_info_t* sinfo, int port)
{
struct addrinfo hints;
struct addrinfo *res = 0;
struct addrinfo *p = 0;
int err=0;
char service[16];
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_flags = AI_PASSIVE
#ifdef AI_NUMERICSERV
| AI_NUMERICSERV
#endif
;
sprintf(service, "%d", port);
if((err=getaddrinfo(NULL, service, &hints, &res)) != 0) {
printf("getaddrinfo: %s\n", gai_strerror(err));
return;
}
p = res;
while(p)
{
/* only TCP and UDP */
if(p->ai_protocol == IPPROTO_TCP ||
p->ai_protocol == IPPROTO_UDP) {
struct socket_service* sv;
sv = server_service_create(p);
if(!sv) {
err=errno;
} else {
sv->next = sinfo->sock_list;
sinfo->sock_list = sv;
FD_SET(sv->s, &sinfo->rset);
if(sv->s > sinfo->maxfd)
sinfo->maxfd = sv->s;
}
}
p = p->ai_next;
}
if(!sinfo->sock_list) {
printf("Fatal: No interfaces could be initialized: %s\n",
strerror(err));
}
if(res) freeaddrinfo(res);
}
struct socket_service* server_service_create(struct addrinfo *ai)
{
struct socket_service* svr;
int s;
const int on = 1;
s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if(s == -1) {
return 0;
}
if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
goto error;
}
#ifdef IPV6_V6ONLY
if(ai->ai_protocol == AF_INET6 &&
setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) {
goto error;
}
#endif
if(bind(s, ai->ai_addr, ai->ai_addrlen) == -1) {
goto error;
}
if(ai->ai_socktype == SOCK_STREAM &&
listen(s, TCP_LISTEN_BACKLOG) == -1) {
goto error;
}
/* create service struct */
svr = (struct socket_service*)malloc(sizeof(struct socket_service));
if(!svr) {
errno = ENOMEM;
goto error;
}
memset(svr, 0, sizeof(struct socket_service));
svr->tcp_state = svr_tcp_listen;
svr->s = s;
if(ai->ai_socktype == SOCK_STREAM)
svr->is_tcp = 1;
svr->buffer = ldns_buffer_new(SERVER_BUFFER_SIZE);
if(!svr->buffer) {
errno = ENOMEM;
free(svr);
goto error;
}
return svr;
error:
close(s);
return 0;
}
void server_service_free(struct socket_service* svr)
{
close(svr->s);
if(svr->reply)
ldns_rr_list_deep_free(svr->reply);
if(svr->buffer)
ldns_buffer_free(svr->buffer);
free(svr);
}
void
handle_listen(struct server_info_t *sinfo, struct socket_service* listen_v)
{
struct socket_service* sh;
int newfd;
if(sinfo->num_tcp >= MAX_TCP) {
printf("Error: incoming tcp query, but MAX_TCP reached (%d)\n",
MAX_TCP);
return;
}
if((newfd=accept(listen_v->s, NULL, NULL)) == -1) {
printf("Error tcp accept: %s", strerror(errno));
return;
}
if(fcntl(newfd, F_SETFL, O_NONBLOCK) == -1) {
printf("Error fcntl: %s\n", strerror(errno));
close(newfd);
return;
}
sh = (struct socket_service*)malloc(sizeof(struct socket_service));
if(!sh) {
printf("out of memory\n");
close(newfd);
return;
}
memset(sh, 0, sizeof(struct socket_service));
sh->tcp_state = svr_tcp_read;
sh->s = newfd;
sh->buffer = ldns_buffer_new(SERVER_BUFFER_SIZE);
sh->is_tcp = 1;
if(!sh->buffer) {
printf("out of memory\n");
close(newfd);
free(sh);
return;
}
ldns_buffer_clear(sh->buffer);
if(sh->s > sinfo->maxfd)
sinfo->maxfd = sh->s;
FD_SET(sh->s, &sinfo->rset);
sinfo->num_tcp++;
/* put after the current service */
sh->next = listen_v->next;
listen_v->next = sh;
}
void handle_read(struct server_info_t *sinfo, struct socket_service* sv,
int *del, struct zones_t* zones)
{
printf("handle_read %s %s\n", sv->is_tcp?"tcp":"udp",
sv->tcp_state==svr_tcp_listen?"listen":"");
/* get the data */
if(sv->is_tcp) {
if(sv->tcp_state == svr_tcp_listen) {
handle_listen(sinfo, sv);
return;
}
if(sv->tcp_state != svr_tcp_read) {
FD_CLR(sv->s, &sinfo->rset);
return;
}
/* read some more from channel */
if(!read_tcp_query(sv, del))
return; /* continue later */
} else {
/* udp recv */
if(!read_udp_query(sv))
return;
}
/* handle request */
if(!process_query(sv, zones))
return;
if(!sv->is_tcp) {
/* sendto */
send_udp_answer(sv);
} else {
/* change socket tcp to writing mode */
sv->tcp_state = svr_tcp_write;
sv->bytes_done = 0;
FD_CLR(sv->s, &sinfo->rset);
FD_SET(sv->s, &sinfo->wset);
}
}
void handle_write(struct server_info_t *sinfo, struct socket_service* sv,
int *del)
{
if(sv->is_tcp) {
if(sv->tcp_state != svr_tcp_write) {
FD_CLR(sv->s, &sinfo->wset);
return;
}
write_tcp_answer(sv, del);
} else {
FD_CLR(sv->s, &sinfo->wset);
}
}
int read_tcp_query(struct socket_service *sv, int* del)
{
ssize_t ret;
uint16_t len;
printf("read tcp query %d\n", (int)sv->bytes_done);
if(sv->bytes_done < sizeof(len)) {
ret = read(sv->s, ldns_buffer_current(sv->buffer),
sizeof(len)-ldns_buffer_position(sv->buffer));
printf("read tcp query got %d\n", (int)ret);
if(ret == 0) {
*del = 1;
return 0;
}
if(ret == -1) {
*del = 1;
printf("read: %s\n", strerror(errno));
return 0;
}
ldns_buffer_skip(sv->buffer, ret);
if(ldns_buffer_position(sv->buffer) < sizeof(len))
return 0; /* more later */
len = ldns_buffer_read_u16_at(sv->buffer, 0);
printf("so len is %d\n", len);
ldns_buffer_clear(sv->buffer);
ldns_buffer_set_limit(sv->buffer, len);
sv->bytes_done = sizeof(len);
}
ret = read(sv->s, ldns_buffer_current(sv->buffer),
ldns_buffer_remaining(sv->buffer));
printf("read tcp query content got %d\n", (int)ret);
if(ret == 0) {
*del = 1;
return 0;
}
if(ret == -1) {
*del = 1;
printf("read: %s\n", strerror(errno));
return 0;
}
ldns_buffer_skip(sv->buffer, ret);
if(ldns_buffer_remaining(sv->buffer) > 0) {
return 0;
}
ldns_buffer_flip(sv->buffer);
return 1;
}
int read_udp_query(struct socket_service *sv)
{
ssize_t sz;
ldns_buffer_clear(sv->buffer);
printf("udp read\n");
sv->peerlen = sizeof(sv->peer);
sz = recvfrom(sv->s, ldns_buffer_begin(sv->buffer),
ldns_buffer_capacity(sv->buffer),
0, (struct sockaddr*)&sv->peer, &sv->peerlen);
printf("udp read %d\n", (int)sz);
if(sz == -1) {
printf("recvfrom: %s\n", strerror(errno));
return 0;
}
if(sz == 0)
return 0;
ldns_buffer_skip(sv->buffer, sz);
ldns_buffer_flip(sv->buffer);
return 1;
}
static void set_error(struct socket_service* sv, ldns_pkt_rcode rcode)
{
LDNS_QR_SET(ldns_buffer_begin(sv->buffer));
LDNS_TC_CLR(ldns_buffer_begin(sv->buffer));
LDNS_RCODE_SET(ldns_buffer_begin(sv->buffer), rcode);
}
int process_query(struct socket_service* sv, struct zones_t* zones)
{
ldns_pkt* q = 0, *r = 0;
ldns_status status;
ldns_pkt_rcode rcode = LDNS_RCODE_NOERROR;
/* if QR bit is set drop packet */
if(ldns_buffer_limit(sv->buffer) < LDNS_HEADER_SIZE ||
LDNS_QR_WIRE(ldns_buffer_begin(sv->buffer)))
return 0;
status = ldns_wire2pkt(&q, ldns_buffer_begin(sv->buffer),
ldns_buffer_limit(sv->buffer));
if(status != LDNS_STATUS_OK || !q) {
/* form error */
printf("bad packet: %s\n", ldns_get_errorstr_by_id(status));
if(q)
ldns_pkt_free(q);
set_error(sv, LDNS_RCODE_FORMERR);
return 1;
}
if(1) {
printf("Got query:\n");
ldns_pkt_print(stdout, q);
}
r = ldns_pkt_new();
ldns_pkt_set_id(r, ldns_pkt_id(q));
ldns_pkt_set_qr(r, true);
ldns_pkt_set_aa(r, true);
ldns_pkt_set_rd(r, ldns_pkt_rd(q));
rcode = process_pkts(sv, q, r, zones);
if(rcode != LDNS_RCODE_NOERROR) {
printf("answer error %d\n", rcode);
ldns_pkt_free(q);
ldns_pkt_free(r);
set_error(sv, rcode);
return 1;
}
if(sv->reply)
fill_r_up_pkt(sv, r);
if(1) {
printf("Got answer %s:\n", sv->reply?"(head, more to follow)":"pkt");
ldns_pkt_print(stdout, r);
}
ldns_buffer_clear(sv->buffer);
status = ldns_pkt2buffer_wire(sv->buffer, r);
if(status != LDNS_STATUS_OK) {
printf("could not wireformat pkt: %s\n",
ldns_get_errorstr_by_id(status));
ldns_pkt_free(q);
ldns_pkt_free(r);
return 0;
}
ldns_buffer_flip(sv->buffer);
ldns_pkt_free(q);
ldns_pkt_free(r);
return 1;
}
void send_udp_answer(struct socket_service* sv)
{
ssize_t sz = sendto(sv->s, ldns_buffer_begin(sv->buffer),
ldns_buffer_limit(sv->buffer), 0,
(struct sockaddr*)&sv->peer, sv->peerlen);
if(sz == -1) {
printf("sendto: %s\n", strerror(errno));
return;
}
if(sz < (int)ldns_buffer_limit(sv->buffer)) {
printf("sendto: message not completely sent.\n");
return;
}
}
void write_tcp_answer(struct socket_service* sv, int* del)
{
uint16_t len = htons(ldns_buffer_limit(sv->buffer));
ssize_t ret;
if(sv->bytes_done < sizeof(len)) {
ret = write(sv->s,
((uint8_t*)&len) + ldns_buffer_position(sv->buffer),
sizeof(len)-ldns_buffer_position(sv->buffer));
if(ret == 0) {
*del = 1;
return;
}
if(ret == -1) {
printf("write: %s\n", strerror(errno));
*del = 1;
return;
}
ldns_buffer_skip(sv->buffer, ret);
if(ldns_buffer_position(sv->buffer) < sizeof(len))
return; /* later */
sv->bytes_done = sizeof(len);
ldns_buffer_set_position(sv->buffer, 0);
}
ret = write(sv->s, ldns_buffer_current(sv->buffer),
ldns_buffer_remaining(sv->buffer));
if(ret == 0) {
*del = 1;
return;
}
if(ret == -1) {
printf("write: %s\n", strerror(errno));
*del = 1;
return;
}
ldns_buffer_skip(sv->buffer, ret);
if(ldns_buffer_remaining(sv->buffer) > 0)
return; /* later */
/* finished TCP packet, more? */
if(sv->reply) {
fill_r_up(sv);
/* write that next time */
return;
}
*del = 1;
return;
}
void fill_r_up_pkt(struct socket_service* sv, ldns_pkt* in_here)
{
size_t max = 512; /* max bytes in packet */
size_t now = 0;
size_t i;
size_t added = 0;
if(sv->is_tcp)
max = TCP_PKT_SIZE;
else {
/* EDNS 0 */
}
if(!sv->reply)
return;
now = LDNS_HEADER_SIZE;
for(i=0; i<ldns_pkt_qdcount(in_here); i++)
now += ldns_rr_uncompressed_size(ldns_rr_list_rr(
ldns_pkt_question(in_here), i));
/* add until the max is reached */
for(i=0; i<ldns_rr_list_rr_count(sv->reply); i++)
{
now += ldns_rr_uncompressed_size(ldns_rr_list_rr(
sv->reply, i));
if(now >= max) {
/* TCP: always add one, maybe more */
/* UDP: never cross limit. */
if(!sv->is_tcp || added != 0)
break;
}
ldns_pkt_push_rr(in_here, LDNS_SECTION_ANSWER,
ldns_rr_list_rr(sv->reply, i));
ldns_rr_list_set_rr(sv->reply, NULL, i);
added++;
}
/* fixup the rrlist */
memmove(sv->reply->_rrs, sv->reply->_rrs+added,
sizeof(ldns_rr*)*(sv->reply->_rr_count-added));
sv->reply->_rr_count -= added;
if(ldns_rr_list_rr_count(sv->reply) == 0) {
ldns_rr_list_free(sv->reply);
sv->reply = 0;
}
if(!sv->is_tcp && sv->reply) {
ldns_pkt_set_tc(in_here, true);
ldns_rr_list_deep_free(sv->reply);
sv->reply = 0;
}
}
void fill_r_up(struct socket_service* sv)
{
ldns_pkt* p = ldns_pkt_new();
ldns_status status;
if(!p) {
printf("out of memory\n");
LDNS_RCODE_SET(ldns_buffer_begin(sv->buffer),
LDNS_RCODE_SERVFAIL);
ldns_buffer_set_limit(sv->buffer, LDNS_HEADER_SIZE);
ldns_rr_list_deep_free(sv->reply);
sv->reply = 0;
return;
}
ldns_buffer_clear(sv->buffer);
ldns_pkt_set_id(p, LDNS_ID_WIRE(ldns_buffer_begin(sv->buffer)));
ldns_pkt_set_qr(p, LDNS_QR_WIRE(ldns_buffer_begin(sv->buffer)));
ldns_pkt_set_opcode(p, LDNS_OPCODE_WIRE(ldns_buffer_begin(sv->buffer)));
ldns_pkt_set_aa(p, LDNS_AA_WIRE(ldns_buffer_begin(sv->buffer)));
ldns_pkt_set_rd(p, LDNS_RD_WIRE(ldns_buffer_begin(sv->buffer)));
ldns_pkt_set_ra(p, LDNS_RA_WIRE(ldns_buffer_begin(sv->buffer)));
ldns_pkt_set_rcode(p, LDNS_RCODE_WIRE(ldns_buffer_begin(sv->buffer)));
fill_r_up_pkt(sv, p);
status = ldns_pkt2buffer_wire(sv->buffer, p);
if(status != LDNS_STATUS_OK) {
printf("could not wireformat continuation packet\n");
LDNS_RCODE_SET(ldns_buffer_begin(sv->buffer),
LDNS_RCODE_SERVFAIL);
ldns_buffer_set_limit(sv->buffer, LDNS_HEADER_SIZE);
if(sv->reply) ldns_rr_list_deep_free(sv->reply);
sv->reply = 0;
}
ldns_buffer_flip(sv->buffer);
}

View File

@@ -0,0 +1,148 @@
/*
server.h masterdont server, serves IXFR, AXFR, SOA queries.
*/
#ifndef SERVER_H
#define SERVER_H
struct zones_t;
/**
* Socket that is being serviced by the server.
*/
struct socket_service {
/* socket */
int s;
/* true if a tcp socket */
int is_tcp;
/* tcp state: listening, reading, or writing. */
enum {svr_tcp_listen, svr_tcp_read, svr_tcp_write} tcp_state;
/* bytes processed for tcp */
size_t bytes_done;
/* peer address */
struct sockaddr_storage peer;
socklen_t peerlen;
/* buffer for input/output */
ldns_buffer* buffer;
/* rrs for the reply. If not null, these RRs are part of the answer. */
ldns_rr_list* reply;
/* next in linked list */
struct socket_service* next;
};
struct server_info_t {
/* zones */
struct zones_t* zones;
/* config */
struct config_file* cfg;
/* number of open tcp connections */
int num_tcp;
/* socket list */
struct socket_service* sock_list;
/* select data, max fd */
int maxfd;
/* fd sets to select on, copied from. */
fd_set rset, wset, eset;
};
/**
* start the server, give zones, configfile (already read)
* and portnumber to bind.
* returns true if it needs to reload, false for exit.
*/
int server_start(const char* config);
/**
* free service list
*/
void server_free(struct server_info_t* s);
/**
* create service sockets on specified port.
*/
void server_bind(struct server_info_t* sinfo, int port);
/**
* create servicing struct from addr. socket, bind, (listen).
* NULL on error.
*/
struct socket_service* server_service_create(struct addrinfo *ai);
/**
* free the service, close the socket
*/
void server_service_free(struct socket_service* svr);
/**
* Perform a select and handle the events on the sockets.
*/
void server_handle_net(struct server_info_t *sinfo);
/**
* Handle read possible on serviced socket.
* Sets delete to true if connection should be closed (for tcp).
*/
void handle_read(struct server_info_t *sinfo, struct socket_service* sv,
int *del, struct zones_t* zones);
/**
* Handle write possible on serviced socket.
* Sets delete to true if connection should be closed (for tcp).
*/
void handle_write(struct server_info_t *sinfo, struct socket_service* sv,
int *del);
/**
* Handle tcp listen. Creates new socket service after accepting.
*/
void handle_listen(struct server_info_t *sinfo, struct socket_service* sv);
/**
* read tcp query from socket.
* returns true when query is finished OK. del is true on error.
*/
int read_tcp_query(struct socket_service *sv, int* del);
/**
* read udp query from socket.
* returns true when query is read OK.
*/
int read_udp_query(struct socket_service *sv);
/**
* process query.
* First result packet is in the buffer.
* More results can be found in the rrlist.
* return false if query should be dropped (no reply).
*/
int process_query(struct socket_service* sv, struct zones_t* zones);
/**
* send udp answer back to sender.
*/
void send_udp_answer(struct socket_service* sv);
/**
* send (part of) tcp answer.
* del is true when tcp should be closed up.
*/
void write_tcp_answer(struct socket_service* sv, int* del);
/**
* Dump RRs into the answer to get more reply. Makes new reply buffer.
* reply becomes NULL when last buffer is filled.
*/
void fill_r_up(struct socket_service* sv);
/**
* Dumps RRs into the answer section of the pkt.
*/
void fill_r_up_pkt(struct socket_service* sv, ldns_pkt* in_here);
#endif /* SERVER_H */

View File

@@ -0,0 +1,245 @@
/* zinfo.c - zone information */
#include "config.h"
#include "zinfo.h"
#include "zones.h"
static int cmp_version(const void* a, const void* b)
{
struct zversion_t* x = (struct zversion_t*)a;
struct zversion_t* y = (struct zversion_t*)b;
if(x->serial < y->serial)
return -1;
if(x->serial > y->serial)
return -1;
return 0;
}
static int cmp_domain(const void* a, const void* b)
{
struct zdomain_t* x = (struct zdomain_t*)a;
struct zdomain_t* y = (struct zdomain_t*)b;
return ldns_rdf_compare(x->name, y->name);
}
struct zinfo_t* zinfo_create(void)
{
struct zinfo_t* zinfo = (struct zinfo_t*)calloc(1, sizeof(*zinfo));
zinfo->is_present = 0;
ldns_rbtree_init(&zinfo->vs, cmp_version);
ldns_rbtree_init(&zinfo->zone, cmp_domain);
return zinfo;
}
static void del_vs(ldns_rbnode_t* node, void* arg)
{
(void)arg;
zversion_delete((struct zversion_t*)node);
}
static void del_domain(ldns_rbnode_t* node, void* arg)
{
(void)arg;
zdomain_delete((struct zdomain_t*)node);
}
void zinfo_delete(struct zinfo_t* zinfo)
{
if(!zinfo) return;
free(zinfo->dir);
ldns_rr_list_deep_free(zinfo->last_soa);
ldns_traverse_postorder(&zinfo->vs, del_vs, NULL);
ldns_traverse_postorder(&zinfo->zone, del_domain, NULL);
free(zinfo);
}
/** Get a pointer to a static buffer with filename */
const char* zinfo_index_name(struct zone_entry_t* entry)
{
static char buf[1024];
snprintf(buf, sizeof(buf), "%s/zone.%s.index",
entry->zinfo->dir, entry->zstr);
return buf;
}
/** Get a pointer to a static buffer with filename */
const char* zinfo_ixfr_name(struct zone_entry_t* entry, uint32_t soa)
{
static char buf[1024];
snprintf(buf, sizeof(buf), "%s/zone.%s.ixfr.%u",
entry->zinfo->dir, entry->zstr, soa);
return buf;
}
/** Get a pointer to a static buffer with filename */
const char* zinfo_full_name(struct zone_entry_t* entry, uint32_t soa)
{
static char buf[1024];
snprintf(buf, sizeof(buf), "%s/zone.%s.full.%u",
entry->zinfo->dir, entry->zstr, soa);
return buf;
}
/** see if file exists */
static int file_exists(const char* path)
{
struct stat buf;
if(stat(path, &buf) < 0) {
if(errno == ENOENT)
return 0;
printf("stat(%s): %s\n", path, strerror(errno));
return 0;
}
return 1;
}
int zinfo_read(struct zone_entry_t* entry)
{
const char* iname = zinfo_index_name(entry);
FILE* index = fopen(iname, "ra");
uint32_t serial = 0;
uint32_t last_full = 0;
int have_last_full;
if(!index) {
if(errno == ENOENT) {
printf("zone %s is empty\n", entry->zstr);
return 1;
}
perror(iname);
return 0;
}
if(fscanf(index, " %u", &serial) != 1) {
fclose(index);
printf("error reading %s\n", iname);
return 0;
}
fclose(index);
/* read versions */
while(file_exists(zinfo_ixfr_name(entry, serial))) {
struct zversion_t* v = zversion_read(entry, serial);
if(!v) return 0;
if(file_exists(zinfo_full_name(entry, serial))) {
have_last_full = 1;
last_full = serial;
}
serial = v->next_serial;
}
if(file_exists(zinfo_full_name(entry, serial))) {
have_last_full = 1;
last_full = serial;
}
/* read full zone */
if(!have_last_full) {
printf("No full zone file available for zone %s\n",
entry->zstr);
return 0;
}
entry->zinfo->last_serial = serial;
entry->zinfo->is_present = 1;
if(!zfull_read(entry, last_full))
return 0;
return 1;
}
int zinfo_get_zone_diff(struct zone_entry_t* entry, uint32_t serial_from,
uint32_t serial_to, ldns_rr_list** rr_remove, ldns_rr_list** rr_add,
ldns_rr** soa_from, ldns_rr** soa_to)
{
/* DIFFs stored in memory and served from memory without copy */
/* TODO */
}
void zinfo_get_zone_full(struct zone_entry_t* entry, uint32_t serial,
ldns_zone** z)
{
/* full zone kept in memory, served from memory after a fork
* (and close of other sockets after fork) */
/* TODO */
}
void zversion_delete(struct zversion_t* v)
{
if(!v) return;
ldns_rr_list_deep_free(v->ixfr);
free(v);
}
struct zversion_t* zversion_read(struct zone_entry_t* entry, uint32_t serial)
{
const char* fn = zinfo_ixfr_name(entry, serial);
struct zversion_t* v;
FILE* in = fopen(fn, "ra");
ldns_status status;
ldns_rr* rr = 0;
uint32_t dttl = 3600;
ldns_rdf* origin = 0, *prev = 0;
int line_nr = 1;
if(!in) {
perror(fn);
return NULL;
}
v = (struct zversion_t*)calloc(1, sizeof(*v));
if(!v) {
fclose(in);
printf("out of memory\n");
return NULL;
}
v->serial = serial;
v->ixfr = ldns_rr_list_new();
while(!feof(in)) {
status = ldns_rr_new_frm_fp_l(&rr, in, &dttl, &origin,
&prev, &line_nr);
if(status == LDNS_STATUS_SYNTAX_TTL ||
status == LDNS_STATUS_SYNTAX_ORIGIN ||
status == LDNS_STATUS_SYNTAX_EMPTY)
continue;
if(status != LDNS_STATUS_OK) {
printf("error %s:%d: %s\n", fn, line_nr,
ldns_get_errorstr_by_id(status));
fclose(in);
ldns_rdf_deep_free(origin);
ldns_rdf_deep_free(prev);
ldns_rr_list_deep_free(v->ixfr);
free(v);
return NULL;
}
ldns_rr_list_push_rr(v->ixfr, rr);
}
ldns_rdf_deep_free(origin);
ldns_rdf_deep_free(prev);
fclose(in);
if(ldns_rr_list_rr_count(v->ixfr) < 1 ||
ldns_rr_get_type(ldns_rr_list_rr(v->ixfr, 0))
!= LDNS_RR_TYPE_SOA) {
printf("invalid IXFR format in %s\n", fn);
ldns_rr_list_deep_free(v->ixfr);
free(v);
return NULL;
}
v->next_serial = ldns_rdf2native_int32(ldns_rr_rdf(
ldns_rr_list_rr(v->ixfr, 0), 2));
return v;
}
static void del_rrset(ldns_rbnode_t* node, void* arg)
{
(void)arg;
zrrset_delete((struct zrrset_t*)node);
}
void zdomain_delete(struct zdomain_t* d)
{
if(!d) return;
ldns_traverse_postorder(&d->rrsets, del_rrset, NULL);
ldns_rdf_deep_free(d->name);
free(d);
}
int zfull_read(struct zone_entry_t* entry, uint32_t serial)
{
}
void zrrset_delete(struct zrrset_t* r)
{
if(!r) return;
ldns_rr_list_deep_free(r->list);
free(r);
}

View File

@@ -0,0 +1,112 @@
/* zinfo.h - zone info */
#ifndef ZINFO_H
#define ZINFO_H
struct zone_entry_t;
/**
* Store zone content information
* zone identity is stored in zone_entry_t.
*/
struct zinfo_t {
/**
* directory to use for disk storage
* o zone.<name>.index -- oldest SOA number in dir
* o zone.<name>.ixfr.<soa> -- text format ixfr to next version.
* o zone.<name>.full.<soa> -- text format full zone file.
* The full file may be omitted for many versions. At least one.
*/
char* dir;
/** is the zone present at all (or empty, no data) */
int is_present;
/** latest serial number */
uint32_t last_serial;
/** latest SOA (also present in complete zone) plus rrsigs */
ldns_rr_list* last_soa;
/** tree of versions, sorted by serial and contains IXFRs.
* the last serial number is not in here, but kept as complete zone. */
ldns_rbtree_t vs;
/** for last version, the complete zone. zdomain_t sorted by name */
ldns_rbtree_t zone;
};
/**
* A zone version
*/
struct zversion_t {
/** rbtree node, sorted by serial */
ldns_rbnode_t node;
/** serial number */
uint32_t serial;
/** next serial number */
uint32_t next_serial;
/** ixfr contents */
ldns_rr_list* ixfr;
};
/**
* A domain name in the complete zone tree
*/
struct zdomain_t {
/** rbtree node */
ldns_rbnode_t node;
/** rdf name */
ldns_rdf* name;
/** the rrsets present, sorted by type */
ldns_rbtree_t rrsets;
};
/**
* An rrset at a name in the complete zone tree
*/
struct zrrset_t {
/** rbtree node */
ldns_rbnode_t node;
/** rr set */
ldns_rr_list* list;
};
/**
* Create a zinfo. No data, empty.
*/
struct zinfo_t* zinfo_create(void);
/**
* Delete a zinfo
*/
void zinfo_delete(struct zinfo_t* zinfo);
/**
* Read zone info from stable storage (disk)
*/
int zinfo_read(struct zone_entry_t* entry);
/** Get a pointer to a static buffer with filename */
const char* zinfo_index_name(struct zone_entry_t* entry);
/** Get a pointer to a static buffer with filename */
const char* zinfo_ixfr_name(struct zone_entry_t* entry, uint32_t soa);
/** Get a pointer to a static buffer with filename */
const char* zinfo_full_name(struct zone_entry_t* entry, uint32_t soa);
int zinfo_get_zone_diff(struct zone_entry_t* entry, uint32_t serial_from,
uint32_t serial_to, ldns_rr_list** rr_remove, ldns_rr_list** rr_add,
ldns_rr** soa_from, ldns_rr** soa_to);
void zinfo_get_zone_full(struct zone_entry_t* entry, uint32_t serial,
ldns_zone** z);
/* ----------------------- zversion ---------------------- */
void zversion_delete(struct zversion_t* v);
struct zversion_t* zversion_read(struct zone_entry_t* entry, uint32_t serial);
/* ----------------------- zdomain ---------------------- */
void zdomain_delete(struct zdomain_t* d);
int zfull_read(struct zone_entry_t* entry, uint32_t serial);
/* ----------------------- zrrset ---------------------- */
void zrrset_delete(struct zrrset_t* r);
#endif

View File

@@ -0,0 +1,126 @@
#include "config.h"
#include "zones.h"
#include "zinfo.h"
/** compare two zone_entry */
static int zones_cmp(const void* a, const void* b)
{
struct zone_entry_t* x = (struct zone_entry_t*)a;
struct zone_entry_t* y = (struct zone_entry_t*)b;
if(x->zclass != y->zclass) {
if(x->zclass < y->zclass)
return -1;
return 1;
}
return ldns_rdf_compare(x->zname, y->zname);
}
struct zones_t* zones_create()
{
struct zones_t* zones = (struct zones_t*)malloc(
sizeof(struct zones_t));
if(!zones)
return NULL;
zones->ztree = ldns_rbtree_create(zones_cmp);
if(!zones->ztree) {
free(zones);
return NULL;
}
return zones;
}
void zones_read(struct zones_t* zones)
{
struct zone_entry_t* entry;
LDNS_RBTREE_FOR(entry, struct zone_entry_t*, zones->ztree) {
if(!zinfo_read(entry)) {
fprintf(stderr, "could not read zone %s\n",
entry->zstr);
exit(1);
}
}
}
struct zone_entry_t* zones_find(struct zones_t* zones, const char* name,
uint16_t fclass)
{
ldns_rdf* rd = ldns_dname_new_frm_str(name);
struct zone_entry_t* found;
if(!rd) {
printf("out of memory\n");
return NULL;
}
found = zones_find_rdf(zones, rd, fclass);
ldns_rdf_deep_free(rd);
return found;
}
struct zone_entry_t* zones_find_rdf(struct zones_t* zones, ldns_rdf* name,
uint16_t fclass)
{
struct zone_entry_t z;
ldns_rbnode_t* found;
z.node.key = &z;
z.zname = name;
z.zclass = fclass;
found = ldns_rbtree_search(zones->ztree, &z);
return (struct zone_entry_t*)found;
}
struct zone_entry_t* zones_insert(struct zones_t* zones, const char* name,
uint16_t nclass)
{
struct zone_entry_t* entry = zones_find(zones, name, nclass);
if(entry)
return entry;
entry = (struct zone_entry_t*)malloc(sizeof(struct zone_entry_t));
memset(entry, 0, sizeof(struct zone_entry_t));
entry->node.key = entry;
entry->zstr = strdup(name);
if(!entry->zstr) {
free(entry);
return NULL;
}
entry->zclass = nclass;
entry->zname = ldns_dname_new_frm_str(name);
if(!entry->zname) {
free(entry);
free(entry->zstr);
return NULL;
}
entry->zinfo = zinfo_create();
if(!entry->zinfo) {
free(entry);
free(entry->zstr);
ldns_rdf_deep_free(entry->zname);
return NULL;
}
/* insert entry into data structure */
ldns_rbtree_insert(zones->ztree, &entry->node);
return entry;
}
void zone_entry_free(struct zone_entry_t* entry)
{
if(!entry) return;
zinfo_delete(entry->zinfo);
free(entry->zstr);
ldns_rdf_deep_free(entry->zname);
free(entry);
}
static void z_free(ldns_rbnode_t* n, void* arg)
{
(void)arg;
zone_entry_free((struct zone_entry_t*)n);
}
void zones_free(struct zones_t* zones)
{
if(!zones)
return;
ldns_traverse_postorder(zones->ztree, z_free, NULL);
ldns_rbtree_free(zones->ztree);
free(zones);
}

View File

@@ -0,0 +1,76 @@
/*
zones.h keep list of zones to handle with backend info.
*/
#ifndef ZONES_H
#define ZONES_H
struct zinfo_t;
/**
* zone entry information
*/
struct zone_entry_t {
/** rbtree node info */
ldns_rbnode_t node;
/** zone name */
ldns_rdf* zname;
/** zone name in text */
char* zstr;
/** zone class */
uint16_t zclass;
/** zone info */
struct zinfo_t* zinfo;
/** next in linked list */
struct zone_entry_t* next;
};
/**
* Keep zones information.
*/
struct zones_t {
/** tree of zone_entry, sorted by zname, zclass */
ldns_rbtree_t* ztree;
};
/**
* create new empty zones struct
*/
struct zones_t* zones_create(void);
/**
* Read all the zone entry storage
*/
void zones_read(struct zones_t* zones);
/**
* Find zone entry given the name
* or NULL if doesn't exist
*/
struct zone_entry_t* zones_find(struct zones_t* zones, const char* name,
uint16_t fclass);
/**
* find a zone based on rdf
*/
struct zone_entry_t* zones_find_rdf(struct zones_t* zones, ldns_rdf* name,
uint16_t fclass);
/**
* Insert new entry for zone name, returns new entry.
* or NULL if out of memory.
*/
struct zone_entry_t* zones_insert(struct zones_t* zones, const char* name,
uint16_t nclass);
/**
* free a zone entry
*/
void zone_entry_free(struct zone_entry_t* entry);
/**
* free zones data structure
*/
void zones_free(struct zones_t* zones);
#endif /* ZONES_H */