Commit Diff
Diff:
7202f80f7c0dd3d8f3b5e4f79afe3c78953c902b
d6a24f1e33bdffd82a3ab72c5d190dfd881761cb
Commit:
d6a24f1e33bdffd82a3ab72c5d190dfd881761cb
Tree:
0a3390d47dca04d2919ab138f791cad69b10aea9
Author:
pbug <pbug@delphinusdns.org>
Committer:
pbug <pbug@delphinusdns.org>
Date:
Thu Jul 24 17:42:08 2008 UTC
Message:
* Make SOA with NXDOMAIN work * some cleaning of reply_soa (remove #if 0's) * some more comments in reply_a for better understanding * update TODO with this thing that was wanted.
blob - 467587e7381d9faadb5de5b96bb0aeff7622523b
blob + c635a36ddd9914e52874bac0ec8886923e4ba3f7
--- TODO
+++ TODO
@@ -1,7 +1,7 @@
Here are a few things left to do (until beta):
* CNAME needs to include answers to the RR type originally requested. [done]
-* NXDOMAIN should include an AUTHORITY SOA.
+* NXDOMAIN should include an AUTHORITY SOA. [done]
* AAAA and A RR's when there is more than 1 need to be rotated every answer in
order to make use of load sharing.
* TXT RR support
blob - 909e57d16afbcfa4263aaebf4e769bcc8ff36557
blob + ac32ea12f0205a3bae0aa62fa7af8416811cabf0
--- main.c
+++ main.c
@@ -36,6 +36,7 @@ struct question * build_fake_question(char *, int, u_i
void mainloop(int *, int *, int, char **, DB *);
int free_question(struct question *);
int lookup_zone(DB *, struct question *, struct domain *, int *, char *);
+int get_soa(DB *, struct question *, struct domain *);
extern void reply_notimpl(struct sreply *);
extern void reply_nxdomain(struct sreply *);
@@ -63,7 +64,7 @@ int memcasecmp(char *, char *, int);
extern char *__progname;
static int Wflag = 0;
-static char rcsid[] = "$Id: main.c,v 1.8 2008/07/10 18:27:19 pbug Exp $";
+static char rcsid[] = "$Id: main.c,v 1.9 2008/07/24 17:42:08 pbug Exp $";
/*
* MAIN - set up arguments, set up database, set up sockets, call mainloop
@@ -507,7 +508,15 @@ mainloop(int *udp, int *tcp, int sockcount, char **ide
*/
nxdomain:
snprintf(replystring, DNS_MAXNAME, "NXDOMAIN");
- BUILD_REPLY(sreply, so, buf, len, question, from, fromlen, NULL, NULL);
+
+ /*
+ * 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_nxdomain(&sreply);
goto out;
case DNS_TYPE_CNAME:
@@ -1349,4 +1358,64 @@ build_fake_question(char *name, int namelen, u_int16_t
q->hdr->qclass = htons(DNS_CLASS_IN);
return (q);
+}
+
+/*
+ * GET_SOA - get authoritative soa for a particular domain
+ */
+
+int
+get_soa(DB *db, struct question *question, struct domain *sd)
+{
+ int plen;
+ int ret = 0;
+
+ DBT key, data;
+
+ char *p;
+
+ p = question->hdr->name;
+ plen = question->hdr->namelen;
+
+ do {
+
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+
+ key.data = (char *)p;
+ key.size = plen;
+
+ data.data = NULL;
+ data.size = 0;
+
+#if DB_VERSION_MAJOR > 3
+ ret = db->get(db, NULL, &key, &data, 0);
+#else
+ ret = db->get(db, &key, &data, 0);
+#endif
+
+ if (ret != 0) {
+ plen -= (*p + 1);
+ p = (p + (*p + 1));
+ continue;
+ }
+
+ if (data.size != sizeof(struct domain)) {
+ syslog(LOG_INFO, "btree db is damaged, drop");
+ return -1;
+ }
+
+ memcpy((char *)sd, (char *)data.data, data.size);
+
+ if ((sd->flags & DOMAIN_HAVE_SOA) == DOMAIN_HAVE_SOA) {
+ /* we'll take this one */
+ return 0;
+ } else {
+ plen -= (*p + 1);
+ p = (p + (*p + 1));
+ }
+
+ } while (*p);
+
+ return -1;
}
blob - 69960d150060c20bfe777e2c78833a75340f08f8
blob + 6adde6c639912f9a95cd11d01d8bd62a3b691e4a
--- reply.c
+++ reply.c
@@ -46,7 +46,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.4 2008/07/10 18:03:07 pbug Exp $";
+static char rcsid[] = "$Id: reply.c,v 1.5 2008/07/24 17:42:08 pbug Exp $";
/*
* REPLY_A() - replies a DNS question (*q) on socket (so)
@@ -113,15 +113,20 @@ reply_a(struct sreply *sreply)
a_count = 0;
do {
- answer->name[0] = 0xc0;
- answer->name[1] = 0x0c;
- answer->type = q->hdr->qtype;
- answer->class = q->hdr->qclass;
- answer->ttl = htonl(sd->ttl);
+ /*
+ * answer->name is a pointer to the request (0xc00c)
+ */
- answer->rdlength = htons(sizeof(in_addr_t));
+ answer->name[0] = 0xc0; /* 1 byte */
+ answer->name[1] = 0x0c; /* 2 bytes */
+ answer->type = q->hdr->qtype; /* 4 bytes */
+ answer->class = q->hdr->qclass; /* 6 bytes */
+ answer->ttl = htonl(sd->ttl); /* 10 bytes */
- memcpy((char *)&answer->rdata, (char *)&sd->a[a_count++], sizeof(in_addr_t));
+ answer->rdlength = htons(sizeof(in_addr_t)); /* 12 bytes */
+
+ memcpy((char *)&answer->rdata, (char *)&sd->a[a_count++],
+ sizeof(in_addr_t)); /* 16 bytes */
outlen += 16;
/* can we afford to write another header? if no truncate */
@@ -794,28 +799,16 @@ reply_soa(struct sreply *sreply)
}
if (i >= sizeof(reply)) {
-#if 0
- free(label);
-#endif
return ;
}
outlen = i;
-#if 0
- free(label);
-#endif
/* compress the label if possible */
if ((tmplen = compress_label(reply, outlen, labellen)) > 0) {
outlen = tmplen;
}
-#if 0
- label = dns_label((char *)mysoa.responsible_person, &labellen);
- if (label == NULL)
- return;
-#endif
-
label = &sd->soa.responsible_person[0];
labellen = sd->soa.rp_len;
plabel = label;
@@ -828,18 +821,11 @@ reply_soa(struct sreply *sreply)
}
if (i >= sizeof(reply)) {
-#if 0
- free(label);
-#endif
return ;
}
outlen = i;
-#if 0
- free(label);
-#endif
-
/* 2 compress the label if possible */
if ((tmplen = compress_label(reply, outlen, labellen)) > 0) {
@@ -847,15 +833,6 @@ reply_soa(struct sreply *sreply)
}
-#if 0
- if ((outlen + sizeof(mysoa.serial)) > sizeof(reply)) {
- /* XXX server error reply? */
- return;
- }
- soa_val = (u_int32_t *)&reply[outlen];
- *soa_val = htonl(mysoa.serial);
- outlen += sizeof(mysoa.serial);
-#else
if ((outlen + sizeof(sd->soa.serial)) > sizeof(reply)) {
/* XXX server error reply? */
return;
@@ -863,71 +840,34 @@ reply_soa(struct sreply *sreply)
soa_val = (u_int32_t *)&reply[outlen];
*soa_val = htonl(sd->soa.serial);
outlen += sizeof(sd->soa.serial);
-#endif
-#if 0
- if ((outlen + sizeof(mysoa.refresh)) > sizeof(reply)) {
- return;
- }
- soa_val = (u_int32_t *)&reply[outlen];
- *soa_val = htonl(mysoa.refresh);
- outlen += sizeof(mysoa.refresh);
-#else
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);
-#endif
-#if 0
- if ((outlen + sizeof(mysoa.retry)) > sizeof(reply)) {
- return;
- }
- soa_val = (u_int32_t *)&reply[outlen];
- *soa_val = htonl(mysoa.retry);
- outlen += sizeof(mysoa.retry);
-#else
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);
-#endif
-#if 0
- if ((outlen + sizeof(mysoa.expire)) > sizeof(reply)) {
- return;
- }
- soa_val = (u_int32_t *)&reply[outlen];
- *soa_val = htonl(mysoa.expire);
- outlen += sizeof(mysoa.expire);
-#else
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);
-#endif
-#if 0
- if ((outlen + sizeof(mysoa.minttl)) > sizeof(reply)) {
- return;
- }
- soa_val = (u_int32_t *)&reply[outlen];
- *soa_val = htonl(mysoa.minttl);
- outlen += sizeof(mysoa.minttl);
-#else
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);
-#endif
answer->rdlength = htons(&reply[outlen] - &answer->rdata);
@@ -994,34 +934,195 @@ reply_nxdomain(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;
-
-#if 0
- struct question *q = sreply->q;
struct domain *sd = sreply->sd1;
-#endif
odh = (struct dns_header *)&reply[0];
outlen = sizeof(struct dns_header);
if (len > sizeof(reply)) {
return;
+
}
- memcpy(&reply, buf, len);
+ /*
+ * 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);
+ SET_DNS_RCODE_NAMEERR(odh);
+
+ 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);
SET_DNS_RCODE_NAMEERR(odh);
+
+ NTOHS(odh->query);
- HTONS(odh->query);
+ odh->question = ntohs(1);
+ odh->answer = 0;
+ odh->nsrr = ntohs(1);
+ odh->additional = 0;
- if (sendto(so, reply, len, 0, sa, salen) < 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