Commit Diff
Diff:
e14c68ba191ab2ea78b2abf23aecb8103c982d1f
38ea682958848c9447a984042b446aa7025115b3
Commit:
38ea682958848c9447a984042b446aa7025115b3
Tree:
8f2beb06d1a4439f900dae6c902b57a20305aa14
Author:
pjp <pjp@delphinusdns.org>
Committer:
pjp <pjp@delphinusdns.org>
Date:
Sat Nov 14 10:07:19 2015 UTC
Message:
When an EDNS question has a version != 0 reply with BADVERS, this fixes some warnings at http://dnsviz.net/
blob - d167829bfdf3d7bdfabd774ff67379abd6e89f41
blob + cfd3ae2be1df91b690fe861ead45213d711d2b80
--- additional.c
+++ additional.c
@@ -43,7 +43,7 @@ extern void * find_substruct(struct domain *, u_int16
extern int dnssec;
-static const char rcsid[] = "$Id: additional.c,v 1.11 2015/09/13 05:57:35 pjp Exp $";
+static const char rcsid[] = "$Id: additional.c,v 1.12 2015/11/14 10:07:19 pjp Exp $";
/*
@@ -483,6 +483,12 @@ additional_opt(struct question *question, char *reply,
answer->class = htons(question->edns0len);
if (dnssec && question->dnssecok)
rcode = DNSSEC_OK;
+
+ if (question->badvers)
+ rcode |= (0x1 << 24);
+
+ if (question->ednsversion)
+ rcode |= (question->ednsversion << 16);
answer->ttl = htonl(rcode); /* EXTENDED RCODE */
blob - ae1be4ebb60dc6a40de2a2304b98e24fd4bac235
blob + da7f28e7d109e9a5abe44e844a8717da35498e48
--- dns.h
+++ dns.h
@@ -104,6 +104,7 @@ struct dns_question_hdr {
#define DNS_BADTIME 0x12 /* RCODE (18) BADTIME RFC 2845 p. 3 */
#define DNS_BADKEY 0x11 /* RCODE (17) BADKEY RFC 2845 p. 3 */
#define DNS_BADSIG 0x10 /* RCODE (16) BADSIG RFC 2845 p. 3 */
+#define DNS_BADVERS 0x10 /* RCODE (16) BADVERS RFC 2671 p. 6 */
#define DNS_REFUSED 0x5 /* RCODE - Refused */
#define DNS_NOTIMPL 0x4 /* RCODE - Not Implemented */
#define DNS_NAMEERR 0x3 /* RCODE - Name Error, NXDOMAIN */
@@ -220,7 +221,9 @@ struct question {
struct dns_question_hdr *hdr;
char *converted_name;
u_int16_t edns0len;
+ u_int8_t ednsversion;
int dnssecok;
+ int badvers;
};
#endif /* DNS_H */
blob - f58cf4b0455410d54f67fd5d4112b1a10221073d
blob + 384b8cd592be453b08d33ec1853acd705b0d5b0e
--- main.c
+++ main.c
@@ -54,6 +54,7 @@ extern void receivelog(char *, int);
extern int reply_a(struct sreply *, DB *);
extern int reply_aaaa(struct sreply *, DB *);
extern int reply_any(struct sreply *);
+extern int reply_badvers(struct sreply *);
extern int reply_cname(struct sreply *);
extern int reply_fmterror(struct sreply *);
extern int reply_notimpl(struct sreply *);
@@ -193,7 +194,7 @@ static struct tcps {
} *tn1, *tnp, *tntmp;
-static const char rcsid[] = "$Id: main.c,v 1.26 2015/11/10 11:25:57 pjp Exp $";
+static const char rcsid[] = "$Id: main.c,v 1.27 2015/11/14 10:07:19 pjp Exp $";
/*
* MAIN - set up arguments, set up database, set up sockets, call mainloop
@@ -1087,6 +1088,7 @@ build_question(char *buf, int len, int additional)
u_int i;
u_int namelen = 0;
u_int16_t *qtype, *qclass;
+ u_int32_t ttl;
int num_label;
char *p, *end_name = NULL;
@@ -1254,11 +1256,16 @@ build_question(char *buf, int len, int additional)
break;
/* RFC 3225 */
- if (ntohl(opt->ttl) & DNSSEC_OK)
+ ttl = ntohl(opt->ttl);
+ if (((ttl >> 16) & 0xff) != 0)
+ q->ednsversion = (ttl >> 16) & 0xff;
+
+ if (ttl & DNSSEC_OK)
q->dnssecok = 1;
- else if (ntohl(opt->ttl) != 0)
+ else if (ttl != 0)
break;
+
q->edns0len = ntohs(opt->class);
if (q->edns0len < 512)
q->edns0len = 512; /* RFC 6891 - page 10 */
@@ -2342,7 +2349,6 @@ mainloop(struct cfg *cfg)
dolog(LOG_INFO, "TCP packet on descriptor %u interface \"%s\" malformed question from %s, drop\n", tnp->so, tnp->ident, tnp->address);
goto drop;
}
-
/* goto drop beyond this point should goto out instead */
fakequestion = NULL;
@@ -2979,6 +2985,18 @@ axfrentry:
}
/* goto drop beyond this point should goto out instead */
+
+ /* hack around whether we're edns version 0 */
+ if (question->ednsversion != 0) {
+ build_reply(&sreply, so, buf, len, question, from, fromlen, NULL, NULL, aregion, istcp, wildcard, NULL, replybuf);
+ slen = reply_badvers(&sreply);
+
+ dolog(LOG_INFO, "on descriptor %u interface \"%s\" edns version is %u from %s, replying badvers\n", so, cfg->ident[i], question->ednsversion, address);
+
+ snprintf(replystring, DNS_MAXNAME, "BADVERS");
+ goto udpout;
+ }
+
fakequestion = NULL;
sd0 = lookup_zone(cfg->db, question, &type0, &lzerrno, (char *)&replystring);
blob - 95b6a13982ad842336a02cd22f4b22dacf297af6
blob + 1556a00ef282b410af87c99ef0df17f238ff1868
--- reply.c
+++ reply.c
@@ -69,6 +69,7 @@ int reply_ns(struct sreply *, DB *);
int reply_notimpl(struct sreply *);
int reply_nxdomain(struct sreply *, DB *);
int reply_noerror(struct sreply *, DB *);
+int reply_badvers(struct sreply *);
int reply_soa(struct sreply *);
int reply_ptr(struct sreply *);
int reply_txt(struct sreply *);
@@ -128,7 +129,7 @@ extern uint8_t vslen;
outlen = tmplen; \
} while (0);
-static const char rcsid[] = "$Id: reply.c,v 1.40 2015/11/10 11:04:07 pjp Exp $";
+static const char rcsid[] = "$Id: reply.c,v 1.41 2015/11/14 10:07:19 pjp Exp $";
/*
* REPLY_A() - replies a DNS question (*q) on socket (so)
@@ -6757,4 +6758,94 @@ truncate:
HTONS(odh->query);
return (offset);
+}
+
+/*
+ * REPLY_BADVERS() - replies a DNS question (*q) on socket (so)
+ *
+ */
+
+int
+reply_badvers(struct sreply *sreply)
+{
+ char *reply = sreply->replybuf;
+ struct dns_header *odh;
+ u_int16_t outlen;
+
+ 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;
+ int istcp = sreply->istcp;
+ int replysize = 512;
+ int retlen = -1;
+
+ if (istcp) {
+ replysize = 65535;
+ }
+
+ if (!istcp && q->edns0len > 512)
+ replysize = q->edns0len;
+
+ odh = (struct dns_header *)&reply[0];
+ outlen = sizeof(struct dns_header);
+
+ if (len > replysize) {
+ return (retlen);
+
+ }
+
+ 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);
+
+ SET_DNS_REPLY(odh);
+ SET_DNS_AUTHORITATIVE(odh);
+
+ HTONS(odh->query);
+
+ odh->question = htons(1);
+ odh->answer = 0;
+ odh->nsrr = 0;
+ odh->additional = 0;
+
+ if (q->edns0len) {
+ /* tag on edns0 opt record */
+ odh->additional = htons(1);
+ q->badvers = DNS_BADVERS;
+ outlen = additional_opt(q, reply, replysize, outlen);
+ }
+
+ if (sreply->sr != NULL) {
+ retlen = reply_raw2(so, reply, outlen, sreply->sr);
+ } else {
+
+ if (istcp) {
+ char *tmpbuf;
+ u_int16_t *plen;
+
+ tmpbuf = malloc(outlen + 2);
+ if (tmpbuf == NULL) {
+ dolog(LOG_INFO, "malloc: %s\n", strerror(errno));
+ }
+ plen = (u_int16_t *)tmpbuf;
+ *plen = htons(outlen);
+
+ memcpy(&tmpbuf[2], reply, outlen);
+
+ if ((retlen = send(so, tmpbuf, outlen + 2, 0)) < 0) {
+ dolog(LOG_INFO, "send: %s\n", strerror(errno));
+ }
+ free(tmpbuf);
+ } else {
+ if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
+ }
+ } /* sreply->sr.. */
+
+ return (retlen);
}
repomaster@centroid.eu