Commit Diff
Diff:
8061892ef42909c7080e4830b12cc3a3ccea7fc6
cd18f39398bc007c41a0ac7c7d07b44b58b0aa79
Commit:
cd18f39398bc007c41a0ac7c7d07b44b58b0aa79
Tree:
8eee97a21930d3bf8e93bc00ded9154a69f7eb20
Author:
pjp <pjp@delphinusdns.org>
Committer:
pjp <pjp@delphinusdns.org>
Date:
Sat May 10 15:11:21 2014 UTC
Message:
* Fix up some previous made mistakes regarding EDNS0 * This should _hopefully_ complete EDNS0 support (receive and send) * relevant RFC's are RFC 6891 and RFC3225
blob - 6d82f55f6f3a42d3502b39347bbd3fccc1a473dc
blob + 70cac757f5e2e2b4d87ff391ade774a30e61a696
--- additional.c
+++ additional.c
@@ -33,10 +33,11 @@ int additional_a(char *, int, struct domain *, char *,
int additional_aaaa(char *, int, struct domain *, char *, int, int, int *);
int additional_mx(char *, int, struct domain *, char *, int, int, int *);
int additional_ptr(char *, int, struct domain *, char *, int, int, int *);
+int additional_opt(struct question *, char *, int, int);
extern int compress_label(u_char *, int, int);
-static const char rcsid[] = "$Id: additional.c,v 1.15 2014/04/13 09:05:42 pjp Exp $";
+static const char rcsid[] = "$Id: additional.c,v 1.16 2014/05/10 15:11:21 pjp Exp $";
/*
@@ -433,6 +434,35 @@ additional_ptr(char *name, int namelen, struct domain
(*retcount)++;
+
+out:
+ return (offset);
+
+}
+
+/*
+ * ADDITIONAL_OPT - tag on an additional EDNS0 (OPT) record to packet
+ */
+
+int
+additional_opt(struct question *question, char *reply, int replylen, int offset)
+{
+ struct dns_optrr *answer;
+
+ if ((offset + sizeof(struct dns_optrr)) > replylen) {
+ goto out;
+ }
+
+ answer = (struct dns_optrr *)&reply[offset];
+
+ memset(answer->name, 0, sizeof(answer->name));
+ answer->type = htons(DNS_TYPE_OPT);
+ answer->class = htons(question->edns0len);
+ answer->ttl = htonl(0);
+
+ answer->rdlen = htons(0);
+
+ offset += sizeof(struct dns_optrr);
out:
return (offset);
blob - 8a892009c0d5f8c6df71e5b298b975297e67e397
blob + f0e0ec662eca35446354dc35f161fab11a716d89
--- dns.h
+++ dns.h
@@ -71,13 +71,13 @@ struct dns_rr {
*/
struct dns_optrr {
- char name[0]; /* always 0 */
+ char name[1]; /* 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 */
-};
+ char rdata[0]; /* attribute, value pairs */
+}__attribute__((packed));
/* RFC 1035 - page 28 */
struct dns_question_hdr {
blob - ff055b13e8d93979b4fa2142dc317d3af654be2a
blob + eef77a715198e46ddca387fdd99bc16e9f5d24b6
--- main.c
+++ main.c
@@ -166,7 +166,7 @@ static struct tcps {
} *tn1, *tnp, *tntmp;
-static const char rcsid[] = "$Id: main.c,v 1.91 2014/05/10 07:15:50 pjp Exp $";
+static const char rcsid[] = "$Id: main.c,v 1.92 2014/05/10 15:11:21 pjp Exp $";
/*
* MAIN - set up arguments, set up database, set up sockets, call mainloop
@@ -344,8 +344,17 @@ main(int argc, char *argv[])
}
(void)mkdir(MYDB_PATH, 0700);
+ snprintf(mydatabase, sizeof(mydatabase), "%s/%ld",
+ MYDB_PATH, (long)getpid());
- if ((ret = dbenv->open(dbenv, MYDB_PATH, DB_CREATE | \
+ if (mkdir(mydatabase, 0750) < 0) {
+ if (errno != EEXIST) {
+ dolog(LOG_ERR, "mkdir: %s\n", strerror(errno));
+ exit(1);
+ }
+ }
+
+ if ((ret = dbenv->open(dbenv, mydatabase, DB_CREATE | \
DB_INIT_LOCK | DB_INIT_MPOOL | DB_SYSTEM_MEM, \
S_IRUSR | S_IWUSR)) != 0) {
dolog(LOG_INFO, "dbenv->open failed: %s\n", db_strerror(ret));
@@ -364,10 +373,15 @@ main(int argc, char *argv[])
* make a temporary database...
*/
- snprintf(mydatabase, sizeof(mydatabase), "%s/wdns.%ld",
+
+ snprintf(mydatabase, sizeof(mydatabase), "%s/%ld/wdns.db",
MYDB_PATH, (long)getpid());
+
+ (void)unlink(mydatabase);
+
database = mydatabase;
+
fd = open(database, O_WRONLY | O_CREAT, 0600);
if (fd < 0) {
dolog(LOG_INFO, "open: %s\n", strerror(errno));
@@ -1067,7 +1081,7 @@ main(int argc, char *argv[])
*/
struct question *
-build_question(char *buf, int len, int additional)
+build_question(char *buf, int len, int additional)
{
u_int i;
u_int namelen = 0;
@@ -1220,15 +1234,15 @@ build_question(char *buf, int len, int additional)
if (additional != 1)
break;
- i += (2 * sizeof(u_int16_t)) + 2;
+ i += (2 * sizeof(u_int16_t)) + 1;
/* check that the minimum optrr fits */
- if (i + 10 > len)
+ /* 10 */
+ if (i + sizeof(struct dns_optrr) > len)
break;
-
opt = (struct dns_optrr *)&buf[i];
- if (*opt->name != 0)
+ if (opt->name[0] != 0)
break;
if (ntohs(opt->type) != DNS_TYPE_OPT)
blob - 8d33325ecd798bcf3286be913c74046fedf80aa3
blob + fe74f33d8c70a986e3380ce431d6b3f17b8e8b56
--- reply.c
+++ reply.c
@@ -54,6 +54,7 @@ extern int additional_a(char *, int, struct domain *,
extern int additional_aaaa(char *, int, struct domain *, char *, int, int, int *);
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 int additional_opt(struct question *, char *, int, int);
extern struct question * build_fake_question(char *, int, u_int16_t);
extern int free_question(struct question *);
@@ -87,7 +88,7 @@ struct collects {
extern int debug, verbose;
-static const char rcsid[] = "$Id: reply.c,v 1.55 2014/05/01 15:26:24 pjp Exp $";
+static const char rcsid[] = "$Id: reply.c,v 1.56 2014/05/10 15:11:21 pjp Exp $";
/*
* REPLY_A() - replies a DNS question (*q) on socket (so)
@@ -130,6 +131,9 @@ reply_a(struct sreply *sreply, DB *db)
if (istcp) {
replysize = 65535;
}
+
+ if (q->edns0len > 512)
+ replysize = q->edns0len;
odh = (struct dns_header *)&reply[0];
@@ -217,6 +221,12 @@ reply_a(struct sreply *sreply, DB *db)
odh->answer = htons(a_count);
}
+ if (q->edns0len) {
+ /* tag on edns0 opt record */
+ odh->additional = htons(1);
+ outlen = additional_opt(q, reply, replysize, outlen);
+ }
+
out:
if (sreply->sr != NULL) {
reply_raw2(so, reply, outlen, sreply->sr);
@@ -294,6 +304,9 @@ reply_aaaa(struct sreply *sreply, DB *db)
if (istcp) {
replysize = 65535;
}
+
+ if (q->edns0len > 512)
+ replysize = q->edns0len;
odh = (struct dns_header *)&reply[0];
@@ -360,6 +373,12 @@ reply_aaaa(struct sreply *sreply, DB *db)
answer = (struct answer *)&reply[outlen];
} while (aaaa_count < RECORD_COUNT && --sd->aaaa_count);
+ if (q->edns0len) {
+ /* tag on edns0 opt record */
+ odh->additional = htons(1);
+ outlen = additional_opt(q, reply, replysize, outlen);
+ }
+
out:
if (sreply->sr != NULL) {
reply_raw2(so, reply, outlen, sreply->sr);
@@ -440,6 +459,8 @@ reply_mx(struct sreply *sreply, DB *db)
replysize = 65535;
}
+ if (q->edns0len > 512)
+ replysize = q->edns0len;
odh = (struct dns_header *)&reply[0];
@@ -568,6 +589,15 @@ reply_mx(struct sreply *sreply, DB *db)
free(cn1);
}
+ if (q->edns0len) {
+ /* tag on edns0 opt record */
+ NTOHS(odh->additional);
+ odh->additional++;
+ HTONS(odh->additional);
+
+ outlen = additional_opt(q, reply, replysize, outlen);
+ }
+
out:
if (sreply->sr != NULL) {
reply_raw2(so, reply, outlen, sreply->sr);
@@ -642,6 +672,9 @@ reply_ns(struct sreply *sreply, DB *db)
if (istcp) {
replysize = 65535;
}
+
+ if (q->edns0len > 512)
+ replysize = q->edns0len;
odh = (struct dns_header *)&reply[0];
@@ -802,6 +835,15 @@ reply_ns(struct sreply *sreply, DB *db)
free(cn1);
}
+ if (q->edns0len) {
+ /* tag on edns0 opt record */
+ NTOHS(odh->additional);
+ odh->additional++;
+ HTONS(odh->additional);
+
+ outlen = additional_opt(q, reply, replysize, outlen);
+ }
+
out:
if (sreply->sr != NULL) {
reply_raw2(so, reply, outlen, sreply->sr);
@@ -882,6 +924,9 @@ reply_cname(struct sreply *sreply)
replysize = 65535;
}
+ if (q->edns0len > 512)
+ replysize = q->edns0len;
+
odh = (struct dns_header *)&reply[0];
outlen = sizeof(struct dns_header);
@@ -991,6 +1036,15 @@ reply_cname(struct sreply *sreply)
HTONS(odh->answer);
}
+ if (q->edns0len) {
+ /* tag on edns0 opt record */
+ NTOHS(odh->additional);
+ odh->additional++;
+ HTONS(odh->additional);
+
+ outlen = additional_opt(q, reply, replysize, outlen);
+ }
+
if (sreply->sr != NULL) {
reply_raw2(so, reply, outlen, sreply->sr);
} else {
@@ -1060,6 +1114,9 @@ reply_ptr(struct sreply *sreply)
if (istcp) {
replysize = 65535;
}
+
+ if (q->edns0len > 512)
+ replysize = q->edns0len;
odh = (struct dns_header *)&reply[0];
outlen = sizeof(struct dns_header);
@@ -1130,6 +1187,15 @@ reply_ptr(struct sreply *sreply)
}
answer->rdlength = htons(&reply[outlen] - &answer->rdata);
+
+ if (q->edns0len) {
+ /* tag on edns0 opt record */
+ NTOHS(odh->additional);
+ odh->additional++;
+ HTONS(odh->additional);
+
+ outlen = additional_opt(q, reply, replysize, outlen);
+ }
if (sreply->sr != NULL) {
reply_raw2(so, reply, outlen, sreply->sr);
@@ -1214,6 +1280,9 @@ reply_soa(struct sreply *sreply)
if (istcp) {
replysize = 65535;
}
+
+ if (q->edns0len > 512)
+ replysize = q->edns0len;
/* st */
@@ -1348,6 +1417,15 @@ reply_soa(struct sreply *sreply)
outlen += sizeof(sd->soa.minttl);
answer->rdlength = htons(&reply[outlen] - &answer->rdata);
+
+ if (q->edns0len) {
+ /* tag on edns0 opt record */
+ NTOHS(odh->additional);
+ odh->additional++;
+ HTONS(odh->additional);
+
+ outlen = additional_opt(q, reply, replysize, outlen);
+ }
if (sreply->sr != NULL) {
reply_raw2(so, reply, outlen, sreply->sr);
@@ -1418,6 +1496,9 @@ reply_spf(struct sreply *sreply)
replysize = 65535;
}
+ if (q->edns0len > 512)
+ replysize = q->edns0len;
+
/* st */
odh = (struct dns_header *)&reply[0];
@@ -1469,6 +1550,15 @@ reply_spf(struct sreply *sreply)
answer->rdlength = htons(sd->spflen + 1);
+ if (q->edns0len) {
+ /* tag on edns0 opt record */
+ NTOHS(odh->additional);
+ odh->additional++;
+ HTONS(odh->additional);
+
+ outlen = additional_opt(q, reply, replysize, outlen);
+ }
+
if (sreply->sr != NULL) {
reply_raw2(so, reply, outlen, sreply->sr);
} else {
@@ -1537,6 +1627,9 @@ reply_txt(struct sreply *sreply)
if (istcp) {
replysize = 65535;
}
+
+ if (q->edns0len > 512)
+ replysize = q->edns0len;
/* st */
@@ -1589,6 +1682,15 @@ reply_txt(struct sreply *sreply)
answer->rdlength = htons(sd->txtlen + 1);
+ if (q->edns0len) {
+ /* tag on edns0 opt record */
+ NTOHS(odh->additional);
+ odh->additional++;
+ HTONS(odh->additional);
+
+ outlen = additional_opt(q, reply, replysize, outlen);
+ }
+
if (sreply->sr != NULL) {
reply_raw2(so, reply, outlen, sreply->sr);
} else {
@@ -1661,6 +1763,9 @@ reply_sshfp(struct sreply *sreply)
if (istcp) {
replysize = 65535;
}
+
+ if (q->edns0len > 512)
+ replysize = q->edns0len;
odh = (struct dns_header *)&reply[0];
@@ -1736,6 +1841,15 @@ reply_sshfp(struct sreply *sreply)
answer = (struct answer *)&reply[outlen];
} while (++sshfp_count < RECORD_COUNT && --sd->sshfp_count);
+ if (q->edns0len) {
+ /* tag on edns0 opt record */
+ NTOHS(odh->additional);
+ odh->additional++;
+ HTONS(odh->additional);
+
+ outlen = additional_opt(q, reply, replysize, outlen);
+ }
+
out:
if (sreply->sr != NULL) {
reply_raw2(so, reply, outlen, sreply->sr);
@@ -1814,6 +1928,8 @@ reply_srv(struct sreply *sreply, DB *db)
replysize = 65535;
}
+ if (q->edns0len > 512)
+ replysize = q->edns0len;
odh = (struct dns_header *)&reply[0];
@@ -1945,6 +2061,15 @@ reply_srv(struct sreply *sreply, DB *db)
free(cn1);
}
+ if (q->edns0len) {
+ /* tag on edns0 opt record */
+ NTOHS(odh->additional);
+ odh->additional++;
+ HTONS(odh->additional);
+
+ outlen = additional_opt(q, reply, replysize, outlen);
+ }
+
out:
if (sreply->sr != NULL) {
reply_raw2(so, reply, outlen, sreply->sr);
@@ -2511,6 +2636,9 @@ reply_noerror(struct sreply *sreply)
if (istcp) {
replysize = 65535;
}
+
+ if (q->edns0len > 512)
+ replysize = q->edns0len;
odh = (struct dns_header *)&reply[0];
outlen = sizeof(struct dns_header);
@@ -2685,6 +2813,15 @@ reply_noerror(struct sreply *sreply)
outlen += sizeof(sd->soa.minttl);
answer->rdlength = htons(&reply[outlen] - &answer->rdata);
+
+ if (q->edns0len) {
+ /* tag on edns0 opt record */
+ NTOHS(odh->additional);
+ odh->additional++;
+ HTONS(odh->additional);
+
+ outlen = additional_opt(q, reply, replysize, outlen);
+ }
if (sreply->sr != NULL) {
reply_raw2(so, reply, outlen, sreply->sr);
@@ -3086,6 +3223,9 @@ reply_any(struct sreply *sreply)
if (istcp) {
replysize = 65535;
}
+
+ if (q->edns0len > 512)
+ replysize = q->edns0len;
/* st */
@@ -3119,6 +3259,15 @@ reply_any(struct sreply *sreply)
outlen = create_anyreply(sreply, (char *)reply, replysize, outlen, 1);
if (outlen == 0) {
return;
+ }
+
+ if (q->edns0len) {
+ /* tag on edns0 opt record */
+ NTOHS(odh->additional);
+ odh->additional++;
+ HTONS(odh->additional);
+
+ outlen = additional_opt(q, reply, replysize, outlen);
}
if (sreply->sr != NULL) {
repomaster@centroid.eu