Commit Diff
Diff:
cfe99b901e4f3656cfbef4122ccb54b76c2a1400
6b7d7305a7c372ab44d86ad6ee00abd6393fcf30
Commit:
6b7d7305a7c372ab44d86ad6ee00abd6393fcf30
Tree:
05641babc21480336c041b391940321285516b1d
Author:
pjp <pjp@delphinusdns.org>
Committer:
pjp <pjp@delphinusdns.org>
Date:
Mon Nov 4 07:00:40 2019 UTC
Message:
refactor lookup_axfr() do the plumbing to respond to valid notifies and update zone...
blob - 210238d9c3de1370ef4bded18a7839fcf8ea3526
blob + 9c25a3e11054c316b0e9b842d471c211b2882e8d
--- ddd-db.h
+++ ddd-db.h
@@ -27,7 +27,7 @@
*/
/*
- * $Id: ddd-db.h,v 1.25 2019/11/03 15:21:19 pjp Exp $
+ * $Id: ddd-db.h,v 1.26 2019/11/04 07:00:40 pjp Exp $
*/
#ifndef _DB_H
@@ -50,6 +50,7 @@
#define IMSG_SHUTDOWN_MESSAGE 6 /* shut the server down */
#define IMSG_RELOAD_MESSAGE 7 /* reload/restart the server */
#define IMSG_PARSEAUTH_MESSAGE 8 /* parse message with auth required */
+#define IMSG_NOTIFY_MESSAGE 9 /* notify our replicant engine */
#define ERR_DROP 0x1
#define ERR_NXDOMAIN 0x2
blob - aeb78453476e40024440fa8ebc2452de829d1435
blob + 1298d6712235c944327d88ca286a7cc3c06fa232
--- dddctl.c
+++ dddctl.c
@@ -27,7 +27,7 @@
*/
/*
- * $Id: dddctl.c,v 1.82 2019/11/03 15:21:19 pjp Exp $
+ * $Id: dddctl.c,v 1.83 2019/11/04 07:00:40 pjp Exp $
*/
#include <sys/param.h>
@@ -364,7 +364,7 @@ extern int raxfr_tsig(FILE *, u_char *, u_char *, u_ch
extern int memcasecmp(u_char *, u_char *, int);
extern int tsig_pseudoheader(char *, uint16_t, time_t, HMAC_CTX *);
-extern int lookup_axfr(FILE *, int, char *, struct soa *, u_int32_t, char *, char *);
+extern int lookup_axfr(FILE *, int, char *, struct soa *, u_int32_t, char *, char *, int *);
extern int dnssec;
@@ -6492,7 +6492,7 @@ dig(int argc, char *argv[])
}
if (type == DNS_TYPE_AXFR) {
- if (lookup_axfr(f, so, domainname, &mysoa, format, tsigkey, tsigpass) < 0) {
+ if (lookup_axfr(f, so, domainname, &mysoa, format, tsigkey, tsigpass, &segment) < 0) {
exit(1);
}
blob - 8434643c80c2f2a578a70256ee8fe998b848d722
blob + aca93ff852577a5fd36f338bb4cbb5ae1fa9e7cf
--- delphinusdnsd.c
+++ delphinusdnsd.c
@@ -27,7 +27,7 @@
*/
/*
- * $Id: delphinusdnsd.c,v 1.78 2019/11/03 15:21:19 pjp Exp $
+ * $Id: delphinusdnsd.c,v 1.79 2019/11/04 07:00:41 pjp Exp $
*/
@@ -1970,6 +1970,12 @@ axfrentry:
snprintf(replystring, DNS_MAXNAME, "NOTIFY");
build_reply(&sreply, so, buf, len, question, from, fromlen, NULL, NULL, aregion, istcp, 0, NULL, replybuf);
slen = reply_notify(&sreply, NULL);
+
+ /* send notify to replicant process */
+ idata = strlen(question->converted_name) + 1;
+ imsg_compose(ibuf[MY_IMSG_RAXFR], IMSG_NOTIFY_MESSAGE,
+ 0, 0, -1, question->converted_name, idata);
+ msgbuf_write(&ibuf[MY_IMSG_RAXFR]->w);
goto udpout;
} else if (question->tsig.have_tsig && question->tsig.tsigerrorcode != 0) {
@@ -1985,6 +1991,11 @@ axfrentry:
snprintf(replystring, DNS_MAXNAME, "NOTIFY");
build_reply(&sreply, so, buf, len, question, from, fromlen, NULL, NULL, aregion, istcp, 0, NULL, replybuf);
slen = reply_notify(&sreply, NULL);
+ /* send notify to replicant process */
+ idata = strlen(question->converted_name) + 1;
+ imsg_compose(ibuf[MY_IMSG_RAXFR], IMSG_NOTIFY_MESSAGE,
+ 0, 0, -1, question->converted_name, idata);
+ msgbuf_write(&ibuf[MY_IMSG_RAXFR]->w);
goto udpout;
} else {
/* RFC 1996 - 3.10 is probably broken reply REFUSED */
@@ -2373,7 +2384,8 @@ setup_master(ddDB *db, char **av, char *socketpath, st
if (mshutdown) {
dolog(LOG_INFO, "shutting down on signal %d\n", msig);
- unlink(socketpath);
+ if (! debug)
+ unlink(socketpath);
pid = getpgrp();
killpg(pid, msig);
@@ -2390,7 +2402,8 @@ setup_master(ddDB *db, char **av, char *socketpath, st
dolog(LOG_ERR, "munmap: %s\n", strerror(errno));
}
- unlink(socketpath);
+ if (! debug)
+ unlink(socketpath);
dolog(LOG_INFO, "restarting on SIGHUP or command\n");
@@ -2505,6 +2518,7 @@ tcploop(struct cfg *cfg, struct imsgbuf **ibuf)
int axfr_acl = 0;
int sp;
int lfd;
+ int idata;
uint conncnt = 0;
int tcpflags;
pid_t pid;
@@ -2913,6 +2927,11 @@ tcploop(struct cfg *cfg, struct imsgbuf **ibuf)
snprintf(replystring, DNS_MAXNAME, "NOTIFY");
build_reply(&sreply, so, pbuf, len, question, from, fromlen, NULL, NULL, aregion, istcp, 0, NULL, replybuf);
slen = reply_notify(&sreply, NULL);
+ /* send notify to replicant process */
+ idata = strlen(question->converted_name) + 1;
+ imsg_compose(ibuf[MY_IMSG_RAXFR], IMSG_NOTIFY_MESSAGE,
+ 0, 0, -1, &question->converted_name, idata);
+ msgbuf_write(&ibuf[MY_IMSG_RAXFR]->w);
goto tcpout;
} else if (question->tsig.have_tsig && question->tsig.tsigerrorcode != 0) {
@@ -2928,6 +2947,11 @@ tcploop(struct cfg *cfg, struct imsgbuf **ibuf)
snprintf(replystring, DNS_MAXNAME, "NOTIFY");
build_reply(&sreply, so, pbuf, len, question, from, fromlen, NULL, NULL, aregion, istcp, 0, NULL, replybuf);
slen = reply_notify(&sreply, NULL);
+ /* send notify to replicant process */
+ idata = strlen(question->converted_name) + 1;
+ imsg_compose(ibuf[MY_IMSG_RAXFR], IMSG_NOTIFY_MESSAGE,
+ 0, 0, -1, &question->converted_name, idata);
+ msgbuf_write(&ibuf[MY_IMSG_RAXFR]->w);
goto tcpout;
} else {
/* RFC 1996 - 3.10 is probably broken, replying REFUSED */
blob - c1514972ab5cc5b012e43e909dff25c632603645
blob + e717ccc628db936de9f28d9d821386d0534f595f
--- examples/example9.conf
+++ examples/example9.conf
@@ -1,11 +1,11 @@
version "9";
options "cool stuff" {
versionstring "DELPHINUSDNSD - http://delphinusdns.centroid.eu";
- interface "lo0";
- interface "re0";
+ ;interface "lo0";
+ ;interface "re0";
;bind 127.0.0.1;
- ;bind 192.168.34.4;
+ bind 192.168.177.2;
ratelimit-pps 6;
blob - ee7865e16fd98ec22677ca69445e92b6cfb5d0c4
blob + 1be9d99e932c1a9ee5a195b36ccb7f8afe5cb46c
--- parse.y
+++ parse.y
@@ -21,7 +21,7 @@
*/
/*
- * $Id: parse.y,v 1.78 2019/11/03 15:21:19 pjp Exp $
+ * $Id: parse.y,v 1.79 2019/11/04 07:00:41 pjp Exp $
*/
%{
@@ -3769,40 +3769,68 @@ notifysource(struct question *q, struct sockaddr_stora
if (! rz->active)
continue;
- tsigkey = dns_label(rz->tsigkey, &tsigretlen);
zone = dns_label(rz->zonename, &zoneretlen);
- /* if we are the right zone, right tsigkey, and right master IP/IP6 */
- if ((zoneretlen == q->hdr->namelen) &&
- (memcasecmp(zone, q->hdr->name, zoneretlen) == 0) &&
- (tsigretlen == q->tsig.tsigkeylen) &&
- (memcasecmp(tsigkey, q->tsig.tsigkey, tsigretlen) == 0) &&
- (rz->storage.ss_family == from->ss_family)) {
- free(tsigkey);
- free(zone);
- if (from->ss_family == AF_INET) {
- /* IPv4 notify */
- rzs = (struct sockaddr_in *)&rz->storage;
-
- if (fromi->sin_addr.s_addr == rzs->sin_addr.s_addr) {
+ if (q->tsig.have_tsig && q->tsig.tsigverified) {
+ tsigkey = dns_label(rz->tsigkey, &tsigretlen);
+ /* if we are the right zone, right tsigkey, and right master IP/IP6 */
+ if ((zoneretlen == q->hdr->namelen) &&
+ (memcasecmp(zone, q->hdr->name, zoneretlen) == 0) &&
+ (tsigretlen == q->tsig.tsigkeylen) &&
+ (memcasecmp(tsigkey, q->tsig.tsigkey, tsigretlen) == 0) &&
+ (rz->storage.ss_family == from->ss_family)) {
+ free(tsigkey);
+ free(zone);
+ if (from->ss_family == AF_INET) {
+ /* IPv4 notify */
+ rzs = (struct sockaddr_in *)&rz->storage;
+
+ if (fromi->sin_addr.s_addr == rzs->sin_addr.s_addr) {
#if 0
- if (memcmp((void*)&fromi->sin_addr, (void*)&rzs->sin_addr, 4) == 0) {
+ if (memcmp((void*)&fromi->sin_addr, (void*)&rzs->sin_addr, 4) == 0) {
#endif
- return 1;
- }
- } else {
- /* IPv6 notify */
- rzs6 = (struct sockaddr_in6 *)&rz->storage;
+ return 1;
+ }
+ } else {
+ /* IPv6 notify */
+ rzs6 = (struct sockaddr_in6 *)&rz->storage;
- if (memcmp((void*)&fromi6->sin6_addr,
- (void*)&rzs6->sin6_addr, 16) == 0)
- return 1;
+ if (memcmp((void*)&fromi6->sin6_addr,
+ (void*)&rzs6->sin6_addr, 16) == 0)
+ return 1;
+ }
+ } else {
+ free(tsigkey);
+ free(zone);
}
} else {
- free(tsigkey);
- free(zone);
- }
- }
+ /* we don't have tsig here */
+
+ if ((zoneretlen == q->hdr->namelen) &&
+ (memcasecmp(zone, q->hdr->name, zoneretlen) == 0) &&
+ (rz->storage.ss_family == from->ss_family)) {
+ free(zone);
+ if (from->ss_family == AF_INET) {
+ /* IPv4 notify */
+ rzs = (struct sockaddr_in *)&rz->storage;
+
+ if (fromi->sin_addr.s_addr == rzs->sin_addr.s_addr) {
+ return 1;
+ }
+ } else {
+ /* IPv6 notify */
+ rzs6 = (struct sockaddr_in6 *)&rz->storage;
+
+ if (memcmp((void*)&fromi6->sin6_addr,
+ (void*)&rzs6->sin6_addr, 16) == 0)
+ return 1;
+ }
+ } else {
+ free(zone);
+ }
+ } /* if havetsig */
+
+ } /* SLIST_FOREACH */
return 0;
}
blob - 32d425da3e8824050fd64de55fa36b32cdaa00c0
blob + 0bc1065d3bf183ff275cbbea1664801581210844
--- raxfr.c
+++ raxfr.c
@@ -26,7 +26,7 @@
*
*/
/*
- * $Id: raxfr.c,v 1.22 2019/11/03 15:47:41 pjp Exp $
+ * $Id: raxfr.c,v 1.23 2019/11/04 07:00:41 pjp Exp $
*/
#include <sys/types.h>
@@ -139,7 +139,7 @@ extern struct rbtree * Lookup_zone(ddDB *, char *, u_
extern struct rbtree * find_rrset(ddDB *db, char *name, int len);
extern struct rrset * find_rr(struct rbtree *rbt, u_int16_t rrtype);
extern struct question *build_question(char *, int, int, char *);
-extern int lookup_axfr(FILE *, int, char *, struct soa *, u_int32_t, char *, char *);
+extern int lookup_axfr(FILE *, int, char *, struct soa *, u_int32_t, char *, char *, int *);
extern int find_tsig_key(char *, int, char *, int);
@@ -1261,8 +1261,14 @@ replicantloop(ddDB *db, struct imsgbuf *ibuf, struct i
struct rrset *rrset;
struct rr *rrp;
struct timeval tv;
+ fd_set rset;
+ int max = 0;
+ struct imsg imsg;
+ ssize_t n, datalen;
+ char *dn = NULL;
+
#if __OpenBSD__
if (pledge("stdio wpath rpath cpath inet", NULL) < 0) {
perror("pledge");
@@ -1317,8 +1323,9 @@ replicantloop(ddDB *db, struct imsgbuf *ibuf, struct i
free(rbt);
free(apex);
}
-
+
for (;;) {
+ FD_ZERO(&rset);
if (endspurt) {
tv.tv_sec = 0;
tv.tv_usec = 5000;
@@ -1326,8 +1333,14 @@ replicantloop(ddDB *db, struct imsgbuf *ibuf, struct i
tv.tv_sec = 1;
tv.tv_usec = 0;
}
+
+ FD_SET(ibuf->fd, &rset);
+
+ if (ibuf->fd > max)
+ max = ibuf->fd;
+
- sel = select(0, NULL, NULL, NULL, &tv);
+ sel = select(max + 1, &rset, NULL, NULL, &tv);
if (sel == -1) {
dolog(LOG_INFO, "select error: %s\n", strerror(errno));
continue;
@@ -1359,6 +1372,83 @@ replicantloop(ddDB *db, struct imsgbuf *ibuf, struct i
lastnow = now;
+ if (FD_ISSET(ibuf->fd, &rset)) {
+ if ((n = imsg_read(ibuf)) < 0 && errno != EAGAIN) {
+ dolog(LOG_ERR, "imsg read failure %s\n", strerror(errno));
+ continue;
+ }
+ if (n == 0) {
+ /* child died? */
+ dolog(LOG_INFO, "sigpipe on child? exiting.\n");
+ continue;
+ }
+
+ for (;;) {
+ if ((n = imsg_get(ibuf, &imsg)) < 0) {
+ dolog(LOG_ERR, "imsg read error: %s\n", strerror(errno));
+ break;
+ } else {
+ if (n == 0)
+ break;
+
+ datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
+
+ dolog(LOG_DEBUG, "got imsg of type %d\n", imsg.hdr.type);
+
+ switch(imsg.hdr.type) {
+ case IMSG_NOTIFY_MESSAGE:
+ dn = malloc(datalen);
+ if (dn == NULL) {
+ dolog(LOG_INFO, "malloc: %s\n", strerror(errno));
+ break;
+ }
+
+ memcpy(dn, imsg.data, datalen);
+ dn[datalen - 1] = '\0';
+
+ SLIST_FOREACH(lrz, &rzones, rzone_entry) {
+ if (lrz->zonename == NULL)
+ continue;
+
+ if (strcmp(dn, lrz->zonename) == 0)
+ break;
+ }
+
+ if (lrz != NULL) {
+ dolog(LOG_DEBUG, "zone %s is being notified now\n", dn);
+ if ((serial = get_remote_soa(lrz)) == MY_SOCK_TIMEOUT) {
+ dolog(LOG_INFO, "timeout upon notify, dropping\n");
+ } else if (serial > lrz->soa.serial) {
+ /* initiate AXFR and update zone */
+ dolog(LOG_INFO, "new higher serial detected (%ld vs. %ld)\n", serial, lrz->soa.serial);
+
+ if (pull_rzone(lrz, now, 0) < 0) {
+ dolog(LOG_INFO, "AXFR failed\n");
+ }
+
+ /* schedule restart */
+ schedule_restart(lrz->zonename, now + 100);
+ /*
+ * we've scheduled a restart and there may be more
+ * AXFR's to do we only have a window of 100 seconds
+ * so we select for 5000 microseconds only, so that
+ * other tasks can still complete.
+ */
+ endspurt = 1;
+ }
+ } else {
+ dolog(LOG_DEBUG, "couldn't find a rzone for domainame %s\n", dn);
+ }
+
+ free(dn);
+ break;
+ } /* switch */
+
+ imsg_free(&imsg);
+ }
+ }
+ }
+
LIST_FOREACH_SAFE(sp0, &myschedules, myschedule_entry, sp1) {
if (sp0->when <= now) {
/* we hit a timeout on refresh */
@@ -1801,13 +1891,14 @@ do_raxfr(FILE *f, struct rzone *rzone)
struct sockaddr *sa;
socklen_t slen = sizeof(struct sockaddr_in);
- int window = 32768;
+ u_int window = 32768;
char tsigpass[512];
char humanpass[1024];
char *keyname;
int tsigpasslen, keynamelen;
- int format = (TCP_FORMAT | ZONE_FORMAT);
+ u_int32_t format = (TCP_FORMAT | ZONE_FORMAT);
int len, dotsig = 1;
+ int segment;
struct soa mysoa;
@@ -1820,7 +1911,7 @@ do_raxfr(FILE *f, struct rzone *rzone)
#ifndef __linux__
/* biggen the window */
- while (setsockopt(so, SOL_SOCKET, SO_RCVBUF, &window, sizeof(window)) != -1)
+ while (window && setsockopt(so, SOL_SOCKET, SO_RCVBUF, &window, sizeof(window)) != -1)
window <<= 1;
#endif
@@ -1874,8 +1965,9 @@ do_raxfr(FILE *f, struct rzone *rzone)
dotsig = 0;
}
+ segment = 0;
- if (lookup_axfr(f, so, rzone->zonename, &mysoa, format, ((dotsig == 0) ? NULL : rzone->tsigkey), ((dotsig == 0) ? NULL : humanpass)) < 0) {
+ if (lookup_axfr(f, so, rzone->zonename, &mysoa, format, ((dotsig == 0) ? NULL : rzone->tsigkey), humanpass, &segment) < 0) {
dolog(LOG_ERR, "lookup_axfr() failed\n");
close(so);
return -1;
@@ -1887,34 +1979,34 @@ do_raxfr(FILE *f, struct rzone *rzone)
int
-pull_rzone(struct rzone *lrz, time_t now, int doschedule)
+pull_rzone(struct rzone *rzone, time_t now, int doschedule)
{
char *p, *q;
FILE *f;
char buf[PATH_MAX];
- p = strrchr(lrz->filename, '/');
+ p = strrchr(rzone->filename, '/');
if (p == NULL) {
- dolog(LOG_INFO, "can't determine temporary filename from %s\n", lrz->filename);
+ dolog(LOG_INFO, "can't determine temporary filename from %s\n", rzone->filename);
if (doschedule)
- schedule_retry(lrz->zonename, now + lrz->soa.retry);
+ schedule_retry(rzone->zonename, now + rzone->soa.retry);
return -1;
}
p++;
q = p;
if (*p == '\0') {
- dolog(LOG_INFO, "can't determine temporary filename from %s (2)\n", lrz->filename);
+ dolog(LOG_INFO, "can't determine temporary filename from %s (2)\n", rzone->filename);
if (doschedule)
- schedule_retry(lrz->zonename, now + lrz->soa.retry);
+ schedule_retry(rzone->zonename, now + rzone->soa.retry);
return -1;
}
snprintf(buf, sizeof(buf), "%s.XXXXXXXXXXXXXX", p);
if ((p = mktemp(buf)) == NULL) {
- dolog(LOG_INFO, "can't determine temporary filename from %s (3)\n", lrz->filename);
+ dolog(LOG_INFO, "can't determine temporary filename from %s (3)\n", rzone->filename);
if (doschedule)
- schedule_retry(lrz->zonename, now + lrz->soa.retry);
+ schedule_retry(rzone->zonename, now + rzone->soa.retry);
return -1;
}
@@ -1922,18 +2014,18 @@ pull_rzone(struct rzone *lrz, time_t now, int doschedu
f = fopen(p, "w");
if (f == NULL) {
- dolog(LOG_INFO, "can't create temporary filename for zone %s\n", lrz->zonename);
+ dolog(LOG_INFO, "can't create temporary filename for zone %s\n", rzone->zonename);
if (doschedule)
- schedule_retry(lrz->zonename, now + lrz->soa.retry);
+ schedule_retry(rzone->zonename, now + rzone->soa.retry);
return -1;
}
- fprintf(f, "; REPLICANT file for zone %s gotten on %lld\n\n", lrz->zonename, now);
+ fprintf(f, "; REPLICANT file for zone %s gotten on %lld\n\n", rzone->zonename, now);
- if (do_raxfr(f, lrz) < 0) {
+ if (do_raxfr(f, rzone) < 0) {
dolog(LOG_INFO, "do_raxfr failed\n");
if (doschedule)
- schedule_retry(lrz->zonename, now + lrz->soa.retry);
+ schedule_retry(rzone->zonename, now + rzone->soa.retry);
return -1;
}
@@ -1943,7 +2035,7 @@ pull_rzone(struct rzone *lrz, time_t now, int doschedu
if (link(p, q) < 0) {
dolog(LOG_ERR, "can't link %s to %s\n", p, q);
if (doschedule)
- schedule_retry(lrz->zonename, now + lrz->soa.retry);
+ schedule_retry(rzone->zonename, now + rzone->soa.retry);
return -1;
}
blob - 227b1c45245d3041735135445511a427101a723b
blob + 3dab4938782baf6f999affcbe7ee6a22c156bc95
--- util.c
+++ util.c
@@ -27,7 +27,7 @@
*/
/*
- * $Id: util.c,v 1.44 2019/11/03 10:37:05 pjp Exp $
+ * $Id: util.c,v 1.45 2019/11/04 07:00:41 pjp Exp $
*/
#include <sys/types.h>
@@ -103,9 +103,8 @@ int tsig_pseudoheader(char *, uint16_t, time_t, HMAC_C
char * bin2hex(char *, int);
u_int64_t timethuman(time_t);
char * bitmap2human(char *, int);
-int lookup_axfr(FILE *, int, char *, struct soa *, u_int32_t, char *, char *);
+int lookup_axfr(FILE *, int, char *, struct soa *, u_int32_t, char *, char *, int *);
-static int segment;
static int bytes_received, answers;
static int additionalcount = 0;
@@ -1646,7 +1645,7 @@ bitmap2human(char *bitmap, int len)
int
-lookup_axfr(FILE *f, int so, char *zonename, struct soa *mysoa, u_int32_t format, char *tsigkey, char *tsigpass)
+lookup_axfr(FILE *f, int so, char *zonename, struct soa *mysoa, u_int32_t format, char *tsigkey, char *tsigpass, int *segment)
{
char query[512];
char pseudo_packet[512];
@@ -1941,10 +1940,10 @@ lookup_axfr(FILE *f, int so, char *zonename, struct so
HMAC_Update(ctx, estart, (p - estart));
}
- if (segment == 0 && (format & ZONE_FORMAT) && f != NULL)
+ if (*segment == 0 && (format & ZONE_FORMAT) && f != NULL)
fprintf(f, "zone \"%s\" {\n", zonename);
- segment++;
+ (*segment)++;
for (count = 0; count < segmentcount; count++) {
char mac[32];
repomaster@centroid.eu