Commit Diff
Diff:
1af8b3d18b647dadccbf700de0c1cf22ad5c771e
acf49a7d4fe06aeaa5f43d5b6ace335d7f495821
Commit:
acf49a7d4fe06aeaa5f43d5b6ace335d7f495821
Tree:
e42db5df088a666bfa03226528df617636b266c5
Author:
pjp <pjp@delphinusdns.org>
Committer:
pjp <pjp@delphinusdns.org>
Date:
Fri Jul 10 10:42:27 2020 UTC
Message:
shuttling large packets via IMSG wasn't a very good idea. Instead set up three shared memory regions with slots, IMSG is used to indicate the offset in the particular region to grab information, it tends to work. Also I identified a backlog. When a question is handed off from mainloop to forward, it should now greedily get them all or face a backlog. It seems to do this well now. There is some code and debugging crap left that I will remove later.
blob - 9de010d1bbff020d9e21278e2c74e6475b2acf24
blob + 9ce214292bd89d86ed916fa9ee39115588cf2aaa
--- cache.c
+++ cache.c
@@ -27,7 +27,7 @@
*/
/*
- * $Id: cache.c,v 1.2 2020/07/08 17:33:28 pjp Exp $
+ * $Id: cache.c,v 1.3 2020/07/10 10:42:27 pjp Exp $
*/
#include <sys/types.h>
@@ -87,6 +87,7 @@ extern void dolog(int, char *, ...);
extern char * expand_compression(u_char *, u_char *, u_char *, u_char *, int *, int);
extern void pack(char *, char *, int);
extern void pack16(char *, u_int16_t);
+extern void pack32(char *, u_int32_t);
extern void unpack(char *, char *, int);
extern uint16_t unpack16(char *);
extern uint32_t unpack32(char *);
@@ -97,8 +98,8 @@ extern int tsig;
extern int dnssec;
extern int cache;
-int cacheit(u_char *, u_char *, u_char *, struct imsgbuf *, int);
-struct scache * build_cache(u_char *, u_char *, u_char *, uint16_t, char *, int, uint32_t, uint16_t, struct imsgbuf *, int);
+int cacheit(u_char *, u_char *, u_char *, struct imsgbuf *, struct imsgbuf *, char *);
+struct scache * build_cache(u_char *, u_char *, u_char *, uint16_t, char *, int, uint32_t, uint16_t, struct imsgbuf *, struct imsgbuf *, char *);
void transmit_rr(struct scache *, void *, int);
@@ -155,7 +156,7 @@ static struct cache_logic supported_cache[] = {
struct scache *
-build_cache(u_char *payload, u_char *estart, u_char *end, uint16_t rdlen, char *name, int namelen, uint32_t dnsttl, uint16_t dnstype, struct imsgbuf *imsgbuf, int fd)
+build_cache(u_char *payload, u_char *estart, u_char *end, uint16_t rdlen, char *name, int namelen, uint32_t dnsttl, uint16_t dnstype, struct imsgbuf *imsgbuf, struct imsgbuf *bimsgbuf, char *ptr)
{
static struct scache ret;
@@ -169,7 +170,8 @@ build_cache(u_char *payload, u_char *estart, u_char *e
ret.dnsttl = dnsttl;
ret.rrtype = dnstype;
ret.imsgbuf = imsgbuf;
- ret.fd = fd;
+ ret.bimsgbuf = bimsgbuf;
+ ret.shared = ptr;
return (&ret);
}
@@ -177,26 +179,51 @@ build_cache(u_char *payload, u_char *estart, u_char *e
void
transmit_rr(struct scache *scache, void *rr, int rrsize)
{
- struct rr_imsg ri;
+ struct rr_imsg ri, *pri;
+ int offset, i;
- memset(&ri, 0, sizeof(ri));
- memcpy(&ri.name, scache->name, sizeof(ri.name));
- ri.namelen = scache->namelen;
+ memcpy(ri.imsg.rr.name, scache->name, sizeof(ri.imsg.rr.name));
+ ri.imsg.rr.namelen = scache->namelen;
- ri.ttl = scache->dnsttl;
- ri.rrtype = scache->rrtype;
+ ri.imsg.rr.ttl = scache->dnsttl;
+ ri.imsg.rr.rrtype = scache->rrtype;
- memcpy(&ri.un, rr, rrsize);
- ri.unlen = rrsize;
+ memcpy(&ri.imsg.rr.un, rr, rrsize);
+ ri.imsg.rr.buflen = rrsize;
+ ri.read = 0;
+
+ /* wait for lock */
+ while (scache->shared[0] == '*') {
+ usleep(arc4random() % 300);
+ }
+
+ scache->shared[0] = '*'; /* nice semaphore eh? */
+
- imsg_compose(scache->imsgbuf, IMSG_RR_ATTACHED, 0, 0, -1, (void*)&ri, sizeof(ri));
- msgbuf_write(&scache->imsgbuf->w);
+ for (pri = (struct rr_imsg *)&scache->shared[16], i = 0;
+ i < SHAREDMEMSIZE; i++, pri++) {
+ if (unpack32((char *)&pri->read) == 1) {
+ memcpy(pri, &ri, sizeof(struct rr_imsg));
+ pack32((char *)&pri->read, 0);
+ break;
+ }
+ }
+
+ if (i == SHAREDMEMSIZE) {
+ dolog(LOG_INFO, "can't find an open slot in sharedmemsize\n");
+ }
+
+ scache->shared[0] = ' '; /* release */
+
+ offset = i;
+
+
}
int
-cacheit(u_char *payload, u_char *estart, u_char *end, struct imsgbuf *imsgbuf, int fd)
+cacheit(u_char *payload, u_char *estart, u_char *end, struct imsgbuf *imsgbuf, struct imsgbuf *bimsgbuf, char *ptr)
{
- struct dns_header *dh = (struct dns_header *)payload;
+ struct dns_header *dh;
struct scache *scache;
char expand[DNS_MAXNAME + 1];
int elen, i, x;
@@ -209,6 +236,7 @@ cacheit(u_char *payload, u_char *estart, u_char *end,
struct cache_logic *cr;
+ dh = (struct dns_header *)payload;
p += sizeof(struct dns_header); /* skip dns_header */
elen = 0,
@@ -238,6 +266,7 @@ cacheit(u_char *payload, u_char *estart, u_char *end,
pb += 4; /* skip type and class */
for (x = 0; x < ntohs(dh->answer); x++) {
+ printf("%d out of %d\n", x, ntohs(dh->answer));
elen = 0;
memset(&expand, 0, sizeof(expand));
pb = expand_compression(pb, estart, end, (u_char *)&expand, &elen, sizeof(expand));
@@ -266,7 +295,7 @@ cacheit(u_char *payload, u_char *estart, u_char *end,
pb += 10; /* skip answerd */
- scache = build_cache(pb, estart, end, rdlen, expand, elen, rrttl, rrtype, imsgbuf, fd);
+ scache = build_cache(pb, estart, end, rdlen, expand, elen, rrttl, rrtype, imsgbuf, bimsgbuf, ptr);
for (cr = supported_cache; cr->rrtype != 0; cr++) {
if (rrtype == cr->rrtype) {
@@ -282,6 +311,13 @@ cacheit(u_char *payload, u_char *estart, u_char *end,
} /* for(x ... */
+ i = 42;
+ if (imsg_compose(bimsgbuf, IMSG_RR_ATTACHED, 0, 0, -1, &i, sizeof(int)) != 1) {
+ dolog(LOG_INFO, "imsg_compose failed: %s\n", strerror(errno));
+ }
+
+ if (msgbuf_write(&bimsgbuf->w) == -1)
+ dolog(LOG_ERR, "msgbuf_write: %s\n", strerror(errno));
return (0);
}
@@ -300,6 +336,8 @@ cache_rrsig(struct scache *scache)
u_int32_t tmp4;
u_char *p = q;
+ memset(&rs, 0, sizeof(struct rrsig));
+
BOUNDS_CHECK((q + 2), scache->payload, scache->rdlen, scache->end);
tmp = unpack16(q);
rs.type_covered = ntohs(tmp);
@@ -344,7 +382,7 @@ cache_rrsig(struct scache *scache)
memcpy(&rs.signature, q, rs.signature_len);
q += rs.signature_len;
- transmit_rr(scache, &rs, sizeof(rs));
+ transmit_rr(scache, (void *)&rs, sizeof(rs));
return (q - scache->estart);
}
@@ -358,6 +396,8 @@ cache_ds(struct scache *scache)
u_char *p = scache->payload;
u_char *q = p;
+ memset(&d, 0, sizeof(struct ds));
+
BOUNDS_CHECK((scache->payload + 2), q, scache->rdlen, scache->end);
tmpshort = unpack16(p);
d.key_tag = ntohs(tmpshort);
@@ -389,6 +429,8 @@ cache_sshfp(struct scache *scache)
u_char *p = scache->payload;
u_char *q = p;
+ memset(&s, 0, sizeof(struct sshfp));
+
BOUNDS_CHECK((scache->payload + 1), q, scache->rdlen, scache->end);
s.algorithm = *p++;
BOUNDS_CHECK((scache->payload + 1), q, scache->rdlen, scache->end);
@@ -418,6 +460,9 @@ cache_dnskey(struct scache *scache)
u_char *p = scache->payload;
u_char *q = p;
+
+ memset(&dk, 0, sizeof(struct dnskey));
+
BOUNDS_CHECK((scache->payload + 2), q, scache->rdlen, scache->end);
tmpshort = unpack16(p);
dk.flags = ntohs(tmpshort);
@@ -454,6 +499,8 @@ cache_mx(struct scache *scache)
int max = sizeof(expand);
int elen = 0;
+ memset(&mx, 0, sizeof(struct smx));
+
BOUNDS_CHECK((q + 2), scache->payload, scache->rdlen, scache->end);
mxpriority = unpack16(q);
@@ -492,6 +539,8 @@ cache_nsec3(struct scache *scache)
u_int16_t iter;
u_char *brr = scache->payload; /* begin of rd record :-) */
+ memset(&n, 0, sizeof(struct nsec3));
+
BOUNDS_CHECK((scache->payload + 1), brr, scache->rdlen, scache->end);
n.algorithm = *p++;
BOUNDS_CHECK((scache->payload + 1), brr, scache->rdlen, scache->end);
@@ -537,6 +586,9 @@ cache_nsec3param(struct scache *scache)
u_char *p = scache->payload;
u_char *q = scache->payload;
+
+ memset(&np, 0, sizeof(struct nsec3param));
+
BOUNDS_CHECK((scache->payload + 1), q, scache->rdlen, scache->end);
np.algorithm = *p++;
BOUNDS_CHECK((scache->payload + 1), q, scache->rdlen, scache->end);
@@ -594,6 +646,7 @@ cache_ns(struct scache *scache)
int max = sizeof(expand);
int elen = 0;
+ memset(&nsi, 0, sizeof(struct ns));
memset(&expand, 0, sizeof(expand));
save = expand_compression(q, scache->estart, scache->end, (u_char *)&expand, &elen, max);
if (save == NULL) {
@@ -626,6 +679,8 @@ cache_aaaa(struct scache *scache)
u_char *p = scache->payload;
u_char *q = p;
+ memset(&aaaa, 0, sizeof(struct aaaa));
+
BOUNDS_CHECK((scache->payload + sizeof(ia)), q, scache->rdlen, scache->end);
unpack((char *)&ia, p, sizeof(struct in6_addr));
p += sizeof(ia);
@@ -645,6 +700,8 @@ cache_a(struct scache *scache)
u_char *q = p;
struct a ar;
+ memset(&ar, 0, sizeof(ar));
+
BOUNDS_CHECK((scache->payload + sizeof(ia)), q, scache->rdlen, scache->end);
ar.a = unpack32(p);
p += sizeof(ia);
@@ -664,6 +721,8 @@ cache_tlsa(struct scache *scache)
u_char *q = p;
uint16_t rdlen = scache->rdlen;
+ memset(&t, 0, sizeof(struct tlsa));
+
BOUNDS_CHECK((scache->payload + 1), q, scache->rdlen, scache->end);
t.usage = *p++;
BOUNDS_CHECK((scache->payload + 1), q, scache->rdlen, scache->end);
@@ -700,6 +759,8 @@ cache_srv(struct scache *scache)
int max = sizeof(expand);
int elen = 0;
+ memset(&s, 0, sizeof(struct srv));
+
BOUNDS_CHECK((q + 2), scache->payload, scache->rdlen, scache->end);
tmp16 = unpack16(q);
s.priority = ntohs(tmp16);
@@ -724,7 +785,7 @@ cache_srv(struct scache *scache)
memcpy(&s.target, expand, sizeof(s.target));
- transmit_rr(scache, &s, sizeof(s));
+ transmit_rr(scache, (void*)&s, sizeof(s));
return (q - scache->estart);
}
@@ -741,7 +802,6 @@ cache_naptr(struct scache *scache)
int max = sizeof(expand);
int elen = 0;
int len, i;
-
/* we won't cache naptr either for now */
return -1;
blob - 866e25b34fd845ad68b572f55286b2fb21919680
blob + 224012d7f096d27b87de1620bbce641a2ffbdb56
--- db.c
+++ db.c
@@ -27,7 +27,7 @@
*/
/*
- * $Id: db.c,v 1.20 2020/07/08 12:29:02 pjp Exp $
+ * $Id: db.c,v 1.21 2020/07/10 10:42:27 pjp Exp $
*/
#include <sys/types.h>
@@ -359,7 +359,7 @@ expire_rr(ddDB *db, char *name, int len, u_int16_t rrt
/* expire these */
if (rrtype != DNS_TYPE_RRSIG) {
- if (difftime(now, rp->created) >= rp->ttl) {
+ if (difftime(now, rp->created) >= (double)rp->ttl) {
count = 0;
TAILQ_FOREACH_SAFE(rt1, &rp->rr_head, entries, rt2) {
@@ -378,7 +378,7 @@ expire_rr(ddDB *db, char *name, int len, u_int16_t rrt
count = 0;
TAILQ_FOREACH_SAFE(rt1, &rp->rr_head, entries, rt2) {
struct rrsig *rrsig = (struct rrsig *)rt1->rdata;
- if (difftime(now, rrsig->created) >= rrsig->ttl) {
+ if (difftime(now, rrsig->created) >= (double)rrsig->ttl) {
TAILQ_REMOVE(&rp->rr_head, rt1, entries);
free(rt1->rdata);
free(rt1);
@@ -410,7 +410,8 @@ expire_db(ddDB *db, int all)
now = time(NULL);
else
#if __OpenBSD__
- now = 67768036191673199;
+ now = 4000000000; /* Tue Oct 2 09:06:40 CEST 2096 hbdM */
+
#else
now = 2147483647;
#endif
blob - 73c44f9575948ea6e7166ad447f3d47ec7b579bf
blob + 0a260facbed7194329a37a3655e8d6967b1156ad
--- ddd-db.h
+++ ddd-db.h
@@ -27,7 +27,7 @@
*/
/*
- * $Id: ddd-db.h,v 1.40 2020/07/08 12:29:02 pjp Exp $
+ * $Id: ddd-db.h,v 1.41 2020/07/10 10:42:27 pjp Exp $
*/
#ifndef _DB_H
@@ -64,6 +64,7 @@
#define IMSG_FORWARD_UDP 12 /* forward a UDP packet */
#define IMSG_FORWARD_TCP 13 /* forward a TCP packet (with fd) */
#define IMSG_RR_ATTACHED 14 /* an RR is sent through imsg */
+#define IMSG_PARSEERROR_MESSAGE 15 /* return error message from pledge parser */
#define ERR_DROP 0x1
#define ERR_NXDOMAIN 0x2
@@ -358,6 +359,9 @@ struct cfg {
int sockcount; /* set sockets */
int nth;
pid_t pid;
+ char *shptr; /* shared memory 1 */
+ char *shptr2; /* shared memory 2 */
+ char *shptr3; /* shared memory 3 */
ddDB *db; /* database */
};
@@ -435,7 +439,8 @@ struct scache {
uint32_t dnsttl;
uint16_t rrtype;
struct imsgbuf *imsgbuf;
- int fd;
+ struct imsgbuf *bimsgbuf;
+ char *shared;
};
struct cache_logic {
@@ -460,52 +465,48 @@ struct reply_logic {
#define MIN(a,b) (((a) < (b))?(a):(b))
#endif
+struct sf_imsg {
+ int read;
+ int len;
+ char pad[12];
+ struct sforward sf;
+};
+
struct rr_imsg {
- char name[DNS_MAXNAME + 1];
- int namelen;
- uint16_t rrtype;
- uint32_t ttl;
-
- uint16_t unlen;
+ int read;
+ int len;
+ char pad[12];
union {
- struct dnskey dnskey;
- struct rrsig rrsig;
- struct nsec nsec;
- struct nsec3 nsec3;
- struct nsec3param nsec3param;
- struct ds ds;
- struct soa soa;
- struct smx mx;
- struct ns ns;
- struct srv srv;
- struct sshfp sshfp;
- struct tlsa tlsa;
- struct naptr naptr;
- struct cname cname;
- struct ptr ptr;
- struct txt txt;
- struct a a;
- struct aaaa aaaa;
- } un;
-#define ri_dnskey un.dnskey
-#define ri_rrsig un.rrsig
-#define ri_nsec un.nsec
-#define ri_nsec3 un.nsec3
-#define ri_nsec3param un.nsec3param
-#define ri_ds un.ds
-#define ri_soa un.soa
-#define ri_mx un.mx
-#define ri_ns un.ns
-#define ri_srv un.srv
-#define ri_sshfp un.sshfp
-#define ri_tlsa un.tlsa
-#define ri_naptr un.naptr
-#define ri_cname un.cname
-#define ri_ptr un.ptr
-#define ri_txt un.txt
-#define ri_a un.a
-#define ri_aaaa un.aaaa
+ struct {
+ char name[DNS_MAXNAME + 1];
+ int namelen;
+ uint16_t rrtype;
+ uint32_t ttl;
+
+ uint16_t buflen;
+
+ char un[7000];
+ } rr;
+
+ char pad[8192];
+ } imsg;
}; /* end of struct rr_imsg */
+struct fwdpq {
+ int read;
+ int rc;
+ int istcp;
+ int cache;
+ int tsigcheck;
+ struct tsig tsig;
+ char mac[32];
+ int buflen;
+
+ char buf[16384];
+};
+
+
+#define SHAREDMEMSIZE 400
+#define SHAREDMEMSIZE3 200
#endif /* _DB_H */
blob - 33815e91fb373265741f5cbfc0452b6fc10f5fb7
blob + 42283e6fd021cd854bfafa8b42c3191522391f92
--- ddd-dns.h
+++ ddd-dns.h
@@ -27,7 +27,7 @@
*/
/*
- * $Id: ddd-dns.h,v 1.20 2020/07/06 07:17:40 pjp Exp $
+ * $Id: ddd-dns.h,v 1.21 2020/07/10 10:42:27 pjp Exp $
*/
#ifndef _DNS_H
@@ -298,6 +298,7 @@ struct parsequestion {
struct sforward {
int family;
+ time_t gotit;
struct sockaddr_in from4;
struct sockaddr_in6 from6;
blob - 8377026cb9f92ac91b184a1cb0c5fe424bf8572c
blob + 4fdb03fbfd80a21c077acdab7a1a1b85ca2d5023
--- delphinusdnsd.c
+++ delphinusdnsd.c
@@ -27,7 +27,7 @@
*/
/*
- * $Id: delphinusdnsd.c,v 1.117 2020/07/08 12:29:02 pjp Exp $
+ * $Id: delphinusdnsd.c,v 1.118 2020/07/10 10:42:27 pjp Exp $
*/
@@ -328,12 +328,18 @@ main(int argc, char *argv[], char *environ[])
struct cfg *cfg;
struct imsgbuf cortex_ibuf;
struct imsgbuf *ibuf;
+ struct rr_imsg *ri = NULL;
+ struct sf_imsg *sf = NULL;
+ struct fwdpq *fwdpq = NULL;
static ddDB *db;
time_t now;
struct tm *ltm;
+ char *shptr;
+ int shsize;
+
if (geteuid() != 0) {
fprintf(stderr, "must be started as root\n");
@@ -576,7 +582,60 @@ main(int argc, char *argv[], char *environ[])
}
}
+ if (forward) {
+ shsize = 16 + (SHAREDMEMSIZE * sizeof(struct sf_imsg));
+ shptr = mmap(NULL, shsize, PROT_READ | PROT_WRITE, MAP_SHARED |\
+ MAP_ANON, -1, 0);
+
+ if (shptr == MAP_FAILED) {
+ dolog(LOG_ERR, "failed to setup rlimit mmap segment, exit\n");
+ exit(1);
+ }
+
+ /* initialize */
+ for (sf = (struct sf_imsg *)&shptr[16], i = 0; i < SHAREDMEMSIZE; i++, sf++) {
+ sf->read = 1;
+ }
+
+ cfg->shptr = shptr;
+
+ shsize = 16 + (SHAREDMEMSIZE * sizeof(struct rr_imsg));
+
+ shptr = mmap(NULL, shsize, PROT_READ | PROT_WRITE, MAP_SHARED |\
+ MAP_ANON, -1, 0);
+
+ if (shptr == MAP_FAILED) {
+ dolog(LOG_ERR, "failed to setup rlimit mmap segment, exit\n");
+ exit(1);
+ }
+
+ /* initialize */
+ for (ri = (struct rr_imsg *)&shptr[16], i = 0; i < SHAREDMEMSIZE; i++, ri++) {
+ ri->read = 1;
+ }
+
+ cfg->shptr2 = shptr;
+
+ shsize = 16 + (SHAREDMEMSIZE3 * sizeof(struct fwdpq));
+
+ shptr = mmap(NULL, shsize, PROT_READ | PROT_WRITE, MAP_SHARED |\
+ MAP_ANON, -1, 0);
+
+ if (shptr == MAP_FAILED) {
+ dolog(LOG_ERR, "failed to setup rlimit mmap segment, exit\n");
+ exit(1);
+ }
+
+ /* initialize */
+ for (fwdpq = (struct fwdpq *)&shptr[16], i = 0; i < SHAREDMEMSIZE3; i++, fwdpq++) {
+ pack32((char *)&fwdpq->read, 1);
+ }
+
+ cfg->shptr3 = shptr;
+
+ } /* if forward */
+
pw = getpwnam(DEFAULT_PRIVILEGE);
if (pw == NULL) {
dolog(LOG_INFO, "getpwnam: %s\n", strerror(errno));
@@ -1543,6 +1602,7 @@ mainloop(struct cfg *cfg, struct imsgbuf *ibuf)
struct rbtree *rbt0 = NULL, *rbt1 = NULL;
struct rrset *csd;
struct rr *rr_csd;
+ struct sf_imsg sf, *sfi = NULL;
struct sreply sreply;
struct reply_logic *rl = NULL;
@@ -1558,6 +1618,7 @@ mainloop(struct cfg *cfg, struct imsgbuf *ibuf)
struct sforward *sforward;
ssize_t n, datalen;
+ int ix;
sforward = (struct sforward *)calloc(1, sizeof(struct sforward));
@@ -2137,8 +2198,34 @@ forwardudp:
} else
sforward->havemac = 0;
+ sforward->gotit = time(NULL);
+ memcpy(&sf.sf, sforward, sizeof(struct sforward));
+
+ /* wait for lock */
+ while (cfg->shptr[0] == '*') {
+ usleep(arc4random() % 300);
+ }
+
+ cfg->shptr[0] = '*'; /* nice semaphore eh? */
+
+ for (sfi = (struct sf_imsg *)&cfg->shptr[16], ix = 0;
+ ix < SHAREDMEMSIZE; ix++, sfi++) {
+ if (unpack32((char *)&sfi->read) == 1) {
+ memcpy(sfi, &sf, sizeof(struct sf_imsg));
+ pack32((char *)&sfi->read, 0);
+ break;
+ }
+ }
+
+ if (ix == SHAREDMEMSIZE) {
+ dolog(LOG_INFO, "delphinusdnsd udp: can't find an open slot in sharedmemsize\n");
+ goto udpout;
+ }
+
+ cfg->shptr[0] = ' ';
+
imsg_compose(udp_ibuf, IMSG_FORWARD_UDP,
- 0, 0, -1, sforward, sizeof(struct sforward));
+ 0, 0, -1, &ix, sizeof(int));
msgbuf_write(&udp_ibuf->w);
goto udpout;
@@ -2587,6 +2674,7 @@ tcploop(struct cfg *cfg, struct imsgbuf *ibuf, struct
struct rbtree *rbt0 = NULL, *rbt1 = NULL;
struct rrset *csd;
struct rr *rr_csd;
+ struct sf_imsg sf, *sfi = NULL;
struct sreply sreply;
struct reply_logic *rl = NULL;
@@ -2600,6 +2688,7 @@ tcploop(struct cfg *cfg, struct imsgbuf *ibuf, struct
u_int32_t imsg_type;
struct sforward *sforward;
+ int ix;
sforward = (struct sforward *)calloc(1, sizeof(struct sforward));
@@ -3171,8 +3260,35 @@ forwardtcp:
} else
sforward->havemac = 0;
+ sforward->gotit = time(NULL);
+ memcpy(&sf.sf, sforward, sizeof(struct sforward));
+
+ /* wait for lock */
+ while (cfg->shptr[0] == '*') {
+ usleep(arc4random() % 300);
+ }
+
+ cfg->shptr[0] = '*'; /* nice semaphore eh? */
+
+ for (sfi = (struct sf_imsg *)&cfg->shptr[16], ix = 0;
+ ix < SHAREDMEMSIZE; ix++, sfi++) {
+ if (unpack32((char *)&sfi->read) == 1) {
+ memcpy(sfi, &sf, sizeof(struct sf_imsg));
+ pack32((char *)&sfi->read, 0);
+ break;
+ }
+ }
+
+ if (ix == SHAREDMEMSIZE) {
+ dolog(LOG_INFO, "delphinusdnsd udp: can't find an open slot in sharedmemsize\n");
+ goto tcpout;
+ }
+
+ cfg->shptr[0] = ' ';
+
+
imsg_compose(ibuf, IMSG_FORWARD_TCP,
- 0, 0, so, sforward, sizeof(struct sforward));
+ 0, 0, so, &ix, sizeof(int));
msgbuf_write(&ibuf->w);
slen = 0;
blob - 6c9829c235ecb3bf983342250bb74cc0f1a5e105
blob + 52798aaecbdc764e10deb8010d093cde9ea3e441
--- forward.c
+++ forward.c
@@ -27,7 +27,7 @@
*/
/*
- * $Id: forward.c,v 1.16 2020/07/08 17:33:28 pjp Exp $
+ * $Id: forward.c,v 1.17 2020/07/10 10:42:27 pjp Exp $
*/
#include <sys/types.h>
@@ -35,6 +35,8 @@
#include <sys/queue.h>
#include <sys/uio.h>
#include <sys/select.h>
+#include <sys/mman.h>
+#include <sys/resource.h>
#include <netinet/in.h>
#include <arpa/inet.h>
@@ -48,6 +50,7 @@
#include <syslog.h>
#include <unistd.h>
+#include <fcntl.h>
#include <imsg.h>
#ifdef __linux__
@@ -124,20 +127,6 @@ struct forwardqueue {
SLIST_ENTRY(forwardqueue) entries; /* next entry */
} *fwq1, *fwq2, *fwqp;
-struct fwdpq {
- int rc;
- int istcp;
- int cache;
- int tsigcheck;
- struct tsig tsig;
- char mac[32];
- int buflen;
- char buf[1];
-};
-
-
-#define FWDPQHEADER sizeof(struct fwdpq)
-
void init_forward(void);
int insert_forward(int, struct sockaddr_storage *, uint16_t, char *);
void forwardloop(ddDB *, struct cfg *, struct imsgbuf *, struct imsgbuf *);
@@ -145,13 +134,14 @@ void forwardthis(ddDB *, struct cfg *, int, struct sfo
void sendit(struct forwardqueue *, struct sforward *);
void returnit(ddDB *, struct cfg *, struct forwardqueue *, char *, int, struct imsgbuf *);
struct tsig * check_tsig(char *, int, char *);
-void fwdparseloop(struct imsgbuf *);
+void fwdparseloop(struct imsgbuf *, struct imsgbuf *, struct cfg *);
void changeforwarder(struct forwardqueue *);
void stirforwarders(void);
extern void dolog(int, char *, ...);
extern void pack(char *, char *, int);
extern void pack16(char *, u_int16_t);
+extern void pack32(char *, u_int32_t);
extern uint16_t unpack16(char *);
extern uint32_t unpack32(char *);
extern void ddd_shutdown(void);
@@ -170,7 +160,7 @@ extern void build_reply(struct sreply *, int, char *,
extern struct rbtree * Lookup_zone(ddDB *, char *, int, int, int);
extern struct rbtree * lookup_zone(ddDB *, struct question *, int *, int *, char *, int);
extern char *convert_name(char *, int);
-extern int cacheit(u_char *, u_char *, u_char *, struct imsgbuf *, int);
+extern int cacheit(u_char *, u_char *, u_char *, struct imsgbuf *, struct imsgbuf *, char *);
extern int reply_a(struct sreply *, ddDB *);
extern int reply_aaaa(struct sreply *, ddDB *);
@@ -194,6 +184,7 @@ extern int reply_nsec3(struct sreply *, ddDB *);
extern int reply_nsec3param(struct sreply *, ddDB *);
extern struct rbtree * create_rr(ddDB *, char *, int, int, void *, uint32_t);
extern void flag_rr(struct rbtree *rbt);
+extern struct rbtree * find_rrset(ddDB *, char *, int);
/*
* XXX everything but txt and naptr, works...
@@ -305,13 +296,18 @@ forwardloop(ddDB *db, struct cfg *cfg, struct imsgbuf
{
struct timeval tv;
struct imsg imsg;
- struct imsgbuf parse_ibuf, *pibuf;
+ struct imsgbuf parse_ibuf, biparse_ibuf, *pibuf, *bpibuf;
+ struct rr_imsg *ri;
+ struct sf_imsg *sf;
char *buf;
+ char *rdata;
+ struct rbtree *rbt = NULL;
int max, sel;
int len, need;
int pi[2];
+ int bipi[2];
int i, count;
u_int packetcount = 0;
@@ -319,6 +315,11 @@ forwardloop(ddDB *db, struct cfg *cfg, struct imsgbuf
fd_set rset;
pid_t pid;
+ char *ptr;
+ time_t now, time0;
+
+ ptr = cfg->shptr;
+
dolog(LOG_INFO, "FORWARD: expired %d records from non-forwarding DB\n", expire_db(db, 1));
if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, PF_UNSPEC, &pi[0]) < 0) {
@@ -326,6 +327,11 @@ forwardloop(ddDB *db, struct cfg *cfg, struct imsgbuf
ddd_shutdown();
exit(1);
}
+ if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, PF_UNSPEC, &bipi[0]) < 0) {
+ dolog(LOG_INFO, "socketpair() failed\n");
+ ddd_shutdown();
+ exit(1);
+ }
pid = fork();
switch (pid) {
@@ -340,18 +346,23 @@ forwardloop(ddDB *db, struct cfg *cfg, struct imsgbuf
close(ibuf->fd);
close(cortex->fd);
close(pi[1]);
+ close(bipi[1]);
imsg_init(&parse_ibuf, pi[0]);
-
+ imsg_init(&biparse_ibuf, bipi[0]);
+
setproctitle("forward parse engine");
- fwdparseloop(&parse_ibuf);
+ fwdparseloop(&parse_ibuf, &biparse_ibuf, cfg);
/* NOTREACHED */
break;
default:
close(pi[0]);
+ close(bipi[0]);
imsg_init(&parse_ibuf, pi[1]);
+ imsg_init(&biparse_ibuf, bipi[1]);
pibuf = &parse_ibuf;
+ bpibuf = &biparse_ibuf;
break;
}
@@ -374,6 +385,9 @@ forwardloop(ddDB *db, struct cfg *cfg, struct imsgbuf
FD_SET(ibuf->fd, &rset);
if (ibuf->fd > max)
max = ibuf->fd;
+ FD_SET(bpibuf->fd, &rset);
+ if (bpibuf->fd > max)
+ max = bpibuf->fd;
SLIST_FOREACH(fwq1, &fwqhead, entries) {
if (fwq1->so > max)
@@ -392,17 +406,26 @@ forwardloop(ddDB *db, struct cfg *cfg, struct imsgbuf
sel = select(max + 1, &rset, NULL, NULL, &tv);
if (sel == -1) {
+ dolog(LOG_INFO, "select error\n");
continue;
}
if (sel == 0) {
if (cache) {
+ time0 = time(NULL);
count = expire_db(db, 0);
+
+ now = time(NULL);
+#if DEBUG
+ dolog(LOG_INFO, "%f seconds spent in expire_db()\n", difftime(now, time0));
+#endif
if (count)
dolog(LOG_INFO, "Forward CACHE expire_db: expired %d RR's\n", count);
}
continue;
}
+
+ time0 = time(NULL);
SLIST_FOREACH_SAFE(fwq1, &fwqhead, entries, fwqp) {
if (FD_ISSET(fwq1->so, &rset)) {
if (fwq1->istcp) {
@@ -423,13 +446,23 @@ forwardloop(ddDB *db, struct cfg *cfg, struct imsgbuf
if (len <= 0)
goto drop;
+ time0 = time(NULL);
returnit(db, cfg, fwq1, buf, len, pibuf);
+ now = time(NULL);
+#if DEBUG
+ dolog(LOG_INFO, "%f seconds spent in returnit tcp\n", difftime(now, time0));
+#endif
} else {
len = recv(fwq1->so, buf, 0xffff, 0);
if (len < 0)
goto drop;
+ time0 = time(NULL);
returnit(db, cfg, fwq1, buf, len, pibuf);
+ now = time(NULL);
+#if DEBUG
+ dolog(LOG_INFO, "%f seconds spent in returnit udp\n", difftime(now, time0));
+#endif
}
drop:
@@ -448,12 +481,25 @@ drop:
}
}
+
+ now = time(NULL);
+#if DEBUG
+ dolog(LOG_INFO, "%f seconds spent in singly linked list\n", difftime(now, time0));
+#endif
+
+
if (FD_ISSET(ibuf->fd, &rset)) {
+ time_t time0, now;
+ time0 = time(NULL);
if ((n = imsg_read(ibuf)) < 0 && errno != EAGAIN) {
dolog(LOG_ERR, "imsg read failure %s\n", strerror(errno));
continue;
}
+ now = time(NULL);
+#if DEBUG
+ dolog(LOG_INFO, "%f seconds spent in imsg_read\n", difftime(now, time0));
+#endif
if (n == 0) {
/* child died? */
dolog(LOG_INFO, "sigpipe on child? forward process exiting.\n");
@@ -461,17 +507,25 @@ drop:
}
for (;;) {
- if ((n = imsg_get(ibuf, &imsg)) < 0) {
- dolog(LOG_ERR, "imsg read error: %s\n", strerror(errno));
+ time0 = time(NULL);
+ errno = 0;
+ if ((n = imsg_get(ibuf, &imsg)) <= 0) {
+ if (n != 0)
+ dolog(LOG_ERR, "imsg read error: %s\n", strerror(errno));
break;
} else {
+ now = time(NULL);
+#if DEBUG
+ dolog(LOG_INFO, "%f seconds spent in imsg_get\n", difftime(now, time0));
+#endif
+
if (n == 0)
break;
datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
- if (datalen != sizeof(struct sforward)) {
+ if (datalen != sizeof(int)) {
imsg_free(&imsg);
- continue;
+ break;
}
switch(imsg.hdr.type) {
@@ -479,23 +533,171 @@ drop:
#if DEBUG
dolog(LOG_INFO, "received UDP message from mainloop\n");
#endif
- forwardthis(db, cfg, -1, (struct sforward *)imsg.data);
+ if (datalen != sizeof(int))
+ break;
+
+ memcpy(&i, imsg.data, sizeof(i));
+
+
+ sf = (struct sf_imsg *)&ptr[16];
+ sf = &sf[i];
+
+ rdata = malloc(sizeof(struct sforward));
+ if (rdata == NULL) {
+ dolog(LOG_ERR, " cache insertion failed\n");
+ imsg_free(&imsg);
+ break;
+ }
+
+ memcpy(rdata, &sf->sf, sizeof(struct sforward));
+ time0 = time(NULL);
+
+
+#if DEBUG
+ now = time(NULL);
+ dolog(LOG_INFO, "%f seconds lag between forward from mainloop\n", difftime(now, ((struct sforward *)rdata)->gotit));
+#endif
+
+ forwardthis(db, cfg, -1, (struct sforward *)rdata);
+ now = time(NULL);
+#if DEBUG
+ dolog(LOG_INFO, "%f seconds spent in forwardthis udp\n", difftime(now, time0));
+#endif
+ free(rdata);
+ /* aquire lock */
+ while (ptr[0] == '*')
+ usleep(arc4random() % 300);
+ ptr[0] = '*';
+
+ sf->read = 1;
+
+ ptr[0] = ' '; /* release */
+
break;
case IMSG_FORWARD_TCP:
#if DEBUG
dolog(LOG_INFO, "received TCP message and descriptor\n");
#endif
- forwardthis(db, cfg, imsg.fd, (struct sforward *)imsg.data);
+ if (datalen != sizeof(int))
+ break;
+
+ memcpy(&i, imsg.data, sizeof(i));
+
+ sf = (struct sf_imsg *)&ptr[16];
+ sf = &sf[i];
+
+ rdata = malloc(sizeof(struct sforward));
+ if (rdata == NULL) {
+ dolog(LOG_ERR, " cache insertion failed\n");
+ imsg_free(&imsg);
+ break;
+ }
+
+ memcpy(rdata, &sf->sf, sizeof(struct sforward));
+ time0 = time(NULL);
+ forwardthis(db, cfg, imsg.fd, (struct sforward *)rdata);
+ now = time(NULL);
+#if DEBUG
+ dolog(LOG_INFO, "%f seconds spent in forwardthis tcp\n", difftime(now, time0));
+#endif
+ free(rdata);
+ /* aquire lock */
+ while (ptr[0] == '*')
+ usleep(arc4random() % 300);
+ ptr[0] = '*';
+
+ sf->read = 1;
+
+ ptr[0] = ' '; /* release */
break;
}
imsg_free(&imsg);
}
+
+ continue;
} /* for (;;) */
} /* FD_ISSET... */
- }
+ if (FD_ISSET(bpibuf->fd, &rset)) {
+ time0 = time(NULL);
+ if ((n = imsg_read(bpibuf)) < 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? forward process biparse.ibuf exiting.\n");
+ exit(1);
+ }
+
+ for (;;) {
+ if ((n = imsg_get(bpibuf, &imsg)) < 0) {
+ dolog(LOG_ERR, "imsg read error 2: %s\n", strerror(errno));
+ break;
+ } else {
+ if (n == 0)
+ break;
+
+ datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
+
+ switch(imsg.hdr.type) {
+ case IMSG_RR_ATTACHED:
+ if (datalen != sizeof(int))
+ break;
+
+ memcpy(&i, imsg.data, sizeof(i));
+
+ while (cfg->shptr2[0] == '*')
+ usleep(arc4random() % 300);
+
+ cfg->shptr2[0] = '*';
+ ri = (struct rr_imsg *)&cfg->shptr2[16];
+ for (i = 0; i < SHAREDMEMSIZE; i++, ri++) {
+ if (ri->read == 0) {
+ rdata = malloc(ri->imsg.rr.buflen);
+ if (rdata == NULL) {
+ dolog(LOG_ERR, " cache insertion failed\n");
+ ri->read = 1;
+ continue;
+ }
+
+ memcpy(rdata, &ri->imsg.rr.un, ri->imsg.rr.buflen);
+
+ if ((rbt = create_rr(db, ri->imsg.rr.name,
+ ri->imsg.rr.namelen, ri->imsg.rr.rrtype,
+ (void *)rdata, ri->imsg.rr.ttl)) == NULL) {
+ dolog(LOG_ERR, "cache insertion failed 2\n");
+ free(rdata);
+ ri->read = 1;
+ continue;
+ }
+ flag_rr(rbt);
+
+ ri->read = 1;
+ } /* if ri->read == 0*/
+ } /* for */
+ cfg->shptr2[0] = ' ';
+
+ now = time(NULL);
+
+#if DEBUG
+ dolog(LOG_INFO, "%f seconds spent in shared memory\n", difftime(now, time0));
+#endif
+ break;
+
+ default:
+ break;
+ }
+ imsg_free(&imsg);
+ break;
+ } /* if */
+ } /* for (;;) */
+ } /* FD_ISSET...bpibuf */
+
+ } /* for (;;) */
+
/* NOTREACHED */
}
@@ -595,13 +797,17 @@ forwardthis(ddDB *db, struct cfg *cfg, int so, struct
if ((count = expire_rr(db, sforward->buf, sforward->buflen,
ntohs(sforward->type), now)) != 0) {
dolog(LOG_INFO, "Forward CACHE expired %d records\n", count);
- goto newqueue;
+ rbt = find_rrset(db, sforward->buf, sforward->buflen);
+ if (rbt == NULL) {
+ dolog(LOG_INFO, "no such record in our cache, skip\n");
+ goto newqueue;
+ }
}
/* sforward->type is in netbyte order */
if (Lookup_zone(db, sforward->buf, sforward->buflen,
ntohs(sforward->type), 0) != NULL) {
/* we have a cache */
-#if DEBUG
+#if 0
dolog(LOG_INFO, "replying %s type %d out of the cache\n", convert_name(sforward->buf, sforward->buflen), ntohs(sforward->type));
#endif
/* build a pseudo question packet */
@@ -676,18 +882,20 @@ forwardthis(ddDB *db, struct cfg *cfg, int so, struct
* at this point the rl->reply will fail.. expire it
* and fill it with dnssec data if available
*/
- if (q->dnssecok == 1) {
- expire_rr(db, q->hdr->name, q->hdr->namelen,
+ expire_rr(db, q->hdr->name, q->hdr->namelen,
ntohs(q->hdr->qtype), highexpire);
- free_question(q);
- goto newqueue;
- }
- dolog(LOG_INFO, "reply failed\n");
+ free_question(q);
+ goto newqueue;
}
break;
} /* if rl->rrtype == */
}
+ if (rl->rrtype == 0) {
+ dolog(LOG_INFO, "we did not have any right answer in our cache, skip to newqueue\n");
+ goto newqueue;
+ }
+
free_question(q);
/* at this point we return everythign is done */
return;
@@ -850,8 +1058,8 @@ sendit(struct forwardqueue *fwq, struct sforward *sfor
}
q->edns0len = sforward->edns0len;
- if (q->edns0len > (MAX_IMSGSIZE - FWDPQHEADER))
- q->edns0len = (MAX_IMSGSIZE - FWDPQHEADER);
+ if (q->edns0len > 16384)
+ q->edns0len = 16384;
if (fwq->istcp == 1) {
p = &buf[2];
@@ -928,26 +1136,26 @@ sendit(struct forwardqueue *fwq, struct sforward *sfor
void
returnit(ddDB *db, struct cfg *cfg, struct forwardqueue *fwq, char *rbuf, int rlen, struct imsgbuf *ibuf)
{
- struct rbtree *rbt = NULL;
struct timeval tv;
struct dns_header *dh;
struct tsig *stsig = NULL;
struct question *q;
- struct fwdpq *fwdpq;
+ struct fwdpq *fwdpq, *fwdpq0;
struct imsg imsg;
- struct rr_imsg ri;
static char *buf = NULL;
- char *p, *rdata;
+ char *p;
int so;
- int sel;
+ int i; /* = v/r */
+ int sel, rc;
int len = 0;
int outlen;
socklen_t tolen;
fd_set rset;
ssize_t n, datalen;
+ time_t time0, now;
if (buf == NULL) {
buf = calloc(1, 0xffff + 2);
@@ -986,7 +1194,7 @@ returnit(ddDB *db, struct cfg *cfg, struct forwardqueu
}
/* send it on to our sandbox */
- fwdpq = (struct fwdpq *)calloc(1, rlen + FWDPQHEADER);
+ fwdpq = (struct fwdpq *)calloc(1, sizeof(struct fwdpq));
if (fwdpq == NULL) {
dolog(LOG_INFO, "calloc: %s\n", strerror(errno));
return;
@@ -997,12 +1205,12 @@ returnit(ddDB *db, struct cfg *cfg, struct forwardqueu
if (fwq->istcp) {
fwdpq->buflen = rlen;
} else {
- if (rlen > (16384 - FWDPQHEADER)) { /* leave some space for struct */
+ if (rlen > sizeof(fwdpq->buf)) {
dolog(LOG_INFO, "can't send packet to parser, too big\n");
return;
}
- memcpy(&fwdpq->buf, p, rlen);
+ memcpy(&fwdpq->buf[0], p, rlen);
fwdpq->buflen = rlen;
}
@@ -1019,13 +1227,30 @@ returnit(ddDB *db, struct cfg *cfg, struct forwardqueu
fwdpq->istcp = 1;
else
fwdpq->istcp = 0;
+
+ /* lock */
+ while (cfg->shptr3[0] == '*')
+ usleep(arc4random() % 300);
- if (imsg_compose(ibuf, IMSG_PARSE_MESSAGE, 0, 0, (fwq->istcp == 1) ? fwq->so : -1, fwdpq, fwq->istcp ? FWDPQHEADER : rlen + FWDPQHEADER) < 0) {
+ cfg->shptr3[0] = '*';
+
+ fwdpq0 = (struct fwdpq *)&cfg->shptr3[16];
+ for (i = 0; i < SHAREDMEMSIZE3; i++, fwdpq0++) {
+ if (unpack32((char *)&fwdpq0->read) == 1) {
+ memcpy(fwdpq0, fwdpq, sizeof(struct fwdpq));
+ pack32((char *)&fwdpq0->read, 0);
+ break;
+ }
+ }
+
+ if (imsg_compose(ibuf, IMSG_PARSE_MESSAGE, 0, 0, (fwq->istcp == 1) ? fwq->so : -1, &i, sizeof(i)) < 0) {
dolog(LOG_INFO, "imsg_compose: %s\n", strerror(errno));
free(fwdpq);
return;
}
msgbuf_write(&ibuf->w);
+
+ cfg->shptr3[0] = ' ';
for (;;) {
FD_ZERO(&rset);
@@ -1042,14 +1267,19 @@ returnit(ddDB *db, struct cfg *cfg, struct forwardqueu
}
if (sel == 0) {
dolog(LOG_ERR, "returnit internal error around select (timeout), drop\n");
- continue;
+ return;
}
if (FD_ISSET(ibuf->fd, &rset)) {
- if (((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)) {
+ time0 = time(NULL);
+ if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) {
dolog(LOG_ERR, "returnit internal error around imsg_read, drop\n");
continue;
}
+ now = time(NULL);
+#if DEBUG
+ dolog(LOG_INFO, "%f seconds spent in imsg_read 2\n", difftime(now, time0));
+#endif
if (n == 0) {
dolog(LOG_INFO, "imsg peer died? shutting down\n");
ddd_shutdown();
@@ -1063,10 +1293,15 @@ returnit(ddDB *db, struct cfg *cfg, struct forwardqueu
for (;;) {
+ time0 = time(NULL);
if ((n = imsg_get(ibuf, &imsg)) == -1) {
dolog(LOG_ERR, "returnit internal error around imsg_get, drop\n");
break;
}
+ now = time(NULL);
+#if DEBUG
+ dolog(LOG_INFO, "%f seconds spent in imsg_get\n", difftime(now, time0));
+#endif
if (n == 0) {
#if DEBUG
@@ -1077,51 +1312,55 @@ returnit(ddDB *db, struct cfg *cfg, struct forwardqueu
datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
switch (imsg.hdr.type) {
- case IMSG_PARSEREPLY_MESSAGE:
- memcpy(fwdpq, imsg.data, datalen);
+ case IMSG_PARSEERROR_MESSAGE:
+ if (datalen != sizeof(int)) {
+ dolog(LOG_ERR, "bad parserepy message, drop\n", fwdpq->rc);
+ imsg_free(&imsg);
+ free(fwdpq);
+ return;
+ }
- if (fwq->istcp == 1)
- fwq->so = imsg.fd;
+ memcpy(&rc, imsg.data, datalen);
- if (fwdpq->rc != PARSE_RETURN_ACK) {
- dolog(LOG_ERR, "returnit parser did not ACK this (%d), drop\n", fwdpq->rc);
- imsg_free(&imsg);
- break;
- }
+ if (rc != PARSE_RETURN_ACK) {
+ dolog(LOG_ERR, "returnit parser did not ACK this (%d), drop\n", rc);
+ imsg_free(&imsg);
+ free(fwdpq);
+ return;
+ }
+ imsg_free(&imsg);
+ break;
+ case IMSG_PARSEREPLY_MESSAGE:
- imsg_free(&imsg);
- goto endimsg;
- break;
- case IMSG_RR_ATTACHED:
- if (datalen > sizeof(ri)) {
- dolog(LOG_ERR, "returnit RR reply was bogus\n");
- imsg_free(&imsg);
- break;
- }
+ if (datalen != sizeof(int)) {
+ dolog(LOG_ERR, "bad parsereply message, drop\n");
+ imsg_free(&imsg);
+ free(fwdpq);
+ return;
+ }
- memcpy((void *)&ri, imsg.data, datalen);
+ memcpy(&i, imsg.data, sizeof(int));
- rdata = malloc(ri.unlen);
- if (rdata == NULL) {
- dolog(LOG_ERR, "returnit cache insertion failed\n");
- imsg_free(&imsg);
- break;
- }
+ /* lock */
+ while (cfg->shptr3[0] == '*')
+ usleep(arc4random() % 300);
- memcpy(rdata, &ri.un, ri.unlen);
+ cfg->shptr3[0] = '*';
- if ((rbt = create_rr(db, ri.name, ri.namelen,
- ri.rrtype, (void *)rdata, ri.ttl)) == NULL) {
- dolog(LOG_ERR, "returnit cache insertion failed 2\n");
- imsg_free(&imsg);
- free(rdata);
- break;
- }
+ fwdpq0 = (struct fwdpq *)&cfg->shptr3[16];
+ fwdpq0 = &fwdpq0[i];
- flag_rr(rbt);
+ memcpy(fwdpq, fwdpq0, sizeof(struct fwdpq));
+ pack32((char *)&fwdpq0->read, 1);
+ cfg->shptr3[0] = ' ';
+
+ if (fwq->istcp == 1)
+ fwq->so = imsg.fd;
+
imsg_free(&imsg);
+ goto endimsg;
break;
default:
dolog(LOG_INFO, "received unexpected IMSG\n");
@@ -1129,9 +1368,9 @@ returnit(ddDB *db, struct cfg *cfg, struct forwardqueu
break;
}
+ /* back to select */
break;
} /* for (;;) */
- /* back to select */
} /* for (;;) */
endimsg:
@@ -1631,14 +1870,14 @@ check_tsig(char *buf, int len, char *mac)
}
void
-fwdparseloop(struct imsgbuf *ibuf)
+fwdparseloop(struct imsgbuf *ibuf, struct imsgbuf *bibuf, struct cfg *cfg)
{
int fd = ibuf->fd;
int sel, istcp = 0;
- int rlen, tmp;
+ int rlen, tmp, rc, i;
struct tsig *stsig = NULL;
- struct fwdpq *fwdpq;
+ struct fwdpq *fwdpq, *fwdpq0;
struct imsg imsg;
struct dns_header *dh;
@@ -1646,7 +1885,14 @@ fwdparseloop(struct imsgbuf *ibuf)
u_char *end, *estart;
fd_set rset;
ssize_t n, datalen;
+ int flags;
+ fcntl(bibuf->fd, F_GETFL, &flags, sizeof(flags));
+ flags |= O_NONBLOCK;
+ if (fcntl(bibuf->fd, F_SETFL, &flags, sizeof(flags)) < 0) {
+ dolog(LOG_INFO, "fcntl: %s\n", strerror(errno));
+ }
+
#if __OpenBSD__
if (pledge("stdio sendfd recvfd", NULL) < 0) {
perror("pledge");
@@ -1656,7 +1902,7 @@ fwdparseloop(struct imsgbuf *ibuf)
#endif
- fwdpq = (struct fwdpq *)calloc(1, 0xffff + FWDPQHEADER);
+ fwdpq = (struct fwdpq *)calloc(1, sizeof(struct fwdpq));
if (fwdpq == NULL) {
dolog(LOG_INFO, "calloc: %s\n", strerror(errno));
ddd_shutdown();
@@ -1690,69 +1936,83 @@ fwdparseloop(struct imsgbuf *ibuf)
}
datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
-
- if (imsg.fd != -1) {
- istcp = 1;
- }
switch (imsg.hdr.type) {
case IMSG_PARSE_MESSAGE:
-
/* XXX magic numbers */
- if (datalen > MAX_IMSGSIZE) {
- fwdpq->rc = PARSE_RETURN_NAK;
- imsg_compose(ibuf, IMSG_PARSEREPLY_MESSAGE, 0, 0, imsg.fd, fwdpq, sizeof(struct fwdpq));
+ if (datalen != sizeof(int)) {
+ rc = PARSE_RETURN_NAK;
+ imsg_compose(ibuf, IMSG_PARSEERROR_MESSAGE, 0, 0, imsg.fd, &rc, sizeof(int));
msgbuf_write(&ibuf->w);
break;
}
+
+ memcpy(&i, imsg.data, datalen);
- memcpy(fwdpq, imsg.data, datalen);
+ /* lock */
+ while (cfg->shptr3[0] == '*')
+ usleep(arc4random() % 300);
+ cfg->shptr3[0] = '*';
+ fwdpq0 = (struct fwdpq *)&cfg->shptr3[16];
+ fwdpq0 = &fwdpq0[i];
+
+ memcpy(fwdpq, fwdpq0, sizeof(struct fwdpq));
+ pack32((char *)&fwdpq0->read, 1);
+
+ cfg->shptr3[0] = ' '; /* unlock */
+
istcp = fwdpq->istcp;
if (istcp) {
packet = malloc(fwdpq->buflen);
if (packet == NULL) {
dolog(LOG_INFO, "malloc %s\n", strerror(errno));
- fwdpq->rc = PARSE_RETURN_NAK;
+ rc = PARSE_RETURN_NAK;
/* send the descriptor back to them */
- imsg_compose(ibuf, IMSG_PARSEREPLY_MESSAGE, 0, 0, imsg.fd, fwdpq, sizeof(struct fwdpq));
+ imsg_compose(ibuf, IMSG_PARSEERROR_MESSAGE, 0, 0, imsg.fd, &rc, sizeof(int));
msgbuf_write(&ibuf->w);
break;
}
- if (recv(imsg.fd, packet, fwdpq->buflen, 0) < 0) {
+ if (recv(imsg.fd, packet, fwdpq->buflen, MSG_WAITALL) < 0) {
dolog(LOG_INFO, "recv in forward sandbox: %s\n", strerror(errno));
- fwdpq->rc = PARSE_RETURN_NAK;
+ rc = PARSE_RETURN_NAK;
/* send the descriptor back to them */
- imsg_compose(ibuf, IMSG_PARSEREPLY_MESSAGE, 0, 0, imsg.fd, fwdpq, sizeof(struct fwdpq));
+ imsg_compose(ibuf, IMSG_PARSEERROR_MESSAGE, 0, 0, imsg.fd, &rc, sizeof(int));
msgbuf_write(&ibuf->w);
+ free(packet);
break;
}
+ dolog(LOG_INFO, "received %d bytes from descriptor %d\n", fwdpq->buflen, imsg.fd);
} else
- packet = (u_char *)&fwdpq->buf;
+ packet = &fwdpq->buf[0];
if (istcp) {
tmp = fwdpq->buflen;
} else {
- tmp = datalen - FWDPQHEADER;
+ tmp = fwdpq->buflen;
}
if (tmp < sizeof(struct dns_header)) {
/* SEND NAK */
- fwdpq->rc = PARSE_RETURN_NAK;
- imsg_compose(ibuf, IMSG_PARSEREPLY_MESSAGE, 0, 0, (istcp) ? imsg.fd : -1, fwdpq, sizeof(struct fwdpq));
+ rc = PARSE_RETURN_NAK;
+ imsg_compose(ibuf, IMSG_PARSEERROR_MESSAGE, 0, 0, (istcp) ? imsg.fd : -1, &rc, sizeof(int));
msgbuf_write(&ibuf->w);
+ if (istcp)
+ free(packet);
break;
}
/* pjp */
dh = (struct dns_header *)packet;
if (! (ntohs(dh->query) & DNS_REPLY)) {
- fwdpq->rc = PARSE_RETURN_NOTAREPLY;
- imsg_compose(ibuf, IMSG_PARSEREPLY_MESSAGE, 0, 0, (istcp) ? imsg.fd : -1, fwdpq, sizeof(struct fwdpq));
+ rc = PARSE_RETURN_NOTAREPLY;
+ imsg_compose(ibuf, IMSG_PARSEERROR_MESSAGE, 0, 0, (istcp) ? imsg.fd : -1, &rc, sizeof(int));
msgbuf_write(&ibuf->w);
+ if (istcp)
+ free(packet);
break;
}
@@ -1765,9 +2025,11 @@ fwdparseloop(struct imsgbuf *ibuf)
* all valid answers have a
* question, so this is good
*/
- fwdpq->rc = PARSE_RETURN_NOQUESTION;
- imsg_compose(ibuf, IMSG_PARSEREPLY_MESSAGE, 0, 0, (istcp) ? imsg.fd : -1, fwdpq, sizeof(struct fwdpq));
+ rc = PARSE_RETURN_NOQUESTION;
+ imsg_compose(ibuf, IMSG_PARSEERROR_MESSAGE, 0, 0, (istcp) ? imsg.fd : -1, &rc, sizeof(int));
msgbuf_write(&ibuf->w);
+ if (istcp)
+ free(packet);
break;
}
/* insert parsing logic here */
@@ -1778,12 +2040,11 @@ fwdparseloop(struct imsgbuf *ibuf)
rlen = tmp;
end = &packet[rlen];
- if (cacheit(packet, estart, end, ibuf, imsg.fd) < 0) {
- goto skipcache;
+ if (cacheit(packet, estart, end, ibuf, bibuf, cfg->shptr2) < 0) {
+ dolog(LOG_INFO, "cacheit failed\n");
}
}
-skipcache:
/* check to see if we tsig */
if (fwdpq->tsigcheck) {
@@ -1791,11 +2052,13 @@ skipcache:
stsig = check_tsig((char *)packet, rlen, fwdpq->mac);
if (stsig == NULL) {
dolog(LOG_INFO, "FORWARD parser, malformed reply packet\n");
- fwdpq->rc = PARSE_RETURN_MALFORMED;
+ rc = PARSE_RETURN_MALFORMED;
- imsg_compose(ibuf, IMSG_PARSEREPLY_MESSAGE, 0, 0, (istcp) ? imsg.fd : -1, fwdpq, sizeof(struct fwdpq));
+ imsg_compose(ibuf, IMSG_PARSEERROR_MESSAGE, 0, 0, (istcp) ? imsg.fd : -1, &rc, sizeof(int));
msgbuf_write(&ibuf->w);
+ if (istcp)
+ free(packet);
break;
}
@@ -1803,14 +2066,32 @@ skipcache:
}
fwdpq->rc = PARSE_RETURN_ACK;
- imsg_compose(ibuf, IMSG_PARSEREPLY_MESSAGE, 0, 0, (istcp) ? imsg.fd : -1, fwdpq, sizeof(struct fwdpq));
+
+ cfg->shptr3[0] = '*';
+
+ fwdpq0 = (struct fwdpq *)&cfg->shptr3[16];
+ for (i = 0; i < SHAREDMEMSIZE3; i++, fwdpq0++) {
+ if (unpack32((char *)&fwdpq0->read) == 1) {
+ memcpy(fwdpq0, fwdpq, sizeof(struct fwdpq));
+ pack32((char *)&fwdpq0->read, 0);
+ break;
+ }
+ }
+
+ imsg_compose(ibuf, IMSG_PARSEREPLY_MESSAGE, 0, 0, (istcp) ? imsg.fd : -1, &i, sizeof(int));
msgbuf_write(&ibuf->w);
+ cfg->shptr3[0] = ' ';
+
free(stsig);
+
+ if (istcp)
+ free(packet);
break;
} /* switch */
imsg_free(&imsg);
+ break;
} /* for(;;) */
} /* FD_ISSET */
} /* for(;;) */
repomaster@centroid.eu