Commit Diff
Diff:
1945abea6162c67834048ca131285d386ca76d97
f98bb34d3faf8c472168d779ec7a343d86e954b9
Commit:
f98bb34d3faf8c472168d779ec7a343d86e954b9
Tree:
892c3b39e09e1b7199b2f9923617976cb3061c64
Author:
pbug <pbug@delphinusdns.org>
Committer:
pbug <pbug@delphinusdns.org>
Date:
Mon Sep 19 19:59:23 2011 UTC
Message:
Change to berkeley db 4.6+, this allows us to use shared sysv memory needed to have multiple server instances that do recursing. The database is now on disk with this change, with a 260KB (default) SYSV shared memory cache. The cache size can be tweaked with the newly added -c flag. The OS has upper limits for SYSV shared memory though and the -c value must account for 25% more for internal purposes. Revert db.h struct domain to static arrays instead of pointers, this is necessary because we want to use shared memory between the database. This reverts revision 1.13 of db.h which was commited on Sun Mar 28 20:18:26 2010 UTC. So far wildcarddnsd has been extremely stable with the pointers, I'm hoping we'll get this much stability back. Added passive AXFR code. The axfr server does NOT bind to port 53 but rather another port, luckily that is configurable with other nameservers like BIND9. BIND nameservers wanting to make use of a wildcarddnsd master should turn IXFR queries off. Fix a small error that would bring wildcarddnsd to a SIGSEGV due to doing an FD_ISSET() on a non-descriptor. This only happens when one doesn't have the logging system turned on so it took a while for me to find it. Added the -n flag which allows multiple forked copies of wdnsd to be started. This is similar to how apache 1.3 web server does it.
blob - df52216bc37c32f7bfecf1aa751e0d16d78b6d78
blob + d0cb7a09ea17251c8b86325fa26355285612fcab
--- Makefile.freebsd7
+++ Makefile.freebsd7
@@ -1,19 +1,15 @@
PROG=wildcarddnsd
-SRCS=main.c parse.c reply.c additional.c region.c wildcard.c recurse.c res_random.c bsd-arc4random.c log.c
+SRCS=main.c parse.c reply.c additional.c region.c wildcard.c recurse.c res_random.c bsd-arc4random.c log.c axfr.c
-#CFLAGS= -DDEBUG -g -Wall
-CFLAGS= -Wall -g
-LDFLAGS= -Wall -g
-LDADD= -lcrypto -lssl
+CFLAGS= -Wall -g -I/usr/local/include/db48/
+LDFLAGS= -Wall -g -L/usr/local/lib/db48/
+LDADD= -lcrypto -lssl -ldb
OBJDIR=.
BINDIR=/usr/local/sbin
MANDIR=/usr/local/man/man
MAN= wildcarddnsd.8
-
-#afterinstall:
-# @freebsd/install.sh
.include <bsd.prog.mk>
blob - a8a3e541aa744831d264cca9a569ec82a6270588
blob + 3b364152081a0f632e8096db9196443178cdd462
--- Makefile.freebsd8
+++ Makefile.freebsd8
@@ -1,19 +1,15 @@
PROG=wildcarddnsd
-SRCS=main.c parse.c reply.c additional.c region.c wildcard.c recurse.c res_random.c log.c
+SRCS=main.c parse.c reply.c additional.c region.c wildcard.c recurse.c res_random.c log.c axfr.c
-#CFLAGS= -DDEBUG -g -Wall
-CFLAGS= -Wall -g
-LDFLAGS= -Wall -g
-LDADD= -lcrypto -lssl
+CFLAGS= -Wall -g -I/usr/local/include/db48/
+LDFLAGS= -Wall -g -L/usr/local/lib/db48/
+LDADD= -lcrypto -lssl -ldb
OBJDIR=.
BINDIR=/usr/local/sbin
MANDIR=/usr/local/man/man
MAN= wildcarddnsd.8
-
-#afterinstall:
-# @freebsd/install.sh
.include <bsd.prog.mk>
blob - 8a62e12c27355ddab21b1e154ef12dca1f285535
blob + a6b3f88a4c55c1c5e045eecc29dc59788662ff9e
--- Makefile.linux
+++ Makefile.linux
@@ -16,7 +16,8 @@ build:
$(CC) $(CFLAGS) -c bsd-arc4random.c
$(CC) $(CFLAGS) -c res_random.c
$(CC) $(CFLAGS) -c log.c
- $(CC) $(CFLAGS) -o wildcarddnsd additional.o main.o parse.o reply.o region.o wildcard.o recurse.o bsd-arc4random.o res_random.o log.o $(LDADD)
+ $(CC) $(CFLAGS) -c axfr.c
+ $(CC) $(CFLAGS) -o wildcarddnsd additional.o main.o parse.o reply.o region.o wildcard.o recurse.o bsd-arc4random.o res_random.o log.o axfr.o $(LDADD)
install:
blob - 37d6e44b806083d0d7bdc463ca99b40e6ff831cf
blob + 52b1f9b768e2faaa5c3081ad38d425e37fc4d294
--- Makefile.netbsd
+++ Makefile.netbsd
@@ -1,18 +1,14 @@
PROG=wildcarddnsd
-SRCS=main.c parse.c reply.c additional.c region.c wildcard.c recurse.c res_random.c bsd-arc4random.c log.c
+SRCS=main.c parse.c reply.c additional.c region.c wildcard.c recurse.c res_random.c bsd-arc4random.c log.c axfr.c
-#CFLAGS= -DDEBUG -g -Wall
-CFLAGS= -Wall -g
-LDFLAGS= -Wall -g
-LDADD= -lcrypto -lssl
+CFLAGS= -Wall -g -I/usr/pkg/include/db46/
+LDFLAGS= -Wall -g -L/usr/pkg/lib -R/usr/pkg/lib
+LDADD= -lcrypto -lssl -ldb46
OBJDIR=.
BINDIR=/usr/local/sbin
MAN= wildcarddnsd.8
-
-#afterinstall:
-# @freebsd/install.sh
.include <bsd.prog.mk>
blob - 1b992446c6d789069e132dc5e673319c597b01c2
blob + ac063f1911402effabab59bf15d24196ba56a177
--- Makefile.openbsd
+++ Makefile.openbsd
@@ -1,11 +1,11 @@
PROG=wildcarddnsd
-SRCS=main.c parse.c reply.c additional.c region.c wildcard.c recurse.c res_random.c log.c
+SRCS=main.c parse.c reply.c additional.c region.c wildcard.c recurse.c res_random.c log.c axfr.c
#CFLAGS= -DDEBUG -g -Wall
-CFLAGS= -Wall -g
-LDFLAGS= -Wall -g
-LDADD= -lcrypto -lssl
+CFLAGS= -Wall -g -I/usr/local/include/db4
+LDFLAGS= -Wall -g -L/usr/local/lib/db4
+LDADD= -lcrypto -lssl -ldb
OBJDIR=.
BINDIR=/usr/local/sbin
blob - 009f8f69e3c361e07375ae8315820de3e465c635
blob + 1dc06cbd1d95ec50118fd6565683bfc8eb660160
--- README
+++ README
@@ -1,4 +1,4 @@
-$Id: README,v 1.20 2011/04/22 16:43:34 pbug Exp $
+$Id: README,v 1.21 2011/09/19 19:59:23 pbug Exp $
1. README
2. WHY WILDCARDNS?
@@ -41,7 +41,7 @@ followed by su'ing and make install. Wildcarddnsd ins
is where the chroot is set).
Under OpenSuse 10.3 and Ubuntu I noticed the following files missing:
-cvs, gcc development and sleepycat's berkeley db (4.5) development. These
+cvs, gcc development and sleepycat's berkeley db (4.8) development. These
had to be install prior to making wildcarddnsd. You basically know when you
need to install these, when make barfs with db.h missing (or in extreme cases
sys/param.h missing).
@@ -51,6 +51,10 @@ do this manually. Also by default the config file is
/etc/wildcarddns.conf this can be changed by adding the -f option to
wildcarddnsd.
+Also make sure the /var/db directory exists as wildcardnsd's berkeley database
+will be set in /var/db/wdns, this is a new option starting in BETA_7 which
+is slated for a 2012 release.
+
A sample config file exists with the sources. example7.conf was a real life
config once.
@@ -62,7 +66,7 @@ you may have to install openssl-dev packages.
----------------
------------------+--------------------+---------------------+
-Operating System: | makes and compiles | responds to queries |
+Operating System**| makes and compiles | responds to queries |
------------------+--------------------+---------------------+
FreeBSD 7.3 | yes | yes |
------------------+--------------------+---------------------+
@@ -70,7 +74,7 @@ FreeBSD 8.2 | yes | yes
------------------+--------------------+---------------------+
NetBSD 5.1 | yes* | yes |
------------------+--------------------+---------------------+
-OpenBSD 4.8 | yes | yes |
+OpenBSD 5.0 | yes | yes |
------------------+--------------------+---------------------+
Ubuntu 10.10 | yes | yes |
------------------+--------------------+---------------------+
@@ -78,6 +82,7 @@ Debian 6.0 | yes | yes
------------------+--------------------+---------------------+
* there was a period in time that NetBSD didn't compile
+** All Operating Systems require Berkeley DB 4.6 or higher.
5. EXAMPLES
-----------
blob - 36b9c99cecd14837de350cca46df5b244db210da
blob + 23aa952501b6a153791560a9e342e279aa4342ad
--- additional.c
+++ additional.c
@@ -36,7 +36,7 @@ int additional_ptr(char *, int, struct domain *, char
extern int compress_label(u_char *, int, int);
-static const char rcsid[] = "$Id: additional.c,v 1.11 2011/02/13 18:06:53 pbug Exp $";
+static const char rcsid[] = "$Id: additional.c,v 1.12 2011/09/19 19:59:23 pbug Exp $";
/*
@@ -190,7 +190,7 @@ additional_aaaa(char *name, int namelen, struct domain
answer->rdlength = htons(sizeof(struct in6_addr));
- memcpy((char *)&answer->rdata, (char *)sd->aaaa[aaaa_count], sizeof(struct in6_addr));
+ memcpy((char *)&answer->rdata, (char *)&sd->aaaa[aaaa_count], sizeof(struct in6_addr));
offset += sizeof(struct answer);
(*retcount)++;
@@ -223,7 +223,7 @@ additional_aaaa(char *name, int namelen, struct domain
answer->rdlength = htons(sizeof(struct in6_addr));
- memcpy((char *)&answer->rdata, (char *)sd->aaaa[aaaa_count], sizeof(struct in6_addr));
+ memcpy((char *)&answer->rdata, (char *)&sd->aaaa[aaaa_count], sizeof(struct in6_addr));
offset += sizeof(struct answer);
(*retcount)++;
}
@@ -288,25 +288,25 @@ additional_mx(char *name, int namelen, struct domain *
answer->type = htons(DNS_TYPE_MX);
answer->class = htons(DNS_CLASS_IN);
answer->ttl = htonl(sd->ttl);
- answer->mx_priority = htons(sd->mx[mx_count]->preference);
+ answer->mx_priority = htons(sd->mx[mx_count].preference);
offset += sizeof(struct answer);
- if ((offset + sd->mx[mx_count]->exchangelen) > replylen) {
+ if ((offset + sd->mx[mx_count].exchangelen) > replylen) {
offset = rroffset;
goto out;
}
- memcpy((char *)&reply[offset], (char *)sd->mx[mx_count]->exchange, sd->mx[mx_count]->exchangelen);
+ memcpy((char *)&reply[offset], (char *)sd->mx[mx_count].exchange, sd->mx[mx_count].exchangelen);
- offset += sd->mx[mx_count]->exchangelen;
- tmplen = compress_label((u_char*)reply, offset, sd->mx[mx_count]->exchangelen);
+ offset += sd->mx[mx_count].exchangelen;
+ tmplen = compress_label((u_char*)reply, offset, sd->mx[mx_count].exchangelen);
if (tmplen != 0) {
- answer->rdlength = htons((sd->mx[mx_count]->exchangelen - (offset - tmplen)) + sizeof(u_int16_t));
+ answer->rdlength = htons((sd->mx[mx_count].exchangelen - (offset - tmplen)) + sizeof(u_int16_t));
offset = tmplen;
} else
- answer->rdlength = htons(sd->mx[mx_count]->exchangelen + sizeof(u_int16_t));
+ answer->rdlength = htons(sd->mx[mx_count].exchangelen + sizeof(u_int16_t));
(*retcount)++;
@@ -341,22 +341,22 @@ additional_mx(char *name, int namelen, struct domain *
offset += sizeof(struct answer);
- if ((offset + sd->mx[mx_count]->exchangelen) > replylen) {
+ if ((offset + sd->mx[mx_count].exchangelen) > replylen) {
offset = rroffset;
goto out;
}
- memcpy((char *)&reply[offset], (char *)sd->mx[mx_count]->exchange, sd->mx[mx_count]->exchangelen);
+ memcpy((char *)&reply[offset], (char *)sd->mx[mx_count].exchange, sd->mx[mx_count].exchangelen);
- offset += sd->mx[mx_count]->exchangelen;
- tmplen = compress_label((u_char *)reply, offset, sd->mx[mx_count]->exchangelen);
+ offset += sd->mx[mx_count].exchangelen;
+ tmplen = compress_label((u_char *)reply, offset, sd->mx[mx_count].exchangelen);
if (tmplen != 0) {
- answer->rdlength = htons((sd->mx[mx_count]->exchangelen - (offset - tmplen)) + sizeof(u_int16_t));
+ answer->rdlength = htons((sd->mx[mx_count].exchangelen - (offset - tmplen)) + sizeof(u_int16_t));
offset = tmplen;
} else
- answer->rdlength = htons(sd->mx[mx_count]->exchangelen + sizeof(u_int16_t));
+ answer->rdlength = htons(sd->mx[mx_count].exchangelen + sizeof(u_int16_t));
(*retcount)++;
}
blob - /dev/null
blob + 26da01248c5012884b76552228192966b5f64b1b (mode 644)
--- /dev/null
+++ axfr.c
@@ -0,0 +1,830 @@
+/*
+ * Copyright (c) 2011 Peter J. Philipp
+ * All rights reserved.
+ *
+ * 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.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include "include.h"
+#include "dns.h"
+#include "db.h"
+
+void axfrloop(int *afd, int sockcount, char **ident, DB *db);
+void axfr_connection(int so, char *address, int is_ipv6, DB *db);
+void reap(int sig);
+int build_header(DB *db, char *reply, char *buf, struct question *q, int answercount);
+int build_soa(DB *db, char *reply, int offset, struct domain *sd, struct question *q);
+int checklabel(DB *db, struct domain *sd, struct domain *soa, struct question *q);
+
+extern in_addr_t getmask(int prefixlen);
+extern int getmask6(int prefixlen, struct sockaddr_in6 *sin6);
+extern void build_reply(struct sreply *reply, int so, char *buf, int len, struct question *q, struct sockaddr *sa, socklen_t slen, struct domain *sd1, struct domain *sd2, u_int8_t region, int istcp, int wildcard, struct recurses *sr);
+struct question * build_question(char *, int);
+extern void reply_fmterror(struct sreply *);
+extern void reply_nxdomain(struct sreply *);
+extern int get_soa(DB *, struct question *, struct domain *, int);
+extern int compress_label(u_char *, int, int);
+extern u_int16_t create_anyreply(struct sreply *sreply, char *reply, int rlen, int offset, int soa);
+extern struct question * build_fake_question(char *, int, u_int16_t);
+extern int free_question(struct question *);
+
+
+
+SLIST_HEAD(listhead, axfrentry) axfrhead;
+
+struct axfrentry {
+ char name[INET6_ADDRSTRLEN];
+ int family;
+ struct sockaddr_storage hostmask;
+ struct sockaddr_storage netmask;
+ u_int8_t prefixlen;
+ SLIST_ENTRY(axfrentry) entries;
+} *an1, *an2, *anp;
+
+
+static const char rcsid[] = "$Id: axfr.c,v 1.1 2011/09/19 19:59:23 pbug Exp $";
+
+/*
+ * INIT_AXFR - initialize the axfr singly linked list
+ */
+
+void
+init_axfr(void)
+{
+ SLIST_INIT(&axfrhead);
+ return;
+}
+
+/*
+ * INSERT_AXFR - insert an address and prefixlen into the axfr slist
+ */
+
+int
+insert_axfr(char *address, char *prefixlen)
+{
+ struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
+ int pnum;
+ int ret;
+
+ pnum = atoi(prefixlen);
+ an2 = malloc(sizeof(struct axfrentry)); /* Insert after. */
+
+ if (strchr(address, ':') != NULL) {
+ an2->family = AF_INET6;
+ sin6 = (struct sockaddr_in6 *)&an2->hostmask;
+ if ((ret = inet_pton(AF_INET6, address, &sin6->sin6_addr.s6_addr)) != 1)
+ return (-1);
+ sin6->sin6_family = AF_INET6;
+ sin6 = (struct sockaddr_in6 *)&an2->netmask;
+ sin6->sin6_family = AF_INET6;
+ if (getmask6(pnum, sin6) < 0)
+ return(-1);
+ an2->prefixlen = pnum;
+ } else {
+
+ an2->family = AF_INET;
+ sin = (struct sockaddr_in *)&an2->hostmask;
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = inet_addr(address);
+ sin = (struct sockaddr_in *)&an2->netmask;
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = getmask(pnum);
+ an2->prefixlen = pnum;
+
+ }
+
+ SLIST_INSERT_HEAD(&axfrhead, an2, entries);
+
+ return (0);
+}
+
+/*
+ * FIND_AXFR - walk the axfr list and find the correponding network
+ * if a network matches return 1, if no match is found return
+ * 0.
+ */
+
+int
+find_axfr(struct sockaddr_storage *sst, int family)
+{
+ struct sockaddr_in *sin, *sin0;
+ struct sockaddr_in6 *sin6, *sin60, *sin61;
+ u_int32_t hostmask, netmask;
+ u_int32_t a;
+#ifdef __amd64
+ u_int64_t *hm[2], *nm[2], *a6[2];
+#else
+ u_int32_t *hm[4], *nm[4], *a6[4];
+#endif
+
+ SLIST_FOREACH(anp, &axfrhead, entries) {
+ if (anp->family == AF_INET) {
+ if (family != AF_INET)
+ continue;
+ sin = (struct sockaddr_in *)sst;
+ a = sin->sin_addr.s_addr;
+ sin = (struct sockaddr_in *)&anp->hostmask;
+ sin0 = (struct sockaddr_in *)&anp->netmask;
+ hostmask = sin->sin_addr.s_addr;
+ netmask = sin0->sin_addr.s_addr;
+ if ((hostmask & netmask) == (a & netmask)) {
+ return (1);
+ } /* if hostmask */
+ } else if (anp->family == AF_INET6) {
+ if (family != AF_INET6)
+ continue;
+ sin6 = (struct sockaddr_in6 *)sst;
+ sin60 = (struct sockaddr_in6 *)&anp->hostmask;
+ sin61 = (struct sockaddr_in6 *)&anp->netmask;
+#ifdef __amd64
+ /*
+ * If this is on a 64 bit machine, we'll benefit
+ * by using 64 bit registers, this should make it
+ * a tad faster...
+ */
+ hm[0] = (u_int64_t *)&sin60->sin6_addr.s6_addr;
+ hm[1] = (hm[0] + 1);
+ nm[0] = (u_int64_t *)&sin61->sin6_addr.s6_addr;
+ nm[1] = (nm[0] + 1);
+ a6[0] = (u_int64_t *)&sin6->sin6_addr.s6_addr;
+ a6[1] = (a6[0] + 1);
+ if ( ((*hm[0] & *nm[0]) == (*a6[0] & *nm[0]))&&
+ ((*hm[1] & *nm[1]) == (*a6[1] & *nm[1]))) {
+#else
+ hm[0] = (u_int32_t *)&sin60->sin6_addr.s6_addr;
+ hm[1] = (hm[0] + 1); hm[2] = (hm[1] + 1);
+ hm[3] = (hm[2] + 1);
+ nm[0] = (u_int32_t *)&sin61->sin6_addr.s6_addr;
+ nm[1] = (nm[0] + 1); nm[2] = (nm[1] + 1);
+ nm[3] = (nm[2] + 1);
+ a6[0] = (u_int32_t *)&sin6->sin6_addr.s6_addr;
+ a6[1] = (a6[0] + 1); a6[2] = (a6[1] + 1);
+ a6[3] = (a6[2] + 1);
+
+ if ( ((*hm[0] & *nm[0]) == (*a6[0] & *nm[0]))&&
+ ((*hm[1] & *nm[1]) == (*a6[1] & *nm[1]))&&
+ ((*hm[2] & *nm[2]) == (*a6[2] & *nm[2]))&&
+ ((*hm[3] & *nm[3]) == (*a6[3] & *nm[3]))) {
+#endif
+
+ return (1);
+ } /* if ip6 address */
+
+ } /* if AF_INET6 */
+ } /* SLIST */
+
+ return (0);
+}
+
+void
+axfrloop(int *afd, int sockcount, char **ident, DB *db)
+{
+ fd_set rset;
+
+ struct timeval tv;
+ struct sockaddr_storage from;
+ struct sockaddr_in6 *sin6;
+ struct sockaddr_in *sin;
+
+ int i, so;
+ int sel, maxso = 0;
+ int is_ipv6, axfr_acl;
+ socklen_t fromlen;
+ pid_t pid;
+
+ char address[INET6_ADDRSTRLEN];
+
+ signal(SIGCHLD, reap);
+
+ for (i = 0; i < sockcount; i++) {
+ listen(afd[i], 5);
+
+ if (afd[i] > maxso)
+ maxso = afd[i];
+ }
+
+ for (;;) {
+
+ FD_ZERO(&rset);
+
+ for (i = 0; i < sockcount; i++) {
+ FD_SET(afd[i], &rset);
+ }
+
+ tv.tv_sec = 10;
+ tv.tv_usec = 0;
+
+ sel = select(maxso + 1, &rset, NULL, NULL, NULL);
+
+ if (sel < 0) {
+ syslog(LOG_INFO, "select: %m");
+ continue;
+ }
+
+ for (i = 0; i < sockcount; i++) {
+ if (FD_ISSET(afd[i], &rset)) {
+ fromlen = sizeof(struct sockaddr_storage);
+
+ so = accept(afd[i], (struct sockaddr*)&from, &fromlen);
+ if (so < 0) {
+ syslog(LOG_INFO, "afd accept: %m");
+ continue;
+ }
+
+ if (from.ss_family == AF_INET6) {
+ is_ipv6 = 1;
+
+ fromlen = sizeof(struct sockaddr_in6);
+ sin6 = (struct sockaddr_in6 *)&from;
+ inet_ntop(AF_INET6, (void*)&sin6->sin6_addr, (char*)&address, sizeof(address));
+ axfr_acl = find_axfr((struct sockaddr_storage *)sin6, AF_INET6);
+
+ } else if (from.ss_family == AF_INET) {
+ is_ipv6 = 0;
+
+ fromlen = sizeof(struct sockaddr_in);
+ sin = (struct sockaddr_in *)&from;
+ inet_ntop(AF_INET, (void*)&sin->sin_addr, (char*)&address, sizeof(address));
+
+ axfr_acl = find_axfr((struct sockaddr_storage *)sin, AF_INET);
+
+ } else {
+ syslog(LOG_INFO, "afd accept unknown family %d, close", from.ss_family);
+ close(so);
+ continue;
+ }
+
+ if (! axfr_acl) {
+ syslog(LOG_INFO, "connection from %s was not in our axfr acl, drop", address);
+ close(so);
+ continue;
+ }
+
+ syslog(LOG_INFO, "AXFR connection from %s on interface \"%s\"", address, ident[i]);
+
+ switch (pid = fork()) {
+ case 0:
+ axfr_connection(so, address, is_ipv6, db);
+ exit(0);
+ /*NOTREACHED*/
+ default:
+ close(so);
+ break;
+ }
+
+ } /* if(FD_ISSET..) */
+
+ } /* for (i.. */
+
+ } /* for (;;) */
+
+}
+
+/*
+ * AXFR_CONNECTION - this is the main core of AXFR engine, forked
+ *
+ */
+
+void
+axfr_connection(int so, char *address, int is_ipv6, DB *db)
+{
+
+ char buf[4000];
+ char *p = &buf[0];
+ char *q;
+ char *reply;
+
+ int len, dnslen;
+ int offset = 0;
+ int ret;
+ int qlen;
+ int outlen, i;
+ int rrcount;
+
+ u_int16_t *tmp;
+
+ struct dns_header *dh, *odh;
+ struct sreply sreply;
+ struct question *question, *fq;
+ struct domain soa, sdomain, nsdomain, savesd;
+
+ DBT key, data;
+ DBC *cursor;
+
+ for (;;) {
+ len = recv(so, p + offset, sizeof(buf) - offset, 0);
+ if (len <= 0) {
+ close(so);
+ exit(1);
+ }
+
+ /*
+ * do a little dance here because we don't know if the
+ * input is fragmented or not...
+ */
+ if (offset + len >= 2) {
+ tmp = (u_int16_t *)p;
+ dnslen = ntohs(*tmp);
+ } else {
+ offset += len;
+ continue;
+ }
+ if (dnslen + 2 != offset + len) {
+ offset += len;
+ continue;
+ }
+
+
+ /* by now the packet should be normalized */
+
+ dh = (struct dns_header *)(p + 2);
+
+ if ((ntohs(dh->query) & DNS_REPLY)) {
+ syslog(LOG_INFO, "AXFR dns packet is not a question, drop");
+ goto drop;
+ }
+
+ if (ntohs(dh->question) != 1) {
+ syslog(LOG_INFO, "AXFR dns packet does not have a question count of 1 (RFC 5936, page 9), reply fmterror");
+
+ build_reply(&sreply, so, (p + 2), dnslen, NULL, NULL, 0, NULL, NULL, 0xff, 1, 0, NULL);
+
+ reply_fmterror(&sreply);
+ goto drop;
+ }
+
+ if ((question = build_question((p + 2), dnslen)) == NULL) {
+ syslog(LOG_INFO, "AXFR malformed question, drop");
+ goto drop;
+ }
+
+ if (ntohs(question->hdr->qclass) != DNS_CLASS_IN) {
+ syslog(LOG_INFO, "AXFR question wasn't for class DNS_CLASS_IN, drop");
+ goto drop;
+ }
+
+ if (ntohs(question->hdr->qtype) != DNS_TYPE_AXFR &&
+ ntohs(question->hdr->qtype) != DNS_TYPE_SOA) {
+ syslog(LOG_INFO, "AXFR question wasn't for types AXFR or SOA (requested type: %d), drop", ntohs(question->hdr->qtype));
+ goto drop;
+ }
+
+ /* now we can be reasonably sure that it's an AXFR for us */
+
+ reply = calloc(1, 65538);
+ if (reply == NULL) {
+ syslog(LOG_INFO, "internal error: %m");
+ goto drop;
+ }
+
+ odh = (struct dns_header *)(reply + 2);
+
+ q = question->hdr->name;
+ qlen = question->hdr->namelen;
+
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+
+ key.data = (char *)q;
+ key.size = qlen;
+
+ data.data = NULL;
+ data.size = 0;
+
+ ret = db->get(db, NULL, &key, &data, 0);
+
+ if (ret != 0) {
+ memset(&sdomain, 0, sizeof(sdomain));
+ (void)get_soa(db, question, &sdomain, 0);
+ build_reply(&sreply, so, (p + 2), dnslen, question, NULL, 0, &sdomain, NULL, 0xff, 1, 0, NULL);
+ reply_nxdomain(&sreply);
+ syslog(LOG_INFO, "AXFR request for zone %s, no db entry, nxdomain -> drop", question->converted_name);
+ goto drop;
+ }
+
+ if (data.size != sizeof(struct domain)) {
+ syslog(LOG_INFO, "AXFR btree db is damaged, drop");
+ goto drop;
+ }
+
+ memcpy((char *)&soa, (char *)data.data, data.size);
+
+ /*
+ * check if we have an SOA record
+ */
+
+ if (! (soa.flags & DOMAIN_HAVE_SOA)) {
+ memset(&sdomain, 0, sizeof(sdomain));
+ (void)get_soa(db, question, &sdomain, 0);
+ build_reply(&sreply, so, (p + 2), dnslen, question, NULL, 0, &sdomain, NULL, 0xff, 1, 0, NULL);
+ reply_nxdomain(&sreply);
+
+ syslog(LOG_INFO, "AXFR request for zone %s, which has no SOA for the zone, nxdomain -> drop", question->converted_name);
+ goto drop;
+ }
+
+ if (ntohs(question->hdr->qtype) == DNS_TYPE_SOA) {
+ syslog(LOG_INFO, "TCP SOA request for zone \"%s\", replying...", question->converted_name);
+ outlen = 0;
+ outlen = build_header(db, (reply + 2), (p + 2), question, 1);
+ outlen = build_soa(db, (reply + 2), outlen, &soa, question);
+
+ tmp = (u_int16_t *)reply;
+ *tmp = htons(outlen);
+
+ len = send(so, reply, outlen + 2, 0);
+ if (len <= 0) {
+ goto drop;
+ }
+
+ outlen = 0;
+ offset = 0;
+ p = &buf[0];
+
+ free (reply);
+
+ continue;
+ }
+
+ syslog(LOG_INFO, "AXFR request for zone \"%s\", replying...", question->converted_name);
+
+ outlen = build_header(db, (reply + 2), (p + 2), question, 0);
+ outlen = build_soa(db, (reply + 2), outlen, &soa, question);
+ rrcount = 1;
+
+ if (db->cursor(db, NULL, &cursor, 0) != 0) {
+ syslog(LOG_INFO, "db->cursor: %m");
+ goto drop;
+ }
+
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+
+
+ if (cursor->c_get(cursor, &key, &data, DB_FIRST) != 0) {
+ syslog(LOG_INFO, "cursor->c_get: %m");
+ goto drop;
+ }
+
+ do {
+ if (data.size != sizeof(struct domain)) {
+ syslog(LOG_INFO, "AXFR btree db is damaged (%d), drop", __LINE__);
+ goto drop;
+ }
+
+ memcpy((char *)&sdomain, (char *)data.data, data.size);
+ memcpy((char *)&savesd, (char *)data.data, data.size);
+
+ if (checklabel(db, &sdomain, &soa, question)) {
+ fq = build_fake_question(sdomain.zone, sdomain.zonelen, 0);
+ build_reply(&sreply, so, (p + 2), dnslen, fq, NULL, 0, &sdomain, NULL, 0xff, 1, 0, NULL);
+ outlen = create_anyreply(&sreply, (reply + 2), 65535, outlen, 0);
+ free_question(fq);
+
+ if ((savesd.flags & DOMAIN_HAVE_NS) &&
+ (savesd.ns_type & NS_TYPE_DELEGATE)) {
+ for (i = 0; i < savesd.ns_count; i++) {
+ fq = build_fake_question(savesd.ns[i].nsserver,
+ savesd.ns[i].nslen, 0);
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+
+ key.data = fq->hdr->name;
+ key.size = fq->hdr->namelen;
+
+ data.data = NULL;
+ data.size = 0;
+
+ ret = db->get(db, NULL, &key, &data, 0);
+ if (ret != 0) {
+ free_question(fq);
+ continue;
+ }
+
+ if (data.size != sizeof(struct domain)) {
+ syslog(LOG_INFO, "AXFR btree db is damaged (%d), drop", __LINE__);
+ goto drop;
+ }
+
+ memcpy((char *)&nsdomain, (char*)data.data, data.size);
+
+ build_reply(&sreply, so, (p + 2), dnslen, fq, NULL, 0, &nsdomain, NULL, 0xff, 1, 0, NULL);
+ outlen = create_anyreply(&sreply, (reply + 2), 65535, outlen, 0);
+ free_question(fq);
+
+ } /* for (i.. */
+ } /* if (sdomain.flags */
+
+ } /* if (checklabel */
+
+ /*
+ * if we accumulate 60000 bytes out of the maximum
+ * 65535 bytes then we fragment.
+ */
+ /* XXX */
+ if (outlen > 60000) {
+ tmp = (u_int16_t *)reply;
+ *tmp = htons(outlen);
+
+ /* set the rrcount in there */
+
+ NTOHS(odh->answer);
+ odh->answer += rrcount;
+ HTONS(odh->answer);
+
+ len = send(so, reply, outlen + 2, 0);
+ if (len <= 0) {
+ goto drop;
+ }
+
+ rrcount = 0;
+ outlen = build_header(db, (reply + 2), (p + 2), question, 0);
+ }
+
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+ } while (cursor->c_get(cursor, &key, &data, DB_NEXT) == 0);
+
+ cursor->c_close(cursor);
+
+ outlen = build_soa(db, (reply + 2), outlen, &soa, question);
+ rrcount++;
+
+ tmp = (u_int16_t *)reply;
+ *tmp = htons(outlen);
+
+ /* set the rrcount in there */
+
+ NTOHS(odh->answer);
+ odh->answer += rrcount;
+ HTONS(odh->answer);
+
+ len = send(so, reply, outlen + 2, 0);
+ if (len <= 0)
+ goto drop;
+
+ goto drop;
+
+ } /* for(;;) */
+
+
+
+drop:
+ close(so);
+ exit(0);
+}
+
+/*
+ * REAP - reap the child that is zombied by now, this is a sighandler for
+ * SIGCHLD
+ */
+
+void
+reap(int sig)
+{
+ int status;
+ pid_t pid;
+
+ while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
+ }
+}
+
+
+/*
+ * build_header - build a header reply
+ *
+ */
+
+int
+build_header(DB *db, char *reply, char *buf, struct question *q, int answercount)
+{
+ struct dns_header *odh;
+ u_int16_t outlen;
+
+ odh = (struct dns_header *)reply;
+ outlen = sizeof(struct dns_header);
+
+ /* copy question to reply */
+ memcpy(reply, buf, sizeof(struct dns_header) + q->hdr->namelen + 4);
+ /* blank query */
+ memset((char *)&odh->query, 0, sizeof(u_int16_t));
+
+ outlen += (q->hdr->namelen + 4);
+
+ SET_DNS_REPLY(odh);
+ SET_DNS_AUTHORITATIVE(odh);
+
+ NTOHS(odh->query);
+
+ odh->question = htons(1);
+ odh->answer = htons(answercount);
+ odh->nsrr = 0;
+ odh->additional = 0;
+
+ return (outlen);
+}
+
+
+
+/*
+ * BUILD_SOA - build an SOA answer
+ */
+
+int
+build_soa(DB *db, char *reply, int offset, struct domain *sd, struct question *q)
+{
+ char *p;
+ char *label;
+ char *plabel;
+
+ int labellen;
+ int tmplen;
+ u_int32_t *soa_val;
+
+ struct answer {
+ char name[2];
+ u_int16_t type;
+ u_int16_t class;
+ u_int32_t ttl;
+ u_int16_t rdlength; /* 12 */
+ char rdata;
+ } __attribute__((packed));
+
+ struct answer *answer;
+ answer = (struct answer *)(&reply[offset]);
+
+ answer->name[0] = 0xc0;
+ answer->name[1] = 0x0c;
+ answer->type = htons(DNS_TYPE_SOA);
+ answer->class = htons(DNS_CLASS_IN);
+ answer->ttl = htonl(sd->ttl);
+
+ offset += 12; /* up to rdata length */
+
+ p = (char *)&answer->rdata;
+
+
+ label = sd->soa.nsserver;
+ labellen = sd->soa.nsserver_len;
+
+ plabel = label;
+
+ if (offset + labellen <= 65535)
+ memcpy(&reply[offset], (char *)plabel, labellen);
+ else
+ return (offset); /* XXX */
+
+ offset += labellen;
+
+ /* compress the label if possible */
+ if ((tmplen = compress_label((u_char*)reply, offset, labellen)) > 0) {
+ offset = tmplen;
+ }
+
+ label = sd->soa.responsible_person;
+ labellen = sd->soa.rp_len;
+ plabel = label;
+
+ if (offset + labellen <= 65535)
+ memcpy(&reply[offset], (char *)plabel, labellen);
+ else
+ return (offset); /* XXX */
+
+ offset += labellen;
+
+ /* 2 compress the label if possible */
+
+ if ((tmplen = compress_label((u_char*)reply, offset, labellen)) > 0) {
+ offset = tmplen;
+ }
+
+
+ /* XXX */
+ if ((offset + sizeof(sd->soa.serial)) >= 65535 ) {
+ /* XXX server error reply? */
+ return (offset);
+ }
+ soa_val = (u_int32_t *)&reply[offset];
+ *soa_val = htonl(sd->soa.serial);
+ offset += sizeof(sd->soa.serial); /* XXX */
+
+ /* XXX */
+ if ((offset + sizeof(sd->soa.refresh)) >= 65535 ) {
+ return (offset);
+ }
+ soa_val = (u_int32_t *)&reply[offset];
+ *soa_val = htonl(sd->soa.refresh);
+ offset += sizeof(sd->soa.refresh); /* XXX */
+
+ if ((offset + sizeof(sd->soa.retry)) >= 65535 ) {
+ return (offset);
+ }
+ soa_val = (u_int32_t *)&reply[offset];
+ *soa_val = htonl(sd->soa.retry);
+ offset += sizeof(sd->soa.retry); /* XXX */
+
+ if ((offset + sizeof(sd->soa.expire)) >= 65535 ) {
+ return (offset);
+ }
+ soa_val = (u_int32_t *)&reply[offset];
+ *soa_val = htonl(sd->soa.expire);
+ offset += sizeof(sd->soa.expire);
+
+ if ((offset + sizeof(sd->soa.minttl)) > 65535 ) {
+ return (offset);
+ }
+ soa_val = (u_int32_t *)&reply[offset];
+ *soa_val = htonl(sd->soa.minttl);
+ offset += sizeof(sd->soa.minttl);
+
+ answer->rdlength = htons(&reply[offset] - &answer->rdata);
+
+ return (offset);
+}
+
+int
+checklabel(DB *db, struct domain *sd, struct domain *soa, struct question *q)
+{
+ struct domain tmpsd;
+ char *p;
+ int plen, ret;
+
+ DBT key, data;
+
+ if (memcmp(sd, soa, sizeof(struct domain)) == 0)
+ return 1;
+
+ p = sd->zone;
+ plen = sd->zonelen;
+
+ do {
+ if (*p == '\0')
+ return (0);
+
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+
+ key.data = (char *)p;
+ key.size = plen;
+
+ data.data = NULL;
+ data.size = 0;
+
+ ret = db->get(db, NULL, &key, &data, 0);
+ if (ret == DB_NOTFOUND) {
+ plen -= (*p + 1);
+ p = (p + (*p + 1));
+
+ continue;
+ }
+
+ if (data.size != sizeof(struct domain)) {
+ syslog(LOG_INFO, "AXFR btree db is damaged (%d), drop", __LINE__);
+ return (0);
+ }
+
+ memcpy(&tmpsd, data.data, sizeof(tmpsd));
+
+ /*
+ * the encountered label has an SOA before we got to the
+ * root, so we skip this record entirely...
+ */
+
+ if (tmpsd.flags & DOMAIN_HAVE_SOA)
+ return (0);
+
+
+ /*
+ * and check the next label...
+ */
+
+ plen -= (*p + 1);
+ p = (p + (*p + 1));
+
+
+ } while (memcmp(p, q->hdr->name, q->hdr->namelen) != 0);
+
+
+ return (1);
+}
blob - a278baba0d89975b09fa4b2ed1b00fbef6c72c48
blob + 2c608e959db7c65a799d3bd40e334f536a571235
--- db.h
+++ db.h
@@ -64,9 +64,9 @@ struct ns {
} __attribute__((packed));
struct domain {
- char *zone; /* name of zone in dns name format */
+ char zone[DNS_MAXNAME]; /* name of zone in dns name format */
int zonelen; /* length of zone, above */
- char *zonename; /* name of zone in human readable */
+ char zonename[DNS_MAXNAME + 1]; /* name of zone in human readable */
u_int16_t flags; /* flags of zone */
#define DOMAIN_HAVE_A 0x1
#define DOMAIN_HAVE_SOA 0x2
@@ -78,30 +78,30 @@ struct domain {
#define DOMAIN_HAVE_TXT 0x80
#define DOMAIN_STATIC_ZONE 0x100
#define DOMAIN_NEGATIVE_CACHE 0x200
- struct soa *soa; /* start of authority */
+ struct soa soa; /* start of authority */
u_int32_t ttl; /* time to live */
time_t created; /* time created, for dynamic zones */
in_addr_t a[RECORD_COUNT]; /* IP addresses */
u_int8_t region[RECORD_COUNT]; /* region of IP address */
int a_count; /* IP address count (max 10) */
int a_ptr; /* pointer to last used address */
- struct in6_addr *aaaa[RECORD_COUNT]; /* IPv6 addresses */
+ struct in6_addr aaaa[RECORD_COUNT]; /* IPv6 addresses */
int aaaa_count; /* IPv6 address count (max 10) */
int aaaa_ptr; /* pointer to last used IPv6 address */
- struct smx *mx[RECORD_COUNT]; /* MX addresses */
+ struct smx mx[RECORD_COUNT]; /* MX addresses */
int mx_count; /* MX address count, max 10 */
int mx_ptr; /* pointer to last used MX adddress */
- struct ns *ns[RECORD_COUNT]; /* NS resource records (max 10) */
+ struct ns ns[RECORD_COUNT]; /* NS resource records (max 10) */
int ns_count; /* count of NS records, (max 10) */
int ns_ptr; /* pointer to last used NS address */
int ns_type; /* set if it's a delegation */
#define NS_TYPE_DELEGATE 0x1
#define NS_TYPE_HINT 0x2
- char *cname; /* CNAME RR */
+ char cname[DNS_MAXNAME]; /* CNAME RR */
int cnamelen; /* len of CNAME */
- char *ptr; /* PTR RR */
+ char ptr[DNS_MAXNAME]; /* PTR RR */
int ptrlen; /* len of PTR */
- char *txt; /* TXT string */
+ char txt[DNS_MAXNAME]; /* TXT string */
int txtlen; /* len of TXT */
} __attribute__((packed));
@@ -187,6 +187,7 @@ struct logging {
struct cfg {
int udp[DEFAULT_SOCKET]; /* udp sockets */
int tcp[DEFAULT_SOCKET]; /* tcp socket */
+ int axfr[DEFAULT_SOCKET]; /* axfr udp socket */
char *ident[DEFAULT_SOCKET]; /* identification of interface */
int recurse; /* recurse socket */
int log; /* logging socket */
blob - 0bda8f68db38fca29bf6757c7c70b5144b7015d7
blob + f6b5d59e3ef009f4b18847b23ece469a3696f029
--- dns.h
+++ dns.h
@@ -135,6 +135,7 @@ struct dns_question_hdr {
#define DNS_TYPE_MX 15
#define DNS_TYPE_TXT 16
+#define DNS_TYPE_AXFR 252 /* RFC 5936, page 10 */
#define DNS_TYPE_ANY 255
/* DNS types 0xff00 -> 0xfffe (private use) RFC 5395, page 8 */
blob - b00dfcb99d9da4f4526e6d0603422d82092182b4
blob + bfb51079e3905f852a9be58be560afedfa766d63
--- include.h
+++ include.h
@@ -29,12 +29,14 @@
#define _INCLUDES_H
#include <sys/param.h>
+#include <sys/ipc.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <sys/queue.h>
#include <sys/mman.h>
+#include <sys/wait.h>
#include <net/if.h>
blob - c6fbfc09b53a8f1b26235f79e81421e07bf069dd
blob + f2bf50c29ff3c08cf1d8ed219b48c68b2b78120f
--- main.c
+++ main.c
@@ -61,6 +61,7 @@ extern int find_recurse(struct sockaddr_storage *, int
extern void init_recurse(void);
extern int remotelog(int, char *, ...);
extern void receivelog(char *buf, int len);
+extern void axfrloop(int *afd, int sockcount, char **ident, DB *db);
char * dns_label(char *, int *);
int compress_label(u_char *, u_int16_t, int);
@@ -68,7 +69,7 @@ int memcasecmp(u_char *, u_char *, int);
char * get_dns_type(int dnstype);
void build_reply(struct sreply *reply, int so, char *buf, int len, struct question *q, struct sockaddr *sa, socklen_t slen, struct domain *sd1, struct domain *sd2, u_int8_t region, int istcp, int wildcard, struct recurses *sr);
void recurseheader(struct srecurseheader *, int, struct sockaddr_storage *, struct sockaddr_storage *, int);
-void setup_master(int, char **);
+void setup_master(DB *, DB_ENV *, int, char **);
void master_shutdown(int);
void master_reload(int);
void slave_shutdown(void);
@@ -81,6 +82,7 @@ void slave_signal(int);
#endif
#define PIDFILE "/var/run/wildcarddnsd.pid"
+#define MYDB_PATH "/var/db/wdns"
struct typetable {
@@ -104,11 +106,16 @@ struct typetable {
extern char *__progname;
extern struct logging logging;
+extern int axfrport;
static int lflag = 0;
static int rflag = 0;
static u_int16_t port = 53;
static int *ptr = NULL;
static int reload = 0;
+static int mshutdown = 0;
+static int msig;
+static char *database;
+static char mydatabase[512];
/* singly linked list for tcp operations */
SLIST_HEAD(listhead, tcps) tcpshead;
@@ -129,7 +136,7 @@ struct tcps {
} *tn1, *tn2, *tnp;
-static const char rcsid[] = "$Id: main.c,v 1.66 2011/06/28 18:40:19 pbug Exp $";
+static const char rcsid[] = "$Id: main.c,v 1.67 2011/09/19 19:59:23 pbug Exp $";
/*
* MAIN - set up arguments, set up database, set up sockets, call mainloop
@@ -141,17 +148,22 @@ main(int argc, char *argv[])
{
static int udp[DEFAULT_SOCKET];
static int tcp[DEFAULT_SOCKET];
+ static int afd[DEFAULT_SOCKET];
+ static int uafd[DEFAULT_SOCKET];
int raw[2];
- int lfd;
+ int lfd = -1;
+ int fd, n;
int ch, i, j;
int gai_error;
- int salen;
+ int salen, ret;
int bflag = 0, iflag = 0;
+ int nflag = 0;
int bcount = 0, icount = 0;
int found = 0;
int on = 1;
int sp[2];
+ u_int32_t cachesize = 0;
pid_t pid;
@@ -169,7 +181,10 @@ main(int argc, char *argv[])
struct sockaddr_in6 *sin6;
struct cfg *cfg;
+ static DB_ENV *dbenv;
static DB *db;
+
+ key_t key;
if (geteuid() != 0) {
fprintf(stderr, "must be started as root\n"); /* .. dolt */
@@ -178,7 +193,7 @@ main(int argc, char *argv[])
av = argv;
- while ((ch = getopt(argc, argv, "b:f:i:lp:r")) != -1) {
+ while ((ch = getopt(argc, argv, "b:c:f:i:ln:p:r")) != -1) {
switch (ch) {
case 'b':
bflag = 1;
@@ -188,6 +203,13 @@ main(int argc, char *argv[])
}
bind_list[bcount++] = optarg;
break;
+ case 'c':
+#if defined __NetBSD__ || defined __linux__
+ cachesize = atoi(optarg);
+#else
+ cachesize = strtonum(optarg, 1, 0xffffffff, NULL);
+#endif
+ break;
case 'f':
conffile = optarg;
break;
@@ -202,6 +224,9 @@ main(int argc, char *argv[])
case 'l':
lflag = 1;
break;
+ case 'n':
+ nflag = atoi(optarg);
+ break;
case 'p':
port = atoi(optarg) & 0xffff;
break;
@@ -254,38 +279,74 @@ main(int argc, char *argv[])
*ptr = 0;
- /* make a master program that holds the pidfile, boss of ... eek */
- pid = fork();
- switch (pid) {
- case -1:
- syslog(LOG_ERR, "fork(): %m");
+#if DB_VERSION_MAJOR == 4
+
+ if ((ret = db_env_create(&dbenv, 0)) != 0) {
+ syslog(LOG_INFO, "db_env_create: %s", db_strerror(ret));
+ slave_shutdown();
exit(1);
- case 0:
- break;
- default:
- setup_master(port, av);
- /* NOTREACHED */
+ }
+
+ key = ftok("/usr/local/sbin/wildcarddnsd", 1);
+
+ if ((ret = dbenv->set_shm_key(dbenv, key)) != 0) {
+ syslog(LOG_INFO, "dbenv->set_shm_key failed");
+ slave_shutdown();
exit(1);
}
-
-#if DB_VERSION_MAJOR == 4
+ /* set cache size , if requested */
- if (db_create((DB **)&db, (DB_ENV *)NULL, 0) != 0) {
+ if (cachesize) {
+ if ((ret = dbenv->set_cachesize(dbenv, 0, cachesize, 0)) != 0) {
+ syslog(LOG_INFO, "dbenv->set_cachesize: %s",
+ db_strerror(ret));
+ slave_shutdown();
+ exit(1);
+ }
+ }
+
+ (void)mkdir(MYDB_PATH, 0700);
+
+ if ((ret = dbenv->open(dbenv, MYDB_PATH, DB_CREATE | \
+ DB_INIT_LOCK | DB_INIT_MPOOL | DB_SYSTEM_MEM, \
+ S_IRUSR | S_IWUSR)) != 0) {
+ syslog(LOG_INFO, "dbenv->open failed: %s", db_strerror(ret));
+ slave_shutdown();
+ exit(1);
+ }
+
+ if (db_create((DB **)&db, (DB_ENV *)dbenv, 0) != 0) {
syslog(LOG_INFO, "db_create: %m");
slave_shutdown();
exit(1);
}
+
+ /*
+ * we want to run multiple instances of different versions so we'll
+ * make a temporary database...
+ */
+
+ snprintf(mydatabase, sizeof(mydatabase), "%s/wdns.%ld",
+ MYDB_PATH, (long)getpid());
+ database = mydatabase;
+
+ fd = open(database, O_WRONLY | O_CREAT, 0600);
+ if (fd < 0) {
+ syslog(LOG_INFO, "open: %m");
+ }
+ close(fd);
+
#if DB_VERSION_MINOR > 0
- if (db->open(db, NULL, NULL, NULL, DB_BTREE, DB_CREATE, 0600) != 0) {
+ if (db->open(db, NULL, database, NULL, DB_BTREE, DB_CREATE, 0600) != 0) {
syslog(LOG_INFO, "db->open: %m");
db->close(db, DB_NOSYNC);
slave_shutdown();
exit(1);
}
#else
- if (db->open(db, NULL, NULL, DB_BTREE, DB_CREATE, 0600) != 0) {
+ if (db->open(db, database, NULL, DB_BTREE, DB_CREATE, 0600) != 0) {
syslog(LOG_INFO, "db->open: %m");
db->close(db, DB_NOSYNC);
slave_shutdown();
@@ -294,6 +355,7 @@ main(int argc, char *argv[])
#endif /*minor*/
#else
+ #error "db185 isn't used anymore. Please install Berkeley DB v4."
db = dbopen(NULL, O_RDWR, 0, DB_BTREE, NULL);
@@ -304,6 +366,23 @@ main(int argc, char *argv[])
}
#endif
+ /* make a master program that holds the pidfile, boss of ... eek */
+
+ pid = fork();
+ switch (pid) {
+ case -1:
+ syslog(LOG_ERR, "fork(): %m");
+ exit(1);
+ case 0:
+ break;
+ default:
+ setup_master(db, dbenv, port, av);
+ /* NOTREACHED */
+ exit(1);
+ }
+
+ /* end of setup_master code */
+
init_wildcard();
init_recurse();
@@ -407,6 +486,50 @@ main(int argc, char *argv[])
exit(1);
}
+ if (axfrport) {
+ /* axfr port below */
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ hints.ai_flags = AI_NUMERICHOST;
+
+ snprintf(buf, sizeof(buf) - 1, "%u", axfrport);
+
+ if ((gai_error = getaddrinfo(bind_list[i], buf, &hints, &res0)) != 0) {
+ syslog(LOG_INFO, "getaddrinfo: %s\n", gai_strerror(gai_error));
+ slave_shutdown();
+ exit (1);
+ }
+
+ res = res0;
+
+ if ((afd[i] = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0) {
+ syslog(LOG_INFO, "tcp socket: %m");
+ slave_shutdown();
+ exit(1);
+ }
+ if (setsockopt(afd[i], SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
+ syslog(LOG_INFO, "setsockopt: %m");
+ slave_shutdown();
+ exit(1);
+ }
+ if (bind(afd[i], res->ai_addr, res->ai_addrlen) < 0) {
+ syslog(LOG_INFO, "tcp bind: %m");
+ slave_shutdown();
+ exit(1);
+ }
+
+ if ((uafd[i] = socket(res->ai_family, SOCK_DGRAM, res->ai_protocol)) < 0) {
+ syslog(LOG_INFO, "axfr udp socket: %m");
+ slave_shutdown();
+ exit(1);
+ }
+ if (bind(uafd[i], res->ai_addr, res->ai_addrlen) < 0) {
+ syslog(LOG_INFO, "axfr udp socket bind: %m");
+ slave_shutdown();
+ exit(1);
+ }
+ } /* axfrport */
+
} /* for .. bcount */
} else {
@@ -507,6 +630,39 @@ main(int argc, char *argv[])
exit(1);
}
+
+ /* axfr socket */
+ if (axfrport) {
+ if ((afd[i] = socket(pifap->ifa_addr->sa_family, SOCK_STREAM, IPPROTO_TCP)) < 0) {
+ syslog(LOG_INFO, "tcp socket: %m");
+ slave_shutdown();
+ exit(1);
+ }
+ if (setsockopt(afd[i], SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
+ syslog(LOG_INFO, "setsockopt: %m");
+ slave_shutdown();
+ exit(1);
+ }
+
+ ((struct sockaddr_in *)pifap->ifa_addr)->sin_port = htons(axfrport);
+
+ if (bind(afd[i], (struct sockaddr *)pifap->ifa_addr, salen) < 0) {
+ syslog(LOG_INFO, "tcp bind: %m");
+ slave_shutdown();
+ exit(1);
+ }
+ if ((uafd[i] = socket(pifap->ifa_addr->sa_family, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
+ syslog(LOG_INFO, "axfr udp socket: %m");
+ slave_shutdown();
+ exit(1);
+ }
+ if (bind(uafd[i], (struct sockaddr *)pifap->ifa_addr, salen) < 0) {
+ syslog(LOG_INFO, "udp axfr bind: %m");
+ slave_shutdown();
+ exit(1);
+ }
+ } /* axfrport */
+
} /* AF_INET */
if (i >= DEFAULT_SOCKET) {
@@ -644,7 +800,7 @@ main(int argc, char *argv[])
exit(1);
}
-#ifdef __OpenBSD__
+#if defined __OpenBSD__ || defined __FreeBSD__
if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) < 0) {
syslog(LOG_INFO, "setresgid: %m");
slave_shutdown();
@@ -670,6 +826,117 @@ main(int argc, char *argv[])
}
#endif
+ /*
+ * start our axfr process
+ */
+
+ if (axfrport) {
+ switch (pid = fork()) {
+ case 0:
+ /* close descriptors that we don't need */
+ for (j = 0; j < i; j++) {
+ close(tcp[j]);
+ close(udp[j]);
+ }
+ close(raw[0]);
+ close(raw[1]);
+
+#ifndef __linux__
+ setproctitle("AXFR engine on port %d", axfrport);
+#endif
+
+ axfrloop(afd, i, ident, db);
+ /* NOTREACHED */
+ exit(1);
+ default:
+ /* close afd descriptors, they aren't needed here */
+ for (j = 0; j < i; j++) {
+ close(afd[i]);
+ }
+
+ break;
+ }
+
+ } /* axfrport */
+
+ /* what follows is a bit mangled code, we set up nflag + 1 amount of
+ * server instances (1 per cpu?) and if we're recursive we also set up
+ * the same amount of recursive instances all connected through a
+ * socketpair() so that it looks somewhat like this (with 4 instances):
+ *
+ * replies <--- [] ---- [] recursive end
+ * |
+ * replies <--- [] ---- []
+ * request * ---> |
+ * replies <--- [] ---- []
+ * |
+ * replies <--- [] ---- []
+ *
+ */
+
+ for (n = 0; n < nflag; n++) {
+ switch (pid = fork()) {
+ case 0:
+ if (rflag) {
+ /*
+ * set up socket pair
+ */
+
+ if (socketpair(AF_UNIX, SOCK_DGRAM, 0, (int *)&sp) < 0) {
+ syslog(LOG_INFO, "socketpair: %m");
+ slave_shutdown();
+ exit(1);
+ }
+
+ switch (pid = fork()) {
+ case -1:
+ syslog(LOG_INFO, "fork: %m");
+ slave_shutdown();
+ exit(1);
+
+ case 0:
+ for (j = 0; j < i; j++) {
+ close(tcp[j]);
+ close(udp[j]);
+ }
+ close (sp[1]);
+
+ recurseloop(sp[0], (int *)&raw, db);
+ /* NOTREACHED */
+ break;
+
+ default:
+ close(raw[0]);
+ close(raw[1]);
+ close (sp[0]);
+ break;
+ } /* switch */
+ } /* rflag */
+
+
+ cfg->sockcount = i;
+ cfg->db = db;
+ for (i = 0; i < cfg->sockcount; i++) {
+ cfg->udp[i] = udp[i];
+ cfg->tcp[i] = tcp[i];
+
+ if (axfrport)
+ cfg->axfr[i] = uafd[i];
+
+ cfg->ident[i] = strdup(ident[i]);
+ }
+ cfg->recurse = (rflag ? sp[1] : -1);
+ cfg->log = lfd;
+
+
+ (void)mainloop(cfg);
+
+ /* NOTREACHED */
+ default:
+ break;
+ } /* switch pid= fork */
+ } /* for (.. nflag */
+
if (rflag) {
/*
* set up socket pair
@@ -704,7 +971,8 @@ main(int argc, char *argv[])
close (sp[0]);
break;
} /* switch */
- } /* rflag */
+
+ } /* rflag */
cfg->sockcount = i;
@@ -712,12 +980,16 @@ main(int argc, char *argv[])
for (i = 0; i < cfg->sockcount; i++) {
cfg->udp[i] = udp[i];
cfg->tcp[i] = tcp[i];
+
+ if (axfrport)
+ cfg->axfr[i] = uafd[i];
+
cfg->ident[i] = strdup(ident[i]);
}
cfg->recurse = (rflag ? sp[1] : -1);
cfg->log = lfd;
-
+
(void)mainloop(cfg);
/* NOTREACHED */
@@ -1329,7 +1601,18 @@ lookup_zone(DB *db, struct question *question, struct
goto out;
}
+ /*
+ * check if our record is dynamic (non-static)
+ * if so, we'll hand it down to the recurse
+ * process later on...
+ */
+ if (! (sd->flags & DOMAIN_STATIC_ZONE)) {
+ syslog(LOG_INFO, "non-static zone %s passed to recurse process\n", sd->zonename);
+ *lzerrno = ERR_NOERROR;
+ return (-1);
+ }
+
switch (ntohs(question->hdr->qtype)) {
case DNS_TYPE_ANY:
returnval = DNS_TYPE_ANY;
@@ -1813,8 +2096,14 @@ mainloop(struct cfg *cfg)
if (maxso < cfg->udp[i])
maxso = cfg->udp[i];
+ if (axfrport && maxso < cfg->axfr[i])
+ maxso = cfg->axfr[i];
+
FD_SET(cfg->tcp[i], &rset);
FD_SET(cfg->udp[i], &rset);
+
+ if (axfrport)
+ FD_SET(cfg->axfr[i], &rset);
}
SLIST_FOREACH(tnp, &tcpshead, entries) {
@@ -2290,9 +2579,17 @@ tcpnxdomain:
/* UDP marriage */
for (i = 0; i < cfg->sockcount; i++) {
+ if (axfrport && FD_ISSET(cfg->axfr[i], &rset)) {
+ istcp = 0;
+ so = cfg->axfr[i];
+
+ goto axfrentry;
+ }
+
if (FD_ISSET(cfg->udp[i], &rset)) {
istcp = 0;
so = cfg->udp[i];
+axfrentry:
fromlen = sizeof(sockaddr_large);
memset(&msgh, 0, sizeof(msgh));
@@ -2695,7 +2992,7 @@ udpnxdomain:
} /* for */
- if (FD_ISSET(lfd, &rset)) {
+ if (logging.bind == 1 && FD_ISSET(lfd, &rset)) {
logfromlen = sizeof(struct sockaddr_storage);
len = recvfrom(lfd, buf, sizeof(buf), 0, (struct sockaddr *)&logfrom, &logfromlen);
if (len < 0) {
@@ -2795,11 +3092,12 @@ recurseheader(struct srecurseheader *rh, int proto, st
*/
void
-setup_master(int port, char **av)
+setup_master(DB *db, DB_ENV *dbenv, int port, char **av)
{
+ DB *destroy;
char buf[512];
pid_t pid;
- int fd;
+ int fd, ret;
#ifndef __linux__
setproctitle("wildcarddnsd master on port %u", port);
@@ -2832,6 +3130,29 @@ setup_master(int port, char **av)
master_shutdown(SIGTERM);
}
+ if (mshutdown) {
+ syslog(LOG_INFO, "shutting down on signal %d", msig);
+ unlink(PIDFILE);
+ db->close(db, 0);
+
+
+ if (db_create((DB **)&destroy, (DB_ENV *)dbenv, 0) != 0) {
+ syslog(LOG_INFO, "db_create: %m");
+ }
+
+ ret = destroy->remove(destroy, database, NULL, 0);
+ if (ret != 0) {
+ syslog(LOG_INFO, "db->remove: %s", db_strerror(ret));
+ }
+
+ dbenv->close(dbenv, 0);
+
+ pid = getpgrp();
+ killpg(pid, msig);
+
+ exit(0);
+ }
+
if (reload) {
signal(SIGTERM, SIG_IGN);
@@ -2842,10 +3163,23 @@ setup_master(int port, char **av)
syslog(LOG_ERR, "munmap: %m");
}
- closelog();
unlink(PIDFILE);
+ db->close(db, 0);
+
+ if (db_create((DB **)&destroy, (DB_ENV *)dbenv, 0) != 0) {
+ syslog(LOG_INFO, "db_create: %m");
+ }
+
+ ret = destroy->remove(destroy, database, NULL, 0);
+ if (ret != 0) {
+ syslog(LOG_INFO, "db->remove: %s", db_strerror(ret));
+ }
+
+ dbenv->close(dbenv, 0);
+
syslog(LOG_INFO, "restarting on SIGHUP");
+ closelog();
if (execvp("/usr/local/sbin/wildcarddnsd", av) < 0) {
syslog(LOG_ERR, "execvp: %m");
}
@@ -2864,14 +3198,8 @@ setup_master(int port, char **av)
void
master_shutdown(int sig)
{
- pid_t pid;
-
- unlink(PIDFILE);
-
- pid = getpgrp();
- killpg(pid, sig);
-
- exit(0);
+ msig = sig;
+ mshutdown = 1;
}
/*
blob - 0d052691a870a18516fe927842d04b57455837e0
blob + 39ba8e75333aa4e584698c347e280283e70be75d
--- parse.c
+++ parse.c
@@ -35,6 +35,7 @@ extern void init_region(void);
extern int insert_region(char *address, char *prefix, u_int8_t region);
extern int insert_wildcard(char *address, char *prefixlen);
extern int insert_recurse(char *, char *);
+extern int insert_axfr(char *, char *);
extern void slave_shutdown(void);
static int parse_file0(char *filename, DB *db, FILE *f);
@@ -60,7 +61,8 @@ struct myrr_lookup {
enum { CMD_TYPE_VERSION = 1, CMD_TYPE_REGION,
CMD_TYPE_ZONE, CMD_TYPE_INCLUDE,
CMD_TYPE_WILDCARDONLYFOR, CMD_TYPE_RECURSEFOR,
- CMD_TYPE_LOGGING };
+ CMD_TYPE_LOGGING, CMD_TYPE_AXFRFOR,
+ CMD_TYPE_AXFRPORT };
struct cmd_lookup {
char *name;
@@ -72,7 +74,9 @@ struct cmd_lookup {
{ "include ", CMD_TYPE_INCLUDE },
{ "wildcard-only-for ", CMD_TYPE_WILDCARDONLYFOR },
{ "recurse-for ", CMD_TYPE_RECURSEFOR },
+ { "axfr-for ", CMD_TYPE_AXFRFOR },
{ "logging ", CMD_TYPE_LOGGING },
+ { "axfrport ", CMD_TYPE_AXFRPORT },
{ NULL, 0},
};
@@ -84,13 +88,16 @@ struct cmd_lookup {
#define CONFIG_WILDCARDONLYFOR 0x20
#define CONFIG_RECURSEFOR 0x40
#define CONFIG_LOGGING 0x80
+#define CONFIG_AXFRFOR 0x100
+#define CONFIG_AXFRPORT 0x200
#define WILDCARDVERSION 5
static u_int32_t config = 0;
struct logging logging;
+int axfrport = 0;
-static const char rcsid[] = "$Id: parse.c,v 1.31 2011/06/28 17:04:33 pbug Exp $";
+static const char rcsid[] = "$Id: parse.c,v 1.32 2011/09/19 19:59:23 pbug Exp $";
/*
* PARSE_FILE - parse the configfile XXX rewrite me in yacc :(
@@ -255,6 +262,15 @@ parse_file0(char *filename, DB *db, FILE *f)
confstatus |= CONFIG_VERSION;
confstatus &= ~CONFIG_START;
break;
+ case CMD_TYPE_AXFRPORT:
+ if ((config & CONFIG_VERSION) != CONFIG_VERSION) {
+ syslog(LOG_INFO, "%s: must have version at top of config\n", filename);
+ return (-1);
+ }
+
+ confstatus |= CONFIG_AXFRPORT;
+ confstatus &= ~CONFIG_START;
+ break;
case CMD_TYPE_ZONE:
if ((config & CONFIG_VERSION) != CONFIG_VERSION) {
syslog(LOG_INFO, "%s: must have version at top of config\n", filename);
@@ -318,6 +334,20 @@ parse_file0(char *filename, DB *db, FILE *f)
confstatus |= CONFIG_RECURSEFOR;
confstatus &= ~CONFIG_START;
goto loop;
+ case CMD_TYPE_AXFRFOR:
+ if ((config & CONFIG_VERSION) != CONFIG_VERSION) {
+ syslog(LOG_INFO, "%s: must have version at top of config\n", filename);
+ return (-1);
+ }
+ if (strchr(starttoken, '{') == NULL) {
+ syslog(LOG_INFO, "%s: must have opening brace ('{') in axfr-for entry on line %d", filename, line);
+ return (-1);
+ }
+ config |= CONFIG_AXFRFOR;
+
+ confstatus |= CONFIG_AXFRFOR;
+ confstatus &= ~CONFIG_START;
+ goto loop;
case CMD_TYPE_LOGGING:
if ((config & CONFIG_VERSION) != CONFIG_VERSION) {
syslog(LOG_INFO, "%s: must have version at top of config\n", filename);
@@ -454,13 +484,6 @@ parse_file0(char *filename, DB *db, FILE *f)
#endif
}
- if (sdomain.zonename == NULL) {
- sdomain.zonename = (char *) malloc(DNS_MAXNAME + 1);
- if (sdomain.zonename == NULL) {
- syslog(LOG_INFO, "malloc(1): %m");
- return (-1);
- }
- }
#if __linux__
strncpy((char *)sdomain.zonename, (char *)&domainname[0],
@@ -599,14 +622,7 @@ parse_file0(char *filename, DB *db, FILE *f)
save = *p;
*p = 0;
if (sdomain.aaaa_count < RECORD_COUNT) {
- if (sdomain.aaaa[sdomain.aaaa_count] == NULL) {
- sdomain.aaaa[sdomain.aaaa_count] = (struct in6_addr *)malloc(sizeof(struct in6_addr));
- if (sdomain.aaaa[sdomain.aaaa_count] == NULL) {
- syslog(LOG_INFO, "malloc(2): %m");
- return (-1);
- }
- }
- ia6 = (struct in6_addr *)sdomain.aaaa[sdomain.aaaa_count];
+ ia6 = (struct in6_addr *)&sdomain.aaaa[sdomain.aaaa_count];
sdomain.aaaa_count++;
} else {
syslog(LOG_INFO, "%s: too many aaaa records for zone \"%s\", skipping line %d\n", filename, domainname, line);
@@ -639,16 +655,8 @@ parse_file0(char *filename, DB *db, FILE *f)
save = *p;
*p = 0;
- if (sdomain.mx[sdomain.mx_count] == NULL) {
- sdomain.mx[sdomain.mx_count] = (struct smx *)malloc(sizeof(struct smx));
- if (sdomain.mx[sdomain.mx_count] == NULL) {
- syslog(LOG_INFO, "malloc(3): %m");
- return (-1);
- }
- }
-
if (sdomain.mx_count < RECORD_COUNT) {
- sdomain.mx[sdomain.mx_count]->preference = atoi(starttoken);
+ sdomain.mx[sdomain.mx_count].preference = atoi(starttoken);
} else {
syslog(LOG_INFO, "%s: too many mx records for zone \"%s\", skipping line %d\n", filename, domainname, line);
return (-1);
@@ -672,13 +680,13 @@ parse_file0(char *filename, DB *db, FILE *f)
char *name;
char *n;
- if ((name = dns_label(starttoken, (int *)&sdomain.mx[sdomain.mx_count]->exchangelen)) == NULL) {
+ if ((name = dns_label(starttoken, (int *)&sdomain.mx[sdomain.mx_count].exchangelen)) == NULL) {
fprintf(stderr, "illegal mx server, skipping line %d\n", line);
goto skip;
}
- n = (char *)sdomain.mx[sdomain.mx_count]->exchange;
+ n = (char *)sdomain.mx[sdomain.mx_count].exchange;
- memcpy((char *)n, name, sdomain.mx[sdomain.mx_count]->exchangelen);
+ memcpy((char *)n, name, sdomain.mx[sdomain.mx_count].exchangelen);
free (name);
}
@@ -698,23 +706,15 @@ parse_file0(char *filename, DB *db, FILE *f)
save = *p;
*p = 0;
- if (sdomain.soa == NULL) {
- sdomain.soa = (struct soa*)malloc(sizeof(struct soa));
- if (sdomain.soa == NULL) {
- syslog(LOG_INFO, "malloc(4): %m");
- return (-1);
- }
- }
-
{
char *name;
- if ((name = dns_label(starttoken, (int *)&sdomain.soa->nsserver_len)) == NULL) {
+ if ((name = dns_label(starttoken, (int *)&sdomain.soa.nsserver_len)) == NULL) {
fprintf(stderr, "illegal nameserver, skipping line %d\n", line);
goto skip;
}
- memcpy((char *)&sdomain.soa->nsserver[0], name, sdomain.soa->nsserver_len);
+ memcpy((char *)&sdomain.soa.nsserver[0], name, sdomain.soa.nsserver_len);
free (name);
}
@@ -740,12 +740,12 @@ parse_file0(char *filename, DB *db, FILE *f)
{
char *name;
- if ((name = dns_label(starttoken, (int *)&sdomain.soa->rp_len)) == NULL) {
+ if ((name = dns_label(starttoken, (int *)&sdomain.soa.rp_len)) == NULL) {
fprintf(stderr, "illegal nameserver, skipping line %d\n", line);
goto skip;
}
- memcpy((char *)&sdomain.soa->responsible_person[0], name, sdomain.soa->rp_len);
+ memcpy((char *)&sdomain.soa.responsible_person[0], name, sdomain.soa.rp_len);
free (name);
}
@@ -768,7 +768,7 @@ parse_file0(char *filename, DB *db, FILE *f)
save = *p;
*p = 0;
- sdomain.soa->serial = atoi(starttoken);
+ sdomain.soa.serial = atoi(starttoken);
*p = save;
@@ -789,7 +789,7 @@ parse_file0(char *filename, DB *db, FILE *f)
save = *p;
*p = 0;
- sdomain.soa->refresh = atoi(starttoken);
+ sdomain.soa.refresh = atoi(starttoken);
*p = save;
@@ -810,7 +810,7 @@ parse_file0(char *filename, DB *db, FILE *f)
save = *p;
*p = 0;
- sdomain.soa->retry = atoi(starttoken);
+ sdomain.soa.retry = atoi(starttoken);
*p = save;
@@ -831,7 +831,7 @@ parse_file0(char *filename, DB *db, FILE *f)
save = *p;
*p = 0;
- sdomain.soa->expire = atoi(starttoken);
+ sdomain.soa.expire = atoi(starttoken);
*p = save;
@@ -847,7 +847,7 @@ parse_file0(char *filename, DB *db, FILE *f)
save = *p;
*p = 0;
- sdomain.soa->minttl = atoi(starttoken);
+ sdomain.soa.minttl = atoi(starttoken);
*p = save;
sdomain.flags |= DOMAIN_HAVE_SOA;
@@ -858,14 +858,6 @@ parse_file0(char *filename, DB *db, FILE *f)
save = *p;
*p = 0;
- if (sdomain.ptr == NULL) {
- sdomain.ptr = (char *)malloc(DNS_MAXNAME);
- if (sdomain.ptr == NULL) {
- syslog(LOG_INFO, "malloc(5): %m");
- return (-1);
- }
- }
-
{
char *name;
@@ -895,25 +887,17 @@ parse_file0(char *filename, DB *db, FILE *f)
return (-1);
}
- if (sdomain.ns[sdomain.ns_count] == NULL) {
- sdomain.ns[sdomain.ns_count] = (struct ns*)malloc(sizeof(struct ns));
- if (sdomain.ns[sdomain.ns_count] == NULL) {
- syslog(LOG_INFO, "malloc(6): %m");
- return (-1);
- }
- }
-
{
char *name;
char *n;
- if ((name = dns_label(starttoken, &(sdomain.ns[sdomain.ns_count]->nslen))) == NULL) {
+ if ((name = dns_label(starttoken, &(sdomain.ns[sdomain.ns_count].nslen))) == NULL) {
fprintf(stderr, "illegal ns server, skipping line %d\n", line);
goto skip;
}
- n = (char *)sdomain.ns[sdomain.ns_count]->nsserver;
+ n = (char *)sdomain.ns[sdomain.ns_count].nsserver;
- memcpy((char *)n, name, sdomain.ns[sdomain.ns_count]->nslen);
+ memcpy((char *)n, name, sdomain.ns[sdomain.ns_count].nslen);
free (name);
}
@@ -939,14 +923,6 @@ parse_file0(char *filename, DB *db, FILE *f)
save = *p;
*p = 0;
- if (sdomain.cname == NULL) {
- sdomain.cname = (char *)malloc(DNS_MAXNAME);
- if (sdomain.cname == NULL) {
- syslog(LOG_INFO, "malloc(7): %m");
- return (-1);
- }
- }
-
{
char *name;
@@ -955,7 +931,7 @@ parse_file0(char *filename, DB *db, FILE *f)
goto skip;
}
- memcpy((char *)sdomain.cname, name, sdomain.cnamelen);
+ memcpy((char *)&sdomain.cname[0], name, sdomain.cnamelen);
free (name);
}
@@ -986,15 +962,7 @@ parse_file0(char *filename, DB *db, FILE *f)
* let's remember to put that in reply_txt()
*/
- if (sdomain.txt == NULL) {
- sdomain.txt = (char *)malloc(DNS_MAXNAME);
- if (sdomain.txt == NULL) {
- syslog(LOG_INFO, "malloc(7): %m");
- return (-1);
- }
- }
-
- memcpy(sdomain.txt, starttoken, tokenlen);
+ memcpy(&sdomain.txt, starttoken, tokenlen);
sdomain.txtlen = tokenlen;
*p = save;
@@ -1018,14 +986,6 @@ parse_file0(char *filename, DB *db, FILE *f)
key.data = (char *)converted_name;
key.size = converted_namelen;
- if (sdomain.zone == NULL) {
- sdomain.zone = (char *)malloc(DNS_MAXNAME);
- if (sdomain.zone == NULL) {
- syslog(LOG_INFO, "malloc(X): %m");
- return (-1);
- }
- }
-
memcpy(sdomain.zone, converted_name, converted_namelen);
sdomain.zonelen = converted_namelen;
@@ -1091,6 +1051,29 @@ skip:
confstatus &= ~(CONFIG_VERSION);
confstatus |= CONFIG_START;
}
+ if (confstatus & CONFIG_AXFRPORT) {
+ for (; *starttoken && *starttoken != '"'; starttoken++);
+ starttoken++;
+ for (p = starttoken; *p && *p != '"';p++);
+ if (*p == '\0') {
+ syslog(LOG_INFO, "%s: (%d) malformed line %d", filename, __LINE__, line);
+ return (-1);
+ }
+ *p++ = '\0';
+
+ axfrport = atoi(starttoken);
+
+ if (*p != ';') {
+ syslog(LOG_INFO, "%s: missing trailing semi-colon on line %d", filename, line);
+ return (-1);
+ }
+
+ config |= CONFIG_AXFRPORT;
+
+ confstatus |= CONFIG_START;
+ confstatus &= ~(CONFIG_AXFRPORT);
+ goto loop;
+ }
if (confstatus & CONFIG_INCLUDE) {
confstatus &= ~(CONFIG_INCLUDE);
confstatus |= CONFIG_START;
@@ -1184,6 +1167,39 @@ skip:
return (-1);
}
} /* CONFIG_WILDCARDONLYFOR */
+ if (confstatus & CONFIG_AXFRFOR) {
+ if (*starttoken == '}') {
+ confstatus &= ~(CONFIG_AXFRFOR);
+ confstatus |= CONFIG_START;
+ goto loop;
+ }
+
+ p = strchr(starttoken, '/');
+ if (p == NULL) {
+ if (*starttoken == '\n')
+ goto loop;
+
+ syslog(LOG_INFO, "%s: (%d) malformed line, line %d", filename, __LINE__, line);
+ return (-1);
+ }
+
+ *p++ = '\0';
+
+ address = starttoken;
+ starttoken = p;
+
+ p = strchr(starttoken, ';');
+ if (p == NULL) {
+ syslog(LOG_INFO, "%s: (%d) malformed line, line %d, must have closing semi-colon", filename, __LINE__, line);
+ return (-1);
+ }
+
+ *p = '\0';
+ if (insert_axfr(address, starttoken) < 0) {
+ syslog(LOG_INFO, "%s: address on line %d, is malformed", filename, line);
+ return (-1);
+ }
+ } /* CONFIG_AXFRFOR */
if (confstatus & CONFIG_RECURSEFOR) {
if (*starttoken == '}') {
confstatus &= ~(CONFIG_RECURSEFOR);
blob - 046192e43f483372fe049a86f6400bf67476ee58
blob + 8a616048dce5d950499d17b06177d28e3bc2ff10
--- recurse.c
+++ recurse.c
@@ -90,7 +90,7 @@ struct recurseentry {
} *rn1, *rn2, *rnp;
-static const char rcsid[] = "$Id: recurse.c,v 1.36 2011/04/19 16:33:46 pbug Exp $";
+static const char rcsid[] = "$Id: recurse.c,v 1.37 2011/09/19 19:59:23 pbug Exp $";
/*
* INIT_RECURSE - initialize the recurse singly linked list
@@ -693,11 +693,11 @@ again:
for (i = 0; i < sd->ns_count; i++) {
if (sr->af == AF_INET6) {
- if (lookup_aaaa(db, sr, sd->ns[(sd->ns_ptr + i) % sd->ns_count] ) < 0)
+ if (lookup_aaaa(db, sr, &sd->ns[(sd->ns_ptr + i) % sd->ns_count] ) < 0)
continue;
sr->aaaa_count++;
} else {
- if (lookup_a(db, sr, sd->ns[(sd->ns_ptr + i) % sd->ns_count] ) < 0)
+ if (lookup_a(db, sr, &sd->ns[(sd->ns_ptr + i) % sd->ns_count] ) < 0)
continue;
sr->a_count++;
}
@@ -799,29 +799,14 @@ negative_cache(DB *db, struct recurses *sr)
memset(&sd, 0, sizeof(sd));
sd.zonelen = sr->question->hdr->namelen;
- if (sd.zone == NULL) {
- sd.zone = (char *) malloc(sd.zonelen);
- if (sd.zone == NULL) {
- syslog(LOG_INFO, "malloc: %m");
- return (-1);
- }
- }
- memcpy((char *)sd.zone, (char *)sr->question->hdr->name, sd.zonelen);
+ memcpy((char *)&sd.zone, (char *)sr->question->hdr->name, sd.zonelen);
- if (sd.zonename == NULL) {
- sd.zonename = (char *) malloc(DNS_MAXNAME + 1);
- if (sd.zonename == NULL) {
- syslog(LOG_INFO, "malloc(1): %m");
- return (-1);
- }
- }
-
#if __linux__
- strncpy((char *)sd.zonename, (char *)sr->question->converted_name, DNS_MAXNAME);
+ strncpy((char *)&sd.zonename, (char *)sr->question->converted_name, DNS_MAXNAME);
sd.zonename[DNS_MAXNAME] = 0;
#else
- strlcpy((char *)sd.zonename, (char *)sr->question->converted_name, DNS_MAXNAME + 1);
+ strlcpy((char *)&sd.zonename, (char *)sr->question->converted_name, DNS_MAXNAME + 1);
#endif
sd.created = time(NULL);
@@ -1172,14 +1157,7 @@ again:
if (sdomain.zone == NULL) {
- sdomain.zone = (char *) malloc(cn_len[i]);
- if (sdomain.zone == NULL) {
- syslog(LOG_INFO, "malloc(1): %m");
- return (-1);
- }
-
-
- memcpy(sdomain.zone, converted_name[i], cn_len[i]);
+ memcpy(&sdomain.zone, converted_name[i], cn_len[i]);
sdomain.zonelen = cn_len[i];
}
@@ -1259,7 +1237,7 @@ again:
update = 1;
for (j = 0; j < sdomain.aaaa_count; j++) {
- if (memcmp(sdomain.aaaa[j], p, sizeof(struct in6_addr)) == 0) {
+ if (memcmp(&sdomain.aaaa[j], p, sizeof(struct in6_addr)) == 0) {
#if 0
syslog(LOG_INFO, "record exists already");
#endif
@@ -1290,12 +1268,7 @@ again:
}
if (update) {
- sdomain.aaaa[j] = malloc(sizeof(struct in6_addr));
- if (sdomain.aaaa[j] == NULL) {
- syslog(LOG_ERR, "malloc: %m");
- return(-1);
- }
- memcpy(sdomain.aaaa[j], p, sizeof(struct in6_addr));
+ memcpy(&sdomain.aaaa[j], p, sizeof(struct in6_addr));
sdomain.aaaa_count++;
sdomain.aaaa_ptr = 0;
sdomain.flags |= DOMAIN_HAVE_AAAA;
@@ -1322,13 +1295,8 @@ again:
break;
case DNS_TYPE_TXT:
txtlen = (*p);
- sdomain.txt = malloc(txtlen);
- if (sdomain.txt == NULL) {
- syslog(LOG_ERR, "malloc: %m");
- return (-1);
- }
-
- memcpy(sdomain.txt, (p + 1), txtlen);
+
+ memcpy(&sdomain.txt, (p + 1), txtlen);
sdomain.txtlen = txtlen;
sdomain.flags |= DOMAIN_HAVE_TXT;
@@ -1395,13 +1363,7 @@ again:
}
}
- sdomain.cname = malloc(cn_len[i]);
- if (sdomain.cname == NULL) {
- syslog(LOG_ERR, "malloc: %m");
- return (-1);
- }
-
- memcpy(sdomain.cname, converted_name[i], cn_len[i]);
+ memcpy(&sdomain.cname, converted_name[i], cn_len[i]);
sdomain.cnamelen = cn_len[i];
sdomain.flags |= DOMAIN_HAVE_CNAME;
@@ -1425,14 +1387,7 @@ again:
if (rrcount[pointer] == 0)
pointer++;
} else if (ntohs(a->type) == DNS_TYPE_PTR) {
-
- sdomain.ptr = malloc(cn_len[i]);
- if (sdomain.ptr == NULL) {
- syslog(LOG_ERR, "malloc: %m");
- return (-1);
- }
-
- memcpy(sdomain.ptr, converted_name[i], cn_len[i]);
+ memcpy(&sdomain.ptr, converted_name[i], cn_len[i]);
sdomain.ptrlen = cn_len[i];
sdomain.flags |= DOMAIN_HAVE_PTR;
@@ -1458,7 +1413,7 @@ again:
} else if (ntohs(a->type) == DNS_TYPE_NS) {
update = 1;
for (j = 0; j < sdomain.ns_count; j++) {
- if (memcasecmp((u_char *)sdomain.ns[j]->nsserver, (u_char *)converted_name[i], MIN(cn_len[i], sdomain.ns[j]->nslen)) == 0) {
+ if (memcasecmp((u_char *)sdomain.ns[j].nsserver, (u_char *)converted_name[i], MIN(cn_len[i], sdomain.ns[j].nslen)) == 0) {
#if 0
syslog(LOG_INFO, "record exists already");
#endif
@@ -1472,15 +1427,9 @@ again:
}
if (update) {
- sdomain.ns[j] = malloc(sizeof(struct ns));
- if (sdomain.ns[j] == NULL) {
- syslog(LOG_ERR, "malloc: %m");
- return (-1);
- }
+ memcpy(sdomain.ns[j].nsserver, converted_name[i], cn_len[i]);
+ sdomain.ns[j].nslen = cn_len[i];
- memcpy(&sdomain.ns[j]->nsserver, converted_name[i], cn_len[i]);
- sdomain.ns[j]->nslen = cn_len[i];
-
sdomain.ns_count++;
sdomain.ns_ptr = 0;
sdomain.flags |= DOMAIN_HAVE_NS;
@@ -1509,7 +1458,7 @@ again:
} else if (ntohs(a->type) == DNS_TYPE_MX) {
update = 1;
for (j = 0; j < sdomain.mx_count; j++) {
- if (memcasecmp((u_char *)sdomain.mx[j]->exchange, (u_char *)converted_name[i], MIN(cn_len[i], sdomain.mx[j]->exchangelen)) == 0) {
+ if (memcasecmp((u_char *)sdomain.mx[j].exchange, (u_char *)converted_name[i], MIN(cn_len[i], sdomain.mx[j].exchangelen)) == 0) {
update = 0;
}
}
@@ -1520,16 +1469,10 @@ again:
}
if (update) {
- sdomain.mx[j] = malloc(sizeof(struct smx));
- if (sdomain.mx[j] == NULL) {
- syslog(LOG_ERR, "malloc: %m");
- return (-1);
- }
+ memcpy(&sdomain.mx[j].exchange, converted_name[i], cn_len[i]);
+ sdomain.mx[j].exchangelen = cn_len[i];
+ sdomain.mx[j].preference = ntohs(*preference);
- memcpy(&sdomain.mx[j]->exchange, converted_name[i], cn_len[i]);
- sdomain.mx[j]->exchangelen = cn_len[i];
- sdomain.mx[j]->preference = ntohs(*preference);
-
sdomain.mx_count++;
sdomain.mx_ptr = 0;
sdomain.flags |= DOMAIN_HAVE_MX;
@@ -1617,7 +1560,9 @@ again:
soa->expire = ntohl(mysoa->expire);
soa->minttl = ntohl(mysoa->minttl);
- sdomain.soa = soa;
+ memcpy(&sdomain.soa, soa, sizeof(sdomain.soa));
+ free(soa);
+
sdomain.flags |= DOMAIN_HAVE_SOA;
sdomain.created = time(NULL);
sdomain.ttl = htonl(a->ttl);
@@ -1973,39 +1918,10 @@ remove_zone(DB *db, struct domain *sd)
DBT key;
char *zone;
int zonelen;
- int i;
zone = sd->zone;
zonelen = sd->zonelen;
- if (sd->zonename != NULL)
- free(sd->zonename);
-
- if ((sd->flags & DOMAIN_HAVE_SOA) == DOMAIN_HAVE_SOA) {
- free(sd->soa);
- }
- if ((sd->flags & DOMAIN_HAVE_AAAA) == DOMAIN_HAVE_AAAA) {
- for (i = 0; i < sd->aaaa_count; i++)
- free(sd->aaaa[i]);
- }
- if ((sd->flags & DOMAIN_HAVE_MX) == DOMAIN_HAVE_MX) {
- for (i = 0; i < sd->mx_count; i++)
- free(sd->mx[i]);
- }
- if ((sd->flags & DOMAIN_HAVE_NS) == DOMAIN_HAVE_NS) {
- for (i = 0; i < sd->ns_count; i++)
- free(sd->ns[i]);
- }
- if ((sd->flags & DOMAIN_HAVE_CNAME) == DOMAIN_HAVE_CNAME) {
- free(sd->cname);
- }
- if ((sd->flags & DOMAIN_HAVE_PTR) == DOMAIN_HAVE_PTR) {
- free(sd->ptr);
- }
- if ((sd->flags & DOMAIN_HAVE_TXT) == DOMAIN_HAVE_TXT) {
- free(sd->txt);
- }
-
key.data = (char *)zone;
key.size = zonelen;
@@ -2306,7 +2222,7 @@ lookup_aaaa(DB *db, struct recurses *sr, struct ns *ns
sd = &sdomain;
if ((sd->flags & DOMAIN_HAVE_AAAA) == DOMAIN_HAVE_AAAA) {
- memcpy((char *)&sr->aaaa[sr->aaaa_count], (char *)sd->aaaa[0], sizeof(struct in6_addr));
+ memcpy((char *)&sr->aaaa[sr->aaaa_count], (char *)&sd->aaaa[0], sizeof(struct in6_addr));
sd->a_count++;
found = 1;
blob - 2bc861b56b84af29eb5706c5dcefdd01778dde82
blob + 3b596a24db7c435382259c1c84107d56618e58dd
--- reply.c
+++ reply.c
@@ -59,7 +59,7 @@ extern void slave_shutdown(void);
void update_db(DB *, struct domain *);
struct domain * Lookup_zone(DB *db, char *name, u_int16_t namelen, u_int16_t type, int);
void collects_init(void);
-u_int16_t create_anyreply(struct sreply *sreply, char *reply, int rlen, int offset);
+u_int16_t create_anyreply(struct sreply *sreply, char *reply, int rlen, int offset, int soa);
#ifdef __linux__
static int udp_cksum(const struct iphdr *ip, const struct udphdr *up, int len);
@@ -80,7 +80,7 @@ struct collects {
} *cn1, *cn2, *cnp;
-static const char rcsid[] = "$Id: reply.c,v 1.45 2011/04/12 10:45:49 pbug Exp $";
+static const char rcsid[] = "$Id: reply.c,v 1.46 2011/09/19 19:59:23 pbug Exp $";
/*
* REPLY_A() - replies a DNS question (*q) on socket (so)
@@ -326,7 +326,7 @@ reply_aaaa(struct sreply *sreply, DB *db)
answer->rdlength = htons(sizeof(struct in6_addr));
- memcpy((char *)&answer->rdata, (char *)sd->aaaa[pos++ % mod], sizeof(struct in6_addr));
+ memcpy((char *)&answer->rdata, (char *)&sd->aaaa[pos++ % mod], sizeof(struct in6_addr));
outlen += 28;
/* can we afford to write another header? if no truncate */
@@ -461,13 +461,13 @@ reply_mx(struct sreply *sreply, DB *db)
else
answer->ttl = htonl(sd->ttl);
- answer->rdlength = htons(sizeof(u_int16_t) + sd->mx[mx_count]->exchangelen);
+ answer->rdlength = htons(sizeof(u_int16_t) + sd->mx[mx_count].exchangelen);
- answer->mx_priority = htons(sd->mx[mx_count]->preference);
- memcpy((char *)&answer->exchange, (char *)sd->mx[mx_count]->exchange, sd->mx[mx_count]->exchangelen);
+ answer->mx_priority = htons(sd->mx[mx_count].preference);
+ memcpy((char *)&answer->exchange, (char *)sd->mx[mx_count].exchange, sd->mx[mx_count].exchangelen);
- name = sd->mx[mx_count]->exchange;
- namelen = sd->mx[mx_count]->exchangelen;
+ name = sd->mx[mx_count].exchange;
+ namelen = sd->mx[mx_count].exchangelen;
sd0 = Lookup_zone(db, name, namelen, htons(DNS_TYPE_A), wildcard);
if (sd0 != NULL) {
@@ -500,10 +500,10 @@ reply_mx(struct sreply *sreply, DB *db)
}
}
- outlen += (12 + 2 + sd->mx[mx_count]->exchangelen);
+ outlen += (12 + 2 + sd->mx[mx_count].exchangelen);
/* can we afford to write another header? if no truncate */
- if (sd->mx_count > 1 && (outlen + 12 + 2 + sd->mx[mx_count]->exchangelen) > DNS_MAXUDP) {
+ if (sd->mx_count > 1 && (outlen + 12 + 2 + sd->mx[mx_count].exchangelen) > DNS_MAXUDP) {
NTOHS(odh->query);
SET_DNS_TRUNCATION(odh);
HTONS(odh->query);
@@ -682,8 +682,8 @@ reply_ns(struct sreply *sreply, DB *db)
else
answer->ttl = htonl(sd->ttl);
- name = sd->ns[pos % mod]->nsserver;
- namelen = sd->ns[pos % mod]->nslen;
+ name = sd->ns[pos % mod].nsserver;
+ namelen = sd->ns[pos % mod].nslen;
answer->rdlength = htons(namelen);
@@ -735,7 +735,7 @@ reply_ns(struct sreply *sreply, DB *db)
/* can we afford to write another header? if no truncate */
- if (sd->ns_count > 1 && (outlen + 12 + sd->ns[pos % mod]->nslen) > DNS_MAXUDP) {
+ if (sd->ns_count > 1 && (outlen + 12 + sd->ns[pos % mod].nslen) > DNS_MAXUDP) {
NTOHS(odh->query);
SET_DNS_TRUNCATION(odh);
HTONS(odh->query);
@@ -1224,8 +1224,8 @@ reply_soa(struct sreply *sreply)
p = (char *)&answer->rdata;
- label = sd->soa->nsserver;
- labellen = sd->soa->nsserver_len;
+ label = sd->soa.nsserver;
+ labellen = sd->soa.nsserver_len;
plabel = label;
@@ -1248,8 +1248,8 @@ reply_soa(struct sreply *sreply)
outlen = tmplen;
}
- label = sd->soa->responsible_person;
- labellen = sd->soa->rp_len;
+ label = sd->soa.responsible_person;
+ labellen = sd->soa.rp_len;
plabel = label;
for (i = outlen; i < sizeof(reply); i++) {
@@ -1273,42 +1273,42 @@ reply_soa(struct sreply *sreply)
/* XXX */
- if ((outlen + sizeof(sd->soa->serial)) > sizeof(reply)) {
+ if ((outlen + sizeof(sd->soa.serial)) > sizeof(reply)) {
/* XXX server error reply? */
return;
}
soa_val = (u_int32_t *)&reply[outlen];
- *soa_val = htonl(sd->soa->serial);
- outlen += sizeof(sd->soa->serial); /* XXX */
+ *soa_val = htonl(sd->soa.serial);
+ outlen += sizeof(sd->soa.serial); /* XXX */
/* XXX */
- if ((outlen + sizeof(sd->soa->refresh)) > sizeof(reply)) {
+ if ((outlen + sizeof(sd->soa.refresh)) > sizeof(reply)) {
return;
}
soa_val = (u_int32_t *)&reply[outlen];
- *soa_val = htonl(sd->soa->refresh);
- outlen += sizeof(sd->soa->refresh); /* XXX */
+ *soa_val = htonl(sd->soa.refresh);
+ outlen += sizeof(sd->soa.refresh); /* XXX */
- if ((outlen + sizeof(sd->soa->retry)) > sizeof(reply)) {
+ if ((outlen + sizeof(sd->soa.retry)) > sizeof(reply)) {
return;
}
soa_val = (u_int32_t *)&reply[outlen];
- *soa_val = htonl(sd->soa->retry);
- outlen += sizeof(sd->soa->retry); /* XXX */
+ *soa_val = htonl(sd->soa.retry);
+ outlen += sizeof(sd->soa.retry); /* XXX */
- if ((outlen + sizeof(sd->soa->expire)) > sizeof(reply)) {
+ if ((outlen + sizeof(sd->soa.expire)) > sizeof(reply)) {
return;
}
soa_val = (u_int32_t *)&reply[outlen];
- *soa_val = htonl(sd->soa->expire);
- outlen += sizeof(sd->soa->expire);
+ *soa_val = htonl(sd->soa.expire);
+ outlen += sizeof(sd->soa.expire);
- if ((outlen + sizeof(sd->soa->minttl)) > sizeof(reply)) {
+ if ((outlen + sizeof(sd->soa.minttl)) > sizeof(reply)) {
return;
}
soa_val = (u_int32_t *)&reply[outlen];
- *soa_val = htonl(sd->soa->minttl);
- outlen += sizeof(sd->soa->minttl);
+ *soa_val = htonl(sd->soa.minttl);
+ outlen += sizeof(sd->soa.minttl);
answer->rdlength = htons(&reply[outlen] - &answer->rdata);
@@ -1670,13 +1670,13 @@ reply_nxdomain(struct sreply *sreply)
p = (char *)&answer->rdata;
#if 0
- label = dns_label((char *)mysoa->nsserver, &labellen);
+ label = dns_label((char *)mysoa.nsserver, &labellen);
if (label == NULL)
return;
#endif
- label = sd->soa->nsserver;
- labellen = sd->soa->nsserver_len;
+ label = &sd->soa.nsserver[0];
+ labellen = sd->soa.nsserver_len;
plabel = label;
@@ -1699,8 +1699,8 @@ reply_nxdomain(struct sreply *sreply)
outlen = tmplen;
}
- label = sd->soa->responsible_person;
- labellen = sd->soa->rp_len;
+ label = sd->soa.responsible_person;
+ labellen = sd->soa.rp_len;
plabel = label;
for (i = outlen; i < sizeof(reply); i++) {
@@ -1724,41 +1724,41 @@ reply_nxdomain(struct sreply *sreply)
/* XXX */
- if ((outlen + sizeof(sd->soa->serial)) > sizeof(reply)) {
+ if ((outlen + sizeof(sd->soa.serial)) > sizeof(reply)) {
/* XXX server error reply? */
return;
}
soa_val = (u_int32_t *)&reply[outlen];
- *soa_val = htonl(sd->soa->serial);
- outlen += sizeof(sd->soa->serial);
+ *soa_val = htonl(sd->soa.serial);
+ outlen += sizeof(sd->soa.serial);
- if ((outlen + sizeof(sd->soa->refresh)) > sizeof(reply)) {
+ if ((outlen + sizeof(sd->soa.refresh)) > sizeof(reply)) {
return;
}
soa_val = (u_int32_t *)&reply[outlen];
- *soa_val = htonl(sd->soa->refresh);
- outlen += sizeof(sd->soa->refresh);
+ *soa_val = htonl(sd->soa.refresh);
+ outlen += sizeof(sd->soa.refresh);
- if ((outlen + sizeof(sd->soa->retry)) > sizeof(reply)) {
+ if ((outlen + sizeof(sd->soa.retry)) > sizeof(reply)) {
return;
}
soa_val = (u_int32_t *)&reply[outlen];
- *soa_val = htonl(sd->soa->retry);
- outlen += sizeof(sd->soa->retry);
+ *soa_val = htonl(sd->soa.retry);
+ outlen += sizeof(sd->soa.retry);
- if ((outlen + sizeof(sd->soa->expire)) > sizeof(reply)) {
+ if ((outlen + sizeof(sd->soa.expire)) > sizeof(reply)) {
return;
}
soa_val = (u_int32_t *)&reply[outlen];
- *soa_val = htonl(sd->soa->expire);
- outlen += sizeof(sd->soa->expire);
+ *soa_val = htonl(sd->soa.expire);
+ outlen += sizeof(sd->soa.expire);
- if ((outlen + sizeof(sd->soa->minttl)) > sizeof(reply)) {
+ if ((outlen + sizeof(sd->soa.minttl)) > sizeof(reply)) {
return;
}
soa_val = (u_int32_t *)&reply[outlen];
- *soa_val = htonl(sd->soa->minttl);
- outlen += sizeof(sd->soa->minttl);
+ *soa_val = htonl(sd->soa.minttl);
+ outlen += sizeof(sd->soa.minttl);
answer->rdlength = htons(&reply[outlen] - &answer->rdata);
@@ -1992,8 +1992,8 @@ reply_noerror(struct sreply *sreply)
p = (char *)&answer->rdata;
- label = sd->soa->nsserver;
- labellen = sd->soa->nsserver_len;
+ label = sd->soa.nsserver;
+ labellen = sd->soa.nsserver_len;
plabel = label;
@@ -2016,8 +2016,8 @@ reply_noerror(struct sreply *sreply)
outlen = tmplen;
}
- label = sd->soa->responsible_person;
- labellen = sd->soa->rp_len;
+ label = &sd->soa.responsible_person[0];
+ labellen = sd->soa.rp_len;
plabel = label;
for (i = outlen; i < sizeof(reply); i++) {
@@ -2041,41 +2041,41 @@ reply_noerror(struct sreply *sreply)
/* XXX */
- if ((outlen + sizeof(sd->soa->serial)) > sizeof(reply)) {
+ if ((outlen + sizeof(sd->soa.serial)) > sizeof(reply)) {
/* XXX server error reply? */
return;
}
soa_val = (u_int32_t *)&reply[outlen];
- *soa_val = htonl(sd->soa->serial);
- outlen += sizeof(sd->soa->serial);
+ *soa_val = htonl(sd->soa.serial);
+ outlen += sizeof(sd->soa.serial);
- if ((outlen + sizeof(sd->soa->refresh)) > sizeof(reply)) {
+ if ((outlen + sizeof(sd->soa.refresh)) > sizeof(reply)) {
return;
}
soa_val = (u_int32_t *)&reply[outlen];
- *soa_val = htonl(sd->soa->refresh);
- outlen += sizeof(sd->soa->refresh);
+ *soa_val = htonl(sd->soa.refresh);
+ outlen += sizeof(sd->soa.refresh);
- if ((outlen + sizeof(sd->soa->retry)) > sizeof(reply)) {
+ if ((outlen + sizeof(sd->soa.retry)) > sizeof(reply)) {
return;
}
soa_val = (u_int32_t *)&reply[outlen];
- *soa_val = htonl(sd->soa->retry);
- outlen += sizeof(sd->soa->retry);
+ *soa_val = htonl(sd->soa.retry);
+ outlen += sizeof(sd->soa.retry);
- if ((outlen + sizeof(sd->soa->expire)) > sizeof(reply)) {
+ if ((outlen + sizeof(sd->soa.expire)) > sizeof(reply)) {
return;
}
soa_val = (u_int32_t *)&reply[outlen];
- *soa_val = htonl(sd->soa->expire);
- outlen += sizeof(sd->soa->expire);
+ *soa_val = htonl(sd->soa.expire);
+ outlen += sizeof(sd->soa.expire);
- if ((outlen + sizeof(sd->soa->minttl)) > sizeof(reply)) {
+ if ((outlen + sizeof(sd->soa.minttl)) > sizeof(reply)) {
return;
}
soa_val = (u_int32_t *)&reply[outlen];
- *soa_val = htonl(sd->soa->minttl);
- outlen += sizeof(sd->soa->minttl);
+ *soa_val = htonl(sd->soa.minttl);
+ outlen += sizeof(sd->soa.minttl);
answer->rdlength = htons(&reply[outlen] - &answer->rdata);
@@ -2504,7 +2504,7 @@ reply_any(struct sreply *sreply)
odh->nsrr = 0;
odh->additional = 0;
- outlen = create_anyreply(sreply, (char *)&reply, sizeof(reply), outlen);
+ outlen = create_anyreply(sreply, (char *)&reply, sizeof(reply), outlen, 1);
if (outlen == 0) {
return;
}
@@ -2545,7 +2545,7 @@ reply_any(struct sreply *sreply)
*/
u_int16_t
-create_anyreply(struct sreply *sreply, char *reply, int rlen, int offset)
+create_anyreply(struct sreply *sreply, char *reply, int rlen, int offset, int soa)
{
int a_count, aaaa_count, ns_count, mx_count;
int tmplen, pos, mod;
@@ -2570,7 +2570,7 @@ create_anyreply(struct sreply *sreply, char *reply, in
char *name, *p;
int i;
- if (sd->flags & DOMAIN_HAVE_SOA) {
+ if ((sd->flags & DOMAIN_HAVE_SOA) && soa) {
NTOHS(odh->answer);
odh->answer++;
HTONS(odh->answer);
@@ -2594,8 +2594,8 @@ create_anyreply(struct sreply *sreply, char *reply, in
offset += 10; /* up to rdata length */
- label = sd->soa->nsserver;
- labellen = sd->soa->nsserver_len;
+ label = sd->soa.nsserver;
+ labellen = sd->soa.nsserver_len;
plabel = label;
@@ -2618,8 +2618,8 @@ create_anyreply(struct sreply *sreply, char *reply, in
offset = tmplen;
}
- label = sd->soa->responsible_person;
- labellen = sd->soa->rp_len;
+ label = sd->soa.responsible_person;
+ labellen = sd->soa.rp_len;
plabel = label;
for (i = offset; i < rlen; i++) {
@@ -2641,45 +2641,45 @@ create_anyreply(struct sreply *sreply, char *reply, in
offset = tmplen;
}
- if ((offset + sizeof(sd->soa->serial)) > rlen) {
+ if ((offset + sizeof(sd->soa.serial)) > rlen) {
goto truncate;
}
soa_val = (u_int32_t *)&reply[offset];
- *soa_val = htonl(sd->soa->serial);
- offset += sizeof(sd->soa->serial);
+ *soa_val = htonl(sd->soa.serial);
+ offset += sizeof(sd->soa.serial);
- if ((offset + sizeof(sd->soa->refresh)) > rlen) {
+ if ((offset + sizeof(sd->soa.refresh)) > rlen) {
goto truncate;
}
soa_val = (u_int32_t *)&reply[offset];
- *soa_val = htonl(sd->soa->refresh);
- offset += sizeof(sd->soa->refresh);
+ *soa_val = htonl(sd->soa.refresh);
+ offset += sizeof(sd->soa.refresh);
- if ((offset + sizeof(sd->soa->retry)) > rlen) {
+ if ((offset + sizeof(sd->soa.retry)) > rlen) {
goto truncate;
}
soa_val = (u_int32_t *)&reply[offset];
- *soa_val = htonl(sd->soa->retry);
- offset += sizeof(sd->soa->retry);
+ *soa_val = htonl(sd->soa.retry);
+ offset += sizeof(sd->soa.retry);
- if ((offset + sizeof(sd->soa->expire)) > rlen) {
+ if ((offset + sizeof(sd->soa.expire)) > rlen) {
goto truncate;
}
soa_val = (u_int32_t *)&reply[offset];
- *soa_val = htonl(sd->soa->expire);
- offset += sizeof(sd->soa->expire);
+ *soa_val = htonl(sd->soa.expire);
+ offset += sizeof(sd->soa.expire);
- if ((offset + sizeof(sd->soa->minttl)) > rlen) {
+ if ((offset + sizeof(sd->soa.minttl)) > rlen) {
goto truncate;
}
soa_val = (u_int32_t *)&reply[offset];
- *soa_val = htonl(sd->soa->minttl);
- offset += sizeof(sd->soa->minttl);
+ *soa_val = htonl(sd->soa.minttl);
+ offset += sizeof(sd->soa.minttl);
answer->rdlength = htons(&reply[offset] - answer->rdata);
@@ -2710,8 +2710,8 @@ create_anyreply(struct sreply *sreply, char *reply, in
offset += 10; /* struct answer */
- name = sd->ns[pos % mod]->nsserver;
- namelen = sd->ns[pos % mod]->nslen;
+ name = sd->ns[pos % mod].nsserver;
+ namelen = sd->ns[pos % mod].nslen;
if (offset + namelen > rlen)
goto truncate;
@@ -2729,7 +2729,7 @@ create_anyreply(struct sreply *sreply, char *reply, in
/* can we afford to write another header? if no truncate */
- if (sd->ns_count > 1 && (offset + sd->ns[pos % mod]->nslen) > rlen) {
+ if (sd->ns_count > 1 && (offset + sd->ns[pos % mod].nslen) > rlen) {
goto truncate;
}
@@ -2815,28 +2815,28 @@ create_anyreply(struct sreply *sreply, char *reply, in
answer->type = htons(DNS_TYPE_MX);
answer->class = htons(DNS_CLASS_IN);
answer->ttl = htonl(sd->ttl);
- answer->rdlength = htons(sizeof(u_int16_t) + sd->mx[mx_count]->exchangelen);
+ answer->rdlength = htons(sizeof(u_int16_t) + sd->mx[mx_count].exchangelen);
offset += 10; /* up to rdata length */
mx_priority = (u_int16_t *)&reply[offset];
- *mx_priority = htons(sd->mx[mx_count]->preference);
+ *mx_priority = htons(sd->mx[mx_count].preference);
offset += 2;
- if (offset + sd->mx[mx_count]->exchangelen > rlen)
+ if (offset + sd->mx[mx_count].exchangelen > rlen)
goto truncate;
- memcpy((char *)&reply[offset], (char *)sd->mx[mx_count]->exchange, sd->mx[mx_count]->exchangelen);
+ memcpy((char *)&reply[offset], (char *)sd->mx[mx_count].exchange, sd->mx[mx_count].exchangelen);
- offset += sd->mx[mx_count]->exchangelen;
+ offset += sd->mx[mx_count].exchangelen;
- if ((tmplen = compress_label((u_char*)reply, offset, sd->mx[mx_count]->exchangelen)) > 0) {
+ if ((tmplen = compress_label((u_char*)reply, offset, sd->mx[mx_count].exchangelen)) > 0) {
offset = tmplen;
}
/* can we afford to write another header? if no truncate */
- if (sd->mx_count > 1 && (offset + 12 + 2 + sd->mx[mx_count]->exchangelen) > rlen) {
+ if (sd->mx_count > 1 && (offset + 12 + 2 + sd->mx[mx_count].exchangelen) > rlen) {
goto truncate;
}
@@ -3019,7 +3019,7 @@ create_anyreply(struct sreply *sreply, char *reply, in
answer->rdlength = htons(sizeof(struct in6_addr));
offset += 10;
- memcpy((char *)&reply[offset] ,(char *)sd->aaaa[pos++ % mod], sizeof(struct in6_addr));
+ memcpy((char *)&reply[offset] ,(char *)&sd->aaaa[pos++ % mod], sizeof(struct in6_addr));
offset += 16;
/* can we afford to write another header? if no truncate */
blob - d7e5767f9510013fc6a306022f53e5eeaa8a3d23
blob + b7bd7b870086d2a0a5aedbcc8a290d5e8f17a216
--- wildcarddnsd.8
+++ wildcarddnsd.8
@@ -23,7 +23,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd November 27, 2005
+.Dd September 19, 2011
.Dt WILDCARDDNSD 8
.Os
.Sh NAME
@@ -35,12 +35,14 @@
.Op Fl b Ar address
.Op ...
.Oc
+.Op Fl c Ar size
.Op Fl f Ar file
.Oo
.Op Fl i Ar interface
.Op ...
.Oc
.Op Fl l
+.Op Fl n Ar instances
.Op Fl p Ar port
.Sh DESCRIPTION
.Nm
@@ -63,6 +65,11 @@ to. This option can be repeated multiple times to add
not be used in conjunction with
.Fl i .
.It Xo
+.Fl c
+.Ar size
+Specifies a size in bytes for the SYSV shared memory cache that DB4 is
+using.
+.It Xo
.Fl f
.Ar file
.Xc
@@ -82,6 +89,12 @@ used in conjunction with
.It Fl l
Turn syslog logging of queries on.
.It Xo
+.Fl n
+.Ar instances
+is the number of instances plus one that should be forked for
+.Nm .
+This may be good for multi-cpu/core boxes.
+.It Xo
.Fl p
.Ar port
.Xc
@@ -98,6 +111,7 @@ with
.Pa /etc/wildcarddns.conf
.Sh SEE ALSO
.Xr bind 2 ,
+.Xr fork 2,
.Xr daemon 3 ,
.Xr pf 4 ,
.Sh AUTHORS
blob - 526bbfa48fb12e3339c323ff4096a6af0b4cb747
blob + 8dc0a6aad43863ae95fce65fdd8ae4a2c64f787f
--- wildcarddnsd.cat8
+++ wildcarddnsd.cat8
@@ -4,20 +4,22 @@ NNAAMMEE
wwiillddccaarrddddnnssdd - the Wildcard DNS daemon
SSYYNNOOPPSSIISS
- wwiillddccaarrddddnnssdd [[--bb _a_d_d_r_e_s_s] [...]] [--ff _f_i_l_e] [[--ii _i_n_t_e_r_f_a_c_e] [...]] [--ll]
- [--pp _p_o_r_t]
+ wwiillddccaarrddddnnssdd [[--bb _a_d_d_r_e_s_s] [...]] [--cc _s_i_z_e] [--ff _f_i_l_e] [[--ii _i_n_t_e_r_f_a_c_e]
+ [...]] [--ll] [--nn _i_n_s_t_a_n_c_e_s] [--pp _p_o_r_t]
DDEESSCCRRIIPPTTIIOONN
wwiillddccaarrddddnnssdd is the daemon that runs Wildcard DNS.
The options are as follows:
-
--bb _a_d_d_r_e_s_s
Adds an _a_d_d_r_e_s_s that wwiillddccaarrddddnnssdd should bind(2) to. This option
can be repeated multiple times to add more. May not be used in
conjunction with --ii.
+ --cc _s_i_z_e Specifies a size in bytes for the SYSV shared memory cache that
+ DB4 is using.
+
--ff _f_i_l_e
The configuration file to be used is found at _f_i_l_e.
@@ -28,6 +30,9 @@ DDEESSCCRRIIPPTTIIOONN
--ll Turn syslog logging of queries on.
+ --nn _i_n_s_t_a_n_c_e_s is the number of instances plus one that should be forked
+ for wwiillddccaarrddddnnssdd. This may be good for multi-cpu/core boxes.
+
--pp _p_o_r_t
Specifies the _p_o_r_t that wwiillddccaarrddddnnssdd should listen on. This can
be useful when using wwiillddccaarrddddnnssdd with pf(4).
@@ -36,9 +41,10 @@ FFIILLEESS
_/_e_t_c_/_w_i_l_d_c_a_r_d_d_n_s_._c_o_n_f
SSEEEE AALLSSOO
- bind(2), daemon(3), pf(4),
+ bind(2), fork(2,) daemon(3), pf(4),
AAUUTTHHOORRSS
This software was written by Peter J. Philipp <pjp@centroid.eu>
-OpenBSD 4.8 November 27, 2005 OpenBSD 4.8
+
+OpenBSD 4.9 September 19, 2011 OpenBSD 4.9
repomaster@centroid.eu