Commit Diff
Diff:
5545c2c427d4a4de9531b591c070b896acd452ec
d64396b724038bdb7e3ddd8ac8292c3d3340ea6b
Commit:
d64396b724038bdb7e3ddd8ac8292c3d3340ea6b
Tree:
3a80d76f76d09ddc51a1855094c7f63197809da2
Author:
pjp <pjp@delphinusdns.org>
Committer:
pjp <pjp@delphinusdns.org>
Date:
Fri May 9 22:02:18 2014 UTC
Message:
* first steps at EDNS0 support, this just detects an EDNS0 request but doesn't reply in that fashion. * EDNS0 is RFC 6891 * while there I think I fixed a bug that would have allowed compressed names the check was in a wrong spot, please correct me if I'm wrong.
blob - 2ce49977f3ea5592b394e4a8c4b7c3c38c02bc93
blob + 9ac472a4a0ccee82816f873f55880359e1842b2c
--- dns.h
+++ dns.h
@@ -65,6 +65,20 @@ struct dns_rr {
char *rdata; /* data of record */
};
+/*
+ * EDNS0 OPT RR, based on dns_rr
+ * RFC 6891 - page 7
+ */
+
+struct dns_optrr {
+ char name[0]; /* always 0 */
+ u_int16_t type; /* must be 41 */
+ u_int16_t class; /* UDP payload size (4096) */
+ u_int32_t ttl; /* extended RCODE */
+ u_int16_t rdlen; /* length of all RDATA */
+ char *rdata; /* attribute, value pairs */
+};
+
/* RFC 1035 - page 28 */
struct dns_question_hdr {
char *name;
@@ -136,6 +150,7 @@ struct dns_question_hdr {
#define DNS_TYPE_TXT 16
#define DNS_TYPE_SRV 33 /* RFC 2782, page 8 */
+#define DNS_TYPE_OPT 41 /* RFC 6891, page 7 */
#define DNS_TYPE_SSHFP 44 /* RFC 4255 */
#define DNS_TYPE_SPF 99 /* RFC 4408 */
@@ -178,6 +193,7 @@ struct dns_question_hdr {
struct question {
struct dns_question_hdr *hdr;
char *converted_name;
+ int edns0len;
};
#endif /* DNS_H */
blob - 79912675c00f74e97bf80a6715aa8a4b41accb1a
blob + 53870531cacbc444d9e74fe716cbb718beb0b59c
--- main.c
+++ main.c
@@ -32,7 +32,7 @@
/* prototypes */
-struct question * build_question(char *, int);
+struct question * build_question(char *, int, int);
struct question * build_fake_question(char *, int, u_int16_t);
void mainloop(struct cfg *cfg);
int free_question(struct question *);
@@ -131,7 +131,7 @@ static int msig;
static char *database;
static char mydatabase[512];
static char *rptr;
-static ratelimit_backlog;
+static int ratelimit_backlog;
int debug = 0;
int verbose = 0;
@@ -166,7 +166,7 @@ static struct tcps {
} *tn1, *tnp, *tntmp;
-static const char rcsid[] = "$Id: main.c,v 1.88 2014/05/05 08:46:17 pjp Exp $";
+static const char rcsid[] = "$Id: main.c,v 1.89 2014/05/09 22:02:18 pjp Exp $";
/*
* MAIN - set up arguments, set up database, set up sockets, call mainloop
@@ -1067,7 +1067,7 @@ main(int argc, char *argv[])
*/
struct question *
-build_question(char *buf, int len)
+build_question(char *buf, int len, int additional)
{
u_int i;
u_int namelen = 0;
@@ -1076,7 +1076,8 @@ build_question(char *buf, int len)
char *p, *end_name = NULL;
- struct question *q;
+ struct dns_optrr *opt = NULL;
+ struct question *q = NULL;
/* find the end of name */
for (i = sizeof(struct dns_header); i < len; i++) {
@@ -1182,6 +1183,14 @@ build_question(char *buf, int len)
for (i = sizeof(struct dns_header); i < len && &buf[i] < end_name;) {
u_int labelend;
+
+ /* check for compression */
+ if ((buf[i] & 0xc0) == 0xc0) {
+ dolog(LOG_INFO, "question has compressed name, drop\n");
+ free_question(q);
+ return NULL; /* XXX should say error */
+ }
+
labelend = (u_int)buf[i] + 1 + i; /* i = offset, plus contents of buf[i], + 1 */
/*
@@ -1192,11 +1201,6 @@ build_question(char *buf, int len)
for (i++; i < labelend; i++) {
int c0;
- if ((buf[i] & 0xc0) == 0xc0) {
- dolog(LOG_INFO, "question has compressed name, drop\n");
- free_question(q);
- return NULL; /* XXX should say error */
- }
c0 = buf[i];
*p++ = tolower(c0);
}
@@ -1210,8 +1214,40 @@ build_question(char *buf, int len)
*p = '\0';
+ /* check for edns0 opt rr */
+ do {
+ /* if we don't have an additional section, break */
+ if (additional != 1)
+ break;
+
+ i += (2 * sizeof(u_int16_t)) + 2;
+
+ /* check that the minimum optrr fits */
+ if (i + 10 > len)
+ break;
+
+
+ opt = (struct dns_optrr *)&buf[i];
+ if (*opt->name != 0)
+ break;
+
+ if (ntohs(opt->type) != DNS_TYPE_OPT)
+ break;
+
+ /* hackaround everything 0 for edns0 question */
+ if (ntohl(opt->ttl) != 0)
+ break;
+
+ /* if we got options here I don't want to know about them */
+ if (ntohs(opt->rdlen) > 0)
+ break;
+
+ q->edns0len = ntohs(opt->class);
+
+ } while (0);
+
/* fill our name into the dns header struct */
-
+
memcpy(q->hdr->name, &buf[sizeof(struct dns_header)], q->hdr->namelen);
/* make it lower case */
@@ -1233,6 +1269,7 @@ build_question(char *buf, int len)
memcpy((char *)&q->hdr->qtype, (char *)qtype, sizeof(u_int16_t));
memcpy((char *)&q->hdr->qclass, (char *)qclass, sizeof(u_int16_t));
+
return (q);
}
@@ -2470,7 +2507,7 @@ mainloop(struct cfg *cfg)
}
- if ((question = build_question(pbuf, len)) == NULL) {
+ if ((question = build_question(pbuf, len, 0)) == NULL) {
dolog(LOG_INFO, "TCP packet on descriptor %u interface \"%s\" malformed question from %s, drop\n", tnp->so, tnp->ident, tnp->address);
goto drop;
}
@@ -2996,7 +3033,7 @@ axfrentry:
rh.len = len;
}
- if ((question = build_question(buf, len)) == NULL) {
+ if ((question = build_question(buf, len, ntohs(dh->additional))) == NULL) {
dolog(LOG_INFO, "on descriptor %u interface \"%s\" malformed question from %s, drop\n", so, cfg->ident[i], address);
goto drop;
}
@@ -3355,12 +3392,12 @@ udpnxdomain:
udpout:
if (lflag) {
- dolog(LOG_INFO, "request on descriptor %u interface \"%s\" from %s (ttl=%u, region=%d) for \"%s\" type=%s class=%u, answering \"%s\"\n", so, cfg->ident[i], address, received_ttl, aregion, question->converted_name, get_dns_type(ntohs(question->hdr->qtype)), ntohs(question->hdr->qclass), replystring);
+ dolog(LOG_INFO, "request on descriptor %u interface \"%s\" from %s (ttl=%u, region=%d) for \"%s\" type=%s class=%u, %sanswering \"%s\"\n", so, cfg->ident[i], address, received_ttl, aregion, question->converted_name, get_dns_type(ntohs(question->hdr->qtype)), ntohs(question->hdr->qclass), (question->edns0len ? "edns0, " : ""), replystring);
}
if (logging.active == 1 && logging.bind == 0) {
- remotelog(lfd, "request on descriptor %u interface \"%s\" from %s (ttl=%u, region=%d) for \"%s\" type=%s class=%u, answering \"%s\"", so, cfg->ident[i], address, received_ttl, aregion, question->converted_name, get_dns_type(ntohs(question->hdr->qtype)), ntohs(question->hdr->qclass), replystring);
+ remotelog(lfd, "request on descriptor %u interface \"%s\" from %s (ttl=%u, region=%d) for \"%s\" type=%s class=%u, %sanswering \"%s\"", so, cfg->ident[i], address, received_ttl, aregion, question->converted_name, get_dns_type(ntohs(question->hdr->qtype)), ntohs(question->hdr->qclass), (question->edns0len ? "edns0, ": ""), replystring);
}
if (fakequestion != NULL) {
repomaster@centroid.eu