Commit Diff
Diff:
84ea0365efbdd21b6c4cdad89103cbb82ffddb3d
8c7bdc7cd8a895f42a77ec91cf88f60f8ae10db1
Commit:
8c7bdc7cd8a895f42a77ec91cf88f60f8ae10db1
Tree:
deb208cbe001559f75f84618182318cf649309d0
Author:
pbug <pbug@delphinusdns.org>
Committer:
pbug <pbug@delphinusdns.org>
Date:
Sat Mar 7 10:19:31 2009 UTC
Message:
* add a ERR_NOERROR variable for domains that have an SOA but lack a specific resource record. Before it would reply with NXDOMAIN and the (bind?)foreign server would negative cache even AAAA records if A record didn't have a database entry. This should fix this: http://sourceforge.net/forum/forum.php?thread_id=3075205&forum_id=514229
blob - f0ec45be5d13ae431c46d5d66ffe317600c69448
blob + 76e264beafc23654f4b7cb00fb4ccd78246967f0
--- db.h
+++ db.h
@@ -32,6 +32,7 @@
#define ERR_DROP 0x1
#define ERR_NXDOMAIN 0x2
+#define ERR_NOERROR 0x4
/* db stuff */
blob - ff3c245a8a01751ebfe4a07e4a1c4081e98897ab
blob + ef64695a236d00f7938a94fab3aa1ccd2fc5a49a
--- main.c
+++ main.c
@@ -40,6 +40,7 @@ int get_soa(DB *, struct question *, struct domain *);
extern void reply_notimpl(struct sreply *);
extern void reply_nxdomain(struct sreply *);
+extern void reply_noerror(struct sreply *);
extern void reply_fmterror(struct sreply *);
extern void reply_a(struct sreply *);
extern void reply_aaaa(struct sreply *);
@@ -65,7 +66,7 @@ extern char *__progname;
static int Wflag = 0;
static int lflag = 0;
-static char rcsid[] = "$Id: main.c,v 1.17 2009/03/01 10:10:21 pbug Exp $";
+static char rcsid[] = "$Id: main.c,v 1.18 2009/03/07 10:19:31 pbug Exp $";
/*
* MAIN - set up arguments, set up database, set up sockets, call mainloop
@@ -517,6 +518,26 @@ mainloop(int *udp, int *tcp, int sockcount, char **ide
case ERR_NXDOMAIN:
goto nxdomain;
+ case ERR_NOERROR:
+ /*
+ * this is hackish not sure if this should be here
+ */
+
+ snprintf(replystring, DNS_MAXNAME, "NOERROR");
+
+ /*
+ * lookup an authoritative soa
+ */
+
+ memset(&sd0, 0, sizeof(sd0));
+ (void)get_soa(db, question, &sd0);
+
+ BUILD_REPLY(sreply, so, buf, len, question, from, \
+ fromlen, &sd0, NULL);
+
+ reply_noerror(&sreply);
+ goto out;
+
}
}
@@ -1168,7 +1189,7 @@ lookup_zone(DB *db, struct question *question, struct
break;
}
- *lzerrno = ERR_NXDOMAIN;
+ *lzerrno = ERR_NOERROR;
return -1;
case DNS_TYPE_AAAA:
if ((sd->flags & DOMAIN_HAVE_AAAA) ==
@@ -1180,7 +1201,7 @@ lookup_zone(DB *db, struct question *question, struct
break;
}
- *lzerrno = ERR_NXDOMAIN;
+ *lzerrno = ERR_NOERROR;
return -1;
case DNS_TYPE_MX:
if ((sd->flags & DOMAIN_HAVE_MX) ==
@@ -1192,7 +1213,7 @@ lookup_zone(DB *db, struct question *question, struct
break;
}
- *lzerrno = ERR_NXDOMAIN;
+ *lzerrno = ERR_NOERROR;
return -1;
case DNS_TYPE_PTR:
if ((sd->flags & DOMAIN_HAVE_PTR) ==
@@ -1204,7 +1225,7 @@ lookup_zone(DB *db, struct question *question, struct
break;
}
- *lzerrno = ERR_NXDOMAIN;
+ *lzerrno = ERR_NOERROR;
return -1;
case DNS_TYPE_SOA:
@@ -1219,7 +1240,7 @@ lookup_zone(DB *db, struct question *question, struct
case DNS_TYPE_CNAME:
if ((sd->flags & DOMAIN_HAVE_CNAME) != DOMAIN_HAVE_CNAME) {
- *lzerrno = ERR_NXDOMAIN;
+ *lzerrno = ERR_NOERROR;
return -1;
}
@@ -1227,7 +1248,7 @@ lookup_zone(DB *db, struct question *question, struct
break;
case DNS_TYPE_NS:
if ((sd->flags & DOMAIN_HAVE_NS) != DOMAIN_HAVE_NS) {
- *lzerrno = ERR_NXDOMAIN;
+ *lzerrno = ERR_NOERROR;
return -1;
}
returnval = DNS_TYPE_NS;
@@ -1278,7 +1299,7 @@ lookup_zone(DB *db, struct question *question, struct
break;
}
- *lzerrno = ERR_NXDOMAIN;
+ *lzerrno = ERR_NOERROR;
return -1;
case DNS_TYPE_AAAA:
if ((sd->flags & DOMAIN_HAVE_AAAA) ==
@@ -1290,7 +1311,7 @@ lookup_zone(DB *db, struct question *question, struct
break;
}
- *lzerrno = ERR_NXDOMAIN;
+ *lzerrno = ERR_NOERROR;
return -1;
case DNS_TYPE_MX:
if ((sd->flags & DOMAIN_HAVE_MX) ==
@@ -1302,7 +1323,7 @@ lookup_zone(DB *db, struct question *question, struct
break;
}
- *lzerrno = ERR_NXDOMAIN;
+ *lzerrno = ERR_NOERROR;
return -1;
case DNS_TYPE_PTR:
if ((sd->flags & DOMAIN_HAVE_PTR) ==
@@ -1314,7 +1335,7 @@ lookup_zone(DB *db, struct question *question, struct
break;
}
- *lzerrno = ERR_NXDOMAIN;
+ *lzerrno = ERR_NOERROR;
return -1;
case DNS_TYPE_SOA:
@@ -1328,7 +1349,7 @@ lookup_zone(DB *db, struct question *question, struct
case DNS_TYPE_NS:
if ((sd->flags & DOMAIN_HAVE_NS) != DOMAIN_HAVE_NS) {
- *lzerrno = ERR_NXDOMAIN;
+ *lzerrno = ERR_NOERROR;
return -1;
}
returnval = DNS_TYPE_NS;
@@ -1336,7 +1357,7 @@ lookup_zone(DB *db, struct question *question, struct
case DNS_TYPE_CNAME:
if ((sd->flags & DOMAIN_HAVE_CNAME) != DOMAIN_HAVE_CNAME) {
- *lzerrno = ERR_NXDOMAIN;
+ *lzerrno = ERR_NOERROR;
return -1;
}
returnval = DNS_TYPE_CNAME;
blob - 964434beff1c084c5a8accd7b7a5d715bb9f45fc
blob + caf38b7c5d14a413d15859629ea2399f60c52e41
--- reply.c
+++ reply.c
@@ -35,6 +35,7 @@ void reply_mx(struct sreply *);
void reply_ns(struct sreply *);
void reply_notimpl(struct sreply *);
void reply_nxdomain(struct sreply *);
+void reply_noerror(struct sreply *);
void reply_soa(struct sreply *);
void reply_ptr(struct sreply *);
void reply_cname(struct sreply *);
@@ -46,7 +47,7 @@ extern int additional_aaaa(char *, int, struct domain
extern int additional_mx(char *, int, struct domain *, char *, int, int, int *);
extern int additional_ptr(char *, int, struct domain *, char *, int, int, int *);
-static char rcsid[] = "$Id: reply.c,v 1.6 2009/02/17 10:55:46 pbug Exp $";
+static char rcsid[] = "$Id: reply.c,v 1.7 2009/03/07 10:19:31 pbug Exp $";
/*
* REPLY_A() - replies a DNS question (*q) on socket (so)
@@ -1164,6 +1165,217 @@ reply_fmterror(struct sreply *sreply)
HTONS(odh->query);
if (sendto(so, reply, sizeof(struct dns_header), 0, sa, salen) < 0) {
+ syslog(LOG_INFO, "sendto: %m");
+ }
+
+ return;
+}
+
+/*
+ * REPLY_NOERROR() - replies a DNS question (*q) on socket (so)
+ * based on reply_nxdomain
+ *
+ */
+
+void
+reply_noerror(struct sreply *sreply)
+{
+ char reply[512];
+ struct dns_header *odh;
+ int outlen;
+ char *p;
+ u_int32_t *soa_val;
+ int i, tmplen;
+ int labellen;
+ char *label, *plabel;
+
+ 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 soa {
+ char *nsserver;
+ char *responsible_person;
+ u_int32_t serial;
+ u_int32_t refresh;
+ u_int32_t retry;
+ u_int32_t expire;
+ u_int32_t minttl;
+ };
+
+
+ struct answer *answer;
+
+ int so = sreply->so;
+ char *buf = sreply->buf;
+ int len = sreply->len;
+ struct question *q = sreply->q;
+ struct sockaddr *sa = sreply->sa;
+ int salen = sreply->salen;
+ struct domain *sd = sreply->sd1;
+
+ odh = (struct dns_header *)&reply[0];
+ outlen = sizeof(struct dns_header);
+
+ if (len > sizeof(reply)) {
+ return;
+
+ }
+
+ /*
+ * no SOA, use the old code
+ */
+
+ if ((sd->flags & DOMAIN_HAVE_SOA) != DOMAIN_HAVE_SOA) {
+
+ memcpy(&reply, buf, len);
+ memset((char *)&odh->query, 0, sizeof(u_int16_t));
+
+ SET_DNS_REPLY(odh);
+#if 0
+ SET_DNS_RCODE_NAMEERR(odh);
+#endif
+
+ HTONS(odh->query);
+
+ if (sendto(so, reply, len, 0, sa, salen) < 0) {
+ syslog(LOG_INFO, "sendto: %m");
+ }
+
+ return;
+ }
+
+ /* 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);
+#if 0
+ SET_DNS_RCODE_NAMEERR(odh);
+#endif
+
+ NTOHS(odh->query);
+
+ odh->question = ntohs(1);
+ odh->answer = 0;
+ odh->nsrr = ntohs(1);
+ odh->additional = 0;
+
+ answer = (struct answer *)(&reply[0] + sizeof(struct dns_header) +
+ q->hdr->namelen + 4);
+
+ answer->name[0] = 0xc0;
+ answer->name[1] = 0x0c;
+ answer->type = htons(DNS_TYPE_SOA);
+ answer->class = q->hdr->qclass;
+ answer->ttl = htonl(sd->ttl);
+
+ outlen += 12; /* up to rdata length */
+
+ p = (char *)&answer->rdata;
+
+#if 0
+ label = dns_label((char *)mysoa.nsserver, &labellen);
+ if (label == NULL)
+ return;
+#endif
+
+ label = &sd->soa.nsserver[0];
+ labellen = sd->soa.nsserver_len;
+
+ plabel = label;
+
+ /* copy label to reply */
+ for (i = outlen; i < sizeof(reply); i++) {
+ if (i - outlen == labellen)
+ break;
+
+ reply[i] = *plabel++;
+ }
+
+ if (i >= sizeof(reply)) {
+ return ;
+ }
+
+ outlen = i;
+
+ /* compress the label if possible */
+ if ((tmplen = compress_label(reply, outlen, labellen)) > 0) {
+ outlen = tmplen;
+ }
+
+ label = &sd->soa.responsible_person[0];
+ labellen = sd->soa.rp_len;
+ plabel = label;
+
+ for (i = outlen; i < sizeof(reply); i++) {
+ if (i - outlen == labellen)
+ break;
+
+ reply[i] = *plabel++;
+ }
+
+ if (i >= sizeof(reply)) {
+ return ;
+ }
+
+ outlen = i;
+
+ /* 2 compress the label if possible */
+
+ if ((tmplen = compress_label(reply, outlen, labellen)) > 0) {
+ outlen = tmplen;
+ }
+
+
+ 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);
+
+ 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);
+
+ 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);
+
+ 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);
+
+ 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);
+
+ answer->rdlength = htons(&reply[outlen] - &answer->rdata);
+
+ if (sendto(so, reply, outlen, 0, sa, salen) < 0) {
syslog(LOG_INFO, "sendto: %m");
}
repomaster@centroid.eu