Commit Diff
Diff:
15376126260d832604a55beb211387394efee4fb
854878fb557179a769be62065e7a86dfc955b471
Commit:
854878fb557179a769be62065e7a86dfc955b471
Tree:
8f786e13bc6431980850a053ed50c6ba7415ab51
Author:
pjp <pjp@delphinusdns.org>
Committer:
pjp <pjp@delphinusdns.org>
Date:
Wed Aug 26 07:17:26 2020 UTC
Message:
A zone "" {} MUST now have a valid zone in it, as we use it for simplifying AXFR. redo some logic in AXFR's speeding it up considerably. In databases, from a minute in replying to a few seconds. add zone.c file which handles these zone improvements. tested on OpenBSD/amd64
blob - c41403a0c603aa8cdb741d4d55e4c1c0c9aac4a0
blob + a252b5cd9c0f77c84e1b89abd2f48657aae0a1f7
--- Makefile.linux
+++ Makefile.linux
@@ -8,8 +8,8 @@ AR=ar
all: delphinusdnsd dddctl
-delphinusdnsd: imsg-buffer.o imsg.o additional.o parse.o delphinusdnsd.o reply.o region.o log.o axfr.o filter.o ratelimit.o passlist.o base64.o dnssec.o util.o ent.o db.o tsig.o raxfr.o forward.o cache.o
- $(CC) $(CFLAGS) -o delphinusdnsd/delphinusdnsd additional.o imsg-buffer.o imsg.o delphinusdnsd.o parse.o reply.o region.o log.o axfr.o filter.o ratelimit.o passlist.o base64.o dnssec.o util.o ent.o db.o tsig.o raxfr.o forward.o cache.o $(LDADD)
+delphinusdnsd: imsg-buffer.o imsg.o additional.o parse.o delphinusdnsd.o reply.o region.o log.o axfr.o filter.o ratelimit.o passlist.o base64.o dnssec.o util.o ent.o db.o tsig.o raxfr.o forward.o cache.o zone.o
+ $(CC) $(CFLAGS) -o delphinusdnsd/delphinusdnsd additional.o imsg-buffer.o imsg.o delphinusdnsd.o parse.o reply.o region.o log.o axfr.o filter.o ratelimit.o passlist.o base64.o dnssec.o util.o ent.o db.o tsig.o raxfr.o forward.o cache.o zone.o $(LDADD)
dddctl: dddctl.o util.o dnssec.o parse.o base64.o ent.o raxfr.o tsig.o region.o imsg-buffer.o imsg.o sign.o query.o
$(CC) $(CFLAGS) -o dddctl/dddctl dddctl.o util.o dnssec.o base64.o parse.o ent.o db.o raxfr.o tsig.o region.o imsg-buffer.o imsg.o sign.o query.o $(LDADD)
@@ -88,6 +88,9 @@ forward.o: forward.c
cache.o: cache.c
$(CC) $(CFLAGS) -c cache.c
+
+zone.o: zone.c
+ $(CC) $(CFLAGS) -c zone.c
install: install-delphinusdnsd install-dddctl
blob - 4b7bd93ad40c62c3e64172071d1ee8dcab67c976
blob + 38e5a4a3044ec0bdcdd24478097835f366a9b774
--- axfr.c
+++ axfr.c
@@ -27,7 +27,7 @@
*/
/*
- * $Id: axfr.c,v 1.47 2020/08/08 05:51:48 pjp Exp $
+ * $Id: axfr.c,v 1.48 2020/08/26 07:17:26 pjp Exp $
*/
#include <sys/types.h>
@@ -125,13 +125,16 @@ extern int domaincmp(struct node *e1, struct node *e2)
extern char * dns_label(char *, int *);
extern int additional_tsig(struct question *, char *, int, int, int, int, HMAC_CTX *);
extern int find_tsig_key(char *keyname, int keynamelen, char *key, int keylen);
+extern int have_zone(char *zonename, int zonelen);
+
int notify = 0; /* do not notify when set to 0 */
extern int debug, verbose;
extern time_t time_changed;
extern int tsig;
extern long glob_time_offset;
+extern struct zonetree zonehead;
SLIST_HEAD(, axfrentry) axfrhead;
@@ -840,8 +843,7 @@ axfr_connection(int so, char *address, int is_ipv6, dd
char *buf;
char tsigkey[512];
- char *p;
- char *q;
+ char *p, *q;
char *reply, *replybuf;
int len, dnslen = 0;
@@ -852,13 +854,12 @@ axfr_connection(int so, char *address, int is_ipv6, dd
int envelopcount;
int tsigkeylen;
- struct node *n, *nx;
+ struct zoneentry find, *res;
struct dns_header *dh, *odh;
struct sreply sreply;
struct question *question, *fq;
- struct rbtree *rbt = NULL, *rbt2 = NULL, *saverbt = NULL, *soa = NULL;
+ struct rbtree *rbt = NULL, *rbt2 = NULL, *soa = NULL;
struct rrset *rrset = NULL;
- struct rr *rrp = NULL;
ddDBT key, data;
HMAC_CTX *tsigctx = NULL;
@@ -942,6 +943,8 @@ axfr_connection(int so, char *address, int is_ipv6, dd
goto drop;
}
+ question->aa = 1;
+
if (ntohs(question->hdr->qclass) != DNS_CLASS_IN) {
dolog(LOG_INFO, "AXFR question wasn't for class DNS_CLASS_IN, drop\n");
goto drop;
@@ -976,6 +979,11 @@ axfr_connection(int so, char *address, int is_ipv6, dd
q = question->hdr->name;
qlen = question->hdr->namelen;
+ if (have_zone(q, qlen) != 1) {
+ dolog(LOG_INFO, "not in our list of zones, drop\n");
+ goto drop;
+ }
+
rbt = find_rrset(db, q, qlen);
if (rbt == NULL) {
rbt2 = get_soa(db, question);
@@ -1064,49 +1072,25 @@ axfr_connection(int so, char *address, int is_ipv6, dd
outlen = build_soa(db, (reply + 2), outlen, soa, question);
rrcount = 1;
envelopcount = 1;
-
- RB_FOREACH_SAFE(n, domaintree, &db->head, nx) {
- if ((rbt = calloc(1, sizeof(struct rbtree))) == NULL) {
- dolog(LOG_INFO, "calloc: %s\n", strerror(errno));
- goto drop;
- }
- if ((saverbt = calloc(1, sizeof(struct rbtree))) == NULL) {
- dolog(LOG_INFO, "calloc: %s\n", strerror(errno));
- goto drop;
- }
- memcpy((char*)rbt, (char*)n->data, sizeof(struct rbtree));
- memcpy((char*)saverbt,(char*)n->data, sizeof(struct rbtree));
+ memcpy(find.name, q, qlen);
+ find.namelen = qlen;
+ if ((res = RB_FIND(zonetree, &zonehead, &find)) == NULL) {
+ dolog(LOG_INFO, "internal error getting zonename\n");
+ goto drop;
+ }
+
+ TAILQ_FOREACH(wep, &res->walkhead, walk_entry) {
+ rbt = wep->rbt;
+
if (checklabel(db, rbt, soa, question)) {
fq = build_fake_question(rbt->zone, rbt->zonelen, 0, NULL, 0);
+ fq->aa = 1;
build_reply(&sreply, so, (p + 2), dnslen, fq, NULL, 0, rbt, NULL, 0xff, 1, 0, replybuf);
+
outlen = create_anyreply(&sreply, (reply + 2), 65535, outlen, 0);
free_question(fq);
-
- if ((rrset = find_rr(rbt, DNS_TYPE_NS)) != NULL) {
- rrp = TAILQ_FIRST(&rrset->rr_head);
- if (rrp != NULL &&
- ((struct ns *)rrp->rdata)->ns_type & NS_TYPE_DELEGATE) {
- TAILQ_FOREACH(rrp, &rrset->rr_head, entries) {
- fq = build_fake_question(((struct ns *)rrp->rdata)->nsserver,
- ((struct ns *)rrp->rdata)->nslen, 0, NULL, 0);
- rbt2 = find_rrset(db, fq->hdr->name, fq->hdr->namelen);
- if (rbt2 == NULL) {
- free_question(fq);
- continue;
- }
-
- build_reply(&sreply, so, (p + 2), dnslen, fq, NULL, 0, rbt2, NULL, 0xff, 1, 0, replybuf);
- outlen = create_anyreply(&sreply, (reply + 2), 65535, outlen, 0);
- if (rbt2) {
- rbt2 = NULL;
- }
- free_question(fq);
-
- } /* TAILQ_FOREACH */
- } /* if (rrp != NULL */
- } /* if (find_rr */
} /* if checklabel */
/*
@@ -1210,10 +1194,6 @@ drop:
rbt2 = NULL;
}
- if (saverbt) {
- saverbt = NULL;
- }
-
close(so);
exit(0);
}
@@ -1314,11 +1294,6 @@ build_soa(ddDB *db, char *reply, int offset, struct rb
offset += 12; /* up to rdata length */
-#if 0
- p = (char *)&answer->rdata;
-#endif
-
-
label = ((struct soa *)rrp->rdata)->nsserver;
labellen = ((struct soa *)rrp->rdata)->nsserver_len;
@@ -1394,50 +1369,6 @@ build_soa(ddDB *db, char *reply, int offset, struct rb
int
checklabel(ddDB *db, struct rbtree *rbt, struct rbtree *soa, struct question *q)
{
- struct rbtree *tmprbt;
- struct rrset *rrset;
- char *p;
- int plen;
-
- if (memcmp(rbt, soa, sizeof(struct rbtree)) == 0)
- return 1;
-
- p = rbt->zone;
- plen = rbt->zonelen;
-
- do {
- if (*p == '\0')
- return (0);
-
- tmprbt = find_rrset(db, p, plen);
- if (tmprbt == NULL) {
- plen -= (*p + 1);
- p = (p + (*p + 1));
-
- continue;
- }
-
- /*
- * the encountered label has an SOA before we got to the
- * root, so we skip this record entirely...
- */
-
- if ((rrset = find_rr(tmprbt, DNS_TYPE_SOA)) != NULL) {
- 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 - a48ad910eb3176a6646f80c027f96e15bf8ddb1f
blob + 99276c3c9b611c059f10ed80a11f8b5a9a522191
--- ddd-db.h
+++ ddd-db.h
@@ -27,7 +27,7 @@
*/
/*
- * $Id: ddd-db.h,v 1.52 2020/08/08 16:04:52 pjp Exp $
+ * $Id: ddd-db.h,v 1.53 2020/08/26 07:17:26 pjp Exp $
*/
#ifndef _DB_H
@@ -554,5 +554,25 @@ struct pkt_imsg {
#define SHAREDMEMSIZE 400
#define SHAREDMEMSIZE3 200
+
+struct walkentry {
+ struct rbtree *rbt;
+ TAILQ_ENTRY(walkentry) walk_entry;
+} *we1, *wep;
+
+struct zoneentry {
+ char name[DNS_MAXNAME];
+ int namelen;
+ char *humanname;
+ TAILQ_HEAD(, walkentry) walkhead;
+ RB_ENTRY(zoneentry) zone_entry;
+};
+
+RB_HEAD(zonetree, zoneentry);
+RB_PROTOTYPE(zonetree, zoneentry, zone_entry, zonecmp);
+
+extern int zonecmp(struct zoneentry *, struct zoneentry *);
+
+
#endif /* _DB_H */
blob - e0fc726639a5e17359bdbef3cd4d7b4cacef3e72
blob + 438317dbc980bee95616bfd96e0e4734c0936282
--- dddctl.c
+++ dddctl.c
@@ -27,7 +27,7 @@
*/
/*
- * $Id: dddctl.c,v 1.115 2020/07/26 14:03:50 pjp Exp $
+ * $Id: dddctl.c,v 1.116 2020/08/26 07:17:26 pjp Exp $
*/
#include <sys/types.h>
@@ -110,8 +110,8 @@ int insert_filter(char *, char *);
int insert_passlist(char *, char *);
int insert_notifyddd(char *, char *);
int insert_forward(struct sockaddr_storage *, uint16_t, char *);
+int insert_zone(char *);
-
int illdestination;
int *ptr = &illdestination;
@@ -201,6 +201,12 @@ main(int argc, char *argv[])
usage(argc, argv);
exit(1);
+}
+
+int
+insert_zone(char *zonename)
+{
+ return 0;
}
int
blob - 0bdb320c4f0156c7cc96f497ee8ca3f7cff5eee7
blob + cd1cdd116889e56474388ff51be6501b10bf7488
--- delphinusdnsd/Makefile.freebsd
+++ delphinusdnsd/Makefile.freebsd
@@ -2,7 +2,7 @@
PROG=delphinusdnsd
-SRCS=delphinusdnsd.c parse.y reply.c additional.c region.c log.c axfr.c filter.c ratelimit.c passlist.c base64.c dnssec.c util.c ent.c db.c imsg-buffer.c imsg.c tsig.c raxfr.c forward.c cache.c
+SRCS=delphinusdnsd.c parse.y reply.c additional.c region.c log.c axfr.c filter.c ratelimit.c passlist.c base64.c dnssec.c util.c ent.c db.c imsg-buffer.c imsg.c tsig.c raxfr.c forward.c cache.c zone.c
CFLAGS= -Wall -g -L/usr/local/lib
CFLAGS+= -I${.CURDIR}/..
blob - 2d7bba39756d8e7577a6f1ee301ce0a57c5a6405
blob + 26713dd94c0b9d5c9ac5e927f696f26e252474b3
--- delphinusdnsd/Makefile.netbsd
+++ delphinusdnsd/Makefile.netbsd
@@ -2,7 +2,7 @@
PROG=delphinusdnsd
-SRCS=delphinusdnsd.c parse.y reply.c additional.c region.c log.c axfr.c filter.c ratelimit.c passlist.c base64.c dnssec.c util.c ent.c db.c imsg-buffer.c imsg.c tsig.c raxfr.c forward.c cache.c
+SRCS=delphinusdnsd.c parse.y reply.c additional.c region.c log.c axfr.c filter.c ratelimit.c passlist.c base64.c dnssec.c util.c ent.c db.c imsg-buffer.c imsg.c tsig.c raxfr.c forward.c cache.c zone.c
CFLAGS= -g
CFLAGS+= -I${.CURDIR}/.. -I/usr/pkg/libressl/include
blob - cab0daf5d78ed9b40d47431d6ab4c53deeb7723f
blob + 07b4fa22f8be4f01c59e73823511fe379b48aea5
--- delphinusdnsd/Makefile.openbsd
+++ delphinusdnsd/Makefile.openbsd
@@ -2,7 +2,7 @@
PROG=delphinusdnsd
-SRCS=delphinusdnsd.c parse.y reply.c additional.c region.c log.c axfr.c filter.c ratelimit.c passlist.c base64.c dnssec.c util.c ent.c db.c tsig.c raxfr.c forward.c cache.c
+SRCS=delphinusdnsd.c parse.y reply.c additional.c region.c log.c axfr.c filter.c ratelimit.c passlist.c base64.c dnssec.c util.c ent.c db.c tsig.c raxfr.c forward.c cache.c zone.c
#CFLAGS= -DDEBUG -g -Wall
CFLAGS= -Wall -g
blob - e1aacb41f72712b9b08844bddebe705be562f3b3
blob + e6cffe0cd059b6caf21457266f206a6818381395
--- delphinusdnsd.c
+++ delphinusdnsd.c
@@ -27,7 +27,7 @@
*/
/*
- * $Id: delphinusdnsd.c,v 1.140 2020/08/19 12:49:03 pjp Exp $
+ * $Id: delphinusdnsd.c,v 1.141 2020/08/26 07:17:26 pjp Exp $
*/
@@ -176,6 +176,7 @@ extern int notifysource(struct question *, struct soc
extern int drop_privs(char *, struct passwd *);
extern struct rbtree * get_soa(ddDB *, struct question *);
extern struct rbtree * get_ns(ddDB *, struct rbtree *, int *);
+extern void populate_zone(ddDB *db);
struct question *convert_question(struct parsequestion *, int);
@@ -680,6 +681,7 @@ main(int argc, char *argv[], char *environ[])
}
if (axfrport && axfrport != port) {
+ populate_zone(db);
/* axfr port below */
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
@@ -722,6 +724,7 @@ main(int argc, char *argv[], char *environ[])
exit(1);
}
} else if (axfrport && axfrport == port) {
+ populate_zone(db);
afd[i] = -1;
}
@@ -820,6 +823,7 @@ main(int argc, char *argv[], char *environ[])
/* axfr socket */
if (axfrport && axfrport != port) {
+ populate_zone(db);
if ((afd[i] = socket(pifap->ifa_addr->sa_family, SOCK_STREAM, IPPROTO_TCP)) < 0) {
dolog(LOG_INFO, "tcp socket: %s\n", strerror(errno));
ddd_shutdown();
@@ -849,6 +853,7 @@ main(int argc, char *argv[], char *environ[])
exit(1);
}
} else if (axfrport && axfrport == port) {
+ populate_zone(db);
afd[i] = -1;
}
blob - 6f7ed18f15bc57b2ddc653234e4a5b35c4b62e82
blob + 8c6b3b016139c53214b808cd6d8c75b4a067698e
--- forward.c
+++ forward.c
@@ -27,7 +27,7 @@
*/
/*
- * $Id: forward.c,v 1.41 2020/08/08 05:51:48 pjp Exp $
+ * $Id: forward.c,v 1.42 2020/08/26 07:17:26 pjp Exp $
*/
#include <sys/types.h>
@@ -474,7 +474,7 @@ drop:
fwq1->so = -1;
if (fwq1->returnso != -1)
- close(fwq2->returnso);
+ close(fwq1->returnso);
if (fwq1->tsigkey)
free(fwq1->tsigkey);
blob - 83a795fd60f944a2cfaa2a8394f8c13329b5d64f
blob + f6d811366d066a252005ef2cfbf5eaa086045044
--- parse.y
+++ parse.y
@@ -21,7 +21,7 @@
*/
/*
- * $Id: parse.y,v 1.113 2020/08/08 05:51:48 pjp Exp $
+ * $Id: parse.y,v 1.114 2020/08/26 07:17:26 pjp Exp $
*/
%{
@@ -96,6 +96,7 @@ extern int insert_forward(int, struct sockaddr_storage
extern int insert_passlist(char *, char *);
extern int insert_tsig(char *, char *);
extern int insert_tsig_key(char *, int, char *, int);
+extern int insert_zone(char *);
extern void ddd_shutdown(void);
extern int mybase64_encode(u_char const *, size_t, char *, size_t);
extern int mybase64_decode(char const *, u_char *, size_t);
@@ -809,6 +810,13 @@ zone:
zonelabel:
QUOTEDSTRING
+ {
+ if (insert_zone($1) < 0) {
+ return -1;
+ }
+
+ free($1);
+ }
;
zonecontent:
blob - /dev/null
blob + 8a129f4e58c6068d4dfaa05aedcc30b9043dd481 (mode 644)
--- /dev/null
+++ zone.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2020 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.
+ *
+ */
+
+/*
+ * $Id: zone.c,v 1.1 2020/08/26 07:17:26 pjp Exp $
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#ifdef __linux__
+#include <grp.h>
+#define __USE_BSD 1
+#include <endian.h>
+#include <bsd/stdlib.h>
+#include <bsd/string.h>
+#include <bsd/sys/queue.h>
+#define __unused
+#include <bsd/sys/tree.h>
+#include <bsd/sys/endian.h>
+#else /* not linux */
+#include <sys/queue.h>
+#include <sys/tree.h>
+#endif /* __linux__ */
+
+
+
+#include "ddd-dns.h"
+#include "ddd-db.h"
+
+void init_zone(void);
+int insert_zone(char *);
+int have_zone(char *zonename, int zonelen);
+void populate_zone(ddDB *db);
+int zonecmp(struct zoneentry *, struct zoneentry *);
+
+extern void dolog(int, char *, ...);
+extern in_addr_t getmask(int);
+extern int getmask6(int, struct sockaddr_in6 *);
+extern char * dns_label(char *, int *);
+extern void ddd_shutdown(void);
+extern int dn_contains(char *name, int len, char *anchorname, int alen);
+
+extern int debug, verbose;
+
+struct zonetree zonehead = RB_INITIALIZER(&zonehead);
+RB_GENERATE(zonetree, zoneentry, zone_entry, zonecmp);
+
+int
+insert_zone(char *zonename)
+{
+ struct zoneentry *zep;
+ int len;
+ char *tmp;
+
+ if (strlen(zonename) > DNS_MAXNAME) {
+ dolog(LOG_INFO, "zonename too long\n");
+ return -1;
+ }
+
+ zep = malloc(sizeof(struct zoneentry));
+ if (zep == NULL) {
+ dolog(LOG_INFO, "malloc: %s\n", strerror(errno));
+ return -1;
+ }
+
+ tmp = dns_label(zonename, &len);
+ zep->namelen = len;
+ memcpy(zep->name, tmp, len);
+ free(tmp);
+
+ zep->humanname = strdup(zonename);
+ if (zep->humanname == NULL) {
+ dolog(LOG_INFO, "strdup failed\n");
+ return -1;
+ }
+
+ TAILQ_INIT(&zep->walkhead);
+
+ RB_INSERT(zonetree, &zonehead, zep);
+ return (0);
+}
+
+void
+populate_zone(ddDB *db)
+{
+ struct node *walk;
+ struct zoneentry find, *res;
+ struct rbtree *rbt = NULL;
+ char *p;
+ int plen;
+
+ RB_FOREACH(walk, domaintree, &db->head) {
+ rbt = (struct rbtree *)walk->data;
+ if (rbt == NULL) {
+ continue;
+ }
+
+ for (plen = rbt->zonelen, p = rbt->zone; plen > 0;
+ p++, plen--) {
+ memcpy(find.name, p, plen);
+ find.namelen = plen;
+ if ((res = RB_FIND(zonetree, &zonehead, &find)) != NULL) {
+ break;
+ }
+
+ plen -= *p;
+ p += *p;
+ }
+
+ TAILQ_FOREACH(wep, &res->walkhead, walk_entry) {
+ if (wep->rbt == rbt)
+ break;
+ }
+
+ if (wep)
+ continue;
+
+ if ((wep = malloc(sizeof(struct walkentry))) == NULL) {
+ dolog(LOG_INFO, "malloc: %s\n", strerror(errno));
+ ddd_shutdown();
+ sleep(10);
+ exit(1);
+ }
+
+ wep->rbt = rbt;
+ TAILQ_INSERT_TAIL(&res->walkhead, wep, walk_entry);
+ }
+}
+
+int
+have_zone(char *zonename, int zonelen)
+{
+ struct zoneentry find, *res;
+
+ memcpy(find.name, zonename, zonelen);
+ find.namelen = zonelen;
+ if ((res = RB_FIND(zonetree, &zonehead, &find)) != NULL) {
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+zonecmp(struct zoneentry *e1, struct zoneentry *e2)
+{
+ if (e1->namelen == e2->namelen)
+ return (memcmp(e1->name, e2->name, e1->namelen));
+ else if (e1->namelen < e2->namelen)
+ return -1;
+ else
+ return 1;
+}
repomaster@centroid.eu