Commit Diff
Diff:
662d9d7e1642e0a619ff7f9c0893a6a6bf340de0
0d95ac68ffb564f80434b642a9fc4b0c5d8f45f7
Commit:
0d95ac68ffb564f80434b642a9fc4b0c5d8f45f7
Tree:
c31107084b510b67a450c850737a847ac78c9695
Author:
pbug <pbug@delphinusdns.org>
Committer:
pbug <pbug@delphinusdns.org>
Date:
Mon Dec 27 20:17:56 2010 UTC
Message:
* The ANY type support per request by Alexander Dzuba. * this type only supports A RR's for now and needs testing, first commit in a series. compiles on OpenBSD, replies to any requests
blob - 318db88409cc1f8f9e65734820c84c08d04364de
blob + e8d2ed84f7ec49a410a25ace0c005912aa0788a8
--- dns.h
+++ dns.h
@@ -135,6 +135,8 @@ struct dns_question_hdr {
#define DNS_TYPE_MX 15
#define DNS_TYPE_TXT 16
+#define DNS_TYPE_ANY 255
+
/* DNS types 0xff00 -> 0xfffe (private use) RFC 5395, page 8 */
#define DNS_TYPE_BALANCE 0xfffe /* split horizon dns */
blob - 27ec2cfffa4076737fe702ebd762aaa0ec067722
blob + 91c79e5e885ad3498b15c219ab899fae06b7beb1
--- main.c
+++ main.c
@@ -50,6 +50,7 @@ extern void reply_cname(struct sreply *);
extern void reply_mx(struct sreply *, DB *);
extern void reply_ns(struct sreply *, DB *);
extern void reply_txt(struct sreply *);
+extern void reply_any(struct sreply *);
extern u_int8_t find_region(struct sockaddr_storage *sst, int family);
extern int find_wildcard(struct sockaddr_storage *sst, int family);
extern void init_wildcard(void);
@@ -82,6 +83,7 @@ struct typetable {
{ "MX", DNS_TYPE_MX},
{ "TXT", DNS_TYPE_TXT},
{ "AAAA", DNS_TYPE_AAAA},
+ { "ANY", DNS_TYPE_ANY },
{ NULL, 0}
};
@@ -112,7 +114,7 @@ struct tcps {
} *tn1, *tn2, *tnp;
-static const char rcsid[] = "$Id: main.c,v 1.56 2010/09/30 09:12:32 pbug Exp $";
+static const char rcsid[] = "$Id: main.c,v 1.57 2010/12/27 20:17:56 pbug Exp $";
/*
* MAIN - set up arguments, set up database, set up sockets, call mainloop
@@ -1150,6 +1152,9 @@ lookup_zone(DB *db, struct question *question, struct
switch (ntohs(question->hdr->qtype)) {
+ case DNS_TYPE_ANY:
+ returnval = DNS_TYPE_ANY;
+ break;
case DNS_TYPE_A:
if ((sd->flags & DOMAIN_HAVE_A) ==
DOMAIN_HAVE_A) {
@@ -1285,6 +1290,9 @@ lookup_zone(DB *db, struct question *question, struct
}
switch (ntohs(question->hdr->qtype)) {
+ case DNS_TYPE_ANY:
+ returnval = DNS_TYPE_ANY;
+ break;
case DNS_TYPE_A:
if ((sd->flags & DOMAIN_HAVE_A) ==
DOMAIN_HAVE_A) {
@@ -1938,6 +1946,13 @@ tcpnxdomain:
}
break;
+
+ case DNS_TYPE_ANY:
+ build_reply(&sreply, tnp->so, pbuf, len, question, from, \
+ fromlen, &sd0, NULL, tnp->region, istcp, tnp->wildcard, NULL);
+ reply_any(&sreply);
+ break; /* must break here */
+
case DNS_TYPE_AAAA:
if (type0 == DNS_TYPE_CNAME) {
@@ -2342,6 +2357,13 @@ udpnxdomain:
}
break;
+
+ case DNS_TYPE_ANY:
+ build_reply(&sreply, so, buf, len, question, from, \
+ fromlen, &sd0, NULL, aregion, istcp, wildcard, NULL);
+ reply_any(&sreply);
+ break; /* must break here */
+
case DNS_TYPE_AAAA:
if (type0 == DNS_TYPE_CNAME) {
blob - 7b17d5c5851781da5d27d036b9caa75ee780dbd8
blob + e1540da592e6ed15b01188f4a6a8fb73810f3e7c
--- reply.c
+++ reply.c
@@ -40,6 +40,7 @@ void reply_soa(struct sreply *);
void reply_ptr(struct sreply *);
void reply_txt(struct sreply *sreply);
void reply_cname(struct sreply *);
+void reply_any(struct sreply *);
void reply_fmterror(struct sreply *);
void reply_raw2(int so, char *reply, int outlen, struct recurses *sr);
void reply_raw6(int so, char *reply, int outlen, struct recurses *sr);
@@ -57,6 +58,7 @@ extern int lookup_zone(DB *, struct question *, struct
void update_db(DB *, struct domain *);
struct domain * Lookup_zone(DB *db, char *name, u_int16_t namelen, u_int16_t type, int);
void collects_init(void);
+u_int16_t create_anyreply(struct sreply *sreply, char *reply, int rlen, int offset);
#ifdef __linux__
static int udp_cksum(const struct iphdr *ip, const struct udphdr *up, int len);
@@ -77,7 +79,7 @@ struct collects {
} *cn1, *cn2, *cnp;
-static const char rcsid[] = "$Id: reply.c,v 1.38 2010/10/06 10:42:54 pbug Exp $";
+static const char rcsid[] = "$Id: reply.c,v 1.39 2010/12/27 20:17:56 pbug Exp $";
/*
* REPLY_A() - replies a DNS question (*q) on socket (so)
@@ -2456,3 +2458,188 @@ in_cksum(const u_short *addr, register int len, int cs
return (answer);
}
+void
+reply_any(struct sreply *sreply)
+{
+ char reply[512];
+ struct dns_header *odh;
+ u_int16_t outlen;
+ char *p;
+ u_int32_t *soa_val;
+ int i, tmplen;
+ int labellen;
+ char *label, *plabel;
+
+ 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;
+ int istcp = sreply->istcp;
+
+ /* st */
+
+ odh = (struct dns_header *)&reply[0];
+ outlen = sizeof(struct dns_header);
+
+ if (len > sizeof(reply)) {
+ 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);
+ if (sreply->sr == NULL)
+ SET_DNS_AUTHORITATIVE(odh);
+ else
+ SET_DNS_RECURSION_AVAIL(odh);
+
+ NTOHS(odh->query);
+
+ odh->question = htons(1);
+ odh->answer = htons(1);
+ odh->nsrr = 0;
+ odh->additional = 0;
+
+ outlen = create_anyreply(sreply, (char *)&reply, sizeof(reply), outlen);
+ if (outlen == 0) {
+ return;
+ }
+
+ if (sreply->sr != NULL) {
+ reply_raw2(so, reply, outlen, sreply->sr);
+ } else {
+ if (istcp) {
+ char *tmpbuf;
+ u_int16_t *plen;
+
+ tmpbuf = malloc(outlen + 2);
+ if (tmpbuf == NULL) {
+ syslog(LOG_INFO, "malloc: %m");
+ }
+ plen = (u_int16_t *)tmpbuf;
+ *plen = htons(outlen);
+
+ 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");
+ }
+ }
+ }
+
+ return;
+}
+
+/*
+ * CREATE_ANYREPLY - pack an entire zone record into an any reply or axfr
+ *
+ */
+
+u_int16_t
+create_anyreply(struct sreply *sreply, char *reply, int rlen, int offset)
+{
+ int a_count;
+ int tmplen, pos, mod;
+ int ttlhack;
+ struct answer {
+ u_int16_t type; /* 0 */
+ u_int16_t class; /* 2 */
+ u_int32_t ttl; /* 4 */
+ u_int16_t rdlength; /* 8 */
+ char rdata[0]; /* 10 */
+ } __packed;
+ struct answer *answer;
+ struct domain *sd = sreply->sd1;
+ u_int8_t region = sreply->region;
+ struct dns_header *odh = (struct dns_header *)reply;
+
+ if (sd->flags & DOMAIN_HAVE_A) {
+ /* if we aren't a balance record our region code is 0xff so check */
+ if (sd->region[sd->a_ptr] != 0xff) {
+ ttlhack = 1;
+ }
+
+ a_count = 0;
+ pos = sd->a_ptr;
+ mod = sd->a_count;
+
+ do {
+ /*
+ * skip records that are not in the needed region
+ */
+ if (ttlhack && sd->region[pos % mod] != region) {
+ pos++;
+ continue;
+ }
+
+ memcpy(&reply[offset], sd->zone, sd->zonelen);
+ offset += sd->zonelen;
+
+ if ((tmplen = compress_label((u_char*)reply, offset, sd->zonelen)) > 0) {
+ offset = tmplen;
+ } else
+ return 0;
+
+ answer = (struct answer *)&reply[offset];
+
+ answer->type = htons(DNS_TYPE_A);
+ answer->class = htons(DNS_CLASS_IN);
+ answer->ttl = htonl(sd->ttl);
+ answer->rdlength = htons(sizeof(in_addr_t));
+
+ memcpy((char *)&answer->rdata, (char *)&sd->a[pos++ % mod],
+ sizeof(in_addr_t));
+
+ a_count++;
+ offset += 14;
+
+ /* can we afford to write another header? if no truncate */
+ if (sd->a_count > 1 && offset + 16 > rlen) {
+ NTOHS(odh->query);
+ SET_DNS_TRUNCATION(odh);
+ HTONS(odh->query);
+ goto out;
+ }
+
+ answer = (struct answer *)&reply[offset];
+
+ } while (a_count < RECORD_COUNT && --sd->a_count);
+
+ if (ttlhack) {
+ odh->answer = htons(a_count);
+ }
+
+
+ }
+ if (sd->flags & DOMAIN_HAVE_SOA) {
+ }
+ if (sd->flags & DOMAIN_HAVE_CNAME) {
+ }
+ if (sd->flags & DOMAIN_HAVE_PTR) {
+ }
+ if (sd->flags & DOMAIN_HAVE_MX) {
+ }
+ if (sd->flags & DOMAIN_HAVE_AAAA) {
+ }
+ if (sd->flags & DOMAIN_HAVE_NS) {
+ }
+ if (sd->flags & DOMAIN_HAVE_TXT) {
+ }
+
+
+out:
+ return (offset);
+}
repomaster@centroid.eu