Commit Diff
Diff:
bb3365575bf75f58c4f34c17cedc3e6ba173aaea
a042435d6c61780f70670dd56d06f8a7cccdd5d7
Commit:
a042435d6c61780f70670dd56d06f8a7cccdd5d7
Tree:
7764d050ded20b72b2509de6ee7540a9c75b95cd
Author:
pbug <pbug@delphinusdns.org>
Committer:
pbug <pbug@delphinusdns.org>
Date:
Fri Mar 19 11:36:52 2010 UTC
Message:
* when serving a ns or mx record, tag on additional records that are found in the database. This has the potential for slow-down but it's the only way I want to do it right now.
blob - c3a23df982ded7d4b858c37c1a3c60116c97965b
blob + cc032048119c78cfff3923d1349d3a0bf1e5c212
--- example7.conf
+++ example7.conf
@@ -137,7 +137,11 @@ zone "centroid.eu" {
localhost.centroid.eu,aaaa,3600,::1
; the below are new delegations (NS) records
;delegation.centroid.eu,delegate,3600,ns1.server.com.
+ ; glue record
+ ;ns1.server.com.,a,3600,10.0.0.1
;delegation.centroid.eu,delegate,3600,ns2.server.com.
+ ; glue record
+ ;ns2.server.com.,a,3600,10.0.0.2
}
zone "ipv6.centroid.eu" {
ipv6.centroid.eu,soa,3600,uranus.centroid.eu.,pjp.solarscale.de.,1244725285,3600,1800,7200,3600
blob - 658d20afea12e02fccb3cb87a92b8b92b0c2fa19
blob + 88f0cac8892da9b97f1510fbf86e85bb4831ae3f
--- main.c
+++ main.c
@@ -47,9 +47,11 @@ extern void reply_aaaa(struct sreply *, DB *);
extern void reply_soa(struct sreply *);
extern void reply_ptr(struct sreply *);
extern void reply_cname(struct sreply *);
-extern void reply_mx(struct sreply *);
+extern void reply_mx(struct sreply *, DB *);
extern void reply_ns(struct sreply *, DB *);
extern u_int8_t find_region(in_addr_t);
+extern void collects_init(void);
+
char * dns_label(char *, int *);
int compress_label(char *, int, int);
int memcasecmp(char *, char *, int);
@@ -101,7 +103,7 @@ struct tcps {
} *tn1, *tn2, *tnp;
-static const char rcsid[] = "$Id: main.c,v 1.39 2010/03/14 21:41:37 pbug Exp $";
+static const char rcsid[] = "$Id: main.c,v 1.40 2010/03/19 11:36:52 pbug Exp $";
/*
* MAIN - set up arguments, set up database, set up sockets, call mainloop
@@ -1352,6 +1354,7 @@ mainloop(int *udp, int *tcp, int sockcount, char **ide
int flag;
SLIST_INIT(&tcpshead);
+ collects_init();
/*
* set descriptors nonblocking, and listen on them
@@ -1709,7 +1712,7 @@ tcpnxdomain:
} else if (type0 == DNS_TYPE_MX) {
BUILD_REPLY(sreply, so, pbuf, len, question, from, \
fromlen, &sd0, NULL, tnp->region, istcp);
- reply_mx(&sreply);
+ reply_mx(&sreply, db);
break; /* must break here */
}
@@ -2020,7 +2023,7 @@ udpnxdomain:
} else if (type0 == DNS_TYPE_MX) {
BUILD_REPLY(sreply, so, buf, len, question, from, \
fromlen, &sd0, NULL, aregion, istcp);
- reply_mx(&sreply);
+ reply_mx(&sreply, db);
break; /* must break here */
}
blob - 3d751441f69888733cf71b7379e6597ebb619770
blob + abf0ad2f156b6f6576291151181384e0447ec3e3
--- reply.c
+++ reply.c
@@ -31,7 +31,7 @@
void reply_a(struct sreply *, DB *);
void reply_aaaa(struct sreply *, DB *);
-void reply_mx(struct sreply *);
+void reply_mx(struct sreply *, DB *);
void reply_ns(struct sreply *, DB *);
void reply_notimpl(struct sreply *);
void reply_nxdomain(struct sreply *);
@@ -47,10 +47,28 @@ 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 *);
+extern struct question * build_fake_question(char *, int, u_int16_t);
+extern int free_question(struct question *);
+extern int lookup_zone(DB *, struct question *, struct domain *, int *, char *);
+
void update_db(DB *, struct domain *);
+struct domain * Lookup_zone(DB *db, char *name, int namelen, u_int16_t type);
+void collects_init(void);
-static const char rcsid[] = "$Id: reply.c,v 1.16 2010/03/18 08:55:13 pbug Exp $";
+SLIST_HEAD(listhead, collects) collectshead;
+
+struct collects {
+ char *name;
+ int namelen;
+ u_int16_t type;
+ struct domain *sd;
+ SLIST_ENTRY(collects) entries;
+} *cn1, *cn2, *cnp;
+
+
+static const char rcsid[] = "$Id: reply.c,v 1.17 2010/03/19 11:36:52 pbug Exp $";
+
/*
* REPLY_A() - replies a DNS question (*q) on socket (so)
*
@@ -89,10 +107,6 @@ reply_a(struct sreply *sreply, DB *db)
u_int8_t region = sreply->region;
int istcp = sreply->istcp;
-#if 0
- memset(&reply, 0, sizeof(reply));
-#endif
-
if (istcp) {
plen = (u_int16_t *)&reply[0];
odh = (struct dns_header *)&reply[2];
@@ -344,13 +358,17 @@ out:
*/
void
-reply_mx(struct sreply *sreply)
+reply_mx(struct sreply *sreply, DB *db)
{
char reply[512];
struct dns_header *odh;
+ struct domain *sd0;
int outlen;
int mx_count;
u_int16_t *plen;
+ char *name;
+ int namelen;
+ int additional = 0;
struct answer {
char name[2];
@@ -374,11 +392,7 @@ reply_mx(struct sreply *sreply)
int istcp = sreply->istcp;
- if (istcp) {
- plen = (u_int16_t *)&reply[0];
- odh = (struct dns_header *)&reply[2];
- } else
- odh = (struct dns_header *)&reply[0];
+ odh = (struct dns_header *)&reply[0];
outlen = sizeof(struct dns_header);
@@ -386,10 +400,7 @@ reply_mx(struct sreply *sreply)
return;
}
- if (istcp) {
- memcpy(&reply[2], buf, sizeof(struct dns_header) + q->hdr->namelen + 4);
- } else
- memcpy(&reply, buf, sizeof(struct dns_header) + q->hdr->namelen + 4);
+ memcpy(&reply, buf, sizeof(struct dns_header) + q->hdr->namelen + 4);
memset((char *)&odh->query, 0, sizeof(u_int16_t));
outlen += (q->hdr->namelen + 4);
@@ -405,12 +416,8 @@ reply_mx(struct sreply *sreply)
odh->additional = 0;
/* skip dns header, question name, qtype and qclass */
- if (istcp) {
- answer = (struct answer *)(&reply[2] + sizeof(struct dns_header) +
+ answer = (struct answer *)(&reply[0] + sizeof(struct dns_header) +
q->hdr->namelen + 4);
- } else
- answer = (struct answer *)(&reply[0] + sizeof(struct dns_header) +
- q->hdr->namelen + 4);
mx_count = 0;
do {
@@ -424,6 +431,41 @@ reply_mx(struct sreply *sreply)
answer->mx_priority = htons(sd->mx[mx_count].preference);
memcpy((char *)&answer->exchange, (char *)&sd->mx[mx_count].exchange, sd->mx[mx_count].exchangelen);
+
+ name = sd->mx[mx_count].exchange;
+ namelen = sd->mx[mx_count].exchangelen;
+
+ sd0 = Lookup_zone(db, name, namelen, htons(DNS_TYPE_A));
+ if (sd0 != NULL) {
+ cn1 = malloc(sizeof(struct collects));
+ if (cn1 != NULL) {
+ cn1->name = malloc(namelen);
+ if (cn1->name != NULL) {
+ memcpy(cn1->name, name, namelen);
+ cn1->namelen = namelen;
+ cn1->sd = sd0;
+ cn1->type = DNS_TYPE_A;
+
+ SLIST_INSERT_HEAD(&collectshead, cn1, entries);
+ }
+ }
+ }
+ sd0 = Lookup_zone(db, name, namelen, htons(DNS_TYPE_AAAA));
+ if (sd0 != NULL) {
+ cn1 = malloc(sizeof(struct collects));
+ if (cn1 != NULL) {
+ cn1->name = malloc(namelen);
+ if (cn1->name != NULL) {
+ memcpy(cn1->name, name, namelen);
+ cn1->namelen = namelen;
+ cn1->sd = sd0;
+ cn1->type = DNS_TYPE_AAAA;
+
+ SLIST_INSERT_HEAD(&collectshead, cn1, entries);
+ }
+ }
+ }
+
outlen += (12 + 2 + sd->mx[mx_count].exchangelen);
/* can we afford to write another header? if no truncate */
@@ -438,12 +480,54 @@ reply_mx(struct sreply *sreply)
answer = (struct answer *)&reply[outlen];
} while (++mx_count < 10 && --sd->mx_count);
+ /* write additional */
+
+ SLIST_FOREACH(cnp, &collectshead, entries) {
+ int addcount;
+ int tmplen;
+
+ switch (cnp->type) {
+ case DNS_TYPE_A:
+ tmplen = additional_a(cnp->name, cnp->namelen, cnp->sd, reply, sizeof(reply), outlen, &addcount);
+ additional += addcount;
+ break;
+ case DNS_TYPE_AAAA:
+ tmplen = additional_aaaa(cnp->name, cnp->namelen, cnp->sd, reply, sizeof(reply), outlen, &addcount);
+ additional += addcount;
+ break;
+ }
+
+ if (tmplen > 0) {
+ outlen = tmplen;
+ }
+ }
+
+ odh->additional = htons(additional);
+
+ while (!SLIST_EMPTY(&collectshead)) {
+ cn1 = SLIST_FIRST(&collectshead);
+ SLIST_REMOVE_HEAD(&collectshead, entries);
+ free(cn1->name);
+ free(cn1->sd);
+ free(cn1);
+ }
+
out:
if (istcp) {
+ char *tmpbuf;
+
+ tmpbuf = malloc(outlen + 2);
+ if (tmpbuf == NULL) {
+ syslog(LOG_INFO, "malloc: %m");
+ }
+ plen = (u_int16_t *)tmpbuf;
*plen = htons(outlen);
- if (send(so, reply, outlen + 2, 0) < 0) {
- syslog(LOG_INFO, "sendto: %m");
+
+ memcpy(&tmpbuf[2], reply, outlen);
+ if (send(so, tmpbuf, outlen + 2, 0) < 0) {
+ syslog(LOG_INFO, "send: %m");
}
+ free(tmpbuf);
} else {
if (sendto(so, reply, outlen, 0, sa, salen) < 0) {
syslog(LOG_INFO, "sendto: %m");
@@ -463,10 +547,14 @@ reply_ns(struct sreply *sreply, DB *db)
{
char reply[512];
struct dns_header *odh;
+ struct domain *sd0;
int outlen;
int ns_count;
int mod, pos;
u_int16_t *plen;
+ char *name;
+ int namelen;
+ int additional = 0;
struct answer {
char name[2];
@@ -492,11 +580,7 @@ reply_ns(struct sreply *sreply, DB *db)
memset(&reply, 0, sizeof(reply));
#endif
- if (istcp) {
- plen = (u_int16_t *)&reply[0];
- odh = (struct dns_header *)&reply[2];
- } else
- odh = (struct dns_header *)&reply[0];
+ odh = (struct dns_header *)&reply[0];
outlen = sizeof(struct dns_header);
@@ -504,10 +588,7 @@ reply_ns(struct sreply *sreply, DB *db)
return;
}
- if (istcp) {
- memcpy(&reply[2], buf, sizeof(struct dns_header) + q->hdr->namelen + 4);
- } else
- memcpy(&reply, buf, sizeof(struct dns_header) + q->hdr->namelen + 4);
+ memcpy(&reply, buf, sizeof(struct dns_header) + q->hdr->namelen + 4);
memset((char *)&odh->query, 0, sizeof(u_int16_t));
@@ -533,11 +614,7 @@ reply_ns(struct sreply *sreply, DB *db)
odh->additional = 0;
/* skip dns header, question name, qtype and qclass */
- if (istcp) {
- answer = (struct answer *)(&reply[2] + sizeof(struct dns_header) +
- q->hdr->namelen + 4);
- } else
- answer = (struct answer *)(&reply[0] + sizeof(struct dns_header) +
+ answer = (struct answer *)(&reply[0] + sizeof(struct dns_header) +
q->hdr->namelen + 4);
ns_count = 0;
@@ -551,12 +628,50 @@ reply_ns(struct sreply *sreply, DB *db)
answer->class = q->hdr->qclass;
answer->ttl = htonl(sd->ttl);
- answer->rdlength = htons(sd->ns[pos % mod].nslen);
+ name = sd->ns[pos % mod].nsserver;
+ namelen = sd->ns[pos % mod].nslen;
- memcpy((char *)&answer->ns, (char *)&sd->ns[pos % mod].nsserver, sd->ns[pos % mod].nslen);
- outlen += (12 + sd->ns[pos % mod].nslen);
+ answer->rdlength = htons(namelen);
+ memcpy((char *)&answer->ns, (char *)name, namelen);
+ sd0 = Lookup_zone(db, name, namelen, htons(DNS_TYPE_A));
+ if (sd0 != NULL) {
+ cn1 = malloc(sizeof(struct collects));
+ if (cn1 != NULL) {
+ cn1->name = malloc(namelen);
+ if (cn1->name != NULL) {
+ memcpy(cn1->name, name, namelen);
+ cn1->namelen = namelen;
+ cn1->sd = sd0;
+ cn1->type = DNS_TYPE_A;
+
+ SLIST_INSERT_HEAD(&collectshead, cn1, entries);
+ }
+ }
+
+ }
+ sd0 = Lookup_zone(db, name, namelen, htons(DNS_TYPE_AAAA));
+ if (sd0 != NULL) {
+ cn1 = malloc(sizeof(struct collects));
+ if (cn1 != NULL) {
+ cn1->name = malloc(namelen);
+ if (cn1->name != NULL) {
+ memcpy(cn1->name, name, namelen);
+ cn1->namelen = namelen;
+ cn1->sd = sd0;
+ cn1->type = DNS_TYPE_AAAA;
+
+ SLIST_INSERT_HEAD(&collectshead, cn1, entries);
+
+ }
+ }
+
+ }
+
+ outlen += (12 + namelen);
+
+
/* can we afford to write another header? if no truncate */
if (sd->ns_count > 1 && (outlen + 12 + sd->ns[pos % mod].nslen) > DNS_MAXUDP) {
NTOHS(odh->query);
@@ -571,12 +686,54 @@ reply_ns(struct sreply *sreply, DB *db)
answer = (struct answer *)&reply[outlen];
} while (++ns_count < 10 && --sd->ns_count);
+ /* shuffle through our linked collect structure and add additional */
+
+ SLIST_FOREACH(cnp, &collectshead, entries) {
+ int addcount;
+ int tmplen;
+
+ switch (cnp->type) {
+ case DNS_TYPE_A:
+ tmplen = additional_a(cnp->name, cnp->namelen, cnp->sd, reply, sizeof(reply), outlen, &addcount);
+ additional += addcount;
+ break;
+ case DNS_TYPE_AAAA:
+ tmplen = additional_aaaa(cnp->name, cnp->namelen, cnp->sd, reply, sizeof(reply), outlen, &addcount);
+ additional += addcount;
+ break;
+ }
+
+ if (tmplen > 0) {
+ outlen = tmplen;
+ }
+ }
+
+ odh->additional = htons(additional);
+
+ while (!SLIST_EMPTY(&collectshead)) {
+ cn1 = SLIST_FIRST(&collectshead);
+ SLIST_REMOVE_HEAD(&collectshead, entries);
+ free(cn1->name);
+ free(cn1->sd);
+ free(cn1);
+ }
+
out:
if (istcp) {
+ char *tmpbuf;
+
+ tmpbuf = malloc(outlen + 2);
+ if (tmpbuf == NULL) {
+ syslog(LOG_INFO, "malloc: %m");
+ }
+ plen = (u_int16_t *)tmpbuf;
*plen = htons(outlen);
- if (send(so, reply, outlen + 2, 0) < 0) {
+
+ memcpy(&tmpbuf[2], reply, outlen);
+ if (send(so, tmpbuf, outlen + 2, 0) < 0) {
syslog(LOG_INFO, "send: %m");
}
+ free(tmpbuf);
} else {
if (sendto(so, reply, outlen, 0, sa, salen) < 0) {
syslog(LOG_INFO, "sendto: %m");
@@ -1746,4 +1903,49 @@ update_db(DB *db, struct domain *sd)
} while (ret != 0);
return;
+}
+
+/*
+ * Lookup_zone: wrapper for lookup_zone() et al.
+ */
+
+struct domain *
+Lookup_zone(DB *db, char *name, int namelen, u_int16_t type)
+{
+ struct domain *sd;
+ struct question *fakequestion;
+ char fakereplystring[DNS_MAXNAME + 1];
+ int mytype;
+ int lzerrno;
+
+ fakequestion = build_fake_question(name, namelen, type);
+ if (fakequestion == NULL) {
+ syslog(LOG_INFO, "fakequestion(2) failed");
+ return (NULL);
+ }
+
+ sd = calloc(sizeof(struct domain), 1);
+ if (sd == NULL) {
+ syslog(LOG_INFO, "calloc: %m");
+ free_question(fakequestion);
+ return (NULL);
+ }
+
+ mytype = lookup_zone(db, fakequestion, sd, &lzerrno, (char *)&fakereplystring);
+
+ if (mytype < 0) {
+ free(sd);
+ free_question(fakequestion);
+ return (NULL);
+ }
+
+ free_question(fakequestion);
+
+ return (sd);
+}
+
+void
+collects_init(void)
+{
+ SLIST_INIT(&collectshead);
}
repomaster@centroid.eu