Commit Diff
Diff:
210f221839134802a53621a679e8170ae66a1486
1f1faf13451d59d120d291d58ddc7d20ba493ca8
Commit:
1f1faf13451d59d120d291d58ddc7d20ba493ca8
Tree:
0624bd88b3ffa34c1b5b3c98e46dcedfb9664f89
Author:
pjp <pjp@delphinusdns.org>
Committer:
pjp <pjp@delphinusdns.org>
Date:
Sun May 11 15:39:50 2014 UTC
Message:
* NAPTR (RFC 2915) support * while there I did some checking against replysize for large packets in reply_* instead of UDP_MAXSIZE * the NAPTR pointers take up 20KB more per record, so if you got 200 records your database will grow by roughly 4 MB
blob - 8247dcbe3990f9c0636688477518ee4406054b43
blob + da3f0499f4ada9864c5345a2b987cc416e510163
--- db.h
+++ db.h
@@ -78,6 +78,19 @@ struct sshfp {
int fplen; /* fingerprint length */
} __attribute__((packed));
+struct naptr {
+ u_int16_t order; /* NAPTR 16 bit order */
+ u_int16_t preference; /* 16 bit preference */
+ char flags[DNS_MAXNAME]; /* flags 255 bytes */
+ int flagslen; /* flags length */
+ char services[DNS_MAXNAME]; /* services */
+ int serviceslen; /* services length */
+ char regexp[DNS_MAXNAME]; /* regexp */
+ int regexplen; /* regexp len */
+ char replacement[DNS_MAXNAME]; /* replacement this is a domain */
+ int replacementlen;
+} __attribute__((packed));
+
struct domain {
char zone[DNS_MAXNAME]; /* name of zone in dns name format */
int zonelen; /* length of zone, above */
@@ -96,6 +109,7 @@ struct domain {
#define DOMAIN_HAVE_SRV 0x400
#define DOMAIN_HAVE_SPF 0x800
#define DOMAIN_HAVE_SSHFP 0x1000
+#define DOMAIN_HAVE_NAPTR 0x2000
struct soa soa; /* start of authority */
u_int32_t ttl; /* time to live */
time_t created; /* time created, for dynamic zones */
@@ -127,6 +141,8 @@ struct domain {
int srv_count; /* count of SRV RR */
struct sshfp sshfp[RECORD_COUNT]; /* SSHFP resource record */
int sshfp_count; /* SSHFP RR count */
+ struct naptr naptr[RECORD_COUNT]; /* NAPTR RR, eek 20K! */
+ int naptr_count;
} __attribute__((packed));
struct sreply {
blob - f0e0ec662eca35446354dc35f161fab11a716d89
blob + e1a97f24aa458900ff4a618bc07e7178b9ef387e
--- dns.h
+++ dns.h
@@ -157,6 +157,7 @@ struct dns_question_hdr {
#define DNS_TYPE_TXT 16
#define DNS_TYPE_SRV 33 /* RFC 2782, page 8 */
+#define DNS_TYPE_NAPTR 35 /* RFC 2915, page 3 */
#define DNS_TYPE_OPT 41 /* RFC 6891, page 7 */
#define DNS_TYPE_SSHFP 44 /* RFC 4255 */
blob - 6a2b46bcc7a54abbd343fc29c3d3e283decac966
blob + bdbb62d7255f08daf6992905e639a4325e7517b6
--- example8.conf
+++ example8.conf
@@ -50,6 +50,12 @@ zone "centroid.eu" {
;
centroid.eu,spf,3600,"v=spf1 ip4:200.46.208.61 ~all"
;
+ ;
+ ; NAPTR trial
+ centroid.eu,naptr,3600,10,10,"u","E2U+sip","!^.*$!sip:1234@sip.example.com!",centroid.eu
+ centroid.eu,naptr,3600,10,20,"u","E2U+sip","!^.*$!sip:1234@sip.example.com!",.
+
+ ;
www.centroid.eu,a,3600,62.75.160.180
www.centroid.eu,a,3600,200.46.208.61
;
blob - eef77a715198e46ddca387fdd99bc16e9f5d24b6
blob + 71f25c30eb641ff89d69fca0f81fa24951a80a16
--- main.c
+++ main.c
@@ -55,6 +55,7 @@ extern void reply_txt(struct sreply *);
extern void reply_spf(struct sreply *);
extern void reply_any(struct sreply *);
extern void reply_srv(struct sreply *, DB *);
+extern void reply_naptr(struct sreply *, DB *);
extern void reply_sshfp(struct sreply *);
extern u_int8_t find_region(struct sockaddr_storage *sst, int family);
extern int find_wildcard(struct sockaddr_storage *sst, int family);
@@ -112,6 +113,7 @@ struct typetable {
{ "SRV", DNS_TYPE_SRV },
{ "SPF", DNS_TYPE_SPF },
{ "SSHFP", DNS_TYPE_SSHFP },
+ { "NAPTR", DNS_TYPE_NAPTR },
{ NULL, 0}
};
@@ -166,7 +168,7 @@ static struct tcps {
} *tn1, *tnp, *tntmp;
-static const char rcsid[] = "$Id: main.c,v 1.92 2014/05/10 15:11:21 pjp Exp $";
+static const char rcsid[] = "$Id: main.c,v 1.93 2014/05/11 15:39:50 pjp Exp $";
/*
* MAIN - set up arguments, set up database, set up sockets, call mainloop
@@ -1560,6 +1562,31 @@ compress_label(u_char *buf, u_int16_t offset, int labe
p += sizeof(struct soa); /* advance struct soa */
break;
+ case DNS_TYPE_NAPTR:
+ p += (2 * sizeof(u_int16_t)); /* order and preference */
+ p += *p; /* flags */
+ p++;
+ p += *p; /* services */
+ p++;
+ p += *p; /* regexp */
+ p++;
+
+ label[++i] = p;
+ while (p <= end && *p) {
+ if ((*p & 0xc0) == 0xc0) {
+ p++;
+ break;
+ }
+ p += *p;
+ p++;
+
+ if (p >= end)
+ goto end;
+ }
+
+ p++; /* one more */
+ break;
+
default:
break;
/* XXX */
@@ -1832,6 +1859,15 @@ lookup_zone(DB *db, struct question *question, struct
}
returnval = DNS_TYPE_SRV;
break;
+
+ case DNS_TYPE_NAPTR:
+ if ((sd->flags & DOMAIN_HAVE_NAPTR) != DOMAIN_HAVE_NAPTR) {
+
+ *lzerrno = ERR_NOERROR;
+ return -1;
+ }
+ returnval = DNS_TYPE_NAPTR;
+ break;
case DNS_TYPE_CNAME:
if ((sd->flags & DOMAIN_HAVE_CNAME) != DOMAIN_HAVE_CNAME) {
@@ -1918,7 +1954,7 @@ lookup_zone(DB *db, struct question *question, struct
}
switch (ntohs(question->hdr->qtype)) {
- case DNS_TYPE_ANY:
+ case DNS_TYPE_ANY:
returnval = DNS_TYPE_ANY;
break;
case DNS_TYPE_A:
@@ -2020,6 +2056,14 @@ lookup_zone(DB *db, struct question *question, struct
}
*lzerrno = ERR_NOERROR;
return -1;
+ case DNS_TYPE_NAPTR:
+ if ((sd->flags & DOMAIN_HAVE_NAPTR) ==
+ DOMAIN_HAVE_NAPTR) {
+ returnval = DNS_TYPE_NAPTR;
+ break;
+ }
+ *lzerrno = ERR_NOERROR;
+ return -1;
case DNS_TYPE_SPF:
if ((sd->flags & DOMAIN_HAVE_SPF) ==
DOMAIN_HAVE_SPF) {
@@ -2762,7 +2806,15 @@ tcpnxdomain:
}
break;
+ case DNS_TYPE_NAPTR:
+ if (type0 == DNS_TYPE_NAPTR) {
+ build_reply(&sreply, tnp->so, pbuf, len, question, from, \
+ fromlen, &sd0, NULL, tnp->region, istcp,
+ tnp->wildcard, NULL, replybuf);
+ reply_naptr(&sreply, cfg->db);
+ }
+ break;
case DNS_TYPE_CNAME:
if (type0 == DNS_TYPE_CNAME) {
@@ -3311,6 +3363,17 @@ udpnxdomain:
NULL, replybuf);
reply_srv(&sreply, cfg->db);
+ }
+ break;
+
+ case DNS_TYPE_NAPTR:
+ if (type0 == DNS_TYPE_NAPTR) {
+
+ build_reply(&sreply, so, buf, len, question, from, \
+ fromlen, &sd0, NULL, aregion, istcp, wildcard, \
+ NULL, replybuf);
+
+ reply_naptr(&sreply, cfg->db);
}
break;
blob - 7a6ee8fdcc60bafc8e470732306ac3550300fb19
blob + 7b5ae94b915c0eb8cea96630797e4868bb3632ca
--- parse.y
+++ parse.y
@@ -58,7 +58,7 @@ typedef struct {
int lineno;
} YYSTYPE;
-static const char rcsid[] = "$Id: parse.y,v 1.17 2014/05/05 08:46:17 pjp Exp $";
+static const char rcsid[] = "$Id: parse.y,v 1.18 2014/05/11 15:39:50 pjp Exp $";
static int version = 0;
static int state = 0;
static uint8_t region = 0;
@@ -117,6 +117,7 @@ int fill_mx(char *name, char *type, int myttl, int pri
int fill_sshfp(char *name, char *type, int myttl, int alg, int fptype, char *fingerprint);
int fill_srv(char *, char *, int, int, int, int, char *);
int fill_txt(char *name, char *type, int myttl, char *msg);
+int fill_naptr(char *, char *, int, int, int, char *, char *, char *, char *);
int fill_spf(char *name, char *type, int myttl, char *msg);
int get_record(struct domain *sdomain, char *converted_name, int converted_namelen);
void set_record(struct domain *sdomain, char *converted_name, int converted_namelen);
@@ -514,6 +515,29 @@ zonestatement:
free ($3);
free ($7);
}
+ |
+ STRING COMMA STRING COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA QUOTEDSTRING COMMA QUOTEDSTRING COMMA QUOTEDSTRING COMMA STRING CRLF
+ {
+ if (strcasecmp($3, "naptr") == 0) {
+ if (fill_naptr($1, $3, $5, $7, $9, $11, $13, $15, $17) < 0) {
+ return -1;
+ }
+
+ if (debug)
+ printf(" %s NAPTR\n", $1);
+ } else {
+ if (debug)
+ printf("another naptr like record I don't know?\n");
+ return (-1);
+ }
+
+ free ($1);
+ free ($3);
+ free ($11);
+ free ($13);
+ free ($15);
+ free ($17);
+ }
| comment CRLF
;
@@ -1041,6 +1065,7 @@ struct rrtab {
{ "srv", DNS_TYPE_SRV },
{ "spf", DNS_TYPE_SPF },
{ "sshfp", DNS_TYPE_SSHFP },
+ { "naptr", DNS_TYPE_NAPTR },
{ NULL, 0 },
};
@@ -1644,6 +1669,83 @@ fill_spf(char *name, char *type, int myttl, char *msg)
sdomain.spflen = len;
sdomain.flags |= DOMAIN_HAVE_SPF;
+
+ set_record(&sdomain, converted_name, converted_namelen);
+
+ if (converted_name)
+ free (converted_name);
+
+ return (0);
+
+}
+
+
+int
+fill_naptr(char *name, char *type, int myttl, int order, int preference, char *flags, char *services, char *regexp, char *replacement)
+{
+ struct domain sdomain;
+ int converted_namelen;
+ char *converted_name, *naptrname;
+ int flagslen, serviceslen, regexplen, replacementlen;
+ int i, naptr_namelen;
+
+ for (i = 0; i < strlen(name); i++) {
+ name[i] = tolower(name[i]);
+ }
+
+ if ((flagslen = strlen(flags)) > 255 ||
+ (serviceslen = strlen(services)) > 255 ||
+ (regexplen = strlen(regexp)) > 255 ||
+ (replacementlen = strlen(replacement)) > 255) {
+
+ dolog(LOG_ERR, "NAPTR record too long line %d\n", file->lineno);
+ return (-1);
+ }
+
+ converted_name = check_rr(name, type, DNS_TYPE_NAPTR, &converted_namelen);
+ if (converted_name == NULL) {
+ return -1;
+ }
+
+ memset(&sdomain, 0, sizeof(sdomain));
+ if (get_record(&sdomain, converted_name, converted_namelen) < 0) {
+ return (-1);
+ }
+
+#ifdef __linux__
+ strncpy((char *)sdomain.zonename, (char *)name, DNS_MAXNAME + 1);
+ sdomain.zonename[DNS_MAXNAME] = '\0';
+#else
+ strlcpy((char *)sdomain.zonename, (char *)name, DNS_MAXNAME + 1);
+#endif
+ memcpy(sdomain.zone, converted_name, converted_namelen);
+ sdomain.zonelen = converted_namelen;
+
+ sdomain.ttl = myttl;
+
+ sdomain.naptr[sdomain.naptr_count].order = order;
+ sdomain.naptr[sdomain.naptr_count].preference = preference;
+
+ memcpy(&sdomain.naptr[sdomain.naptr_count].flags, flags, flagslen);
+ sdomain.naptr[sdomain.naptr_count].flagslen = flagslen;
+
+ memcpy(&sdomain.naptr[sdomain.naptr_count].services, services, serviceslen);
+ sdomain.naptr[sdomain.naptr_count].serviceslen = serviceslen;
+
+ memcpy(&sdomain.naptr[sdomain.naptr_count].regexp, regexp, regexplen);
+ sdomain.naptr[sdomain.naptr_count].regexplen = regexplen;
+
+ naptrname = check_rr(replacement, type, DNS_TYPE_NAPTR, &naptr_namelen);
+ if (converted_name == NULL) {
+ return -1;
+ }
+
+ memcpy(&sdomain.naptr[sdomain.naptr_count].replacement, naptrname, naptr_namelen);
+ sdomain.naptr[sdomain.naptr_count].replacementlen = naptr_namelen;
+
+ sdomain.naptr_count++;
+
+ sdomain.flags |= DOMAIN_HAVE_NAPTR;
set_record(&sdomain, converted_name, converted_namelen);
blob - fe74f33d8c70a986e3380ce431d6b3f17b8e8b56
blob + b7eaec65e7405c5ae56df6fc3cae3522e65c755e
--- reply.c
+++ reply.c
@@ -41,6 +41,7 @@ void reply_ptr(struct sreply *);
void reply_txt(struct sreply *sreply);
void reply_spf(struct sreply *sreply);
void reply_srv(struct sreply *sreply, DB *db);
+void reply_naptr(struct sreply *sreply, DB *db);
void reply_sshfp(struct sreply *);
void reply_cname(struct sreply *);
void reply_any(struct sreply *);
@@ -88,7 +89,7 @@ struct collects {
extern int debug, verbose;
-static const char rcsid[] = "$Id: reply.c,v 1.56 2014/05/10 15:11:21 pjp Exp $";
+static const char rcsid[] = "$Id: reply.c,v 1.57 2014/05/11 15:39:50 pjp Exp $";
/*
* REPLY_A() - replies a DNS question (*q) on socket (so)
@@ -205,7 +206,7 @@ reply_a(struct sreply *sreply, DB *db)
outlen += 16;
/* can we afford to write another header? if no truncate */
- if (sd->a_count > 1 && outlen + 16 > DNS_MAXUDP) {
+ if (sd->a_count > 1 && outlen + 16 > replysize) {
NTOHS(odh->query);
SET_DNS_TRUNCATION(odh);
HTONS(odh->query);
@@ -360,7 +361,7 @@ reply_aaaa(struct sreply *sreply, DB *db)
outlen += 28;
/* can we afford to write another header? if no truncate */
- if (sd->aaaa_count > 1 && outlen + 28 > DNS_MAXUDP) {
+ if (sd->aaaa_count > 1 && outlen + 28 > replysize) {
NTOHS(odh->query);
SET_DNS_TRUNCATION(odh);
HTONS(odh->query);
@@ -546,7 +547,7 @@ reply_mx(struct sreply *sreply, DB *db)
outlen += (12 + 2 + sd->mx[mx_count].exchangelen);
/* can we afford to write another header? if no truncate */
- if (sd->mx_count > 1 && (outlen + 12 + 2 + sd->mx[mx_count].exchangelen) > DNS_MAXUDP) {
+ if (sd->mx_count > 1 && (outlen + 12 + 2 + sd->mx[mx_count].exchangelen) > replysize) {
NTOHS(odh->query);
SET_DNS_TRUNCATION(odh);
HTONS(odh->query);
@@ -791,7 +792,7 @@ reply_ns(struct sreply *sreply, DB *db)
/* can we afford to write another header? if no truncate */
- if (sd->ns_count > 1 && (outlen + 12 + sd->ns[pos % mod].nslen) > DNS_MAXUDP) {
+ if (sd->ns_count > 1 && (outlen + 12 + sd->ns[pos % mod].nslen) > replysize) {
NTOHS(odh->query);
SET_DNS_TRUNCATION(odh);
HTONS(odh->query);
@@ -1829,7 +1830,7 @@ reply_sshfp(struct sreply *sreply)
memcpy((char *)&answer->target, (char *)sd->sshfp[sshfp_count].fingerprint, sd->sshfp[sshfp_count].fplen);
/* can we afford to write another header? if no truncate */
- if (sd->sshfp_count > 1 && (outlen + 12 + 2 + sd->sshfp[sshfp_count].fplen) > DNS_MAXUDP) {
+ if (sd->sshfp_count > 1 && (outlen + 12 + 2 + sd->sshfp[sshfp_count].fplen) > replysize) {
NTOHS(odh->query);
SET_DNS_TRUNCATION(odh);
HTONS(odh->query);
@@ -1881,6 +1882,255 @@ out:
/*
+ * REPLY_NAPTR() - replies a DNS question (*q) on socket (so)
+ * (based on reply_srv)
+ */
+
+
+void
+reply_naptr(struct sreply *sreply, DB *db)
+{
+ char *reply = sreply->replybuf;
+ struct dns_header *odh;
+ struct domain *sd0;
+ int naptr_count;
+ u_int16_t *plen;
+ char *name;
+ u_int16_t outlen;
+ u_int16_t namelen;
+ int additional = 0;
+
+ struct answer {
+ char name[2];
+ u_int16_t type;
+ u_int16_t class;
+ u_int32_t ttl;
+ u_int16_t rdlength; /* 12 */
+ u_int16_t naptr_order;
+ u_int16_t naptr_preference;
+ char rest;
+ } __attribute__((packed));
+
+ struct answer *answer;
+
+ 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;
+ int wildcard = sreply->wildcard;
+ int replysize = 512;
+ int tmplen, savelen;
+ char *p;
+
+ if (istcp) {
+ replysize = 65535;
+ }
+
+ if (q->edns0len > 512)
+ replysize = q->edns0len;
+
+ odh = (struct dns_header *)&reply[0];
+
+ outlen = sizeof(struct dns_header);
+
+ if (len > replysize) {
+ return;
+ }
+
+ 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);
+
+ if (sreply->sr == NULL) {
+ SET_DNS_AUTHORITATIVE(odh);
+ } else
+ SET_DNS_RECURSION_AVAIL(odh);
+
+ HTONS(odh->query);
+
+ odh->question = htons(1);
+ odh->answer = htons(sd->naptr_count);
+ odh->nsrr = 0;
+ odh->additional = 0;
+
+ /* skip dns header, question name, qtype and qclass */
+ answer = (struct answer *)(&reply[0] + sizeof(struct dns_header) +
+ q->hdr->namelen + 4);
+
+ naptr_count = 0;
+ do {
+ savelen = outlen;
+ answer->name[0] = 0xc0;
+ answer->name[1] = 0x0c;
+ answer->type = q->hdr->qtype;
+ answer->class = q->hdr->qclass;
+ if (sreply->sr != NULL)
+ answer->ttl = htonl(sd->ttl - (time(NULL) - sd->created));
+ else
+ answer->ttl = htonl(sd->ttl);
+
+ answer->naptr_order = htons(sd->naptr[naptr_count].order);
+ answer->naptr_preference = htons(sd->naptr[naptr_count].preference);
+
+ p = (char *)&answer->rest;
+
+ *p = sd->naptr[naptr_count].flagslen;
+ memcpy((p + 1), sd->naptr[naptr_count].flags, sd->naptr[naptr_count].flagslen);
+ p += (sd->naptr[naptr_count].flagslen + 1);
+ outlen += (1 + sd->naptr[naptr_count].flagslen);
+
+ /* services */
+ *p = sd->naptr[naptr_count].serviceslen;
+ memcpy((p + 1), sd->naptr[naptr_count].services, sd->naptr[naptr_count].serviceslen);
+ p += (sd->naptr[naptr_count].serviceslen + 1);
+ outlen += (1 + sd->naptr[naptr_count].serviceslen);
+
+ /* regexp */
+ *p = sd->naptr[naptr_count].regexplen;
+ memcpy((p + 1), sd->naptr[naptr_count].regexp, sd->naptr[naptr_count].regexplen);
+ p += (sd->naptr[naptr_count].regexplen + 1);
+ outlen += (1 + sd->naptr[naptr_count].regexplen);
+
+ /* replacement */
+
+ memcpy((char *)p, (char *)sd->naptr[naptr_count].replacement, sd->naptr[naptr_count].replacementlen);
+
+ name = sd->naptr[naptr_count].replacement;
+ namelen = sd->naptr[naptr_count].replacementlen;
+
+ outlen += (12 + 4 + sd->naptr[naptr_count].replacementlen);
+
+ /* compress the label if possible */
+ if ((tmplen = compress_label((u_char*)reply, outlen, namelen)) > 0) {
+ outlen = tmplen;
+ }
+
+ answer->rdlength = htons(outlen - (savelen + 12));
+
+
+ sd0 = Lookup_zone(db, name, namelen, htons(DNS_TYPE_A), wildcard);
+ 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, collect_entry);
+ }
+ }
+ }
+ sd0 = Lookup_zone(db, name, namelen, htons(DNS_TYPE_AAAA), wildcard);
+ 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, collect_entry);
+ }
+ }
+ }
+
+
+ /* can we afford to write another header? if no truncate */
+ if (sd->naptr_count > naptr_count && (outlen + 12 + 4 + sd->naptr[naptr_count + 1].replacementlen + sd->naptr[naptr_count + 1].flagslen + 1 + sd->naptr[naptr_count + 1].serviceslen + 1 + sd->naptr[naptr_count + 1].regexplen + 1) > replysize) {
+ NTOHS(odh->query);
+ SET_DNS_TRUNCATION(odh);
+ HTONS(odh->query);
+ goto out;
+ }
+
+ /* set new offset for answer */
+ answer = (struct answer *)&reply[outlen];
+ } while (++naptr_count < RECORD_COUNT && --sd->naptr_count);
+
+ /* write additional */
+
+ SLIST_FOREACH(cnp, &collectshead, collect_entry) {
+ int addcount;
+ int tmplen;
+
+ switch (cnp->type) {
+ case DNS_TYPE_A:
+ tmplen = additional_a(cnp->name, cnp->namelen, cnp->sd, reply, replysize, outlen, &addcount);
+ additional += addcount;
+ break;
+ case DNS_TYPE_AAAA:
+ tmplen = additional_aaaa(cnp->name, cnp->namelen, cnp->sd, reply, replysize, 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, collect_entry);
+ free(cn1->name);
+ free(cn1->sd);
+ 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);
+ } else {
+ if (istcp) {
+ char *tmpbuf;
+
+ 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 (send(so, tmpbuf, outlen + 2, 0) < 0) {
+ dolog(LOG_INFO, "send: %s\n", strerror(errno));
+ }
+ free(tmpbuf);
+ } else {
+ if (sendto(so, reply, outlen, 0, sa, salen) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
+ }
+ }
+
+ return;
+}
+
+
+/*
* REPLY_SRV() - replies a DNS question (*q) on socket (so)
* (based on reply_mx)
*/
@@ -2018,7 +2268,7 @@ reply_srv(struct sreply *sreply, DB *db)
outlen += (12 + 6 + sd->srv[srv_count].targetlen);
/* can we afford to write another header? if no truncate */
- if (sd->srv_count > 1 && (outlen + 12 + 6 + sd->srv[srv_count].targetlen) > DNS_MAXUDP) {
+ if (sd->srv_count > 1 && (outlen + 12 + 6 + sd->srv[srv_count].targetlen) > replysize) {
NTOHS(odh->query);
SET_DNS_TRUNCATION(odh);
HTONS(odh->query);
@@ -3309,6 +3559,7 @@ u_int16_t
create_anyreply(struct sreply *sreply, char *reply, int rlen, int offset, int soa)
{
int a_count, aaaa_count, ns_count, mx_count, srv_count, sshfp_count;
+ int naptr_count;
int tmplen, pos, mod;
int ttlhack;
struct answer {
@@ -3328,6 +3579,7 @@ create_anyreply(struct sreply *sreply, char *reply, in
u_int32_t *soa_val;
u_int16_t namelen;
u_int16_t *mx_priority, *srv_priority, *srv_port, *srv_weight;
+ u_int16_t *naptr_order, *naptr_preference;
u_int8_t *sshfp_alg, *sshfp_fptype;
char *name, *p;
int i;
@@ -3738,6 +3990,98 @@ create_anyreply(struct sreply *sreply, char *reply, in
NTOHS(odh->answer);
odh->answer += sshfp_count;
+ HTONS(odh->answer);
+
+ }
+ if (sd->flags & DOMAIN_HAVE_NAPTR) {
+ naptr_count = 0;
+ do {
+ if ((offset + q->hdr->namelen) > rlen) {
+ goto truncate;
+ }
+
+ memcpy(&reply[offset], q->hdr->name, q->hdr->namelen);
+ offset += q->hdr->namelen;
+
+ if ((tmplen = compress_label((u_char*)reply, offset, q->hdr->namelen)) > 0) {
+ offset = tmplen;
+ }
+
+
+ if (offset + 12 > rlen)
+ goto truncate;
+
+ answer = (struct answer *)&reply[offset];
+
+ answer->type = htons(DNS_TYPE_NAPTR);
+ answer->class = htons(DNS_CLASS_IN);
+ answer->ttl = htonl(sd->ttl);
+ answer->rdlength = htons((2 * sizeof(u_int16_t)) + sd->naptr[naptr_count].flagslen + 1 + sd->naptr[naptr_count].serviceslen + 1 + sd->naptr[naptr_count].regexplen + 1 + sd->naptr[naptr_count].replacementlen);
+
+ offset += 10; /* up to rdata length */
+
+ naptr_order = (u_int16_t *)&reply[offset];
+ *naptr_order = htons(sd->naptr[naptr_count].order);
+
+ offset += 2;
+
+ naptr_preference = (u_int16_t *)&reply[offset];
+ *naptr_preference = htons(sd->naptr[naptr_count].preference);
+
+ offset += 2;
+
+ /* flags */
+ if (offset + sd->naptr[naptr_count].flagslen + 1> rlen)
+ goto truncate;
+
+ reply[offset] = sd->naptr[naptr_count].flagslen;
+ offset++;
+
+ memcpy((char *)&reply[offset], (char *)sd->naptr[naptr_count].flags, sd->naptr[naptr_count].flagslen);
+
+ offset += sd->naptr[naptr_count].flagslen;
+ /* services */
+ if (offset + sd->naptr[naptr_count].serviceslen + 1> rlen)
+ goto truncate;
+
+ reply[offset] = sd->naptr[naptr_count].serviceslen;
+ offset++;
+
+ memcpy((char *)&reply[offset], (char *)sd->naptr[naptr_count].services, sd->naptr[naptr_count].serviceslen);
+
+ offset += sd->naptr[naptr_count].serviceslen;
+ /* regexp */
+ if (offset + sd->naptr[naptr_count].regexplen + 1> rlen)
+ goto truncate;
+
+ reply[offset] = sd->naptr[naptr_count].regexplen;
+ offset++;
+
+ memcpy((char *)&reply[offset], (char *)sd->naptr[naptr_count].regexp, sd->naptr[naptr_count].regexplen);
+
+ offset += sd->naptr[naptr_count].regexplen;
+ /* replacement */
+ if (offset + sd->naptr[naptr_count].replacementlen > rlen)
+ goto truncate;
+
+ memcpy((char *)&reply[offset], (char *)sd->naptr[naptr_count].replacement, sd->naptr[naptr_count].replacementlen);
+
+ offset += sd->naptr[naptr_count].replacementlen;
+
+ if ((tmplen = compress_label((u_char*)reply, offset, sd->naptr[naptr_count].replacementlen)) > 0) {
+ offset = tmplen;
+ }
+
+ /* can we afford to write another header? if no truncate */
+ if (sd->naptr_count > naptr_count && (offset + 12 + 4 + sd->naptr[naptr_count + 1].flagslen + 1) > rlen) {
+ goto truncate;
+ }
+
+ answer->rdlength = htons(&reply[offset] - answer->rdata);
+ } while (++naptr_count < RECORD_COUNT && --sd->naptr_count);
+
+ NTOHS(odh->answer);
+ odh->answer += naptr_count;
HTONS(odh->answer);
}
repomaster@centroid.eu